Archived
fix(w05): 都齐了红条整条收起 —— 开关是案卷真数据 gate_state,不看那句话空不空
2026-08-31 用户:「没有必填字段不需要警告了,还差什么这个红色区域就不要显示」。 病根在一层机制之下:配方把 gate_reason 清成空串时,**空值按列归型不落笔** (jsonb 合并保旧值)—— 那句话一旦写下就永远清不掉,红条亮过就灭不了。 治法:案卷加开关列 gate_state(tally open/clear,两个值都非空、两个方向都真写), 与发卡条件共用同一句判定(GATE_OPEN_WHEN 一处真源);红条挂 data-class-of=gate_state, v-clear 整条收起(判断留在样式表);人补齐最后一格保存,quiet 拍照跑 project、 重推件,红条当场消失。空文本 :has(:empty) 兜底保留(首拍还没写过的形)。 107 包内(开关双向 + 一处真源两锚,else 侧变异红过)+ 定向 1109 测; 2.13.0 装库核过(开关/CSS/else=clear)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -801,6 +801,12 @@ describe('件① 评估输入补全', () => {
|
|||||||
* 类似还差 1 行必填没填这种提示」—— 逐块 gapbar 撤下,点名并进顶条(同一批基座读数,
|
* 类似还差 1 行必填没填这种提示」—— 逐块 gapbar 撤下,点名并进顶条(同一批基座读数,
|
||||||
* 数值 0 的那行由样式表自己收起来)。
|
* 数值 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('缺项点名全并进顶条「还差什么」,正文不再有逐块红带', () => {
|
it('缺项点名全并进顶条「还差什么」,正文不再有逐块红带', () => {
|
||||||
expect(html).toContain('class="jc-gate-sub" data-class-of="parts_profile_missing"');
|
expect(html).toContain('class="jc-gate-sub" data-class-of="parts_profile_missing"');
|
||||||
expect(html).toContain('data-slot="parts_profile_missing_keys"');
|
expect(html).toContain('data-slot="parts_profile_missing_keys"');
|
||||||
|
|||||||
@@ -251,6 +251,16 @@ describe('S1 配方', () => {
|
|||||||
expect((card?.kind === 'card' ? card.guide ?? [] : []).length).toBeGreaterThanOrEqual(3);
|
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 是同一件事的正反面', () => {
|
it('发卡条件与 doneWhen 是同一件事的正反面', () => {
|
||||||
const when = acts[4]?.kind === 'card' ? (acts[4].when ?? '') : '';
|
const when = acts[4]?.kind === 'card' ? (acts[4].when ?? '') : '';
|
||||||
for (const reading of [
|
for (const reading of [
|
||||||
|
|||||||
@@ -330,6 +330,14 @@ const VALIDATION_PROJECTION = {
|
|||||||
* 两处不给 `doneWhen`:`S3_review`(人拍板且可循环)、`T_release`(签下去)——
|
* 两处不给 `doneWhen`:`S3_review`(人拍板且可循环)、`T_release`(签下去)——
|
||||||
* 判据不许摆在还欠一张卡的那一步眼前(会诱使它去凑判据,2026-08-28 用户实测逼出的立墙)。
|
* 判据不许摆在还欠一张卡的那一步眼前(会诱使它去凑判据,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 = [
|
export const ASSESSMENT_STEPS = [
|
||||||
{
|
{
|
||||||
item: 'S1_inputs' as const,
|
item: 'S1_inputs' as const,
|
||||||
@@ -488,6 +496,11 @@ export const ASSESSMENT_STEPS = [
|
|||||||
fields: {
|
fields: {
|
||||||
eval_ref: { in: 'evalRef' },
|
eval_ref: { in: 'evalRef' },
|
||||||
chip_type_id: { lookup: 'mine:sub_eval.part', by: { role: 'original' }, take: 'chip_type_id', else: '' },
|
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: {
|
gate_reason: {
|
||||||
when: 'sub_eval_part_rows < 2',
|
when: 'sub_eval_part_rows < 2',
|
||||||
then: '原料号与候选料号填成了同一个 —— 没法比出差异,请终止本单,换两个不同的料号重开。',
|
then: '原料号与候选料号填成了同一个 —— 没法比出差异,请终止本单,换两个不同的料号重开。',
|
||||||
@@ -518,9 +531,7 @@ export const ASSESSMENT_STEPS = [
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
kind: 'card' as const,
|
kind: 'card' as const,
|
||||||
when:
|
when: 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',
|
|
||||||
as: 'execution' as const,
|
as: 'execution' as const,
|
||||||
variant: 'data' as const,
|
variant: 'data' as const,
|
||||||
title: '数据工单 · 差异评估的输入还差几格',
|
title: '数据工单 · 差异评估的输入还差几格',
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const manifest: ActivityManifest = {
|
|||||||
activityId: ACTIVITY_ID,
|
activityId: ACTIVITY_ID,
|
||||||
name: 'ACT-WORK-05 · 差异评估',
|
name: 'ACT-WORK-05 · 差异评估',
|
||||||
/* 重写不是改 —— 同版重装是 no-op(静默丢失,踩过) */
|
/* 重写不是改 —— 同版重装是 no-op(静默丢失,踩过) */
|
||||||
packageVersion: '2.12.1',
|
packageVersion: '2.13.0',
|
||||||
category: '需求分析与方案匹配',
|
category: '需求分析与方案匹配',
|
||||||
sdkVersion: '0.1.0-m5',
|
sdkVersion: '0.1.0-m5',
|
||||||
checksum: 'dev-checksum-part-substitution-assessment',
|
checksum: 'dev-checksum-part-substitution-assessment',
|
||||||
@@ -431,6 +431,13 @@ export const manifest: ActivityManifest = {
|
|||||||
/* 与 `parts.chip_type.type_id` 同一条身份链路,同一个理由改成 text —— 见该字段的大注释 */
|
/* 与 `parts.chip_type.type_id` 同一条身份链路,同一个理由改成 text —— 见该字段的大注释 */
|
||||||
col({ name: 'chip_type_id', type: 'text', label: '本单锁定的芯片类型' }),
|
col({ name: 'chip_type_id', type: 'text', label: '本单锁定的芯片类型' }),
|
||||||
col({ name: 'gate_reason', 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: '结论摘要' }),
|
col({ name: 'summary', type: 'text', label: '结论摘要' }),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ const optionSelect = (col: string, address: string, valueCol: string, labelCol:
|
|||||||
* `classToken` 在它上面永远算不出 v-token;显隐靠 `.jc-gate-text` 的 `data-blank` +
|
* `classToken` 在它上面永远算不出 v-token;显隐靠 `.jc-gate-text` 的 `data-blank` +
|
||||||
* CSS `:has(:empty)`(规则在 SHELL_CSS,包内测试钉着)。
|
* CSS `:has(:empty)`(规则在 SHELL_CSS,包内测试钉着)。
|
||||||
*/
|
*/
|
||||||
const gateBar = (): string => `<div class="jc-gate-bar">
|
const gateBar = (): string => `<div class="jc-gate-bar" data-class-of="gate_state">
|
||||||
<span><b>还差什么</b> —— <span class="jc-gate-text" data-slot="gate_reason" data-blank></span></span>
|
<span><b>还差什么</b> —— <span class="jc-gate-text" data-slot="gate_reason" data-blank></span></span>
|
||||||
<span class="jc-gate-sub" data-class-of="parts_profile_missing">主数据还差 <b data-slot="parts_profile_missing"></b> 行必填 —— <span data-slot="parts_profile_missing_keys"></span></span>
|
<span class="jc-gate-sub" data-class-of="parts_profile_missing">主数据还差 <b data-slot="parts_profile_missing"></b> 行必填 —— <span data-slot="parts_profile_missing_keys"></span></span>
|
||||||
<span class="jc-gate-sub" data-class-of="parts_parameter_missing">参数值还差 <b data-slot="parts_parameter_missing"></b> 行必填 —— <span data-slot="parts_parameter_missing_keys"></span></span>
|
<span class="jc-gate-sub" data-class-of="parts_parameter_missing">参数值还差 <b data-slot="parts_parameter_missing"></b> 行必填 —— <span data-slot="parts_parameter_missing_keys"></span></span>
|
||||||
|
|||||||
@@ -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{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 b{font-weight:800}
|
||||||
.jc-gate-bar:has(.jc-gate-text:empty){display:none}
|
.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 用户:「页面上所有的问题都合并到最上面的还差什么」)——
|
/* 逐块的缺项点名并进这一条(2026-08-31 用户:「页面上所有的问题都合并到最上面的还差什么」)——
|
||||||
与提交闸同源的基座读数,数值为 0 的那一行自己消失,只在待处理态出现 */
|
与提交闸同源的基座读数,数值为 0 的那一行自己消失,只在待处理态出现 */
|
||||||
.jc-gate-sub{display:none;font-size:12px;color:#a03d34;padding-left:2px}
|
.jc-gate-sub{display:none;font-size:12px;color:#a03d34;padding-left:2px}
|
||||||
|
|||||||
Reference in New Issue
Block a user