forked from ChaiHao/BPOS-MVP
A2-A7 全部补齐到验收线;顺手把几处「门拦住却不给路」的坑填了
活动:A2 选型 / A3 寻源 / A4 定价 / A6 议价 / A7 归档五件各补成真活动包 —— 契约宽进(input.required 空,归一在活动内)、台账必填声明(含行级 requiredWhen)、 入场哨兵与 L1/L2 判据一律读基座数、两份件(在办可编辑 + 办结静态快照)、 三案例常备、包内自测。e2e 各三案例 released、行动被拒 0、发口正确、提交闸每单真拦。 基座(共享面,改一处影响所有活动,故每处都带回归): · 重发判断走在站上场之前 —— 人答完那步常已收掉,readyToWork 先抛「不能再往它上面挂活」, 于是「重发已答过的卡 = 无事发生」这条唯一活路在最需要时够不着,A1 基线当场熔断; · 决策卡补幂等兜底(与执行工单同一把尺):头两次无事发生,第三次起才算被拒; · 输出没成形先就地重问一次,原话进工作日志、不再摆上卡面; · 工具调用读数 tool_<名>_calls —— 「机检只读基座数」这条纪律第一次覆盖到工具; · 执行卡 steps/standard 补进出参 schema(从前能到卡面全靠厂商 JSON 模式宽松); · 件的就地更新改逐节点 morph,保存先把新值镜像进只读那份 —— 不闪、不等回声。 A1(基线,全程守住):措辞三档对齐(必填/建议/选填)、禁止拿历史价当客户目标价、 卡骨架从步骤剧本搬进说明书(压成一拍连做时剧本没摊开,会发出没有指导书的裸卡)。 契约两处**新增可选字段**(非破坏):FieldDeclaration.requiredWhen、工单 finalHtml; api-report 同批更新。docs/adr 与 docs/archive 的 13 份文件在工作树里不见了, 本次予以恢复而非提交删除。 门禁:typecheck / lint / depcruise / test(1366)全绿。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2108,7 +2108,7 @@
|
||||
.proto-root .jc-rp-vals dd { margin: 0; padding: 8px 12px; font-size: 12px; color: var(--ink); line-height: 1.65; background: #fff; }
|
||||
|
||||
/* 落款 */
|
||||
.proto-root .jc-rp-foot { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 13px 20px 15px; border-top: 2px solid var(--line); background: #fbfcfd; }
|
||||
.proto-root .jc-rp-foot { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px; padding: 13px 20px 15px; border-top: 2px solid var(--line); background: #fbfcfd; }
|
||||
.proto-root .jc-rp-sign { display: flex; align-items: center; gap: 9px; flex: 1 1 200px; min-width: 0; }
|
||||
.proto-root .jc-rp-ava { flex: none; width: 30px; height: 30px; border-radius: 999px; display: grid; place-items: center; font-size: 12px; font-weight: 700; color: #fff; background: var(--brand); }
|
||||
.proto-root .jc-rp-sign b { display: block; font-size: 12px; color: var(--ink-2); }
|
||||
@@ -2301,7 +2301,8 @@
|
||||
.proto-root .jc-fc-h em.bad { color: var(--danger); }
|
||||
/* 卡体与动作栏 */
|
||||
.proto-root .jc-fc-b { padding: 11px 13px; display: flex; flex-direction: column; gap: 10px; }
|
||||
.proto-root .jc-fc-ft { display: flex; align-items: center; gap: 8px; padding: 9px 13px; border-top: 1px solid var(--line-soft); background: #fbfcfe; }
|
||||
/* 动作靠右(2026-08-03 用户:「提交按钮放左侧太奇怪了」)—— 验收卡的「重做|通过」有 jc-fc-sp 撑开,不受影响 */
|
||||
.proto-root .jc-fc-ft { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 9px 13px; border-top: 1px solid var(--line-soft); background: #fbfcfe; }
|
||||
/*
|
||||
* **交不了的时候,说清差在哪** —— 只摆一个灰按钮等于让人猜自己哪儿做错了。
|
||||
* 底色用警示色而不是错误红:这不是出错,是活还没干完。
|
||||
|
||||
@@ -81,6 +81,13 @@ function collectEdits(edits: ViewEdits, order: WorkOrder, onField: (k: string, v
|
||||
export function ViewRegion({ detail, onReplyOrder, values, onField, locate }: ViewRegionProps) {
|
||||
const [view, setView] = useState<Tab>('open');
|
||||
const [page, setPage] = useState(0);
|
||||
/*
|
||||
* **件内翻页**(2026-08-02 用户:「一个执行单可以派多个 HTML 待执行报告,
|
||||
* 合理利用右上角的翻页和待处理的数字气泡」):件里带 `data-page` 的可见段
|
||||
* 各算一页(A2 = 一颗待选型芯片一页)。单卡多页时,右上角那对箭头翻的是页。
|
||||
*/
|
||||
const [docPage, setDocPage] = useState(0);
|
||||
const [docPages, setDocPages] = useState(1);
|
||||
/** 工作成果:列表里点开的那份定稿报告 */
|
||||
const [doneSel, setDoneSel] = useState<string | null>(null);
|
||||
const [openFile, setOpenFile] = useState<FileDoc | undefined>(undefined);
|
||||
@@ -279,29 +286,56 @@ export function ViewRegion({ detail, onReplyOrder, values, onField, locate }: Vi
|
||||
<Ico name="chevron-left" s={14} /> 返回列表
|
||||
</button>
|
||||
) : view === 'open' ? (
|
||||
<span className="jc-tnav-pg" aria-label="翻页">
|
||||
<button
|
||||
type="button"
|
||||
className="jc-tnav-btn"
|
||||
disabled={pos === 0}
|
||||
onClick={() => setPage(pos - 1)}
|
||||
aria-label="上一件"
|
||||
>
|
||||
<Ico name="chevron-left" s={15} />
|
||||
</button>
|
||||
<b className="jc-tnav-n jc-mono">
|
||||
{openList.length === 0 ? 0 : pos + 1}/{openList.length}
|
||||
</b>
|
||||
<button
|
||||
type="button"
|
||||
className="jc-tnav-btn"
|
||||
disabled={pos >= openList.length - 1}
|
||||
onClick={() => setPage(pos + 1)}
|
||||
aria-label="下一件"
|
||||
>
|
||||
<Ico name="chevron-right" s={15} />
|
||||
</button>
|
||||
</span>
|
||||
/* 单卡多页时这对箭头翻**件里的页**(一颗芯片一页);多卡时照旧翻件 */
|
||||
docPages > 1 && openList.length <= 1 ? (
|
||||
<span className="jc-tnav-pg" aria-label="翻页">
|
||||
<button
|
||||
type="button"
|
||||
className="jc-tnav-btn"
|
||||
disabled={docPage === 0}
|
||||
onClick={() => setDocPage(docPage - 1)}
|
||||
aria-label="上一页"
|
||||
>
|
||||
<Ico name="chevron-left" s={15} />
|
||||
</button>
|
||||
<b className="jc-tnav-n jc-mono">
|
||||
{docPage + 1}/{docPages}
|
||||
</b>
|
||||
<button
|
||||
type="button"
|
||||
className="jc-tnav-btn"
|
||||
disabled={docPage >= docPages - 1}
|
||||
onClick={() => setDocPage(docPage + 1)}
|
||||
aria-label="下一页"
|
||||
>
|
||||
<Ico name="chevron-right" s={15} />
|
||||
</button>
|
||||
</span>
|
||||
) : (
|
||||
<span className="jc-tnav-pg" aria-label="翻页">
|
||||
<button
|
||||
type="button"
|
||||
className="jc-tnav-btn"
|
||||
disabled={pos === 0}
|
||||
onClick={() => setPage(pos - 1)}
|
||||
aria-label="上一件"
|
||||
>
|
||||
<Ico name="chevron-left" s={15} />
|
||||
</button>
|
||||
<b className="jc-tnav-n jc-mono">
|
||||
{openList.length === 0 ? 0 : pos + 1}/{openList.length}
|
||||
</b>
|
||||
<button
|
||||
type="button"
|
||||
className="jc-tnav-btn"
|
||||
disabled={pos >= openList.length - 1}
|
||||
onClick={() => setPage(pos + 1)}
|
||||
aria-label="下一件"
|
||||
>
|
||||
<Ico name="chevron-right" s={15} />
|
||||
</button>
|
||||
</span>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
@@ -416,12 +450,21 @@ export function ViewRegion({ detail, onReplyOrder, values, onField, locate }: Vi
|
||||
) : view === 'done' ? (
|
||||
doneItem !== undefined ? (
|
||||
/*
|
||||
* 定稿归档 = **同一份件,不加编辑态**(§9.3 第 2 条:在办与归档同一张模版)。
|
||||
* 与待处理那一屏一样,这里也只放件本身 —— 判据留在对话区那张办结卡上,
|
||||
* 归档之后「凭什么算过」比当时更常被问起,所以它跟着卡走,不跟着件走。
|
||||
* **定稿归档 = 办结那一刻的件快照,1:1 静态重放**(2026-08-02 用户:
|
||||
* 「HTML UI、数据、内容、布局都要 1:1 地从待处理状态转换为静态报告
|
||||
* 放到工作成果」—— 反复强调过)。
|
||||
*
|
||||
* 从前两条路都不对:验收单渲**当下**的任务视图(随后续推进还会变),
|
||||
* 执行单干脆退回 WorkOrderReport 卡壳(题头/编号带/blocks)——
|
||||
* 没有一样是人办结时看到的那份。现在办结那一刻基座把渲好的件
|
||||
* 存进工单(`finalHtml`),这里原样静态渲它;老单没有快照的,
|
||||
* 退最近一帧任务视图,再没有才退卡壳(历史兼容)。
|
||||
*/
|
||||
doneItem.mode === 'acceptance' && detail.viewHtml !== undefined ? (
|
||||
<ViewContainer html={detail.viewHtml} title={`${detail.card.activity} · 定稿报告`} />
|
||||
doneItem.finalHtml !== undefined || detail.viewHtml !== undefined ? (
|
||||
<ViewContainer
|
||||
html={doneItem.finalHtml ?? detail.viewHtml ?? ''}
|
||||
title={`${detail.card.activity} · 定稿报告`}
|
||||
/>
|
||||
) : (
|
||||
<article className="jc-mst-doc">
|
||||
<WorkOrderReport
|
||||
@@ -504,6 +547,8 @@ export function ViewRegion({ detail, onReplyOrder, values, onField, locate }: Vi
|
||||
<ViewContainer
|
||||
html={detail.viewHtml}
|
||||
title={`${detail.card.activity} · 汇报报告`}
|
||||
page={docPage}
|
||||
onPages={setDocPages}
|
||||
editable
|
||||
onEdits={(save) => {
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user