Browse Source

chore: 清理移动端验证用的临时脚本

Co-Authored-By: Claude Code <noreply@anthropic.com>
Huccct 1 day ago
parent
commit
918281184a

+ 0 - 36
prototypes/fmode-mvp-20261014/_all.mjs

@@ -1,36 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
-const p = await ctx.newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear();
-await p.waitForTimeout(600);
-await p.fill('input[type="tel"]', '13800138000');
-await p.fill('input[type="text"][maxlength="6"]', '123456');
-await p.click('button[type="submit"]');
-await p.waitForTimeout(3000);
-
-const pages = [
-  ['workbench','/desktop/workbench'], ['chat','/desktop/chat'], ['contacts','/desktop/contacts'],
-  ['projects','/desktop/projects'], ['events','/desktop/events'], ['tasks','/desktop/tasks'],
-  ['deliverables','/desktop/deliverables'], ['agent','/desktop/agent/zhixia'], ['mine','/desktop/mine'],
-];
-for (const [name, path] of pages) {
-  await p.goto('http://localhost:4200' + path, { waitUntil: 'networkidle' });
-  await clear();
-  await p.waitForTimeout(1800);
-  await p.screenshot({ path: `../../.shots/dk-${name}.png` });
-  const r = await p.evaluate(() => ({
-    overflow: document.documentElement.scrollWidth > document.documentElement.clientWidth,
-    demo: /演示数据|未连接真实服务/.test(document.body.innerText),
-    h1: document.querySelector('h1')?.textContent?.trim()?.slice(0,10),
-  }));
-  console.log(`  ${name.padEnd(13)} h1=${(r.h1||'-').padEnd(10)} 溢出=${r.overflow?'⚠️是':'否'} demo文案=${r.demo?'⚠️有':'无'}`);
-}
-console.log(errs.length ? '\n⚠ 错误: '+errs.slice(0,3).join(' | ') : '\n✅ 全部页面无控制台错误');
-await b.close();

+ 0 - 47
prototypes/fmode-mvp-20261014/_chat.mjs

@@ -1,47 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
-const p = await ctx.newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,150)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,150)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear();
-await p.waitForTimeout(600);
-await p.fill('input[type="tel"]', '13800138000');
-await p.fill('input[type="text"][maxlength="6"]', '123456');
-await p.click('button[type="submit"]');
-await p.waitForTimeout(3000);
-await p.goto('http://localhost:4200/desktop/chat', { waitUntil: 'networkidle' });
-await clear();
-await p.waitForTimeout(2500);
-
-const r = await p.evaluate(() => {
-  const lay = document.querySelector('.conversation-layout');
-  return {
-    url: location.pathname,
-    cols: lay ? getComputedStyle(lay).gridTemplateColumns : null,
-    colsCount: lay ? getComputedStyle(lay).gridTemplateColumns.split(' ').length : 0,
-    uiInput: document.querySelectorAll('ui-input').length,
-    msgBubbles: document.querySelectorAll('app-message-bubble').length,
-    composer: !!document.querySelector('app-composer'),
-    overflowX: document.documentElement.scrollWidth > document.documentElement.clientWidth,
-  };
-});
-console.log('=== 1440 ==='); console.log(JSON.stringify(r, null, 2));
-await p.screenshot({ path: '../../.shots/final-chat-1440.png' });
-
-// 窄窗 1100 验证右栏让位
-await p.setViewportSize({ width: 1100, height: 900 });
-await p.waitForTimeout(1500);
-const n = await p.evaluate(() => {
-  const lay = document.querySelector('.conversation-layout');
-  return { cols: getComputedStyle(lay).gridTemplateColumns, railVisible: !!document.querySelector('.rail-col') && getComputedStyle(document.querySelector('.rail-col')).display !== 'none' };
-});
-console.log('=== 1100(右栏应让位)==='); console.log(JSON.stringify(n));
-await p.screenshot({ path: '../../.shots/final-chat-1100.png' });
-
-console.log(errs.length ? '⚠ 错误: '+errs.slice(0,2).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 30
prototypes/fmode-mvp-20261014/_contacts.mjs

@@ -1,30 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(600);
-await p.fill('input[type="tel"]', '13800138000');
-await p.fill('input[type="text"][maxlength="6"]', '123456');
-await p.click('button[type="submit"]');
-await p.waitForTimeout(3000);
-await p.goto('http://localhost:4200/desktop/contacts', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(2000);
-
-// 检查「全部」Tab 下方是否有异常空元素
-const probe = await p.evaluate(() => {
-  const out = [];
-  document.querySelectorAll('section, h2.section-title, .grid, ul.rows').forEach(el => {
-    const r = el.getBoundingClientRect();
-    out.push({
-      tag: el.tagName + (el.className ? '.' + String(el.className).split(' ')[0] : ''),
-      h: Math.round(r.height),
-      text: (el.textContent || '').trim().slice(0, 20),
-    });
-  });
-  return out;
-});
-console.log('=== 「全部」Tab 下的区块 ===');
-probe.forEach(x => console.log(`  ${x.tag.padEnd(24)} h=${String(x.h).padStart(4)}  "${x.text}"`));
-await p.screenshot({ path: '../../.shots/dk-contacts-all.png' });
-await b.close();

+ 0 - 34
prototypes/fmode-mvp-20261014/_dbg.mjs

@@ -1,34 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1100, height: 900 } })).newPage();
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.fill('input[type="tel"]', '13800138000');
-await p.fill('input[type="text"][maxlength="6"]', '123456');
-await p.click('button[type="submit"]');
-await p.waitForTimeout(2500);
-await p.goto('http://localhost:4200/desktop/chat', { waitUntil: 'networkidle' });
-await p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.waitForTimeout(2000);
-
-const info = await p.evaluate(() => {
-  const lay = document.querySelector('.conversation-layout');
-  const rail = document.querySelector('.rail-col');
-  const cs = lay ? getComputedStyle(lay) : null;
-  // 找出给 .conversation-layout 设过规则的样式表
-  let found = [];
-  for (const sheet of document.styleSheets) {
-    let rules; try { rules = sheet.cssRules; } catch { continue; }
-    for (const r of rules) {
-      if (r.selectorText && r.selectorText.includes('conversation-layout')) found.push(r.selectorText + ' → ' + r.style.gridTemplateColumns);
-      if (r.cssRules) {
-        for (const r2 of r.cssRules) {
-          if (r2.selectorText && r2.selectorText.includes('conversation-layout')) found.push('[in ' + r.conditionText + '] ' + r2.selectorText + ' → ' + r2.style.gridTemplateColumns);
-        }
-      }
-    }
-  }
-  return { innerWidth: window.innerWidth, cols: cs?.gridTemplateColumns, railDisplay: rail ? getComputedStyle(rail).display : 'none-el', matchedRules: found };
-});
-console.log(JSON.stringify(info, null, 2));
-await b.close();

+ 0 - 29
prototypes/fmode-mvp-20261014/_dbg2.mjs

@@ -1,29 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1280, height: 1000 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(700);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(2800);
-await p.goto('http://localhost:4200/desktop/contacts', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const info = await p.evaluate(() => {
-  const out = [];
-  // 找所有高度异常(>60px)且内容为空的元素
-  document.querySelectorAll('.page *').forEach(el => {
-    const r = el.getBoundingClientRect();
-    const txt = (el.textContent||'').trim();
-    if (r.height > 50 && txt.length === 0) {
-      out.push({ tag: el.tagName, cls: String(el.className).slice(0,60),
-                 h: Math.round(r.height), w: Math.round(r.width), y: Math.round(r.y) });
-    }
-  });
-  return out.slice(0, 12);
-});
-console.log('高度>50px 且无文字的元素:');
-info.forEach(x => console.log(`  ${x.tag.padEnd(10)} .${x.cls.padEnd(42)} ${x.w}x${x.h} @y=${x.y}`));
-await p.screenshot({ path: '../../.shots/dbg-contacts.png' });
-await b.close();

+ 0 - 37
prototypes/fmode-mvp-20261014/_dbg3.mjs

@@ -1,37 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1280, height: 1000 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(700);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(2800);
-await p.goto('http://localhost:4200/desktop/contacts', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-
-// 直接看 tabs-row / search-row 及其子元素的盒子
-const r = await p.evaluate(() => {
-  const pick = (sel) => {
-    const el = document.querySelector(sel);
-    if (!el) return `${sel}: 不存在`;
-    const b = el.getBoundingClientRect();
-    return `${sel}: ${Math.round(b.width)}x${Math.round(b.height)} @y=${Math.round(b.y)}`;
-  };
-  const tabs = document.querySelector('ui-tabs');
-  const tabsBox = tabs ? tabs.getBoundingClientRect() : null;
-  // ui-tabs 内部结构
-  const inner = tabs ? [...tabs.querySelectorAll('*')].map(e => {
-    const b = e.getBoundingClientRect();
-    return `${e.tagName}.${String(e.className).slice(0,40)} ${Math.round(b.width)}x${Math.round(b.height)}`;
-  }).slice(0,6) : [];
-  return {
-    tabsRow: pick('.tabs-row'),
-    searchRow: pick('.search-row'),
-    searchBox: pick('.search-box'),
-    tabsInternal: inner,
-  };
-});
-console.log(JSON.stringify(r, null, 2));
-await b.close();

+ 0 - 34
prototypes/fmode-mvp-20261014/_f3.mjs

@@ -1,34 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(800);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact: false }).first().click();
-await p.waitForTimeout(3000);
-await p.goto('http://localhost:4200/desktop/chat/zhixia', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(2000);
-
-const r = await p.evaluate(() => ({
-  railItems: document.querySelectorAll('.rail-item').length,
-  previewBtns: document.querySelectorAll('.rail-actions ui-button').length,
-  dlBtns: document.querySelectorAll('.dl-btn').length,
-  convActiveShadow: getComputedStyle(document.querySelector('.conv-row.active')).boxShadow,
-}));
-console.log(JSON.stringify(r, null, 2));
-await p.screenshot({ path: '../../.shots/f3-chat.png' });
-// 点预览验证弹窗
-if (r.previewBtns > 0) {
-  await p.locator('.rail-actions ui-button button').first().click();
-  await p.waitForTimeout(1200);
-  const modal = await p.locator('ui-modal').first().isVisible().catch(()=>false);
-  console.log('预览弹窗可见:', modal);
-  await p.screenshot({ path: '../../.shots/f3-preview.png' });
-}
-console.log(errs.length ? '⚠ '+errs.slice(0,2).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 30
prototypes/fmode-mvp-20261014/_final.mjs

@@ -1,30 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
-const p = await ctx.newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-await p.goto('http://localhost:4200/', { waitUntil: 'domcontentloaded' });
-await p.evaluate(() => { document.querySelectorAll('vite-error-overlay').forEach(e => e.remove()); });
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await p.evaluate(() => { document.querySelectorAll('vite-error-overlay').forEach(e => e.remove()); });
-await p.waitForTimeout(700);
-await p.fill('input[type="tel"]', '13800138000');
-await p.fill('input[type="text"][maxlength="6"]', '123456');
-await p.click('button[type="submit"]');
-await p.waitForTimeout(3000);
-await p.goto('http://localhost:4200/desktop/workbench', { waitUntil: 'networkidle' });
-await p.waitForTimeout(2500);
-const r = await p.evaluate(() => ({
-  demoStrip: !!document.querySelector('.demo-strip'),
-  demoText: /演示数据|未连接真实服务/.test(document.body.innerText),
-  uiCards: document.querySelectorAll('ui-card').length,
-  uiStats: document.querySelectorAll('ui-statistic').length,
-  uiProgress: document.querySelectorAll('ui-progress').length,
-  overflowX: document.documentElement.scrollWidth > document.documentElement.clientWidth,
-}));
-console.log(JSON.stringify(r, null, 2));
-await p.screenshot({ path: '../../.shots/final-workbench-1440.png' });
-console.log(errs.length ? '⚠ 错误: '+errs.slice(0,2).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 48
prototypes/fmode-mvp-20261014/_final2.mjs

@@ -1,48 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(800);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact: false }).first().click();
-await p.waitForTimeout(3000);
-
-// ① 会话切换验证(核心 bug)
-await p.goto('http://localhost:4200/desktop/chat/zhixia', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const before = await p.locator('.chat-title strong').textContent().catch(()=>'?');
-await p.locator('.conv-row').nth(1).click();
-await p.waitForTimeout(2000);
-const after = await p.locator('.chat-title strong').textContent().catch(()=>'?');
-console.log(`① 会话切换: ${before} → ${after}  ${before!==after ? '✅ 可切换' : '❌ 仍不能切换'}`);
-await p.screenshot({ path: '../../.shots/f2-chat.png' });
-
-// ② 通讯录白框
-await p.goto('http://localhost:4200/desktop/contacts', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const boxW = await p.locator('.search-box').first().evaluate(el => Math.round(el.getBoundingClientRect().width)).catch(()=>0);
-console.log(`② 通讯录搜索框宽度: ${boxW}px ${boxW < 400 ? '✅ 已限宽' : '❌ 仍撑满'}`);
-await p.screenshot({ path: '../../.shots/f2-contacts.png' });
-
-// ③ 导航选中态(无竖条) + 折叠
-await p.goto('http://localhost:4200/desktop/workbench', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1500);
-const shadow = await p.locator('.nav-link.active').first().evaluate(el => getComputedStyle(el).boxShadow).catch(()=>'none');
-console.log(`③ 导航选中态 box-shadow: ${shadow} ${shadow==='none' ? '✅ 无竖条' : '❌ 仍有'}`);
-await p.locator('.collapse-btn').click();
-await p.waitForTimeout(1200);
-const navW = await p.locator('.sidebar').evaluate(el => Math.round(el.getBoundingClientRect().width));
-console.log(`④ 折叠后侧栏宽: ${navW}px ${navW < 100 ? '✅ 已折叠' : '❌ 未折叠'}`);
-await p.screenshot({ path: '../../.shots/f2-nav-collapsed.png' });
-
-// ⑤ 我的页 PC 布局
-await p.goto('http://localhost:4200/desktop/mine', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-await p.screenshot({ path: '../../.shots/f2-mine.png', fullPage: true });
-console.log(errs.length ? '⚠ 错误: '+errs.slice(0,2).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 23
prototypes/fmode-mvp-20261014/_mine.mjs

@@ -1,23 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(800);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact: false }).first().click();
-await p.waitForTimeout(3000);
-await p.goto('http://localhost:4200/desktop/mine', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(2200);
-await p.screenshot({ path: '../../.shots/v3-mine.png', fullPage: true });
-const r = await p.evaluate(() => {
-  const lay = document.querySelector('.settings-layout');
-  return {
-    cols: lay ? getComputedStyle(lay).gridTemplateColumns : null,
-    pageW: document.querySelector('.page')?.getBoundingClientRect().width,
-    cards: document.querySelectorAll('ui-card').length,
-  };
-});
-console.log(JSON.stringify(r, null, 2));
-await b.close();

+ 0 - 43
prototypes/fmode-mvp-20261014/_mob.mjs

@@ -1,43 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const ctx = await b.newContext({ viewport: { width: 390, height: 844 }, isMobile: false });
-const p = await ctx.newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-
-// 移动端登录
-await p.goto('http://localhost:4200/mobile/home', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1500);
-console.log('① /mobile/home 未登录跳转:', p.url());
-const ins = await p.locator('ui-m-field input, ui-input input').all();
-if (ins.length >= 2) { await ins[0].fill('13800138000'); await ins[1].fill('123456'); }
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(3500);
-console.log('② 登录后:', p.url());
-await clear(); await p.waitForTimeout(1500);
-await p.screenshot({ path: '../../.shots/mb-home.png' });
-
-// 底部 Tab
-const tab = await p.evaluate(() => ({
-  tabbar: !!document.querySelector('ui-m-tabbar'),
-  items: document.querySelectorAll('ui-m-tabbar .ui-m-tab').length,
-  overflow: document.documentElement.scrollWidth > document.documentElement.clientWidth,
-}));
-console.log('③ 底部 TabBar:', JSON.stringify(tab));
-
-// 遍历各页
-const pages = [['messages','/mobile/messages'],['contacts','/mobile/contacts'],['workbench','/mobile/workbench'],['mine','/mobile/mine'],['deliverables','/mobile/deliverables'],['events','/mobile/events'],['projects','/mobile/projects'],['tasks','/mobile/tasks']];
-for (const [name, path] of pages) {
-  await p.goto('http://localhost:4200'+path, { waitUntil:'networkidle' });
-  await clear(); await p.waitForTimeout(1400);
-  const r = await p.evaluate(() => ({
-    overflow: document.documentElement.scrollWidth > document.documentElement.clientWidth,
-    dk: [...document.querySelectorAll('*')].some(e => /^UI-(BUTTON|AVATAR|MODAL|SELECT|CARD|INPUT|TAG|EMPTY|SKELETON)$/.test(e.tagName)),
-  }));
-  console.log(`   ${name.padEnd(13)} 溢出=${r.overflow?'⚠️是':'否'}  桌面件=${r.dk?'⚠️有':'无'}`);
-  await p.screenshot({ path: `../../.shots/mb-${name}.png` });
-}
-console.log(errs.length ? '⚠ '+errs.slice(0,3).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 20
prototypes/fmode-mvp-20261014/_probe.mjs

@@ -1,20 +0,0 @@
-import { chromium } from 'playwright';
-const browser = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 } });
-const p = await ctx.newPage();
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await p.fill('input[type="tel"]', '13800138000');
-await p.fill('input[type="text"][maxlength="6"]', '123456');
-await p.click('button[type="submit"]');
-await p.waitForTimeout(3000);
-console.log('登录后 URL:', p.url());
-await p.goto('http://localhost:4200/desktop/workbench', { waitUntil: 'networkidle' });
-await p.waitForTimeout(2500);
-console.log('工作台 URL:', p.url());
-const hasNew = await p.locator('text=个任务已阻塞').count();
-const hasUiStat = await p.locator('ui-statistic').count();
-const hasOldCard = await p.locator('.agent-card').count();
-console.log(`新代码标记「个任务已阻塞」: ${hasNew}  |  ui-statistic 元素: ${hasUiStat}  |  旧 .agent-card: ${hasOldCard}`);
-const h1 = await p.locator('h1').first().textContent().catch(()=>null);
-console.log('页面 h1:', h1);
-await browser.close();

+ 0 - 41
prototypes/fmode-mvp-20261014/_shot.mjs

@@ -1,41 +0,0 @@
-import { chromium } from 'playwright';
-const OUT = process.env.SHOT_OUT || 'test-results';
-const browser = await chromium.launch({ executablePath: process.env.DEMO_CHROME || 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-
-async function grab(name, w, h, path, pre) {
-  const ctx = await browser.newContext({ viewport: { width: w, height: h } });
-  const p = await ctx.newPage();
-  const errs = [];
-  p.on('console', m => { if (m.type() === 'error') errs.push(m.text().slice(0, 160)); });
-  p.on('pageerror', e => errs.push('PAGEERROR: ' + e.message.slice(0, 160)));
-  await p.goto('http://localhost:4200' + path, { waitUntil: 'networkidle' });
-  await p.waitForTimeout(1200);
-  if (pre) await pre(p);
-  await p.waitForTimeout(1000);
-  await p.screenshot({ path: `${OUT}/${name}.png` });
-  const dim = await p.evaluate(() => ({ sw: document.documentElement.scrollWidth, cw: document.documentElement.clientWidth }));
-  console.log(`[${name}] ${w}x${h} url=${new URL(p.url()).pathname} scrollW=${dim.sw} clientW=${dim.cw}${dim.sw > dim.cw ? '  ⚠ 横向溢出' : ''}`);
-  if (errs.length) console.log(`   ⚠ 控制台错误 ${errs.length}: ${errs.slice(0,2).join(' || ')}`);
-  await ctx.close();
-}
-
-// 登录流程(演示模式填手机号+验证码)
-async function login(p) {
-  await p.fill('input[type="tel"]', '13800138000');
-  await p.fill('input[type="text"][maxlength="6"]', '123456');
-  await p.click('button[type="submit"]');
-  await p.waitForTimeout(2500);
-}
-
-const A = process.argv[2] || 'login';
-if (A === 'login') {
-  await grab('login', 1440, 900, '/login');
-  await grab('login-m', 390, 844, '/login');
-} else if (A === 'desktop') {
-  await grab('dk-workbench', 1440, 900, '/desktop/workbench', login);
-  await grab('dk-workbench-wide', 1920, 1080, '/desktop/workbench', login);
-  await grab('dk-workbench-narrow', 1100, 900, '/desktop/workbench', login);
-} else if (A === 'mobile') {
-  await grab('mb-home', 390, 844, '/mobile/home', login);
-}
-await browser.close();

+ 0 - 21
prototypes/fmode-mvp-20261014/_t.mjs

@@ -1,21 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(600);
-await p.fill('input[type="tel"]','13800138000'); await p.fill('input[type="text"][maxlength="6"]','123456');
-await p.click('button[type="submit"]'); await p.waitForTimeout(2500);
-await p.goto('http://localhost:4200/desktop/contacts', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const r = await p.evaluate(() => {
-  const tb = document.querySelector('.toolbar');
-  const kids = [...tb.children].map(el => ({
-    tag: el.tagName, cls: String(el.className).slice(0,40),
-    rect: (() => { const x = el.getBoundingClientRect(); return {x:Math.round(x.x),y:Math.round(x.y),w:Math.round(x.width),h:Math.round(x.height)}; })(),
-    inner: el.innerHTML.slice(0,150),
-  }));
-  return kids;
-});
-console.log(JSON.stringify(r, null, 2));
-await b.close();

+ 0 - 25
prototypes/fmode-mvp-20261014/_tab.mjs

@@ -1,25 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 390, height: 844 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(900);
-const ins = await p.locator('ui-input input, ui-m-field input').all();
-if (ins.length>=2) { await ins[0].fill('13800138000'); await ins[1].fill('123456'); }
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(3000);
-await p.goto('http://localhost:4200/mobile/home', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const r = await p.evaluate(() => {
-  const tb = document.querySelector('ui-m-tabbar');
-  if (!tb) return { err: 'no tabbar' };
-  const btns = tb.querySelectorAll('button');
-  return {
-    buttonCount: btns.length,
-    labels: [...btns].map(b => b.textContent.trim().slice(0,8)),
-    onIdx: [...btns].findIndex(b => b.classList.contains('on')),
-    classes: btns[0] ? btns[0].className.slice(0,60) : null,
-  };
-});
-console.log(JSON.stringify(r, null, 2));
-await b.close();

+ 0 - 22
prototypes/fmode-mvp-20261014/_tab2.mjs

@@ -1,22 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 390, height: 844 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(900);
-const ins = await p.locator('ui-input input, ui-m-field input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(3000);
-
-for (const [name, path] of [['首页','/mobile/home'],['会话','/mobile/messages'],['工作台','/mobile/workbench']]) {
-  await p.goto('http://localhost:4200'+path, { waitUntil:'networkidle' });
-  await clear(); await p.waitForTimeout(1500);
-  const r = await p.evaluate(() => {
-    const btns = [...document.querySelectorAll('ui-m-tabbar button')];
-    const active = btns.findIndex(b => b.className.includes('text-primary'));
-    return { labels: btns.map(b=>b.textContent.trim().replace(/\d+/g,'').trim()), activeIdx: active };
-  });
-  console.log(`${name.padEnd(6)} 激活Tab=${r.activeIdx >= 0 ? r.labels[r.activeIdx] : '无'}  (期望: ${name})`);
-}
-await b.close();

+ 0 - 53
prototypes/fmode-mvp-20261014/_v2.mjs

@@ -1,53 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const ctx = await b.newContext({ viewport: { width: 1440, height: 900 } });
-const p = await ctx.newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-
-// 登录页(新版落地页)
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(1500);
-await p.screenshot({ path: '../../.shots/v2-login.png' });
-const loginProbe = await p.evaluate(() => ({
-  landing: !!document.querySelector('.landing'),
-  landingHidden: !!document.querySelector('.landing') && getComputedStyle(document.querySelector('.landing')).display === 'none',
-  cards: document.querySelectorAll('.lp-card').length,
-  inputs: document.querySelectorAll('ui-input').length,
-}));
-console.log('=== 登录页 ==='); console.log(JSON.stringify(loginProbe));
-
-await p.fill('ui-input input >> nth=0', '13800138000');
-await p.fill('ui-input input >> nth=1', '123456');
-await p.click('button[type="submit"], ui-button button');
-await p.waitForTimeout(3000);
-console.log('登录后:', p.url());
-
-// 「我的」页:配色缩略图 + 使用端是否移除
-await p.goto('http://localhost:4200/desktop/mine', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(2000);
-await p.screenshot({ path: '../../.shots/v2-mine.png' });
-const mineProbe = await p.evaluate(() => {
-  const thumbs = [...document.querySelectorAll('.thumb')].map(t => {
-    const nav = t.querySelector('.thumb-nav');
-    const main = t.querySelector('.thumb-main');
-    return {
-      palette: t.getAttribute('data-preview-palette'),
-      navBg: nav ? getComputedStyle(nav).backgroundColor : null,
-      mainBg: main ? getComputedStyle(main).backgroundColor : null,
-    };
-  });
-  return {
-    thumbs,
-    hasUsageSection: /使用端/.test(document.body.innerText),
-    hasAutoDetect: /恢复自动识别/.test(document.body.innerText),
-  };
-});
-console.log('\n=== 我的页 ===');
-console.log('配色缩略图(每格应是不同色):');
-mineProbe.thumbs.forEach(t => console.log(`  ${(t.palette||'').padEnd(10)} nav=${t.navBg}  main=${t.mainBg}`));
-console.log(`「使用端」区块存在: ${mineProbe.hasUsageSection}  「恢复自动识别」存在: ${mineProbe.hasAutoDetect}`);
-console.log(errs.length ? '\n⚠ '+errs.slice(0,2).join(' | ') : '\n✅ 无控制台错误');
-await b.close();

+ 0 - 44
prototypes/fmode-mvp-20261014/_v3.mjs

@@ -1,44 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(1500);
-
-// ui-input 内部是原生 input,直接按位置填
-const inputs = await p.locator('ui-input input').all();
-console.log('找到 ui-input 内原生 input 数量:', inputs.length);
-if (inputs.length >= 2) {
-  await inputs[0].fill('13800138000');
-  await inputs[1].fill('123456');
-}
-// 提交按钮:找「登 录」文本
-await p.getByText('登 录', { exact: false }).first().click();
-await p.waitForTimeout(3500);
-console.log('登录后 URL:', p.url());
-await clear();
-
-await p.goto('http://localhost:4200/desktop/mine', { waitUntil: 'networkidle' });
-await clear(); await p.waitForTimeout(2500);
-await p.screenshot({ path: '../../.shots/v2-mine.png' });
-const probe = await p.evaluate(() => {
-  const thumbs = [...document.querySelectorAll('.thumb')].map(t => {
-    const nav = t.querySelector('.thumb-nav'), main = t.querySelector('.thumb-main');
-    return {
-      palette: t.getAttribute('data-preview-palette'),
-      navBg: nav ? getComputedStyle(nav).backgroundColor : '-',
-      mainBg: main ? getComputedStyle(main).backgroundColor : '-',
-    };
-  });
-  return {
-    thumbCount: thumbs.length,
-    thumbs,
-    hasUsageSection: /使用端/.test(document.body.innerText),
-  };
-});
-console.log('\n=== 我的页 ===');
-console.log('缩略图数量:', probe.thumbCount);
-probe.thumbs.forEach(t => console.log(`  ${(t.palette||'').padEnd(10)} nav=${t.navBg} main=${t.mainBg}`));
-console.log('「使用端」区块仍存在:', probe.hasUsageSection);
-await p.screenshot({ path: '../../.shots/v2-mine-final.png' });
-await b.close();

+ 0 - 59
prototypes/fmode-mvp-20261014/_v4.mjs

@@ -1,59 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(800);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(3000);
-
-// ① 通讯录白框
-await p.goto('http://localhost:4200/desktop/contacts', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const c = await p.evaluate(() => {
-  const tabs = document.querySelector('ui-tabs');
-  return { hasUiTabs: !!tabs, hasSegmented: !!document.querySelector('ui-segmented'),
-           toolbarH: Math.round(document.querySelector('.toolbar')?.getBoundingClientRect().height ?? 0) };
-});
-console.log('① 通讯录:', JSON.stringify(c));
-await p.screenshot({ path: '../../.shots/v4-contacts.png' });
-
-// ② 导航「需要关注」是否删除
-const nav = await p.evaluate(() => document.body.innerText.includes('需要关注'));
-console.log(`② 导航「需要关注」区块: ${nav ? '❌ 仍在' : '✅ 已删除'}`);
-
-// ③ 消息顺序 + 右栏切换
-await p.goto('http://localhost:4200/desktop/chat/zhixia', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(2000);
-const m = await p.evaluate(() => {
-  const msgs = document.querySelector('.messages');
-  return { align: getComputedStyle(msgs).alignContent, railOpen: !!document.querySelector('.rail-col') };
-});
-console.log(`③ 消息排列: align-content=${m.align} ${m.align==='start'?'✅ 自上而下':'❌ 仍贴底'}`);
-await p.screenshot({ path: '../../.shots/v4-chat-results.png' });
-
-// 点「任务」按钮 → 右栏切到任务
-await p.locator('.chat-actions ui-button').first().locator('button').click();
-await p.waitForTimeout(1200);
-const t = await p.evaluate(() => ({
-  railHeader: document.querySelector('.rail-col h2')?.textContent?.trim(),
-  taskItems: document.querySelectorAll('.rail-item.task').length,
-}));
-console.log(`④ 点任务按钮后: 右栏标题="${t.railHeader}" 任务项=${t.taskItems} ${t.railHeader==='任务'?'✅ 已切换':'❌'}`);
-await p.screenshot({ path: '../../.shots/v4-chat-tasks.png' });
-
-// ⑤ 列表页固定头部
-await p.goto('http://localhost:4200/desktop/tasks', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const f = await p.evaluate(() => {
-  const page = document.querySelector('.page');
-  return { splitMode: page?.classList.contains('split-mode'), fixed: !!document.querySelector('.fixed-zone'), scroll: !!document.querySelector('.scroll-zone') };
-});
-console.log(`⑤ 任务看板固定头部: ${JSON.stringify(f)}`);
-console.log(errs.length ? '⚠ '+errs.slice(0,2).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 51
prototypes/fmode-mvp-20261014/_v6.mjs

@@ -1,51 +0,0 @@
-import { chromium } from 'playwright';
-const b = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-const p = await (await b.newContext({ viewport: { width: 1440, height: 900 } })).newPage();
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-const clear = () => p.evaluate(() => document.querySelectorAll('vite-error-overlay').forEach(e=>e.remove()));
-await p.goto('http://localhost:4200/login', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(800);
-const ins = await p.locator('ui-input input').all();
-await ins[0].fill('13800138000'); await ins[1].fill('123456');
-await p.getByText('登 录', { exact:false }).first().click();
-await p.waitForTimeout(3000);
-
-await p.goto('http://localhost:4200/desktop/chat/zhixia', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(2000);
-
-// ① 右栏显示时 vs 隐藏时的列数
-const withRail = await p.evaluate(() => getComputedStyle(document.querySelector('.conversation-layout')).gridTemplateColumns);
-await p.locator('.rail-col .col-head ui-button button').click();  // 关右栏
-await p.waitForTimeout(1000);
-const withoutRail = await p.evaluate(() => ({
-  cols: getComputedStyle(document.querySelector('.conversation-layout')).gridTemplateColumns,
-  railExists: !!document.querySelector('.rail-col'),
-  chatW: Math.round(document.querySelector('.main-col').getBoundingClientRect().width),
-}));
-console.log('① 右栏显示时列数:', withRail);
-console.log('   隐藏后:', JSON.stringify(withoutRail));
-console.log(`   ${withoutRail.cols.split(' ').length === 2 ? '✅ 聊天区已填满' : '❌ 仍留空'}`);
-await p.screenshot({ path: '../../.shots/v6-chat-norail.png' });
-
-// ② 会话列表滚动
-await p.goto('http://localhost:4200/desktop/chat/zhixia', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const scr = await p.evaluate(() => {
-  const el = document.querySelector('.list-scroll');
-  return { overflow: getComputedStyle(el).overflowY, h: Math.round(el.getBoundingClientRect().height) };
-});
-console.log('② 会话列表:', JSON.stringify(scr), scr.overflow === 'auto' ? '✅ 可内滚' : '❌');
-
-// ③ 列表页滚动区
-await p.goto('http://localhost:4200/desktop/events', { waitUntil:'networkidle' });
-await clear(); await p.waitForTimeout(1800);
-const zone = await p.evaluate(() => {
-  const z = document.querySelector('.scroll-zone');
-  const f = document.querySelector('.fixed-zone');
-  return { zoneAnim: getComputedStyle(z).animationName, fixedH: Math.round(f.getBoundingClientRect().height) };
-});
-console.log('③ 列表页滚动区动画:', JSON.stringify(zone));
-console.log(errs.length ? '⚠ '+errs.slice(0,2).join(' | ') : '✅ 无控制台错误');
-await b.close();

+ 0 - 61
prototypes/fmode-mvp-20261014/_verify.mjs

@@ -1,61 +0,0 @@
-import { chromium } from 'playwright';
-const browser = await chromium.launch({ executablePath: 'C:/Program Files/Google/Chrome/Application/chrome.exe' });
-
-async function login(p) {
-  await p.goto('http://localhost:4200/login', { waitUntil: 'networkidle' });
-  await p.waitForTimeout(600);
-  await p.fill('input[type="tel"]', '13800138000');
-  await p.fill('input[type="text"][maxlength="6"]', '123456');
-  await p.click('button[type="submit"]');
-  await p.waitForTimeout(3000);
-}
-
-// 全新 context = 无缓存,Cache-Control: no-store 双保险
-const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, bypassCSP: true });
-const p = await ctx.newPage();
-await p.route('**/*', r => r.continue());
-const errs = [];
-p.on('pageerror', e => errs.push(e.message.slice(0,120)));
-p.on('console', m => { if (m.type()==='error') errs.push(m.text().slice(0,120)); });
-
-await login(p);
-await p.goto('http://localhost:4200/desktop/workbench', { waitUntil: 'networkidle' });
-await p.waitForTimeout(2500);
-
-const probe = await p.evaluate(() => ({
-  url: location.pathname,
-  h1: document.querySelector('h1')?.textContent?.trim(),
-  stats: document.querySelectorAll('ui-statistic').length,
-  cards: document.querySelectorAll('ui-card').length,
-  oldCards: document.querySelectorAll('.agent-card').length,
-  oldMetric: document.querySelectorAll('.bar').length,
-  demoWord: document.body.innerText.includes('演示数据'),
-  overflowX: document.documentElement.scrollWidth > document.documentElement.clientWidth,
-  scrollW: document.documentElement.scrollWidth,
-  clientW: document.documentElement.clientWidth,
-}));
-console.log('=== 工作台(1440×900, 无缓存) ===');
-console.log(JSON.stringify(probe, null, 2));
-if (errs.length) console.log('⚠ 控制台错误:', errs.slice(0,3));
-else console.log('✅ 无控制台错误');
-
-await p.screenshot({ path: '../../.shots/dk-workbench-NEW.png' });
-
-// 宽屏 1920 验证流动布局
-await p.setViewportSize({ width: 1920, height: 1080 });
-await p.waitForTimeout(1200);
-const wide = await p.evaluate(() => ({
-  cols: getComputedStyle(document.querySelector('.grid')).gridTemplateColumns,
-  scrollW: document.documentElement.scrollWidth,
-  clientW: document.documentElement.clientWidth,
-}));
-console.log('\n=== 1920×1080 流动布局 ===');
-console.log('卡片网格列:', wide.cols);
-await p.screenshot({ path: '../../.shots/dk-workbench-1920.png' });
-
-// 窄窗 1100 验证降级
-await p.setViewportSize({ width: 1100, height: 900 });
-await p.waitForTimeout(1200);
-await p.screenshot({ path: '../../.shots/dk-workbench-1100.png' });
-console.log('\n✅ 截图已出:dk-workbench-NEW / -1920 / -1100');
-await browser.close();