M6(1/n): 工作台任务要素 —— 原型 1:1 平移的第一屏

样式整文件搬(README 平移规则 1):app.css 2767 行 + proto.vendor.css +
theme.css + console.css 原样搬,设计令牌与全部 jc-* / g-* 类名不动。

前端(按 §9 重排,渲染输出 1:1):
- shared/:Ico / ScrollArea / useChatWidth 自原型搬,去掉 "use client" 等 Next 专有件;
  失效的 react-hooks disable 指令按 §17 清掉(不改渲染)
- shared/typed-fetch.ts:服务端交互唯一通道,路由契约来自 @contracts/api;
  不引 Hono RPC 客户端(那要求前端 import 后端类型,违反 §5.1)
- app/query.ts:TanStack Query;缓存失效由订阅层驱动,组件不轮询
- features/desk-task:任务列表(一条 = 一个活动的一次运行,不是一整条工作流)/
  标题区 + 工作区四页签 / 对话区(气泡二元制 + 卡族 + **composer 锁**)
- @ui:ViewContainer 用**沙箱 iframe(sandbox 不含 allow-scripts)** —— 结构上无脚本执行权,
  不依赖净化算法的完备性;ViewBlocks 渲染十一种视图块
  feature 不得自行 dangerouslySetInnerHTML,eslint 有规则守着

后端:工作台路由 /api/desk/*(任务清单 / 任务详情 / 工单回传 / 自由输入 / 消息);
回传与后端校验**同 schema**;任务详情是服务端投影 —— 前端零过程状态,刷新即重建

已验证(真机):任务卡「A1 RFQ需求分析 · 序位 1/7 · awaiting-event」、
预算 2/40 步、1 张工单(LLM 步失败后转人兜底那张)、7 行带归侧标签的任务日志

358 个测试通过,门禁五道全绿;web 构建通过

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
JCAI Main Agent
2026-07-27 02:45:42 +08:00
co-authored by Claude Opus 5
parent 3df8becf67
commit 3cfaa04098
27 changed files with 6966 additions and 10 deletions
+61
View File
@@ -0,0 +1,61 @@
/* ============================================================================
JCAI 治理台 · 令牌与基座
—— 只放设计令牌 + 页面基座;治理台的外壳与全部组件在 console.css。
令牌与工作台同源(飞书蓝阶 + 中性阶 + 功能色 + 类型强调色),但**壳不同**:
工作台是浅色三栏工作面,治理台是深色轨 + 深色顶栏的控制台。
========================================================================== */
:root {
/* —— 飞书蓝阶 —— */
--brand: #3370ff;
--brand-deep: #245bdb;
--brand-pressed: #1c4cba;
--brand-soft: #e1eaff;
--brand-wash: #f0f4ff;
/* —— AI 在场渐变 —— */
--ai-a: #3370ff;
--ai-b: #7f3bf5;
--ai-grad: linear-gradient(135deg, var(--ai-a), var(--ai-b));
/* —— 中性阶 —— */
--ink: #1f2329;
--ink-2: #41464e;
--ink-3: #646a73;
--ink-4: #8f959e;
--line: #dee0e3;
--line-soft: #e8eaed;
--canvas: #f0f2f5;
--soft: #f8f9fb;
--cardline: #e1e6ec;
--card-shadow: 0 1px 2px rgba(31, 35, 41, .05);
/* —— 功能色 —— */
--ok: #278717; --ok-accent: #34c724; --ok-soft: #e8f8e4;
--warn: #de7802; --warn-accent: #ff8800; --warn-soft: #fff4e5;
--danger: #d83931; --danger-accent: #f54a45; --danger-soft: #feeae9;
/* —— 活动 / 节点类型强调色 —— */
--st-auto: #4954e6; --st-execute: #e07a00; --st-decision: #7f3bf5;
--st-collab: #0aa294; --st-wait: #6a7590;
/* —— 字体 / 动效 —— */
--sans: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
--mono: ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", Menlo, Consolas, monospace;
--t-fast: .16s cubic-bezier(.3, 0, .2, 1);
--t-med: .26s cubic-bezier(.3, 0, .2, 1);
}
/* ============================== 基座 ============================== */
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
margin: 0;
min-width: 1120px;
background: #eceff4;
color: var(--ink);
font-family: var(--sans);
-webkit-font-smoothing: antialiased;
}
:root { scrollbar-width: thin; scrollbar-color: #c9ced6 transparent; }
::selection { background: var(--brand-soft); }
:where(button, input, textarea, select, a, [tabindex]):focus-visible {
outline: 2px solid var(--brand);
outline-offset: 2px;
border-radius: 8px;
}