feat(canvas): 画布能力 - 完善 LibTV 导入与资源预览

This commit is contained in:
ddCat committed 2026-08-19 07:16:07 +08:00
1 parent 4b9d510129
commit d2a089f1ec
36 files changed
+1722 -68

No files matched your search

+40
View File
@@ -271,6 +271,46 @@ describe("public channel model catalog", () => {
expect(html).toContain("Omni Flash");
});
test("builds the creation catalog only from public backend models and user channels", () => {
const platform = createModelChannel({
id: "public-logical-models",
name: "平台模型",
scope: "system",
apiKey: "system",
models: ["frontend-image"],
modelCosts: [{ model: "frontend-image", capability: "image", billingMode: "fixed_request", unitPriceMicrocredits: 0 }],
});
const custom = createModelChannel({
id: "custom-channel",
name: "我的渠道",
baseUrl: "https://custom.example.com",
apiKey: "synthetic-test-key",
models: ["custom-image-v1"],
});
const normalized = normalizeConfigSnapshot({
config: {
...defaultConfig,
channels: [
platform,
custom,
createModelChannel({ id: "default", name: "默认渠道", apiKey: "", models: ["gpt-image-2"] }),
],
models: ["default::gpt-image-2", "ghost-image"],
imageModels: ["default::gpt-image-2", "ghost-image"],
imageModel: "default::gpt-image-2",
},
}).config;
const staleSnapshot = { ...normalized, models: [...normalized.models, "ghost-image"], imageModels: [...normalized.imageModels, "ghost-image"] };
expect(selectableModelsByCapability(staleSnapshot, "image")).toEqual([
"public-logical-models::frontend-image",
"custom-channel::custom-image-v1",
]);
expect(staleSnapshot.channels.some((channel) => channel.id === "default")).toBe(false);
expect(selectableModelsByCapability(staleSnapshot, "image")).not.toContain("default::gpt-image-2");
expect(selectableModelsByCapability(staleSnapshot, "image")).not.toContain("ghost-image");
});
test("omits resolution_name for Omni and for auto instead of inventing 720p", async () => {
const bodies: Record<string, string>[] = [];
axios.post = (async (_url: string, body: unknown) => {
+26
View File
@@ -0,0 +1,26 @@
import { describe, expect, test } from "bun:test";
import { buildLibTVImagePreviewUrl, formatLibTVBatchTime, parseLibTVProjectUUID } from "../src/lib/canvas/libtv-import";
describe("LibTV canvas import helpers", () => {
test("extracts projectId from LibTV share links", () => {
expect(parseLibTVProjectUUID("https://www.liblib.tv/canvas/share?spaceId=5858202&projectId=dda7684b670b4e57b6027f1334fe6056")).toBe("dda7684b670b4e57b6027f1334fe6056");
});
test("accepts direct UUIDs and rejects unrelated links", () => {
expect(parseLibTVProjectUUID("292A69D540774A9AB9872D8337C9FD0B")).toBe("292a69d540774a9ab9872d8337c9fd0b");
expect(parseLibTVProjectUUID("https://api.liblib.tv/api/canvas/project/detail?uuid=292a69d540774a9ab9872d8337c9fd0b")).toBe("292a69d540774a9ab9872d8337c9fd0b");
expect(parseLibTVProjectUUID("https://example.com/not-a-canvas")).toBe("");
});
test("formats the readable batch label to local yyyyMMddHHmm", () => {
const localTime = new Date(2026, 7, 19, 5, 2);
expect(formatLibTVBatchTime(localTime.toISOString())).toBe("202608190502");
});
test("uses a LibTV CDN thumbnail without changing the original media contract", () => {
const original = "https://libtv-res.liblib.art/path/example.png";
expect(buildLibTVImagePreviewUrl(original)).toBe("https://libtv-res.liblib.art/path/example.png?x-oss-process=image%2Fresize%2Cw_960");
expect(buildLibTVImagePreviewUrl("https://example.com/path/example.png")).toBe("https://example.com/path/example.png");
});
});