Files
bid-doctor/docs/design/ui-demo/page-workbench.html
YANG JIANKUAN e1a9017cd1 docs(design): 新增 UI demo 页面,供 UI 精修评审
- docs/design/ui-demo/:控件总览、表单、卡片、列表与表格,以及工作台、读标两个组合页
- 只用设计规范的变量和组件;新增组件样式放在 demo.css,清单见 index
- index 列出 UI 精修待定问题 Q1–Q12
- design/README 与 AGENTS.md 进度同步

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 12:46:27 +08:00

134 lines
10 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>工作台 · 标博士 UI demo</title>
<link rel="icon" href="../logo/favicon.svg">
<link rel="stylesheet" href="../system/tokens.css">
<link rel="stylesheet" href="../system/fonts-local.css">
<link rel="stylesheet" href="../system/components.css">
<link rel="stylesheet" href="demo.css">
<style>
/* 本页布局:主列 + 右侧 296px 信息栏 */
.wb{display:grid;grid-template-columns:minmax(0,1fr) 296px;gap:var(--sp-6);align-items:start;margin-top:var(--sp-6)}
.wb .rail > * + *{margin-top:var(--sp-4)}
.wb .rail .card{padding:var(--sp-4) var(--sp-5)}
.wb .rail .card-foot{margin:var(--sp-3) calc(-1 * var(--sp-5)) calc(-1 * var(--sp-4));padding:var(--sp-2) var(--sp-5)}
.log{list-style:none;margin:0;padding:0}
.log li{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:var(--sp-2);padding:6px 0;border-top:1px solid var(--border-subtle);font-size:var(--fs-caption);line-height:var(--lh-caption)}
.log li:first-child{border-top:0}
.log li > span:last-child{color:var(--text-secondary);font-family:var(--font-figures);font-variant-numeric:tabular-nums;white-space:nowrap}
.log .who{font-weight:var(--fw-bold)}
.log .ok{color:var(--confirmed);white-space:nowrap}
.wb table.data td{vertical-align:middle}
.todo-row{position:relative;display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:var(--sp-3);align-items:baseline;padding:var(--sp-3) var(--sp-4) var(--sp-3) var(--sp-5);border-top:1px solid var(--border-subtle)}
.todo-row:first-child{border-top:0}
.todo-row::before{content:"";position:absolute;left:0;top:var(--sp-3);bottom:var(--sp-3);width:3px;background:var(--sev-fatal)}
.todo-row b{display:block;font-weight:var(--fw-bold)}
.todo-row .cite-src{white-space:nowrap}
.wb .proj-sub .fig{font-weight:var(--fw-medium)}
</style>
</head>
<body>
<main>
<div class="content">
<div class="page-title">
<div><h1>工作台</h1><p>11月3日 周二 · 按投标截止时间排序,截止临近的排在前面。</p></div>
<div class="actions"><span class="cost">扣 1 次解析 · 剩 <span class="fig">37</span> 次</span><button class="btn primary" data-new><i data-ic="plus"></i>新建项目</button></div>
</div>
<div class="alert warn"><span class="ico w">!</span><div><p><b>某县数据中心机房改造项目今天 17:00 截止。</b>清单还是草稿,还没有做过检查。</p></div><span class="act"><a class="btn sm" href="page-reading.html">去确认清单</a></span></div>
<div class="stats" style="margin-top:var(--sp-5)">
<div class="stat"><small>进行中的项目</small><span class="big">4</span><p>已递交 1 · 已归档 1</p></div>
<div class="stat"><small>7 天内截止</small><span class="big">2</span><p class="due-today">最近:今天 17:00</p></div>
<div class="stat"><small>待处理的致命问题</small><span class="big">3</span><p>在 1 个项目里</p></div>
<div class="stat"><small>待确认的清单条目</small><span class="big">4</span><p>在 2 个项目里</p></div>
</div>
<div class="wb">
<div>
<div class="toolbar">
<div class="seg" role="group" aria-label="按状态筛选" data-seg><button aria-pressed="true" data-v="active">进行中 <span class="fig">4</span></button><button aria-pressed="false" data-v="all">全部 <span class="fig">6</span></button><button aria-pressed="false" data-v="已递交">已递交</button><button aria-pressed="false" data-v="已归档">已归档</button></div>
<div class="right"><label class="search" style="width:240px"><i data-ic="search"></i><input class="input" placeholder="搜索项目、采购人、编号" aria-label="搜索项目" data-q></label></div>
</div>
<table class="data hover">
<thead><tr><th>项目</th><th>投标截止</th><th>状态</th><th>就绪</th><th class="r">致命</th></tr></thead>
<tbody data-rows></tbody>
</table>
<p class="note">「就绪」只表示致命问题都已处理,不代表投标文件没有问题。</p>
<div class="section-h"><h2>待处理的致命问题</h2><span class="sev fatal">致命<span class="fig">3</span></span><span class="more"><a class="plain cap" href="#">去查标页处理</a></span></div>
<div class="results">
<div class="todo-row"><span class="sev fatal">致命</span><div><b>报价超过采购包 1 的最高限价</b><span class="cap muted">智慧大厅建设项目 · 开标一览表 287.60 万元,限价 286.00 万元</span></div><a class="cite-src" href="#">报价册 · 第 <span class="fig">1</span> 页</a></div>
<div class="todo-row"><span class="sev fatal">致命</span><div><b>★ 条款疑似不满足:应用服务器内存</b><span class="cap muted">智慧大厅建设项目 · 响应 256G,要求 ≥ 512G · 上次标记为已修改,问题仍在</span></div><a class="cite-src" href="#">技术册 · 第 <span class="fig">12</span> 页</a></div>
<div class="todo-row"><span class="sev fatal">致命</span><div><b>授权委托书的单位签章位置未发现盖章</b><span class="cap muted">智慧大厅建设项目 · 只看有无,不鉴定真伪</span></div><a class="cite-src" href="#">商务册 · 第 <span class="fig">5</span> 页</a></div>
</div>
</div>
<div class="rail">
<div class="card">
<div class="card-h"><h3>正在进行的任务</h3></div>
<div class="d-row" style="gap:var(--sp-2);margin-bottom:var(--sp-1)"><b>解析补遗 2</b><span class="cap muted" style="margin-left:auto">提取清单</span></div>
<div class="cap muted" style="margin-bottom:var(--sp-2)">某市医保信息系统等保测评服务</div>
<div class="progress"><div class="bar"><i style="width:62%"></i></div><span class="fig">62%</span></div>
<div style="display:flex;gap:var(--sp-2);align-items:flex-start;margin-top:var(--sp-3)"><i data-ic="clock" class="muted" style="margin-top:2px"></i><span class="cap muted">检查排队中 · 智慧社区平台运维 · 前面还有 1 个任务</span></div>
<p class="note">可以离开本页,完成后会发站内通知。</p>
</div>
<div class="card quota">
<div class="card-h"><h3>本期额度</h3><span class="more cap muted">至 2027-10-31</span></div>
<div class="q2">
<div><small>解析剩余</small><span class="big">37</span><span class="unit">/ 50</span><div class="bar"><i style="width:26%"></i></div></div>
<div><small>检查剩余</small><span class="big">12</span><span class="unit">/ 20</span><div class="bar"><i style="width:40%"></i></div></div>
</div>
<div class="card-foot"><a class="plain cap" href="#">扣点规则</a><span class="r"><a class="plain cap" href="#">查看流水</a></span></div>
</div>
<div class="card">
<div class="card-h"><h3>最近处理</h3><span class="more"><a class="plain cap" href="#">全部记录</a></span></div>
<ul class="log">
<li><span><span class="who">王敏</span> <span class="ok">✓ 已修改</span>「授权委托书签章」</span><span>14:26</span></li>
<li><span><span class="who">王敏</span> 确认了清单 v2 · 智慧大厅</span><span>11-02</span></li>
<li><span><span class="who">系统</span> 完成第 2 次检查 · 致命 3</span><span>11-02</span></li>
<li><span><span class="who">系统</span> 并入补遗 1 · 更新 2 条</span><span>11-02</span></li>
<li><span><span class="who">李工</span> 忽略「其他项目名称」:业绩介绍</span><span>11-01</span></li>
</ul>
</div>
</div>
</div>
</div>
</main>
<script src="demo.js"></script>
<script>
const { $, $$, icon, toast } = Demo;
Demo.shell({ nav: "workbench", crumbs: [["工作台", ""]] });
const P = [
{ name: "某县数据中心机房改造项目", buyer: "某县大数据管理局", lot: "标段 1", h: 6, due: "今天 17:00 截止", cls: "due-today", st: "编制中", ready: "", fatal: 0, href: "page-reading.html" },
{ name: "某区智慧社区平台运维服务", buyer: "某区民政局", lot: "全部", h: 53, due: "剩 2 天 5 小时", cls: "due-soon", st: "已检查", ready: "就绪", fatal: 0 },
{ name: "某市政务服务中心智慧大厅建设项目", buyer: "某市政务服务管理办公室", lot: "采购包 1", h: 408, due: "11月20日 09:30 · 剩 17 天", cls: "", st: "已检查", ready: "未就绪", fatal: 3, href: "page-reading.html" },
{ name: "某市医保信息系统等保测评服务", buyer: "某市医疗保障局", lot: "全部", h: 600, due: "11月28日 10:00 · 剩 25 天", cls: "", st: "跟进中", ready: "", fatal: 0 },
{ name: "某区智慧校园一期", buyer: "某区教育局", lot: "全部", h: -1, due: "已截止", cls: "due-past", st: "已递交", ready: "", fatal: 0 },
{ name: "某市不动产登记信息平台升级", buyer: "某市自然资源和规划局", lot: "采购包 2", h: -2, due: "已截止", cls: "due-past", st: "已归档", ready: "", fatal: 0 }
];
let seg = "active", q = "";
function render() {
const rows = P.filter((p) => (seg === "all" || (seg === "active" ? !["已递交", "已归档"].includes(p.st) : p.st === seg)) && (!q || (p.name + p.buyer).includes(q)));
$("[data-rows]").innerHTML = rows.map((p) => `<tr data-href="${p.href || ""}">
<td><div class="proj-name">${p.name}</div><div class="proj-sub">${p.buyer} · ${p.lot}</div></td>
<td class="nw ${p.cls}">${p.due}</td><td><span class="tag status">${p.st}</span></td>
<td class="nw">${p.ready === "就绪" ? '<span class="tag status" data-tip="只表示致命问题都已处理,不代表投标文件没有问题。">就绪</span>' : p.ready || '<span class="muted">—</span>'}</td>
<td class="r">${p.fatal ? `<span class="sev fatal">致命<span class="fig">${p.fatal}</span></span>` : '<span class="muted">—</span>'}</td></tr>`).join("")
|| `<tr><td colspan="5" class="empty-cell"><div class="empty sm"><b>没有符合条件的项目</b><p>换个关键词,或切到「全部」看看。</p></div></td></tr>`;
}
$("[data-seg]").addEventListener("change", (e) => { seg = e.detail; render(); });
$("[data-q]").addEventListener("input", (e) => { q = e.target.value.trim(); render(); });
$("[data-rows]").addEventListener("click", (e) => { const r = e.target.closest("tr[data-href]"); if (!r) return; if (r.dataset.href) location.href = r.dataset.href; else toast("(演示)只做了「读标」组合页"); });
$("[data-new]").onclick = () => location.href = "forms.html#s-new";
render();
</script>
</body>
</html>