feat: complete image console and add verified REST and MCP workflows

This commit is contained in:
2026-11-04 00:41:54 +08:00
parent 3140cd51d2
commit bef8af53ed
48 changed files with 5167 additions and 1176 deletions
+135
View File
@@ -0,0 +1,135 @@
/* ==========================================================================
api.js — 数据访问层(真实 REST)
所有页面只通过 window.API 访问后端。
========================================================================== */
(function () {
async function request(path, options) {
const res = await fetch(path, {
headers: { "Content-Type": "application/json" },
...options,
});
const text = await res.text();
let data = null;
if (text) {
try {
data = JSON.parse(text);
} catch (e) {
data = text;
}
}
if (!res.ok) {
let detail =
data && typeof data === "object"
? data.detail || data.message || JSON.stringify(data)
: String(data || res.statusText);
if (Array.isArray(detail)) {
detail = detail.map((item) => (item.loc || []).slice(1).join(".") + ": " + item.msg).join(";");
}
throw new Error(detail);
}
return data;
}
const get = (path) => request(path, { method: "GET" });
const post = (path, body) =>
request(path, { method: "POST", body: JSON.stringify(body || {}) });
const patch = (path, body) =>
request(path, { method: "PATCH", body: JSON.stringify(body || {}) });
const del = (path) => request(path, { method: "DELETE" });
window.API = {
/* ---------------------------------------------------------- 供应商 */
async listProviders() {
return get("/api/providers");
},
async saveProvider(payload) {
await post("/api/providers", payload);
return get("/api/providers");
},
async deleteProvider(id) {
await del("/api/providers/" + encodeURIComponent(id));
return get("/api/providers");
},
/* ------------------------------------- 上游模型发现(含 image 筛选) */
/* 按供应商 ID 拉取上游模型 */
async discoverProviderModels(providerId) {
return post("/api/providers/" + encodeURIComponent(providerId) + "/discover", {});
},
/* 保存勾选的模型 */
async saveProviderModels(providerId, modelIds, enabled, note) {
await post("/api/providers/" + encodeURIComponent(providerId) + "/models", {
model_ids: modelIds,
enabled: enabled !== false,
note: note || "自动发现",
});
return get("/api/models?provider_id=" + encodeURIComponent(providerId));
},
/* ---------------------------------------------------------- 模型 */
async listModels(providerId) {
const q = providerId ? "?provider_id=" + encodeURIComponent(providerId) : "";
return get("/api/models" + q);
},
async toggleModel(modelId, enabled) {
await patch("/api/models/" + encodeURIComponent(modelId), { enabled: !!enabled });
return get("/api/models");
},
async setModelsEnabled(modelIds, enabled) {
await post("/api/models/bulk", { ids: modelIds, enabled: !!enabled });
return get("/api/models");
},
/* ---------------------------------------------------------- 画廊 */
async listGalleries() {
return get("/api/galleries");
},
async listGallery(profileName) {
if (!profileName) return [];
return get("/api/galleries/" + encodeURIComponent(profileName));
},
async deleteGalleryImage(profileName, filename) {
return del("/api/galleries/" + encodeURIComponent(profileName) + "/" + encodeURIComponent(filename));
},
/* ------------------------------------------------------ 生成记录 */
async listGenerations() {
return get("/api/generations");
},
/* ---------------------------------------------------- 网页端出图 */
/* 网页端固定 profile_name = "user",落到 output/user/(不存在则自动创建) */
async generateImage(payload) {
const body = Object.assign({}, payload);
if (!body.profile_name) body.profile_name = "user";
const res = await post("/api/generate", body);
return {
generation: {
id: res.id,
provider_id: res.provider,
provider_name: res.provider_name,
model: res.model,
profile_name: res.profile_name,
size: res.size,
ratio: res.ratio,
created_at: res.created_at,
},
images: res.images || [],
output_dir: res.output_dir,
};
},
/* ---------------------------------------------------------- SKILL */
async getSkill() {
return get("/api/skills");
},
};
})();