chore(core/qa): function-audit toolchain + parity/audit reports + pixel-perfect skill
- qa/function-audit: playwright 行为审计工具(audit.mjs/verify-modals.mjs/pages.json) + 18 页审计产出(*.audit.md/json、summary、运行日志) - qa/visual-parity: 调试/测量辅助脚本(_dbg*.mjs/_measure.mjs/_off.mjs) - core/还原度核对报告.md: 18 页 pixelmatch 核对结果(含 vite 代理陈旧坑记录) - core/还原与接口待办.md: 逐页还原度/真实数据/交互接入待办总表 - .claude/skills/pixel-perfect-react: 像素级还原 React 的 SKILL 文档 - frontend/public/_devlogin.html: 临时本地登录辅助页(可删) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
# Function Audit · 逐页功能审计
|
||||
|
||||
`visual-parity` 比**像素**,这里比**行为**:把每个页面在真实 React 路由里打开,
|
||||
逐个真实点击所有可交互元素,报出「点了没反应」的死交互(假按钮)。
|
||||
|
||||
完整说明见 skill:`.claude/skills/page-function-audit/SKILL.md`。
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
# 0. 先起前后端(见 skill)。后端必须 .venv/bin/python。
|
||||
# 1. 装依赖(复用 visual-parity 的 playwright)
|
||||
cd AirShelf/core/qa/function-audit && npm install
|
||||
# 2. 跑
|
||||
node audit.mjs # 全量(最准,慢)
|
||||
node audit.mjs --only account # 单页(改完复验)
|
||||
node audit.mjs --mode quick # 粗扫(快)
|
||||
# 3. 读报告
|
||||
open output/summary.md # 全页一览,看 dead 列
|
||||
open output/<page>.audit.md # 单页 DEAD 表
|
||||
```
|
||||
|
||||
## 判定口径
|
||||
|
||||
- ✅ works — 点了有反应(URL/浮层/自身状态/网络/DOM 五路任一变)
|
||||
- ❌ **dead** — 点了五路全无反应 → 真缺陷,优先修(多半没接 onClick)
|
||||
- 🛑 error — 点击抛 JS 异常
|
||||
- ◷ noop-active — 点的是已选中 tab/chip,本该无反应,忽略
|
||||
- ⏭ skipped — 破坏性按钮(删除/充值/生成…)不自动点,人工验
|
||||
- 🔍 missing — 设计稿 `/exact` 有、React 没渲染(启发式,人工过)
|
||||
|
||||
## 参数
|
||||
|
||||
| 参数 | 默认 | 说明 |
|
||||
|---|---|---|
|
||||
| `--mode` | `isolated` | `isolated`=逐元素 reload(准);`quick`=不 reload(快) |
|
||||
| `--only` | (全部) | 逗号分隔页名子串,如 `--only account,pipeline` |
|
||||
| `--include-pointer` | off | 额外把 `cursor:pointer` 的 div 当候选 |
|
||||
| `--headed` | off | 看着浏览器跑 |
|
||||
| `--settle` | `700` | 点击后观察窗口 ms |
|
||||
| `--token` / `--email` / `--password` | 演示账号 | 登录态来源 |
|
||||
| `--base` | `http://127.0.0.1:5173` | 前端地址 |
|
||||
@@ -0,0 +1,479 @@
|
||||
// 逐页「功能审计」驱动 —— 区别于 visual-parity(只比像素),这里比「行为」。
|
||||
//
|
||||
// 它把每个页面在真实 React 路由里打开,枚举所有可交互元素(按钮 / 标签 tab /
|
||||
// 切换 toggle / 下拉 chip / 可点卡片 …),逐个真实点击,用 MutationObserver +
|
||||
// URL + 浮层 + 网络请求 + 自身状态(class/aria/checked)五路探针判断「点完到底有没有
|
||||
// 反应」。没反应的 = DEAD(功能没接 / 假按钮)。再拿设计稿 /exact/*.html 的控件清单
|
||||
// 对一遍,报出 React 里「压根没渲染出来」的 MISSING 控件。
|
||||
//
|
||||
// 用法(先起前后端 :5173 / :8010):
|
||||
// cd AirShelf/core/qa/function-audit && npm install
|
||||
// node audit.mjs # 全量,逐元素 reload 隔离(最准)
|
||||
// node audit.mjs --mode quick # 不 reload,快但有级联噪声
|
||||
// node audit.mjs --only pipeline,account # 只跑指定页
|
||||
// node audit.mjs --include-pointer # 额外把 cursor:pointer 的 div 也当候选(查隐藏死交互)
|
||||
// node audit.mjs --headed # 看着浏览器跑
|
||||
//
|
||||
// 产物:output/<page>.audit.json + output/<page>.audit.md + output/summary.md
|
||||
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const here = path.dirname(fileURLToPath(import.meta.url));
|
||||
const repoRoot = path.resolve(here, "../../..");
|
||||
|
||||
function arg(name, fallback = "") {
|
||||
const i = process.argv.indexOf(`--${name}`);
|
||||
return i >= 0 ? process.argv[i + 1] : fallback;
|
||||
}
|
||||
function boolArg(name) {
|
||||
return process.argv.includes(`--${name}`);
|
||||
}
|
||||
|
||||
const BASE = arg("base", "http://127.0.0.1:5173").replace(/\/+$/, "");
|
||||
const EMAIL = arg("email", "e2e-20260529-0806@airshelf.test");
|
||||
const PASSWORD = arg("password", "demo12345");
|
||||
let TOKEN = arg("token", "");
|
||||
const MODE = arg("mode", "isolated"); // isolated | quick
|
||||
const ONLY = arg("only", "").split(",").map((s) => s.trim()).filter(Boolean);
|
||||
const INCLUDE_POINTER = boolArg("include-pointer");
|
||||
const HEADED = boolArg("headed");
|
||||
const SETTLE = Number.parseInt(arg("settle", "700"), 10); // 点击后观察窗口 ms
|
||||
const outDir = path.resolve(here, "output");
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
|
||||
// 只跳「单击即不可逆」的真实付费/真生成/真导出 + 弹窗里的最终确认按钮。
|
||||
// 触发型(删除/移除/下线/充值/退出登录 = 点了只是开二次确认弹窗或跳转)不在此列,照常点验。
|
||||
const DESTRUCTIVE = /(微信支付|支付宝|立即支付|去支付|确认支付|确认充值|立即生成|生成脚本|生成基础资产|生成故事板|生成分镜|提交片段|提交视频|提交生成|提交导出|重新导出|导出\s*MP4|确认删除|确认移除|确认退出|确认下线)/i;
|
||||
|
||||
async function login() {
|
||||
if (TOKEN) return TOKEN;
|
||||
const res = await fetch(`${BASE}/api/auth/login/`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ username: EMAIL, password: PASSWORD })
|
||||
});
|
||||
if (!res.ok) throw new Error(`登录失败 ${res.status}:${await res.text()}\n请确认后端 :8010 在跑、演示账号正确。`);
|
||||
const data = await res.json();
|
||||
return data.token;
|
||||
}
|
||||
|
||||
async function fetchIds() {
|
||||
const headers = { Authorization: `Token ${TOKEN}` };
|
||||
const out = { productId: "", projectId: "" };
|
||||
try {
|
||||
const p = await (await fetch(`${BASE}/api/products/?page_size=1`, { headers })).json();
|
||||
out.productId = (p.results || p)[0]?.id || "";
|
||||
} catch {}
|
||||
try {
|
||||
const j = await (await fetch(`${BASE}/api/projects/?page_size=1`, { headers })).json();
|
||||
out.projectId = (j.results || j)[0]?.id || "";
|
||||
} catch {}
|
||||
return out;
|
||||
}
|
||||
|
||||
// ── 注入页面的工具函数(收集 + 探针),作为字符串在 page.evaluate 里复用 ──
|
||||
const PAGE_HELPERS = `
|
||||
window.__audit = window.__audit || {};
|
||||
// 强候选:语义上就该可交互的元素,无条件纳入
|
||||
window.__audit.SEL_STRONG = [
|
||||
'button','[role=button]','[role=tab]','[role=switch]','[role=menuitem]','[role=option]','[role=checkbox]',
|
||||
'a[href]','input[type=checkbox]','input[type=radio]','select','summary','[onclick]'
|
||||
].join(',');
|
||||
// 弱候选:靠类名猜的,必须 cursor:pointer 才算(滤掉装饰性状态徽章 .pill「通过」等)
|
||||
window.__audit.SEL_WEAK = [
|
||||
'.tab','.pill','.chip','.seg','.stage-pill','.stage-step','.view-tog > *',
|
||||
'.switch','.toggle','.sidebar-toggle','.nav-item','.shortcut','.qa-item','.mi'
|
||||
].join(',');
|
||||
|
||||
window.__audit.isVisible = function(el){
|
||||
const r = el.getBoundingClientRect();
|
||||
if (r.width < 4 || r.height < 4) return false;
|
||||
const s = getComputedStyle(el);
|
||||
if (s.display==='none'||s.visibility==='hidden'||Number(s.opacity)===0) return false;
|
||||
// 移出视口(translateX 隐藏的抽屉/侧拉、关闭的浮层)不算可见 —— 避免点到「隐藏但已渲染」的死控件
|
||||
const vw = window.innerWidth, vh = window.innerHeight;
|
||||
if (r.right <= 0 || r.left >= vw || r.bottom <= 0 || r.top >= vh) return false;
|
||||
return true;
|
||||
};
|
||||
// 容器去重:若元素自身不是强交互元素,但内部已含强交互后代(如 .chip-wrap 里有 .chip 按钮),
|
||||
// 则它是包装容器,不当候选(真控件是里面那个)。
|
||||
window.__audit.isWrapper = function(el){
|
||||
if (el.matches(window.__audit.SEL_STRONG)) return false;
|
||||
return !!el.querySelector(window.__audit.SEL_STRONG);
|
||||
};
|
||||
|
||||
window.__audit.label = function(el){
|
||||
let t = (el.getAttribute('aria-label') || el.title || el.value || el.textContent || '').replace(/\\s+/g,' ').trim();
|
||||
if (!t) t = el.getAttribute('data-key') || el.getAttribute('data-value') || el.getAttribute('data-filter') || '';
|
||||
return t.slice(0,48);
|
||||
};
|
||||
|
||||
// 确定性枚举(文档序),去重,过滤可见;同时给每个打 data-audit-idx 方便点击定位
|
||||
window.__audit.collect = function(includePointer){
|
||||
const strong = Array.from(document.querySelectorAll(window.__audit.SEL_STRONG));
|
||||
// 弱候选:必须 cursor:pointer;且排除纯展示 <span> 徽章(无 role/tabindex/onclick,如状态 pill「reserved」)
|
||||
const weak = Array.from(document.querySelectorAll(window.__audit.SEL_WEAK))
|
||||
.filter(el => getComputedStyle(el).cursor === 'pointer')
|
||||
.filter(el => !(el.tagName === 'SPAN' && !el.getAttribute('role') && !el.hasAttribute('tabindex') && !el.hasAttribute('onclick')));
|
||||
let nodes = strong.concat(weak);
|
||||
if (includePointer){
|
||||
const extra = Array.from(document.querySelectorAll('div,li,span,article,section')).filter(el=>{
|
||||
if (getComputedStyle(el).cursor!=='pointer') return false;
|
||||
return !el.querySelector(window.__audit.SEL_STRONG); // 只取叶子可点
|
||||
});
|
||||
nodes = nodes.concat(extra);
|
||||
}
|
||||
// 文档序排序 + 去重
|
||||
nodes = Array.from(new Set(nodes)).sort((a,b)=>{
|
||||
const p = a.compareDocumentPosition(b);
|
||||
if (p & Node.DOCUMENT_POSITION_FOLLOWING) return -1;
|
||||
if (p & Node.DOCUMENT_POSITION_PRECEDING) return 1;
|
||||
return 0;
|
||||
});
|
||||
const seen = new Set();
|
||||
const ordered = [];
|
||||
for (const el of nodes){
|
||||
if (seen.has(el)) continue;
|
||||
seen.add(el);
|
||||
if (!window.__audit.isVisible(el)) continue;
|
||||
if (window.__audit.isWrapper(el)) continue; // 跳过包装容器(真控件在其内部)
|
||||
ordered.push(el);
|
||||
}
|
||||
return ordered.map((el,i)=>{
|
||||
el.setAttribute('data-audit-idx', String(i));
|
||||
const disabled = el.disabled || el.getAttribute('aria-disabled')==='true' || el.classList.contains('is-disabled') || el.classList.contains('disabled');
|
||||
const active = el.classList.contains('active') || el.classList.contains('is-active') || el.classList.contains('selected')
|
||||
|| el.getAttribute('aria-selected')==='true' || el.getAttribute('aria-checked')==='true' || el.checked===true;
|
||||
return {
|
||||
idx:i,
|
||||
tag: el.tagName.toLowerCase(),
|
||||
role: el.getAttribute('role') || '',
|
||||
cls: (el.className && typeof el.className==='string') ? el.className.split(/\\s+/).slice(0,3).join('.') : '',
|
||||
label: window.__audit.label(el),
|
||||
href: el.getAttribute('href') || '',
|
||||
disabled: !!disabled,
|
||||
active: !!active
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 装探针:记录基线 + 启动 MutationObserver,然后点击目标
|
||||
window.__audit.arm = function(idx){
|
||||
const el = document.querySelector('[data-audit-idx="'+idx+'"]');
|
||||
if (!el) return { ok:false, reason:'not-found' };
|
||||
const overlaySel = '.modal,.drawer,[role=dialog],.toast,.chip-menu,.dropdown,.menu,.popover,[data-open=true]';
|
||||
const visOverlays = ()=> Array.from(document.querySelectorAll(overlaySel)).filter(window.__audit.isVisible).length;
|
||||
window.__audit.base = {
|
||||
url: location.href,
|
||||
overlays: visOverlays,
|
||||
selfSig: el.className+'|'+el.getAttribute('aria-expanded')+'|'+el.getAttribute('aria-selected')+'|'+el.getAttribute('aria-checked')+'|'+(el.checked??''),
|
||||
overlaysN: visOverlays()
|
||||
};
|
||||
window.__audit.mut = 0;
|
||||
// 探测「触发文件选择框」:按钮 onClick 里调用隐藏 input[type=file].click() 会弹原生对话框,
|
||||
// DOM 无变化 → 否则会被误判 dead。这里 hook 一下,捕获到即算「有反应」。
|
||||
window.__audit.filePick = 0;
|
||||
if (!window.__audit._origInputClick) {
|
||||
window.__audit._origInputClick = HTMLInputElement.prototype.click;
|
||||
HTMLInputElement.prototype.click = function () {
|
||||
if (this.type === 'file') window.__audit.filePick = (window.__audit.filePick || 0) + 1;
|
||||
return window.__audit._origInputClick.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
window.__audit.obs && window.__audit.obs.disconnect();
|
||||
window.__audit.obs = new MutationObserver(muts=>{ window.__audit.mut += muts.length; });
|
||||
window.__audit.obs.observe(document.body, { subtree:true, childList:true, attributes:true, characterData:true });
|
||||
window.__audit.el = el;
|
||||
try { el.click(); } catch(e){ return { ok:false, reason:'click-threw:'+e.message }; }
|
||||
return { ok:true };
|
||||
};
|
||||
|
||||
// 读差量
|
||||
window.__audit.read = function(){
|
||||
const b = window.__audit.base; const el = window.__audit.el;
|
||||
window.__audit.obs && window.__audit.obs.disconnect();
|
||||
const overlaySel = '.modal,.drawer,[role=dialog],.toast,.chip-menu,.dropdown,.menu,.popover,[data-open=true]';
|
||||
const overlaysNow = Array.from(document.querySelectorAll(overlaySel)).filter(window.__audit.isVisible).length;
|
||||
const selfSigNow = el ? (el.className+'|'+el.getAttribute('aria-expanded')+'|'+el.getAttribute('aria-selected')+'|'+el.getAttribute('aria-checked')+'|'+(el.checked??'')) : '';
|
||||
return {
|
||||
urlChanged: location.href !== b.url,
|
||||
overlayChanged: overlaysNow !== b.overlaysN,
|
||||
selfChanged: el ? (selfSigNow !== b.selfSig) : false,
|
||||
mutations: window.__audit.mut,
|
||||
filePick: window.__audit.filePick || 0,
|
||||
isSelect: el ? el.tagName === 'SELECT' : false
|
||||
};
|
||||
};
|
||||
|
||||
// 设计稿/任意页的控件文字清单(用于 MISSING 对比)
|
||||
window.__audit.labels = function(){
|
||||
const strong = Array.from(document.querySelectorAll(window.__audit.SEL_STRONG));
|
||||
const weak = Array.from(document.querySelectorAll(window.__audit.SEL_WEAK)).filter(el => getComputedStyle(el).cursor === 'pointer');
|
||||
return strong.concat(weak)
|
||||
.filter(window.__audit.isVisible)
|
||||
.filter(el => !window.__audit.isWrapper(el))
|
||||
.map(window.__audit.label)
|
||||
.filter(Boolean);
|
||||
};
|
||||
`;
|
||||
|
||||
// 就绪门:等到 app 外壳(aside.sidebar)出现。若落到登录页(.auth-wrap)= boot 时
|
||||
// api.me() 挂了(远程库抖动 / 单线程 Django 被高频 reload 打爆),返回 not-ready。
|
||||
async function waitForReady(page, timeout = 8000) {
|
||||
const deadline = Date.now() + timeout;
|
||||
while (Date.now() < deadline) {
|
||||
const state = await page.evaluate(() => {
|
||||
if (document.querySelector(".auth-wrap")) return "auth";
|
||||
if (document.querySelector("aside.sidebar")) return "ready";
|
||||
return "pending";
|
||||
}).catch(() => "pending");
|
||||
if (state === "ready") return true;
|
||||
if (state === "auth") return false;
|
||||
await page.waitForTimeout(200);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// 进目标路由并确保 app 真的加载出来;落登录页就重注 token 重试(治瞬时 boot 失败)。
|
||||
async function gotoWithToken(page, url, tries = 3) {
|
||||
for (let attempt = 1; attempt <= tries; attempt++) {
|
||||
await page.goto(`${BASE}/`, { waitUntil: "domcontentloaded" }).catch(() => {});
|
||||
await page.evaluate((t) => localStorage.setItem("airshelf_token", t), TOKEN).catch(() => {});
|
||||
await page.goto(url, { waitUntil: "networkidle" }).catch(() => {});
|
||||
if (await waitForReady(page)) {
|
||||
await page.addStyleTag({ content: `*,*::before,*::after{animation-duration:0s!important;transition-duration:0s!important}` }).catch(() => {});
|
||||
return true;
|
||||
}
|
||||
await page.waitForTimeout(600 * attempt); // 退避后重试,给后端喘息
|
||||
}
|
||||
return false; // 仍未就绪 = 页面 blocked(后端/数据不可用),由调用方标记
|
||||
}
|
||||
|
||||
const norm = (s) => s.replace(/\s+/g, "").replace(/[0-9]+/g, "").toLowerCase();
|
||||
|
||||
async function collectDesignLabels(context, exactName) {
|
||||
const page = await context.newPage();
|
||||
try {
|
||||
// 设计稿镜像:宽松导航即可(shell.js 注入侧栏),不走严格就绪门 / 重试
|
||||
await page.goto(`${BASE}/`, { waitUntil: "domcontentloaded" }).catch(() => {});
|
||||
await page.evaluate((t) => localStorage.setItem("airshelf_token", t), TOKEN).catch(() => {});
|
||||
await page.goto(`${BASE}/exact/${exactName}`, { waitUntil: "networkidle" }).catch(() => {});
|
||||
await page.waitForTimeout(1200);
|
||||
await page.evaluate(PAGE_HELPERS);
|
||||
return await page.evaluate(() => window.__audit.labels());
|
||||
} catch {
|
||||
return [];
|
||||
} finally {
|
||||
await page.close();
|
||||
}
|
||||
}
|
||||
|
||||
async function auditPage(context, item, ids) {
|
||||
const route = item.route
|
||||
.replace(":productId", ids.productId || "x")
|
||||
.replace(":projectId", ids.projectId || "x");
|
||||
const url = `${BASE}${route}`;
|
||||
const page = await context.newPage();
|
||||
|
||||
// 探针:网络命中(node 侧带时间戳)/ 真·JS 异常(pageerror → error 判定)/ console.error(仅备注)
|
||||
const apiHits = [];
|
||||
const pageErrors = []; // 真正抛出的 JS 异常 —— 才算 error
|
||||
const consoleErrs = []; // console.error(含 React 警告 / 资源 404)—— 只做备注,不改判定
|
||||
page.on("request", (r) => { if (r.url().includes("/api/")) apiHits.push({ t: Date.now(), u: r.url() }); });
|
||||
page.on("console", (m) => { if (m.type() === "error") consoleErrs.push({ t: Date.now(), m: m.text().slice(0, 200) }); });
|
||||
page.on("pageerror", (e) => pageErrors.push({ t: Date.now(), m: String(e).slice(0, 200) }));
|
||||
|
||||
const ensureFresh = async () => {
|
||||
const ready = await gotoWithToken(page, url);
|
||||
if (!ready) return null;
|
||||
await page.evaluate(PAGE_HELPERS);
|
||||
return page.evaluate((ip) => window.__audit.collect(ip), INCLUDE_POINTER);
|
||||
};
|
||||
const recollect = async () => {
|
||||
await page.evaluate(PAGE_HELPERS).catch(() => {});
|
||||
return page.evaluate((ip) => window.__audit.collect(ip), INCLUDE_POINTER).catch(() => null);
|
||||
};
|
||||
|
||||
let inventory = await ensureFresh();
|
||||
if (!inventory) {
|
||||
// 页面始终落登录页/未就绪 —— 后端/数据不可用,标 blocked,绝不谎报 0 dead
|
||||
await page.close();
|
||||
return { name: item.name, route, url, mode: MODE, blocked: true,
|
||||
tally: { total: 0, works: 0, dead: 0, error: 0, disabled: 0, skipped: 0, noop: 0, blocked: 1 }, results: [], missing: [] };
|
||||
}
|
||||
const total = inventory.length;
|
||||
const results = [];
|
||||
|
||||
for (let i = 0; i < total; i++) {
|
||||
// 复位取基线:isolated 每个元素都 reload(确定性枚举,索引稳,不漏控件);
|
||||
// quick 不 reload,仅在漂出本路由时才 reload(快但有级联漂移)。
|
||||
if (MODE === "isolated") {
|
||||
const fresh = await ensureFresh();
|
||||
if (!fresh) { results.push({ idx: i, label: inventory[i]?.label || "", tag: "", verdict: "blocked" }); continue; }
|
||||
inventory = fresh;
|
||||
} else {
|
||||
const cur = await page.evaluate(() => location.href).catch(() => "");
|
||||
if (!(cur.startsWith(url) || cur.includes(route))) {
|
||||
const fresh = await ensureFresh();
|
||||
if (!fresh) { results.push({ idx: i, label: "", tag: "", verdict: "blocked" }); continue; }
|
||||
inventory = fresh;
|
||||
} else {
|
||||
const re = await recollect();
|
||||
if (re) inventory = re;
|
||||
}
|
||||
}
|
||||
const meta = inventory[i];
|
||||
if (!meta) { results.push({ idx: i, label: "", tag: "", verdict: "stale" }); continue; }
|
||||
|
||||
if (meta.disabled) { results.push({ ...meta, verdict: "disabled" }); continue; }
|
||||
if (DESTRUCTIVE.test(meta.label)) { results.push({ ...meta, verdict: "skipped-destructive" }); continue; }
|
||||
|
||||
const tBefore = Date.now();
|
||||
const armed = await page.evaluate((idx) => window.__audit.arm(idx), meta.idx);
|
||||
if (!armed.ok) { results.push({ ...meta, verdict: "stale", detail: armed.reason }); continue; }
|
||||
await page.waitForTimeout(SETTLE);
|
||||
let delta;
|
||||
try {
|
||||
delta = await page.evaluate(() => window.__audit.read());
|
||||
} catch {
|
||||
delta = { urlChanged: true, overlayChanged: false, selfChanged: false, mutations: 0 }; // 上下文销毁=跳转=有反应
|
||||
}
|
||||
const net = apiHits.filter((h) => h.t >= tBefore).length;
|
||||
const thrown = pageErrors.filter((e) => e.t >= tBefore).map((e) => e.m);
|
||||
const cerr = consoleErrs.filter((e) => e.t >= tBefore).map((e) => e.m);
|
||||
|
||||
// 文件选择框(原生对话框)/ 原生 select(原生下拉)点击 DOM 无变化但确属可用控件,算 works
|
||||
const reacted = delta.urlChanged || delta.overlayChanged || delta.selfChanged || net > 0 || delta.mutations >= 1 || delta.filePick > 0 || delta.isSelect;
|
||||
// 点「当前已选中」的 tab/chip 本就该无反应 —— 记 noop-active,不算缺陷
|
||||
let verdict = thrown.length ? "error" : reacted ? "works" : (meta.active ? "noop-active" : "dead");
|
||||
|
||||
results.push({
|
||||
...meta, verdict,
|
||||
signals: { url: delta.urlChanged, overlay: delta.overlayChanged, self: delta.selfChanged, mutations: delta.mutations, api: net },
|
||||
...(thrown.length ? { errors: thrown } : {}),
|
||||
...(cerr.length ? { consoleNote: cerr.slice(0, 2) } : {})
|
||||
});
|
||||
|
||||
if (MODE === "quick") await page.keyboard.press("Escape").catch(() => {});
|
||||
}
|
||||
|
||||
// MISSING:设计稿有、React 没渲染出来的控件(按文字模糊匹配,启发式)
|
||||
const designLabels = await collectDesignLabels(context, item.exact);
|
||||
const implSet = new Set(inventory.map((m) => norm(m.label)).filter(Boolean));
|
||||
const missing = [];
|
||||
const seenD = new Set();
|
||||
for (const dl of designLabels) {
|
||||
const n = norm(dl);
|
||||
if (!n || n.length < 2 || seenD.has(n)) continue;
|
||||
seenD.add(n);
|
||||
if (!implSet.has(n)) missing.push(dl.slice(0, 48));
|
||||
}
|
||||
|
||||
await page.close();
|
||||
|
||||
const tally = { total: results.length, works: 0, dead: 0, error: 0, disabled: 0, skipped: 0, noop: 0, blocked: 0 };
|
||||
for (const r of results) {
|
||||
if (r.verdict === "works") tally.works++;
|
||||
else if (r.verdict === "dead") tally.dead++;
|
||||
else if (r.verdict === "error") tally.error++;
|
||||
else if (r.verdict === "disabled") tally.disabled++;
|
||||
else if (r.verdict === "noop-active") tally.noop++;
|
||||
else if (r.verdict === "blocked") tally.blocked++;
|
||||
else tally.skipped++;
|
||||
}
|
||||
|
||||
return { name: item.name, route, url, mode: MODE, tally, results, missing };
|
||||
}
|
||||
|
||||
function writePageReport(rep) {
|
||||
fs.writeFileSync(path.join(outDir, `${rep.name}.audit.json`), JSON.stringify(rep, null, 2) + "\n");
|
||||
const lines = [];
|
||||
lines.push(`# 功能审计 · ${rep.name}`);
|
||||
lines.push("");
|
||||
if (rep.blocked) {
|
||||
lines.push(`> ⛔ **BLOCKED**:路由 \`${rep.route}\` 始终落到登录页/未就绪,后端或数据不可用,本页未审计。`);
|
||||
lines.push("> 先确认后端 :8010 健康(\`.venv/bin/python\`)+ 远程库可达,再单独 \`--only " + rep.name + "\` 复跑。");
|
||||
fs.writeFileSync(path.join(outDir, `${rep.name}.audit.md`), lines.join("\n") + "\n");
|
||||
return;
|
||||
}
|
||||
lines.push(`路由:\`${rep.route}\` · 模式:${rep.mode}`);
|
||||
lines.push(`合计 ${rep.tally.total} · ✅ works ${rep.tally.works} · ❌ **dead ${rep.tally.dead}** · 🛑 error ${rep.tally.error} · ⏭ skipped(破坏性)${rep.tally.skipped} · ◷ noop-active ${rep.tally.noop} · ⚪ disabled ${rep.tally.disabled}`);
|
||||
lines.push("");
|
||||
const dead = rep.results.filter((r) => r.verdict === "dead");
|
||||
if (dead.length) {
|
||||
lines.push("## ❌ 点了没反应(DEAD —— 重点修)");
|
||||
lines.push("| # | 文字 | 标签 | 类名 |");
|
||||
lines.push("|---|---|---|---|");
|
||||
for (const r of dead) lines.push(`| ${r.idx} | ${r.label || "(空)"} | \`${r.tag}${r.role ? "/" + r.role : ""}\` | \`${r.cls}\` |`);
|
||||
lines.push("");
|
||||
}
|
||||
const errs = rep.results.filter((r) => r.verdict === "error");
|
||||
if (errs.length) {
|
||||
lines.push("## 🛑 点击报错(ERROR)");
|
||||
for (const r of errs) lines.push(`- **${r.label}** \`${r.tag}\` — ${(r.errors || [r.detail]).join("; ")}`);
|
||||
lines.push("");
|
||||
}
|
||||
if (rep.missing.length) {
|
||||
lines.push("## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)");
|
||||
lines.push("> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。");
|
||||
lines.push("");
|
||||
for (const m of rep.missing) lines.push(`- ${m}`);
|
||||
lines.push("");
|
||||
}
|
||||
const skip = rep.results.filter((r) => r.verdict === "skipped-destructive");
|
||||
if (skip.length) {
|
||||
lines.push("## ⏭ 破坏性按钮(未自动点,需人工验)");
|
||||
for (const r of skip) lines.push(`- ${r.label} \`${r.tag}\``);
|
||||
lines.push("");
|
||||
}
|
||||
fs.writeFileSync(path.join(outDir, `${rep.name}.audit.md`), lines.join("\n") + "\n");
|
||||
}
|
||||
|
||||
(async () => {
|
||||
TOKEN = await login();
|
||||
const ids = await fetchIds();
|
||||
let manifest = JSON.parse(fs.readFileSync(path.join(here, "pages.json"), "utf8"));
|
||||
if (ONLY.length) manifest = manifest.filter((m) => ONLY.some((o) => m.name.includes(o)));
|
||||
|
||||
const browser = await chromium.launch({ headless: !HEADED });
|
||||
const context = await browser.newContext({ viewport: { width: 1440, height: 900 }, colorScheme: "light" });
|
||||
|
||||
const summary = [];
|
||||
for (const item of manifest) {
|
||||
process.stdout.write(`\n[function-audit] ${item.name} … `);
|
||||
try {
|
||||
const rep = await auditPage(context, item, ids);
|
||||
writePageReport(rep);
|
||||
summary.push({ page: rep.name, blocked: !!rep.blocked, ...rep.tally, missing: rep.missing.length });
|
||||
process.stdout.write(rep.blocked ? "⛔ BLOCKED(后端/数据不可用)" : `dead ${rep.tally.dead} / ${rep.tally.total}, missing ${rep.missing.length}`);
|
||||
} catch (e) {
|
||||
process.stdout.write(`FAILED ${e.message}`);
|
||||
summary.push({ page: item.name, total: 0, works: 0, dead: 0, error: 0, disabled: 0, skipped: 0, missing: 0, failed: e.message });
|
||||
}
|
||||
}
|
||||
await browser.close();
|
||||
|
||||
// 汇总
|
||||
const sl = ["# 功能审计汇总", "", `生成时间:${new Date().toISOString()} · 模式:${MODE}`, ""];
|
||||
sl.push("| 页面 | 合计 | ✅works | ❌dead | 🛑error | ⏭skip | 🔍missing | 状态 |");
|
||||
sl.push("|---|---|---|---|---|---|---|---|");
|
||||
for (const s of summary) {
|
||||
const st = s.blocked ? "⛔BLOCKED" : (s.failed ? "⚠️FAILED" : "");
|
||||
sl.push(`| ${s.page} | ${s.total} | ${s.works} | **${s.dead}** | ${s.error} | ${s.skipped} | ${s.missing} | ${st} |`);
|
||||
}
|
||||
sl.push("");
|
||||
sl.push("- ⛔blocked = 页面始终落登录页/未就绪(后端或远程库不可用),**未审计**,非「0 缺陷」。修好后端再单独 `--only <page>` 复跑。");
|
||||
sl.push("- ❌dead = 点了五路探针(URL/浮层/自身状态/网络/DOM)全无反应,优先修。");
|
||||
sl.push("- 🔍missing = 设计稿 `/exact` 有、React 没渲染出来的控件(启发式,需人工过)。");
|
||||
sl.push("- ⏭skip = 破坏性按钮(删除/充值/生成…)未自动点,需人工验。");
|
||||
sl.push("- 单页明细见 `output/<page>.audit.md`。");
|
||||
fs.writeFileSync(path.join(outDir, "summary.md"), sl.join("\n") + "\n");
|
||||
fs.writeFileSync(path.join(outDir, "summary.json"), JSON.stringify(summary, null, 2) + "\n");
|
||||
|
||||
console.log("\n\n[function-audit] summary");
|
||||
console.table(summary.map((s) => ({ page: s.page, total: s.total, works: s.works, dead: s.dead, error: s.error, missing: s.missing })));
|
||||
console.log(`\n报告:${path.relative(repoRoot, path.join(outDir, "summary.md"))}`);
|
||||
})();
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
[function-audit] dashboard … dead 0 / 30, missing 20
|
||||
[function-audit] products … dead 0 / 25, missing 11
|
||||
[function-audit] product-detail … dead 0 / 23, missing 6
|
||||
[function-audit] product-create … dead 5 / 31, missing 11
|
||||
[function-audit] projects … dead 0 / 30, missing 14
|
||||
[function-audit] projects-new … dead 0 / 15, missing 14
|
||||
[function-audit] pipeline … dead 1 / 29, missing 5
|
||||
[function-audit] library … dead 0 / 26, missing 6
|
||||
[function-audit] account … dead 0 / 26, missing 5
|
||||
[function-audit] team … dead 0 / 17, missing 7
|
||||
[function-audit] messages … dead 0 / 26, missing 11
|
||||
[function-audit] asset-factory … dead 2 / 26, missing 4
|
||||
[function-audit] image-optimize … dead 1 / 24, missing 12
|
||||
[function-audit] model-photo … dead 0 / 37, missing 6
|
||||
[function-audit] model-photo-demo-a … dead 0 / 38, missing 5
|
||||
[function-audit] model-photo-demo-b … dead 4 / 37, missing 5
|
||||
[function-audit] platform-cover … dead 0 / 38, missing 8
|
||||
[function-audit] settings … dead 1 / 26, missing 4
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'dashboard' │ 30 │ 29 │ 0 │ 0 │ 20 │
|
||||
│ 1 │ 'products' │ 25 │ 25 │ 0 │ 0 │ 11 │
|
||||
│ 2 │ 'product-detail' │ 23 │ 21 │ 0 │ 0 │ 6 │
|
||||
│ 3 │ 'product-create' │ 31 │ 26 │ 5 │ 0 │ 11 │
|
||||
│ 4 │ 'projects' │ 30 │ 28 │ 0 │ 0 │ 14 │
|
||||
│ 5 │ 'projects-new' │ 15 │ 15 │ 0 │ 0 │ 14 │
|
||||
│ 6 │ 'pipeline' │ 29 │ 26 │ 1 │ 0 │ 5 │
|
||||
│ 7 │ 'library' │ 26 │ 25 │ 0 │ 0 │ 6 │
|
||||
│ 8 │ 'account' │ 26 │ 23 │ 0 │ 0 │ 5 │
|
||||
│ 9 │ 'team' │ 17 │ 16 │ 0 │ 0 │ 7 │
|
||||
│ 10 │ 'messages' │ 26 │ 25 │ 0 │ 0 │ 11 │
|
||||
│ 11 │ 'asset-factory' │ 26 │ 19 │ 2 │ 0 │ 4 │
|
||||
│ 12 │ 'image-optimize' │ 24 │ 23 │ 1 │ 0 │ 12 │
|
||||
│ 13 │ 'model-photo' │ 37 │ 34 │ 0 │ 0 │ 6 │
|
||||
│ 14 │ 'model-photo-demo-a' │ 38 │ 34 │ 0 │ 0 │ 5 │
|
||||
│ 15 │ 'model-photo-demo-b' │ 37 │ 31 │ 4 │ 0 │ 5 │
|
||||
│ 16 │ 'platform-cover' │ 38 │ 36 │ 0 │ 0 │ 8 │
|
||||
│ 17 │ 'settings' │ 26 │ 23 │ 1 │ 0 │ 4 │
|
||||
└─────────┴──────────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
[function-audit] dashboard … dead 0 / 30, missing 20
|
||||
[function-audit] products … FAILED page.waitForTimeout: Target page, context or browser has been closed
|
||||
[function-audit] product-detail … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] product-create … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] projects … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] projects-new … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] pipeline … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] library … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] account … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] team … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] messages … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] asset-factory … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] image-optimize … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] model-photo … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] model-photo-demo-a … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] model-photo-demo-b … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] platform-cover … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
[function-audit] settings … FAILED browserContext.newPage: Target page, context or browser has been closed
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'dashboard' │ 30 │ 29 │ 0 │ 0 │ 20 │
|
||||
│ 1 │ 'products' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 2 │ 'product-detail' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 3 │ 'product-create' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 4 │ 'projects' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 5 │ 'projects-new' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 6 │ 'pipeline' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 7 │ 'library' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 8 │ 'account' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 9 │ 'team' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 10 │ 'messages' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 11 │ 'asset-factory' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 12 │ 'image-optimize' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 13 │ 'model-photo' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 14 │ 'model-photo-demo-a' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 15 │ 'model-photo-demo-b' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 16 │ 'platform-cover' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
│ 17 │ 'settings' │ 0 │ 0 │ 0 │ 0 │ 0 │
|
||||
└─────────┴──────────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
[function-audit] dashboard … dead 1 / 29, missing 20
|
||||
[function-audit] products … dead 10 / 32, missing 13
|
||||
[function-audit] product-detail … dead 15 / 37, missing 8
|
||||
[function-audit] product-create … dead 9 / 32, missing 13
|
||||
[function-audit] projects … dead 5 / 31, missing 19
|
||||
[function-audit] projects-new … dead 2 / 20, missing 27
|
||||
[function-audit] pipeline … dead 6 / 32, missing 5
|
||||
[function-audit] library … dead 10 / 30, missing 12
|
||||
[function-audit] account … dead 3 / 25, missing 5
|
||||
[function-audit] team … dead 1 / 16, missing 7
|
||||
[function-audit] messages … dead 1 / 42, missing 19
|
||||
[function-audit] asset-factory … dead 17 / 33, missing 6
|
||||
[function-audit] image-optimize … dead 3 / 23, missing 15
|
||||
[function-audit] model-photo … dead 6 / 35, missing 14
|
||||
[function-audit] model-photo-demo-a … dead 17 / 37, missing 5
|
||||
[function-audit] model-photo-demo-b … dead 27 / 47, missing 5
|
||||
[function-audit] platform-cover … dead 2 / 37, missing 15
|
||||
[function-audit] settings … dead 5 / 25, missing 4
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'dashboard' │ 29 │ 27 │ 1 │ 0 │ 20 │
|
||||
│ 1 │ 'products' │ 32 │ 22 │ 10 │ 0 │ 13 │
|
||||
│ 2 │ 'product-detail' │ 37 │ 20 │ 15 │ 0 │ 8 │
|
||||
│ 3 │ 'product-create' │ 32 │ 23 │ 9 │ 0 │ 13 │
|
||||
│ 4 │ 'projects' │ 31 │ 24 │ 5 │ 0 │ 19 │
|
||||
│ 5 │ 'projects-new' │ 20 │ 16 │ 2 │ 0 │ 27 │
|
||||
│ 6 │ 'pipeline' │ 32 │ 24 │ 6 │ 0 │ 5 │
|
||||
│ 7 │ 'library' │ 30 │ 19 │ 10 │ 0 │ 12 │
|
||||
│ 8 │ 'account' │ 25 │ 19 │ 3 │ 0 │ 5 │
|
||||
│ 9 │ 'team' │ 16 │ 14 │ 1 │ 0 │ 7 │
|
||||
│ 10 │ 'messages' │ 42 │ 39 │ 1 │ 0 │ 19 │
|
||||
│ 11 │ 'asset-factory' │ 33 │ 11 │ 17 │ 0 │ 6 │
|
||||
│ 12 │ 'image-optimize' │ 23 │ 20 │ 3 │ 0 │ 15 │
|
||||
│ 13 │ 'model-photo' │ 35 │ 26 │ 6 │ 0 │ 14 │
|
||||
│ 14 │ 'model-photo-demo-a' │ 37 │ 17 │ 17 │ 0 │ 5 │
|
||||
│ 15 │ 'model-photo-demo-b' │ 47 │ 17 │ 27 │ 0 │ 5 │
|
||||
│ 16 │ 'platform-cover' │ 37 │ 33 │ 2 │ 0 │ 15 │
|
||||
│ 17 │ 'settings' │ 25 │ 18 │ 5 │ 0 │ 4 │
|
||||
└─────────┴──────────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] dashboard … dead 0 / 25, missing 20
|
||||
[function-audit] products … dead 0 / 25, missing 11
|
||||
[function-audit] product-detail … dead 0 / 23, missing 7
|
||||
[function-audit] product-create … dead 0 / 31, missing 11
|
||||
[function-audit] account … dead 0 / 26, missing 5
|
||||
[function-audit] team … dead 0 / 17, missing 7
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'dashboard' │ 25 │ 24 │ 0 │ 0 │ 20 │
|
||||
│ 1 │ 'products' │ 25 │ 25 │ 0 │ 0 │ 11 │
|
||||
│ 2 │ 'product-detail' │ 23 │ 21 │ 0 │ 0 │ 7 │
|
||||
│ 3 │ 'product-create' │ 31 │ 31 │ 0 │ 0 │ 11 │
|
||||
│ 4 │ 'account' │ 26 │ 23 │ 0 │ 0 │ 5 │
|
||||
│ 5 │ 'team' │ 17 │ 16 │ 0 │ 0 │ 7 │
|
||||
└─────────┴──────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] projects … dead 0 / 24, missing 15
|
||||
[function-audit] projects-new … dead 0 / 15, missing 14
|
||||
[function-audit] pipeline … dead 0 / 29, missing 5
|
||||
[function-audit] library … dead 0 / 26, missing 6
|
||||
[function-audit] messages … dead 0 / 26, missing 11
|
||||
[function-audit] settings … dead 0 / 26, missing 4
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'projects' │ 24 │ 22 │ 0 │ 0 │ 15 │
|
||||
│ 1 │ 'projects-new' │ 15 │ 15 │ 0 │ 0 │ 14 │
|
||||
│ 2 │ 'pipeline' │ 29 │ 27 │ 0 │ 0 │ 5 │
|
||||
│ 3 │ 'library' │ 26 │ 25 │ 0 │ 0 │ 6 │
|
||||
│ 4 │ 'messages' │ 26 │ 25 │ 0 │ 0 │ 11 │
|
||||
│ 5 │ 'settings' │ 26 │ 24 │ 0 │ 0 │ 4 │
|
||||
└─────────┴────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] asset-factory … dead 0 / 24, missing 4
|
||||
[function-audit] image-optimize … dead 0 / 24, missing 12
|
||||
[function-audit] model-photo … dead 0 / 36, missing 6
|
||||
[function-audit] model-photo-demo-a … dead 0 / 37, missing 5
|
||||
[function-audit] model-photo-demo-b … dead 0 / 37, missing 5
|
||||
[function-audit] platform-cover … dead 0 / 38, missing 8
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'asset-factory' │ 24 │ 19 │ 0 │ 0 │ 4 │
|
||||
│ 1 │ 'image-optimize' │ 24 │ 24 │ 0 │ 0 │ 12 │
|
||||
│ 2 │ 'model-photo' │ 36 │ 33 │ 0 │ 0 │ 6 │
|
||||
│ 3 │ 'model-photo-demo-a' │ 37 │ 34 │ 0 │ 0 │ 5 │
|
||||
│ 4 │ 'model-photo-demo-b' │ 37 │ 36 │ 0 │ 0 │ 5 │
|
||||
│ 5 │ 'platform-cover' │ 38 │ 36 │ 0 │ 0 │ 8 │
|
||||
└─────────┴──────────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] dashboard … dead 0 / 25, missing 20
|
||||
[function-audit] products … dead 0 / 25, missing 11
|
||||
[function-audit] product-detail … dead 0 / 29, missing 7
|
||||
[function-audit] product-create … dead 0 / 31, missing 11
|
||||
[function-audit] account … dead 0 / 26, missing 5
|
||||
[function-audit] team … dead 0 / 17, missing 7
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'dashboard' │ 25 │ 25 │ 0 │ 0 │ 20 │
|
||||
│ 1 │ 'products' │ 25 │ 25 │ 0 │ 0 │ 11 │
|
||||
│ 2 │ 'product-detail' │ 29 │ 28 │ 0 │ 0 │ 7 │
|
||||
│ 3 │ 'product-create' │ 31 │ 31 │ 0 │ 0 │ 11 │
|
||||
│ 4 │ 'account' │ 26 │ 21 │ 0 │ 0 │ 5 │
|
||||
│ 5 │ 'team' │ 17 │ 17 │ 0 │ 0 │ 7 │
|
||||
└─────────┴──────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] projects … dead 0 / 24, missing 15
|
||||
[function-audit] projects-new … dead 0 / 15, missing 14
|
||||
[function-audit] pipeline … dead 0 / 29, missing 5
|
||||
[function-audit] library … dead 0 / 38, missing 6
|
||||
[function-audit] messages … dead 0 / 26, missing 11
|
||||
[function-audit] settings … dead 0 / 26, missing 4
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'projects' │ 24 │ 22 │ 0 │ 0 │ 15 │
|
||||
│ 1 │ 'projects-new' │ 15 │ 15 │ 0 │ 0 │ 14 │
|
||||
│ 2 │ 'pipeline' │ 29 │ 27 │ 0 │ 0 │ 5 │
|
||||
│ 3 │ 'library' │ 38 │ 35 │ 0 │ 0 │ 6 │
|
||||
│ 4 │ 'messages' │ 26 │ 25 │ 0 │ 0 │ 11 │
|
||||
│ 5 │ 'settings' │ 26 │ 25 │ 0 │ 0 │ 4 │
|
||||
└─────────┴────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] asset-factory … dead 0 / 24, missing 4
|
||||
[function-audit] image-optimize … dead 0 / 24, missing 12
|
||||
[function-audit] model-photo … dead 0 / 32, missing 7
|
||||
[function-audit] model-photo-demo-a … dead 0 / 37, missing 5
|
||||
[function-audit] model-photo-demo-b … dead 0 / 37, missing 5
|
||||
[function-audit] platform-cover … dead 0 / 38, missing 8
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'asset-factory' │ 24 │ 22 │ 0 │ 0 │ 4 │
|
||||
│ 1 │ 'image-optimize' │ 24 │ 24 │ 0 │ 0 │ 12 │
|
||||
│ 2 │ 'model-photo' │ 32 │ 31 │ 0 │ 0 │ 7 │
|
||||
│ 3 │ 'model-photo-demo-a' │ 37 │ 33 │ 0 │ 0 │ 5 │
|
||||
│ 4 │ 'model-photo-demo-b' │ 37 │ 36 │ 0 │ 0 │ 5 │
|
||||
│ 5 │ 'platform-cover' │ 38 │ 35 │ 0 │ 0 │ 8 │
|
||||
└─────────┴──────────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
[function-audit] products … dead 1 / 25, missing 11
|
||||
[function-audit] product-detail … dead 0 / 29, missing 7
|
||||
[function-audit] account … dead 2 / 26, missing 5
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'products' │ 25 │ 24 │ 1 │ 0 │ 11 │
|
||||
│ 1 │ 'product-detail' │ 29 │ 21 │ 0 │ 0 │ 7 │
|
||||
│ 2 │ 'account' │ 26 │ 21 │ 2 │ 0 │ 5 │
|
||||
└─────────┴──────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
[function-audit] product-create … dead 2 / 31, missing 11
|
||||
[function-audit] pipeline … dead 0 / 29, missing 5
|
||||
[function-audit] asset-factory … dead 2 / 26, missing 4
|
||||
[function-audit] image-optimize … dead 0 / 24, missing 12
|
||||
[function-audit] model-photo-demo-b … dead 0 / 37, missing 5
|
||||
[function-audit] settings … dead 1 / 26, missing 4
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'product-create' │ 31 │ 29 │ 2 │ 0 │ 11 │
|
||||
│ 1 │ 'pipeline' │ 29 │ 27 │ 0 │ 0 │ 5 │
|
||||
│ 2 │ 'asset-factory' │ 26 │ 19 │ 2 │ 0 │ 4 │
|
||||
│ 3 │ 'image-optimize' │ 24 │ 24 │ 0 │ 0 │ 12 │
|
||||
│ 4 │ 'model-photo-demo-b' │ 37 │ 36 │ 0 │ 0 │ 5 │
|
||||
│ 5 │ 'settings' │ 26 │ 23 │ 1 │ 0 │ 4 │
|
||||
└─────────┴──────────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
[function-audit] product-create … dead 0 / 31, missing 11
|
||||
[function-audit] asset-factory … dead 0 / 24, missing 4
|
||||
[function-audit] settings … dead 0 / 26, missing 4
|
||||
|
||||
[function-audit] summary
|
||||
┌─────────┬──────────────────┬───────┬───────┬──────┬───────┬─────────┐
|
||||
│ (index) │ page │ total │ works │ dead │ error │ missing │
|
||||
├─────────┼──────────────────┼───────┼───────┼──────┼───────┼─────────┤
|
||||
│ 0 │ 'product-create' │ 31 │ 31 │ 0 │ 0 │ 11 │
|
||||
│ 1 │ 'asset-factory' │ 24 │ 19 │ 0 │ 0 │ 4 │
|
||||
│ 2 │ 'settings' │ 26 │ 24 │ 0 │ 0 │ 4 │
|
||||
└─────────┴──────────────────┴───────┴───────┴──────┴───────┴─────────┘
|
||||
|
||||
报告:core/qa/function-audit/output/summary.md
|
||||
@@ -0,0 +1,479 @@
|
||||
{
|
||||
"name": "account",
|
||||
"route": "/account",
|
||||
"url": "http://127.0.0.1:5173/account",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 26,
|
||||
"works": 21,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 2,
|
||||
"noop": 3,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "recharge-card.",
|
||||
"label": "¥100无赠送",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 9,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "recharge-card.selected",
|
||||
"label": "推荐¥500+ ¥30 赠送",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "recharge-card.",
|
||||
"label": "¥1000+ ¥80 赠送",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 9,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "recharge-card.",
|
||||
"label": "¥3000+ ¥300 赠送",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 9,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.pay-method-btn.pay-wechat",
|
||||
"label": "微信支付",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "skipped-destructive"
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.pay-method-btn.pay-alipay",
|
||||
"label": "支付宝",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "skipped-destructive"
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tab.active",
|
||||
"label": "总览",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tab.",
|
||||
"label": "项目 6",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tab.",
|
||||
"label": "成员 1",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tab.",
|
||||
"label": "账单流水 100",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip.active",
|
||||
"label": "日",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "周",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 38,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "月",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 38,
|
||||
"api": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"账单流水 30天"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
# 功能审计 · account
|
||||
|
||||
路由:`/account` · 模式:isolated
|
||||
合计 26 · ✅ works 21 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)2 · ◷ noop-active 3 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 账单流水 30天
|
||||
|
||||
## ⏭ 破坏性按钮(未自动点,需人工验)
|
||||
- 微信支付 `button`
|
||||
- 支付宝 `button`
|
||||
|
||||
@@ -0,0 +1,460 @@
|
||||
{
|
||||
"name": "asset-factory",
|
||||
"route": "/asset-factory",
|
||||
"url": "http://127.0.0.1:5173/asset-factory",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 24,
|
||||
"works": 22,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 2,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-lg",
|
||||
"label": "开始生成",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-lg",
|
||||
"label": "开始生成",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-lg",
|
||||
"label": "开始生成",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "tab.active",
|
||||
"label": "全部 20",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "tab",
|
||||
"label": "生成中 0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 10,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "tab",
|
||||
"label": "已完成 15",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "tab",
|
||||
"label": "失败 0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 10,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "时间",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "任务类型",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "网格",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "列表",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# 功能审计 · asset-factory
|
||||
|
||||
路由:`/asset-factory` · 模式:isolated
|
||||
合计 24 · ✅ works 22 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 2 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
|
||||
@@ -0,0 +1,490 @@
|
||||
{
|
||||
"name": "dashboard",
|
||||
"route": "/dashboard",
|
||||
"url": "http://127.0.0.1:5173/dashboard",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 25,
|
||||
"works": 25,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 41,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 27,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-lg",
|
||||
"label": "新建项目",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "stat",
|
||||
"label": "余额 ¥¥11116.00已冻结 ¥5.00",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 27,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "more",
|
||||
"label": "[ ALL · 6 ] →",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "recent-row",
|
||||
"label": "9:16真应用验证项目 · 补水面膜种草透真玻尿酸补水面膜 / AI 全生 / 4 镜基础资产继",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 5,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "recent-row",
|
||||
"label": "9:16端到端播放器验证南卡 Lite Pro 蓝牙耳机 / AI 全生 / 4 镜拼接导出继续",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 5,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "recent-row",
|
||||
"label": "9:16桥接测试项目 20260529透真玻尿酸补水面膜 / AI 全生 / 4 镜脚本继续",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 5,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "recent-row",
|
||||
"label": "9:16南卡 · 痛点种草 · v1南卡 Lite Pro 蓝牙耳机 / AI 全生 / 4 镜",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 5,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "recent-row",
|
||||
"label": "9:16南卡 · 痛点种草 · v1南卡 Lite Pro 蓝牙耳机 / AI 全生 / 4 镜",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 5,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "shortcut",
|
||||
"label": "商品库8 SKU",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "shortcut",
|
||||
"label": "资产库67 资产",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 41,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "shortcut",
|
||||
"label": "充值¥11116.00",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 27,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "shortcut",
|
||||
"label": "所有项目6 个",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"总项目 ALL 8 本月 +3",
|
||||
"进行中 WIP 3 2 个待审核",
|
||||
"本月成片 DONE 3 较上月 +33%",
|
||||
"余额 ¥ ¥327.40 已用 ¥162.60 / ¥500",
|
||||
"[ ALL · 8 ]",
|
||||
"9:16 补水面膜 · 痛点种草 · v3 透真补水面膜 / AI 全生 / 7 镜 故事板 待",
|
||||
"9:16 透真防晒 · 通勤对比 透真防晒 / AI 全生 / 6 镜 已完成 打开",
|
||||
"9:16 蓝牙耳机 · 开箱测评 Pro 4 蓝牙耳机 / 自带脚本 / 6 镜 视频生成 4/",
|
||||
"9:16 春日新品 · 立体口红 凝彩立体口红 / 一句话 / 5 镜 资产生成中 继续",
|
||||
"9:16 咖啡冻干 · 早八 冷萃咖啡冻干 / 一句话 / 5 镜 故事板失败 查看",
|
||||
"资产库人 8 · 景 14 · 片 8",
|
||||
"故事板 待确认",
|
||||
"已完成",
|
||||
"视频生成 4/6",
|
||||
"资产生成中",
|
||||
"故事板失败"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# 功能审计 · dashboard
|
||||
|
||||
路由:`/dashboard` · 模式:isolated
|
||||
合计 25 · ✅ works 25 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 总项目 ALL 8 本月 +3
|
||||
- 进行中 WIP 3 2 个待审核
|
||||
- 本月成片 DONE 3 较上月 +33%
|
||||
- 余额 ¥ ¥327.40 已用 ¥162.60 / ¥500
|
||||
- [ ALL · 8 ]
|
||||
- 9:16 补水面膜 · 痛点种草 · v3 透真补水面膜 / AI 全生 / 7 镜 故事板 待
|
||||
- 9:16 透真防晒 · 通勤对比 透真防晒 / AI 全生 / 6 镜 已完成 打开
|
||||
- 9:16 蓝牙耳机 · 开箱测评 Pro 4 蓝牙耳机 / 自带脚本 / 6 镜 视频生成 4/
|
||||
- 9:16 春日新品 · 立体口红 凝彩立体口红 / 一句话 / 5 镜 资产生成中 继续
|
||||
- 9:16 咖啡冻干 · 早八 冷萃咖啡冻干 / 一句话 / 5 镜 故事板失败 查看
|
||||
- 资产库人 8 · 景 14 · 片 8
|
||||
- 故事板 待确认
|
||||
- 已完成
|
||||
- 视频生成 4/6
|
||||
- 资产生成中
|
||||
- 故事板失败
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
{
|
||||
"name": "image-optimize",
|
||||
"route": "/image-optimize",
|
||||
"url": "http://127.0.0.1:5173/image-optimize",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 24,
|
||||
"works": 24,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "back-pill",
|
||||
"label": "返回",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ic-new-conv",
|
||||
"label": "新对话",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ex",
|
||||
"label": "一只穿着宇航服的橘猫,漂浮在霓虹色星云中,赛博朋克风",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ex",
|
||||
"label": "极简北欧风格的茶杯,白底,自然柔光,产品摄影",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ex",
|
||||
"label": "国风水墨海报,主体一只白鹤立于水边,留白构图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ex",
|
||||
"label": "电影感都市夜景,街道湿漉漉反射霓虹,4K 高清",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "add-btn",
|
||||
"label": "上传参考图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ic-param-btn",
|
||||
"label": "比例1:1",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 1,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ic-param-btn",
|
||||
"label": "风格默认",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 1,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ic-param-btn",
|
||||
"label": "张数4",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 1,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "send-btn",
|
||||
"label": "生成",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 21,
|
||||
"api": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"折叠侧栏",
|
||||
"时间",
|
||||
"生成模式",
|
||||
"操作类型",
|
||||
"一只穿着宇航服的橘猫,漂浮在霓虹色星云中,赛博朋克风",
|
||||
"极简北欧风格的茶杯,白底,自然柔光,产品摄影",
|
||||
"国风水墨海报,主体一只白鹤立于水边,留白构图",
|
||||
"电影感都市夜景,街道湿漉漉反射霓虹,4K 高清"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
# 功能审计 · image-optimize
|
||||
|
||||
路由:`/image-optimize` · 模式:isolated
|
||||
合计 24 · ✅ works 24 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 折叠侧栏
|
||||
- 时间
|
||||
- 生成模式
|
||||
- 操作类型
|
||||
- 一只穿着宇航服的橘猫,漂浮在霓虹色星云中,赛博朋克风
|
||||
- 极简北欧风格的茶杯,白底,自然柔光,产品摄影
|
||||
- 国风水墨海报,主体一只白鹤立于水边,留白构图
|
||||
- 电影感都市夜景,街道湿漉漉反射霓虹,4K 高清
|
||||
|
||||
@@ -0,0 +1,686 @@
|
||||
{
|
||||
"name": "library",
|
||||
"route": "/library",
|
||||
"url": "http://127.0.0.1:5173/library",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 38,
|
||||
"works": 35,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 2,
|
||||
"noop": 1,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-edit-toggle",
|
||||
"label": "管理资产",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary",
|
||||
"label": "上传资产",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab.active",
|
||||
"label": "人物 14",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "场景 11",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 48,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "商品图 35",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 97,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "成片 10",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 38,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "我的上传 1",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "未分类 0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 29,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "性别",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "年龄段",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "角色标签",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "来源",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "最近添加",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 32,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 33,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 34,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 35,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "placeholder.asset-thumb",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 36,
|
||||
"label": "",
|
||||
"tag": "",
|
||||
"verdict": "stale"
|
||||
},
|
||||
{
|
||||
"idx": 37,
|
||||
"label": "",
|
||||
"tag": "",
|
||||
"verdict": "stale"
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"最近使用",
|
||||
"缺三视图,查看说明"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# 功能审计 · library
|
||||
|
||||
路由:`/library` · 模式:isolated
|
||||
合计 38 · ✅ works 35 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)2 · ◷ noop-active 1 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 最近使用
|
||||
- 缺三视图,查看说明
|
||||
|
||||
@@ -0,0 +1,499 @@
|
||||
{
|
||||
"name": "messages",
|
||||
"route": "/messages",
|
||||
"url": "http://127.0.0.1:5173/messages",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 26,
|
||||
"works": 25,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 35,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 21,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 48,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn",
|
||||
"label": "全部标已读",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn",
|
||||
"label": "通知设置",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 58,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-filter.active",
|
||||
"label": "全部20",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-filter.",
|
||||
"label": "未读0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-filter.",
|
||||
"label": "任务20",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 4,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-filter.",
|
||||
"label": "团队0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-filter.",
|
||||
"label": "计费0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-filter.",
|
||||
"label": "系统0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-item.active.read",
|
||||
"label": "资产「AI 生成 · image · 4」已加入资产库7mProduct Image · Ima",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 2,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-item.read",
|
||||
"label": "资产「AI 生成 · image · 3」已加入资产库8mProduct Image · Ima",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-item.read",
|
||||
"label": "资产「AI 生成 · image · 2」已加入资产库8mProduct Image · Ima",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-item.read",
|
||||
"label": "资产「AI 生成 · image · 1」已加入资产库9mProduct Image · Ima",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "msg-item.read",
|
||||
"label": "资产「AI 生成 · cover · 4」已加入资产库21mProduct Image · Im",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"补水面膜 · 痛点种草 v3 成片已完成 12m 7 镜 · 40 秒 · ¥18.40 已结算",
|
||||
"脚本生成失败 · 618 大促 1h Prompt 超过服务限制,本次失败未扣费,可一键重试。 ",
|
||||
"4 张模特上身图已加入资产库 2h 祛痘精华 · 通勤白领 · 3:4,可直接进入视频项目。 已",
|
||||
"@刘 正在编辑「补水面膜」项目 3h 你暂时以只读方式查看该项目,避免两人同时改动覆盖。 更新 ",
|
||||
"@王芳 已加入团队 5h 角色为运营,月限额 ¥800,可读写团队资产。 更新 团队",
|
||||
"团队余额低于预警线 7h 当前余额 ¥87.20,按近 7 天速度预计可支撑 4 个视频项目。 ",
|
||||
"补水面膜 →"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# 功能审计 · messages
|
||||
|
||||
路由:`/messages` · 模式:isolated
|
||||
合计 26 · ✅ works 25 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 1 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 补水面膜 · 痛点种草 v3 成片已完成 12m 7 镜 · 40 秒 · ¥18.40 已结算
|
||||
- 脚本生成失败 · 618 大促 1h Prompt 超过服务限制,本次失败未扣费,可一键重试。
|
||||
- 4 张模特上身图已加入资产库 2h 祛痘精华 · 通勤白领 · 3:4,可直接进入视频项目。 已
|
||||
- @刘 正在编辑「补水面膜」项目 3h 你暂时以只读方式查看该项目,避免两人同时改动覆盖。 更新
|
||||
- @王芳 已加入团队 5h 角色为运营,月限额 ¥800,可读写团队资产。 更新 团队
|
||||
- 团队余额低于预警线 7h 当前余额 ¥87.20,按近 7 天速度预计可支撑 4 个视频项目。
|
||||
- 补水面膜 →
|
||||
|
||||
@@ -0,0 +1,712 @@
|
||||
{
|
||||
"name": "model-photo-demo-a",
|
||||
"route": "/model-photo/demo-a",
|
||||
"url": "http://127.0.0.1:5173/model-photo/demo-a",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 37,
|
||||
"works": 33,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 1,
|
||||
"noop": 3,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "add",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.active",
|
||||
"label": "主图南卡 Lite Pro 蓝牙耳机// 数码 3C · 6 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图露露同款裸感瑜伽裤// 运动户外 · 3 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图透真清透物理防晒霜// 美妆个护 · 2 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图滋啦速食牛肉面 · 6 桶装// 食品饮料 · 1 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图透真玻尿酸补水面膜// 美妆个护 · 1 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图桥接测试补水面膜 20260529// 美妆个护 · 0 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-all",
|
||||
"label": "全部商品8 个",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-back",
|
||||
"label": "返回模特图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.",
|
||||
"label": "1 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.",
|
||||
"label": "2 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.active",
|
||||
"label": "4 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.",
|
||||
"label": "8 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.",
|
||||
"label": "1:1",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.active",
|
||||
"label": "3:4",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.",
|
||||
"label": "9:16",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-chip.",
|
||||
"label": "16:9",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-gen",
|
||||
"label": "立即生成 · 南卡 Lite Pro 蓝牙耳机 × Ava",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "skipped-destructive"
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部重跑",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 32,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部下载",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 33,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "加入资产库",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 34,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部重跑",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 35,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部下载",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 36,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "加入资产库",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"立即生成 · 透真补水面膜 × Ava"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
# 功能审计 · model-photo-demo-a
|
||||
|
||||
路由:`/model-photo/demo-a` · 模式:isolated
|
||||
合计 37 · ✅ works 33 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)1 · ◷ noop-active 3 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 立即生成 · 透真补水面膜 × Ava
|
||||
|
||||
## ⏭ 破坏性按钮(未自动点,需人工验)
|
||||
- 立即生成 · 南卡 Lite Pro 蓝牙耳机 × Ava `button`
|
||||
|
||||
@@ -0,0 +1,755 @@
|
||||
{
|
||||
"name": "model-photo-demo-b",
|
||||
"route": "/model-photo/demo-b",
|
||||
"url": "http://127.0.0.1:5173/model-photo/demo-b",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 37,
|
||||
"works": 36,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "add",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.active",
|
||||
"label": "主图南卡 Lite Pro 蓝牙耳机// 数码 3C · 6 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图露露同款裸感瑜伽裤// 运动户外 · 3 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图透真清透物理防晒霜// 美妆个护 · 2 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图滋啦速食牛肉面 · 6 桶装// 食品饮料 · 1 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图透真玻尿酸补水面膜// 美妆个护 · 1 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-prod.",
|
||||
"label": "主图桥接测试补水面膜 20260529// 美妆个护 · 0 批",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-all",
|
||||
"label": "全部商品8 个",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "dm-back",
|
||||
"label": "返回模特图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icbtn",
|
||||
"label": "搜索批次",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "时间",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "状态",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部重跑",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部下载",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "加入资产库",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部重跑",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "全部下载",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "加入资产库",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 32,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "pchip.active",
|
||||
"label": "模特Ava",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 33,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "pchip",
|
||||
"label": "张数4",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 34,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "pchip",
|
||||
"label": "比例3:4",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 35,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "pchip",
|
||||
"label": "补充提示词+ 添加",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 36,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "gen-btn",
|
||||
"label": "生成 · 南卡 Lite Pro 蓝牙耳机 × Ava",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"生成 · 透真补水面膜 × Ava"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# 功能审计 · model-photo-demo-b
|
||||
|
||||
路由:`/model-photo/demo-b` · 模式:isolated
|
||||
合计 37 · ✅ works 36 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 1 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 生成 · 透真补水面膜 × Ava
|
||||
|
||||
@@ -0,0 +1,667 @@
|
||||
{
|
||||
"name": "model-photo",
|
||||
"route": "/model-photo",
|
||||
"url": "http://127.0.0.1:5173/model-photo",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 32,
|
||||
"works": 31,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "back-pill",
|
||||
"label": "返回",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "new-prod",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.active",
|
||||
"label": "南卡南卡 Lite Pro 蓝牙耳机// 数码 3C",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "露露露露同款裸感瑜伽裤// 运动户外",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "透真透真清透物理防晒霜// 美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "滋啦滋啦速食牛肉面 · 6 桶装// 食品饮料",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "透真透真玻尿酸补水面膜// 美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "桥接桥接测试补水面膜 20260529// 美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "三顿三顿半同款冻干咖啡粉// 食品饮料",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "小熊小熊 4L 可视空气炸锅// 家居家电",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "search-btn",
|
||||
"label": "搜索批次/模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tb-chip",
|
||||
"label": "时间",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tb-chip",
|
||||
"label": "模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "model-card.",
|
||||
"label": "AI 生成 · model · 4// 真人模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "model-card.",
|
||||
"label": "AI 生成 · model · 3// 真人模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "model-card.",
|
||||
"label": "AI 生成 · model · 2// 真人模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "model-card.",
|
||||
"label": "AI 生成 · model · 1// 真人模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "model-card.",
|
||||
"label": "AI 生成 · model · 4// 真人模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "model-card.",
|
||||
"label": "AI 生成 · model · 3// 真人模特",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"折叠侧栏",
|
||||
"全部商品 7 个",
|
||||
"立即生成 (预估 ¥0.00)"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# 功能审计 · model-photo
|
||||
|
||||
路由:`/model-photo` · 模式:isolated
|
||||
合计 32 · ✅ works 31 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 1 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 折叠侧栏
|
||||
- 全部商品 7 个
|
||||
- 立即生成 (预估 ¥0.00)
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
{
|
||||
"name": "pipeline",
|
||||
"route": "/pipeline/1048451e-3b4a-4b66-a8f4-cb865096de2f",
|
||||
"url": "http://127.0.0.1:5173/pipeline/1048451e-3b4a-4b66-a8f4-cb865096de2f",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 29,
|
||||
"works": 27,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 2,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 31,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 56,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.pipeline-back",
|
||||
"label": "返回视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "sp-dot.done",
|
||||
"label": "脚本",
|
||||
"href": "#stage-1",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "sp-dot.active",
|
||||
"label": "基础资产",
|
||||
"href": "#stage-2",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "sp-dot",
|
||||
"label": "故事板",
|
||||
"href": "#stage-3",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 23,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "sp-dot",
|
||||
"label": "视频",
|
||||
"href": "#stage-4",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "sp-dot",
|
||||
"label": "拼接导出",
|
||||
"href": "#stage-5",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 27,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tag-add",
|
||||
"label": "添加人物",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tag-add",
|
||||
"label": "添加场景",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 24,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.btn-sm",
|
||||
"label": "↻ 整体重写",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.btn-sm",
|
||||
"label": "清空对话",
|
||||
"href": "",
|
||||
"disabled": true,
|
||||
"active": false,
|
||||
"verdict": "disabled"
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chat-mode.primary",
|
||||
"label": "AI 全生",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chat-mode",
|
||||
"label": "一句话主题",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 21,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chat-mode",
|
||||
"label": "自带脚本",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 21,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chat-icon-btn",
|
||||
"label": "上传脚本附件",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chat-send-btn",
|
||||
"label": "发送",
|
||||
"href": "",
|
||||
"disabled": true,
|
||||
"active": false,
|
||||
"verdict": "disabled"
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn",
|
||||
"label": "重新生成全部",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-lg",
|
||||
"label": "进入下一步",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"确认脚本,进入下一步"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# 功能审计 · pipeline
|
||||
|
||||
路由:`/pipeline/1048451e-3b4a-4b66-a8f4-cb865096de2f` · 模式:isolated
|
||||
合计 29 · ✅ works 27 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 2
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 确认脚本,进入下一步
|
||||
|
||||
@@ -0,0 +1,705 @@
|
||||
{
|
||||
"name": "platform-cover",
|
||||
"route": "/platform-cover",
|
||||
"url": "http://127.0.0.1:5173/platform-cover",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 38,
|
||||
"works": 35,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 1,
|
||||
"noop": 2,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "back-pill",
|
||||
"label": "返回",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "new-prod",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.active",
|
||||
"label": "南卡南卡 Lite Pro 蓝牙耳机// 数码 3C",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "露露露露同款裸感瑜伽裤// 运动户外",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "透真透真清透物理防晒霜// 美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "滋啦滋啦速食牛肉面 · 6 桶装// 食品饮料",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "透真透真玻尿酸补水面膜// 美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "桥接桥接测试补水面膜 20260529// 美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "三顿三顿半同款冻干咖啡粉// 食品饮料",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "iw-prod-item.",
|
||||
"label": "小熊小熊 4L 可视空气炸锅// 家居家电",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 7,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "search-btn",
|
||||
"label": "搜索",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "抖抖音电商",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "淘淘宝",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "猫天猫",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "京京东",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "拼拼多多",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "红小红书",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "快快手",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 31,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "视视频号",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 32,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "a亚马逊",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 33,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "platform-card.",
|
||||
"label": "阿1688",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 34,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "opt.active",
|
||||
"label": "4 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 35,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "opt.",
|
||||
"label": "8 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 36,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "opt.",
|
||||
"label": "12 张",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 5,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 37,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary",
|
||||
"label": "立即生成 (预估 ¥2.00)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "skipped-destructive"
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"折叠侧栏",
|
||||
"全部商品 7 个",
|
||||
"搜索批次/平台",
|
||||
"时间",
|
||||
"平台"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# 功能审计 · platform-cover
|
||||
|
||||
路由:`/platform-cover` · 模式:isolated
|
||||
合计 38 · ✅ works 35 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)1 · ◷ noop-active 2 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 折叠侧栏
|
||||
- 全部商品 7 个
|
||||
- 搜索批次/平台
|
||||
- 时间
|
||||
- 平台
|
||||
|
||||
## ⏭ 破坏性按钮(未自动点,需人工验)
|
||||
- 立即生成 (预估 ¥2.00) `button`
|
||||
|
||||
@@ -0,0 +1,589 @@
|
||||
{
|
||||
"name": "product-create",
|
||||
"route": "/products/new",
|
||||
"url": "http://127.0.0.1:5173/products/new",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 31,
|
||||
"works": 31,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-edit-toggle",
|
||||
"label": "管理商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-create",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "商品分类",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "创建时间",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "南卡 Lite Pro 蓝牙耳机 · 1200×800南卡 Lite Pro 蓝牙耳机数码 3C",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 31,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "露露同款裸感瑜伽裤 · 1200×800露露同款裸感瑜伽裤运动户外2026-06-08 创建素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "透真清透物理防晒霜 · 1200×800透真清透物理防晒霜美妆个护2026-06-08 创建素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "滋啦速食牛肉面 · 6 桶装 · 1200×800滋啦速食牛肉面 · 6 桶装食品饮料2026-",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "透真玻尿酸补水面膜 · 1200×800透真玻尿酸补水面膜美妆个护2026-05-29 创建素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 31,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "桥接测试补水面膜 20260529 · 1200×800桥接测试补水面膜 20260529美妆个",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "三顿半同款冻干咖啡粉 · 1200×800三顿半同款冻干咖啡粉食品饮料2026-06-08 创建",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "小熊 4L 可视空气炸锅 · 1200×800小熊 4L 可视空气炸锅家居家电2026-06-0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "x",
|
||||
"label": "关闭",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "select",
|
||||
"role": "",
|
||||
"cls": "select",
|
||||
"label": "美妆个护",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "pf-upload-zone",
|
||||
"label": "点击上传或拖拽图片到此处// 支持 JPG、PNG 格式,建议尺寸 800×800 以上,大小不",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn-guide",
|
||||
"label": "使用指南",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 13,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 29,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn",
|
||||
"label": "取消",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 30,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary",
|
||||
"label": "创建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"瑜伽裤 · 1200×800 露露同款裸感瑜伽裤 运动户外 2026-04-30 创建 素材 4",
|
||||
"空气炸锅 · 1200×800 小熊 4L 可视空气炸锅 家居家电 2026-05-03 创建 ",
|
||||
"咖啡冻干粉 · 1200×800 三顿半同款冻干咖啡粉 食品饮料 2026-05-05 创建 素",
|
||||
"防晒霜 · 1200×800 透真清透物理防晒霜 美妆个护 2026-05-08 创建 素材 7",
|
||||
"速食牛肉面 · 1200×800 滋啦速食牛肉面 · 6 桶装 食品饮料 2026-05-10 ",
|
||||
"蓝牙耳机 · 1200×800 南卡 Lite Pro 蓝牙耳机 数码 3C 2026-05-1",
|
||||
"补水面膜 · 1200×800 透真玻尿酸补水面膜 美妆个护 2026-05-15 创建 素材 "
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# 功能审计 · product-create
|
||||
|
||||
路由:`/products/new` · 模式:isolated
|
||||
合计 31 · ✅ works 31 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 瑜伽裤 · 1200×800 露露同款裸感瑜伽裤 运动户外 2026-04-30 创建 素材 4
|
||||
- 空气炸锅 · 1200×800 小熊 4L 可视空气炸锅 家居家电 2026-05-03 创建
|
||||
- 咖啡冻干粉 · 1200×800 三顿半同款冻干咖啡粉 食品饮料 2026-05-05 创建 素
|
||||
- 防晒霜 · 1200×800 透真清透物理防晒霜 美妆个护 2026-05-08 创建 素材 7
|
||||
- 速食牛肉面 · 1200×800 滋啦速食牛肉面 · 6 桶装 食品饮料 2026-05-10
|
||||
- 蓝牙耳机 · 1200×800 南卡 Lite Pro 蓝牙耳机 数码 3C 2026-05-1
|
||||
- 补水面膜 · 1200×800 透真玻尿酸补水面膜 美妆个护 2026-05-15 创建 素材
|
||||
|
||||
@@ -0,0 +1,553 @@
|
||||
{
|
||||
"name": "product-detail",
|
||||
"route": "/products/045ad8d6-8b15-486b-a4a9-f6968eb1555f",
|
||||
"url": "http://127.0.0.1:5173/products/045ad8d6-8b15-486b-a4a9-f6968eb1555f",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 29,
|
||||
"works": 28,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ov-edit.ov-tri-trigger",
|
||||
"label": "AI 生成商品三视图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": true,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "ov-edit.ov-edit-single",
|
||||
"label": "编辑商品信息",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 10,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "thumb.placeholder",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "qa-item",
|
||||
"label": "模特上身图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
},
|
||||
"consoleNote": [
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — ",
|
||||
"Encountered two children with the same key, `%s`. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — "
|
||||
]
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "qa-item",
|
||||
"label": "平台套图",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "qa-item",
|
||||
"label": "图片创作",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "qa-item.primary",
|
||||
"label": "生成视频",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tab.active",
|
||||
"label": "AI 生成素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "视频项目",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 13,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "filter",
|
||||
"label": "全部类型",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 10,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "filter",
|
||||
"label": "最新生成",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 10,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "thumb.placeholder",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "thumb.placeholder",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "thumb.placeholder",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 27,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "thumb.placeholder",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 28,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "thumb.placeholder",
|
||||
"label": "点击放大",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 11,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"通过",
|
||||
"网格视图",
|
||||
"列表视图"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# 功能审计 · product-detail
|
||||
|
||||
路由:`/products/045ad8d6-8b15-486b-a4a9-f6968eb1555f` · 模式:isolated
|
||||
合计 29 · ✅ works 28 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 1 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 通过
|
||||
- 网格视图
|
||||
- 列表视图
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
{
|
||||
"name": "products",
|
||||
"route": "/products",
|
||||
"url": "http://127.0.0.1:5173/products",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 25,
|
||||
"works": 25,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-edit-toggle",
|
||||
"label": "管理商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-create",
|
||||
"label": "新建商品",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "商品分类",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "创建时间",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "南卡 Lite Pro 蓝牙耳机 · 1200×800南卡 Lite Pro 蓝牙耳机数码 3C",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 31,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "露露同款裸感瑜伽裤 · 1200×800露露同款裸感瑜伽裤运动户外2026-06-08 创建素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "透真清透物理防晒霜 · 1200×800透真清透物理防晒霜美妆个护2026-06-08 创建素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "滋啦速食牛肉面 · 6 桶装 · 1200×800滋啦速食牛肉面 · 6 桶装食品饮料2026-",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "透真玻尿酸补水面膜 · 1200×800透真玻尿酸补水面膜美妆个护2026-05-29 创建素材",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 31,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "桥接测试补水面膜 20260529 · 1200×800桥接测试补水面膜 20260529美妆个",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "三顿半同款冻干咖啡粉 · 1200×800三顿半同款冻干咖啡粉食品饮料2026-06-08 创建",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "product-card",
|
||||
"label": "小熊 4L 可视空气炸锅 · 1200×800小熊 4L 可视空气炸锅家居家电2026-06-0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 30,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"瑜伽裤 · 1200×800 露露同款裸感瑜伽裤 运动户外 2026-04-30 创建 素材 4",
|
||||
"空气炸锅 · 1200×800 小熊 4L 可视空气炸锅 家居家电 2026-05-03 创建 ",
|
||||
"咖啡冻干粉 · 1200×800 三顿半同款冻干咖啡粉 食品饮料 2026-05-05 创建 素",
|
||||
"防晒霜 · 1200×800 透真清透物理防晒霜 美妆个护 2026-05-08 创建 素材 7",
|
||||
"速食牛肉面 · 1200×800 滋啦速食牛肉面 · 6 桶装 食品饮料 2026-05-10 ",
|
||||
"蓝牙耳机 · 1200×800 南卡 Lite Pro 蓝牙耳机 数码 3C 2026-05-1",
|
||||
"补水面膜 · 1200×800 透真玻尿酸补水面膜 美妆个护 2026-05-15 创建 素材 "
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
# 功能审计 · products
|
||||
|
||||
路由:`/products` · 模式:isolated
|
||||
合计 25 · ✅ works 25 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 瑜伽裤 · 1200×800 露露同款裸感瑜伽裤 运动户外 2026-04-30 创建 素材 4
|
||||
- 空气炸锅 · 1200×800 小熊 4L 可视空气炸锅 家居家电 2026-05-03 创建
|
||||
- 咖啡冻干粉 · 1200×800 三顿半同款冻干咖啡粉 食品饮料 2026-05-05 创建 素
|
||||
- 防晒霜 · 1200×800 透真清透物理防晒霜 美妆个护 2026-05-08 创建 素材 7
|
||||
- 速食牛肉面 · 1200×800 滋啦速食牛肉面 · 6 桶装 食品饮料 2026-05-10
|
||||
- 蓝牙耳机 · 1200×800 南卡 Lite Pro 蓝牙耳机 数码 3C 2026-05-1
|
||||
- 补水面膜 · 1200×800 透真玻尿酸补水面膜 美妆个护 2026-05-15 创建 素材
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"name": "projects-new",
|
||||
"route": "/projects/new",
|
||||
"url": "http://127.0.0.1:5173/projects/new",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 15,
|
||||
"works": 15,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost",
|
||||
"label": "退出",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 18,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "pp-chip",
|
||||
"label": "全部分类",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"1 选择商品 未选择",
|
||||
"2 项目配置 时长 · 风格 · 人物",
|
||||
"创建新商品 // 在此添加一个新商品",
|
||||
"透真玻尿酸补水面膜 · 1200×800 透真玻尿酸补水面膜 美妆个护 2026-05-15 创",
|
||||
"透真清透物理防晒霜 · 1200×800 透真清透物理防晒霜 美妆个护 2026-05-08 创",
|
||||
"三顿半同款冻干咖啡粉 · 1200×800 三顿半同款冻干咖啡粉 食品饮料 2026-05-05",
|
||||
"南卡 Lite Pro 蓝牙耳机 · 1200×800 南卡 Lite Pro 蓝牙耳机 数码 ",
|
||||
"滋啦速食牛肉面 · 6 桶装 · 1200×800 滋啦速食牛肉面 · 6 桶装 食品饮料 20",
|
||||
"小熊 4L 可视空气炸锅 · 1200×800 小熊 4L 可视空气炸锅 家居家电 2026-0",
|
||||
"露露同款裸感瑜伽裤 · 1200×800 露露同款裸感瑜伽裤 运动户外 2026-04-30 创"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# 功能审计 · projects-new
|
||||
|
||||
路由:`/projects/new` · 模式:isolated
|
||||
合计 15 · ✅ works 15 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 1 选择商品 未选择
|
||||
- 2 项目配置 时长 · 风格 · 人物
|
||||
- 创建新商品 // 在此添加一个新商品
|
||||
- 透真玻尿酸补水面膜 · 1200×800 透真玻尿酸补水面膜 美妆个护 2026-05-15 创
|
||||
- 透真清透物理防晒霜 · 1200×800 透真清透物理防晒霜 美妆个护 2026-05-08 创
|
||||
- 三顿半同款冻干咖啡粉 · 1200×800 三顿半同款冻干咖啡粉 食品饮料 2026-05-05
|
||||
- 南卡 Lite Pro 蓝牙耳机 · 1200×800 南卡 Lite Pro 蓝牙耳机 数码
|
||||
- 滋啦速食牛肉面 · 6 桶装 · 1200×800 滋啦速食牛肉面 · 6 桶装 食品饮料 20
|
||||
- 小熊 4L 可视空气炸锅 · 1200×800 小熊 4L 可视空气炸锅 家居家电 2026-0
|
||||
- 露露同款裸感瑜伽裤 · 1200×800 露露同款裸感瑜伽裤 运动户外 2026-04-30 创
|
||||
|
||||
@@ -0,0 +1,467 @@
|
||||
{
|
||||
"name": "projects",
|
||||
"route": "/projects",
|
||||
"url": "http://127.0.0.1:5173/projects",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 24,
|
||||
"works": 22,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 2,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "收窄导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 21,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 21,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 37,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 21,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 23,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 50,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 26,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-edit-toggle",
|
||||
"label": "管理项目",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary.btn-lg",
|
||||
"label": "新建项目",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab.active",
|
||||
"label": "全部 6",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "进行中 5",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "已完成 1",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 10,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "div",
|
||||
"role": "",
|
||||
"cls": "tab",
|
||||
"label": "失败 0",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 12,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "商品品类",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "脚本来源",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "chip",
|
||||
"label": "创建时间",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "网格",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 13,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "列表",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"9:16 补水面膜 · 痛点种草 · v36 镜 · 0-15s 透真补水面膜 AI 全生 3/",
|
||||
"9:16 速食牛肉面 · 加班治愈4 镜 · 0-12s 滋啦速食 · 6 桶装 一句话主题 2",
|
||||
"删除项目",
|
||||
"9:16 透真防晒 · 通勤对比6 镜 · 0-18s 透真清透防晒霜 AI 全生 4/5 视频",
|
||||
"9:16 咖啡冻干 · 早八剧情5 镜 · 0-15s 三顿半同款冻干 一句话主题 3/5 故事",
|
||||
"9:16 蓝牙耳机 · 开箱测评5 镜 · 0-15s 南卡 Lite Pro 自带脚本 5/5",
|
||||
"9:16 瑜伽裤 · 通勤穿搭5 镜 · 0-15s 露露同款瑜伽裤 AI 全生 5/5 已完成",
|
||||
"故事板生成中",
|
||||
"资产生成中",
|
||||
"视频生成 4/6",
|
||||
"故事板生成失败"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
# 功能审计 · projects
|
||||
|
||||
路由:`/projects` · 模式:isolated
|
||||
合计 24 · ✅ works 22 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 2 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 9:16 补水面膜 · 痛点种草 · v36 镜 · 0-15s 透真补水面膜 AI 全生 3/
|
||||
- 9:16 速食牛肉面 · 加班治愈4 镜 · 0-12s 滋啦速食 · 6 桶装 一句话主题 2
|
||||
- 删除项目
|
||||
- 9:16 透真防晒 · 通勤对比6 镜 · 0-18s 透真清透防晒霜 AI 全生 4/5 视频
|
||||
- 9:16 咖啡冻干 · 早八剧情5 镜 · 0-15s 三顿半同款冻干 一句话主题 3/5 故事
|
||||
- 9:16 蓝牙耳机 · 开箱测评5 镜 · 0-15s 南卡 Lite Pro 自带脚本 5/5
|
||||
- 9:16 瑜伽裤 · 通勤穿搭5 镜 · 0-15s 露露同款瑜伽裤 AI 全生 5/5 已完成
|
||||
- 故事板生成中
|
||||
- 资产生成中
|
||||
- 视频生成 4/6
|
||||
- 故事板生成失败
|
||||
|
||||
@@ -0,0 +1,492 @@
|
||||
{
|
||||
"name": "settings",
|
||||
"route": "/settings",
|
||||
"url": "http://127.0.0.1:5173/settings",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 26,
|
||||
"works": 25,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn",
|
||||
"label": "取消",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 23,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary",
|
||||
"label": "保存所有变更",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 47,
|
||||
"api": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "a",
|
||||
"role": "tab",
|
||||
"cls": "active",
|
||||
"label": "个人信息",
|
||||
"href": "#sec-profile",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "noop-active",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 0,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "a",
|
||||
"role": "tab",
|
||||
"cls": "",
|
||||
"label": "安全3 设备",
|
||||
"href": "#sec-security",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 17,
|
||||
"tag": "a",
|
||||
"role": "tab",
|
||||
"cls": "",
|
||||
"label": "通知4/4",
|
||||
"href": "#sec-notify",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 18,
|
||||
"tag": "a",
|
||||
"role": "tab",
|
||||
"cls": "",
|
||||
"label": "创作默认",
|
||||
"href": "#sec-pref",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 19,
|
||||
"tag": "a",
|
||||
"role": "tab",
|
||||
"cls": "",
|
||||
"label": "显示",
|
||||
"href": "#sec-display",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 6,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 20,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "logout-pill",
|
||||
"label": "退出登录",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 21,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-sm",
|
||||
"label": "上传新头像",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 8,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 22,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.btn-sm",
|
||||
"label": "恢复默认",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 45,
|
||||
"api": 11
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 23,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.btn-sm",
|
||||
"label": "验证",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 23,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.btn-sm",
|
||||
"label": "更换",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 23,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "row-link",
|
||||
"label": "管理团队 →",
|
||||
"href": "#team",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
# 功能审计 · settings
|
||||
|
||||
路由:`/settings` · 模式:isolated
|
||||
合计 26 · ✅ works 25 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 1 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"page": "asset-factory",
|
||||
"blocked": 0,
|
||||
"total": 24,
|
||||
"works": 22,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 2,
|
||||
"missing": 4
|
||||
},
|
||||
{
|
||||
"page": "image-optimize",
|
||||
"blocked": 0,
|
||||
"total": 24,
|
||||
"works": 24,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"missing": 12
|
||||
},
|
||||
{
|
||||
"page": "model-photo",
|
||||
"blocked": 0,
|
||||
"total": 32,
|
||||
"works": 31,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"missing": 7
|
||||
},
|
||||
{
|
||||
"page": "model-photo-demo-a",
|
||||
"blocked": 0,
|
||||
"total": 37,
|
||||
"works": 33,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 1,
|
||||
"noop": 3,
|
||||
"missing": 5
|
||||
},
|
||||
{
|
||||
"page": "model-photo-demo-b",
|
||||
"blocked": 0,
|
||||
"total": 37,
|
||||
"works": 36,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 1,
|
||||
"missing": 5
|
||||
},
|
||||
{
|
||||
"page": "platform-cover",
|
||||
"blocked": 0,
|
||||
"total": 38,
|
||||
"works": 35,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 1,
|
||||
"noop": 2,
|
||||
"missing": 8
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# 功能审计汇总
|
||||
|
||||
生成时间:2026-06-09T07:56:41.981Z · 模式:isolated
|
||||
|
||||
| 页面 | 合计 | ✅works | ❌dead | 🛑error | ⏭skip | 🔍missing | 状态 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| asset-factory | 24 | 22 | **0** | 0 | 0 | 4 | |
|
||||
| image-optimize | 24 | 24 | **0** | 0 | 0 | 12 | |
|
||||
| model-photo | 32 | 31 | **0** | 0 | 0 | 7 | |
|
||||
| model-photo-demo-a | 37 | 33 | **0** | 0 | 1 | 5 | |
|
||||
| model-photo-demo-b | 37 | 36 | **0** | 0 | 0 | 5 | |
|
||||
| platform-cover | 38 | 35 | **0** | 0 | 1 | 8 | |
|
||||
|
||||
- ⛔blocked = 页面始终落登录页/未就绪(后端或远程库不可用),**未审计**,非「0 缺陷」。修好后端再单独 `--only <page>` 复跑。
|
||||
- ❌dead = 点了五路探针(URL/浮层/自身状态/网络/DOM)全无反应,优先修。
|
||||
- 🔍missing = 设计稿 `/exact` 有、React 没渲染出来的控件(启发式,需人工过)。
|
||||
- ⏭skip = 破坏性按钮(删除/充值/生成…)未自动点,需人工验。
|
||||
- 单页明细见 `output/<page>.audit.md`。
|
||||
@@ -0,0 +1,333 @@
|
||||
{
|
||||
"name": "team",
|
||||
"route": "/team",
|
||||
"url": "http://127.0.0.1:5173/team",
|
||||
"mode": "isolated",
|
||||
"tally": {
|
||||
"total": 17,
|
||||
"works": 17,
|
||||
"dead": 0,
|
||||
"error": 0,
|
||||
"disabled": 0,
|
||||
"skipped": 0,
|
||||
"noop": 0,
|
||||
"blocked": 0
|
||||
},
|
||||
"results": [
|
||||
{
|
||||
"idx": 0,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "brand",
|
||||
"label": "Airshelf 工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 1,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "sidebar-toggle",
|
||||
"label": "展开导航",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"tag": "div",
|
||||
"role": "button",
|
||||
"cls": "search-box",
|
||||
"label": "搜索 (Ctrl K)",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 14,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 4,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "商品库",
|
||||
"href": "/products",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 5,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "视频项目",
|
||||
"href": "/projects",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 6,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "图片生成",
|
||||
"href": "/asset-factory",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 20,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 7,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "资产库",
|
||||
"href": "/library",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 36,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 8,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "active",
|
||||
"label": "团队",
|
||||
"href": "/team",
|
||||
"disabled": false,
|
||||
"active": true,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 17,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 9,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "消费",
|
||||
"href": "/account",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 22,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 10,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "设置",
|
||||
"href": "/settings",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": true,
|
||||
"mutations": 49,
|
||||
"api": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 11,
|
||||
"tag": "a",
|
||||
"role": "",
|
||||
"cls": "",
|
||||
"label": "工作台",
|
||||
"href": "/dashboard",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 25,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 12,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "icon-btn",
|
||||
"label": "消息中心",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-primary",
|
||||
"label": "创建账户",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 14,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-sm",
|
||||
"label": "充值",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 15,
|
||||
"tag": "button",
|
||||
"role": "",
|
||||
"cls": "btn.btn-ghost.btn-sm",
|
||||
"label": "设置月限额",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": false,
|
||||
"overlay": true,
|
||||
"self": false,
|
||||
"mutations": 3,
|
||||
"api": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"idx": 16,
|
||||
"tag": "a",
|
||||
"role": "button",
|
||||
"cls": "more",
|
||||
"label": "全部 →",
|
||||
"href": "",
|
||||
"disabled": false,
|
||||
"active": false,
|
||||
"verdict": "works",
|
||||
"signals": {
|
||||
"url": true,
|
||||
"overlay": false,
|
||||
"self": false,
|
||||
"mutations": 19,
|
||||
"api": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"missing": [
|
||||
"搜索",
|
||||
"李 小李的店",
|
||||
"余额 ¥327.40",
|
||||
"账户",
|
||||
"编辑",
|
||||
"重置密码",
|
||||
"移出"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
# 功能审计 · team
|
||||
|
||||
路由:`/team` · 模式:isolated
|
||||
合计 17 · ✅ works 17 · ❌ **dead 0** · 🛑 error 0 · ⏭ skipped(破坏性)0 · ◷ noop-active 0 · ⚪ disabled 0
|
||||
|
||||
## 🔍 设计稿里有、React 没渲染出来的控件(MISSING · 启发式)
|
||||
> 按控件文字与设计稿 `/exact` 对比,可能含装饰/动态文案误报,人工过一眼。
|
||||
|
||||
- 搜索
|
||||
- 李 小李的店
|
||||
- 余额 ¥327.40
|
||||
- 账户
|
||||
- 编辑
|
||||
- 重置密码
|
||||
- 移出
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "airshelf-function-audit",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "逐页功能审计:驱动真实 React 路由,点遍每个按钮/切换/标签,报出「点了没反应」的死交互。",
|
||||
"scripts": {
|
||||
"audit": "node audit.mjs",
|
||||
"audit:quick": "node audit.mjs --mode quick"
|
||||
},
|
||||
"dependencies": {
|
||||
"playwright": "^1.57.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
[
|
||||
{ "name": "dashboard", "route": "/dashboard", "exact": "index.html" },
|
||||
{ "name": "products", "route": "/products", "exact": "products.html" },
|
||||
{ "name": "product-detail", "route": "/products/:productId", "exact": "product-detail.html", "dynamic": "product" },
|
||||
{ "name": "product-create", "route": "/products/new", "exact": "product-create-upload.html" },
|
||||
{ "name": "projects", "route": "/projects", "exact": "projects.html" },
|
||||
{ "name": "projects-new", "route": "/projects/new", "exact": "projects-new.html" },
|
||||
{ "name": "pipeline", "route": "/pipeline/:projectId", "exact": "pipeline.html", "dynamic": "project" },
|
||||
{ "name": "library", "route": "/library", "exact": "library.html" },
|
||||
{ "name": "account", "route": "/account", "exact": "account.html" },
|
||||
{ "name": "team", "route": "/team", "exact": "team.html" },
|
||||
{ "name": "messages", "route": "/messages", "exact": "messages.html" },
|
||||
{ "name": "asset-factory", "route": "/asset-factory", "exact": "asset-factory.html" },
|
||||
{ "name": "image-optimize", "route": "/image-optimize", "exact": "image-optimize.html" },
|
||||
{ "name": "model-photo", "route": "/model-photo", "exact": "model-photo.html" },
|
||||
{ "name": "model-photo-demo-a", "route": "/model-photo/demo-a", "exact": "model-photo-demo-a.html" },
|
||||
{ "name": "model-photo-demo-b", "route": "/model-photo/demo-b", "exact": "model-photo-demo-b.html" },
|
||||
{ "name": "platform-cover", "route": "/platform-cover", "exact": "platform-cover.html" },
|
||||
{ "name": "settings", "route": "/settings", "exact": "settings.html" }
|
||||
]
|
||||
@@ -0,0 +1,108 @@
|
||||
// 弹窗/抽屉内部控件验证(主审计只扫「当前可见」,扫不到默认关闭的弹窗内部)。
|
||||
// 本脚本逐个:导到页面 → 点触发按钮 → 断言弹窗弹出(=触发已接)→ 数内部可交互控件 +
|
||||
// 点「取消/关闭」断言弹窗关闭(=取消已接)→ 断言主操作按钮存在且未禁用(=已接,但不点,避免真删/真扣费/真改密码)。
|
||||
//
|
||||
// 用法:node verify-modals.mjs (需前后端在跑;自动用演示账号登录)
|
||||
|
||||
import { chromium } from "playwright";
|
||||
|
||||
const BASE = (process.argv.includes("--base") ? process.argv[process.argv.indexOf("--base") + 1] : "http://127.0.0.1:5173").replace(/\/+$/, "");
|
||||
const EMAIL = "e2e-20260529-0806@airshelf.test";
|
||||
const PASSWORD = "demo12345";
|
||||
|
||||
// 每个场景:在 route 上点 trigger 文案 → 期望浮层出现 → 点 cancel 文案关闭
|
||||
const SCENARIOS = [
|
||||
{ name: "settings · 修改密码弹窗", route: "/settings", pre: "安全", trigger: "修改", cancel: "取消", primary: /确认|保存|修改/ },
|
||||
{ name: "settings · 上传头像弹窗", route: "/settings", trigger: "上传新头像", cancel: "取消", primary: /确认|上传|保存/ },
|
||||
{ name: "settings · 退出登录确认", route: "/settings", trigger: "退出登录", cancel: "取消", primary: /退出|确认/ },
|
||||
{ name: "team · 创建成员弹窗", route: "/team", trigger: "创建账户", cancel: "取消", primary: /邀请|确认|创建|添加/ },
|
||||
{ name: "team · 团队充值弹窗", route: "/team", trigger: "充值", cancel: "取消", primary: /确认充值|充值/ },
|
||||
{ name: "team · 设置月限额弹窗", route: "/team", trigger: "设置月限额", cancel: "取消", primary: /确认|保存/ },
|
||||
{ name: "library · 上传资产抽屉", route: "/library", trigger: "上传资产", cancel: "取消", primary: /上传|确认/ },
|
||||
{ name: "products · 新建商品抽屉", route: "/products", trigger: "新建商品", cancel: "取消", primary: /创建商品|创建/ }
|
||||
];
|
||||
|
||||
const OVERLAY_SEL = ".modal,.drawer,[role=dialog],.team-modal,.modal-bg.show,.drawer-bg.show,.pc-drawer.show,.logout-confirm";
|
||||
|
||||
async function login() {
|
||||
const res = await fetch(`${BASE}/api/auth/login/`, {
|
||||
method: "POST", headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ username: EMAIL, password: PASSWORD })
|
||||
});
|
||||
if (!res.ok) throw new Error("登录失败:" + res.status);
|
||||
return (await res.json()).token;
|
||||
}
|
||||
|
||||
const HELPERS = `
|
||||
window.__m = {
|
||||
vis(el){ const r=el.getBoundingClientRect(); if(r.width<2||r.height<2) return false; const s=getComputedStyle(el); if(s.display==='none'||s.visibility==='hidden'||+s.opacity===0) return false; if(r.right<=0||r.left>=innerWidth||r.bottom<=0||r.top>=innerHeight) return false; return true; },
|
||||
clickText(txt){ const els=[...document.querySelectorAll('button,[role=button],a,[role=tab],.qa-item,.logout-pill,.nav-item,aside li,aside a,.seg-item,.tab')];
|
||||
const q=txt.replace(/\\s+/g,'');
|
||||
const hit=els.filter(e=>this.vis(e)&&(e.textContent||'').replace(/\\s+/g,'').includes(q)).sort((a,b)=>(a.textContent||'').length-(b.textContent||'').length)[0];
|
||||
if(!hit) return false; hit.click(); return true; },
|
||||
overlayCount(sel){ return [...document.querySelectorAll(sel)].filter(e=>this.vis(e)).length; },
|
||||
// 浮层内部可交互控件数(按钮/输入/可点项),排除最终危险确认
|
||||
innerControls(sel){ const ovs=[...document.querySelectorAll(sel)].filter(e=>this.vis(e)); let n=0; const labels=[];
|
||||
for(const ov of ovs){ for(const el of ov.querySelectorAll('button,[role=button],input,select,textarea,.tab,.mi,.pay-method-btn')){ if(this.vis(el)){ n++; labels.push((el.textContent||el.getAttribute('placeholder')||el.type||'').replace(/\\s+/g,' ').trim().slice(0,16)); } } }
|
||||
return { n, labels: labels.filter(Boolean).slice(0,12) }; },
|
||||
primaryEnabled(sel, re){ const ovs=[...document.querySelectorAll(sel)].filter(e=>this.vis(e));
|
||||
for(const ov of ovs){ for(const b of ov.querySelectorAll('button')){ if(re.test(b.textContent||'')) return !b.disabled; } } return null; }
|
||||
};
|
||||
`;
|
||||
|
||||
async function gotoReady(page, token, route) {
|
||||
await page.goto(`${BASE}/`, { waitUntil: "domcontentloaded" }).catch(() => {});
|
||||
await page.evaluate((t) => localStorage.setItem("airshelf_token", t), token);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await page.goto(`${BASE}${route}`, { waitUntil: "networkidle" }).catch(() => {});
|
||||
const ok = await page.waitForFunction(() => !document.querySelector(".auth-wrap") && document.querySelector("aside.sidebar"), null, { timeout: 9000 }).then(() => true).catch(() => false);
|
||||
if (ok) { await page.waitForTimeout(500); return true; }
|
||||
await page.evaluate((t) => localStorage.setItem("airshelf_token", t), token).catch(() => {});
|
||||
await page.waitForTimeout(700 * (i + 1));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const token = await login();
|
||||
const browser = await chromium.launch({ headless: true });
|
||||
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, colorScheme: "light" });
|
||||
const page = await ctx.newPage();
|
||||
const results = [];
|
||||
|
||||
for (const s of SCENARIOS) {
|
||||
const r = { name: s.name, opened: false, cancelClosed: false, inner: 0, innerLabels: [], primaryWired: null, note: "" };
|
||||
try {
|
||||
if (!(await gotoReady(page, token, s.route))) { r.note = "页面未就绪(后端?)"; results.push(r); continue; }
|
||||
await page.evaluate(HELPERS);
|
||||
if (s.pre) { await page.evaluate((t) => window.__m.clickText(t), s.pre); await page.waitForTimeout(300); }
|
||||
const before = await page.evaluate((sel) => window.__m.overlayCount(sel), OVERLAY_SEL);
|
||||
const clicked = await page.evaluate((t) => window.__m.clickText(t), s.trigger);
|
||||
if (!clicked) { r.note = `没找到触发按钮「${s.trigger}」`; results.push(r); continue; }
|
||||
await page.waitForTimeout(500);
|
||||
const after = await page.evaluate((sel) => window.__m.overlayCount(sel), OVERLAY_SEL);
|
||||
r.opened = after > before;
|
||||
if (r.opened) {
|
||||
const ic = await page.evaluate((sel) => window.__m.innerControls(sel), OVERLAY_SEL);
|
||||
r.inner = ic.n; r.innerLabels = ic.labels;
|
||||
r.primaryWired = await page.evaluate(({ sel, src }) => window.__m.primaryEnabled(sel, new RegExp(src)), { sel: OVERLAY_SEL, src: s.primary.source });
|
||||
// 点取消关闭(安全);取消文案找不到/没关掉则回退 Esc
|
||||
await page.evaluate((t) => window.__m.clickText(t), s.cancel);
|
||||
await page.waitForTimeout(400);
|
||||
let closedN = await page.evaluate((sel) => window.__m.overlayCount(sel), OVERLAY_SEL);
|
||||
if (closedN >= after) { await page.keyboard.press("Escape").catch(() => {}); await page.waitForTimeout(300); closedN = await page.evaluate((sel) => window.__m.overlayCount(sel), OVERLAY_SEL); }
|
||||
r.cancelClosed = closedN < after;
|
||||
}
|
||||
} catch (e) { r.note = String(e).slice(0, 80); }
|
||||
results.push(r);
|
||||
}
|
||||
|
||||
await browser.close();
|
||||
|
||||
console.log("\n弹窗/抽屉内部验证(不点最终危险确认)\n");
|
||||
console.log("| 弹窗 | 触发打开 | 内部控件 | 取消可关 | 主按钮已接 |");
|
||||
console.log("|---|---|---|---|---|");
|
||||
for (const r of results) {
|
||||
console.log(`| ${r.name} | ${r.opened ? "✅" : "❌" + (r.note ? "(" + r.note + ")" : "")} | ${r.opened ? r.inner : "-"} | ${r.opened ? (r.cancelClosed ? "✅" : "❌") : "-"} | ${r.primaryWired === null ? "-" : r.primaryWired ? "✅可用" : "⚪禁用"} |`);
|
||||
}
|
||||
const okN = results.filter((r) => r.opened && r.cancelClosed).length;
|
||||
console.log(`\n${okN}/${results.length} 个弹窗:触发→打开→取消关闭 全通;主操作按钮均存在(未点,避免真删/真扣费/真改密码)。`);
|
||||
@@ -0,0 +1,20 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
const url = process.argv[3];
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
||||
const p = await ctx.newPage();
|
||||
const errs = [];
|
||||
p.on("console", m => { if (m.type()==="error") errs.push(m.text()); });
|
||||
p.on("pageerror", e => errs.push("PAGEERR: "+e.message));
|
||||
await p.goto("http://127.0.0.1:5173/");
|
||||
await p.evaluate((t) => localStorage.setItem("airshelf_token", t), TOK);
|
||||
await p.goto(url, { waitUntil: "networkidle" });
|
||||
await p.waitForTimeout(600);
|
||||
const info = await p.evaluate(() => ({
|
||||
isLogin: !!document.querySelector(".auth-exact-page"),
|
||||
h1: document.querySelector("h1")?.textContent?.slice(0,30),
|
||||
token: localStorage.getItem("airshelf_token")?.length,
|
||||
}));
|
||||
console.log(url, JSON.stringify(info), "ERRORS:", errs.slice(0,5));
|
||||
await b.close();
|
||||
@@ -0,0 +1,21 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
||||
const p = await ctx.newPage();
|
||||
const errs = [];
|
||||
p.on("console", m => { if (m.type()==="error") errs.push(m.text().slice(0,120)); });
|
||||
p.on("pageerror", e => errs.push("PAGEERR: "+e.message.slice(0,150)));
|
||||
await p.goto("http://127.0.0.1:5173/", { waitUntil: "domcontentloaded" });
|
||||
await p.evaluate((t) => localStorage.setItem("airshelf_token", t), TOK);
|
||||
for (const url of ["http://127.0.0.1:5173/model-photo", "http://127.0.0.1:5173/model-photo/demo-a"]) {
|
||||
errs.length = 0;
|
||||
await p.goto(url, { waitUntil: "networkidle" });
|
||||
await p.waitForTimeout(700);
|
||||
const info = await p.evaluate(() => {
|
||||
const txt = document.body.innerText || "";
|
||||
return { isLogin: txt.includes("AUTH/LOGIN") || txt.includes("使用团队邀请邮箱"), firstWords: txt.replace(/\s+/g," ").slice(0,80) };
|
||||
});
|
||||
console.log(url.split("5173")[1], JSON.stringify(info), "ERR:", errs.slice(0,3));
|
||||
}
|
||||
await b.close();
|
||||
@@ -0,0 +1,20 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
|
||||
// check: does loading /exact/model-photo.html mutate the token?
|
||||
const sp = await ctx.newPage();
|
||||
await sp.goto("http://127.0.0.1:5173/", { waitUntil: "domcontentloaded" });
|
||||
await sp.evaluate((t) => localStorage.setItem("airshelf_token", t), TOK);
|
||||
const before = await sp.evaluate(() => localStorage.getItem("airshelf_token")?.length);
|
||||
await sp.goto("http://127.0.0.1:5173/exact/model-photo.html", { waitUntil: "networkidle" });
|
||||
await sp.waitForTimeout(1500);
|
||||
const after = await sp.evaluate(() => localStorage.getItem("airshelf_token")?.length ?? "NULL");
|
||||
console.log("token before source load:", before, "| after /exact/model-photo.html load:", after);
|
||||
// compare with demo-a source
|
||||
await sp.evaluate((t) => localStorage.setItem("airshelf_token", t), TOK);
|
||||
await sp.goto("http://127.0.0.1:5173/exact/model-photo-demo-a.html", { waitUntil: "networkidle" });
|
||||
await sp.waitForTimeout(1500);
|
||||
const afterDemo = await sp.evaluate(() => localStorage.getItem("airshelf_token")?.length ?? "NULL");
|
||||
console.log("after /exact/model-photo-demo-a.html load:", afterDemo);
|
||||
await b.close();
|
||||
@@ -0,0 +1,15 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
async function prepare(page, url, token) {
|
||||
if (token) { await page.goto(new URL(url).origin + "/", { waitUntil: "domcontentloaded" }); await page.evaluate((v)=>localStorage.setItem("airshelf_token",v), token); }
|
||||
await page.goto(url, { waitUntil: "networkidle" });
|
||||
if (token) { await page.evaluate((v)=>localStorage.setItem("airshelf_token",v), token); await page.goto(url, { waitUntil: "networkidle" }); await page.waitForTimeout(900); }
|
||||
}
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport:{width:1440,height:900}, deviceScaleFactor:1, colorScheme:"light", reducedMotion:"reduce" });
|
||||
const sp = await ctx.newPage(); const tp = await ctx.newPage();
|
||||
await prepare(sp, "http://127.0.0.1:5173/exact/model-photo.html", TOK);
|
||||
await prepare(tp, "http://127.0.0.1:5173/model-photo", TOK);
|
||||
const t = await tp.evaluate(()=>{const x=document.body.innerText||"";return {login:x.includes("AUTH/LOGIN"),first:x.replace(/\s+/g," ").slice(0,60),tok:localStorage.getItem("airshelf_token")?.length};});
|
||||
console.log("TARGET after exact-compare-flow:", JSON.stringify(t));
|
||||
await b.close();
|
||||
@@ -0,0 +1,19 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport:{width:1440,height:900} });
|
||||
const p = await ctx.newPage();
|
||||
await p.goto("http://127.0.0.1:5173/", { waitUntil:"domcontentloaded" });
|
||||
await p.evaluate((t)=>localStorage.setItem("airshelf_token",t), TOK);
|
||||
// mirror model-photo
|
||||
await p.goto("http://127.0.0.1:5173/exact/model-photo.html", { waitUntil:"networkidle" });
|
||||
await p.waitForTimeout(1800);
|
||||
const mirror = await p.evaluate(()=>{
|
||||
const items=[...document.querySelectorAll(".mp-ps-item, .ps-item, [class*='ps-item'], .pl-item")].map(e=>e.innerText.replace(/\s+/g,' ').slice(0,30));
|
||||
return { count: items.length, items: items.slice(0,10) };
|
||||
});
|
||||
console.log("MIRROR model-photo product list:", JSON.stringify(mirror));
|
||||
// real API
|
||||
const api = await p.evaluate(async (t)=>{ const r=await fetch("/api/products/",{headers:{Authorization:"Token "+t}}); const d=await r.json(); return (d.results||[]).map(x=>x.title); }, TOK);
|
||||
console.log("REAL /api/products/:", JSON.stringify(api));
|
||||
await b.close();
|
||||
@@ -0,0 +1,18 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 1 });
|
||||
const p = await ctx.newPage();
|
||||
await p.goto("http://127.0.0.1:5173/");
|
||||
await p.evaluate((t) => localStorage.setItem("airshelf_token", t), TOK);
|
||||
await p.goto("http://127.0.0.1:5173/products/new", { waitUntil: "networkidle" });
|
||||
await p.waitForTimeout(800);
|
||||
const r = await p.evaluate(() => {
|
||||
const d = document.querySelector(".pc-drawer");
|
||||
if (!d) return { found: false, body: document.body.className, hasLogin: !!document.querySelector(".auth-exact-page") };
|
||||
const cs = getComputedStyle(d);
|
||||
const rect = d.getBoundingClientRect();
|
||||
return { found: true, width: cs.width, transform: cs.transform, left: rect.left, right: rect.right, rectW: rect.width, cls: d.className };
|
||||
});
|
||||
console.log(JSON.stringify(r, null, 2));
|
||||
await b.close();
|
||||
@@ -0,0 +1,17 @@
|
||||
import { chromium } from "playwright";
|
||||
const TOK = process.argv[2];
|
||||
const b = await chromium.launch();
|
||||
const ctx = await b.newContext({ viewport:{width:1440,height:900}, deviceScaleFactor:1 });
|
||||
async function ys(url){
|
||||
const p = await ctx.newPage();
|
||||
await p.goto("http://127.0.0.1:5173/",{waitUntil:"domcontentloaded"});
|
||||
await p.evaluate((t)=>localStorage.setItem("airshelf_token",t),TOK);
|
||||
await p.goto(url,{waitUntil:"networkidle"}); await p.waitForTimeout(1000);
|
||||
return await p.evaluate(()=>{
|
||||
const g=(sel)=>{const e=document.querySelector(sel);return e?Math.round(e.getBoundingClientRect().top):null;};
|
||||
return { h1:g("h1"), heroTop:g(".factory-hero,.fx-hero,[class*='hero']"), card:g(".factory-card,[class*='factory-card']"), cta:g(".factory-cta .btn,[class*='factory'] .btn-primary"), section:g(".section-h"), tabs:g(".tabs"), toolbar:g(".toolbar") };
|
||||
});
|
||||
}
|
||||
console.log("MIRROR:", JSON.stringify(await ys("http://127.0.0.1:5173/exact/asset-factory.html")));
|
||||
console.log("IMPL :", JSON.stringify(await ys("http://127.0.0.1:5173/asset-factory")));
|
||||
await b.close();
|
||||
Reference in New Issue
Block a user