Files
Agent-System-Documents/docs/proposals/ui-redesign-demos/demo-c-project-portal.html
T
weichen e601b253bc Add UI redesign and auth design proposal with HTML demos
Why: current UI scatters creation entries (project + at sidebar top-left,
new session at bottom-left), has no user/tenant surfaces, and the project
tree forces per-project navigation; the system targets multi-user
multi-tenant operation.

Evidence:
- Studied zai-org/ZCode desktop layout (WorkspaceShellLayout, WorkspaceSidebar,
  DESIGN.md) and mapped transferable patterns (single New-Task entry,
  organize-by views, sidebar account footer) with repo file citations.
- Three layout proposals (task-centric / activity rail / project portal) with
  comparison table and recommendation A; auth stage-2 design (orgs,
  memberships, server sessions) with SSE cookie upgrade removing ?key=.
- Five static demos (index + A/B/C + auth) verified headless: DOM layout
  assertions (column widths, view switching, screen switching), clipping and
  contrast QA clean, zero console errors, light/dark themes render.

Impact: documents only; no code change. Demos double as the R4 design-token
target palette. Implementation proceeds only after direction is approved.

Refs: docs/proposals/2026-09-30-ui-inbox-command-workspace.md (D25-D33),
docs/proposals/2026-09-30-dual-tier-storage-and-multitenancy.md (D17-D24)
2026-09-30 09:59:40 +00:00

244 lines
20 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" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>方案 C · 项目门户 — Agent-System 设计稿</title>
<style>
:root{--font:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei","Noto Sans CJK SC",sans-serif;--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--r-xl:12px;--r-lg:10px;--r-md:8px;--r-sm:6px;--ease:.13s ease}
[data-theme="dark"]{--bg:#121316;--bg-panel:#191a1e;--bg-surface:#1f2026;--bg-hover:#26272f;--bg-selected:#2c2d36;--bg-input:#1c1d22;--border:#282a31;--border-strong:#373943;--border-faint:#202127;--text:#e8e9ec;--text-subtle:#a4a6ae;--text-faint:#71747e;--accent:#5b8def;--accent-dim:rgba(91,141,239,.13);--accent-soft:rgba(91,141,239,.22);--green:#41b26e;--green-dim:rgba(65,178,110,.13);--green-border:rgba(65,178,110,.32);--amber:#d99b3f;--amber-dim:rgba(217,155,63,.13);--shadow-pop:0 12px 32px rgba(0,0,0,.45);--shadow-card:0 1px 2px rgba(0,0,0,.25)}
[data-theme="light"]{--bg:#f6f7f8;--bg-panel:#fff;--bg-surface:#fff;--bg-hover:#f0f1f4;--bg-selected:#e8eaf0;--bg-input:#fff;--border:#e5e6ea;--border-strong:#d4d6dd;--border-faint:#ececf0;--text:#1d1e23;--text-subtle:#5c5f68;--text-faint:#989ba4;--accent:#3a76e0;--accent-dim:rgba(58,118,224,.09);--accent-soft:rgba(58,118,224,.16);--green:#269a59;--green-dim:rgba(38,154,89,.09);--green-border:rgba(38,154,89,.35);--amber:#a8731d;--amber-dim:rgba(168,115,29,.1);--shadow-pop:0 12px 32px rgba(20,22,28,.14);--shadow-card:0 1px 2px rgba(20,22,28,.05)}
*{margin:0;padding:0;box-sizing:border-box}
html,body{height:100%}
body{font-family:var(--font);font-size:14px;color:var(--text);background:var(--bg);overflow:hidden}
button{font-family:inherit;font-size:inherit;color:inherit;background:none;border:none;cursor:pointer}
button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
::-webkit-scrollbar{width:10px}::-webkit-scrollbar-thumb{background:var(--bg-selected);border-radius:6px;border:3px solid transparent;background-clip:content-box}
svg.ic{width:16px;height:16px;flex:none;stroke:currentColor;fill:none;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
svg.ic-s{width:14px;height:14px}
.app{display:flex;height:100vh}
/* ── 左栏:项目列表 ── */
.side{width:264px;flex:none;background:var(--bg-panel);border-right:1px solid var(--border-faint);display:flex;flex-direction:column}
.brand{display:flex;align-items:center;gap:8px;padding:14px 14px 10px}
.brand-mark{width:22px;height:22px;border-radius:6px;background:linear-gradient(135deg,var(--accent),#8f6ce8);display:flex;align-items:center;justify-content:center;color:#fff;flex:none}
.brand-name{font-weight:600;font-size:13.5px}
.newproj{display:flex;align-items:center;gap:8px;height:34px;margin:2px 12px 8px;padding:0 10px;border-radius:var(--r-md);border:1px dashed var(--border-strong);color:var(--text-subtle);font-size:13px}
.newproj:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-dim)}
.side-scroll{flex:1;overflow-y:auto;padding:0 8px;min-height:0}
.sec{font-size:11.5px;color:var(--text-faint);padding:10px 8px 4px;letter-spacing:.3px}
.proj{display:flex;align-items:center;gap:9px;height:34px;padding:0 8px;margin:1px 0;border-radius:var(--r-sm);color:var(--text-subtle);cursor:pointer}
.proj:hover{background:var(--bg-hover)}
.proj.on{background:var(--bg-selected);color:var(--text)}
.proj .oi{width:22px;height:22px;border-radius:6px;color:#fff;font-size:11px;font-weight:700;display:flex;align-items:center;justify-content:center;flex:none}
.proj .n{flex:1;font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.proj .c{font-size:11px;color:var(--text-faint)}
.side-foot{border-top:1px solid var(--border-faint);padding:10px 12px;display:flex;align-items:center;gap:8px}
.avatar{width:26px;height:26px;border-radius:50%;background:linear-gradient(135deg,#5b8def,#8f6ce8);color:#fff;font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center;flex:none}
.sf-n{font-size:13px;font-weight:600}
.sf-s{font-size:11px;color:var(--text-faint)}
.side-foot .sp{flex:1}
.iconbtn{width:26px;height:26px;border-radius:var(--r-sm);display:flex;align-items:center;justify-content:center;color:var(--text-faint)}
.iconbtn:hover{background:var(--bg-hover);color:var(--text-subtle)}
/* ── 主区 ── */
.main{flex:1;min-width:0;display:flex;flex-direction:column}
.view{display:none;flex:1;min-height:0;flex-direction:column}
.view.on{display:flex}
/* 门户视图 */
.pt-head{padding:26px 32px 0}
.pt-crumb{font-size:12px;color:var(--text-faint);display:flex;gap:6px;align-items:center;margin-bottom:8px}
.pt-title{display:flex;align-items:center;gap:12px}
.pt-title h1{font-size:22px;font-weight:700;letter-spacing:-.2px}
.pt-oi{width:34px;height:34px;border-radius:9px;background:linear-gradient(135deg,#5b8def,#8f6ce8);color:#fff;font-size:15px;font-weight:700;display:flex;align-items:center;justify-content:center}
.pt-desc{margin-top:6px;color:var(--text-subtle);font-size:13.5px}
.pt-stats{display:flex;gap:8px;margin-top:14px;flex-wrap:wrap}
.stat{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:13px;border:1px solid var(--border);font-size:12px;color:var(--text-subtle);background:var(--bg-panel)}
.stat b{color:var(--text);font-weight:600}
.stat .dot{width:6px;height:6px}
.dot{width:7px;height:7px;border-radius:50%;flex:none}
.dot.run{background:var(--accent);box-shadow:0 0 0 3px var(--accent-dim)}
.dot.wait{background:var(--amber);box-shadow:0 0 0 3px var(--amber-dim)}
.dot.idle{background:var(--border-strong)}
.dot.done{background:var(--green)}
.pt-actions{margin-left:auto;display:flex;gap:8px}
.btn{height:30px;padding:0 13px;border-radius:var(--r-sm);border:1px solid var(--border);background:var(--bg-surface);display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:var(--text-subtle)}
.btn:hover{border-color:var(--border-strong);color:var(--text)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff;font-weight:600}
.btn.primary:hover{filter:brightness(1.08)}
.pt-body{flex:1;overflow-y:auto;padding:20px 32px 28px;min-height:0}
.sec2{display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;margin:6px 0 12px}
.sec2 .ln{flex:1;height:1px;background:var(--border-faint)}
.sec2 .more{font-size:12px;color:var(--text-faint);font-weight:400;cursor:pointer}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(252px,1fr));gap:12px}
.card{border:1px solid var(--border);border-radius:var(--r-lg);background:var(--bg-panel);padding:13px 14px;cursor:pointer;transition:border-color var(--ease),transform var(--ease);box-shadow:var(--shadow-card)}
.card:hover{border-color:var(--border-strong);transform:translateY(-1px)}
.card .row1{display:flex;align-items:center;gap:8px}
.card .ttl{flex:1;font-size:13.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card .sn{margin-top:6px;font-size:12px;color:var(--text-faint);line-height:1.5;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:36px}
.card .meta{margin-top:9px;display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-faint)}
.card .meta .sp{flex:1}
.card .who{width:16px;height:16px;border-radius:50%;font-size:9px;font-weight:700;color:#fff;display:flex;align-items:center;justify-content:center}
.card.new{border-style:dashed;background:transparent;display:flex;align-items:center;justify-content:center;gap:8px;color:var(--text-faint);min-height:118px;box-shadow:none}
.card.new:hover{border-color:var(--accent);color:var(--accent);background:var(--accent-dim)}
/* 对话视图 */
.cv-head{padding:12px 24px 10px;border-bottom:1px solid var(--border-faint);display:flex;align-items:center;gap:10px}
.cv-back{display:inline-flex;align-items:center;gap:6px;height:28px;padding:0 10px;border-radius:var(--r-sm);border:1px solid var(--border);color:var(--text-subtle);font-size:12.5px}
.cv-back:hover{background:var(--bg-hover);color:var(--text)}
.cv-title{font-size:15px;font-weight:600}
.cv-sub{margin-top:4px;font-size:12px;color:var(--text-faint)}
.msgs{flex:1;overflow-y:auto;padding:20px 24px;min-height:0}
.msg{margin-bottom:18px;max-width:820px}
.m-user{display:flex;justify-content:flex-end}
.m-user .bubble{background:var(--bg-surface);border:1px solid var(--border);border-radius:var(--r-xl);padding:10px 14px;max-width:74%}
.m-meta{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.m-mark{width:20px;height:20px;border-radius:6px;background:linear-gradient(135deg,var(--accent),#8f6ce8);color:#fff;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700}
.m-name{font-size:12.5px;font-weight:600}
.m-model{font-size:10.5px;color:var(--text-faint);border:1px solid var(--border);border-radius:4px;padding:0 5px}
.m-time{font-size:11px;color:var(--text-faint)}
.m-body{font-size:14px;line-height:1.7}
.confirm-card{border:1px solid var(--green-border);background:var(--green-dim);border-radius:var(--r-lg);padding:12px 14px;margin:12px 0;max-width:640px}
.cc-head{display:flex;align-items:center;gap:8px;font-weight:600;font-size:13.5px}
.cc-head .ic{color:var(--green)}
.cc-body{font-size:13px;color:var(--text-subtle);margin:6px 0 10px}
.cc-actions{display:flex;gap:8px;align-items:center}
.btn.sm{height:24px;padding:0 9px;font-size:12px}
.btn.green{background:var(--green);border-color:var(--green);color:#fff;font-weight:600}
.cc-src{margin-left:auto;font-size:11px;color:var(--text-faint)}
.composer-wrap{padding:8px 24px 16px}
.composer{border:1px solid var(--border);border-radius:var(--r-xl);background:var(--bg-input);box-shadow:var(--shadow-card)}
.composer:focus-within{border-color:var(--accent)}
.composer textarea{width:100%;border:none;background:transparent;resize:none;font:inherit;color:var(--text);padding:11px 14px 4px;outline:none}
.composer textarea::placeholder{color:var(--text-faint)}
.cmp-row{display:flex;align-items:center;gap:6px;padding:6px 8px 8px}
.cmp-row .sp{flex:1}
.send{width:30px;height:30px;border-radius:var(--r-sm);background:var(--accent);color:#fff;display:flex;align-items:center;justify-content:center}
.model-chip{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 9px;border-radius:6px;border:1px solid var(--border);font-size:11.5px;color:var(--text-subtle)}
.demo-tag{position:fixed;left:14px;bottom:12px;z-index:60;font-size:11px;color:var(--text-faint);background:var(--bg-panel);border:1px solid var(--border);border-radius:8px;padding:4px 10px;box-shadow:var(--shadow-card);pointer-events:none}
.demo-tag b{color:var(--text-subtle);font-weight:600}
</style>
</head>
<body>
<div class="app">
<aside class="side">
<div class="brand">
<div class="brand-mark"><svg class="ic ic-s" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3.2" fill="#fff" stroke="none"/><circle cx="12" cy="3.6" r="1.7" fill="#fff" stroke="none" opacity=".85"/><circle cx="19.5" cy="8" r="1.7" fill="#fff" stroke="none" opacity=".85"/><circle cx="19.5" cy="16" r="1.7" fill="#fff" stroke="none" opacity=".85"/><circle cx="12" cy="20.4" r="1.7" fill="#fff" stroke="none" opacity=".85"/><circle cx="4.5" cy="16" r="1.7" fill="#fff" stroke="none" opacity=".85"/><circle cx="4.5" cy="8" r="1.7" fill="#fff" stroke="none" opacity=".85"/></svg></div>
<span class="brand-name">Agent-System</span>
</div>
<button class="newproj"><svg class="ic ic-s" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg>新建项目</button>
<div class="side-scroll">
<div class="sec">进行中 · 3</div>
<div class="proj on"><span class="oi" style="background:linear-gradient(135deg,#5b8def,#8f6ce8)">研</span><span class="n">研发体系文档</span><span class="c">4</span></div>
<div class="proj"><span class="oi" style="background:#2f855a">记</span><span class="n">记忆库建设</span><span class="c">3</span></div>
<div class="proj"><span class="oi" style="background:#b7791f">测</span><span class="n">真实模型测试</span><span class="c">2</span></div>
<div class="sec">已归档 · 1</div>
<div class="proj" style="opacity:.6"><span class="oi" style="background:#4a5568">旧</span><span class="n">旧文档迁移</span><span class="c">7</span></div>
</div>
<div class="side-foot">
<span class="avatar">W</span>
<span><div class="sf-n">weichen</div><div class="sf-s">研发体系团队 · OWNER</div></span>
<span class="sp"></span>
<button class="iconbtn" title="主题" onclick="const h=document.documentElement;h.dataset.theme=h.dataset.theme==='dark'?'light':'dark'"><svg class="ic ic-s" viewBox="0 0 24 24"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8Z"/></svg></button>
<button class="iconbtn" title="设置"><svg class="ic ic-s" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M19 12a7 7 0 0 0-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 0 0-2-1.2L14 3h-4l-.5 2.6a7 7 0 0 0-2 1.2l-2.4-1-2 3.4 2 1.6A7 7 0 0 0 5 12c0 .4 0 .8.1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 2 1.2L10 21h4l.5-2.6a7 7 0 0 0 2-1.2l2.4 1 2-3.4-2-1.6c.06-.4.1-.8.1-1.2Z"/></svg></button>
</div>
</aside>
<main class="main">
<!-- 门户视图 -->
<div class="view on" id="v-portal">
<div class="pt-head">
<div class="pt-crumb">项目 / 研发体系文档</div>
<div class="pt-title">
<span class="pt-oi">研</span>
<h1>研发体系文档</h1>
<span class="pt-actions">
<button class="btn"><svg class="ic ic-s" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>搜索项目内容</button>
<button class="btn">⋯</button>
<button class="btn primary" onclick="openConv()"><svg class="ic ic-s" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg>新建会话</button>
</span>
</div>
<div class="pt-desc">研发记忆与体系文档的沉淀、检索与生成。目标系统「两树一网」的载体项目。</div>
<div class="pt-stats">
<span class="stat"><b>4</b> 会话</span>
<span class="stat"><span class="dot run"></span><b>2</b> 运行中</span>
<span class="stat"><span class="dot wait"></span><b>1</b> 待确认</span>
<span class="stat"><b>5</b> 工件</span>
<span class="stat">成员 <b>6</b></span>
</div>
</div>
<div class="pt-body">
<div class="sec2">进行中的会话<span class="ln"></span><span class="more" onclick="toast('查看全部(设计稿示意)')">全部 ›</span></div>
<div class="grid">
<div class="card" onclick="openConv()">
<div class="row1"><span class="dot run"></span><span class="ttl">本周周报起草与素材汇总</span></div>
<div class="sn">检索本周 23 条素材,起草周报;已进入生成确认环节…</div>
<div class="meta"><span>3 分钟前</span><span>·</span><span>18 条消息</span><span class="sp"></span><span class="who" style="background:#5b8def">W</span></div>
</div>
<div class="card" onclick="openConv()">
<div class="row1"><span class="dot wait"></span><span class="ttl">接口设计文档评审</span></div>
<div class="sn">3 处契约变更待确认;评审材料已备齐,建议周四 14:00…</div>
<div class="meta"><span>1 小时前</span><span>·</span><span>9 条消息</span><span class="sp"></span><span class="who" style="background:#2f855a">Y</span></div>
</div>
<div class="card" onclick="openConv()">
<div class="row1"><span class="dot idle"></span><span class="ttl">文档规范修订意见收集</span></div>
<div class="sn">汇总各模块对文档规范 v2.4 的修订意见,输出对照表…</div>
<div class="meta"><span>昨天</span><span>·</span><span>12 条消息</span><span class="sp"></span><span class="who" style="background:#5b8def">W</span></div>
</div>
<button class="card new" onclick="toast('新建会话(设计稿示意)')"><svg class="ic" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg>新建会话</button>
</div>
<div class="sec2" style="margin-top:22px">最近工件<span class="ln"></span><span class="more" onclick="toast('工件面板(设计稿示意)')">全部 ›</span></div>
<div class="grid">
<div class="card" onclick="toast('打开工件(设计稿示意)')">
<div class="row1"><svg class="ic ic-s" viewBox="0 0 24 24" style="color:var(--accent)"><path d="M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8Z"/><path d="M14 3v5h5"/></svg><span class="ttl">周报_第39周.docx</span></div>
<div class="sn">10:24 生成 · 1,214 字 · 本周周报起草与素材汇总</div>
<div class="meta"><span>刚刚</span><span class="sp"></span><span>文档</span></div>
</div>
<div class="card" onclick="toast('打开工件(设计稿示意)')">
<div class="row1"><svg class="ic ic-s" viewBox="0 0 24 24" style="color:var(--green)"><path d="M4 4h16v16H4z"/><path d="M4 10h16M10 4v16"/></svg><span class="ttl">接口契约变更清单.md</span></div>
<div class="sn">09-29 · 3 模块 12 项变更 · 接口设计文档评审</div>
<div class="meta"><span>昨天</span><span class="sp"></span><span>文档</span></div>
</div>
</div>
</div>
</div>
<!-- 对话视图 -->
<div class="view" id="v-conv">
<div class="cv-head">
<button class="cv-back" onclick="closeConv()"><svg class="ic ic-s" viewBox="0 0 24 24"><path d="M19 12H5M11 18l-6-6 6-6"/></svg>返回项目</button>
<span class="cv-title">本周周报起草与素材汇总</span>
<span style="flex:1"></span>
<button class="btn">分享</button>
<button class="btn">⋯</button>
</div>
<div class="cv-sub" style="padding:0 24px 8px;font-size:12px;color:var(--text-faint)">研发体系文档 · 2 个代理运行中 · 更新于 3 分钟前</div>
<div class="msgs">
<div class="msg m-user"><div class="bubble">把记忆库建设项目的本周素材汇总一下,并起草周报——重点写「两树一网」模型 v3 的进展。</div></div>
<div class="msg">
<div class="m-meta"><span class="m-mark">A</span><span class="m-name">助手</span><span class="m-model">GLM-4.6</span><span class="m-time">10:21</span></div>
<div class="m-body">已检索记忆库本周新增的 23 条素材:「两树一网」v3 初稿完成待合并意见;接口契约变更涉及 3 个模块;外部语料导入触发 2 条条目冲突已合并。</div>
<div class="confirm-card">
<div class="cc-head"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="m8.5 12.2 2.4 2.4 4.6-5"/></svg>等待确认:生成《本周周报》草稿</div>
<div class="cc-body">按「进展 / 评审安排 / 风险」三节起草,约 1200 字。确认后写入工件并回写时间线。</div>
<div class="cc-actions"><button class="btn sm green">确认生成</button><button class="btn sm">调整大纲</button><span class="cc-src">来源:消息 #6</span></div>
</div>
</div>
</div>
<div class="composer-wrap">
<div class="composer">
<textarea rows="1" placeholder="给助手发消息;/ 唤起命令…"></textarea>
<div class="cmp-row"><span class="sp"></span><span class="model-chip">GLM-4.6</span><button class="send"><svg class="ic ic-s" viewBox="0 0 24 24"><path d="M12 19V5M5 12l7-7 7 7"/></svg></button></div>
</div>
</div>
</div>
</main>
</div>
<div class="demo-tag"><b>方案 C · 项目门户</b>设计稿 · 无后端 · 点击会话卡进入对话</div>
<script>
function openConv(){document.getElementById('v-portal').classList.remove('on');document.getElementById('v-conv').classList.add('on')}
function closeConv(){document.getElementById('v-conv').classList.remove('on');document.getElementById('v-portal').classList.add('on')}
function toast(msg){let t=document.getElementById('__t');if(!t){t=document.createElement('div');t.id='__t';t.style.cssText='position:fixed;bottom:20px;left:50%;transform:translateX(-50%);z-index:99;background:var(--bg-surface);border:1px solid var(--border-strong);border-radius:8px;padding:8px 16px;font-size:12.5px;box-shadow:var(--shadow-pop);transition:opacity .2s';document.body.appendChild(t)}t.textContent=msg;t.style.opacity=1;clearTimeout(t._h);t._h=setTimeout(()=>t.style.opacity=0,1400)}
</script>
</body>
</html>