- BFF 薄适配层(FastAPI,8090):QA 代理/SSE 中继/Neo4j 直连/抽取代理/会话持久化 - Vue3 前端:五相位检索流水线、文献来源与证据链、知识图谱、提取任务四 tab - 四档响应式(桌面/笔记本/平板/手机)、深浅主题 - 81 个 FR 全部实现,测试追溯矩阵 81/81,后端 121 测/前端 156 测 - 真实凭据已脱敏,运行时配置在 backend/.env(不入 git) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
68 lines
2.8 KiB
JavaScript
68 lines
2.8 KiB
JavaScript
// deploy/m2_probe6.js —— 卡片枚举探针(PM 使用,在远端运行)
|
||
// 枚举文档中全部 .pipeline-card:props 状态 / textContent / 可见性 / 所属容器 / 挂载状态
|
||
const { chromium } = require('playwright');
|
||
|
||
(async () => {
|
||
const browser = await chromium.launch();
|
||
const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
|
||
const page = await ctx.newPage();
|
||
await page.goto('http://127.0.0.1:5180', { waitUntil: 'domcontentloaded' });
|
||
await page.waitForSelector('.app-shell', { timeout: 15000 });
|
||
await page.click('.new-task-btn');
|
||
await page.waitForSelector('.composer textarea', { timeout: 15000 });
|
||
await page.fill('.composer textarea', 'SPL gene family in rice');
|
||
await page.click('.send-btn');
|
||
|
||
// 等流结束
|
||
await page.waitForFunction(() => {
|
||
const rootEl = document.querySelector('#app');
|
||
let n = rootEl; let app = null;
|
||
while (n && !app) { if (n.__vue_app__) app = n.__vue_app__; n = n.__vueParentComponent?.parent || null; }
|
||
if (!app) return false;
|
||
const chat = app.config.globalProperties.$pinia._s.get('chat');
|
||
return chat && !chat.busy && chat.completedOnce;
|
||
}, null, { timeout: 180000 });
|
||
await new Promise((r) => setTimeout(r, 3000)); // 揭示动画收尾
|
||
|
||
const report = await page.evaluate(() => {
|
||
const cards = Array.from(document.querySelectorAll('.pipeline-card'));
|
||
return cards.map((el, i) => {
|
||
let vnode = el.__vueParentComponent;
|
||
let props = null, compName = null;
|
||
for (let d = 0; d < 6 && vnode; d++) {
|
||
if (vnode.props && vnode.props.block) {
|
||
props = { status: vnode.props.block.status, steps: vnode.props.block.steps.map((s) => `${s.phase}:${s.state}`).join(',') };
|
||
compName = vnode.type?.name || vnode.type?.__name || 'anon';
|
||
break;
|
||
}
|
||
vnode = vnode.parent;
|
||
}
|
||
const msgEl = el.closest('.msg');
|
||
const chatScroll = el.closest('.chat-scroll');
|
||
const style = getComputedStyle(el);
|
||
const inDrawer = !!el.closest('.drawer');
|
||
const inOverlay = !!el.closest('.bench-overlay');
|
||
// 每个元素与文档根的连接性 + 是否在视口
|
||
const rect = el.getBoundingClientRect();
|
||
return {
|
||
i,
|
||
props,
|
||
compName,
|
||
text: el.textContent.slice(0, 70),
|
||
display: style.display,
|
||
visibility: style.visibility,
|
||
opacity: style.opacity,
|
||
rect: { x: Math.round(rect.x), y: Math.round(rect.y), w: Math.round(rect.width), h: Math.round(rect.height) },
|
||
inMsg: !!msgEl,
|
||
msgText: msgEl ? msgEl.textContent.slice(0, 30) : null,
|
||
inChatScroll: !!chatScroll,
|
||
inDrawer,
|
||
inOverlay,
|
||
isConnected: el.isConnected,
|
||
};
|
||
});
|
||
});
|
||
console.log(JSON.stringify(report, null, 2));
|
||
await browser.close();
|
||
})();
|