Archived
fix(w05): 评估输入清单两条 Critical 回归 —— 主键丢钥匙、必填填不了
定向复审发现上一轮模版重做(00133c2)新引入两条回归,都出在 sub_eval.input_gap 的缺口表:
- item_key 那格丢了 data-col:一单 11 行,item_key 逐行不同,服务端 resolveRowKey 既在件上
找不到它、又不是「全表一致」的案号型列(那条路只对 caseKey 成立),人保存任何一行都会
「认不出它是哪一行」。补回 <span data-col="item_key">,并把「加一行」提示补上「键必须填」。
- status 声明 required:true,又给了「加一行」,却被降成只读徽标——人新加的行永远没有格子
填这一列,_missing 恒正、提交闸永远拦着(墙不配路)。改回 E04 执行回执同款的混排:
<select class="jc-cell" data-col="status"> 挨着 <span data-class-of="status"> 徽标,
只读徽标不裹 .jc-vcell(它没有孪生件),编辑态天然不被 :has(+ .jc-cell) 那条规则藏起来,
不用动 BIND_CSS。
自查确认另两张可编辑件(parts.profile 的 internal_pn、parts.document 的 internal_pn+doc_seq)
的主键 data-col 本就都在,不是这次回归的范围。
补两条回归网(新 describe「可编辑件的主键与必填列」):①三张可编辑件每个非 caseKey 的主键列
都有 data-col;②每个 required:true 且落在可编辑件上的列都有 data-col。两条从
manifest.declarations.ledger 现读,不是照抄字面值,以后同类回归会自动变红。
P08_CSS 的「空行」复审点:重新用 hexdump 核对源文件 `ACT-WORK-05-数据工单-01-芯片主数据
创建.html` 第 86-89 行(两个 <style> 标签接缝),字节层面确认原文没有空行
(`...border-color:var(--line)}\n.tbl-gap{...}\n</style>\n<style>\n/* ===== 视觉补充段...`,
中间没有任何空行或隐藏字符);target-style.ts 的 P08_CSS 与该区间逐字节相同(Python diff
再次核验,长度 7531 完全一致)。没有改动这段内容——加一行会让它偏离已验证正确的源文件,
详见报告里贴的十六进制证据。
升版本号 1.1.0 → 1.1.1;pnpm activities:install 已验证装包成功。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
* ACT-WORK-05 差异评估的包内自测 —— **只准 import @sdk / @contracts / @sfeel**。
|
||||
* 案例活动没有 `run`,自测不跑回合;测的是清单本身与授权面对齐,结构照 E04 / I01。
|
||||
*
|
||||
* 六组:清单本身合规 / 台账声明 / 案例模型与清单的对齐 / 报告模版:编辑面与只读面各就各位 /
|
||||
* 徽标别名与值域相关的坑(2026-08-27 实测账,回归网)/ 活动入口。
|
||||
* 七组:清单本身合规 / 台账声明 / 案例模型与清单的对齐 / 报告模版:编辑面与只读面各就各位 /
|
||||
* 徽标别名与值域相关的坑(2026-08-27 实测账,回归网)/ 可编辑件的主键与必填列
|
||||
* (2026-08-27 复审,回归网)/ 活动入口。
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { activityManifestSchema } from '@contracts';
|
||||
@@ -304,6 +305,56 @@ describe('徽标别名与值域相关的坑(2026-08-27 实测账,回归网)', ()
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* 2026-08-27 定向复审逮住的两条 Critical(都是这一轮版面重做新引入的回归,不是原有的坑):
|
||||
* ① `sub_eval.input_gap` 的「键」(`item_key`)那一格丢了 `data-col` —— 一单 11 行,`item_key`
|
||||
* 逐行不同,人保存**任何一行**时服务端 `resolveRowKey` 凑不出主键(它既不在件上、
|
||||
* 又不是「全表一致」的那种案号型列),整格落不下去;
|
||||
* ② `sub_eval.input_gap.status` 声明 `required: true`,件上又有「+ 加一行」——
|
||||
* 降成只读徽标后,人新加的行永远没有格子能把这一列填上,`_missing` 恒为正、
|
||||
* 提交闸永远拦着,这是「墙不配路」的死路形态。
|
||||
* 两条各配一张回归网,防的是同一类事故再出现在别的字段上。
|
||||
*/
|
||||
describe('可编辑件的主键与必填列(2026-08-27 复审:主键丢钥匙 / 必填填不了,两条 Critical 回归)', () => {
|
||||
/** 三张真能编辑的件与它们各自绑定的台账对象 */
|
||||
const EDITABLE: ReadonlyArray<{ view: string; domain: string; object: string }> = [
|
||||
{ view: 'p08-master-create', domain: 'parts', object: 'profile' },
|
||||
{ view: 'p10-document-create', domain: 'parts', object: 'document' },
|
||||
{ view: 'eval-input-list', domain: D, object: 'input_gap' },
|
||||
];
|
||||
|
||||
it('每一个主键列都有 data-col —— 它不是编辑面,是行的钥匙,丢了就整行保存不下去', () => {
|
||||
for (const { view, domain, object } of EDITABLE) {
|
||||
const table = byAddress(domain, object);
|
||||
/*
|
||||
* `caseKey` 声明的那一列(如 `eval_ref`)是例外:它是「一单一号,全表当然一致」的
|
||||
* 案号型主键(与 I01 的 `round_ref` 同款),件上压根不摆,服务端 `resolveRowKey`
|
||||
* 按「全表一致」自动补上(`apps/api/src/app/routes/desk.ts` 注释里点名的那条路)——
|
||||
* 摆出来给人填反而是错的(那会让人以为能按行改案号)。真正逐行不同、必须挂
|
||||
* `data-col` 的,是主键里除 caseKey 之外的那几列(如 `item_key`)。
|
||||
*/
|
||||
const pk = (table?.fields.filter((f) => f.primaryKey).map((f) => f.name) ?? []).filter((name) => name !== table?.caseKey);
|
||||
expect(pk.length, `${domain}.${object} 没有非 caseKey 的主键列`).toBeGreaterThan(0);
|
||||
const html = viewHtml(view);
|
||||
for (const col of pk) {
|
||||
expect(html, `${view}: 主键列 ${domain}.${object}.${col} 缺 data-col`).toContain(`data-col="${col}"`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('可编辑件上,每一个 required:true 的列都有真能填的控件(data-col)—— 必填但填不了是墙不配路', () => {
|
||||
for (const { view, domain, object } of EDITABLE) {
|
||||
const table = byAddress(domain, object);
|
||||
const required = table?.fields.filter((f) => f.required === true).map((f) => f.name) ?? [];
|
||||
expect(required.length, `${domain}.${object} 没有声明 required 列`).toBeGreaterThan(0);
|
||||
const html = viewHtml(view);
|
||||
for (const col of required) {
|
||||
expect(html, `${view}: 必填列 ${domain}.${object}.${col} 没有可填的控件`).toContain(`data-col="${col}"`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('活动入口', () => {
|
||||
it('没有 run —— 行为全在清单里', () => {
|
||||
expect(activity.run).toBeUndefined();
|
||||
|
||||
Reference in New Issue
Block a user