/** * 删除规则配置工具(module-management/ruleUtils): * 关系业务键拼串/还原、predicate 三态推断、识别文案、新增行构造、条件面板 items 构造。 */ import { describe, expect, it } from 'vitest' import { REF_RULE_HINT, buildRuleQueryItems, createRefRuleRow, createRuleRow, isCompleteRelationKey, itemMapOf, parseRelationScopeId, parseRulePredicate, relationScopeId, ruleLabel, ruleSummary, ruleTypeText, } from '@/views/module/module-management/ruleUtils' const relation = { b_source_module_id: 'order', b_source_field: 'b_id', b_target_module_id: 'order_item', b_target_field: 'b_order_id', } const fields = [ { b_field: 'b_status', b_name: '状态', b_type: 'select', b_canuse: 1 }, { b_field: 'b_amount', b_name: '金额', b_type: 'money', b_canuse: 1 }, { b_field: 'b_off', b_name: '停用字段', b_type: 'input', b_canuse: 0 }, ] describe('删除规则工具', () => { it('关系业务键与四列互逆', () => { expect(relationScopeId(relation)).toBe('order|b_id|order_item|b_order_id') expect(parseRelationScopeId('order|b_id|order_item|b_order_id')).toEqual({ sourceModuleId: 'order', sourceField: 'b_id', targetModuleId: 'order_item', targetField: 'b_order_id', }) expect(isCompleteRelationKey(relation)).toBe(true) expect(isCompleteRelationKey({ ...relation, b_target_field: null })).toBe(false) }) it('predicate 三态:空=引用、JSON=勾条件、其余=SQL(非法 JSON 降级为 SQL)', () => { expect(parseRulePredicate({ b_predicate: null }).kind).toBe('reference') expect(parseRulePredicate({ b_predicate: ' ' }).kind).toBe('reference') const dsl = parseRulePredicate({ b_predicate: JSON.stringify({ kind: 'dsl', expr: { type: 'group', children: [{ type: 'condition', field: 'b_status' }] }, }), }) expect(dsl.kind).toBe('dsl') expect(dsl.expr.children).toHaveLength(1) expect(parseRulePredicate({ b_predicate: 'select 1 where b_id in (:ids)' })).toMatchObject({ kind: 'sql', }) expect(parseRulePredicate({ b_predicate: '{不是合法 JSON' })).toMatchObject({ kind: 'sql' }) // JSON 合法但不是 dsl 形状:按 SQL 文本处理,内容不丢 expect(parseRulePredicate({ b_predicate: '{"foo":1}' })).toMatchObject({ kind: 'sql' }) }) it('类型文案与摘要:条件走中文描述、SQL 单行截断、引用固定说明', () => { const itemByField = itemMapOf(buildRuleQueryItems(fields, {})) const dslRow = { b_predicate: JSON.stringify({ kind: 'dsl', expr: { type: 'group', children: [{ type: 'condition', field: 'b_amount', operator: 'gt', value: 0 }], }, }), } expect(ruleTypeText(dslRow)).toBe('条件') expect(ruleSummary(dslRow, itemByField)).toBe('金额 大于 0') const sqlRow = { b_predicate: 'select\n b_id\nfrom bill where b_settled = 1' } expect(ruleTypeText(sqlRow)).toBe('SQL') expect(ruleSummary(sqlRow, itemByField)).toBe('select b_id from bill where b_settled = 1') const refRow = { b_predicate: null } expect(ruleTypeText(refRow)).toBe('引用') expect(ruleSummary(refRow, itemByField)).toBe(REF_RULE_HINT) }) it('识别文案:勾条件显示条件摘要,写 SQL 显示提示文案(缺文案退回 SQL 片段)', () => { const itemByField = itemMapOf(buildRuleQueryItems(fields, {})) const dslRow = { b_predicate: JSON.stringify({ kind: 'dsl', expr: { type: 'group', children: [{ type: 'condition', field: 'b_status', operator: 'eq', value: 'audit' }], }, }), } expect(ruleLabel(dslRow, itemByField)).toBe('状态 等于 audit') const sqlRow = { b_predicate: 'select 1 as b_id', b_message: '单据已销账,不能删除' } expect(ruleLabel(sqlRow, itemByField)).toBe('单据已销账,不能删除') expect(ruleLabel({ ...sqlRow, b_message: null }, itemByField)).toBe('select 1 as b_id') expect(ruleLabel({ b_predicate: null }, itemByField)).toBe(REF_RULE_HINT) }) it('新增行:主键由调用方取号传入,无名称/编码字段', () => { const rule = createRuleRow('order', { id: '1900000000000000001', xh: 30 }) expect(rule).toMatchObject({ b_id: '1900000000000000001', b_scope_type: 'module', b_scope_id: 'order', b_hook: 'delete.pre', b_predicate: null, b_canuse: 1, b_xh: 30, }) expect(rule.b_code).toBeUndefined() expect(rule.b_name).toBeUndefined() const ref = createRefRuleRow('order|b_id|order_item|b_order_id', '1900000000000000002') expect(ref).toMatchObject({ b_id: '1900000000000000002', b_scope_type: 'relation', b_scope_id: 'order|b_id|order_item|b_order_id', b_predicate: null, b_hook: 'delete.pre', }) }) it('items 构造:只列启用字段,类型映射控件,select 缺选项时降级为输入', () => { const items = buildRuleQueryItems(fields, { groups: [ { conditions: [ { field: 'b_status', operator: 'in', component: 'select', options: [{ value: 'a' }] }, ], }, ], }) expect(items.map((item) => item.field.b_field)).toEqual(['b_status', 'b_amount']) // 查询配置里定义过:沿用其操作符/控件/选项 expect(items[0].config).toMatchObject({ b_operator: 'in', b_component: 'select' }) expect(items[0].options).toEqual([{ value: 'a', label: 'a' }]) // 未定义过:按字段类型推导(金额 → 数字输入) expect(items[1].config.b_component).toBe('number') expect(items[1].config.b_operator).toBe('eq') }) })