20260917212907

This commit is contained in:
oneao committed 2026-09-17 21:29:08 +08:00
1 parent 6fa3d8535e
commit 5cbf745bbf
115 files changed
+4104 -85

No files matched your search

@@ -0,0 +1,156 @@
/**
* 删除规则配置工具(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')
})
})