@zeng-alt/vue-spel-query-builder 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +163 -0
- package/dist/assets/vue-spel-query-builder.css +480 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.cjs +3111 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.esm +3095 -0
- package/dist/index.esm.map +1 -0
- package/dist/src/components/RuleTree/ExpressionEditor.vue.d.ts +23 -0
- package/dist/src/components/RuleTree/RuleTree.vue.d.ts +13 -0
- package/dist/src/components/RuleTree/RuleTreeNode.vue.d.ts +27 -0
- package/dist/src/components/SpelEditor/SpelEditor.vue.d.ts +17 -0
- package/dist/src/components/SpelEditor/spel-autocomplete-ext.d.ts +7 -0
- package/dist/src/components/SpelEditor/spel-autocomplete-style.d.ts +10 -0
- package/dist/src/components/SpelEditor/spel-autocomplete-tooltip.d.ts +2 -0
- package/dist/src/components/SpelEditor/spel-completions.d.ts +9 -0
- package/dist/src/components/SpelEditor/spel-parser.d.ts +8 -0
- package/dist/src/components/SpelEditor/spel-theme.d.ts +15 -0
- package/dist/src/components/SpelEditor/spel-types.d.ts +92 -0
- package/dist/src/components/index.d.ts +3 -0
- package/dist/src/composables/index.d.ts +2 -0
- package/dist/src/composables/useRuleTree.d.ts +11 -0
- package/dist/src/composables/useSpelEditor.d.ts +23 -0
- package/dist/src/constants/index.d.ts +9 -0
- package/dist/src/index.d.ts +6 -0
- package/dist/src/spel-service.d.ts +9 -0
- package/dist/src/types/index.d.ts +108 -0
- package/dist/src/utils/index.d.ts +26 -0
- package/package.json +107 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["s","l","m","f","d","p","g","b","$emit"],"sources":["../src/spel-service.ts","../node_modules/.pnpm/vue-codemirror@6.1.1_codemirror@6.0.2_vue@3.5.34_typescript@6.0.3_/node_modules/vue-codemirror/dist/vue-codemirror.esm.js","../src/utils/index.ts","../src/composables/useSpelEditor.ts","../src/composables/useRuleTree.ts","../src/components/SpelEditor/spel-theme.ts","../src/components/SpelEditor/spel-completions.ts","../src/components/SpelEditor/spel-autocomplete-style.ts","../src/components/SpelEditor/spel-parser.ts","../src/components/SpelEditor/spel-autocomplete-tooltip.ts","../src/components/SpelEditor/spel-autocomplete-ext.ts","../src/components/SpelEditor/SpelEditor.vue","../src/components/SpelEditor/SpelEditor.vue","../src/components/RuleTree/ExpressionEditor.vue","../src/components/RuleTree/ExpressionEditor.vue","../src/components/RuleTree/RuleTreeNode.vue","../src/components/RuleTree/RuleTreeNode.vue","../src/components/RuleTree/RuleTree.vue","../src/components/RuleTree/RuleTree.vue","../src/constants/index.ts"],"sourcesContent":["import { StandardContext, SpelExpressionEvaluator } from 'spel2js'\n\n// wraps spel2js in a stateful service that simplifies evaluation\nclass SpelService {\n private context: any = null\n\n setContext(authentication?: any, principal?: any) {\n this.context = StandardContext.create(authentication, principal)\n }\n\n getContext() {\n return this.context\n }\n\n compile(expression: string) {\n return SpelExpressionEvaluator.compile(expression)\n }\n\n eval(expression: string, locals?: Record<string, any>) {\n return SpelExpressionEvaluator.eval(expression, this.getContext(), locals)\n }\n}\n\nexport const spelService = new SpelService()\n","/*!\n* VueCodemirror v6.1.1\n* Copyright (c) Surmon. All rights reserved.\n* Released under the MIT License.\n* Surmon\n*/\nimport{inject as e,defineComponent as t,shallowRef as n,computed as o,toRaw as r,onMounted as u,watch as a,onBeforeUnmount as i,h as c}from\"vue\";import{basicSetup as s}from\"codemirror\";import{EditorState as l,Compartment as f,StateEffect as d}from\"@codemirror/state\";import{EditorView as m,keymap as p,placeholder as v}from\"@codemirror/view\";import{indentWithTab as g}from\"@codemirror/commands\";import{indentUnit as b}from\"@codemirror/language\";var h=Object.freeze({autofocus:!1,disabled:!1,indentWithTab:!0,tabSize:2,placeholder:\"\",autoDestroy:!0,extensions:[s]}),y=Symbol(\"vue-codemirror-global-config\");var O,j=function(e){var t=e.onUpdate,n=e.onChange,o=e.onFocus,r=e.onBlur,u=function(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(null!=e&&\"function\"==typeof Object.getOwnPropertySymbols){var r=0;for(o=Object.getOwnPropertySymbols(e);r<o.length;r++)t.indexOf(o[r])<0&&Object.prototype.propertyIsEnumerable.call(e,o[r])&&(n[o[r]]=e[o[r]])}return n}(e,[\"onUpdate\",\"onChange\",\"onFocus\",\"onBlur\"]);return l.create({doc:u.doc,selection:u.selection,extensions:(Array.isArray(u.extensions)?u.extensions:[u.extensions]).concat([m.updateListener.of((function(e){t(e),e.docChanged&&n(e.state.doc.toString(),e),e.focusChanged&&(e.view.hasFocus?o(e):r(e))}))])})},S=function(e){var t=new f;return{compartment:t,run:function(n){t.get(e.state)?e.dispatch({effects:t.reconfigure(n)}):e.dispatch({effects:d.appendConfig.of(t.of(n))})}}},x=function(e,t){var n=S(e),o=n.compartment,r=n.run;return function(n){var u=o.get(e.state);r((null!=n?n:u!==t)?t:[])}},C={type:Boolean,default:void 0},D={autofocus:C,disabled:C,indentWithTab:C,tabSize:Number,placeholder:String,style:Object,autoDestroy:C,phrases:Object,root:Object,extensions:Array,selection:Object},U={modelValue:{type:String,default:\"\"}},w=Object.assign(Object.assign({},D),U);!function(e){e.Change=\"change\",e.Update=\"update\",e.Focus=\"focus\",e.Blur=\"blur\",e.Ready=\"ready\",e.ModelUpdate=\"update:modelValue\"}(O||(O={}));var z={};z[O.Change]=function(e,t){return!0},z[O.Update]=function(e){return!0},z[O.Focus]=function(e){return!0},z[O.Blur]=function(e){return!0},z[O.Ready]=function(e){return!0};var B={};B[O.ModelUpdate]=z[O.Change];var F=Object.assign(Object.assign({},z),B),P=t({name:\"VueCodemirror\",props:Object.assign({},w),emits:Object.assign({},F),setup:function(t,s){var f=n(),d=n(),C=n(),D=Object.assign(Object.assign({},h),e(y,{})),U=o((function(){var e={};return Object.keys(r(t)).forEach((function(n){var o;\"modelValue\"!==n&&(e[n]=null!==(o=t[n])&&void 0!==o?o:D[n])})),e}));return u((function(){var e;d.value=j({doc:t.modelValue,selection:U.value.selection,extensions:null!==(e=D.extensions)&&void 0!==e?e:[],onFocus:function(e){return s.emit(O.Focus,e)},onBlur:function(e){return s.emit(O.Blur,e)},onUpdate:function(e){return s.emit(O.Update,e)},onChange:function(e,n){e!==t.modelValue&&(s.emit(O.Change,e,n),s.emit(O.ModelUpdate,e,n))}}),C.value=function(e){return new m(Object.assign({},e))}({state:d.value,parent:f.value,root:U.value.root});var n=function(e){var t=function(){return e.state.doc.toString()},n=S(e).run,o=x(e,[m.editable.of(!1),l.readOnly.of(!0)]),r=x(e,p.of([g])),u=S(e).run,a=S(e).run,i=S(e).run,c=S(e).run;return{focus:function(){return e.focus()},getDoc:t,setDoc:function(n){n!==t()&&e.dispatch({changes:{from:0,to:e.state.doc.length,insert:n}})},reExtensions:n,toggleDisabled:o,toggleIndentWithTab:r,setTabSize:function(e){u([l.tabSize.of(e),b.of(\" \".repeat(e))])},setPhrases:function(e){a([l.phrases.of(e)])},setPlaceholder:function(e){i(v(e))},setStyle:function(e){void 0===e&&(e={}),c(m.theme({\"&\":Object.assign({},e)}))}}}(C.value);a((function(){return t.modelValue}),(function(e){e!==n.getDoc()&&n.setDoc(e)})),a((function(){return t.extensions}),(function(e){return n.reExtensions(e||[])}),{immediate:!0}),a((function(){return U.value.disabled}),(function(e){return n.toggleDisabled(e)}),{immediate:!0}),a((function(){return U.value.indentWithTab}),(function(e){return n.toggleIndentWithTab(e)}),{immediate:!0}),a((function(){return U.value.tabSize}),(function(e){return n.setTabSize(e)}),{immediate:!0}),a((function(){return U.value.phrases}),(function(e){return n.setPhrases(e||{})}),{immediate:!0}),a((function(){return U.value.placeholder}),(function(e){return n.setPlaceholder(e)}),{immediate:!0}),a((function(){return U.value.style}),(function(e){return n.setStyle(e)}),{immediate:!0}),U.value.autofocus&&n.focus(),s.emit(O.Ready,{state:d.value,view:C.value,container:f.value})})),i((function(){U.value.autoDestroy&&C.value&&function(e){e.destroy()}(C.value)})),function(){return c(\"div\",{class:\"v-codemirror\",style:{display:\"contents\"},ref:f})}}}),T=P,V=function(e,t){e.component(P.name,P),e.component(\"Codemirror\",P),function(e,t){e.provide(y,t)}(e,t)},W={Codemirror:T,install:V};export{T as Codemirror,h as DEFAULT_CONFIG,W as default,V as install};\n//# sourceMappingURL=vue-codemirror.esm.js.map\n","import { spelService } from '../spel-service'\nimport type { RuleNode, LogicalOperator, Expression } from '../types'\n\nexport function generateId(): string {\n return `node_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nexport function validateSpelExpression(expression: string): { valid: boolean; error?: string } {\n try {\n spelService.compile(expression)\n return { valid: true }\n } catch (error) {\n return {\n valid: false,\n error: error instanceof Error ? error.message : 'Invalid SpEL expression',\n }\n }\n}\n\nexport function evalSpelExpression(expression: string, locals: Record<string, any>): any {\n try {\n spelService.setContext()\n return spelService.eval(expression, locals)\n } catch (error) {\n console.error('SpEL evaluation error:', error)\n return null\n }\n}\n\n/**\n * 将 RuleNode 树转换为 SpEL 表达式字符串\n */\nexport function ruleNodeToSpel(node: RuleNode): string {\n if (node.type === 'condition') {\n if (!node.left || !node.comparator) return ''\n\n let leftExpr = formatExpression(node.left)\n\n // 1. 应用列表过滤\n if (node.listFilter && node.listFilter.comparator) {\n const { comparator, fieldPath, value } = node.listFilter\n let target = '#this'\n if (fieldPath) target = `${fieldPath}`\n\n switch (comparator) {\n case 'isEmpty':\n leftExpr = `${leftExpr}.?[${target} == null || ${target}.isEmpty()]`\n break\n case 'isNotEmpty':\n leftExpr = `${leftExpr}.?[${target} != null && !${target}.isEmpty()]`\n break\n case 'isNull':\n leftExpr = `${leftExpr}.?[${target} == null]`\n break\n case 'isNotNull':\n leftExpr = `${leftExpr}.?[${target} != null]`\n break\n default: {\n const filterVal = value ? formatExpression(value) : ''\n leftExpr = `${leftExpr}.?[${target} ${comparator} ${filterVal}]`\n break\n }\n }\n }\n\n // 2. 数组 count 操作符需要追加 .size()\n if (node.comparator.startsWith('count ')) {\n leftExpr = `${leftExpr}.size()`\n const rightExpr = node.right ? formatExpression(node.right) : ''\n const op = node.comparator.replace('count ', '')\n return `${leftExpr} ${op} ${rightExpr}`\n }\n\n const rightExpr = node.right ? formatExpression(node.right) : ''\n\n switch (node.comparator) {\n case '==':\n return `${leftExpr} == ${rightExpr}`\n case '!=':\n return `${leftExpr} != ${rightExpr}`\n case '>':\n return `${leftExpr} > ${rightExpr}`\n case '>=':\n return `${leftExpr} >= ${rightExpr}`\n case '<':\n return `${leftExpr} < ${rightExpr}`\n case '<=':\n return `${leftExpr} <= ${rightExpr}`\n case 'isEmpty':\n return `${leftExpr} == null || ${leftExpr}.isEmpty()`\n case 'isNotEmpty':\n return `${leftExpr} != null && !${leftExpr}.isEmpty()`\n case 'isNull':\n return `${leftExpr} == null`\n case 'isNotNull':\n return `${leftExpr} != null`\n case 'count ==':\n return `${leftExpr}.size() == ${rightExpr}`\n case 'count !=':\n return `${leftExpr}.size() != ${rightExpr}`\n case 'count <':\n return `${leftExpr}.size() < ${rightExpr}`\n case 'count <=':\n return `${leftExpr}.size() <= ${rightExpr}`\n case 'count >':\n return `${leftExpr}.size() > ${rightExpr}`\n case 'count >=':\n return `${leftExpr}.size() >= ${rightExpr}`\n default:\n return `${leftExpr} ${node.comparator} ${rightExpr}`\n }\n }\n\n if (node.type === 'group' && node.children?.length) {\n const childExps = node.children.map(ruleNodeToSpel).filter((exp) => exp.trim() !== '')\n\n if (childExps.length === 0) return ''\n\n if (childExps.length === 1) {\n return node.operator === 'not' ? `!(${childExps[0]})` : childExps[0] || ''\n }\n\n const separator = node.operator === 'or' ? ' || ' : ' && '\n const combined = `(${childExps.join(separator)})`\n\n return node.operator === 'not' ? `!${combined}` : combined\n }\n\n return ''\n}\n\n/**\n * 格式化 Expression 为 SpEL 字符串\n * - 字面量:'字符串',数字不加引号(这里简单处理,所有字面量加单引号,数字可后续增强)\n * - 字段:直接使用路径\n * - 函数:base.method(arg1, arg2, ...)\n */\nexport function formatExpression(expr?: Expression): string {\n if (!expr) return ''\n switch (expr.type) {\n case 'literal':\n return formatLiteral(expr.value)\n case 'field':\n return expr.path\n case 'function': {\n const base = expr.call.base ? formatExpression(expr.call.base) : ''\n\n if (base) {\n return `${base}.${format(expr.call.method, expr.call.args.map(formatExpression))}`\n }\n return `${format(expr.call.method, expr.call.args.map(formatExpression))}`\n }\n default:\n return ''\n }\n}\n\nfunction format(template: string, args: string[]): string {\n return template.replace(/\\{(\\d+)\\}/g, (_, index) => {\n return args[index] ?? ''\n })\n}\n\n/**\n * 格式化字面量:字符串用单引号包裹并转义,数字/布尔不加引号\n */\nfunction formatLiteral(value: string): string {\n if (value === '' || value === undefined || value === null) return \"''\"\n // 整数或小数\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) return value\n // 布尔值\n if (value === 'true' || value === 'false') return value\n // 其他一律作为字符串处理\n if (value.charAt(0) === \"'\" && value.charAt(value.length - 1) === \"'\") return value\n return `'${value}'`\n}\n\n/**\n * 创建一个新的空白条件节点\n */\nexport function createEmptyCondition(): RuleNode {\n return {\n id: generateId(),\n type: 'condition',\n left: { type: 'field', path: '' }, // 默认选择字段\n comparator: '==',\n }\n}\n\n/**\n * 创建一个新的空白分组节点\n */\nexport function createEmptyGroup(operator: LogicalOperator = 'and'): RuleNode {\n return {\n id: generateId(),\n type: 'group',\n operator,\n children: [],\n }\n}\n","import { ref, watch, computed } from 'vue'\nimport { spelService } from '../spel-service'\nimport { validateSpelExpression } from '../utils'\nimport type { SpelEditorProps } from '../types'\n\nexport function useSpelEditor(props: SpelEditorProps, emit: any) {\n const internalValue = ref(props.modelValue)\n const isFocused = ref(false)\n const validation = ref<{ valid: boolean; error?: string }>({ valid: true })\n\n const heightStyle = computed(() => {\n if (typeof props.height === 'number') {\n return { height: `${props.height}px` }\n }\n return { height: props.height || '400px' }\n })\n\n const handleInput = (value: string) => {\n internalValue.value = value\n emit('update:modelValue', value)\n emit('change', value)\n }\n\n const handleValidate = async () => {\n validation.value = validateSpelExpression(internalValue.value)\n emit('validate', validation.value.valid, validation.value.error)\n return validation.value.valid\n }\n\n const run = async (): Promise<any> => {\n try {\n const expression = internalValue.value\n spelService.setContext(props.authentication, props.principal)\n const result = spelService.eval(expression, props.locals)\n\n emit('run', result, undefined)\n return result\n } catch (error) {\n const errorMessage = getErrorMessage(error) || '执行表达式时发生错误'\n emit('run', undefined, errorMessage)\n return undefined\n }\n }\n\n const getErrorMessage = (error: unknown): string => {\n if (typeof error === 'object' && error !== null && 'message' in error) {\n return String(error.message)\n }\n\n return String(error)\n }\n\n const setValue = (value: string) => {\n internalValue.value = value\n emit('update:modelValue', value)\n }\n\n const getValue = () => internalValue.value\n\n watch(\n () => props.modelValue,\n (newValue) => {\n internalValue.value = newValue\n },\n )\n\n return {\n internalValue,\n isFocused,\n validation,\n heightStyle,\n handleInput,\n handleValidate,\n setValue,\n getValue,\n run,\n }\n}\n","import { ruleNodeToSpel, createEmptyCondition, createEmptyGroup } from '../utils'\nimport type { RuleNode, RuleTreeProps } from '../types'\nimport { spelService } from '../spel-service'\n\nexport function useRuleTree(props: RuleTreeProps, emit: any) {\n const getSpelExpression = () => {\n return ruleNodeToSpel(props.modelValue)\n }\n\n const setSpelExpression = (_expression: string) => {\n console.warn('SpEL parsing to RuleTree is not implemented yet')\n }\n\n const addCondition = (parentId: string) => {\n const newNode = createEmptyCondition()\n const updateNode = (node: RuleNode): RuleNode => {\n if (node.id === parentId && node.children) {\n return { ...node, children: [...node.children, newNode] }\n }\n if (node.children) {\n return { ...node, children: node.children.map(updateNode) }\n }\n return node\n }\n const newValue = updateNode(props.modelValue)\n emit('update:modelValue', newValue)\n emit('change', newValue)\n }\n\n const addGroup = (parentId: string, operator: 'and' | 'or' = 'and') => {\n const newNode = createEmptyGroup(operator)\n const updateNode = (node: RuleNode): RuleNode => {\n if (node.id === parentId && node.children) {\n return { ...node, children: [...node.children, newNode] }\n }\n if (node.children) {\n return { ...node, children: node.children.map(updateNode) }\n }\n return node\n }\n const newValue = updateNode(props.modelValue)\n emit('update:modelValue', newValue)\n emit('change', newValue)\n }\n\n const removeNode = (nodeId: string) => {\n const updateNode = (node: RuleNode): RuleNode | null => {\n if (node.id === nodeId) {\n return null\n }\n if (node.children) {\n const filteredChildren = node.children\n .map(updateNode)\n .filter((n): n is RuleNode => n !== null)\n return { ...node, children: filteredChildren }\n }\n return node\n }\n const newValue = updateNode(props.modelValue)\n if (newValue) {\n emit('update:modelValue', newValue)\n emit('change', newValue)\n }\n }\n\n const updateNode = (nodeId: string, updates: Partial<RuleNode>) => {\n const doUpdate = (node: RuleNode): RuleNode => {\n if (node.id === nodeId) {\n return { ...node, ...updates }\n }\n if (node.children) {\n return { ...node, children: node.children.map(doUpdate) }\n }\n return node\n }\n const newValue = doUpdate(props.modelValue)\n emit('update:modelValue', newValue)\n emit('change', newValue)\n }\n\n const validate = () => {\n try {\n const expression = getSpelExpression()\n if (!expression.trim()) {\n return false\n }\n return true\n } catch {\n return false\n }\n }\n\n const run = (props: RuleTreeProps, sepl: string) => {\n spelService.setContext(props.authentication, props.principal)\n return spelService.eval(sepl, props.locals)\n }\n\n return {\n getSpelExpression,\n setSpelExpression,\n addCondition,\n addGroup,\n removeNode,\n updateNode,\n validate,\n run,\n }\n}\n","import { HighlightStyle } from '@codemirror/language'\nimport { EditorView } from '@codemirror/view'\nimport { tags } from '@lezer/highlight'\nimport type { ThemeTokens } from './spel-types'\n\n/**\n * 编辑器主题色板\n */\nexport const DARK: ThemeTokens = {\n editorBg: '#1a1a2e',\n gutterBg: '#16213e',\n gutterBorder: '#3e4451',\n gutterFg: '#5c6370',\n contentFg: '#e5e5e5',\n activeLine: 'rgba(97,175,239,.08)',\n activeGutter: 'rgba(97,175,239,.12)',\n selectionBg: 'rgba(97,175,239,.3)',\n cursor: '#61afef',\n matchBracket: '#e5c07b',\n matchBracketBg: 'rgba(229,192,107,.15)',\n keyword: '#c678dd',\n operator: '#e06c75',\n string: '#98c379',\n number: '#d19a66',\n atom: '#d19a66',\n variable: '#61afef',\n definition: '#e6c07b',\n property: '#98c379',\n comment: '#5c6370',\n acBg: '#21252b',\n acBorder: '#3e4451',\n acScrollThumb: '#4b5263',\n acItemFg: '#abb2bf',\n acItemHoverBg: 'rgba(97,175,239,.2)',\n acIconVar: '#61afef',\n acIconVarBg: '#1d3d55',\n acIconProp: '#98c379',\n acIconPropBg: '#1a3322',\n acIconKey: '#c678dd',\n acIconKeyBg: '#2d1a3d',\n acIconFn: '#e5c07b',\n acIconFnBg: '#3a2c0a',\n acLabel: '#e5c07b',\n acLabelHover: '#f5d88a',\n acDetail: '#5c6370',\n acDetailHover: '#9da5b4',\n acDetailBorder: '#3e4451',\n ttBg: '#1c2028',\n ttBorder: '#4b5263',\n ttFg: '#abb2bf',\n ttLabelFg: '#61afef',\n ttDivider: '#3e4451',\n ttCodeBg: '#0d1117',\n ttCodeFg: '#98c379',\n ttCodeBorder: '#3e4451',\n badgeVarBg: '#1a3a52',\n badgeVarFg: '#61afef',\n badgePropBg: '#1a3b24',\n badgePropFg: '#98c379',\n badgeKeyBg: '#2d1a3d',\n badgeKeyFg: '#c678dd',\n badgeFnBg: '#3b2e0a',\n badgeFnFg: '#e5c07b',\n headerFrom: '#4338ca',\n headerTo: '#7c3aed',\n errBg: 'rgba(127,29,29,.7)',\n errBorder: '#991b1b',\n errFg: '#fca5a5',\n}\n\nexport const LIGHT: ThemeTokens = {\n editorBg: '#fafafa',\n gutterBg: '#f0f0f0',\n gutterBorder: '#d1d5db',\n gutterFg: '#9ca3af',\n contentFg: '#1f2937',\n activeLine: 'rgba(59,130,246,.06)',\n activeGutter: 'rgba(59,130,246,.1)',\n selectionBg: 'rgba(59,130,246,.2)',\n cursor: '#2563eb',\n matchBracket: '#d97706',\n matchBracketBg: 'rgba(217,119,6,.12)',\n keyword: '#7c3aed',\n operator: '#dc2626',\n string: '#16a34a',\n number: '#d97706',\n atom: '#d97706',\n variable: '#2563eb',\n definition: '#b45309',\n property: '#0f766e',\n comment: '#6b7280',\n acBg: '#ffffff',\n acBorder: '#e5e7eb',\n acScrollThumb: '#d1d5db',\n acItemFg: '#374151',\n acItemHoverBg: 'rgba(59,130,246,.1)',\n acIconVar: '#2563eb',\n acIconVarBg: '#dbeafe',\n acIconProp: '#0f766e',\n acIconPropBg: '#ccfbf1',\n acIconKey: '#7c3aed',\n acIconKeyBg: '#ede9fe',\n acIconFn: '#b45309',\n acIconFnBg: '#fef3c7',\n acLabel: '#92400e',\n acLabelHover: '#78350f',\n acDetail: '#9ca3af',\n acDetailHover: '#6b7280',\n acDetailBorder: '#e5e7eb',\n ttBg: '#ffffff',\n ttBorder: '#e5e7eb',\n ttFg: '#4b5563',\n ttLabelFg: '#2563eb',\n ttDivider: '#e5e7eb',\n ttCodeBg: '#f3f4f6',\n ttCodeFg: '#16a34a',\n ttCodeBorder: '#d1d5db',\n badgeVarBg: '#dbeafe',\n badgeVarFg: '#1d4ed8',\n badgePropBg: '#d1fae5',\n badgePropFg: '#065f46',\n badgeKeyBg: '#ede9fe',\n badgeKeyFg: '#6d28d9',\n badgeFnBg: '#fef3c7',\n badgeFnFg: '#92400e',\n headerFrom: '#6366f1',\n headerTo: '#a855f7',\n errBg: 'rgba(254,242,242,.95)',\n errBorder: '#fca5a5',\n errFg: '#dc2626',\n}\n\n/**\n * 创建语法高亮样式(随主题响应式重建)\n */\nexport function createSpelHighlightStyle(T: ThemeTokens) {\n return HighlightStyle.define([\n { tag: tags.keyword, color: T.keyword },\n { tag: tags.operator, color: T.operator },\n { tag: tags.string, color: T.string },\n { tag: tags.number, color: T.number },\n { tag: tags.bool, color: T.atom },\n { tag: tags.null, color: T.atom },\n { tag: tags.atom, color: T.atom },\n { tag: tags.variableName, color: T.variable },\n { tag: tags.special(tags.variableName), color: T.variable },\n { tag: tags.definition(tags.variableName), color: T.definition },\n { tag: tags.propertyName, color: T.property },\n { tag: tags.comment, color: T.comment, fontStyle: 'italic' },\n ])\n}\n\n/**\n * 创建编辑器 UI 主题(随主题响应式重建)\n */\nexport function createSpelTheme(T: ThemeTokens, isDark: boolean, fontSize: number) {\n return EditorView.theme(\n {\n '&': { height: '100%', backgroundColor: T.editorBg },\n '.cm-scroller': {\n overflow: 'auto',\n backgroundColor: T.editorBg,\n fontFamily: \"'Fira Code','JetBrains Mono','Monaco','Consolas',monospace\",\n fontSize: `${fontSize}px`,\n },\n '.cm-content': { caretColor: T.cursor, color: T.contentFg, padding: '12px' },\n '.cm-line': { color: T.contentFg, padding: '2px 0' },\n '.cm-cursor': { borderLeftColor: T.cursor, borderLeftWidth: '2px' },\n '.cm-selectionBackground': { backgroundColor: `${T.selectionBg} !important` },\n '&.cm-focused .cm-selectionBackground': { backgroundColor: `${T.selectionBg} !important` },\n '.cm-activeLine': { backgroundColor: T.activeLine },\n '.cm-gutters': {\n backgroundColor: T.gutterBg,\n borderRight: `1px solid ${T.gutterBorder}`,\n minWidth: '48px',\n },\n '.cm-lineNumbers .cm-gutterElement': {\n color: T.gutterFg,\n padding: '0 12px',\n fontSize: '12px',\n },\n '.cm-activeLineGutter': { backgroundColor: T.activeGutter },\n '.cm-matchingBracket': {\n color: `${T.matchBracket} !important`,\n backgroundColor: T.matchBracketBg,\n fontWeight: 'bold',\n },\n },\n { dark: isDark },\n )\n}\n","import type { SpelEntry, ArrayMeta, ElementField } from './spel-types'\n\nexport function buildEntries(\n authentication?: Record<string, any>,\n principal?: Record<string, any>,\n locals?: Record<string, any>,\n): SpelEntry[] {\n const list: SpelEntry[] = []\n if (authentication) {\n list.push({\n label: 'authentication',\n type: 'variable',\n detail: '用户认证信息',\n desc: '存储当前登录用户的认证信息。',\n extra: 'authentication.name / authentication.roles',\n })\n for (const key of Object.keys(authentication)) {\n list.push({\n label: `authentication.${key}`,\n type: 'property',\n detail: 'authentication 属性',\n desc: `authentication 对象的 ${key} 属性`,\n })\n const val = authentication[key]\n if (val && typeof val === 'object' && !Array.isArray(val))\n for (const sub of Object.keys(val))\n list.push({\n label: `authentication.${key}.${sub}`,\n type: 'property',\n detail: '嵌套属性',\n desc: `authentication.${key} 的 ${sub} 属性`,\n })\n }\n }\n if (principal) {\n list.push({\n label: 'principal',\n type: 'variable',\n detail: '基础变量信息',\n desc: '业务主体对象。',\n extra: 'principal.id / principal.status',\n })\n for (const key of Object.keys(principal)) {\n list.push({\n label: `principal.${key}`,\n type: 'property',\n detail: 'principal 属性',\n desc: `principal 对象的 ${key} 属性`,\n })\n const val = principal[key]\n if (val && typeof val === 'object' && !Array.isArray(val))\n for (const sub of Object.keys(val))\n list.push({\n label: `principal.${key}.${sub}`,\n type: 'property',\n detail: '嵌套属性',\n desc: `principal.${key} 的 ${sub} 属性`,\n })\n }\n }\n if (locals) {\n for (const key of Object.keys(locals)) {\n list.push({\n label: `#${key}`,\n type: 'variable',\n detail: 'locals 变量',\n desc: '用户自定义本地变量。',\n extra: `#${key}`,\n })\n const val = locals[key]\n if (val && typeof val === 'object' && !Array.isArray(val))\n for (const sub of Object.keys(val))\n list.push({\n label: `#${key}.${sub}`,\n type: 'property',\n detail: `#${key} 属性`,\n desc: `#${key} 的 ${sub} 属性`,\n })\n }\n }\n ;[\n { label: 'true', detail: '布尔值', desc: '布尔真值。', extra: 'principal.active == true' },\n { label: 'false', detail: '布尔值', desc: '布尔假值。', extra: 'principal.deleted == false' },\n { label: 'null', detail: '空值', desc: '表示空引用。', extra: 'principal.owner != null' },\n { label: 'and', detail: '逻辑与', desc: '逻辑与 &&。', extra: 'a > 0 and b > 0' },\n { label: 'or', detail: '逻辑或', desc: '逻辑或 ||。', extra: 'a == 1 or b == 1' },\n { label: 'not', detail: '逻辑非', desc: '逻辑非 !。', extra: 'not principal.deleted' },\n ].forEach((k) => list.push({ ...k, type: 'keyword' as const }))\n ;[\n {\n label: 'contains',\n detail: '包含判断',\n desc: '字符串或集合包含判断。',\n extra: \"principal.name.contains('admin')\",\n },\n {\n label: 'startsWith',\n detail: '前缀匹配',\n desc: '字符串前缀匹配。',\n extra: \"principal.code.startsWith('ORD')\",\n },\n {\n label: 'endsWith',\n detail: '后缀匹配',\n desc: '字符串后缀匹配。',\n extra: \"principal.file.endsWith('.pdf')\",\n },\n {\n label: 'matches',\n detail: '正则匹配',\n desc: '正则表达式匹配。',\n extra: \"principal.phone.matches('1[3-9]\\\\\\\\\\\\\\\\d{9}')\",\n },\n {\n label: 'isEmpty',\n detail: '判断为空',\n desc: '字符串或集合长度是否为 0。',\n extra: 'principal.tags.isEmpty()',\n },\n {\n label: 'size()',\n detail: '集合长度',\n desc: '返回集合的元素数量。',\n extra: 'principal.items.size() > 0',\n },\n {\n label: 'length()',\n detail: '字符串长度',\n desc: '返回字符串的字符数量。',\n extra: 'principal.name.length() > 2',\n },\n ].forEach((f) => list.push({ ...f, type: 'function' as const }))\n return list\n}\n\nexport function buildTypeMap(\n authentication?: Record<string, any>,\n principal?: Record<string, any>,\n locals?: Record<string, any>,\n): Record<string, string> {\n const map: Record<string, string> = {}\n function walk(obj: any, prefix: string) {\n if (!obj || typeof obj !== 'object') return\n for (const key of Object.keys(obj)) {\n const fp = prefix ? `${prefix}.${key}` : key\n const val = obj[key]\n if (val === null || val === undefined) map[fp] = 'null'\n else if (Array.isArray(val)) map[fp] = 'array'\n else if (typeof val === 'object') {\n map[fp] = 'object'\n walk(val, fp)\n } else map[fp] = typeof val\n }\n }\n if (authentication) walk(authentication, 'authentication')\n if (principal) walk(principal, 'principal')\n if (locals) {\n for (const key of Object.keys(locals)) {\n const fp = `#${key}`\n const val = locals[key]\n if (val === null || val === undefined) map[fp] = 'null'\n else if (Array.isArray(val)) map[fp] = 'array'\n else if (typeof val === 'object') {\n map[fp] = 'object'\n walk(val, fp)\n } else map[fp] = typeof val\n }\n }\n return map\n}\n\nexport function buildElementFields(obj: any): ElementField[] {\n if (!obj || typeof obj !== 'object') return []\n return Object.keys(obj).map((key) => {\n const val = obj[key]\n const f: ElementField = { label: key, value: key, type: 'null' }\n if (val === null || val === undefined) f.type = 'null'\n else if (Array.isArray(val)) {\n f.type = 'array'\n if (val.length > 0) {\n f.elementType = typeof val[0]\n if (typeof val[0] === 'object' && val[0] !== null)\n f.elementFields = buildElementFields(val[0])\n } else f.elementType = 'string'\n } else if (typeof val === 'object') {\n f.type = 'object'\n f.children = buildElementFields(val)\n } else f.type = typeof val\n return f\n })\n}\n\nexport function buildArrayMeta(\n authentication?: Record<string, any>,\n principal?: Record<string, any>,\n locals?: Record<string, any>,\n): Record<string, ArrayMeta> {\n const meta: Record<string, ArrayMeta> = {}\n function walkArr(obj: any, prefix: string) {\n if (!obj || typeof obj !== 'object') return\n for (const key of Object.keys(obj)) {\n const fp = prefix ? `${prefix}.${key}` : key\n const val = obj[key]\n if (Array.isArray(val)) {\n if (val.length > 0 && typeof val[0] === 'object' && val[0] !== null)\n meta[fp] = { elementType: 'object', elementFields: buildElementFields(val[0]) }\n else if (val.length > 0) meta[fp] = { elementType: typeof val[0] }\n else meta[fp] = { elementType: 'string' }\n } else if (typeof val === 'object' && val !== null) walkArr(val, fp)\n }\n }\n if (authentication) walkArr(authentication, 'authentication')\n if (principal) walkArr(principal, 'principal')\n if (locals) {\n for (const key of Object.keys(locals)) {\n const fp = `#${key}`\n const val = locals[key]\n if (Array.isArray(val)) {\n if (val.length > 0 && typeof val[0] === 'object' && val[0] !== null)\n meta[fp] = { elementType: 'object', elementFields: buildElementFields(val[0]) }\n else if (val.length > 0) meta[fp] = { elementType: typeof val[0] }\n else meta[fp] = { elementType: 'string' }\n } else if (typeof val === 'object' && val !== null) walkArr(val, fp)\n }\n }\n return meta\n}\n\nexport function buildStringMethodEntries(): SpelEntry[] {\n return [\n {\n label: 'length',\n type: 'property',\n detail: '字符串长度',\n desc: '返回字符串的字符数量。',\n extra: 'principal.name.length',\n },\n {\n label: 'isEmpty()',\n type: 'function',\n detail: '判断为空',\n desc: '判断长度是否为 0。',\n extra: 'principal.name.isEmpty()',\n },\n {\n label: 'toUpperCase()',\n type: 'function',\n detail: '转大写',\n desc: '将字符串转换为大写。',\n extra: 'principal.name.toUpperCase()',\n },\n {\n label: 'toLowerCase()',\n type: 'function',\n detail: '转小写',\n desc: '将字符串转换为小写。',\n extra: 'principal.name.toLowerCase()',\n },\n {\n label: 'trim()',\n type: 'function',\n detail: '去除空格',\n desc: '去除字符串首尾空白字符。',\n extra: 'principal.name.trim()',\n },\n {\n label: 'substring(x)',\n type: 'function',\n detail: '子串截取(1参)',\n desc: '从指定位置截取。',\n extra: 'principal.name.substring(3)',\n },\n {\n label: 'substring(x,y)',\n type: 'function',\n detail: '子串截取(2参)',\n desc: '从起始截取到结束。',\n extra: 'principal.name.substring(0, 3)',\n },\n {\n label: 'replace(x,y)',\n type: 'function',\n detail: '字符串替换',\n desc: '替换字符。',\n extra: \"principal.name.replace('old', 'new')\",\n },\n {\n label: 'startsWith(x)',\n type: 'function',\n detail: '前缀匹配',\n desc: '是否以指定前缀开头。',\n extra: \"principal.code.startsWith('ORD')\",\n },\n {\n label: 'endsWith(x)',\n type: 'function',\n detail: '后缀匹配',\n desc: '是否以指定后缀结尾。',\n extra: \"principal.file.endsWith('.pdf')\",\n },\n {\n label: 'contains(x)',\n type: 'function',\n detail: '包含判断',\n desc: '是否包含指定子串。',\n extra: \"principal.name.contains('value')\",\n },\n {\n label: 'indexOf(x)',\n type: 'function',\n detail: '查找索引',\n desc: '返回首次位置。',\n extra: \"principal.name.indexOf('a')\",\n },\n {\n label: 'charAt(x)',\n type: 'function',\n detail: '获取字符',\n desc: '返回指定位置字符。',\n extra: 'principal.name.charAt(0)',\n },\n ]\n}\n\nexport function buildArrayMethodEntries(am?: ArrayMeta): SpelEntry[] {\n const r: SpelEntry[] = [\n {\n label: 'size()',\n type: 'function',\n detail: '集合大小',\n desc: '返回数组元素数量。',\n extra: '...roles.size() > 0',\n },\n {\n label: 'contains(x)',\n type: 'function',\n detail: '包含判断',\n desc: '数组是否包含指定元素。',\n extra: \"...roles.contains('admin')\",\n },\n ]\n if (am?.elementType === 'object' && am.elementFields) {\n r.push({\n label: '?[field == x]',\n type: 'function',\n detail: '过滤-对象数组',\n desc: `可用字段:${am.elementFields.map((f) => f.label).join(', ')}`,\n extra: `...roles.?[${am.elementFields[0]?.label ?? 'field'} == value]`,\n })\n r.push({\n label: '![field]',\n type: 'function',\n detail: '投影-提取字段',\n desc: '从对象数组中提取指定字段。',\n extra: '...roles.![code]',\n })\n for (const f of am.elementFields)\n r.push({\n label: `[0].${f.label}`,\n type: 'property',\n detail: '数组元素字段',\n desc: `元素 ${f.label},类型 ${f.type}`,\n extra: `...roles[0].${f.label}`,\n })\n } else {\n r.push({\n label: '?[#this == x]',\n type: 'function',\n detail: '过滤-基本类型数组',\n desc: `元素类型: ${am?.elementType ?? 'string'}`,\n extra: \"...roles.?[#this == 'value']\",\n })\n }\n return r\n}\n\nexport function buildFilterFieldEntries(fields: ElementField[], prefix = ''): SpelEntry[] {\n return fields.map((f) => ({\n label: f.label,\n type: 'property' as const,\n detail:\n f.type === 'array'\n ? `array<${f.elementType ?? '?'}>`\n : f.type === 'object'\n ? 'object'\n : f.type,\n desc:\n f.type === 'object'\n ? `对象 ${f.label}`\n : f.type === 'array'\n ? `数组 ${f.label}`\n : `字段 ${f.label}`,\n extra: `...?[${prefix ? `${prefix}.` : ''}${f.label} ...]`,\n }))\n}\n\nexport function resolveFieldPath(fields: ElementField[], path: string): ElementField | null {\n const parts = path.split('.')\n let cur: ElementField | null = null\n let pool = fields\n for (const part of parts) {\n cur = pool.find((f) => f.label === part) ?? null\n if (!cur) return null\n if (cur.type === 'object' && cur.children) pool = cur.children\n else if (cur.type === 'array' && cur.elementFields) pool = cur.elementFields\n else if (cur.type === 'array') return cur\n }\n return cur\n}\n","import type { ThemeTokens } from './spel-types'\n\nconst ID = 'spel-autocomplete-style'\n\nexport function injectAutocompleteStyle(T: ThemeTokens) {\n let el = document.getElementById(ID) as HTMLStyleElement | null\n if (!el) { el = document.createElement('style'); el.id = ID; document.head.appendChild(el) }\n el.textContent = [\n `.cm-tooltip-autocomplete { background:${T.acBg}!important; border:1px solid ${T.acBorder}!important; border-radius:8px!important; }`,\n `.cm-tooltip-autocomplete .cm-completionItem { display:flex!important; gap:8px!important; padding:7px 10px!important; cursor:pointer!important; color:${T.acItemFg}!important; }`,\n `.cm-tooltip-autocomplete .cm-completionItem:hover { background:${T.acItemHoverBg}!important; }`,\n `.cm-completionIcon.cm-variable { background:${T.acIconVarBg}; color:${T.acIconVar}; }`,\n `.cm-completionIcon.cm-property { background:${T.acIconPropBg}; color:${T.acIconProp}; }`,\n `.cm-completionLabel { font-family:'Fira Code',monospace!important; font-size:13px!important; color:${T.acLabel}!important; }`,\n `.cm-completionDetail { margin-left:auto!important; font-size:11px!important; color:${T.acDetail}!important; border-left:1px solid ${T.acDetailBorder}!important; }`,\n ].join('\\n')\n}\n\nexport function getTokenAt(doc: { sliceString: (a: number, b: number) => string; length: number }, pos: number) {\n const line = doc.sliceString(Math.max(0, pos - 100), Math.min(doc.length, pos + 100))\n const off = Math.min(pos, 100)\n let s = off; while (s > 0) { const c = line[s - 1]; if (!c || !/[#\\w.]/.test(c)) break; s-- }\n let e = off; while (e < line.length) { const c = line[e]; if (!c || !/[\\w.(]/.test(c)) break; e++ }\n const text = line.slice(s, e).replace(/\\(.*$/, '')\n if (!text) return null\n return { from: pos - (off - s), to: pos + (e - off), text }\n}\n","import { StreamLanguage } from '@codemirror/language'\n\n/**\n * SpEL StreamLanguage 解析器\n * 用于语法高亮、括号匹配等\n */\n\nexport const SPEL_KEYWORDS = new Set([\n 'true', 'false', 'null', 'and', 'or', 'not',\n 'instanceof', 'matches', 'new', 'div', 'mod',\n])\n\nexport const SPEL_BUILTIN_FNS = new Set([\n 'contains', 'startsWith', 'endsWith', 'isEmpty',\n 'size', 'length', 'substring', 'toUpperCase',\n 'toLowerCase', 'trim',\n])\n\nexport const spelLanguage = StreamLanguage.define({\n name: 'spel',\n\n startState: () => ({}),\n\n token(stream) {\n if (stream.eatSpace()) return null\n\n const ch = stream.peek()\n\n // 单行注释\n if (stream.match('//')) {\n stream.skipToEnd()\n return 'comment'\n }\n\n // 字符串\n if (ch === '\"' || ch === \"'\") {\n const q = stream.next()\n if (!q) return null\n let esc = false\n while (!stream.eol()) {\n const c = stream.next()\n if (!c) break\n if (esc) { esc = false; continue }\n if (c === '\\\\') { esc = true; continue }\n if (c === q) break\n }\n return 'string'\n }\n\n // 数字\n if (ch && /\\d/.test(ch)) {\n stream.match(/^\\d+(\\.\\d+)?([eE][+-]?\\d+)?/)\n return 'number'\n }\n\n // #变量(locals)\n if (ch === '#') {\n stream.next()\n stream.match(/^[a-zA-Z_]\\w*/)\n return 'variable-2'\n }\n\n // 标识符\n if (ch && /[a-zA-Z_$]/.test(ch)) {\n stream.match(/^[a-zA-Z_$]\\w*/)\n const word = stream.current()\n if (SPEL_KEYWORDS.has(word)) return 'keyword'\n if (SPEL_BUILTIN_FNS.has(word)) return 'def'\n if (stream.match(/^\\s*\\(/, false)) return 'def'\n return 'variable'\n }\n\n // .属性名\n if (ch === '.') {\n stream.next()\n if (stream.match(/^[a-zA-Z_]\\w*/)) return 'property'\n return 'operator'\n }\n\n // 运算符\n if (ch && /[=!<>&|+\\-*/%^~?:]/.test(ch)) {\n stream.match(/^(===|!==|==|!=|<=|>=|&&|\\|\\||[=!<>&|+\\-*/%^~?:])/)\n return 'operator'\n }\n\n stream.next()\n return null\n },\n})\n","import type { ThemeTokens, SpelEntry } from './spel-types'\n\nexport function buildHoverTooltipDom(entry: SpelEntry, T: ThemeTokens): HTMLElement {\n const bm: Record<string, { bg: string; fg: string; text: string }> = {\n variable: { bg: T.badgeVarBg, fg: T.badgeVarFg, text: 'VAR' },\n property: { bg: T.badgePropBg, fg: T.badgePropFg, text: 'PROP' },\n keyword: { bg: T.badgeKeyBg, fg: T.badgeKeyFg, text: 'KEY' },\n function: { bg: T.badgeFnBg, fg: T.badgeFnFg, text: 'FN' },\n }\n const badge = bm[entry.type] ?? { bg: T.acBg, fg: T.acItemFg, text: '' }\n\n const root = document.createElement('div')\n Object.assign(root.style, {\n padding: '12px 14px', minWidth: '240px', maxWidth: '320px',\n background: T.ttBg, border: `1px solid ${T.ttBorder}`,\n borderRadius: '8px', boxShadow: '0 8px 32px rgba(0,0,0,.18)',\n fontFamily: \"'Fira Code','JetBrains Mono','Consolas',monospace\",\n fontSize: '12px', lineHeight: '1.6', color: T.ttFg,\n })\n\n const h = document.createElement('div')\n Object.assign(h.style, { display:'flex', alignItems:'center', justifyContent:'space-between', gap:'8px', marginBottom:'8px' })\n const lb = document.createElement('span'); lb.textContent = entry.label\n Object.assign(lb.style, { fontWeight:'600', fontSize:'13px', color: T.ttLabelFg })\n const be = document.createElement('span'); be.textContent = badge.text\n Object.assign(be.style, { flexShrink:'0', fontSize:'10px', fontWeight:'700', padding:'2px 6px', borderRadius:'3px', background: badge.bg, color: badge.fg })\n h.appendChild(lb); h.appendChild(be)\n\n const dv = document.createElement('div')\n Object.assign(dv.style, { height:'1px', background: T.ttDivider, marginBottom:'8px' })\n\n const dc = document.createElement('div'); dc.textContent = entry.desc\n Object.assign(dc.style, { fontSize:'12px', color: T.ttFg, lineHeight:'1.65' })\n\n root.appendChild(h); root.appendChild(dv); root.appendChild(dc)\n if (entry.extra) {\n const ex = document.createElement('div'); ex.textContent = entry.extra\n Object.assign(ex.style, { marginTop:'8px', padding:'6px 8px', background: T.ttCodeBg, borderRadius:'4px', fontSize:'11px', color: T.ttCodeFg, borderLeft: `2px solid ${T.ttCodeBorder}` })\n root.appendChild(ex)\n }\n return root\n}","import {\n hoverTooltip,\n keymap,\n lineNumbers,\n highlightActiveLineGutter,\n highlightSpecialChars,\n drawSelection,\n dropCursor,\n rectangularSelection,\n crosshairCursor,\n highlightActiveLine,\n EditorView,\n} from '@codemirror/view'\nimport { EditorState } from '@codemirror/state'\nimport { defaultKeymap, history, historyKeymap } from '@codemirror/commands'\nimport {\n foldGutter,\n indentOnInput,\n syntaxHighlighting,\n bracketMatching,\n} from '@codemirror/language'\nimport {\n closeBrackets,\n closeBracketsKeymap,\n autocompletion,\n completionKeymap,\n type CompletionSource,\n} from '@codemirror/autocomplete'\n\nimport { spelLanguage } from './spel-parser'\nimport { createSpelHighlightStyle, createSpelTheme } from './spel-theme'\nimport type { ThemeTokens } from './spel-types'\n\nexport { buildHoverTooltipDom } from './spel-autocomplete-tooltip'\n\nexport function buildExtensions(\n T: ThemeTokens,\n isDark: boolean,\n fontSize: number,\n source: CompletionSource,\n tooltip: ReturnType<typeof hoverTooltip>,\n) {\n return [\n lineNumbers(),\n highlightActiveLineGutter(),\n highlightSpecialChars(),\n history(),\n foldGutter(),\n drawSelection(),\n dropCursor(),\n EditorState.allowMultipleSelections.of(true),\n indentOnInput(),\n bracketMatching(),\n closeBrackets(),\n rectangularSelection(),\n crosshairCursor(),\n highlightActiveLine(),\n keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...historyKeymap, ...completionKeymap]),\n spelLanguage,\n syntaxHighlighting(createSpelHighlightStyle(T)),\n autocompletion({\n override: [source],\n defaultKeymap: true,\n closeOnBlur: false,\n activateOnTyping: true,\n }),\n tooltip,\n createSpelTheme(T, isDark, fontSize),\n EditorView.lineWrapping,\n ]\n}\n","<script setup lang=\"ts\">\n\nimport { ref, computed, watch } from 'vue'\nimport { Codemirror } from 'vue-codemirror'\nimport { hoverTooltip, EditorView } from '@codemirror/view'\nimport { useSpelEditor } from '../../composables'\nimport type { SpelEditorProps, SpelEditorEmits, SpelEditorInstance, ComponentSize } from '../../types'\nimport { DARK, LIGHT } from './spel-theme'\nimport { buildEntries, buildTypeMap, buildArrayMeta, buildStringMethodEntries, buildArrayMethodEntries, buildFilterFieldEntries, resolveFieldPath } from './spel-completions'\nimport { injectAutocompleteStyle, getTokenAt } from './spel-autocomplete-style'\nimport { buildExtensions, buildHoverTooltipDom } from './spel-autocomplete-ext'\nimport type { SpelEntry, ThemeTokens, ElementField } from './spel-types'\n\nconst props = withDefaults(defineProps<SpelEditorProps>(), { theme: 'dark', size: 'small' })\nconst emit = defineEmits<SpelEditorEmits>()\nconst { internalValue, validation, handleInput, handleValidate, setValue, getValue, run } = useSpelEditor(props, emit)\nconst cmRef = ref()\nconst focus = () => cmRef.value?.view?.focus()\ndefineExpose<SpelEditorInstance>({ getValue, setValue, validate: handleValidate, run, focus })\n\nconst isDark = computed(() => (props.theme ?? 'dark') === 'dark')\nconst T = computed<ThemeTokens>(() => isDark.value ? DARK : LIGHT)\nwatch(isDark, () => injectAutocompleteStyle(T.value), { immediate: true })\n\nconst sz = computed(() => props.size ?? 'small')\nconst sf: Record<ComponentSize, number> = { tiny:12, small:13, medium:14, large:15 }\nconst editorFontSize = computed(() => sf[sz.value])\n\nconst cl = (m: Record<string,string>) => computed(() => m[sz.value] ?? m.small ?? '')\nconst hPC = cl({ tiny:'px-2 py-1', small:'px-4 py-2', medium:'px-5 py-2.5', large:'px-6 py-3' })\nconst hTC = cl({ tiny:'text-xs', small:'text-sm', medium:'text-base', large:'text-lg' })\n\nconst cStyle = computed(() => {\n if (typeof props.height === 'number') return { height: `${props.height}px` }\n if (props.height) return { height: props.height }\n return { minHeight: '200px' }\n})\n\nconst A = () => props.authentication, B = () => props.principal, L = () => props.locals\nconst toO = (e: SpelEntry[], p: string) => {\n const l = p.toLowerCase()\n return e.filter(x => x.label.toLowerCase().startsWith(l)).map(x => ({ label:x.label, type:x.type, detail:x.detail }))\n}\n\n\n\nfunction fieldO(r: ElementField, pfx: string, part: string) {\n if (r.type === 'object' && r.children) return toO(buildFilterFieldEntries(r.children, pfx), part)\n if (r.type === 'string') return toO(buildStringMethodEntries(), part)\n if (r.type === 'array') {\n if (r.elementFields) return toO(buildFilterFieldEntries(r.elementFields, pfx), part)\n return toO(buildArrayMethodEntries({ elementType: r.elementType ?? 'string' }), part)\n }\n return []\n}\n\nfunction filterCtx(ap: string, inside: string, pos: number) {\n const meta = buildArrayMeta(A(), B(), L())[ap]; if (!meta) return null\n const di = inside.lastIndexOf('.')\n if (di >= 0) {\n const pfx = inside.slice(0, di); const part = inside.slice(di + 1)\n if (pfx === '#this') {\n if (meta.elementType === 'string') return { from: pos - part.length, options: toO(buildStringMethodEntries(), part) }\n if (meta.elementType === 'array') return { from: pos - part.length, options: toO(buildArrayMethodEntries({ elementType: meta.elementType }), part) }\n }\n if (meta.elementType === 'object' && meta.elementFields) {\n const r = resolveFieldPath(meta.elementFields, pfx)\n if (r) return { from: pos - part.length, options: fieldO(r, pfx, part) }\n }\n } else {\n const all: SpelEntry[] = []\n if (meta.elementType === 'object' && meta.elementFields) all.push(...buildFilterFieldEntries(meta.elementFields))\n all.push({ label: '#this', type: 'variable', detail: meta.elementType ?? 'any', desc: '当前数组元素', extra: '' })\n return { from: pos - inside.length, options: toO(all, inside) }\n }\n return null\n}\n\n\nconst completionSource: import('@codemirror/autocomplete').CompletionSource = (ctx) => {\n const word = ctx.matchBefore(/[#a-zA-Z_][\\w#.]*/)\n const pos = ctx.pos\n const before = ctx.state.sliceDoc(Math.max(0, pos - 200), pos)\n const lm = before.match(/('(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\")\\.([\\w]*)$/)\n if (lm) return { from: pos - (lm[2]?.length ?? 0), options: toO(buildStringMethodEntries(), lm[2] ?? '') }\n const fm = before.match(/(\\w+(?:\\.\\w+)*)\\.([?!])[[]([^[\\]]*)$/)\n if (fm) { const r = filterCtx(fm[1]!, fm[3]!, pos); if (r) return r }\n if (!word || (word.from === word.to && !ctx.explicit)) return null\n const text = word.text; const di = text.lastIndexOf('.')\n if (di > 0) {\n const base = text.slice(0, di); const part = text.slice(di + 1)\n const type = buildTypeMap(A(), B(), L())[base]\n if (type === 'string') return { from: word.from + di + 1, options: toO(buildStringMethodEntries(), part) }\n if (type === 'array') { const am = buildArrayMeta(A(), B(), L())[base]; return { from: word.from + di + 1, options: toO(buildArrayMethodEntries(am), part) } }\n }\n const lower = text.toLowerCase()\n return { from: word.from, options: buildEntries(A(), B(), L()).filter(e => e.label.toLowerCase().startsWith(lower)).map(e => ({ label:e.label, type:e.type, detail:e.detail, apply:(v:EditorView) => v.dispatch({ changes: { from: word.from, to: word.to, insert: e.label } }) })) }\n}\n\nconst spelHoverTooltip = computed(() => hoverTooltip((view, pos) => {\n const token = getTokenAt(view.state.doc, pos); if (!token) return null\n const entry = buildEntries(A(), B(), L()).find(e => e.label === token.text); if (!entry) return null\n return { pos: token.from, end: token.to, above: true, create: () => ({ dom: buildHoverTooltipDom(entry, T.value) }) }\n}, { hoverTime: 300 }))\n\nconst extensions = computed(() => buildExtensions(T.value, isDark.value, editorFontSize.value, completionSource, spelHoverTooltip.value))\n\nwatch(() => props.modelValue, (nv) => {\n if (!cmRef.value?.view) return\n const view = cmRef.value.view as EditorView\n if (view.state.doc.toString() !== nv) view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: nv } })\n})\n</script>\n\n<template>\n <div class=\"spel-editor-wrap rounded-lg overflow-hidden shadow-lg\"\n :class=\"[isDark ? 'border-gray-700' : 'border-gray-200', `size--${sz}`]\"\n :style=\"[cStyle, { borderWidth:'1px', borderStyle:'solid' }]\">\n <div class=\"flex items-center justify-between select-none\" :class=\"hPC\"\n :style=\"{ background: `linear-gradient(to right, ${T.headerFrom}, ${T.headerTo})` }\">\n <span class=\"flex items-center gap-2 text-white font-medium\" :class=\"hTC\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\"/>\n </svg> SpEL Editor\n </span>\n <span class=\"flex items-center gap-1.5\">\n <span class=\"w-2.5 h-2.5 rounded-full bg-red-400/80\"/>\n <span class=\"w-2.5 h-2.5 rounded-full bg-yellow-400/80\"/>\n <span class=\"w-2.5 h-2.5 rounded-full bg-green-400/80\"/>\n </span>\n </div>\n <Codemirror ref=\"cmRef\" v-model=\"internalValue\" :extensions=\"extensions\"\n :autofocus=\"false\" :indent-with-tab=\"true\" :tab-size=\"2\" class=\"spel-cm-wrap\" @change=\"handleInput\"/>\n <Transition name=\"spel-err\">\n <div v-if=\"!validation.valid\" class=\"flex items-center gap-2 px-4 py-2 text-sm border-t\"\n :style=\"{ background:T.errBg, borderColor:T.errBorder, color:T.errFg }\">\n <svg class=\"w-4 h-4 shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"/>\n </svg> {{ validation.error }}\n </div>\n </Transition>\n </div>\n</template>\n\n<style scoped>\n.spel-editor-wrap { display:flex; flex-direction:column; }\n.spel-cm-wrap { flex:1; overflow:hidden; }\n:deep(.cm-editor) { height:100%; }\n:deep(.cm-editor.cm-focused) { outline:none; }\n:deep(.cm-scroller) { overflow:auto; }\n.spel-err-enter-active,.spel-err-leave-active { transition:all .2s ease; }\n.spel-err-enter-from,.spel-err-leave-to { opacity:0; transform:translateY(-4px); }\n.size--tiny :deep(.cm-content) { padding:8px !important; }\n.size--small :deep(.cm-content) { padding:12px !important; }\n.size--medium :deep(.cm-content) { padding:16px !important; }\n.size--large :deep(.cm-content) { padding:20px !important; }\n.size--tiny :deep(.cm-gutters) { min-width:36px; }\n.size--tiny :deep(.cm-lineNumbers .cm-gutterElement) { font-size:10px; padding:0 6px; }\n.size--small :deep(.cm-gutters) { min-width:48px; }\n.size--medium :deep(.cm-gutters) { min-width:52px; }\n.size--large :deep(.cm-gutters) { min-width:56px; }\n</style>\n\n","<script setup lang=\"ts\">\n\nimport { ref, computed, watch } from 'vue'\nimport { Codemirror } from 'vue-codemirror'\nimport { hoverTooltip, EditorView } from '@codemirror/view'\nimport { useSpelEditor } from '../../composables'\nimport type { SpelEditorProps, SpelEditorEmits, SpelEditorInstance, ComponentSize } from '../../types'\nimport { DARK, LIGHT } from './spel-theme'\nimport { buildEntries, buildTypeMap, buildArrayMeta, buildStringMethodEntries, buildArrayMethodEntries, buildFilterFieldEntries, resolveFieldPath } from './spel-completions'\nimport { injectAutocompleteStyle, getTokenAt } from './spel-autocomplete-style'\nimport { buildExtensions, buildHoverTooltipDom } from './spel-autocomplete-ext'\nimport type { SpelEntry, ThemeTokens, ElementField } from './spel-types'\n\nconst props = withDefaults(defineProps<SpelEditorProps>(), { theme: 'dark', size: 'small' })\nconst emit = defineEmits<SpelEditorEmits>()\nconst { internalValue, validation, handleInput, handleValidate, setValue, getValue, run } = useSpelEditor(props, emit)\nconst cmRef = ref()\nconst focus = () => cmRef.value?.view?.focus()\ndefineExpose<SpelEditorInstance>({ getValue, setValue, validate: handleValidate, run, focus })\n\nconst isDark = computed(() => (props.theme ?? 'dark') === 'dark')\nconst T = computed<ThemeTokens>(() => isDark.value ? DARK : LIGHT)\nwatch(isDark, () => injectAutocompleteStyle(T.value), { immediate: true })\n\nconst sz = computed(() => props.size ?? 'small')\nconst sf: Record<ComponentSize, number> = { tiny:12, small:13, medium:14, large:15 }\nconst editorFontSize = computed(() => sf[sz.value])\n\nconst cl = (m: Record<string,string>) => computed(() => m[sz.value] ?? m.small ?? '')\nconst hPC = cl({ tiny:'px-2 py-1', small:'px-4 py-2', medium:'px-5 py-2.5', large:'px-6 py-3' })\nconst hTC = cl({ tiny:'text-xs', small:'text-sm', medium:'text-base', large:'text-lg' })\n\nconst cStyle = computed(() => {\n if (typeof props.height === 'number') return { height: `${props.height}px` }\n if (props.height) return { height: props.height }\n return { minHeight: '200px' }\n})\n\nconst A = () => props.authentication, B = () => props.principal, L = () => props.locals\nconst toO = (e: SpelEntry[], p: string) => {\n const l = p.toLowerCase()\n return e.filter(x => x.label.toLowerCase().startsWith(l)).map(x => ({ label:x.label, type:x.type, detail:x.detail }))\n}\n\n\n\nfunction fieldO(r: ElementField, pfx: string, part: string) {\n if (r.type === 'object' && r.children) return toO(buildFilterFieldEntries(r.children, pfx), part)\n if (r.type === 'string') return toO(buildStringMethodEntries(), part)\n if (r.type === 'array') {\n if (r.elementFields) return toO(buildFilterFieldEntries(r.elementFields, pfx), part)\n return toO(buildArrayMethodEntries({ elementType: r.elementType ?? 'string' }), part)\n }\n return []\n}\n\nfunction filterCtx(ap: string, inside: string, pos: number) {\n const meta = buildArrayMeta(A(), B(), L())[ap]; if (!meta) return null\n const di = inside.lastIndexOf('.')\n if (di >= 0) {\n const pfx = inside.slice(0, di); const part = inside.slice(di + 1)\n if (pfx === '#this') {\n if (meta.elementType === 'string') return { from: pos - part.length, options: toO(buildStringMethodEntries(), part) }\n if (meta.elementType === 'array') return { from: pos - part.length, options: toO(buildArrayMethodEntries({ elementType: meta.elementType }), part) }\n }\n if (meta.elementType === 'object' && meta.elementFields) {\n const r = resolveFieldPath(meta.elementFields, pfx)\n if (r) return { from: pos - part.length, options: fieldO(r, pfx, part) }\n }\n } else {\n const all: SpelEntry[] = []\n if (meta.elementType === 'object' && meta.elementFields) all.push(...buildFilterFieldEntries(meta.elementFields))\n all.push({ label: '#this', type: 'variable', detail: meta.elementType ?? 'any', desc: '当前数组元素', extra: '' })\n return { from: pos - inside.length, options: toO(all, inside) }\n }\n return null\n}\n\n\nconst completionSource: import('@codemirror/autocomplete').CompletionSource = (ctx) => {\n const word = ctx.matchBefore(/[#a-zA-Z_][\\w#.]*/)\n const pos = ctx.pos\n const before = ctx.state.sliceDoc(Math.max(0, pos - 200), pos)\n const lm = before.match(/('(?:[^'\\\\]|\\\\.)*'|\"(?:[^\"\\\\]|\\\\.)*\")\\.([\\w]*)$/)\n if (lm) return { from: pos - (lm[2]?.length ?? 0), options: toO(buildStringMethodEntries(), lm[2] ?? '') }\n const fm = before.match(/(\\w+(?:\\.\\w+)*)\\.([?!])[[]([^[\\]]*)$/)\n if (fm) { const r = filterCtx(fm[1]!, fm[3]!, pos); if (r) return r }\n if (!word || (word.from === word.to && !ctx.explicit)) return null\n const text = word.text; const di = text.lastIndexOf('.')\n if (di > 0) {\n const base = text.slice(0, di); const part = text.slice(di + 1)\n const type = buildTypeMap(A(), B(), L())[base]\n if (type === 'string') return { from: word.from + di + 1, options: toO(buildStringMethodEntries(), part) }\n if (type === 'array') { const am = buildArrayMeta(A(), B(), L())[base]; return { from: word.from + di + 1, options: toO(buildArrayMethodEntries(am), part) } }\n }\n const lower = text.toLowerCase()\n return { from: word.from, options: buildEntries(A(), B(), L()).filter(e => e.label.toLowerCase().startsWith(lower)).map(e => ({ label:e.label, type:e.type, detail:e.detail, apply:(v:EditorView) => v.dispatch({ changes: { from: word.from, to: word.to, insert: e.label } }) })) }\n}\n\nconst spelHoverTooltip = computed(() => hoverTooltip((view, pos) => {\n const token = getTokenAt(view.state.doc, pos); if (!token) return null\n const entry = buildEntries(A(), B(), L()).find(e => e.label === token.text); if (!entry) return null\n return { pos: token.from, end: token.to, above: true, create: () => ({ dom: buildHoverTooltipDom(entry, T.value) }) }\n}, { hoverTime: 300 }))\n\nconst extensions = computed(() => buildExtensions(T.value, isDark.value, editorFontSize.value, completionSource, spelHoverTooltip.value))\n\nwatch(() => props.modelValue, (nv) => {\n if (!cmRef.value?.view) return\n const view = cmRef.value.view as EditorView\n if (view.state.doc.toString() !== nv) view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: nv } })\n})\n</script>\n\n<template>\n <div class=\"spel-editor-wrap rounded-lg overflow-hidden shadow-lg\"\n :class=\"[isDark ? 'border-gray-700' : 'border-gray-200', `size--${sz}`]\"\n :style=\"[cStyle, { borderWidth:'1px', borderStyle:'solid' }]\">\n <div class=\"flex items-center justify-between select-none\" :class=\"hPC\"\n :style=\"{ background: `linear-gradient(to right, ${T.headerFrom}, ${T.headerTo})` }\">\n <span class=\"flex items-center gap-2 text-white font-medium\" :class=\"hTC\">\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4\"/>\n </svg> SpEL Editor\n </span>\n <span class=\"flex items-center gap-1.5\">\n <span class=\"w-2.5 h-2.5 rounded-full bg-red-400/80\"/>\n <span class=\"w-2.5 h-2.5 rounded-full bg-yellow-400/80\"/>\n <span class=\"w-2.5 h-2.5 rounded-full bg-green-400/80\"/>\n </span>\n </div>\n <Codemirror ref=\"cmRef\" v-model=\"internalValue\" :extensions=\"extensions\"\n :autofocus=\"false\" :indent-with-tab=\"true\" :tab-size=\"2\" class=\"spel-cm-wrap\" @change=\"handleInput\"/>\n <Transition name=\"spel-err\">\n <div v-if=\"!validation.valid\" class=\"flex items-center gap-2 px-4 py-2 text-sm border-t\"\n :style=\"{ background:T.errBg, borderColor:T.errBorder, color:T.errFg }\">\n <svg class=\"w-4 h-4 shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"/>\n </svg> {{ validation.error }}\n </div>\n </Transition>\n </div>\n</template>\n\n<style scoped>\n.spel-editor-wrap { display:flex; flex-direction:column; }\n.spel-cm-wrap { flex:1; overflow:hidden; }\n:deep(.cm-editor) { height:100%; }\n:deep(.cm-editor.cm-focused) { outline:none; }\n:deep(.cm-scroller) { overflow:auto; }\n.spel-err-enter-active,.spel-err-leave-active { transition:all .2s ease; }\n.spel-err-enter-from,.spel-err-leave-to { opacity:0; transform:translateY(-4px); }\n.size--tiny :deep(.cm-content) { padding:8px !important; }\n.size--small :deep(.cm-content) { padding:12px !important; }\n.size--medium :deep(.cm-content) { padding:16px !important; }\n.size--large :deep(.cm-content) { padding:20px !important; }\n.size--tiny :deep(.cm-gutters) { min-width:36px; }\n.size--tiny :deep(.cm-lineNumbers .cm-gutterElement) { font-size:10px; padding:0 6px; }\n.size--small :deep(.cm-gutters) { min-width:48px; }\n.size--medium :deep(.cm-gutters) { min-width:52px; }\n.size--large :deep(.cm-gutters) { min-width:56px; }\n</style>\n\n","<script setup lang=\"ts\">\nimport { computed, watchEffect } from 'vue'\nimport type { Expression, FunctionCall, FunctionDef, FieldOption, ComponentSize } from '../../types'\n\n// ─── 扩展的函数定义(增加 returnType) ────────────────────────\n\nconst FUNCTIONS: FunctionDef[] = [\n // 有调用方\n { label: 'length', value: 'length', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'number' },\n { label: 'size()', value: 'size()', argumentCount: 0, hasBase: true, baseType: 'collection', returnType: 'number' },\n { label: 'toUpperCase()', value: 'toUpperCase()', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'toLowerCase()', value: 'toLowerCase()', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'trim()', value: 'trim()', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'abs()', value: 'abs()', argumentCount: 0, hasBase: true, baseType: 'number', returnType: 'number' },\n { label: 'round()', value: 'round()', argumentCount: 0, hasBase: true, baseType: 'number', returnType: 'number' },\n { label: 'substring(x)', value: 'substring({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'substring(x, y)', value: 'substring({0}, {1})', argumentCount: 2, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'replace()', value: 'replace({0}, {1})', argumentCount: 2, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'startsWith()', value: 'startsWith({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'boolean' },\n { label: 'endsWith()', value: 'endsWith({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'boolean' },\n { label: 'contains()', value: 'contains({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'boolean' },\n { label: 'indexOf()', value: 'indexOf({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'number' },\n { label: 'charAt()', value: 'charAt({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'string' },\n // 独立函数\n { label: 'now()', value: 'now()', argumentCount: 0, hasBase: false, returnType: 'date' },\n { label: 'random()', value: 'random()', argumentCount: 0, hasBase: false, returnType: 'number' },\n { label: 'currentUser()', value: 'currentUser()', argumentCount: 0, hasBase: false, returnType: 'string' },\n]\n\nconst fullFunctionOptions = FUNCTIONS.map(f => ({ label: f.label, value: f.value }))\n\n// ─── Props ─────────────────────────────────────────────────────\nconst props = withDefaults(defineProps<{\n modelValue?: Expression\n fieldOptions?: FieldOption[]\n disabled?: boolean\n allowLiteral?: boolean\n allowFunction?: boolean\n baseTypeFilter?: string // 外部传入的调用方类型过滤条件\n forceNumberInput?: boolean // 新增\n size?: ComponentSize\n}>(), {\n modelValue: () => ({ type: 'field', path: '' }),\n allowLiteral: true,\n allowFunction: true,\n size: 'small',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Expression]\n}>()\n\n// ─── 类型选项 ──────────────────────────────────────────────────\nconst typeOptions = computed(() => {\n const ops: { label: string; value: Expression['type'] }[] = [\n { label: '字段', value: 'field' },\n ]\n if (props.allowLiteral) ops.push({ label: '值', value: 'literal' })\n if (props.allowFunction) ops.push({ label: '方法', value: 'function' })\n return ops\n})\n\nconst currentType = computed(() => props.modelValue.type)\n\nconst currentFunctionDef = computed<FunctionDef | null>(() => {\n if (props.modelValue.type !== 'function') return null\n const funcExpr = props.modelValue as { type: 'function'; call: FunctionCall }\n return FUNCTIONS.find(f => f.value === funcExpr.call.method) ?? null\n})\n\n// ─── 字段过滤(根据 baseTypeFilter 裁剪树形字段) ─────────────\nfunction filterFieldTree(opts: FieldOption[], typeFilter?: string): FieldOption[] {\n if (!typeFilter) return opts\n return opts.reduce((acc: FieldOption[], opt) => {\n if (opt.children && opt.children.length > 0) {\n const filteredChildren = filterFieldTree(opt.children, typeFilter)\n if (filteredChildren.length > 0) {\n acc.push({ ...opt, children: filteredChildren })\n }\n } else {\n if (opt.type === typeFilter) acc.push(opt)\n }\n return acc\n }, [])\n}\n\nconst filteredFieldOptions = computed<FieldOption[]>(() => {\n return filterFieldTree(props.fieldOptions ?? [], props.baseTypeFilter)\n})\n\n// ─── 函数过滤(根据 baseTypeFilter 限制函数列表) ─────────────\nconst filteredFunctionOptions = computed(() => {\n if (!props.baseTypeFilter) return fullFunctionOptions\n return FUNCTIONS\n .filter(f => f.returnType === props.baseTypeFilter)\n .map(f => ({ label: f.label, value: f.value }))\n})\n\n// ─── 更新方法 ──────────────────────────────────────────────────\nfunction setType(type: Expression['type']) {\n if (type === 'literal') {\n emit('update:modelValue', { type: 'literal', value: '' })\n } else if (type === 'field') {\n emit('update:modelValue', { type: 'field', path: '' })\n } else {\n emit('update:modelValue', {\n type: 'function',\n call: { method: '', base: undefined, args: [] },\n })\n }\n}\n\nfunction updateLiteral(value: string) {\n emit('update:modelValue', { type: 'literal', value })\n}\n\nfunction updateFieldPath(path: string) {\n emit('update:modelValue', { type: 'field', path })\n}\n\nfunction updateCall(partial: Partial<FunctionCall>) {\n if (props.modelValue.type !== 'function') return\n emit('update:modelValue', {\n ...props.modelValue,\n call: { ...props.modelValue.call, ...partial },\n })\n}\n\nfunction onMethodChange(method: string) {\n const def = FUNCTIONS.find(f => f.value === method)\n if (!def) return\n\n const args: Expression[] = Array.from({ length: def.argumentCount }, () => ({\n type: 'literal' as const,\n value: '',\n }))\n\n emit('update:modelValue', {\n type: 'function',\n call: {\n method,\n base: def.hasBase ? { type: 'field', path: '' } : undefined,\n args,\n },\n })\n}\n\nfunction updateArg(index: number, expr: Expression) {\n if (props.modelValue.type !== 'function') return\n const args = [...props.modelValue.call.args]\n args[index] = expr\n emit('update:modelValue', {\n ...props.modelValue,\n call: { ...props.modelValue.call, args },\n })\n}\n\n// ─── 占位符文本 ────────────────────────────────────────────────\nconst literalPlaceholder = computed(() => {\n if (props.baseTypeFilter) return `输入${props.baseTypeFilter}值…`\n return '输入值…'\n})\n\nconst safeLiteralValue = computed(() => {\n if (props.modelValue.type === 'literal') {\n return props.modelValue.value\n }\n return ''\n})\n\nwatchEffect(() => {\n if (props.forceNumberInput && props.modelValue.type !== 'literal') {\n emit('update:modelValue', { type: 'literal', value: '' })\n }\n})\n</script>\n\n<template>\n <div class=\"flex items-center gap-1\">\n <template v-if=\"forceNumberInput\">\n <n-input-number\n :value=\"safeLiteralValue !== '' ? Number(safeLiteralValue) : null\"\n placeholder=\"数字…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[120px]\"\n @update:value=\"(v: number | null) => updateLiteral(String(v ?? ''))\"\n />\n </template>\n <template v-else>\n <!-- 类型切换 -->\n <n-select\n :value=\"currentType\"\n :options=\"typeOptions\"\n :size=\"size\"\n class=\"!w-[72px]\"\n :disabled=\"disabled\"\n @update:value=\"setType\"\n />\n\n <!-- 字面量 -->\n <template v-if=\"modelValue.type === 'literal'\">\n <template v-if=\"forceNumberInput\">\n <!-- 数字输入框 -->\n <n-input-number\n :value=\"Number(modelValue.value)\"\n placeholder=\"数字…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[110px]\"\n @update:value=\"(v: number) => updateLiteral(String(v ?? ''))\"\n />\n </template>\n <template v-else>\n\n <n-input\n :value=\"modelValue.value\"\n :placeholder=\"literalPlaceholder\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[120px]\"\n @update:value=\"updateLiteral\"\n />\n </template>\n </template>\n\n <!-- 字段(使用过滤后的树形字段) -->\n <template v-else-if=\"modelValue.type === 'field'\">\n <n-cascader\n :value=\"modelValue.path\"\n :options=\"filteredFieldOptions\"\n placeholder=\"选择字段…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[160px]\"\n clearable\n check-strategy=\"child\"\n @update:value=\"updateFieldPath\"\n />\n </template>\n\n <!-- 函数调用 -->\n <template v-else-if=\"modelValue.type === 'function'\">\n <!-- 方法选择器(使用过滤后的函数列表) -->\n <n-select\n :value=\"modelValue.call.method\"\n :options=\"filteredFunctionOptions\"\n placeholder=\"方法…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[130px]\"\n @update:value=\"onMethodChange\"\n />\n\n <span class=\"text-gray-400 font-mono text-sm\">(</span>\n\n <!-- 调用方(如果需要) -->\n <template v-if=\"currentFunctionDef?.hasBase && modelValue.call.base\">\n <ExpressionEditor\n :model-value=\"modelValue.call.base\"\n :field-options=\"filteredFieldOptions\"\n :base-type-filter=\"currentFunctionDef?.baseType\"\n :disabled=\"disabled\"\n @update:model-value=\"(v: Expression) => updateCall({ base: v })\"\n />\n <span v-if=\"modelValue.call.args.length > 0\" class=\"text-gray-400 font-mono text-sm\">,</span>\n </template>\n\n <!-- 参数列表 -->\n <template v-for=\"(arg, index) in modelValue.call.args\" :key=\"'arg' + index\">\n <span v-if=\"index > 0 || (currentFunctionDef?.hasBase ? true : index > 0)\" class=\"text-gray-400 font-mono text-sm\">,</span>\n <ExpressionEditor\n :model-value=\"arg\"\n :field-options=\"filteredFieldOptions\"\n :disabled=\"disabled\"\n @update:model-value=\"(v: Expression) => updateArg(index, v)\"\n />\n </template>\n\n <span class=\"text-gray-400 font-mono text-sm\">)</span>\n </template>\n\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, watchEffect } from 'vue'\nimport type { Expression, FunctionCall, FunctionDef, FieldOption, ComponentSize } from '../../types'\n\n// ─── 扩展的函数定义(增加 returnType) ────────────────────────\n\nconst FUNCTIONS: FunctionDef[] = [\n // 有调用方\n { label: 'length', value: 'length', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'number' },\n { label: 'size()', value: 'size()', argumentCount: 0, hasBase: true, baseType: 'collection', returnType: 'number' },\n { label: 'toUpperCase()', value: 'toUpperCase()', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'toLowerCase()', value: 'toLowerCase()', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'trim()', value: 'trim()', argumentCount: 0, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'abs()', value: 'abs()', argumentCount: 0, hasBase: true, baseType: 'number', returnType: 'number' },\n { label: 'round()', value: 'round()', argumentCount: 0, hasBase: true, baseType: 'number', returnType: 'number' },\n { label: 'substring(x)', value: 'substring({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'substring(x, y)', value: 'substring({0}, {1})', argumentCount: 2, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'replace()', value: 'replace({0}, {1})', argumentCount: 2, hasBase: true, baseType: 'string', returnType: 'string' },\n { label: 'startsWith()', value: 'startsWith({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'boolean' },\n { label: 'endsWith()', value: 'endsWith({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'boolean' },\n { label: 'contains()', value: 'contains({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'boolean' },\n { label: 'indexOf()', value: 'indexOf({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'number' },\n { label: 'charAt()', value: 'charAt({0})', argumentCount: 1, hasBase: true, baseType: 'string', returnType: 'string' },\n // 独立函数\n { label: 'now()', value: 'now()', argumentCount: 0, hasBase: false, returnType: 'date' },\n { label: 'random()', value: 'random()', argumentCount: 0, hasBase: false, returnType: 'number' },\n { label: 'currentUser()', value: 'currentUser()', argumentCount: 0, hasBase: false, returnType: 'string' },\n]\n\nconst fullFunctionOptions = FUNCTIONS.map(f => ({ label: f.label, value: f.value }))\n\n// ─── Props ─────────────────────────────────────────────────────\nconst props = withDefaults(defineProps<{\n modelValue?: Expression\n fieldOptions?: FieldOption[]\n disabled?: boolean\n allowLiteral?: boolean\n allowFunction?: boolean\n baseTypeFilter?: string // 外部传入的调用方类型过滤条件\n forceNumberInput?: boolean // 新增\n size?: ComponentSize\n}>(), {\n modelValue: () => ({ type: 'field', path: '' }),\n allowLiteral: true,\n allowFunction: true,\n size: 'small',\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: Expression]\n}>()\n\n// ─── 类型选项 ──────────────────────────────────────────────────\nconst typeOptions = computed(() => {\n const ops: { label: string; value: Expression['type'] }[] = [\n { label: '字段', value: 'field' },\n ]\n if (props.allowLiteral) ops.push({ label: '值', value: 'literal' })\n if (props.allowFunction) ops.push({ label: '方法', value: 'function' })\n return ops\n})\n\nconst currentType = computed(() => props.modelValue.type)\n\nconst currentFunctionDef = computed<FunctionDef | null>(() => {\n if (props.modelValue.type !== 'function') return null\n const funcExpr = props.modelValue as { type: 'function'; call: FunctionCall }\n return FUNCTIONS.find(f => f.value === funcExpr.call.method) ?? null\n})\n\n// ─── 字段过滤(根据 baseTypeFilter 裁剪树形字段) ─────────────\nfunction filterFieldTree(opts: FieldOption[], typeFilter?: string): FieldOption[] {\n if (!typeFilter) return opts\n return opts.reduce((acc: FieldOption[], opt) => {\n if (opt.children && opt.children.length > 0) {\n const filteredChildren = filterFieldTree(opt.children, typeFilter)\n if (filteredChildren.length > 0) {\n acc.push({ ...opt, children: filteredChildren })\n }\n } else {\n if (opt.type === typeFilter) acc.push(opt)\n }\n return acc\n }, [])\n}\n\nconst filteredFieldOptions = computed<FieldOption[]>(() => {\n return filterFieldTree(props.fieldOptions ?? [], props.baseTypeFilter)\n})\n\n// ─── 函数过滤(根据 baseTypeFilter 限制函数列表) ─────────────\nconst filteredFunctionOptions = computed(() => {\n if (!props.baseTypeFilter) return fullFunctionOptions\n return FUNCTIONS\n .filter(f => f.returnType === props.baseTypeFilter)\n .map(f => ({ label: f.label, value: f.value }))\n})\n\n// ─── 更新方法 ──────────────────────────────────────────────────\nfunction setType(type: Expression['type']) {\n if (type === 'literal') {\n emit('update:modelValue', { type: 'literal', value: '' })\n } else if (type === 'field') {\n emit('update:modelValue', { type: 'field', path: '' })\n } else {\n emit('update:modelValue', {\n type: 'function',\n call: { method: '', base: undefined, args: [] },\n })\n }\n}\n\nfunction updateLiteral(value: string) {\n emit('update:modelValue', { type: 'literal', value })\n}\n\nfunction updateFieldPath(path: string) {\n emit('update:modelValue', { type: 'field', path })\n}\n\nfunction updateCall(partial: Partial<FunctionCall>) {\n if (props.modelValue.type !== 'function') return\n emit('update:modelValue', {\n ...props.modelValue,\n call: { ...props.modelValue.call, ...partial },\n })\n}\n\nfunction onMethodChange(method: string) {\n const def = FUNCTIONS.find(f => f.value === method)\n if (!def) return\n\n const args: Expression[] = Array.from({ length: def.argumentCount }, () => ({\n type: 'literal' as const,\n value: '',\n }))\n\n emit('update:modelValue', {\n type: 'function',\n call: {\n method,\n base: def.hasBase ? { type: 'field', path: '' } : undefined,\n args,\n },\n })\n}\n\nfunction updateArg(index: number, expr: Expression) {\n if (props.modelValue.type !== 'function') return\n const args = [...props.modelValue.call.args]\n args[index] = expr\n emit('update:modelValue', {\n ...props.modelValue,\n call: { ...props.modelValue.call, args },\n })\n}\n\n// ─── 占位符文本 ────────────────────────────────────────────────\nconst literalPlaceholder = computed(() => {\n if (props.baseTypeFilter) return `输入${props.baseTypeFilter}值…`\n return '输入值…'\n})\n\nconst safeLiteralValue = computed(() => {\n if (props.modelValue.type === 'literal') {\n return props.modelValue.value\n }\n return ''\n})\n\nwatchEffect(() => {\n if (props.forceNumberInput && props.modelValue.type !== 'literal') {\n emit('update:modelValue', { type: 'literal', value: '' })\n }\n})\n</script>\n\n<template>\n <div class=\"flex items-center gap-1\">\n <template v-if=\"forceNumberInput\">\n <n-input-number\n :value=\"safeLiteralValue !== '' ? Number(safeLiteralValue) : null\"\n placeholder=\"数字…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[120px]\"\n @update:value=\"(v: number | null) => updateLiteral(String(v ?? ''))\"\n />\n </template>\n <template v-else>\n <!-- 类型切换 -->\n <n-select\n :value=\"currentType\"\n :options=\"typeOptions\"\n :size=\"size\"\n class=\"!w-[72px]\"\n :disabled=\"disabled\"\n @update:value=\"setType\"\n />\n\n <!-- 字面量 -->\n <template v-if=\"modelValue.type === 'literal'\">\n <template v-if=\"forceNumberInput\">\n <!-- 数字输入框 -->\n <n-input-number\n :value=\"Number(modelValue.value)\"\n placeholder=\"数字…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[110px]\"\n @update:value=\"(v: number) => updateLiteral(String(v ?? ''))\"\n />\n </template>\n <template v-else>\n\n <n-input\n :value=\"modelValue.value\"\n :placeholder=\"literalPlaceholder\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[120px]\"\n @update:value=\"updateLiteral\"\n />\n </template>\n </template>\n\n <!-- 字段(使用过滤后的树形字段) -->\n <template v-else-if=\"modelValue.type === 'field'\">\n <n-cascader\n :value=\"modelValue.path\"\n :options=\"filteredFieldOptions\"\n placeholder=\"选择字段…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[160px]\"\n clearable\n check-strategy=\"child\"\n @update:value=\"updateFieldPath\"\n />\n </template>\n\n <!-- 函数调用 -->\n <template v-else-if=\"modelValue.type === 'function'\">\n <!-- 方法选择器(使用过滤后的函数列表) -->\n <n-select\n :value=\"modelValue.call.method\"\n :options=\"filteredFunctionOptions\"\n placeholder=\"方法…\"\n :size=\"size\"\n :disabled=\"disabled\"\n class=\"!w-[130px]\"\n @update:value=\"onMethodChange\"\n />\n\n <span class=\"text-gray-400 font-mono text-sm\">(</span>\n\n <!-- 调用方(如果需要) -->\n <template v-if=\"currentFunctionDef?.hasBase && modelValue.call.base\">\n <ExpressionEditor\n :model-value=\"modelValue.call.base\"\n :field-options=\"filteredFieldOptions\"\n :base-type-filter=\"currentFunctionDef?.baseType\"\n :disabled=\"disabled\"\n @update:model-value=\"(v: Expression) => updateCall({ base: v })\"\n />\n <span v-if=\"modelValue.call.args.length > 0\" class=\"text-gray-400 font-mono text-sm\">,</span>\n </template>\n\n <!-- 参数列表 -->\n <template v-for=\"(arg, index) in modelValue.call.args\" :key=\"'arg' + index\">\n <span v-if=\"index > 0 || (currentFunctionDef?.hasBase ? true : index > 0)\" class=\"text-gray-400 font-mono text-sm\">,</span>\n <ExpressionEditor\n :model-value=\"arg\"\n :field-options=\"filteredFieldOptions\"\n :disabled=\"disabled\"\n @update:model-value=\"(v: Expression) => updateArg(index, v)\"\n />\n </template>\n\n <span class=\"text-gray-400 font-mono text-sm\">)</span>\n </template>\n\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, ref, watchEffect, watch } from 'vue'\nimport type { RuleNode, FieldOption, LogicalOperator, Expression, ListFilter, ComponentSize } from '../../types'\nimport ExpressionEditor from './ExpressionEditor.vue'\nimport { formatExpression } from '../../utils'\nimport { spelService } from '../../spel-service'\n\nconst props = withDefaults(defineProps<{\n node: RuleNode\n authentication?: Record<string, any>\n principal?: Record<string, any>\n locals?: Record<string, any>\n disabled?: boolean\n level?: number\n theme?: 'light' | 'dark'\n size?: ComponentSize\n}>(), {\n theme: 'light',\n size: 'small',\n})\n\nconst emit = defineEmits<{\n (e: 'add-condition', id: string): void\n (e: 'add-group', id: string): void\n (e: 'remove-node', id: string): void\n (e: 'update-node', id: string, updates: Partial<RuleNode>): void\n}>()\n\nconst level = props.level ?? 0\nconst isEditing = ref(false)\n\nconst handleAddCondition = () => emit('add-condition', props.node.id)\nconst handleAddGroup = () => emit('add-group', props.node.id)\nconst handleRemove = () => emit('remove-node', props.node.id)\n\nfunction handleUpdate(updates: Partial<RuleNode>) {\n emit('update-node', props.node.id, updates)\n}\n\n// ─── 字段树构建(包含对象元素的内部字段)───────────────────────────\nconst fieldOptions = computed<FieldOption[]>(() => {\n const result: FieldOption[] = []\n if (props.authentication) result.push(...buildFieldOptions(props.authentication, 'authentication'))\n if (props.principal) result.push(...buildFieldOptions(props.principal, 'principal'))\n if (props.locals) result.push(...buildFieldOptions(props.locals, '#'))\n return result\n})\n\nfunction buildFieldOptions(obj: Record<string, any>, prefix = ''): FieldOption[] {\n const options: FieldOption[] = []\n for (const [key, value] of Object.entries(obj)) {\n const fullPath = prefix ? (prefix === '#' ? `#${key}` : `${prefix}.${key}`) : key\n if (Array.isArray(value)) {\n const elementType = value.length > 0 ? typeof value[0] : 'number'\n const option: FieldOption = { label: key, value: fullPath, type: 'array', elementType }\n if (elementType === 'object' && value.length > 0 && value[0] && !Array.isArray(value[0])) {\n option.elementChildren = buildFieldOptions(value[0], '') // 取第一个元素构建子字段\n }\n options.push(option)\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n options.push({ label: key, value: fullPath, type: 'object', children: buildFieldOptions(value, fullPath) })\n } else {\n options.push({ label: key, value: fullPath, type: typeof value })\n }\n }\n return options\n}\n\n// ─── 逻辑分组操作符 ──────────────────────────────────────────\nconst logicalOperatorOptions = [\n { label: '且', value: 'and' },\n { label: '或', value: 'or' },\n { label: '非', value: 'not' },\n]\nconst currentOperator = computed(() => props.node.operator ?? 'and')\n\n// ─── 运行时类型检测 ──────────────────────────────────────────\nfunction getDetailedType(val: any): string {\n if (val === null || val === undefined) return 'null'\n if (Array.isArray(val)) return 'array'\n const t = typeof val\n if (t === 'object') return 'object'\n return t\n}\n\nconst leftType = ref<string | null>(null)\nwatchEffect(() => {\n if (props.node.type !== 'condition' || !props.node.left) {\n leftType.value = null\n return\n }\n const exprStr = formatExpression(props.node.left)\n if (!exprStr) { leftType.value = null; return }\n try {\n spelService.setContext(props.authentication, props.principal)\n const result = spelService.eval(exprStr, props.locals)\n leftType.value = getDetailedType(result)\n } catch { leftType.value = null }\n})\n\n// ─── 通用操作符生成函数 ──────────────────────────────────────\nfunction getComparatorsForType(type: string | null): { label: string; value: string }[] {\n const base = [\n { label: '==', value: '==' },\n { label: '!=', value: '!=' },\n { label: 'isNull', value: 'isNull' },\n { label: 'isNotNull', value: 'isNotNull' },\n ]\n if (!type) {\n return [...base,\n { label: '>', value: '>' }, { label: '>=', value: '>=' },\n { label: '<', value: '<' }, { label: '<=', value: '<=' },\n { label: 'isEmpty', value: 'isEmpty' }, { label: 'isNotEmpty', value: 'isNotEmpty' },\n ]\n }\n switch (type) {\n case 'number':\n return [...base, { label: '>', value: '>' }, { label: '>=', value: '>=' }, { label: '<', value: '<' }, { label: '<=', value: '<=' }]\n case 'string':\n return [...base, { label: 'isEmpty', value: 'isEmpty' }, { label: 'isNotEmpty', value: 'isNotEmpty' }]\n case 'boolean':\n return base\n case 'array':\n return [\n { label: 'count ==', value: 'count ==' }, { label: 'count !=', value: 'count !=' },\n { label: 'count <', value: 'count <' }, { label: 'count <=', value: 'count <=' },\n { label: 'count >', value: 'count >' }, { label: 'count >=', value: 'count >=' },\n ...base\n ]\n case 'object':\n case 'null':\n return [...base, { label: 'isEmpty', value: 'isEmpty' }, { label: 'isNotEmpty', value: 'isNotEmpty' }]\n default:\n return base\n }\n}\n\nconst availableComparators = computed(() => getComparatorsForType(leftType.value))\n\nwatchEffect(() => {\n if (props.node.type !== 'condition') return\n const allowed = availableComparators.value.map(c => c.value)\n if (props.node.comparator && !allowed.includes(props.node.comparator)) {\n handleUpdate({ comparator: '' })\n }\n})\n\n// ─── 列表过滤相关 ─────────────────────────────────────────────\nfunction findFieldOption(path: string, options: FieldOption[]): FieldOption | null {\n for (const opt of options) {\n if (opt.value === path) return opt\n if (opt.children) {\n const found = findFieldOption(path, opt.children)\n if (found) return found\n }\n }\n return null\n}\n\nconst currentArrayFieldOption = computed(() => {\n if (props.node.type !== 'condition' || props.node.left?.type !== 'field') return null\n return findFieldOption(props.node.left.path, fieldOptions.value)\n})\n\nconst listElementType = computed(() => {\n const opt = currentArrayFieldOption.value\n if (opt?.type === 'array') return opt.elementType ?? 'number'\n return null\n})\n\n// 查找元素内部字段的类型\nfunction findElementFieldType(path: string, children: FieldOption[]): string | undefined {\n for (const child of children) {\n if (child.value === path) return child.type\n if (child.children) {\n // 如果路径是级联的,需要支持深层查找(这里简单起见直接比较)\n // 本场景一般只一层,可扩展\n const found = findElementFieldType(path, child.children)\n if (found) return found\n }\n }\n return undefined\n}\n\nconst selectedElementFieldType = computed(() => {\n const opt = currentArrayFieldOption.value\n const fieldPath = props.node.listFilter?.fieldPath\n if (!opt || !opt.elementChildren || !fieldPath) return undefined\n return findElementFieldType(fieldPath, opt.elementChildren)\n})\n\nconst listFilterComparators = computed(() => {\n if (listElementType.value === 'object') {\n const fieldType = selectedElementFieldType.value\n if (!fieldType) return [] // 未选字段时不显示操作符\n return getComparatorsForType(fieldType)\n }\n // 基本类型直接使用元素类型\n return getComparatorsForType(listElementType.value)\n})\n\nconst hasFilterValue = computed(() => {\n const comp = props.node.listFilter?.comparator\n if (!comp) return false\n return !['isEmpty', 'isNotEmpty', 'isNull', 'isNotNull'].includes(comp)\n})\n\n// 当左侧字段改变时清空列表过滤\nwatch(() => props.node.left, () => {\n if (props.node.listFilter) {\n handleUpdate({ listFilter: undefined })\n }\n})\n\nfunction updateListFilter(partial: Partial<ListFilter>) {\n const current = props.node.listFilter || { comparator: '' }\n const updated = { ...current, ...partial }\n handleUpdate({ listFilter: updated })\n}\n\nfunction updateListFilterField(fieldPath: string) {\n updateListFilter({ fieldPath, comparator: '' }) // 切换字段时清空操作符和值\n}\n\nfunction updateListFilterComparator(comp: string) {\n const needsValue = !['isEmpty', 'isNotEmpty', 'isNull', 'isNotNull'].includes(comp)\n const partial: Partial<ListFilter> = { comparator: comp }\n if (!needsValue) {\n partial.value = undefined\n } else if (!props.node.listFilter?.value) {\n // 根据当前字段类型初始化值字面量\n const valueType = listElementType.value === 'object'\n ? (selectedElementFieldType.value === 'number' ? 'number' as const : 'string' as const)\n : (listElementType.value === 'number' ? 'number' as const : 'string' as const)\n partial.value = { type: 'literal', value: '', literalType: valueType }\n }\n updateListFilter(partial)\n}\n\nfunction updateListFilterValue(val: string | number) {\n const valueType = listElementType.value === 'object'\n ? (selectedElementFieldType.value === 'number' ? 'number' as const : 'string' as const)\n : (listElementType.value === 'number' ? 'number' as const : 'string' as const)\n updateListFilter({ value: { type: 'literal', value: String(val ?? ''), literalType: valueType } })\n}\n\n// ─── 其他辅助 ──────────────────────────────────────────────\nconst isCountOperator = computed(() => props.node.comparator?.startsWith('count ') ?? false)\nconst hasValueInput = computed(() => {\n return !!props.node.comparator &&\n !['isEmpty', 'isNotEmpty', 'isNull', 'isNotNull'].includes(props.node.comparator)\n})\n\nconst isConfigured = computed(() => {\n if (props.node.type !== 'condition') return false\n return !!(props.node.left && props.node.comparator)\n})\n\nconst summaryExpression = computed(() => {\n if (props.node.type !== 'condition') return { left: '', op: '', right: '' }\n let leftStr = formatExpression(props.node.left)\n // 列表过滤预览\n if (props.node.listFilter && props.node.listFilter.comparator) {\n const { comparator, fieldPath, value } = props.node.listFilter\n let target = '#this'\n if (fieldPath) target = `#this.${fieldPath}`\n switch (comparator) {\n case 'isEmpty':\n leftStr = `${leftStr}.?[${target} == null || ${target}.isEmpty()]`\n break\n case 'isNotEmpty':\n leftStr = `${leftStr}.?[${target} != null && !${target}.isEmpty()]`\n break\n case 'isNull':\n leftStr = `${leftStr}.?[${target} == null]`\n break\n case 'isNotNull':\n leftStr = `${leftStr}.?[${target} != null]`\n break\n default: {\n const filterVal = value ? formatExpression(value) : ''\n leftStr = `${leftStr}.?[${target} ${comparator} ${filterVal}]`\n break\n }\n }\n }\n const op = props.node.comparator ?? ''\n if (op.startsWith('count ')) {\n leftStr = `${leftStr}.size()`\n }\n return {\n left: leftStr,\n op,\n right: props.node.right ? formatExpression(props.node.right) : '',\n }\n})\n\n// ─── 事件处理 ──────────────────────────────────────────────\nfunction handleOperatorChange(value: LogicalOperator) {\n handleUpdate({ operator: value })\n}\nfunction updateLeft(expr: Expression) { handleUpdate({ left: expr }) }\nfunction updateRight(expr: Expression) { handleUpdate({ right: expr }) }\nfunction updateComparator(value: string) { handleUpdate({ comparator: value }) }\n\nfunction toggleEdit() { if (!props.disabled) isEditing.value = !isEditing.value }\nfunction closeEdit() { isEditing.value = false }\n\n// v-click-outside 指令\nconst vClickOutside = {\n mounted(el: HTMLElement, binding: any) {\n const handler = (event: MouseEvent) => {\n const target = event.target as HTMLElement\n if (target.closest('.n-cascader-menu') || target.closest('.n-popover-shared') || target.closest('.v-binder-follower-content')) return\n if (!el.contains(target) && el !== target) binding.value(event)\n }\n ;(el as any).__clickOutsideHandler = handler\n document.addEventListener('click', handler, true)\n },\n unmounted(el: HTMLElement) {\n document.removeEventListener('click', (el as any).__clickOutsideHandler, true)\n delete (el as any).__clickOutsideHandler\n },\n}\n\nconst listFilterLiteralValue = computed(() => {\n const val = props.node.listFilter?.value\n if (val && val.type === 'literal') {\n return val.value\n }\n return ''\n})\n</script>\n\n<template>\n <!-- 条件行 -->\n <div\n v-if=\"node.type === 'condition'\"\n v-click-outside=\"closeEdit\"\n class=\"rounded-md border overflow-hidden transition-all duration-150\"\n :class=\"[\n `theme--${props.theme}`,\n `size--${size}`,\n isEditing ? 'is-editing' : 'is-idle',\n disabled ? 'opacity-60 pointer-events-none' : '',\n ]\"\n >\n <!-- 摘要行 -->\n <div class=\"group/row flex items-center gap-1.5 px-2.5 min-h-[34px] cursor-pointer select-none overflow-hidden\" @click=\"toggleEdit\">\n <span class=\"i-carbon:rule text-[11px] flex-shrink-0 icon-muted\" />\n <template v-if=\"isConfigured\">\n <span class=\"expr-chip expr-chip--field font-mono text-[11px] flex-1 min-w-0\">{{ summaryExpression.left || '?' }}</span>\n <span v-if=\"summaryExpression.op\" class=\"expr-chip expr-chip--op text-[11px] font-semibold flex-shrink-0\">{{ summaryExpression.op }}</span>\n <span v-if=\"summaryExpression.right\" class=\"expr-chip expr-chip--val font-mono text-[11px] flex-1 min-w-0\">{{ summaryExpression.right }}</span>\n <span v-else-if=\"hasValueInput\" class=\"text-[11px] tracking-widest text-placeholder\">···</span>\n </template>\n <span v-else class=\"text-xs italic text-placeholder\">点击配置条件…</span>\n <n-button class=\"!ml-auto opacity-0 group-hover/row:opacity-100 transition-opacity duration-100 flex-shrink-0\" text :size=\"size\" type=\"error\" :disabled=\"disabled\" @click.stop=\"handleRemove\">\n <template #icon><span class=\"i-carbon:close text-xs\" /></template>\n </n-button>\n </div>\n\n <!-- 编辑面板 -->\n <Transition name=\"slide-down\">\n <div v-if=\"isEditing\" class=\"edit-panel border-t px-3 py-3 space-y-2\" @click.stop>\n <div class=\"flex items-start gap-2 flex-wrap\">\n <!-- 左侧表达式 -->\n <div class=\"expr-block\">\n <div class=\"expr-block__label\">左侧</div>\n <div class=\"expr-block__body\">\n <ExpressionEditor :model-value=\"node.left ?? { type: 'field', path: '' }\" :field-options=\"fieldOptions\" :disabled=\"disabled\" :allow-literal=\"false\" :size=\"size\" @update:model-value=\"updateLeft\" />\n </div>\n </div>\n <!-- 操作符 -->\n <div class=\"expr-block\">\n <div class=\"expr-block__label\">操作符</div>\n <div class=\"expr-block__body\">\n <n-select :value=\"node.comparator\" :options=\"availableComparators\" placeholder=\"…\" :disabled=\"disabled\" :size=\"size\" class=\"!w-[108px]\" @update:value=\"updateComparator\" />\n </div>\n </div>\n <!-- 右侧表达式 -->\n <div v-if=\"hasValueInput\" class=\"expr-block\">\n <div class=\"expr-block__label\">右侧</div>\n <div class=\"expr-block__body\">\n <ExpressionEditor v-if=\"isCountOperator\" :model-value=\"node.right ?? { type: 'literal', value: '', literalType: 'number' }\" :force-number-input=\"true\" :disabled=\"disabled\" :size=\"size\" @update:model-value=\"updateRight\" />\n <ExpressionEditor v-else :model-value=\"node.right ?? { type: 'literal', value: '', literalType: 'string' }\" :field-options=\"fieldOptions\" :disabled=\"disabled\" :allow-literal=\"true\" :size=\"size\" @update:model-value=\"updateRight\" />\n </div>\n </div>\n </div>\n\n <!-- 列表过滤区块(仅当左侧为数组时显示) -->\n <div v-if=\"leftType === 'array'\" class=\"flex items-start gap-2 flex-wrap\">\n <div class=\"expr-block\">\n <div class=\"expr-block__label\">列表过滤</div>\n <div class=\"expr-block__body\">\n <!-- 基本类型:直接 #this -->\n <template v-if=\"listElementType !== 'object'\">\n <span class=\"text-xs mr-1 text-secondary\">#this</span>\n <n-select\n :value=\"node.listFilter?.comparator ?? ''\"\n :options=\"listFilterComparators\"\n placeholder=\"操作符\"\n :size=\"size\"\n class=\"!w-[80px]\"\n :disabled=\"disabled\"\n @update:value=\"updateListFilterComparator\"\n />\n <template v-if=\"hasFilterValue\">\n <n-input-number\n v-if=\"listElementType === 'number'\"\n :value=\"listFilterLiteralValue !== '' ? Number(listFilterLiteralValue) : null\"\n :size=\"size\"\n class=\"!w-[100px]\"\n :disabled=\"disabled\"\n @update:value=\"(v: number | null) => updateListFilterValue(v ?? 0)\"\n />\n <n-input\n v-else\n :value=\"listFilterLiteralValue\"\n :size=\"size\"\n class=\"!w-[120px]\"\n :disabled=\"disabled\"\n placeholder=\"文本…\"\n @update:value=\"(v: string) => updateListFilterValue(v)\"\n />\n </template>\n </template>\n <!-- 对象类型:字段选择 + 操作符 + 值 -->\n <template v-else>\n <span class=\"text-xs mr-1 text-secondary\">#this.</span>\n <n-cascader\n :value=\"node.listFilter?.fieldPath\"\n :options=\"currentArrayFieldOption?.elementChildren ?? []\"\n placeholder=\"选择字段\"\n :size=\"size\"\n class=\"!w-[140px]\"\n :disabled=\"disabled\"\n check-strategy=\"child\"\n @update:value=\"updateListFilterField\"\n />\n <n-select\n v-if=\"selectedElementFieldType\"\n :value=\"node.listFilter?.comparator ?? ''\"\n :options=\"listFilterComparators\"\n placeholder=\"操作符\"\n :size=\"size\"\n class=\"!w-[80px]\"\n :disabled=\"disabled\"\n @update:value=\"updateListFilterComparator\"\n />\n <template v-if=\"hasFilterValue && selectedElementFieldType\">\n <n-input-number\n v-if=\"selectedElementFieldType === 'number'\"\n :value=\"listFilterLiteralValue !== '' ? Number(listFilterLiteralValue) : null\"\n :size=\"size\"\n class=\"!w-[100px]\"\n :disabled=\"disabled\"\n @update:value=\"(v: number | null) => updateListFilterValue(v ?? 0)\"\n />\n <n-input\n v-else\n :value=\"listFilterLiteralValue\"\n :size=\"size\"\n class=\"!w-[120px]\"\n :disabled=\"disabled\"\n placeholder=\"文本…\"\n @update:value=\"(v: string) => updateListFilterValue(v)\"\n />\n </template>\n </template>\n </div>\n </div>\n </div>\n\n <!-- 预览 -->\n <div v-if=\"isConfigured\" class=\"flex items-center gap-1.5 px-2 py-1.5 rounded preview-block\">\n <span class=\"i-carbon:code text-xs flex-shrink-0 icon-muted\" />\n <code class=\"text-[11px] leading-none preview-code\">\n <span class=\"preview-left\">{{ summaryExpression.left || '…' }}</span>\n <span v-if=\"summaryExpression.op\" class=\"mx-1 preview-op\">{{ summaryExpression.op }}</span>\n <span v-if=\"summaryExpression.right\" class=\"preview-right\">{{ summaryExpression.right }}</span>\n </code>\n </div>\n </div>\n </Transition>\n </div>\n\n <!-- 分组节点 -->\n <div v-else class=\"relative group-root\" :class=\"[`theme--${props.theme}`, `size--${size}`, level > 0 ? 'ml-4' : '']\">\n <div v-if=\"level > 0\" class=\"group-connector\" />\n <div class=\"flex items-center gap-2 mb-2\">\n <div class=\"op-toggle\">\n <button v-for=\"opt in logicalOperatorOptions\" :key=\"opt.value\" class=\"op-toggle__btn\" :class=\"{\n 'op-toggle__btn--and': currentOperator === 'and' && opt.value === 'and',\n 'op-toggle__btn--or': currentOperator === 'or' && opt.value === 'or',\n 'op-toggle__btn--not': currentOperator === 'not' && opt.value === 'not',\n 'op-toggle__btn--off': currentOperator !== opt.value,\n }\" :disabled=\"disabled\" @click=\"handleOperatorChange(opt.value as LogicalOperator)\">{{ opt.label }}</button>\n </div>\n <div class=\"flex-1\" />\n <div class=\"flex items-center gap-1\">\n <n-button class=\"action-btn\" :size=\"size\" :disabled=\"disabled\" @click=\"handleAddCondition\"><template #icon><span class=\"i-carbon:add text-xs\" /></template>条件</n-button>\n <n-button class=\"action-btn\" :size=\"size\" :disabled=\"disabled\" @click=\"handleAddGroup\"><template #icon><span class=\"i-carbon:folder-add text-xs\" /></template>分组</n-button>\n <template v-if=\"level > 0\">\n <div class=\"w-px h-4 mx-0.5 divider\" />\n <n-button :size=\"size\" quaternary circle type=\"error\" :disabled=\"disabled\" @click=\"handleRemove\"><template #icon><span class=\"i-carbon:trash-can text-sm\" /></template></n-button>\n </template>\n </div>\n </div>\n <div class=\"relative pl-5\">\n <div v-if=\"node.children && node.children.length > 0\" class=\"group-vline\" />\n <div class=\"flex flex-col gap-1.5\">\n <template v-if=\"node.children && node.children.length > 0\">\n <div v-for=\"child in node.children\" :key=\"child.id\" class=\"relative\">\n <div class=\"group-hline\" />\n <RuleTreeNode :node=\"child\" :authentication=\"authentication\" :principal=\"principal\" :locals=\"locals\" :disabled=\"disabled\" :level=\"level + 1\" :theme=\"props.theme\" :size=\"size\"\n @add-condition=\"(id) => $emit('add-condition', id)\" @add-group=\"(id) => $emit('add-group', id)\"\n @remove-node=\"(id) => $emit('remove-node', id)\" @update-node=\"(id, updates) => $emit('update-node', id, updates)\" />\n </div>\n </template>\n <div v-else class=\"flex flex-col items-center justify-center py-6 rounded-md border border-dashed empty-state\">\n <span class=\"i-carbon:add-alt text-xl mb-1 icon-muted\" />\n <p class=\"text-[11px] text-placeholder\">暂无条件,点击右上方按钮添加</p>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n/* ─── Slide transition ─────────────────────────────────────────── */\n.slide-down-enter-active,\n.slide-down-leave-active {\n transition: max-height 0.2s ease, opacity 0.15s ease;\n max-height: 400px;\n overflow: hidden;\n}\n.slide-down-enter-from,\n.slide-down-leave-to {\n max-height: 0;\n opacity: 0;\n}\n\n/* ─── Condition card ───────────────────────────────────────────── */\n.theme--light.is-idle,\n.theme--dark.is-idle {\n background: var(--card-bg);\n border-color: var(--card-border-idle);\n}\n.theme--light.is-idle:hover,\n.theme--dark.is-idle:hover {\n border-color: var(--card-border-hover);\n}\n.theme--light.is-editing,\n.theme--dark.is-editing {\n background: var(--card-bg);\n border-color: var(--card-border-editing);\n box-shadow: var(--card-shadow-editing);\n}\n\n/* ─── Icon & text helpers ──────────────────────────────────────── */\n.icon-muted { color: var(--icon-muted); }\n.text-placeholder { color: var(--text-placeholder); }\n.text-secondary { color: var(--text-secondary); }\n\n/* ─── Expression chips ─────────────────────────────────────────── */\n.expr-chip {\n display: inline-flex;\n align-items: center;\n padding: 1px 6px;\n border-radius: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.expr-chip--field {\n background: var(--expr-field-bg);\n color: var(--expr-field-fg);\n border: 1px solid var(--expr-field-border);\n}\n.expr-chip--op {\n background: var(--expr-op-bg);\n color: var(--expr-op-fg);\n border: 1px solid var(--expr-op-border);\n}\n.expr-chip--val {\n background: var(--expr-val-bg);\n color: var(--expr-val-fg);\n border: 1px solid var(--expr-val-border);\n}\n\n/* ─── Expression block ─────────────────────────────────────────── */\n.expr-block {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.expr-block__label {\n font-size: 10px;\n color: var(--expr-block-label);\n padding-left: 2px;\n letter-spacing: 0.3px;\n}\n.expr-block__body {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n padding: 5px 8px;\n background: var(--expr-block-body-bg);\n border: 1px solid var(--expr-block-body-border);\n border-radius: 6px;\n min-height: 36px;\n}\n\n/* ─── Edit panel ───────────────────────────────────────────────── */\n.edit-panel {\n background: var(--edit-panel-bg);\n border-color: var(--edit-panel-border);\n}\n\n/* ─── Preview block ────────────────────────────────────────────── */\n.preview-block {\n background: var(--preview-bg);\n border: 1px solid var(--preview-border);\n}\n.preview-code {\n color: var(--preview-text);\n}\n.preview-left {\n color: var(--preview-left);\n}\n.preview-op {\n color: var(--preview-op);\n}\n.preview-right {\n color: var(--preview-right);\n}\n\n/* ─── Operator toggle ──────────────────────────────────────────── */\n.op-toggle {\n display: inline-flex;\n border: 1px solid var(--op-toggle-border);\n border-radius: 5px;\n overflow: hidden;\n box-shadow: var(--op-toggle-shadow);\n}\n.op-toggle__btn {\n padding: 0 12px;\n height: 26px;\n font-size: 12px;\n font-weight: 600;\n border: none;\n border-right: 1px solid var(--op-toggle-btn-border);\n background: var(--op-toggle-btn-bg);\n color: var(--op-toggle-btn-fg);\n cursor: pointer;\n transition: background 0.1s, color 0.1s;\n}\n.op-toggle__btn:last-child { border-right: none; }\n.op-toggle__btn:disabled { cursor: not-allowed; opacity: 0.5; }\n.op-toggle__btn--off:not(:disabled):hover {\n background: var(--op-toggle-btn-hover-bg);\n color: var(--op-toggle-btn-hover-fg);\n}\n.op-toggle__btn--and:not(.op-toggle__btn--off) {\n background: var(--op-toggle-and-bg);\n color: var(--op-toggle-active-fg);\n}\n.op-toggle__btn--or:not(.op-toggle__btn--off) {\n background: var(--op-toggle-or-bg);\n color: var(--op-toggle-active-fg);\n}\n.op-toggle__btn--not:not(.op-toggle__btn--off) {\n background: var(--op-toggle-not-bg);\n color: var(--op-toggle-active-fg);\n}\n\n/* ─── Connectors & lines ───────────────────────────────────────── */\n.group-vline {\n position: absolute;\n left: 7px;\n top: 0;\n bottom: 12px;\n width: 1px;\n background: var(--connector-color);\n}\n.group-hline {\n position: absolute;\n left: -13px;\n top: 17px;\n width: 13px;\n height: 1px;\n background: var(--connector-color);\n}\n.group-connector {\n position: absolute;\n left: -9px;\n top: 17px;\n width: 9px;\n height: 1px;\n background: var(--connector-color);\n}\n\n/* ─── Empty state ──────────────────────────────────────────────── */\n.empty-state {\n border-color: var(--empty-border);\n color: var(--empty-fg);\n}\n\n/* ─── Divider ──────────────────────────────────────────────────── */\n.divider {\n background: var(--divider-bg);\n}\n\n/* ─── Action buttons ───────────────────────────────────────────── */\n.action-btn {\n background: #7c3aed !important;\n border-color: #7c3aed !important;\n color: #ffffff !important;\n\n transition:\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n}\n\n.action-btn:hover {\n background: #6d28d9 !important;\n border-color: #6d28d9 !important;\n\n box-shadow: 0 2px 8px rgba(124, 58, 237, 0.28);\n}\n\n.action-btn:active {\n background: #5b21b6 !important;\n border-color: #5b21b6 !important;\n}\n\n.action-btn:disabled {\n opacity: 0.5 !important;\n box-shadow: none !important;\n}\n\n/* ─── Size variants ───────────────────────────────────────────── */\n/* tiny */\n.size--tiny .group\\/row { min-height: 28px; padding-left: 6px; padding-right: 6px; }\n.size--tiny .edit-panel { padding: 6px 8px; }\n.size--tiny .expr-block__body { padding: 3px 6px; min-height: 28px; }\n.size--tiny .expr-block__label { font-size: 9px; }\n.size--tiny .expr-chip { padding: 0 4px; font-size: 10px !important; }\n.size--tiny .op-toggle__btn { padding: 0 8px; height: 22px; font-size: 11px; }\n.size--tiny .action-btn { font-size: 11px !important; }\n.size--tiny .preview-block { padding: 4px 6px; }\n.size--tiny .preview-code { font-size: 10px !important; }\n.size--tiny .empty-state { padding: 12px 0; }\n.size--tiny .empty-state p { font-size: 10px; }\n\n/* small (default) */\n.size--small .group\\/row { min-height: 34px; padding-left: 10px; padding-right: 10px; }\n.size--small .edit-panel { padding: 12px; }\n.size--small .expr-block__body { padding: 5px 8px; min-height: 36px; }\n.size--small .expr-block__label { font-size: 10px; }\n.size--small .expr-chip { padding: 1px 6px; font-size: 11px !important; }\n.size--small .op-toggle__btn { padding: 0 12px; height: 26px; font-size: 12px; }\n.size--small .preview-block { padding: 6px 8px; }\n.size--small .preview-code { font-size: 11px !important; }\n.size--small .empty-state { padding: 24px 0; }\n\n/* medium */\n.size--medium .group\\/row { min-height: 40px; padding-left: 14px; padding-right: 14px; }\n.size--medium .edit-panel { padding: 16px; }\n.size--medium .expr-block__body { padding: 8px 12px; min-height: 44px; }\n.size--medium .expr-block__label { font-size: 11px; }\n.size--medium .expr-chip { padding: 2px 8px; font-size: 12px !important; }\n.size--medium .op-toggle__btn { padding: 0 16px; height: 30px; font-size: 13px; }\n.size--medium .preview-block { padding: 8px 12px; }\n.size--medium .preview-code { font-size: 12px !important; }\n.size--medium .empty-state { padding: 32px 0; }\n\n/* large */\n.size--large .group\\/row { min-height: 48px; padding-left: 18px; padding-right: 18px; }\n.size--large .edit-panel { padding: 20px; }\n.size--large .expr-block__body { padding: 10px 16px; min-height: 52px; }\n.size--large .expr-block__label { font-size: 12px; }\n.size--large .expr-chip { padding: 3px 10px; font-size: 13px !important; }\n.size--large .op-toggle__btn { padding: 0 20px; height: 34px; font-size: 14px; }\n.size--large .preview-block { padding: 10px 16px; }\n.size--large .preview-code { font-size: 13px !important; }\n.size--large .empty-state { padding: 40px 0; }\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watchEffect, watch } from 'vue'\nimport type { RuleNode, FieldOption, LogicalOperator, Expression, ListFilter, ComponentSize } from '../../types'\nimport ExpressionEditor from './ExpressionEditor.vue'\nimport { formatExpression } from '../../utils'\nimport { spelService } from '../../spel-service'\n\nconst props = withDefaults(defineProps<{\n node: RuleNode\n authentication?: Record<string, any>\n principal?: Record<string, any>\n locals?: Record<string, any>\n disabled?: boolean\n level?: number\n theme?: 'light' | 'dark'\n size?: ComponentSize\n}>(), {\n theme: 'light',\n size: 'small',\n})\n\nconst emit = defineEmits<{\n (e: 'add-condition', id: string): void\n (e: 'add-group', id: string): void\n (e: 'remove-node', id: string): void\n (e: 'update-node', id: string, updates: Partial<RuleNode>): void\n}>()\n\nconst level = props.level ?? 0\nconst isEditing = ref(false)\n\nconst handleAddCondition = () => emit('add-condition', props.node.id)\nconst handleAddGroup = () => emit('add-group', props.node.id)\nconst handleRemove = () => emit('remove-node', props.node.id)\n\nfunction handleUpdate(updates: Partial<RuleNode>) {\n emit('update-node', props.node.id, updates)\n}\n\n// ─── 字段树构建(包含对象元素的内部字段)───────────────────────────\nconst fieldOptions = computed<FieldOption[]>(() => {\n const result: FieldOption[] = []\n if (props.authentication) result.push(...buildFieldOptions(props.authentication, 'authentication'))\n if (props.principal) result.push(...buildFieldOptions(props.principal, 'principal'))\n if (props.locals) result.push(...buildFieldOptions(props.locals, '#'))\n return result\n})\n\nfunction buildFieldOptions(obj: Record<string, any>, prefix = ''): FieldOption[] {\n const options: FieldOption[] = []\n for (const [key, value] of Object.entries(obj)) {\n const fullPath = prefix ? (prefix === '#' ? `#${key}` : `${prefix}.${key}`) : key\n if (Array.isArray(value)) {\n const elementType = value.length > 0 ? typeof value[0] : 'number'\n const option: FieldOption = { label: key, value: fullPath, type: 'array', elementType }\n if (elementType === 'object' && value.length > 0 && value[0] && !Array.isArray(value[0])) {\n option.elementChildren = buildFieldOptions(value[0], '') // 取第一个元素构建子字段\n }\n options.push(option)\n } else if (value && typeof value === 'object' && !Array.isArray(value)) {\n options.push({ label: key, value: fullPath, type: 'object', children: buildFieldOptions(value, fullPath) })\n } else {\n options.push({ label: key, value: fullPath, type: typeof value })\n }\n }\n return options\n}\n\n// ─── 逻辑分组操作符 ──────────────────────────────────────────\nconst logicalOperatorOptions = [\n { label: '且', value: 'and' },\n { label: '或', value: 'or' },\n { label: '非', value: 'not' },\n]\nconst currentOperator = computed(() => props.node.operator ?? 'and')\n\n// ─── 运行时类型检测 ──────────────────────────────────────────\nfunction getDetailedType(val: any): string {\n if (val === null || val === undefined) return 'null'\n if (Array.isArray(val)) return 'array'\n const t = typeof val\n if (t === 'object') return 'object'\n return t\n}\n\nconst leftType = ref<string | null>(null)\nwatchEffect(() => {\n if (props.node.type !== 'condition' || !props.node.left) {\n leftType.value = null\n return\n }\n const exprStr = formatExpression(props.node.left)\n if (!exprStr) { leftType.value = null; return }\n try {\n spelService.setContext(props.authentication, props.principal)\n const result = spelService.eval(exprStr, props.locals)\n leftType.value = getDetailedType(result)\n } catch { leftType.value = null }\n})\n\n// ─── 通用操作符生成函数 ──────────────────────────────────────\nfunction getComparatorsForType(type: string | null): { label: string; value: string }[] {\n const base = [\n { label: '==', value: '==' },\n { label: '!=', value: '!=' },\n { label: 'isNull', value: 'isNull' },\n { label: 'isNotNull', value: 'isNotNull' },\n ]\n if (!type) {\n return [...base,\n { label: '>', value: '>' }, { label: '>=', value: '>=' },\n { label: '<', value: '<' }, { label: '<=', value: '<=' },\n { label: 'isEmpty', value: 'isEmpty' }, { label: 'isNotEmpty', value: 'isNotEmpty' },\n ]\n }\n switch (type) {\n case 'number':\n return [...base, { label: '>', value: '>' }, { label: '>=', value: '>=' }, { label: '<', value: '<' }, { label: '<=', value: '<=' }]\n case 'string':\n return [...base, { label: 'isEmpty', value: 'isEmpty' }, { label: 'isNotEmpty', value: 'isNotEmpty' }]\n case 'boolean':\n return base\n case 'array':\n return [\n { label: 'count ==', value: 'count ==' }, { label: 'count !=', value: 'count !=' },\n { label: 'count <', value: 'count <' }, { label: 'count <=', value: 'count <=' },\n { label: 'count >', value: 'count >' }, { label: 'count >=', value: 'count >=' },\n ...base\n ]\n case 'object':\n case 'null':\n return [...base, { label: 'isEmpty', value: 'isEmpty' }, { label: 'isNotEmpty', value: 'isNotEmpty' }]\n default:\n return base\n }\n}\n\nconst availableComparators = computed(() => getComparatorsForType(leftType.value))\n\nwatchEffect(() => {\n if (props.node.type !== 'condition') return\n const allowed = availableComparators.value.map(c => c.value)\n if (props.node.comparator && !allowed.includes(props.node.comparator)) {\n handleUpdate({ comparator: '' })\n }\n})\n\n// ─── 列表过滤相关 ─────────────────────────────────────────────\nfunction findFieldOption(path: string, options: FieldOption[]): FieldOption | null {\n for (const opt of options) {\n if (opt.value === path) return opt\n if (opt.children) {\n const found = findFieldOption(path, opt.children)\n if (found) return found\n }\n }\n return null\n}\n\nconst currentArrayFieldOption = computed(() => {\n if (props.node.type !== 'condition' || props.node.left?.type !== 'field') return null\n return findFieldOption(props.node.left.path, fieldOptions.value)\n})\n\nconst listElementType = computed(() => {\n const opt = currentArrayFieldOption.value\n if (opt?.type === 'array') return opt.elementType ?? 'number'\n return null\n})\n\n// 查找元素内部字段的类型\nfunction findElementFieldType(path: string, children: FieldOption[]): string | undefined {\n for (const child of children) {\n if (child.value === path) return child.type\n if (child.children) {\n // 如果路径是级联的,需要支持深层查找(这里简单起见直接比较)\n // 本场景一般只一层,可扩展\n const found = findElementFieldType(path, child.children)\n if (found) return found\n }\n }\n return undefined\n}\n\nconst selectedElementFieldType = computed(() => {\n const opt = currentArrayFieldOption.value\n const fieldPath = props.node.listFilter?.fieldPath\n if (!opt || !opt.elementChildren || !fieldPath) return undefined\n return findElementFieldType(fieldPath, opt.elementChildren)\n})\n\nconst listFilterComparators = computed(() => {\n if (listElementType.value === 'object') {\n const fieldType = selectedElementFieldType.value\n if (!fieldType) return [] // 未选字段时不显示操作符\n return getComparatorsForType(fieldType)\n }\n // 基本类型直接使用元素类型\n return getComparatorsForType(listElementType.value)\n})\n\nconst hasFilterValue = computed(() => {\n const comp = props.node.listFilter?.comparator\n if (!comp) return false\n return !['isEmpty', 'isNotEmpty', 'isNull', 'isNotNull'].includes(comp)\n})\n\n// 当左侧字段改变时清空列表过滤\nwatch(() => props.node.left, () => {\n if (props.node.listFilter) {\n handleUpdate({ listFilter: undefined })\n }\n})\n\nfunction updateListFilter(partial: Partial<ListFilter>) {\n const current = props.node.listFilter || { comparator: '' }\n const updated = { ...current, ...partial }\n handleUpdate({ listFilter: updated })\n}\n\nfunction updateListFilterField(fieldPath: string) {\n updateListFilter({ fieldPath, comparator: '' }) // 切换字段时清空操作符和值\n}\n\nfunction updateListFilterComparator(comp: string) {\n const needsValue = !['isEmpty', 'isNotEmpty', 'isNull', 'isNotNull'].includes(comp)\n const partial: Partial<ListFilter> = { comparator: comp }\n if (!needsValue) {\n partial.value = undefined\n } else if (!props.node.listFilter?.value) {\n // 根据当前字段类型初始化值字面量\n const valueType = listElementType.value === 'object'\n ? (selectedElementFieldType.value === 'number' ? 'number' as const : 'string' as const)\n : (listElementType.value === 'number' ? 'number' as const : 'string' as const)\n partial.value = { type: 'literal', value: '', literalType: valueType }\n }\n updateListFilter(partial)\n}\n\nfunction updateListFilterValue(val: string | number) {\n const valueType = listElementType.value === 'object'\n ? (selectedElementFieldType.value === 'number' ? 'number' as const : 'string' as const)\n : (listElementType.value === 'number' ? 'number' as const : 'string' as const)\n updateListFilter({ value: { type: 'literal', value: String(val ?? ''), literalType: valueType } })\n}\n\n// ─── 其他辅助 ──────────────────────────────────────────────\nconst isCountOperator = computed(() => props.node.comparator?.startsWith('count ') ?? false)\nconst hasValueInput = computed(() => {\n return !!props.node.comparator &&\n !['isEmpty', 'isNotEmpty', 'isNull', 'isNotNull'].includes(props.node.comparator)\n})\n\nconst isConfigured = computed(() => {\n if (props.node.type !== 'condition') return false\n return !!(props.node.left && props.node.comparator)\n})\n\nconst summaryExpression = computed(() => {\n if (props.node.type !== 'condition') return { left: '', op: '', right: '' }\n let leftStr = formatExpression(props.node.left)\n // 列表过滤预览\n if (props.node.listFilter && props.node.listFilter.comparator) {\n const { comparator, fieldPath, value } = props.node.listFilter\n let target = '#this'\n if (fieldPath) target = `#this.${fieldPath}`\n switch (comparator) {\n case 'isEmpty':\n leftStr = `${leftStr}.?[${target} == null || ${target}.isEmpty()]`\n break\n case 'isNotEmpty':\n leftStr = `${leftStr}.?[${target} != null && !${target}.isEmpty()]`\n break\n case 'isNull':\n leftStr = `${leftStr}.?[${target} == null]`\n break\n case 'isNotNull':\n leftStr = `${leftStr}.?[${target} != null]`\n break\n default: {\n const filterVal = value ? formatExpression(value) : ''\n leftStr = `${leftStr}.?[${target} ${comparator} ${filterVal}]`\n break\n }\n }\n }\n const op = props.node.comparator ?? ''\n if (op.startsWith('count ')) {\n leftStr = `${leftStr}.size()`\n }\n return {\n left: leftStr,\n op,\n right: props.node.right ? formatExpression(props.node.right) : '',\n }\n})\n\n// ─── 事件处理 ──────────────────────────────────────────────\nfunction handleOperatorChange(value: LogicalOperator) {\n handleUpdate({ operator: value })\n}\nfunction updateLeft(expr: Expression) { handleUpdate({ left: expr }) }\nfunction updateRight(expr: Expression) { handleUpdate({ right: expr }) }\nfunction updateComparator(value: string) { handleUpdate({ comparator: value }) }\n\nfunction toggleEdit() { if (!props.disabled) isEditing.value = !isEditing.value }\nfunction closeEdit() { isEditing.value = false }\n\n// v-click-outside 指令\nconst vClickOutside = {\n mounted(el: HTMLElement, binding: any) {\n const handler = (event: MouseEvent) => {\n const target = event.target as HTMLElement\n if (target.closest('.n-cascader-menu') || target.closest('.n-popover-shared') || target.closest('.v-binder-follower-content')) return\n if (!el.contains(target) && el !== target) binding.value(event)\n }\n ;(el as any).__clickOutsideHandler = handler\n document.addEventListener('click', handler, true)\n },\n unmounted(el: HTMLElement) {\n document.removeEventListener('click', (el as any).__clickOutsideHandler, true)\n delete (el as any).__clickOutsideHandler\n },\n}\n\nconst listFilterLiteralValue = computed(() => {\n const val = props.node.listFilter?.value\n if (val && val.type === 'literal') {\n return val.value\n }\n return ''\n})\n</script>\n\n<template>\n <!-- 条件行 -->\n <div\n v-if=\"node.type === 'condition'\"\n v-click-outside=\"closeEdit\"\n class=\"rounded-md border overflow-hidden transition-all duration-150\"\n :class=\"[\n `theme--${props.theme}`,\n `size--${size}`,\n isEditing ? 'is-editing' : 'is-idle',\n disabled ? 'opacity-60 pointer-events-none' : '',\n ]\"\n >\n <!-- 摘要行 -->\n <div class=\"group/row flex items-center gap-1.5 px-2.5 min-h-[34px] cursor-pointer select-none overflow-hidden\" @click=\"toggleEdit\">\n <span class=\"i-carbon:rule text-[11px] flex-shrink-0 icon-muted\" />\n <template v-if=\"isConfigured\">\n <span class=\"expr-chip expr-chip--field font-mono text-[11px] flex-1 min-w-0\">{{ summaryExpression.left || '?' }}</span>\n <span v-if=\"summaryExpression.op\" class=\"expr-chip expr-chip--op text-[11px] font-semibold flex-shrink-0\">{{ summaryExpression.op }}</span>\n <span v-if=\"summaryExpression.right\" class=\"expr-chip expr-chip--val font-mono text-[11px] flex-1 min-w-0\">{{ summaryExpression.right }}</span>\n <span v-else-if=\"hasValueInput\" class=\"text-[11px] tracking-widest text-placeholder\">···</span>\n </template>\n <span v-else class=\"text-xs italic text-placeholder\">点击配置条件…</span>\n <n-button class=\"!ml-auto opacity-0 group-hover/row:opacity-100 transition-opacity duration-100 flex-shrink-0\" text :size=\"size\" type=\"error\" :disabled=\"disabled\" @click.stop=\"handleRemove\">\n <template #icon><span class=\"i-carbon:close text-xs\" /></template>\n </n-button>\n </div>\n\n <!-- 编辑面板 -->\n <Transition name=\"slide-down\">\n <div v-if=\"isEditing\" class=\"edit-panel border-t px-3 py-3 space-y-2\" @click.stop>\n <div class=\"flex items-start gap-2 flex-wrap\">\n <!-- 左侧表达式 -->\n <div class=\"expr-block\">\n <div class=\"expr-block__label\">左侧</div>\n <div class=\"expr-block__body\">\n <ExpressionEditor :model-value=\"node.left ?? { type: 'field', path: '' }\" :field-options=\"fieldOptions\" :disabled=\"disabled\" :allow-literal=\"false\" :size=\"size\" @update:model-value=\"updateLeft\" />\n </div>\n </div>\n <!-- 操作符 -->\n <div class=\"expr-block\">\n <div class=\"expr-block__label\">操作符</div>\n <div class=\"expr-block__body\">\n <n-select :value=\"node.comparator\" :options=\"availableComparators\" placeholder=\"…\" :disabled=\"disabled\" :size=\"size\" class=\"!w-[108px]\" @update:value=\"updateComparator\" />\n </div>\n </div>\n <!-- 右侧表达式 -->\n <div v-if=\"hasValueInput\" class=\"expr-block\">\n <div class=\"expr-block__label\">右侧</div>\n <div class=\"expr-block__body\">\n <ExpressionEditor v-if=\"isCountOperator\" :model-value=\"node.right ?? { type: 'literal', value: '', literalType: 'number' }\" :force-number-input=\"true\" :disabled=\"disabled\" :size=\"size\" @update:model-value=\"updateRight\" />\n <ExpressionEditor v-else :model-value=\"node.right ?? { type: 'literal', value: '', literalType: 'string' }\" :field-options=\"fieldOptions\" :disabled=\"disabled\" :allow-literal=\"true\" :size=\"size\" @update:model-value=\"updateRight\" />\n </div>\n </div>\n </div>\n\n <!-- 列表过滤区块(仅当左侧为数组时显示) -->\n <div v-if=\"leftType === 'array'\" class=\"flex items-start gap-2 flex-wrap\">\n <div class=\"expr-block\">\n <div class=\"expr-block__label\">列表过滤</div>\n <div class=\"expr-block__body\">\n <!-- 基本类型:直接 #this -->\n <template v-if=\"listElementType !== 'object'\">\n <span class=\"text-xs mr-1 text-secondary\">#this</span>\n <n-select\n :value=\"node.listFilter?.comparator ?? ''\"\n :options=\"listFilterComparators\"\n placeholder=\"操作符\"\n :size=\"size\"\n class=\"!w-[80px]\"\n :disabled=\"disabled\"\n @update:value=\"updateListFilterComparator\"\n />\n <template v-if=\"hasFilterValue\">\n <n-input-number\n v-if=\"listElementType === 'number'\"\n :value=\"listFilterLiteralValue !== '' ? Number(listFilterLiteralValue) : null\"\n :size=\"size\"\n class=\"!w-[100px]\"\n :disabled=\"disabled\"\n @update:value=\"(v: number | null) => updateListFilterValue(v ?? 0)\"\n />\n <n-input\n v-else\n :value=\"listFilterLiteralValue\"\n :size=\"size\"\n class=\"!w-[120px]\"\n :disabled=\"disabled\"\n placeholder=\"文本…\"\n @update:value=\"(v: string) => updateListFilterValue(v)\"\n />\n </template>\n </template>\n <!-- 对象类型:字段选择 + 操作符 + 值 -->\n <template v-else>\n <span class=\"text-xs mr-1 text-secondary\">#this.</span>\n <n-cascader\n :value=\"node.listFilter?.fieldPath\"\n :options=\"currentArrayFieldOption?.elementChildren ?? []\"\n placeholder=\"选择字段\"\n :size=\"size\"\n class=\"!w-[140px]\"\n :disabled=\"disabled\"\n check-strategy=\"child\"\n @update:value=\"updateListFilterField\"\n />\n <n-select\n v-if=\"selectedElementFieldType\"\n :value=\"node.listFilter?.comparator ?? ''\"\n :options=\"listFilterComparators\"\n placeholder=\"操作符\"\n :size=\"size\"\n class=\"!w-[80px]\"\n :disabled=\"disabled\"\n @update:value=\"updateListFilterComparator\"\n />\n <template v-if=\"hasFilterValue && selectedElementFieldType\">\n <n-input-number\n v-if=\"selectedElementFieldType === 'number'\"\n :value=\"listFilterLiteralValue !== '' ? Number(listFilterLiteralValue) : null\"\n :size=\"size\"\n class=\"!w-[100px]\"\n :disabled=\"disabled\"\n @update:value=\"(v: number | null) => updateListFilterValue(v ?? 0)\"\n />\n <n-input\n v-else\n :value=\"listFilterLiteralValue\"\n :size=\"size\"\n class=\"!w-[120px]\"\n :disabled=\"disabled\"\n placeholder=\"文本…\"\n @update:value=\"(v: string) => updateListFilterValue(v)\"\n />\n </template>\n </template>\n </div>\n </div>\n </div>\n\n <!-- 预览 -->\n <div v-if=\"isConfigured\" class=\"flex items-center gap-1.5 px-2 py-1.5 rounded preview-block\">\n <span class=\"i-carbon:code text-xs flex-shrink-0 icon-muted\" />\n <code class=\"text-[11px] leading-none preview-code\">\n <span class=\"preview-left\">{{ summaryExpression.left || '…' }}</span>\n <span v-if=\"summaryExpression.op\" class=\"mx-1 preview-op\">{{ summaryExpression.op }}</span>\n <span v-if=\"summaryExpression.right\" class=\"preview-right\">{{ summaryExpression.right }}</span>\n </code>\n </div>\n </div>\n </Transition>\n </div>\n\n <!-- 分组节点 -->\n <div v-else class=\"relative group-root\" :class=\"[`theme--${props.theme}`, `size--${size}`, level > 0 ? 'ml-4' : '']\">\n <div v-if=\"level > 0\" class=\"group-connector\" />\n <div class=\"flex items-center gap-2 mb-2\">\n <div class=\"op-toggle\">\n <button v-for=\"opt in logicalOperatorOptions\" :key=\"opt.value\" class=\"op-toggle__btn\" :class=\"{\n 'op-toggle__btn--and': currentOperator === 'and' && opt.value === 'and',\n 'op-toggle__btn--or': currentOperator === 'or' && opt.value === 'or',\n 'op-toggle__btn--not': currentOperator === 'not' && opt.value === 'not',\n 'op-toggle__btn--off': currentOperator !== opt.value,\n }\" :disabled=\"disabled\" @click=\"handleOperatorChange(opt.value as LogicalOperator)\">{{ opt.label }}</button>\n </div>\n <div class=\"flex-1\" />\n <div class=\"flex items-center gap-1\">\n <n-button class=\"action-btn\" :size=\"size\" :disabled=\"disabled\" @click=\"handleAddCondition\"><template #icon><span class=\"i-carbon:add text-xs\" /></template>条件</n-button>\n <n-button class=\"action-btn\" :size=\"size\" :disabled=\"disabled\" @click=\"handleAddGroup\"><template #icon><span class=\"i-carbon:folder-add text-xs\" /></template>分组</n-button>\n <template v-if=\"level > 0\">\n <div class=\"w-px h-4 mx-0.5 divider\" />\n <n-button :size=\"size\" quaternary circle type=\"error\" :disabled=\"disabled\" @click=\"handleRemove\"><template #icon><span class=\"i-carbon:trash-can text-sm\" /></template></n-button>\n </template>\n </div>\n </div>\n <div class=\"relative pl-5\">\n <div v-if=\"node.children && node.children.length > 0\" class=\"group-vline\" />\n <div class=\"flex flex-col gap-1.5\">\n <template v-if=\"node.children && node.children.length > 0\">\n <div v-for=\"child in node.children\" :key=\"child.id\" class=\"relative\">\n <div class=\"group-hline\" />\n <RuleTreeNode :node=\"child\" :authentication=\"authentication\" :principal=\"principal\" :locals=\"locals\" :disabled=\"disabled\" :level=\"level + 1\" :theme=\"props.theme\" :size=\"size\"\n @add-condition=\"(id) => $emit('add-condition', id)\" @add-group=\"(id) => $emit('add-group', id)\"\n @remove-node=\"(id) => $emit('remove-node', id)\" @update-node=\"(id, updates) => $emit('update-node', id, updates)\" />\n </div>\n </template>\n <div v-else class=\"flex flex-col items-center justify-center py-6 rounded-md border border-dashed empty-state\">\n <span class=\"i-carbon:add-alt text-xl mb-1 icon-muted\" />\n <p class=\"text-[11px] text-placeholder\">暂无条件,点击右上方按钮添加</p>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n/* ─── Slide transition ─────────────────────────────────────────── */\n.slide-down-enter-active,\n.slide-down-leave-active {\n transition: max-height 0.2s ease, opacity 0.15s ease;\n max-height: 400px;\n overflow: hidden;\n}\n.slide-down-enter-from,\n.slide-down-leave-to {\n max-height: 0;\n opacity: 0;\n}\n\n/* ─── Condition card ───────────────────────────────────────────── */\n.theme--light.is-idle,\n.theme--dark.is-idle {\n background: var(--card-bg);\n border-color: var(--card-border-idle);\n}\n.theme--light.is-idle:hover,\n.theme--dark.is-idle:hover {\n border-color: var(--card-border-hover);\n}\n.theme--light.is-editing,\n.theme--dark.is-editing {\n background: var(--card-bg);\n border-color: var(--card-border-editing);\n box-shadow: var(--card-shadow-editing);\n}\n\n/* ─── Icon & text helpers ──────────────────────────────────────── */\n.icon-muted { color: var(--icon-muted); }\n.text-placeholder { color: var(--text-placeholder); }\n.text-secondary { color: var(--text-secondary); }\n\n/* ─── Expression chips ─────────────────────────────────────────── */\n.expr-chip {\n display: inline-flex;\n align-items: center;\n padding: 1px 6px;\n border-radius: 4px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.expr-chip--field {\n background: var(--expr-field-bg);\n color: var(--expr-field-fg);\n border: 1px solid var(--expr-field-border);\n}\n.expr-chip--op {\n background: var(--expr-op-bg);\n color: var(--expr-op-fg);\n border: 1px solid var(--expr-op-border);\n}\n.expr-chip--val {\n background: var(--expr-val-bg);\n color: var(--expr-val-fg);\n border: 1px solid var(--expr-val-border);\n}\n\n/* ─── Expression block ─────────────────────────────────────────── */\n.expr-block {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n.expr-block__label {\n font-size: 10px;\n color: var(--expr-block-label);\n padding-left: 2px;\n letter-spacing: 0.3px;\n}\n.expr-block__body {\n display: flex;\n align-items: center;\n gap: 4px;\n flex-wrap: wrap;\n padding: 5px 8px;\n background: var(--expr-block-body-bg);\n border: 1px solid var(--expr-block-body-border);\n border-radius: 6px;\n min-height: 36px;\n}\n\n/* ─── Edit panel ───────────────────────────────────────────────── */\n.edit-panel {\n background: var(--edit-panel-bg);\n border-color: var(--edit-panel-border);\n}\n\n/* ─── Preview block ────────────────────────────────────────────── */\n.preview-block {\n background: var(--preview-bg);\n border: 1px solid var(--preview-border);\n}\n.preview-code {\n color: var(--preview-text);\n}\n.preview-left {\n color: var(--preview-left);\n}\n.preview-op {\n color: var(--preview-op);\n}\n.preview-right {\n color: var(--preview-right);\n}\n\n/* ─── Operator toggle ──────────────────────────────────────────── */\n.op-toggle {\n display: inline-flex;\n border: 1px solid var(--op-toggle-border);\n border-radius: 5px;\n overflow: hidden;\n box-shadow: var(--op-toggle-shadow);\n}\n.op-toggle__btn {\n padding: 0 12px;\n height: 26px;\n font-size: 12px;\n font-weight: 600;\n border: none;\n border-right: 1px solid var(--op-toggle-btn-border);\n background: var(--op-toggle-btn-bg);\n color: var(--op-toggle-btn-fg);\n cursor: pointer;\n transition: background 0.1s, color 0.1s;\n}\n.op-toggle__btn:last-child { border-right: none; }\n.op-toggle__btn:disabled { cursor: not-allowed; opacity: 0.5; }\n.op-toggle__btn--off:not(:disabled):hover {\n background: var(--op-toggle-btn-hover-bg);\n color: var(--op-toggle-btn-hover-fg);\n}\n.op-toggle__btn--and:not(.op-toggle__btn--off) {\n background: var(--op-toggle-and-bg);\n color: var(--op-toggle-active-fg);\n}\n.op-toggle__btn--or:not(.op-toggle__btn--off) {\n background: var(--op-toggle-or-bg);\n color: var(--op-toggle-active-fg);\n}\n.op-toggle__btn--not:not(.op-toggle__btn--off) {\n background: var(--op-toggle-not-bg);\n color: var(--op-toggle-active-fg);\n}\n\n/* ─── Connectors & lines ───────────────────────────────────────── */\n.group-vline {\n position: absolute;\n left: 7px;\n top: 0;\n bottom: 12px;\n width: 1px;\n background: var(--connector-color);\n}\n.group-hline {\n position: absolute;\n left: -13px;\n top: 17px;\n width: 13px;\n height: 1px;\n background: var(--connector-color);\n}\n.group-connector {\n position: absolute;\n left: -9px;\n top: 17px;\n width: 9px;\n height: 1px;\n background: var(--connector-color);\n}\n\n/* ─── Empty state ──────────────────────────────────────────────── */\n.empty-state {\n border-color: var(--empty-border);\n color: var(--empty-fg);\n}\n\n/* ─── Divider ──────────────────────────────────────────────────── */\n.divider {\n background: var(--divider-bg);\n}\n\n/* ─── Action buttons ───────────────────────────────────────────── */\n.action-btn {\n background: #7c3aed !important;\n border-color: #7c3aed !important;\n color: #ffffff !important;\n\n transition:\n background 0.2s ease,\n border-color 0.2s ease,\n box-shadow 0.2s ease;\n}\n\n.action-btn:hover {\n background: #6d28d9 !important;\n border-color: #6d28d9 !important;\n\n box-shadow: 0 2px 8px rgba(124, 58, 237, 0.28);\n}\n\n.action-btn:active {\n background: #5b21b6 !important;\n border-color: #5b21b6 !important;\n}\n\n.action-btn:disabled {\n opacity: 0.5 !important;\n box-shadow: none !important;\n}\n\n/* ─── Size variants ───────────────────────────────────────────── */\n/* tiny */\n.size--tiny .group\\/row { min-height: 28px; padding-left: 6px; padding-right: 6px; }\n.size--tiny .edit-panel { padding: 6px 8px; }\n.size--tiny .expr-block__body { padding: 3px 6px; min-height: 28px; }\n.size--tiny .expr-block__label { font-size: 9px; }\n.size--tiny .expr-chip { padding: 0 4px; font-size: 10px !important; }\n.size--tiny .op-toggle__btn { padding: 0 8px; height: 22px; font-size: 11px; }\n.size--tiny .action-btn { font-size: 11px !important; }\n.size--tiny .preview-block { padding: 4px 6px; }\n.size--tiny .preview-code { font-size: 10px !important; }\n.size--tiny .empty-state { padding: 12px 0; }\n.size--tiny .empty-state p { font-size: 10px; }\n\n/* small (default) */\n.size--small .group\\/row { min-height: 34px; padding-left: 10px; padding-right: 10px; }\n.size--small .edit-panel { padding: 12px; }\n.size--small .expr-block__body { padding: 5px 8px; min-height: 36px; }\n.size--small .expr-block__label { font-size: 10px; }\n.size--small .expr-chip { padding: 1px 6px; font-size: 11px !important; }\n.size--small .op-toggle__btn { padding: 0 12px; height: 26px; font-size: 12px; }\n.size--small .preview-block { padding: 6px 8px; }\n.size--small .preview-code { font-size: 11px !important; }\n.size--small .empty-state { padding: 24px 0; }\n\n/* medium */\n.size--medium .group\\/row { min-height: 40px; padding-left: 14px; padding-right: 14px; }\n.size--medium .edit-panel { padding: 16px; }\n.size--medium .expr-block__body { padding: 8px 12px; min-height: 44px; }\n.size--medium .expr-block__label { font-size: 11px; }\n.size--medium .expr-chip { padding: 2px 8px; font-size: 12px !important; }\n.size--medium .op-toggle__btn { padding: 0 16px; height: 30px; font-size: 13px; }\n.size--medium .preview-block { padding: 8px 12px; }\n.size--medium .preview-code { font-size: 12px !important; }\n.size--medium .empty-state { padding: 32px 0; }\n\n/* large */\n.size--large .group\\/row { min-height: 48px; padding-left: 18px; padding-right: 18px; }\n.size--large .edit-panel { padding: 20px; }\n.size--large .expr-block__body { padding: 10px 16px; min-height: 52px; }\n.size--large .expr-block__label { font-size: 12px; }\n.size--large .expr-chip { padding: 3px 10px; font-size: 13px !important; }\n.size--large .op-toggle__btn { padding: 0 20px; height: 34px; font-size: 14px; }\n.size--large .preview-block { padding: 10px 16px; }\n.size--large .preview-code { font-size: 13px !important; }\n.size--large .empty-state { padding: 40px 0; }\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useRuleTree } from '../../composables'\nimport type { RuleTreeProps, RuleTreeEmits, RuleTreeInstance } from '../../types'\nimport RuleTreeNode from './RuleTreeNode.vue'\nimport { NConfigProvider } from 'naive-ui'\nimport { darkTheme, lightTheme } from 'naive-ui'\n\nconst props = withDefaults(defineProps<RuleTreeProps>(), {\n theme: 'light',\n size: 'small',\n})\nconst emit = defineEmits<RuleTreeEmits>()\n\nconst { getSpelExpression, setSpelExpression, addCondition, addGroup, removeNode, updateNode, validate } = useRuleTree(props, emit)\n\ndefineExpose<RuleTreeInstance>({\n getSpelExpression,\n setSpelExpression,\n validate,\n})\n\nconst currentTheme = computed(() => props.theme === 'dark' ? darkTheme : lightTheme)\n</script>\n\n<template>\n <NConfigProvider :theme=\"currentTheme\">\n <div class=\"rule-tree-container\" :class=\"[`theme--${props.theme}`, `size--${props.size}`]\">\n <RuleTreeNode\n :node=\"modelValue\"\n :authentication=\"authentication\"\n :principal=\"principal\"\n :locals=\"locals\"\n :disabled=\"disabled\"\n :level=\"0\"\n :theme=\"props.theme\"\n :size=\"props.size\"\n @add-condition=\"addCondition\"\n @add-group=\"addGroup\"\n @remove-node=\"removeNode\"\n @update-node=\"updateNode\"\n />\n </div>\n </NConfigProvider>\n</template>\n\n<style scoped>\n/* ===================================================================\n Container\n =================================================================== */\n.rule-tree-container {\n padding: 16px;\n border-radius: 8px;\n min-height: 200px;\n transition: background 0.2s, border-color 0.2s;\n}\n\n/* ===================================================================\n CSS Custom Properties — Light & Dark themes\n Defined at the root container so all descendants inherit the correct values.\n =================================================================== */\n.rule-tree-container.theme--light {\n background: #f8fafc;\n\n --card-bg: #ffffff;\n --card-border-idle: #e5e7eb;\n --card-border-hover: #d1d5db;\n --card-border-editing: #60a5fa;\n --card-shadow-editing: 0 1px 3px rgba(0,0,0,.08);\n\n --edit-panel-bg: rgba(249, 250, 251, 0.8);\n --edit-panel-border: #f3f4f6;\n\n --preview-bg: #ffffff;\n --preview-border: #f3f4f6;\n --preview-text: #6b7280;\n --preview-left: #2563eb;\n --preview-op: #4b5563;\n --preview-right: #065f46;\n\n --text-primary: #1f2937;\n --text-secondary: #6b7280;\n --text-placeholder: #9ca3af;\n --text-muted: #d1d5db;\n --icon-muted: #9ca3af;\n\n --expr-field-bg: #eff6ff;\n --expr-field-fg: #1d4ed8;\n --expr-field-border: #bfdbfe;\n\n --expr-op-bg: #f3f4f6;\n --expr-op-fg: #1f2937;\n --expr-op-border: #d1d5db;\n\n --expr-val-bg: #ecfdf5;\n --expr-val-fg: #065f46;\n --expr-val-border: #a7f3d0;\n\n --expr-block-body-bg: #ffffff;\n --expr-block-body-border: #e5e7eb;\n --expr-block-label: #9ca3af;\n\n --op-toggle-border: #d1d5db;\n --op-toggle-shadow: 0 1px 2px rgba(0,0,0,.04);\n --op-toggle-btn-bg: #ffffff;\n --op-toggle-btn-fg: #6b7280;\n --op-toggle-btn-border: #e5e7eb;\n --op-toggle-btn-hover-bg: #f9fafb;\n --op-toggle-btn-hover-fg: #374151;\n --op-toggle-and-bg: #1d4ed8;\n --op-toggle-or-bg: #d97706;\n --op-toggle-not-bg: #dc2626;\n --op-toggle-active-fg: #ffffff;\n\n --connector-color: #e5e7eb;\n\n --empty-border: #e5e7eb;\n --empty-fg: #9ca3af;\n\n --divider-bg: #e5e7eb;\n}\n\n.rule-tree-container.theme--dark {\n background: #1a1a2e;\n\n --card-bg: #1e1e32;\n --card-border-idle: #3e3e5c;\n --card-border-hover: #5c5c7a;\n --card-border-editing: #60a5fa;\n --card-shadow-editing: 0 1px 6px rgba(96, 165, 250, 0.15);\n\n --edit-panel-bg: rgba(30, 30, 50, 0.85);\n --edit-panel-border: #3e3e5c;\n\n --preview-bg: #252545;\n --preview-border: #3e3e5c;\n --preview-text: #9ca3af;\n --preview-left: #93c5fd;\n --preview-op: #d1d5db;\n --preview-right: #6ee7b7;\n\n --text-primary: #e5e5e5;\n --text-secondary: #9ca3af;\n --text-placeholder: #6b7280;\n --text-muted: #4b5563;\n --icon-muted: #6b7280;\n\n --expr-field-bg: rgba(59, 130, 246, 0.15);\n --expr-field-fg: #93c5fd;\n --expr-field-border: rgba(59, 130, 246, 0.3);\n\n --expr-op-bg: rgba(107, 114, 128, 0.2);\n --expr-op-fg: #d1d5db;\n --expr-op-border: rgba(107, 114, 128, 0.3);\n\n --expr-val-bg: rgba(16, 185, 129, 0.15);\n --expr-val-fg: #6ee7b7;\n --expr-val-border: rgba(16, 185, 129, 0.3);\n\n --expr-block-body-bg: #252545;\n --expr-block-body-border: #3e3e5c;\n --expr-block-label: #6b7280;\n\n --op-toggle-border: #3e3e5c;\n --op-toggle-shadow: 0 1px 2px rgba(0,0,0,.2);\n --op-toggle-btn-bg: #252545;\n --op-toggle-btn-fg: #9ca3af;\n --op-toggle-btn-border: #3e3e5c;\n --op-toggle-btn-hover-bg: #2e2e52;\n --op-toggle-btn-hover-fg: #e5e5e5;\n --op-toggle-and-bg: #2563eb;\n --op-toggle-or-bg: #d97706;\n --op-toggle-not-bg: #dc2626;\n --op-toggle-active-fg: #ffffff;\n\n --connector-color: #3e3e5c;\n\n --empty-border: #3e3e5c;\n --empty-fg: #6b7280;\n\n --divider-bg: #3e3e5c;\n}\n\n/* ─── Size variants ────────────────────────────────────────────── */\n.rule-tree-container.size--tiny { padding: 8px; }\n.rule-tree-container.size--small { padding: 12px; }\n.rule-tree-container.size--medium { padding: 20px; }\n.rule-tree-container.size--large { padding: 28px; }\n</style>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useRuleTree } from '../../composables'\nimport type { RuleTreeProps, RuleTreeEmits, RuleTreeInstance } from '../../types'\nimport RuleTreeNode from './RuleTreeNode.vue'\nimport { NConfigProvider } from 'naive-ui'\nimport { darkTheme, lightTheme } from 'naive-ui'\n\nconst props = withDefaults(defineProps<RuleTreeProps>(), {\n theme: 'light',\n size: 'small',\n})\nconst emit = defineEmits<RuleTreeEmits>()\n\nconst { getSpelExpression, setSpelExpression, addCondition, addGroup, removeNode, updateNode, validate } = useRuleTree(props, emit)\n\ndefineExpose<RuleTreeInstance>({\n getSpelExpression,\n setSpelExpression,\n validate,\n})\n\nconst currentTheme = computed(() => props.theme === 'dark' ? darkTheme : lightTheme)\n</script>\n\n<template>\n <NConfigProvider :theme=\"currentTheme\">\n <div class=\"rule-tree-container\" :class=\"[`theme--${props.theme}`, `size--${props.size}`]\">\n <RuleTreeNode\n :node=\"modelValue\"\n :authentication=\"authentication\"\n :principal=\"principal\"\n :locals=\"locals\"\n :disabled=\"disabled\"\n :level=\"0\"\n :theme=\"props.theme\"\n :size=\"props.size\"\n @add-condition=\"addCondition\"\n @add-group=\"addGroup\"\n @remove-node=\"removeNode\"\n @update-node=\"updateNode\"\n />\n </div>\n </NConfigProvider>\n</template>\n\n<style scoped>\n/* ===================================================================\n Container\n =================================================================== */\n.rule-tree-container {\n padding: 16px;\n border-radius: 8px;\n min-height: 200px;\n transition: background 0.2s, border-color 0.2s;\n}\n\n/* ===================================================================\n CSS Custom Properties — Light & Dark themes\n Defined at the root container so all descendants inherit the correct values.\n =================================================================== */\n.rule-tree-container.theme--light {\n background: #f8fafc;\n\n --card-bg: #ffffff;\n --card-border-idle: #e5e7eb;\n --card-border-hover: #d1d5db;\n --card-border-editing: #60a5fa;\n --card-shadow-editing: 0 1px 3px rgba(0,0,0,.08);\n\n --edit-panel-bg: rgba(249, 250, 251, 0.8);\n --edit-panel-border: #f3f4f6;\n\n --preview-bg: #ffffff;\n --preview-border: #f3f4f6;\n --preview-text: #6b7280;\n --preview-left: #2563eb;\n --preview-op: #4b5563;\n --preview-right: #065f46;\n\n --text-primary: #1f2937;\n --text-secondary: #6b7280;\n --text-placeholder: #9ca3af;\n --text-muted: #d1d5db;\n --icon-muted: #9ca3af;\n\n --expr-field-bg: #eff6ff;\n --expr-field-fg: #1d4ed8;\n --expr-field-border: #bfdbfe;\n\n --expr-op-bg: #f3f4f6;\n --expr-op-fg: #1f2937;\n --expr-op-border: #d1d5db;\n\n --expr-val-bg: #ecfdf5;\n --expr-val-fg: #065f46;\n --expr-val-border: #a7f3d0;\n\n --expr-block-body-bg: #ffffff;\n --expr-block-body-border: #e5e7eb;\n --expr-block-label: #9ca3af;\n\n --op-toggle-border: #d1d5db;\n --op-toggle-shadow: 0 1px 2px rgba(0,0,0,.04);\n --op-toggle-btn-bg: #ffffff;\n --op-toggle-btn-fg: #6b7280;\n --op-toggle-btn-border: #e5e7eb;\n --op-toggle-btn-hover-bg: #f9fafb;\n --op-toggle-btn-hover-fg: #374151;\n --op-toggle-and-bg: #1d4ed8;\n --op-toggle-or-bg: #d97706;\n --op-toggle-not-bg: #dc2626;\n --op-toggle-active-fg: #ffffff;\n\n --connector-color: #e5e7eb;\n\n --empty-border: #e5e7eb;\n --empty-fg: #9ca3af;\n\n --divider-bg: #e5e7eb;\n}\n\n.rule-tree-container.theme--dark {\n background: #1a1a2e;\n\n --card-bg: #1e1e32;\n --card-border-idle: #3e3e5c;\n --card-border-hover: #5c5c7a;\n --card-border-editing: #60a5fa;\n --card-shadow-editing: 0 1px 6px rgba(96, 165, 250, 0.15);\n\n --edit-panel-bg: rgba(30, 30, 50, 0.85);\n --edit-panel-border: #3e3e5c;\n\n --preview-bg: #252545;\n --preview-border: #3e3e5c;\n --preview-text: #9ca3af;\n --preview-left: #93c5fd;\n --preview-op: #d1d5db;\n --preview-right: #6ee7b7;\n\n --text-primary: #e5e5e5;\n --text-secondary: #9ca3af;\n --text-placeholder: #6b7280;\n --text-muted: #4b5563;\n --icon-muted: #6b7280;\n\n --expr-field-bg: rgba(59, 130, 246, 0.15);\n --expr-field-fg: #93c5fd;\n --expr-field-border: rgba(59, 130, 246, 0.3);\n\n --expr-op-bg: rgba(107, 114, 128, 0.2);\n --expr-op-fg: #d1d5db;\n --expr-op-border: rgba(107, 114, 128, 0.3);\n\n --expr-val-bg: rgba(16, 185, 129, 0.15);\n --expr-val-fg: #6ee7b7;\n --expr-val-border: rgba(16, 185, 129, 0.3);\n\n --expr-block-body-bg: #252545;\n --expr-block-body-border: #3e3e5c;\n --expr-block-label: #6b7280;\n\n --op-toggle-border: #3e3e5c;\n --op-toggle-shadow: 0 1px 2px rgba(0,0,0,.2);\n --op-toggle-btn-bg: #252545;\n --op-toggle-btn-fg: #9ca3af;\n --op-toggle-btn-border: #3e3e5c;\n --op-toggle-btn-hover-bg: #2e2e52;\n --op-toggle-btn-hover-fg: #e5e5e5;\n --op-toggle-and-bg: #2563eb;\n --op-toggle-or-bg: #d97706;\n --op-toggle-not-bg: #dc2626;\n --op-toggle-active-fg: #ffffff;\n\n --connector-color: #3e3e5c;\n\n --empty-border: #3e3e5c;\n --empty-fg: #6b7280;\n\n --divider-bg: #3e3e5c;\n}\n\n/* ─── Size variants ────────────────────────────────────────────── */\n.rule-tree-container.size--tiny { padding: 8px; }\n.rule-tree-container.size--small { padding: 12px; }\n.rule-tree-container.size--medium { padding: 20px; }\n.rule-tree-container.size--large { padding: 28px; }\n</style>\n","import type { Comparator } from '../types'\n\nexport const DEFAULT_COMPARATORS: Comparator[] = [\n { value: '==', label: '等于', types: ['string', 'number', 'boolean', 'date'] },\n { value: '!=', label: '不等于', types: ['string', 'number', 'boolean', 'date'] },\n { value: '>', label: '大于', types: ['number', 'date'] },\n { value: '>=', label: '大于等于', types: ['number', 'date'] },\n { value: '<', label: '小于', types: ['number', 'date'] },\n { value: '<=', label: '小于等于', types: ['number', 'date'] },\n { value: 'contains', label: '包含', types: ['string'] },\n { value: 'startsWith', label: '开头', types: ['string'] },\n { value: 'endsWith', label: '结尾', types: ['string'] },\n { value: 'matches', label: '正则匹配', types: ['string'] },\n { value: 'in', label: '在列表中', types: ['string', 'number'] },\n { value: 'not in', label: '不在列表中', types: ['string', 'number'] },\n { value: 'isEmpty', label: '为空', types: ['string', 'array', 'object'] },\n { value: 'isNotEmpty', label: '不为空', types: ['string', 'array', 'object'] },\n]\n\nexport const GROUP_OPERATORS = [\n { value: 'and', label: '且' },\n { value: 'or', label: '或' },\n]\n\nexport const EDITOR_THEME = 'one-dark'\n\nexport const EDITOR_DEFAULT_HEIGHT = '400px'\n\nexport const RULE_TREE_DEFAULT_HEIGHT = '500px'\n"],"x_google_ignoreList":[1],"mappings":"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"}
|