Archived
契约:launchOption 加 group/groupLabel(x-options.group 从字典表现读人读名)、 launchParam 加 linkGroup(x-link 结组);api-report 已随 --update 入库。 前端 launch-link.ts 纯函数管三条口径:锚摆全量、其余按锚的分组键收窄 (未标类型殿后一组,新增照走);锚粘着 —— 清空只解除收窄不换锚,人改得了主意。 服务端不据此立墙:combo 本就收候选之外的值,类型一致归 S1 收步判据 sub_eval_part_distinct_chip_type_id = 1(数得出来的门)。 W05 清单两格挂上 x-link: chip-type;文档同步。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -208,3 +208,88 @@ describe('validateLaunchParams', () => {
|
||||
expect(nan.ok).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
/* ── 按分组键联动(2026-08-31 用户定:原料号 / 候选料号按芯片类型互相收窄)────────────
|
||||
派生层只负责把两样东西送到前端:①候选带上它的分组键与人读名(`x-options.group`);
|
||||
②这一格属于哪个联动组(`x-link`)。收窄怎么摆是前端的事,**服务端不据此立墙**。 */
|
||||
describe('x-options.group / x-link', () => {
|
||||
const LINKED = {
|
||||
type: 'object',
|
||||
required: ['originalInternalPn', 'candidateInternalPn'],
|
||||
properties: {
|
||||
originalInternalPn: {
|
||||
type: 'string',
|
||||
title: '原内部料号',
|
||||
'x-control': 'combo',
|
||||
'x-options': {
|
||||
ledger: 'parts.profile',
|
||||
value: 'internal_pn',
|
||||
label: 'internal_pn',
|
||||
group: { column: 'chip_type_id', ledger: 'parts.chip_type', value: 'type_id', label: 'type_name' },
|
||||
},
|
||||
'x-link': 'chip-type',
|
||||
'x-order': 1,
|
||||
},
|
||||
candidateInternalPn: {
|
||||
type: 'string',
|
||||
title: '候选内部料号',
|
||||
'x-control': 'combo',
|
||||
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn', group: 'chip_type_id' },
|
||||
'x-link': 'chip-type',
|
||||
'x-order': 2,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('分组键两种写法都认:整份声明(带字典)与只写列名;x-link 读成联动组名', () => {
|
||||
const specs = fieldSpecsOf(LINKED);
|
||||
expect(specs[0]?.optionsSource?.group).toEqual({ column: 'chip_type_id', dict: { ledger: 'parts.chip_type', value: 'type_id', label: 'type_name' } });
|
||||
// 只写列名 = 有分组键、没有人读名字典
|
||||
expect(specs[1]?.optionsSource?.group).toEqual({ column: 'chip_type_id', dict: undefined });
|
||||
expect(specs.map((s) => s.linkGroup)).toEqual(['chip-type', 'chip-type']);
|
||||
});
|
||||
|
||||
it('分组键写残(没有 column,或字典缺 ledger/value)就当没声明 —— 候选照出,只是不联动', () => {
|
||||
const bad = fieldSpecsOf({
|
||||
properties: {
|
||||
a: { type: 'string', 'x-control': 'combo', 'x-options': { ledger: 'l.o', value: 'v', group: {} } },
|
||||
b: { type: 'string', 'x-control': 'combo', 'x-options': { ledger: 'l.o', value: 'v', group: { column: 'c', ledger: 'd.t' } } },
|
||||
},
|
||||
});
|
||||
expect(bad[0]?.optionsSource).toEqual({ ledger: 'l.o', value: 'v', label: 'v', group: undefined });
|
||||
// 字典写残 → 只留分组键,人读名没有(不炸)
|
||||
expect(bad[1]?.optionsSource?.group).toEqual({ column: 'c', dict: undefined });
|
||||
});
|
||||
|
||||
it('候选带 group / groupLabel 原样交给前端;有候选才给 linkGroup(一个候选都没有,联动无从谈起)', async () => {
|
||||
const params = await launchParamsOf(LINKED, async (src) =>
|
||||
src.group === undefined
|
||||
? [{ value: 'AMS1117-3.3', label: 'AMS1117-3.3' }]
|
||||
: [
|
||||
{ value: 'LM2596S-5.0', label: 'LM2596S-5.0', group: '1', groupLabel: 'DC-DC 降压稳压器' },
|
||||
{ value: 'OLD-001', label: 'OLD-001', group: '' },
|
||||
],
|
||||
);
|
||||
expect(params[0]).toMatchObject({
|
||||
key: 'originalInternalPn',
|
||||
linkGroup: 'chip-type',
|
||||
options: [
|
||||
{ value: 'LM2596S-5.0', label: 'LM2596S-5.0', group: '1', groupLabel: 'DC-DC 降压稳压器' },
|
||||
{ value: 'OLD-001', label: 'OLD-001', group: '' },
|
||||
],
|
||||
});
|
||||
// 候选读不到 → 仍是 combo,但不摆联动组(前端没有可收窄的东西)
|
||||
const empty = await launchParamsOf(LINKED, noResolve);
|
||||
expect(empty[0]?.linkGroup).toBeUndefined();
|
||||
expect(empty[0]?.type).toBe('combo');
|
||||
});
|
||||
|
||||
it('服务端不据分组立墙:两格填不同类型的料号照样收(类型一致归活动的收步判据管)', async () => {
|
||||
const params = await launchParamsOf(LINKED, async () => [
|
||||
{ value: 'LM2596S-5.0', label: 'LM2596S-5.0', group: '1' },
|
||||
{ value: 'AMS1117-3.3', label: 'AMS1117-3.3', group: '2' },
|
||||
]);
|
||||
const out = validateLaunchParams(params, { originalInternalPn: 'LM2596S-5.0', candidateInternalPn: 'AMS1117-3.3' }, fieldSpecsOf(LINKED));
|
||||
expect(out).toEqual({ ok: true, data: { originalInternalPn: 'LM2596S-5.0', candidateInternalPn: 'AMS1117-3.3' } });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user