feat(images): 期2 图片趴三类 — 模特上身图/平台套图/自由创作 归类+成组+接模特库
后端: - 独立生图三类归类:model+product→model_tryon(模特上身图,引用模特库,不送审) / cover→platform_kit(平台套图) / image→free_create(自由创作);生成演员(model 无 product)仍→person(视频角色,留期3) - 成组:每次提交一个 batch_id 串起整批,落 asset.metadata;另记 mode + model_entity_id(上身图溯源模特库) - generate-image 端点透传 model_entity_id;资产库 _tab_q+summary 加 tryon/kits/creations 三类桶 - 单测 StandaloneCategoryTests 直跑 worker 验四态归类全绿(绕开异步 .delay) 前端: - 资产库 library.tsx 加三类 tab(模特上身图/平台套图/自由创作)+ 计数 + 筛选维度 - ai-tools 模特选择器数据源 person→模特库(listModels 映射,选中传形象图当参考 = 引用模特库),ActorLibrary 同源 - api.ts submitGenerateImage 加 model_entity_id 验收:tsc+build 全绿;无头 0 console error(资产库三类 tab 各归类正确、模特选择器 5 张取自模特库) 基线既有 3 失败(StandaloneImageReferenceTests 异步漂移)零新增 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
44e90233ff
commit
c8f3f91d38
@@ -0,0 +1,52 @@
|
||||
// 期2 图片趴三类走查:资产库三类 tab(归类) + 图片生成页模特选择器接模特库 + 抓 console/pageerror。
|
||||
import { chromium } from "playwright";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const BASE = process.env.BASE || "http://localhost:5188";
|
||||
const OUT = path.resolve("../../../_qa_shots/models-p2");
|
||||
fs.mkdirSync(OUT, { recursive: true });
|
||||
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const r = { consoleErrors: [], library: {}, picker: {} };
|
||||
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 });
|
||||
|
||||
// ── 资产库:三类 tab 存在 + 计数 + 逐 tab 截图 ──
|
||||
await p.goto(BASE + "/library", { waitUntil: "load" });
|
||||
await p.waitForTimeout(2600);
|
||||
for (const key of ["tryon", "kits", "creations"]) {
|
||||
r.library[key + "_tabExists"] = await p.locator(`.tab[data-tab="${key}"]`).count();
|
||||
}
|
||||
async function openTab(key) {
|
||||
await p.locator(`.tab[data-tab="${key}"]`).click();
|
||||
await p.waitForTimeout(2200);
|
||||
const cards = await p.locator(".asset-card, .lib-card, .ph-frame, .a-card").count();
|
||||
await p.screenshot({ path: path.join(OUT, `library-${key}.png`), fullPage: true });
|
||||
return cards;
|
||||
}
|
||||
r.library.tryonCards = await openTab("tryon");
|
||||
r.library.kitsCards = await openTab("kits");
|
||||
r.library.creationsCards = await openTab("creations");
|
||||
|
||||
// ── 图片生成页:模特上身图 → 模特选择器接模特库 ──
|
||||
await p.goto(BASE + "/model-photo", { waitUntil: "load" });
|
||||
await p.waitForTimeout(2600);
|
||||
r.picker.url = p.url();
|
||||
r.picker.modelCards = await p.locator(".model-grid .model-card").count();
|
||||
r.picker.firstModelName = await p.locator(".model-grid .model-card .m-name").first().innerText().catch(() => "");
|
||||
await p.screenshot({ path: path.join(OUT, "model-photo-picker.png"), fullPage: true });
|
||||
|
||||
await browser.close();
|
||||
console.log(JSON.stringify(r, null, 2));
|
||||
fs.writeFileSync(path.join(OUT, "summary.json"), JSON.stringify(r, null, 2));
|
||||
Reference in New Issue
Block a user