diff --git a/activities/part-substitution-assessment/__tests__/activity.test.ts b/activities/part-substitution-assessment/__tests__/activity.test.ts index ca4c786..e030158 100644 --- a/activities/part-substitution-assessment/__tests__/activity.test.ts +++ b/activities/part-substitution-assessment/__tests__/activity.test.ts @@ -801,6 +801,12 @@ describe('件① 评估输入补全', () => { * 类似还差 1 行必填没填这种提示」—— 逐块 gapbar 撤下,点名并进顶条(同一批基座读数, * 数值 0 的那行由样式表自己收起来)。 */ + it('都齐了红条整条收起:开关是案卷真数据 gate_state(v-clear),不看那句话空不空', () => { + expect(html).toContain('class="jc-gate-bar" data-class-of="gate_state"'); + expect(html).toContain('.jc-gate-bar.v-clear{display:none}'); + expect(colOf('sub_eval.case', 'gate_state')?.tally).toEqual(['open', 'clear']); + }); + it('缺项点名全并进顶条「还差什么」,正文不再有逐块红带', () => { expect(html).toContain('class="jc-gate-sub" data-class-of="parts_profile_missing"'); expect(html).toContain('data-slot="parts_profile_missing_keys"'); diff --git a/activities/part-substitution-assessment/__tests__/steps.test.ts b/activities/part-substitution-assessment/__tests__/steps.test.ts index 9451424..24d06de 100644 --- a/activities/part-substitution-assessment/__tests__/steps.test.ts +++ b/activities/part-substitution-assessment/__tests__/steps.test.ts @@ -251,6 +251,16 @@ describe('S1 配方', () => { expect((card?.kind === 'card' ? card.guide ?? [] : []).length).toBeGreaterThanOrEqual(3); }); + it('红条开关 gate_state 与发卡条件同一句判定(一处真源)—— gate_reason 清空不落笔,开关列两个方向都真写', () => { + const kase = acts[3]; + const fields = kase?.kind === 'project' ? kase.fields : undefined; + const gs = fields?.['gate_state'] as { when?: string; then?: string; else?: string } | undefined; + const card = acts[4]; + expect(gs?.then).toBe('open'); + expect(gs?.else).toBe('clear'); + expect(card?.kind === 'card' && card.when).toBe(gs?.when); + }); + it('发卡条件与 doneWhen 是同一件事的正反面', () => { const when = acts[4]?.kind === 'card' ? (acts[4].when ?? '') : ''; for (const reading of [ diff --git a/activities/part-substitution-assessment/src/case-model.ts b/activities/part-substitution-assessment/src/case-model.ts index 42f7872..df1dbfd 100644 --- a/activities/part-substitution-assessment/src/case-model.ts +++ b/activities/part-substitution-assessment/src/case-model.ts @@ -330,6 +330,14 @@ const VALIDATION_PROJECTION = { * 两处不给 `doneWhen`:`S3_review`(人拍板且可循环)、`T_release`(签下去)—— * 判据不许摆在还欠一张卡的那一步眼前(会诱使它去凑判据,2026-08-28 用户实测逼出的立墙)。 */ +/** + * 「输入还差东西」的判定 —— 发卡条件与案卷 `gate_state` 共用同一句(一处真源): + * 条件只用基座读数(gate_reason 为空串时那一列压根不写、未绑定名参与比较会翻车)。 + */ +const GATE_OPEN_WHEN = + 'sub_eval_part_exists_status_found < 2 or sub_eval_part_missing > 0 or ' + + 'sub_eval_part_distinct_chip_type_id > 1 or parts_profile_missing > 0 or parts_parameter_missing > 0'; + export const ASSESSMENT_STEPS = [ { item: 'S1_inputs' as const, @@ -488,6 +496,11 @@ export const ASSESSMENT_STEPS = [ fields: { eval_ref: { in: 'evalRef' }, chip_type_id: { lookup: 'mine:sub_eval.part', by: { role: 'original' }, take: 'chip_type_id', else: '' }, + /* + * 红条的开关(2026-08-31):gate_reason 清空时按列归型不落笔(旧话留在草稿里), + * 这面开关两个值都非空、两个方向都真写 —— 件上按它收红条,与发卡条件同一句判定。 + */ + gate_state: { when: GATE_OPEN_WHEN, then: 'open', else: 'clear' }, gate_reason: { when: 'sub_eval_part_rows < 2', then: '原料号与候选料号填成了同一个 —— 没法比出差异,请终止本单,换两个不同的料号重开。', @@ -518,9 +531,7 @@ export const ASSESSMENT_STEPS = [ */ { kind: 'card' as const, - when: - 'sub_eval_part_exists_status_found < 2 or sub_eval_part_missing > 0 or ' + - 'sub_eval_part_distinct_chip_type_id > 1 or parts_profile_missing > 0 or parts_parameter_missing > 0', + when: GATE_OPEN_WHEN, as: 'execution' as const, variant: 'data' as const, title: '数据工单 · 差异评估的输入还差几格', diff --git a/activities/part-substitution-assessment/src/manifest.ts b/activities/part-substitution-assessment/src/manifest.ts index 5d771f8..31983f8 100644 --- a/activities/part-substitution-assessment/src/manifest.ts +++ b/activities/part-substitution-assessment/src/manifest.ts @@ -54,7 +54,7 @@ export const manifest: ActivityManifest = { activityId: ACTIVITY_ID, name: 'ACT-WORK-05 · 差异评估', /* 重写不是改 —— 同版重装是 no-op(静默丢失,踩过) */ - packageVersion: '2.12.1', + packageVersion: '2.13.0', category: '需求分析与方案匹配', sdkVersion: '0.1.0-m5', checksum: 'dev-checksum-part-substitution-assessment', @@ -431,6 +431,13 @@ export const manifest: ActivityManifest = { /* 与 `parts.chip_type.type_id` 同一条身份链路,同一个理由改成 text —— 见该字段的大注释 */ col({ name: 'chip_type_id', type: 'text', label: '本单锁定的芯片类型' }), col({ name: 'gate_reason', type: 'text', label: '入参未就绪原因(件上摆的就是它)' }), + /* + * **红条的开关是真数据,不是那句话空不空**(2026-08-31 用户:「没有必填要警告了, + * 红色区域就不要显示」):gate_reason 清成空串时按列归型**不落笔**(空值=不写这一列, + * jsonb 合并保旧值)—— 那句话一旦写下就清不掉,红条永远亮着。开关列两个值都非空, + * 两个方向都写得动;件上 data-class-of 投影 v-clear 收红条,判断留在样式表。 + */ + col({ name: 'gate_state', type: 'text', label: '入参闸门状态', tally: ['open', 'clear'] }), col({ name: 'summary', type: 'text', label: '结论摘要' }), ], }, diff --git a/activities/part-substitution-assessment/src/views/report.ts b/activities/part-substitution-assessment/src/views/report.ts index e382afe..7eaeffd 100644 --- a/activities/part-substitution-assessment/src/views/report.ts +++ b/activities/part-substitution-assessment/src/views/report.ts @@ -98,7 +98,7 @@ const optionSelect = (col: string, address: string, valueCol: string, labelCol: * `classToken` 在它上面永远算不出 v-token;显隐靠 `.jc-gate-text` 的 `data-blank` + * CSS `:has(:empty)`(规则在 SHELL_CSS,包内测试钉着)。 */ -const gateBar = (): string => `
+const gateBar = (): string => `
还差什么 —— 主数据还差 行必填 —— 参数值还差 行必填 —— diff --git a/activities/part-substitution-assessment/src/views/style.ts b/activities/part-substitution-assessment/src/views/style.ts index 3e4fd0e..1d58e25 100644 --- a/activities/part-substitution-assessment/src/views/style.ts +++ b/activities/part-substitution-assessment/src/views/style.ts @@ -149,6 +149,9 @@ i{font-style:normal} .jc-gate-bar{display:flex;flex-direction:column;gap:5px;margin:0 0 16px;padding:11px 14px;border-radius:10px;background:var(--danger-soft);border:1px solid #f5c0ba;color:var(--danger);font-size:12.5px;line-height:1.7} .jc-gate-bar b{font-weight:800} .jc-gate-bar:has(.jc-gate-text:empty){display:none} +/* 都齐了就整条收起(2026-08-31 用户定)—— 开关是案卷真数据 gate_state(v-clear), + 不看那句话空不空:gate_reason 清空时按列归型不落笔,旧话会一直留在草稿里 */ +.jc-gate-bar.v-clear{display:none} /* 逐块的缺项点名并进这一条(2026-08-31 用户:「页面上所有的问题都合并到最上面的还差什么」)—— 与提交闸同源的基座读数,数值为 0 的那一行自己消失,只在待处理态出现 */ .jc-gate-sub{display:none;font-size:12px;color:#a03d34;padding-left:2px}