chore(收尾): mock 数据同步 B2 引用模型-附件 refType 场景引用/page unusedCount/upload scene 白名单
This commit is contained in:
+9
-1
@@ -58,6 +58,9 @@ export interface MockAttachment {
|
|||||||
id: number;
|
id: number;
|
||||||
siteId: number;
|
siteId: number;
|
||||||
articleId?: number;
|
articleId?: number;
|
||||||
|
/** 场景引用类型(B2):banner/link/site;空=未使用 */
|
||||||
|
refType?: string;
|
||||||
|
refId?: number;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
url: string;
|
url: string;
|
||||||
fileSize: number;
|
fileSize: number;
|
||||||
@@ -324,7 +327,12 @@ export function seedDb(): MockDb {
|
|||||||
at({ fileName: "2026秋季学期校历.pdf", url: "/mock-files/2026校历.pdf", mimeType: "application/pdf", articleId: 1 }),
|
at({ fileName: "2026秋季学期校历.pdf", url: "/mock-files/2026校历.pdf", mimeType: "application/pdf", articleId: 1 }),
|
||||||
at({ fileName: "运动会秩序册.pdf", url: "/mock-files/运动会秩序册.pdf", mimeType: "application/pdf", articleId: 5 }),
|
at({ fileName: "运动会秩序册.pdf", url: "/mock-files/运动会秩序册.pdf", mimeType: "application/pdf", articleId: 5 }),
|
||||||
at({ fileName: "迎新晚会节目单.docx", url: "/mock-files/迎新晚会节目单.docx", articleId: 6 }),
|
at({ fileName: "迎新晚会节目单.docx", url: "/mock-files/迎新晚会节目单.docx", articleId: 6 }),
|
||||||
at({ fileName: "banner-旧图.png", url: "/mock-img/banner-old.svg", mimeType: "image/png" }),
|
// B2 场景引用:轮播图/友链 Logo 附件带 refType/refId(与真实后端形态一致)
|
||||||
|
at({ fileName: "banner-1.png", url: "/mock-img/banner-1.svg", mimeType: "image/png", refType: "banner", refId: 1 }),
|
||||||
|
at({ fileName: "banner-2.png", url: "/mock-img/banner-2.svg", mimeType: "image/png", refType: "banner", refId: 2 }),
|
||||||
|
at({ fileName: "banner-3.png", url: "/mock-img/banner-3.svg", mimeType: "image/png", refType: "banner", refId: 3 }),
|
||||||
|
at({ fileName: "logo-教育部.png", url: "/mock-img/logo-1.svg", mimeType: "image/png", refType: "link", refId: 1 }),
|
||||||
|
at({ fileName: "未使用旧banner.png", url: "/mock-img/banner-old.svg", mimeType: "image/png" }),
|
||||||
at({ fileName: "未使用配图.jpg", url: "/mock-img/orphan.svg", mimeType: "image/jpeg" })
|
at({ fileName: "未使用配图.jpg", url: "/mock-img/orphan.svg", mimeType: "image/jpeg" })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -724,12 +724,12 @@ async function handleApi(req: IncomingMessage, res: ServerResponse, path: string
|
|||||||
const page = num(q(req, "page"), 1)!;
|
const page = num(q(req, "page"), 1)!;
|
||||||
const pageSize = num(q(req, "pageSize"), 10)!;
|
const pageSize = num(q(req, "pageSize"), 10)!;
|
||||||
let rows = db.attachments.filter(t => t.siteId === siteId);
|
let rows = db.attachments.filter(t => t.siteId === siteId);
|
||||||
if (orphanOnly) rows = rows.filter(t => !t.articleId);
|
if (orphanOnly) rows = rows.filter(t => !t.articleId && !t.refType); // B2 未使用语义
|
||||||
const total = rows.length;
|
const total = rows.length;
|
||||||
const list = rows
|
const list = rows
|
||||||
.slice((page - 1) * pageSize, page * pageSize)
|
.slice((page - 1) * pageSize, page * pageSize)
|
||||||
.map((t: MockAttachment) => ({ ...t, orphan: !t.articleId }));
|
.map((t: MockAttachment) => ({ ...t, orphan: !t.articleId }));
|
||||||
sendJson(res, ok({ total, list, orphanCount: db.attachments.filter(t => t.siteId === siteId && !t.articleId).length }));
|
sendJson(res, ok({ total, list, unusedCount: db.attachments.filter(t => t.siteId === siteId && !t.articleId && !t.refType).length })); // B2:orphanCount→unusedCount
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (method === "POST" && path === "/api/attachment/upload") {
|
if (method === "POST" && path === "/api/attachment/upload") {
|
||||||
@@ -744,10 +744,14 @@ async function handleApi(req: IncomingMessage, res: ServerResponse, path: string
|
|||||||
db.files.set(url, { buffer: file.buffer, mime: file.mime, name: safeName });
|
db.files.set(url, { buffer: file.buffer, mime: file.mime, name: safeName });
|
||||||
const siteId = num(q(req, "siteId"), 0) ?? num(body.toString("latin1").match(/name="siteId"\r\n\r\n(\d+)/)?.[1], 0)!;
|
const siteId = num(q(req, "siteId"), 0) ?? num(body.toString("latin1").match(/name="siteId"\r\n\r\n(\d+)/)?.[1], 0)!;
|
||||||
const articleId = num(q(req, "articleId")) ?? num(body.toString("latin1").match(/name="articleId"\r\n\r\n(\d+)/)?.[1], undefined);
|
const articleId = num(q(req, "articleId")) ?? num(body.toString("latin1").match(/name="articleId"\r\n\r\n(\d+)/)?.[1], undefined);
|
||||||
|
// B2:scene 初步标记(banner/link/site 白名单,其余忽略)
|
||||||
|
const sceneRaw = q(req, "scene");
|
||||||
|
const scene = ["banner", "link", "site"].includes(sceneRaw) ? sceneRaw : undefined;
|
||||||
const row: MockAttachment = {
|
const row: MockAttachment = {
|
||||||
id: nextId(db.attachments),
|
id: nextId(db.attachments),
|
||||||
siteId,
|
siteId,
|
||||||
articleId,
|
articleId,
|
||||||
|
refType: scene,
|
||||||
fileName: safeName,
|
fileName: safeName,
|
||||||
url,
|
url,
|
||||||
fileSize: file.buffer.length,
|
fileSize: file.buffer.length,
|
||||||
@@ -755,7 +759,7 @@ async function handleApi(req: IncomingMessage, res: ServerResponse, path: string
|
|||||||
createTime: now(),
|
createTime: now(),
|
||||||
};
|
};
|
||||||
db.attachments.push(row);
|
db.attachments.push(row);
|
||||||
sendJson(res, ok({ ...row, orphan: !row.articleId }));
|
sendJson(res, ok({ ...row, orphan: !row.articleId && !row.refType }));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (method === "POST" && path === "/api/attachment/delete") {
|
if (method === "POST" && path === "/api/attachment/delete") {
|
||||||
|
|||||||
Reference in New Issue
Block a user