fix(projects+assets): 项目封面引用真实商品图 + 资产库排除软删资产

- 项目卡封面:废弃「项目名关键词→静态 mock 假图」映射(与真实数据脱节,导致全是假面膜图),
  改用后端 cover_preview_url(取商品 cover_asset 主图);无商品图 → 干净占位
- 资产库 queryset/summary/facets 补 is_deleted=False:软删资产不再出现在资产库与 tab 计数
  (此前 is_deleted 字段在资产库未生效,软删无效)
- 单测 AssetSoftDeleteTests:列表 + 计数均排除软删

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-21 19:44:45 +08:00
co-authored by Claude Opus 4.8
parent c6e9c7e77b
commit 9e791a4db9
4 changed files with 56 additions and 21 deletions
+27
View File
@@ -0,0 +1,27 @@
import { chromium } from "playwright";
import fs from "node:fs";
import path from "node:path";
const BASE = process.env.BASE || "http://localhost:5200";
const OUT = path.resolve("../../../_qa_shots/cleanup");
fs.mkdirSync(OUT, { recursive: true });
const browser = await chromium.launch({ headless: true });
const r = { consoleErrors: [] };
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
const p = await ctx.newPage();
p.on("console", (m) => { if (m.type() === "error") r.consoleErrors.push(m.text()); });
p.on("pageerror", (e) => r.consoleErrors.push("PAGEERR:" + e.message));
await p.goto(BASE + "/login", { waitUntil: "load" });
await p.waitForTimeout(400);
await p.fill("#auth-username", "airshelf"); await p.fill("#auth-pwd", "Restraint2026");
await p.click("button.btn-cta");
await p.waitForFunction(() => !location.pathname.startsWith("/login"), { timeout: 12000 });
await p.goto(BASE + "/projects", { waitUntil: "load" }); await p.waitForTimeout(2600);
await p.screenshot({ path: path.join(OUT, "projects.png"), fullPage: true });
await p.goto(BASE + "/library", { waitUntil: "load" }); await p.waitForTimeout(2600);
r.libTabs = (await p.locator(".tab").allInnerTexts().catch(() => [])).join(" | ");
await p.screenshot({ path: path.join(OUT, "library.png"), fullPage: true });
await p.goto(BASE + "/models", { waitUntil: "load" }); await p.waitForTimeout(2600);
r.modelCards = await p.locator(".model-card").count();
await p.screenshot({ path: path.join(OUT, "models.png"), fullPage: true });
await browser.close();
console.log(JSON.stringify(r, null, 2));