Files
vame 41fc6e86dd feat(frontend): 对齐万华门户风格并更新全量截图文档
- 新增门户导航子页面(交易信息、政策法规、操作指南、常见问题、采购平台)并统一门户壳层样式
- 按万华站点风格重构首页与登录页(导航、轮播、公告、登录区)
- 优化小滨助手:首页/登录页接入、可拖拽吸边、圆形图标、圆形外框与切换动画优化
- 重新生成全量页面截图并更新《滨化智慧招标平台-前端界面截图汇总.docx》

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-13 15:35:20 +08:00

146 lines
5.4 KiB
JavaScript

import { chromium } from "playwright";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const OUT = path.resolve(__dirname, "../../shots");
const BASE = process.env.BASE_URL || "http://localhost:5174";
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
fs.rmSync(OUT, { recursive: true, force: true });
fs.mkdirSync(OUT, { recursive: true });
const manifest = [];
let idx = 0;
async function expand(page) {
await page.evaluate(() => {
document.querySelectorAll(".h-screen").forEach((el) => {
el.style.height = "auto";
el.style.minHeight = "100vh";
el.style.overflow = "visible";
});
document.querySelectorAll(".overflow-hidden").forEach((el) => (el.style.overflow = "visible"));
document.querySelectorAll("main").forEach((el) => {
el.style.overflow = "visible";
el.style.height = "auto";
});
});
}
async function shot(page, section, title, { full = true, wait = 500, expandLayout = true } = {}) {
idx += 1;
const file = `${String(idx).padStart(2, "0")}.png`;
if (expandLayout) await expand(page).catch(() => {});
await sleep(wait);
await page.screenshot({ path: path.join(OUT, file), fullPage: full });
manifest.push({ file, section, title });
console.log(`[${idx}] ${section} / ${title} -> ${file}`);
}
async function goto(page, url) {
await page.goto(BASE + url, { waitUntil: "networkidle" }).catch(async () => {
await page.goto(BASE + url, { waitUntil: "domcontentloaded" });
});
await sleep(450);
}
async function clickIf(page, locator, wait = 300) {
const n = await locator.count();
if (n > 0) {
await locator.first().click().catch(() => {});
await sleep(wait);
}
}
async function switchRole(page, name) {
await page.locator("header button:has(svg.lucide-refresh-cw)").first().click();
await sleep(250);
await page.getByRole("menuitem", { name }).first().click();
await sleep(700);
}
async function run() {
const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width: 1440, height: 900 }, deviceScaleFactor: 1.3 });
page.setDefaultTimeout(15000);
const A = "一、门户与登录";
await goto(page, "/portal");
await shot(page, A, "首页(门户)", { wait: 700 });
await clickIf(page, page.getByRole("link", { name: "交易信息" }));
await shot(page, A, "门户导航 · 交易信息页");
await goto(page, "/portal/policies");
await shot(page, A, "门户导航 · 政策法规页");
await goto(page, "/portal/guides");
await shot(page, A, "门户导航 · 操作指南页");
await goto(page, "/portal/faq");
await shot(page, A, "门户导航 · 常见问题页");
await goto(page, "/portal/procurement-platform");
await shot(page, A, "门户导航 · 采购平台页");
await goto(page, "/");
await shot(page, A, "登录页(含可拖拽小滨)", { full: false, expandLayout: false });
const B = "二、角色工作台";
await goto(page, "/app");
await shot(page, B, "招标专员工作台", { wait: 800 });
for (const rn of ["采购需求人员", "评标专家", "评标委员会工作领导小组", "供应商", "系统管理员", "合规 / 审计"]) {
await switchRole(page, rn);
await shot(page, B, `${rn}工作台`, { wait: 700 });
}
await switchRole(page, "招标专员");
const C = "三、核心业务页面";
for (const [url, title] of [
["/app/delegation", "发起招标委托"],
["/app/projects", "项目管理列表"],
["/app/projects/P2026001", "项目详情"],
["/app/projects/P2026001/shortlist", "供应商长短名单"],
["/app/projects/P2026001/sourcing", "AI智慧寻源"],
["/app/projects/P2026001/opening", "开标大厅"],
["/app/projects/P2026001/evaluation", "在线评标室"],
["/app/deposits", "保证金管理"],
["/app/suppliers", "供应商管理"],
["/app/experts", "专家管理"],
["/app/reports", "报表中心"],
["/app/exceptions", "异常决策"],
["/app/expert-tasks", "评标任务"],
["/app/bidding", "投标中心"],
["/app/audit-logs", "审计日志"],
["/app/collusion", "围串标分析"],
["/app/evidence", "存证验证"],
["/app/admin/users", "用户与权限管理"],
["/app/admin/keys", "密钥管理"],
["/app/settings", "系统设置"],
]) {
await goto(page, url);
await shot(page, C, title, { wait: 600 });
}
const D = "四、弹窗与抽屉";
await goto(page, "/app/suppliers");
await clickIf(page, page.locator("tbody tr"), 700);
await shot(page, D, "供应商详情抽屉", { full: false, expandLayout: false });
await goto(page, "/app/expert-tasks");
await clickIf(page, page.getByRole("button", { name: /确认邀请/ }), 500);
await clickIf(page, page.getByRole("button", { name: /签署评标承诺书/ }), 700);
await shot(page, D, "评标纪律承诺书弹窗", { full: false, expandLayout: false });
await goto(page, "/app/admin/keys");
await clickIf(page, page.getByRole("button", { name: /手动触发密钥漂移/ }), 700);
await shot(page, D, "密钥漂移二次授权弹窗", { full: false, expandLayout: false });
fs.writeFileSync(path.join(OUT, "manifest.json"), JSON.stringify(manifest, null, 2));
await browser.close();
console.log(`完成:共 ${manifest.length} 张截图`);
}
run().catch((e) => {
console.error(e);
fs.writeFileSync(path.join(OUT, "manifest.json"), JSON.stringify(manifest, null, 2));
process.exit(1);
});