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/docs/SS01-客户与市场/i01-html/I01-执行工单-01-需求受理.html
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

187 lines
13 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>执行工单 1 · 需求受理与信息补充 · I01 品牌形象与销售工具包管理</title>
<style>
: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;
--ok:#278717; --ok-soft:#e8f8e4; --danger:#d83931; --danger-soft:#feeae9;
--mono:"SF Mono",Menlo,Consolas,monospace;
}
*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Microsoft YaHei",sans-serif;background:#eef1f6;color:var(--ink);font-size:14px;line-height:1.7;-webkit-font-smoothing:antialiased}
.page{margin:0;padding:0}
.card{background:#fff;overflow:hidden;border:0;border-radius:0;box-shadow:none}
.card-head{display:flex;align-items:center;gap:14px;padding:18px 22px;border-bottom:2px solid var(--ink);background:linear-gradient(120deg,#fffaf1 0%,#fff 55%,#fbf6ea 100%)}
.badge{flex:none;width:44px;height:44px;border-radius:10px;display:grid;place-items:center;background:var(--human);color:#fff;font-weight:800;font-size:13px;box-shadow:0 6px 16px rgba(169,113,30,.25)}
.tit{flex:1;min-width:0}
.tit .kick{font-size:11px;letter-spacing:.08em;color:var(--ink-4);font-weight:700}
.tit h1{margin:2px 0 0;font-size:19px;font-weight:800;line-height:1.3}
.tit .sub{font-size:12px;color:var(--ink-3);margin-top:3px}
.side{display:flex;flex-direction:column;align-items:flex-end;gap:6px;flex:none}
.tag{font-size:11px;font-weight:800;padding:2px 10px;border-radius:999px;color:var(--human);background:var(--human-soft);border:1px solid var(--human-line)}
.step{font-size:12px;color:var(--ink-3)}
.deadline{font-size:12px;color:var(--ink-3)}
.deadline b{color:var(--danger)}
.card-bd{padding:20px 22px}
.zone{font-size:11px;font-weight:800;letter-spacing:.12em;color:var(--ink-4);margin:0 0 8px}
.zone b{color:var(--ink-3)}
.note{border:1px solid var(--line);border-left:3px solid var(--human);border-radius:8px;background:var(--soft);padding:14px 16px;margin-bottom:16px}
.note p{margin:0;font-size:13px;color:var(--ink-2)}
.note b{color:var(--ink)}
.note .done{color:var(--ok);font-weight:700}
.note .need{color:var(--human);font-weight:700}
.jc-editgate{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:14px 0 10px;padding:9px 12px;border-radius:9px;background:var(--soft);border:1px solid var(--line-soft);font-size:12px;color:var(--ink-3)}
.jc-editgate-t{flex:1 1 auto;min-width:0}
.jc-editgate-t b{color:var(--ink-2);font-weight:700}
.jc-egbtn{flex:none;display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:1px solid var(--line);border-radius:7px;padding:6px 13px;font:inherit;font-size:12px;font-weight:700;color:var(--ink-2);background:#fff}
.jc-egbtn:hover{border-color:var(--brand);color:var(--brand)}
.jc-egbtn.save{color:#fff;background:var(--human);border-color:var(--human)}
.jc-egbtn.save:hover{filter:brightness(1.06);color:#fff}
.jc-editgate .eg-cancel,.jc-editgate .eg-save{display:none}
.jc-editgate.on{background:var(--human-soft);border-color:var(--human-line);color:#7c4a12}
.jc-editgate.on .eg-open{display:none}
.jc-editgate.on .eg-cancel,.jc-editgate.on .eg-save{display:inline-flex}
.tbl-wrap{border:1px solid var(--line-soft);border-radius:10px;overflow:hidden}
table{width:100%;border-collapse:collapse;font-size:12.5px}
th{text-align:left;background:var(--soft);font-size:11px;letter-spacing:.03em;font-weight:800;color:var(--ink-3);padding:9px 10px;border-bottom:1px solid var(--line)}
th.req::after{content:" *";color:var(--danger);font-size:11px}
td{padding:8px 10px;border-bottom:1px solid var(--line-soft);vertical-align:middle}
tr:last-child td{border-bottom:0}
td.rn{position:relative;width:38px;white-space:nowrap;font-family:var(--mono);font-size:11px;color:var(--ink-4);text-align:center}
.jc-vcell{display:block;font-size:12.5px;color:var(--ink);line-height:1.5;overflow-wrap:anywhere}
.jc-vcell.mono{font-family:var(--mono);font-size:11.5px;color:var(--ink-2)}
.jc-cell{display:none;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}
.jc-cell:focus{border-color:var(--brand);box-shadow:0 0 0 3px var(--brand-wash);outline:none}
table.on td>.jc-vcell{display:none}
table.on td>.jc-cell{display:block}
td.rn .jc-rowdel{display:none;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}
td.rn .jc-rowdel:hover{border-color:var(--danger);color:var(--danger);background:var(--danger-soft)}
table.on td.rn .jc-rn-num{display:none}
table.on td.rn .jc-rowdel{display:block}
.jc-addrow{display:none;margin:8px 0 0;padding:8px 12px;border-radius:9px;background:var(--soft);border:1px dashed var(--line);font-size:12px;color:var(--ink-3)}
.jc-addrow.show{display:flex;align-items:center;gap:8px}
.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)}
.jc-addrow button:hover{background:var(--brand-soft)}
.jc-addrow em{font-style:normal;font-size:11.5px;color:var(--ink-4)}
.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)}
.flow b{color:var(--ink)}
.card-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}
</style>
</head>
<body>
<div class="page">
<div class="card">
<header class="card-head">
<div class="badge">执行</div>
<div class="tit">
<div class="kick">SS01 客户与市场 · I01 品牌形象与销售工具包管理 · 执行工单 1/3</div>
<h1>需求受理与信息补充</h1>
<div class="sub">收件人:<span data-slot="meta.task.owner">AM(内容运营)</span> · 关联任务:<span data-slot="meta.task.id">TASK-xxx</span></div>
</div>
<div class="side">
<span class="tag">执行工单</span>
<span class="step" data-slot="meta.phase">步骤 ① 需求识别与受理</span>
<span class="deadline">最迟交回:<b data-slot="card.deadline">1 个工作日</b></span>
</div>
</header>
<div class="card-bd">
<p class="zone"><b>【做什么】</b>—— 确认本轮要生产的内容</p>
<div class="note">
<p><span class="done">AI 已完成</span>:按规则识别本轮内容需求来源(战略调整 / 新市场 / 工具过期 / 使用方请求)与需求类型(公司介绍 / 能力声明 / 销售工具包 / 选型指南 / 替代对照表 / 案例集 / 白皮书等),产出下方需求清单(<b>候选基线</b>)。</p>
<p><span class="need">需要你查漏补缺</span>:点「编辑」在清单上增删改——<b>加一行 = 补充新需求</b>、<b>删一行 = 排除</b>、<b>改单元格 = 修正</b>;尤其要补「目标客户、适用场景、优先级」这些 AI 规则之外的信息(如使用方要一份方案,但你线下知道要针对某客户做定向版)。</p>
</div>
<p class="zone"><b>【交回什么】</b>—— 核对后的内容需求清单(*为必填)</p>
<div class="jc-editgate" id="editgate">
<span class="jc-editgate-t"><b data-slot="sd.requirement_count">AI 已识别 2 个内容需求</b>,点「编辑」增删改</span>
<button class="jc-egbtn eg-open" type="button">编辑</button>
<button class="jc-egbtn eg-cancel" type="button">取消</button>
<button class="jc-egbtn eg-save" type="button">保存</button>
</div>
<div class="tbl-wrap">
<table id="tbl">
<thead>
<tr>
<th style="width:38px">#</th>
<th class="req" data-h="内容类型">内容类型</th>
<th data-h="需求来源">需求来源</th>
<th data-h="目标客户">目标客户</th>
<th data-h="适用场景">适用场景</th>
<th data-h="优先级">优先级</th>
</tr>
</thead>
<tbody data-rows="in.requirement">
<tr>
<td class="rn"><span class="jc-rn-num">1</span><button class="jc-rowdel" type="button" title="删除此行">×</button></td>
<td data-field="content_type"><span class="jc-vcell">系统方案白皮书</span><input class="jc-cell" value="系统方案白皮书"></td>
<td data-field="source"><span class="jc-vcell">使用方请求(E04 价值传递)</span><input class="jc-cell" value="使用方请求(E04 价值传递)"></td>
<td data-field="target_customer"><span class="jc-vcell">AvtoKom(定向)</span><input class="jc-cell" value="AvtoKom(定向)"></td>
<td data-field="scene"><span class="jc-vcell">攻坚</span><input class="jc-cell" value="攻坚"></td>
<td data-field="priority"><span class="jc-vcell mono">高</span><input class="jc-cell" value="高"></td>
</tr>
<tr>
<td class="rn"><span class="jc-rn-num">2</span><button class="jc-rowdel" type="button" title="删除此行">×</button></td>
<td data-field="content_type"><span class="jc-vcell">公司介绍</span><input class="jc-cell" value="公司介绍"></td>
<td data-field="source"><span class="jc-vcell">战略调整(进入俄罗斯市场)</span><input class="jc-cell" value="战略调整(进入俄罗斯市场)"></td>
<td data-field="target_customer"><span class="jc-vcell">—(通用)</span><input class="jc-cell" value="—(通用)"></td>
<td data-field="scene"><span class="jc-vcell">首触</span><input class="jc-cell" value="首触"></td>
<td data-field="priority"><span class="jc-vcell mono">中</span><input class="jc-cell" value="中"></td>
</tr>
</tbody>
</table>
</div>
<div class="jc-addrow" id="addrow">
<button type="button">+ 加一行(补充新需求)</button>
<em>新加行的「内容类型」为必填;「目标客户」填定向客户,通用内容可留「—」</em>
</div>
<div class="flow"><b>审批 / 提交:</b>本工单只承载内容;「提交回执」请在对话区的【执行卡】中进行。</div>
</div>
<footer class="card-foot">
<span>I01 品牌形象与销售工具包管理 · 执行工单 1/3 · 需求受理</span>
<span style="font-family:'SF Mono',Menlo,Consolas,monospace">工单类型:执行 · <span data-slot="card.id">WO-I01-01</span></span>
</footer>
</div>
</div>
<script>
(function(){
var gate=document.getElementById('editgate'),tbl=document.getElementById('tbl'),addrow=document.getElementById('addrow'),tbody=tbl.querySelector('tbody');
function setEdit(on){gate.classList.toggle('on',on);tbl.classList.toggle('on',on);addrow.classList.toggle('show',on);}
gate.querySelector('.eg-open').addEventListener('click',function(){setEdit(true);});
gate.querySelector('.eg-cancel').addEventListener('click',function(){
tbody.querySelectorAll('tr').forEach(function(tr){tr.querySelectorAll('td').forEach(function(td){var v=td.querySelector('.jc-vcell'),c=td.querySelector('.jc-cell');if(v&&c){c.value=v.textContent;}});});
setEdit(false);
});
gate.querySelector('.eg-save').addEventListener('click',function(){
tbody.querySelectorAll('tr').forEach(function(tr){tr.querySelectorAll('td').forEach(function(td){var v=td.querySelector('.jc-vcell'),c=td.querySelector('.jc-cell');if(v&&c){v.textContent=c.value;}});});
renumber();setEdit(false);
});
addrow.querySelector('button').addEventListener('click',function(){
var tr=document.createElement('tr');
tr.innerHTML='<td class="rn"><span class="jc-rn-num"></span><button class="jc-rowdel" type="button" title="删除此行">×</button></td>'+'<td data-field="content_type"><span class="jc-vcell"></span><input class="jc-cell" placeholder="内容类型"></td>'+'<td data-field="source"><span class="jc-vcell"></span><input class="jc-cell" placeholder="需求来源"></td>'+'<td data-field="target_customer"><span class="jc-vcell"></span><input class="jc-cell" placeholder="目标客户"></td>'+'<td data-field="scene"><span class="jc-vcell"></span><input class="jc-cell" placeholder="适用场景"></td>'+'<td data-field="priority"><span class="jc-vcell mono"></span><input class="jc-cell" placeholder="优先级"></td>';
tbody.appendChild(tr);renumber();
});
tbody.addEventListener('click',function(e){if(e.target.classList.contains('jc-rowdel')){e.target.closest('tr').remove();renumber();}});
function renumber(){tbody.querySelectorAll('tr').forEach(function(tr,i){tr.querySelector('.jc-rn-num').textContent=i+1;});}
})();
</script>
</body>
</html>