This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-MVP/activities/crm-relationship-coverage/src/views/prd-style.ts
T
xcsandClaude Opus 5 0aa2fc11b0 资料文件真产出来了;E04/I01 补到验收线,顺手填了几个「墙拦住却不给路」的坑
**资料文件全链**(用户:审核资料这一步要真产出 word/excel/md/html,前端能渲、点资料名能开)
接手时这一步一个文件都产不出来 —— S3 剧本白纸黑字写着「file_ref 本 MVP 阶段可留空」。
文件是台账那一行的投影,不另存一份:
· 声明 `file:{titleColumn,bodyColumn,formatColumn}`,它同时是授权面(没声明就点不开)
· 现造真字节 —— docx/xlsx 是自己打的 OOXML 包(zip-write:store+CRC32,零依赖)
· 读回来渲 —— 解的就是造出来那份字节,渲得出来才证明文件是真的
· 件上 `data-file-of` → 工作区二级界面(Word 纸面/Excel 网格/渲好的 md/沙箱 html)+ 下载原件
放行落地前把每一份冻进 `sys.task_asset_file`(迁移 0029):归档件点开的必须是签字那一刻
那一份,而资料落在主数据上、试跑单不落正式表 —— 不存这一份,收工后一个都点不开。
工作成果里「产出的资料」自成一摞。Markdown 富文本渲染顺带销账(仍零依赖)。

**Harness**
· 画面按「这一拍办完之后」在办的那一步挑 —— 从前拿拍首的局面决定拍尾的事:
  收掉 S4、发出 S5 的卡,而屏上还摆着 S4 的只读件,人无处可填(墙要配路第四次现形)
· 验收「重做」真能退回重做,且打回后台账没动就不许再提交(软硬两段,不锁死单子)
· 立监听的授权面是清单声明;发卡的授权面是调人预算,不是计划项
· 读工具同参重调有兜底;空转写身后还有行动就不废串;finish 的 doneWhen 按写完后的草稿算

**界面**
· 翻件与翻页各归各位(从前二选一,多卡多页时页翻不动);没得翻写「—」不写 0/0
· 工作成果详情能翻份;表宽超出能横滑(E04/I01 抄版式时把 overflow-x 抄丢了)
· 查看面灰底滚过一屏变白 —— 两条独立的路都治了(沙箱内不同色 / 弹性子项不长个)
· 测试台「取不到」不再当成「还活着」

**活动**
E04 关系覆盖、I01 品牌内容各自补到验收线:判据全读基座数、判据指向的东西摆上卡面、
样例满载且名字 ≤14 字;提交前要裁的判据搬进说明书(模型会压拍,压过之后只有说明书还在)。

验收:e2e i01 4/4、e04 3/3 全部 released,资料在办中渲得出、放行后存了档点得开;
门禁 typecheck/lint/depcruise/1628 测全绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EEJX8Z7CHejvwmDQyPQuBX
2026-08-24 10:26:45 +08:00

163 lines
11 KiB
TypeScript
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.
/**
* E04 关系覆盖与关键人经营 · 视觉底(**E04 自己的 PRD 目标件,不是借来的家族版面**)。
*
* 上一版这里写着「E04 没有自己的 PRD 目标件」——那是假的:
* `docs/SS01-客户与市场/e04-html/` 下的四份 HTML(执行工单 1/2、验收工单 1/2)正是
* E04 自己的目标件,颜色变量、卡头渐变、判据框、原生 select/textarea 全部逐字量自那四份文件,
* 不是 A1/A2 那一支「浮起卡片 + 渐变徽章 + 头像签名」的家族版面。
*
* 两处**有意**偏离目标件,原因写在这里(别处再改记得回头看):
* 1. 目标件的必填只在表头打一个「*」;本仓有个更早、已验证过的平台级三档占位系统
* (必填红 / 建议填橘 / 选填灰,2026-08-02 定,`docs/HTML报告生成规范.md` 收录),
* 比「只在表头提一句」更能在空格子上直接指路。两者都留着:表头照抄目标件的「*」,
* 空格子再叠一层三档胶囊——不冲突,目标件的例子本来就没有空格子可比对。
* 2. 候选清单「状态」列:目标件那一列是「正式/试用」(客户主数据的状态),
* 本活动的 `candidate.status` 是另一个真实字段(`pending/covered/excluded`,
* 候选行本轮的覆盖生命周期,`declarations.ledger` 里 tally 着),两者恰好同名不同义。
* 留的是本活动这个——它是真在用的数据,目标件那份是另一件事。
*
* 版面照目标件分两层:这份文件是**底**(配色变量、卡壳、头/尾、判据框、说明框、表格基础排版),
* `report.ts` 里的 `BIND_CSS` 是**面**(哪个值决定哪种颜色/文案——三档占位、缺项红带、
* 状态徽、编辑闸开合、行增删这些「数据驱动的开关」,判断在样式表,取值在模版,两处不许混)。
*/
export const PRD_CSS = `
.proto-root {
--ink:#1f2329; --ink-2:#41464e; --ink-3:#646a73; --ink-4:#8f959e;
--line:#dee0e3; --line-soft:#e8eaed; --soft:#f8f9fb;
--brand:#3370ff; --brand-deep:#245bdb; --brand-soft:#e1eaff; --brand-wash:#f0f4ff;
--human:#a9711e; --human-soft:#f6ecd8; --human-line:#e6d3a8;
--ledger:#b23a2e; --ledger-soft:#f7e4e0; --ledger-line:#ecc5bd;
--ok:#278717; --ok-soft:#e8f8e4;
--danger:#d83931; --danger-soft:#feeae9;
--warn-accent:#a9711e; --warn-soft:#f6ecd8;
--mono: "SF Mono", Menlo, Consolas, monospace;
--t-fast: .16s;
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
color: var(--ink);
font-size: 14px;
line-height: 1.7;
}
.proto-root, .proto-root * { box-sizing: border-box; }
/* ==================== 卡壳(嵌进工作区,不自带浮起——外层已经是一张卡)==================== */
.proto-root .jc-report { background: #fff; overflow: hidden; }
.proto-root .jc-rp-head { display: flex; align-items: center; gap: 14px; padding: 18px 22px; border-bottom: 2px solid var(--ink); }
.proto-root .jc-report.tone-human .jc-rp-head { background: linear-gradient(120deg, #fffaf1 0%, #fff 55%, #fbf6ea 100%); }
.proto-root .jc-report.tone-ledger .jc-rp-head { background: linear-gradient(120deg, #fdf3f1 0%, #fff 55%, #fbf2f0 100%); }
.proto-root .jc-rp-badge {
flex: none; width: 44px; height: 44px; border-radius: 10px;
display: grid; place-items: center; color: #fff; font-weight: 800; font-size: 13px;
}
.proto-root .jc-report.tone-human .jc-rp-badge { background: var(--human); box-shadow: 0 6px 16px rgba(169,113,30,.25); }
.proto-root .jc-report.tone-ledger .jc-rp-badge { background: var(--ledger); box-shadow: 0 6px 16px rgba(178,58,46,.25); }
.proto-root .jc-rp-tit { flex: 1; min-width: 0; }
.proto-root .jc-rp-tit em { font-style: normal; font-size: 11px; letter-spacing: .08em; color: var(--ink-4); font-weight: 700; }
.proto-root .jc-rp-tit h3 { margin: 2px 0 0; font-size: 19px; font-weight: 800; line-height: 1.3; }
.proto-root .jc-rp-sub { font-size: 12px; color: var(--ink-3); margin-top: 3px; }
.proto-root .jc-rp-side { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; flex: none; }
/* 目标件 side 第二行:步骤(静态文案),同目标件 .step 的字号字色 */
.proto-root .jc-rp-step { font-size: 12px; color: var(--ink-3); }
/* 关联任务号:全长 UUID 如实给,排版上截尾 —— 截断是排版,不是数据 */
.proto-root .jc-rp-taskid {
display: inline-block; max-width: 150px; overflow: hidden; text-overflow: ellipsis;
white-space: nowrap; vertical-align: bottom; font-family: var(--mono); font-size: 11px;
}
.proto-root .jc-rp-tag { font-size: 11px; font-weight: 800; padding: 2px 10px; border-radius: 999px; border: 1px solid; }
.proto-root .jc-report.tone-human .jc-rp-tag { color: var(--human); background: var(--human-soft); border-color: var(--human-line); }
.proto-root .jc-report.tone-ledger .jc-rp-tag { color: var(--ledger); background: var(--ledger-soft); border-color: var(--ledger-line); }
.proto-root .jc-rp-wait { font-size: 12px; color: var(--ink-3); }
.proto-root .jc-rp-wait.warn { color: var(--danger); font-weight: 700; }
.proto-root .jc-rp-bd { padding: 20px 22px; }
/* 【做什么】/【交回什么】这类分区小标——括号label + 破折号说明,同一行 */
.proto-root .jc-rp-part { font-size: 11px; font-weight: 800; letter-spacing: .12em; color: var(--ink-4); margin: 20px 0 8px; }
.proto-root .jc-rp-part:first-child { margin-top: 0; }
.proto-root .jc-rp-part b { color: var(--ink-3); }
/* AI 已完成 / 需要你 —— 说明框,左侧色条按 tone 走 */
.proto-root .jc-derive { border: 1px solid var(--line); border-left: 3px solid; border-radius: 8px; background: var(--soft); padding: 14px 16px; margin-bottom: 16px; }
.proto-root .jc-report.tone-human .jc-derive { border-left-color: var(--human); }
.proto-root .jc-report.tone-ledger .jc-derive { border-left-color: var(--ledger); }
.proto-root .jc-derive p { margin: 0; font-size: 13px; color: var(--ink-2); }
.proto-root .jc-derive p + p { margin-top: 6px; }
.proto-root .jc-derive b { color: var(--ink); }
.proto-root .jc-derive .done { color: var(--ok); font-weight: 700; }
.proto-root .jc-report.tone-human .jc-derive .need { color: var(--human); font-weight: 700; }
.proto-root .jc-report.tone-ledger .jc-derive .need { color: var(--ledger); font-weight: 700; }
/* 验收判据框——目标件里两份验收工单同一色(赭红),不随 tone 变 */
.proto-root .jc-criteria { border: 1px solid var(--ledger-line); border-radius: 10px; background: var(--ledger-soft); padding: 13px 16px; margin-bottom: 18px; }
.proto-root .jc-criteria-t { font-size: 11px; font-weight: 800; letter-spacing: .08em; color: var(--ledger); margin-bottom: 7px; }
.proto-root .jc-criteria ul { margin: 0; padding-left: 18px; font-size: 12.5px; color: var(--ink-2); }
.proto-root .jc-criteria li { margin: 4px 0; }
.proto-root .jc-criteria b { color: var(--ink); }
/* 表格基础排版(交互态的显隐开关在 BIND_CSS) */
/*
* **表宽超出就得能横着滑**(2026-08-23 用户:「表格已经显示不全了,不能左右滑动」)。
* 从前这里是 overflow: hidden —— 那是为了让圆角裁住表头,可它同时把超出的列
* **直接裁掉且滑不动**:列一多(或某列为了放下下拉框加宽)就看不全,人还没有任何办法。
* quote-* 各包一直是 overflow-x: auto,这两个新包抄版式时把这一条抄丢了。
* (注释里不写反引号 —— 整段 CSS 是模版字符串,一个反引号就把它截断,本轮踩第三次。)
* 竖向仍 hidden:件是整篇铺开跟着外层滚的,表格自己不该再套一层竖滚动条。
*/
.proto-root .jc-tbl-wrap { border: 1px solid var(--line-soft); border-radius: 10px; overflow-x: auto; overflow-y: hidden; margin-bottom: 4px; }
.proto-root .jc-tbl-in { width: 100%; border-collapse: collapse; font-size: 13px; }
.proto-root .jc-tbl-in th { text-align: left; background: var(--soft); font-size: 11px; letter-spacing: .04em; font-weight: 800; color: var(--ink-3); padding: 9px 11px; border-bottom: 1px solid var(--line); }
.proto-root .jc-tbl-in th.req::after { content: " *"; color: var(--danger); font-size: 11px; }
.proto-root .jc-tbl-in th.sug::after { content: " 建议"; color: var(--warn-accent); font-size: 10px; font-weight: 600; }
.proto-root .jc-tbl-in th.opt::after { content: " 选填"; color: var(--ink-4); font-size: 10px; font-weight: 600; }
.proto-root .jc-tbl-in td { padding: 9px 11px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
.proto-root .jc-tbl-in tr:last-child td { border-bottom: 0; }
.proto-root .jc-tbl-in td.jc-rn { width: 38px; white-space: nowrap; font-family: var(--mono); font-size: 11px; color: var(--ink-4); text-align: center; position: relative; }
.proto-root .jc-vcell { display: block; font-size: 12.5px; color: var(--ink); line-height: 1.5; overflow-wrap: anywhere; }
.proto-root .jc-vcell.mono { font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); }
.proto-root .jc-vcell.cust { font-weight: 700; }
.proto-root .jc-vcell.dim { color: var(--ink-4); text-decoration: line-through; }
.proto-root .jc-diffnew { font-weight: 800; color: var(--ok); }
.proto-root .jc-cell, .proto-root select.jc-cell, .proto-root textarea.jc-cell {
width: 100%; min-width: 60px; border: 1px solid var(--line); border-radius: 6px;
padding: 6px 8px; font: inherit; font-size: 12.5px; color: var(--ink); background: #fff;
}
/* 多行文本照目标件:最小两行高,竖向可拉 */
.proto-root textarea.jc-cell { min-height: 40px; resize: vertical; }
.proto-root .jc-cell.mono { font-family: var(--mono); font-size: 11.5px; }
.proto-root .jc-cell:focus { border-color: var(--brand); box-shadow: 0 0 0 3px var(--brand-wash); outline: none; }
/* 格内次行小字(依据 / 编码)—— 主行之下,不占独立列 */
.proto-root .jc-sub { display: block; font-size: 11px; color: var(--ink-4); margin-top: 2px; line-height: 1.55; }
.proto-root .jc-sub i { font-style: normal; }
/* 取值位(i)全空的次行整行藏掉;直填文本的次行(如对象格的编码)不归这条管 */
.proto-root .jc-sub:has(i):not(:has(i:not(:empty))) { display: none; }
.proto-root .jc-rowdel {
width: 22px; height: 22px; margin: 0 auto; cursor: pointer;
border: 1px solid var(--line); border-radius: 6px; padding: 0;
font: inherit; font-size: 14px; line-height: 1; color: var(--ink-3); background: #fff;
transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
}
.proto-root .jc-rowdel:hover { border-color: var(--danger); color: var(--danger); background: var(--danger-soft); }
.proto-root .jc-addrow em { font-style: normal; font-size: 11.5px; color: var(--ink-4); }
.proto-root .jc-addrow button {
cursor: pointer; border: 1px solid var(--brand-soft); border-radius: 7px; padding: 5px 12px;
font: inherit; font-size: 12px; font-weight: 700; color: var(--brand-deep); background: var(--brand-wash);
}
.proto-root .jc-addrow button:hover { background: var(--brand-soft); }
/* 本工单只承载内容,提交/审批请在对话区——目标件四份文件都有这一条 */
.proto-root .jc-flow { margin-top: 16px; padding: 9px 12px; border-radius: 8px; background: var(--soft); border: 1px dashed var(--line); font-size: 12px; color: var(--ink-3); }
.proto-root .jc-flow b { color: var(--ink); }
.proto-root .jc-rp-foot { padding: 13px 22px; border-top: 1px solid var(--line-soft); font-size: 11.5px; color: var(--ink-4); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; }
.proto-root .jc-rp-foot span:last-child { font-family: var(--mono); }
`;