add: 添加 SQLite 任务持久化

This commit is contained in:
2026-06-20 11:07:30 +08:00
parent a759b1e835
commit 1b15ef30b3
4 changed files with 856 additions and 4 deletions
+66
View File
@@ -0,0 +1,66 @@
// jobs_api.js — client for the SQLite-backed recurring jobs sidecar.
const params = new URLSearchParams(location.search);
const QUERY_API = params.get("jobsApi");
const DEFAULT_PORT = "5581";
const API_BASE = QUERY_API
? QUERY_API.replace(/\/$/, "")
: `${location.protocol}//${location.hostname || "127.0.0.1"}:${DEFAULT_PORT}`;
export function jobsApiURL() {
return API_BASE;
}
export async function listRecurringJobs() {
const res = await request("/api/jobs");
return (res && res.jobs) || [];
}
export async function createRecurringJob(job) {
const res = await request("/api/jobs", {
method: "POST",
body: job,
});
return res && res.job;
}
export async function runRecurringJobNow(id) {
const res = await request(`/api/jobs/${encodeURIComponent(id)}/run`, {
method: "POST",
});
return res && res.job;
}
export async function stopRecurringJob(id) {
const res = await request(`/api/jobs/${encodeURIComponent(id)}/stop`, {
method: "POST",
});
return res && res.job;
}
export async function deleteRecurringJob(id) {
return request(`/api/jobs/${encodeURIComponent(id)}`, {
method: "DELETE",
});
}
async function request(path, { method = "GET", body } = {}) {
const headers = { "Content-Type": "application/json" };
const res = await fetch(`${API_BASE}${path}`, {
method,
headers,
body: body == null ? undefined : JSON.stringify(body),
});
let data = {};
const ct = res.headers.get("Content-Type") || "";
if (ct.includes("application/json")) {
data = await res.json();
} else {
const text = await res.text();
data = text ? { error: text } : {};
}
if (!res.ok) {
throw new Error(data.error || `HTTP ${res.status}`);
}
return data;
}