@xw-components/formula-editor 18.1.0 → 18.1.1
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/esm2022/formula-editor-request.service.mjs +11 -5
- package/esm2022/formula-editor.component.mjs +195 -32
- package/esm2022/formula-editor.model.mjs +9 -1
- package/esm2022/formula-editor.service.mjs +3 -6
- package/fesm2022/formula-editor.mjs +214 -40
- package/fesm2022/formula-editor.mjs.map +1 -1
- package/formula-editor-request.service.d.ts +43 -8
- package/formula-editor.component.d.ts +169 -7
- package/formula-editor.model.d.ts +9 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formula-editor.mjs","sources":["../../../../components/formula-editor/formula-editor-request.service.ts","../../../../components/formula-editor/formula-editor.model.ts","../../../../components/formula-editor/formula-editor.service.ts","../../../../components/formula-editor/formula-editor-icon.ts","../../../../components/formula-editor/formula-editor.component.ts","../../../../components/formula-editor/formula-editor.component.html","../../../../components/formula-editor/formula-editor.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nimport { NzTreeNodeOptions } from 'ng-zorro-antd/tree';\n\nimport { Field, Func, ItemType } from './formula-editor.model';\nimport { ValidationResult } from './formula-editor.service';\n\nexport const FormulaEditorRequestServiceToken = new InjectionToken<FormulaEditorRequestService>('FormulaEditorRequestServiceToken');\n\n/**\n * 公式编辑器请求服务,用于获取函数列表、字段列表、指标列表和校验公式格式\n * 实现类需要实现四个方法。如果有部分方法不需要,可以实现空方法。\n */\nexport abstract class FormulaEditorRequestService {\n constructor() {}\n\n /**\n * 获取函数列表\n */\n abstract getFunctions(): Promise<NzTreeNodeOptions[]>;\n\n /**\n * 获取字段列表\n */\n abstract getFields(): Promise<Field[]>;\n\n /**\n * 校验公式格式\n * @param formula 公式字符串\n * @returns 校验结果\n */\n abstract validateFormula(formula: NzSafeAny): Promise<ValidationResult>;\n\n /**\n * 获取字段的描述\n * @param item 字段对象\n * @returns 描述字符串\n */\n getFieldDescription(): Promise<string> {\n return Promise.resolve('');\n }\n}\n","/**\n * 输入项类型,可选择指标模式或字段模式\n */\nexport enum ItemType {\n Field = 'field', // 字段模式\n Template = 'template' // 模板模式\n}\n\n/**\n * 输入校验格式方法\n */\nexport enum CheckFormatMethod {\n self = 'self', // 组件自带校验\n server = 'server' // 自定义异步校验\n}\n\nexport interface Field {\n id: string;\n name: string;\n image?: string; // 图标url\n icon?: string; // iconfont 图标名\n className?: string; // 类名,用于样式绑定\n description?: string; // 描述\n}\n\nexport interface Func {\n id: string;\n name: string;\n className?: string; // 类名,用于样式绑定\n description?: string; // 描述\n}\n\n/**\n * 函数列表模式,可选择列表或树模式\n */\nexport enum FuncListType {\n List = 'list', // 列表模式\n Tree = 'tree' // 树模式\n}\n\nexport const OPERATOR_LIST = [\n {\n type: 'add',\n name: '+',\n description: '加法'\n },\n {\n type: 'minus',\n name: '-',\n description: '减法'\n },\n {\n type: 'multiply',\n name: '*',\n description: '乘法'\n },\n {\n type: 'divide',\n name: '/',\n description: '除法'\n },\n {\n type: 'left-parenthesis',\n name: '(',\n description: '左括号'\n },\n {\n type: 'right-parenthesis',\n name: ')',\n description: '右括号'\n }\n];\n","import { style } from '@angular/animations';\nimport { inject, Injectable } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { Editor, Node, mergeAttributes } from '@tiptap/core';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nexport interface ValidationResult {\n isValid: boolean;\n errors: string[];\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class FormulaEditorService {\n private readonly sanitizer: DomSanitizer = inject(DomSanitizer);\n funcNode?: Node;\n fieldNode?: Node;\n paramNode?: Node;\n\n initNodes() {\n this.createFuncNode();\n this.createFieldNode();\n }\n\n createFieldNode() {\n this.fieldNode = Node.create({\n name: 'field',\n inline: true,\n group: 'inline',\n selectable: false,\n draggable: true,\n atom: true,\n addAttributes() {\n return {\n id: {\n default: null\n },\n name: {\n default: ''\n },\n className: {\n default: ''\n },\n dataType: {\n default: 'field'\n }\n };\n },\n renderText({ node }) {\n return `${node.attrs['name']}`;\n },\n parseHTML() {\n return [{ tag: 'div[data-type=\"field\"]' }];\n },\n renderHTML({ HTMLAttributes, node }) {\n return [\n 'div',\n mergeAttributes(\n {\n 'data-type': 'field',\n class: `field-node ${node.attrs['className']}` || '',\n contenteditable: 'false',\n style: `display: inline-block;margin: 0 4px;font-size: 13px;height: 18px;line-height: 18px;`\n },\n HTMLAttributes\n ),\n node.attrs['name']\n ];\n }\n });\n }\n\n createFuncNode() {\n this.funcNode = Node.create({\n name: 'func',\n inline: true,\n group: 'inline',\n selectable: false,\n draggable: false,\n content: 'inline*',\n atom: true,\n addAttributes() {\n return {\n id: {\n default: null\n },\n name: {\n default: ''\n },\n className: {\n default: ''\n },\n dataType: {\n default: 'func'\n }\n };\n },\n renderText({ node }) {\n const funcName = node.attrs['name'] || '';\n const childrenText = node.content.content\n .map(child => {\n if (child.text) {\n return child.text;\n }\n if (child.type && child.type.spec && child.type.spec['toText']) {\n return child.type.spec['toText']({ node: child });\n }\n return '';\n })\n .join('');\n return `${funcName}(${childrenText})`;\n },\n parseHTML() {\n return [{ tag: 'div[data-type=\"func\"]' }];\n },\n addNodeView() {\n return ({ node }) => {\n const createElement = (tag: string, props: Record<string, any> = {}) => {\n const element = document.createElement(tag);\n Object.entries(props).forEach(([key, value]) => {\n if (key === 'style') {\n Object.entries(value).forEach(([styleKey, styleValue]) => {\n (element.style as any)[styleKey] = styleValue;\n });\n } else if (key === 'innerText') {\n element.innerText = value;\n } else if (key === 'className') {\n element.className = value;\n } else {\n element.setAttribute(key, value);\n }\n });\n return element;\n };\n\n const className = node.attrs['className'] || '';\n const funcName = node.attrs['name'];\n\n const container = createElement('span', {\n style: {\n display: 'inline-block',\n margin: '0 4px',\n fontSize: '13px'\n }\n });\n\n const content = createElement('span', {\n style: {\n whiteSpace: 'pre-wrap',\n display: 'inline-block'\n },\n contenteditable: 'true'\n });\n\n const before = createElement('span', {\n innerText: `${funcName} `,\n contenteditable: 'false',\n className\n });\n\n const bracket = (value: string, style: Record<string, any> = {}) => {\n return createElement('span', {\n innerText: value,\n contenteditable: 'false',\n style: {\n ...style\n }\n });\n };\n\n container.append(before, bracket('(', { marginRight: '2px' }), content, bracket(')', { marginLeft: '2px' }));\n\n return {\n dom: container,\n contentDOM: content\n };\n };\n }\n });\n }\n\n /**\n * 校验公式的JSON表示是否有效\n * @param formula 公式的JSON表示\n * @returns 校验结果,包含是否有效和错误信息数组\n */\n public validateFormula(formula: any): ValidationResult {\n const errors: string[] = [];\n\n if (!formula) {\n errors.push('公式不能为空');\n return { isValid: false, errors };\n }\n\n if (formula.type !== 'doc') {\n errors.push('公式根节点类型必须是 doc');\n }\n\n if (!formula.content || !Array.isArray(formula.content)) {\n errors.push('公式必须包含 content 数组');\n return { isValid: false, errors };\n }\n\n for (const paragraph of formula.content) {\n if (paragraph.type !== 'paragraph') {\n errors.push('段落类型必须是 paragraph');\n continue;\n }\n\n if (!paragraph.content || !Array.isArray(paragraph.content)) {\n continue;\n }\n\n for (const node of paragraph.content) {\n this.validateNode(node, errors);\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors\n };\n }\n\n /**\n * 从JSON数据中提取内容文本或HTML\n * @param jsonData 公式的JSON表示\n * @param outputFormat 输出格式,'text'或'html',默认'text'\n * @returns 提取的内容文本或HTML字符串\n */\n public getContentFromJson(jsonData: NzSafeAny, outputFormat: 'text' | 'html' = 'text'): string | SafeHtml {\n if (!jsonData || !jsonData.content) return '';\n return outputFormat === 'html'\n ? this.sanitizer.bypassSecurityTrustHtml(this.processContentToHtml(jsonData.content))\n : this.processContent(jsonData.content);\n }\n\n private processContent(content: any[]): string {\n if (!content || !Array.isArray(content)) return '';\n return content.map(item => this.processNode(item)).join('');\n }\n\n private processNode(node: any): string {\n if (!node) return '';\n\n switch (node.type) {\n case 'func':\n return this.processFuncNode(node);\n case 'field':\n return `{${node.attrs?.name || ''}}`;\n case 'metric':\n return `[${node.attrs?.name || ''}]`;\n case 'text':\n return node.text || '';\n case 'paragraph':\n return this.processContent(node.content);\n case 'doc':\n return this.processContent(node.content);\n default:\n return '';\n }\n }\n\n private processFuncNode(node: any): string {\n const funcName = node.attrs?.name || '';\n const content = this.processContent(node.content);\n return `${funcName}(${content})`;\n }\n\n private processContentToHtml(content: any[]): string {\n if (!content || !Array.isArray(content)) return '';\n\n return content.map(item => this.processNodeToHtml(item)).join('');\n }\n\n private processNodeToHtml(node: any): string {\n if (!node) return '';\n\n switch (node.type) {\n case 'func':\n return this.processFuncNodeToHtml(node);\n case 'field':\n return `<span class=\"${node.attrs?.className || ''}\" style=\"display: inline-block; margin: 0 4px;height: 18px;line-height: 18px;\">${node.attrs?.name || ''}</span>`;\n case 'text':\n return this.escapeHtml(node.text || '');\n case 'paragraph':\n return this.processContentToHtml(node.content);\n case 'doc':\n return this.processContentToHtml(node.content);\n default:\n return '';\n }\n }\n\n private processFuncNodeToHtml(node: any): string {\n const funcName = node.attrs?.name || '';\n const className = node.attrs?.className || '';\n const content = this.processContentToHtml(node.content);\n\n return `<span style=\"display: inline-block; margin: 0 4px;\"><span contenteditable=\"false\" class=\"${className}\">${funcName}(</span><span style=\"white-space: pre-wrap; display: inline-block; margin: 0 4px;\" contenteditable=\"true\">${content}</span><span contenteditable=\"false\" class=\"${className}\">)</span></span>`;\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n private validateNode(node: any, errors: string[], path: string = ''): void {\n if (!node || !node.type) {\n return;\n }\n\n const currentPath = path ? `${path} > ${node.type}` : node.type;\n\n if (node.type === 'func') {\n this.validateFuncNode(node, errors, currentPath);\n }\n }\n\n private validateFuncNode(node: any, errors: string[], path: string): void {\n if (!node.content || !Array.isArray(node.content)) {\n return;\n }\n\n const content = node.content;\n const length = content.length;\n\n for (let i = 0; i < length; i++) {\n const currentItem = content[i];\n const nextItem = content[i + 1];\n\n if (currentItem.type === 'field' || currentItem.type === 'func') {\n if (i < length - 1) {\n if (nextItem && nextItem.type === 'text') {\n const text = nextItem.text || '';\n if (!text.startsWith(',')) {\n errors.push(`${path}: 参数之间必须用逗号分隔,位置 ${i + 1}`);\n }\n } else {\n errors.push(`${path}: 参数之间必须用逗号分隔,位置 ${i + 1}`);\n }\n }\n }\n\n if (currentItem.type === 'func') {\n this.validateFuncNode(currentItem, errors, `${path} > ${currentItem.attrs?.name || 'func'}`);\n }\n }\n }\n}\n","export const ICONS = {\r\n cheng: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M460.8 896c-7.1 0-12.8-5.7-12.8-12.8V614.8L268.8 794c-5 5-13.1 5.1-18.1 0.1l-0.1-0.1-49.5-49.8c-5-5-5.1-13.1-0.1-18.1l0.1-0.1L383 544.1H140.8c-7.1 0-12.8-5.7-12.8-12.8v-70.4c0-7.1 5.7-12.8 12.8-12.8h239.4L200.9 268.9c-5-5-5.1-13.1-0.1-18.1l0.1-0.1 49.5-49.8c5-5 13.1-5.1 18.1-0.1l0.1 0.1 179.2 179.2V140.8c0-7.1 5.7-12.8 12.8-12.8H531c7.1 0 12.8 5.7 12.8 12.8v242.3L725.9 201c5-4.9 12.9-4.9 17.9 0l49.8 49.8c5 5 5.1 13.1 0.1 18.1l-0.1 0.1-179.2 179.1h268.4c7.1 0 12.8 5.7 12.8 12.8v70.4c0 7.1-5.7 12.8-12.8 12.8H611.6L793.5 726c5 5 5.1 13.1 0.1 18.1l-0.1 0.1-49.8 49.8c-5 4.9-12.9 4.9-17.9 0L543.7 611.8v271.6c0 7.1-5.7 12.8-12.8 12.8l-70.1-0.2z\" /></svg>`,\r\n chu: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M808.3 283.6L283.6 808.3c-5 5-13.1 5-18.1 0l-49.8-49.8c-5-5-5-13.1 0-18.1l524.7-524.7c5-5 13.1-5 18.1 0l49.8 49.8c4.9 5 4.9 13.1 0 18.1z\" /></svg>`,\r\n jia: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M476.8 896c-7.1 0-12.8-5.7-12.8-12.8V560H140.8c-7.1 0-12.8-5.7-12.8-12.8v-70.4c0-7.1 5.7-12.8 12.8-12.8H464V140.8c0-7.1 5.7-12.8 12.8-12.8h70.4c7.1 0 12.8 5.7 12.8 12.8V464h323.2c7.1 0 12.8 5.7 12.8 12.8v70.4c0 7.1-5.7 12.8-12.8 12.8H560v323.2c-0.2 7-5.8 12.7-12.8 12.8h-70.4z\" /></svg>`,\r\n jian: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M140.8 464h742.4c7.1 0 12.8 5.7 12.8 12.8v70.4c0 7.1-5.7 12.8-12.8 12.8H140.8c-7.1 0-12.8-5.7-12.8-12.8v-70.4c0-7.1 5.7-12.8 12.8-12.8z\" /></svg>`,\r\n youkuohao: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M416 163c38.7 49.3 68.8 104.8 88.9 164.1 19.8 59.6 29.7 122.1 29.3 184.9 1.1 62.3-8.5 124.2-28.4 183.2-23.2 59.2-53.3 115.4-89.8 167.4l56.9 33.3c42.9-56 76.8-118.4 100.4-184.9 23.2-64.1 34.9-131.8 34.7-199.9 0.3-69.3-11.4-138-34.7-203.3-23.2-65-57.2-125.8-100.4-179.8L416 163z\" /></svg>`,\r\n zuokuohao: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M608 163c-38.7 49.3-68.8 104.8-88.9 164.1-19.8 59.6-29.7 122.1-29.3 184.9-1.1 62.3 8.5 124.2 28.4 183.2 23.1 59.2 53.2 115.4 89.6 167.4L550.9 896c-42.8-56-76.6-118.4-100.2-184.9-23.2-64.1-34.9-131.8-34.7-199.9-0.3-69.3 11.4-138 34.7-203.3C473.9 242.8 507.9 182 551.1 128l56.9 35z\" /></svg>`\r\n};\r\n","import { CommonModule } from '@angular/common';\nimport { Component, effect, ElementRef, inject, input, signal, Signal, ViewChild, AfterViewInit, OnInit, TemplateRef } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { Editor } from '@tiptap/core';\nimport StarterKit from '@tiptap/starter-kit';\nimport { NzButtonModule } from 'ng-zorro-antd/button';\nimport { NzHighlightPipe } from 'ng-zorro-antd/core/highlight';\nimport { NzColDirective, NzGridModule } from 'ng-zorro-antd/grid';\nimport { NzIconModule } from 'ng-zorro-antd/icon';\nimport { NzInputModule } from 'ng-zorro-antd/input';\nimport { NzMessageService } from 'ng-zorro-antd/message';\nimport { NzToolTipModule } from 'ng-zorro-antd/tooltip';\nimport { NzFormatEmitEvent, NzTreeModule, NzTreeNodeOptions } from 'ng-zorro-antd/tree';\n\nimport { FormulaEditorRequestService, FormulaEditorRequestServiceToken } from './formula-editor-request.service';\nimport { CheckFormatMethod, Field, Func, FuncListType, ItemType, OPERATOR_LIST } from './formula-editor.model';\nimport { FormulaEditorService, ValidationResult } from './formula-editor.service';\nimport { ICONS } from './formula-editor-icon';\nimport { DomSanitizer } from '@angular/platform-browser';\n\n/**\n * 公式编辑器组件\n * 用于创建和编辑计算公式,支持函数、指标和字段的插入与验证\n * 依赖className与在使用组件处使用穿透样式实现样式\n */\n@Component({\n selector: 'app-formula-editor',\n standalone: true,\n imports: [\n NzColDirective,\n NzGridModule,\n NzInputModule,\n FormsModule,\n NzIconModule,\n CommonModule,\n NzTreeModule,\n NzButtonModule,\n NzToolTipModule,\n NzHighlightPipe\n ],\n templateUrl: './formula-editor.component.html',\n styleUrls: ['./formula-editor.component.less']\n})\nexport class FormulaEditorComponent implements AfterViewInit, OnInit {\n private readonly formulaEditorService = inject(FormulaEditorService);\n private readonly sanitizer = inject(DomSanitizer);\n private readonly msg = inject(NzMessageService);\n private readonly formulaEditorRequestService = inject<FormulaEditorRequestService>(FormulaEditorRequestServiceToken);\n @ViewChild('editor') editor!: ElementRef;\n\n /**\n * 项目类型,决定显示字段或自定义\n * 默认值:ItemType.Field\n */\n itemType = input<ItemType>(ItemType.Field);\n\n /**\n * 字段标题,当项目类型为字段时显示\n * 默认值:'字段'\n */\n fieldTitle = input<string>('字段');\n\n /**\n * 格式检查方法\n * 默认值:CheckFormatMethod.self\n */\n checkFormatMethod = input<CheckFormatMethod>(CheckFormatMethod.self);\n\n /**\n * 函数列表显示类型\n * 默认值:FuncListType.Tree\n */\n functionListType = input<FuncListType>(FuncListType.Tree);\n\n itemTemplate = input<TemplateRef<void> | null>(null);\n\n readonly _itemType = ItemType;\n readonly _funcListType = FuncListType;\n\n searchWord: string = '';\n\n fieldListOrigin: Field[] = [];\n fieldList: Field[] = [];\n\n editorObj!: Editor;\n checkLoading: boolean = false;\n showDescription: boolean = true;\n\n funcNode: NzTreeNodeOptions[] = [];\n fieldDescription: string = '';\n editDescription: string = '请选择函数';\n\n editDescShow: 'func' | 'error' | 'none' = 'none';\n\n searchField: Signal<string> = signal('');\n searchFunction: Signal<string> = signal('');\n\n _operatorList = OPERATOR_LIST;\n\n getOperatorIcon(type: string): string {\n const iconMap: Record<string, string> = {\n add: ICONS.jia,\n minus: ICONS.jian,\n multiply: ICONS.cheng,\n divide: ICONS.chu,\n 'left-parenthesis': ICONS.zuokuohao,\n 'right-parenthesis': ICONS.youkuohao\n };\n return this.sanitizer.bypassSecurityTrustHtml(iconMap[type] || '') as string;\n }\n\n /**\n * 构造函数\n * 初始化信号监听,处理搜索和项目类型变化\n */\n\n constructor() {\n effect(() => {\n const searchWord = this.searchField();\n this.fieldList = this.fieldListOrigin.filter(item => item.name.includes(searchWord));\n });\n effect(() => {\n const itemType = this.itemType();\n if (itemType === ItemType.Field) {\n this.formulaEditorRequestService.getFields().then(res => {\n this.fieldListOrigin = res;\n this.fieldList = [...this.fieldListOrigin];\n });\n }\n });\n }\n\n ngOnInit() {\n this.formulaEditorRequestService.getFunctions().then(res => {\n this.funcNode = res;\n });\n this.formulaEditorRequestService.getFieldDescription().then(res => {\n this.fieldDescription = res;\n });\n }\n\n ngAfterViewInit() {\n this.formulaEditorService.initNodes();\n this.editorObj = new Editor({\n element: this.editor.nativeElement,\n extensions: [\n StarterKit.configure({\n blockquote: false,\n codeBlock: false,\n code: false\n }),\n this.formulaEditorService.funcNode!,\n this.formulaEditorService.fieldNode!\n ]\n });\n }\n\n insertFunc(func: Func) {\n this.editorObj\n .chain()\n .insertContent({\n type: 'func',\n attrs: {\n name: func.name,\n id: func.id,\n className: `text-func-${func.className}`\n },\n content: []\n })\n .focus()\n .run();\n }\n\n insertField(field: Field) {\n this.editorObj\n .chain()\n .insertContent({\n type: 'field',\n attrs: {\n name: field.name,\n id: field.id,\n className: `text-field-${field.className}`\n }\n })\n .focus()\n .run();\n }\n\n insertOperator(operator: string) {\n this.editorObj\n .chain()\n .insertContent({\n type: 'text',\n text: operator\n })\n .focus()\n .run();\n }\n\n functionClick(node: NzFormatEmitEvent) {\n const func = node.node!.origin as unknown as Func;\n this.editDescription = func.description || '';\n this.editDescShow = 'func';\n this.insertFunc(func);\n }\n\n /**\n * 获取公式JSON\n * @returns 公式的JSON表示\n * @example\n * // 返回示例\n * {\n * \"type\": \"doc\",\n * \"content\": [\n * {\n * \"type\": \"paragraph\",\n * \"content\": [\n * {\n * \"type\": \"func\",\n * \"attrs\": {\n * \"name\": \"SUM\",\n * \"id\": \"sum\",\n * \"className\": \"text-func-agg\"\n * }\n * }\n * ]\n * }\n * ]\n * }\n */\n public getFormula() {\n const formula = this.editorObj.getJSON();\n return formula;\n }\n\n /**\n * 获取公式文本\n * @returns 公式的纯文本表示\n * @example\n * // 返回示例\n * \"SUM(field1, field2)\"\n */\n public getFormulaText() {\n const formulaText = this.editorObj.getText();\n return formulaText;\n }\n\n checkFormat() {\n if (this.checkFormatMethod() === CheckFormatMethod.self) {\n const result = this.validateFormula();\n if (result.isValid) {\n this.msg.success('格式校验通过');\n } else {\n this.msg.error(`格式校验不通过: ${result.errors.join(', ')}`);\n this.editDescription = result.errors.join(', ');\n this.editDescShow = 'error';\n }\n } else {\n this.checkLoading = true;\n this.formulaEditorRequestService.validateFormula(this.getFormula()).then(res => {\n this.checkLoading = false;\n if (res.isValid) {\n this.msg.success('格式校验通过');\n } else {\n this.msg.error(`格式校验不通过: ${res.errors.join(', ')}`);\n this.editDescription = res.errors.join(', ');\n this.editDescShow = 'error';\n }\n });\n }\n }\n\n /**\n * 从JSON加载公式\n * @param formula 公式的JSON表示\n * @example\n * // 使用示例\n * const formula = {\n * \"type\": \"doc\",\n * \"content\": [\n * {\n * \"type\": \"paragraph\",\n * \"content\": [\n * {\n * \"type\": \"func\",\n * \"attrs\": {\n * \"name\": \"SUM\",\n * \"id\": \"sum\",\n * \"className\": \"text-func-agg\"\n * }\n * }\n * ]\n * }\n * ]\n * };\n * formulaEditor.loadFormula(formula);\n */\n public loadFormula(formula: any) {\n if (!formula || !this.editorObj) {\n return;\n }\n this.editorObj.commands.setContent(formula);\n }\n\n // 校验公式\n validateFormula(): ValidationResult {\n const formula = this.editorObj.getJSON();\n const result = this.formulaEditorService.validateFormula(formula);\n return result;\n }\n\n toggleDescription() {\n this.showDescription = !this.showDescription;\n }\n}\n","<div nz-row class=\"formula-editor\">\n <div nz-col nzSpan=\"10\" class=\"editor-box\">\n <div class=\"editor-title\">\n <div class=\"label-title label-require\">字段表达式</div>\n <button nz-button nzType=\"link\" nzSize=\"small\" [nzLoading]=\"checkLoading\" (click)=\"checkFormat()\">格式校验</button>\n </div>\n <div class=\"edit-box\">\n <div class=\"edit-operation-box\">\n @for (item of _operatorList; track item) {\n <div class=\"edit-operation-item\" (click)=\"insertOperator(item.name)\">\n <span class=\"operator-icon\" [innerHTML]=\"getOperatorIcon(item.type)\"></span>\n </div>\n }\n </div>\n <div #editor class=\"editor\"></div>\n @if (editDescShow !== 'none') {\n <div class=\"edit-description-box\">\n <div class=\"edit-description-head\" [style]=\"{ marginBottom: !showDescription ? '10px' : '0' }\">\n <span class=\"edit-description-title\">{{ editDescShow === 'func' ? '函数释义' : '校验错误信息' }}</span>\n <span\n class=\"edit-description-icon\"\n nz-icon\n [nzType]=\"showDescription ? 'down' : 'up'\"\n nzTheme=\"outline\"\n (click)=\"toggleDescription()\"\n ></span>\n </div>\n @if (showDescription) {\n <div class=\"edit-description-text\"> {{ editDescription }} </div>\n }\n </div>\n }\n </div>\n </div>\n @switch (itemType()) {\n @case (_itemType.Field) {\n <div nz-col nzSpan=\"7\" class=\"field-box\">\n <div class=\"label-title\"\n >{{ fieldTitle() }}\n @if (fieldDescription) {\n <span nz-icon nzType=\"question-circle\" nzTheme=\"outline\" nz-tooltip [nzTooltipTitle]=\"fieldDescription\"></span>\n }\n </div>\n <nz-input-group [nzSuffix]=\"suffixIconSearch\">\n <input type=\"text\" nz-input placeholder=\"搜索\" [(ngModel)]=\"searchField\" />\n </nz-input-group>\n <ng-template #suffixIconSearch>\n <i nz-icon nzType=\"search\"></i>\n </ng-template>\n <div class=\"field-list\">\n @for (item of fieldList; track item) {\n <div (click)=\"insertField(item)\" [class]=\"item.className ? 'item-field-' + item.className : ''\" class=\"field-list-item\">\n @if (item.image) {\n <img class=\"field-img\" [src]=\"item.image\" />\n }\n @if (item.icon) {\n <span class=\"field-icon\" nz-icon [nzIconfont]=\"item.icon\"></span>\n }\n <span class=\"field-name\" [innerHTML]=\"item.name | nzHighlight: searchField() : 'i' : 'node-highlight'\"></span>\n @if (item.description) {\n <span\n class=\"desc-icon\"\n nz-icon\n nzType=\"question-circle\"\n nzTheme=\"outline\"\n nz-tooltip\n [nzTooltipTitle]=\"item.description\"\n ></span>\n }\n </div>\n }\n </div>\n </div>\n }\n @case (_itemType.Template) {\n <div nz-col nzSpan=\"7\" class=\"field-box\">\n <ng-container *ngTemplateOutlet=\"itemTemplate()\"></ng-container>\n </div>\n }\n }\n <div nz-col nzSpan=\"7\" class=\"function-box\">\n <div class=\"label-title\">函数</div>\n <nz-input-group [nzSuffix]=\"suffixIconSearch\">\n <input type=\"text\" nz-input placeholder=\"搜索\" [(ngModel)]=\"searchFunction\" />\n </nz-input-group>\n <ng-template #suffixIconSearch>\n <i nz-icon nzType=\"search\"></i>\n </ng-template>\n <nz-tree\n class=\"function-tree\"\n [nzHideUnMatched]=\"true\"\n [nzSearchValue]=\"searchFunction()\"\n [nzTreeTemplate]=\"nzTreeTemplate\"\n [nzData]=\"funcNode\"\n [nzShowExpand]=\"functionListType() === _funcListType.Tree\"\n (nzClick)=\"functionClick($event)\"\n ></nz-tree>\n <ng-template #nzTreeTemplate let-node let-origin=\"origin\">\n <span class=\"custom-node\" [innerHTML]=\"origin.name | nzHighlight: searchFunction() : 'i' : 'node-highlight'\">\n @if (origin.description) {\n <span\n class=\"desc-icon\"\n nz-icon\n nzType=\"question-circle\"\n nzTheme=\"outline\"\n nz-tooltip\n [nzTooltipTitle]=\"origin.description\"\n ></span>\n }\n </span>\n </ng-template>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"formula-editor.mjs","sources":["../../../../components/formula-editor/formula-editor-request.service.ts","../../../../components/formula-editor/formula-editor.model.ts","../../../../components/formula-editor/formula-editor.service.ts","../../../../components/formula-editor/formula-editor-icon.ts","../../../../components/formula-editor/formula-editor.component.ts","../../../../components/formula-editor/formula-editor.component.html","../../../../components/formula-editor/formula-editor.ts"],"sourcesContent":["import { InjectionToken, WritableSignal } from '@angular/core';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nimport { NzTreeNodeOptions } from 'ng-zorro-antd/tree';\n\nimport { Field, Func, ItemType } from './formula-editor.model';\nimport { ValidationResult } from './formula-editor.service';\n\nexport const FormulaEditorRequestServiceToken = new InjectionToken<FormulaEditorRequestService>('FormulaEditorRequestServiceToken');\n\n/**\n * 公式编辑器请求服务,用于获取函数列表、字段列表、指标列表和校验公式格式\n * 实现类需要实现四个方法。如果有部分方法不需要,可以实现空方法。\n */\nexport abstract class FormulaEditorRequestService {\n constructor() {}\n\n /**\n * 获取函数列表\n * 实现类需要根据前n个选择框的值来动态获取下一个选择框的选项\n * 例如:\n * ```typescript\n * getFunctions(functionList: WritableSignal<NzTreeNodeOptions[]>) {\n * functionList.set([\n * { title: 'SUM', key: 'sum', className: 'sum' },\n * { title: 'AVG', key: 'avg', className: 'avg' }\n * ]);\n * }\n * ```\n * @param functionList 函数列表信号量\n */\n abstract getFunctions(functionList: WritableSignal<NzTreeNodeOptions[]>): void;\n\n /**\n * 获取字段列表\n * 实现类需要根据前n个选择框的值来动态获取下一个选择框的选项\n * 例如:\n * ```typescript\n * getFields(fieldList: WritableSignal<Field[]>) {\n * fieldList.set([\n * { id: 'user', name: '用户', className: 'user' },\n * { id: 'order', name: '订单', className: 'user' }\n * ]);\n * }\n * ```\n * @param fieldList 字段列表信号量\n */\n abstract getFields(fieldList: WritableSignal<Field[]>): void;\n\n /**\n * 校验公式格式\n * 实现类需要根据公式字符串来校验格式是否正确\n * 例如:\n * ```typescript\n * validateFormula(formula: NzSafeAny, res: WritableSignal<ValidationResult | null>) {\n * res.set({ valid: true, message: '' });\n * }\n * ```\n * @param formula 公式字符串\n * @param res 字段列表信号量\n */\n abstract validateFormula(formula: NzSafeAny, res: WritableSignal<ValidationResult | null>): void;\n\n /**\n * 获取字段的描述\n * 实现类需要根据字段id来获取字段的描述\n * 例如:\n * ```typescript\n * getFieldDescription(description: WritableSignal<string>) {\n * description.set('');\n * }\n * ```\n * @param description 描述字符串信号量\n */\n getFieldDescription(description: WritableSignal<string>): void {\n description.set('');\n }\n}\n","/**\n * 输入项类型,可选择指标模式或字段模式\n */\nexport enum ItemType {\n Field = 'field', // 字段模式\n Template = 'template' // 模板模式\n}\n\n/**\n * 输入校验格式方法\n */\nexport enum CheckFormatMethod {\n self = 'self', // 组件自带校验\n server = 'server' // 自定义异步校验\n}\n\nexport interface Field {\n id: string;\n name: string;\n image?: string; // 图标url\n icon?: string; // iconfont 图标名\n className?: string; // 类名,用于样式绑定\n description?: string; // 描述\n}\n\nexport interface Func {\n id: string;\n name: string;\n className?: string; // 类名,用于样式绑定\n description?: string; // 描述\n}\n\n/**\n * 函数列表模式,可选择列表或树模式\n */\nexport enum FuncListType {\n List = 'list', // 列表模式\n Tree = 'tree' // 树模式\n}\n\nexport interface DefaultText {\n inputTitle?: string; // 输入项标题\n fieldTitle?: string; // 字段标题\n checkFormatTitle?: string; // 校验格式标题\n functionTitle?: string; // 函数标题\n searchFieldPlaceholder?: string; // 搜索字段占位符\n searchFunctionPlaceholder?: string; // 搜索函数占位符\n}\n\nexport const DEFAULT_TEXT: DefaultText = {\n inputTitle: '字段表达式',\n fieldTitle: '字段',\n checkFormatTitle: '格式校验',\n functionTitle: '函数',\n searchFieldPlaceholder: '搜索',\n searchFunctionPlaceholder: '搜索'\n};\n\nexport const OPERATOR_LIST = [\n {\n type: 'add',\n name: '+',\n description: '加法'\n },\n {\n type: 'minus',\n name: '-',\n description: '减法'\n },\n {\n type: 'multiply',\n name: '*',\n description: '乘法'\n },\n {\n type: 'divide',\n name: '/',\n description: '除法'\n },\n {\n type: 'left-parenthesis',\n name: '(',\n description: '左括号'\n },\n {\n type: 'right-parenthesis',\n name: ')',\n description: '右括号'\n }\n];\n","import { inject, Injectable } from '@angular/core';\nimport { DomSanitizer, SafeHtml } from '@angular/platform-browser';\nimport { Node, mergeAttributes } from '@tiptap/core';\nimport { NzSafeAny } from 'ng-zorro-antd/core/types';\nexport interface ValidationResult {\n isValid: boolean;\n errors: string[];\n}\n\n@Injectable()\nexport class FormulaEditorService {\n private readonly sanitizer: DomSanitizer = inject(DomSanitizer);\n funcNode?: Node;\n fieldNode?: Node;\n paramNode?: Node;\n\n initNodes() {\n this.createFuncNode();\n this.createFieldNode();\n }\n\n createFieldNode() {\n this.fieldNode = Node.create({\n name: 'field',\n inline: true,\n group: 'inline',\n selectable: false,\n draggable: true,\n atom: true,\n addAttributes() {\n return {\n id: {\n default: null\n },\n name: {\n default: ''\n },\n className: {\n default: ''\n },\n dataType: {\n default: 'field'\n }\n };\n },\n renderText({ node }) {\n return `${node.attrs['name']}`;\n },\n parseHTML() {\n return [{ tag: 'div[data-type=\"field\"]' }];\n },\n renderHTML({ HTMLAttributes, node }) {\n return [\n 'div',\n mergeAttributes(\n {\n 'data-type': 'field',\n class: `field-node ${node.attrs['className']}` || '',\n contenteditable: 'false',\n style: `display: inline-block;margin: 0 4px;font-size: 13px;height: 18px;line-height: 18px;`\n },\n HTMLAttributes\n ),\n node.attrs['name']\n ];\n }\n });\n }\n\n createFuncNode() {\n this.funcNode = Node.create({\n name: 'func',\n inline: true,\n group: 'inline',\n selectable: false,\n draggable: false,\n content: 'inline*',\n atom: true,\n addAttributes() {\n return {\n id: {\n default: null\n },\n name: {\n default: ''\n },\n className: {\n default: ''\n },\n dataType: {\n default: 'func'\n }\n };\n },\n renderText({ node }) {\n const funcName = node.attrs['name'] || '';\n const childrenText = node.content.content\n .map(child => {\n if (child.text) {\n return child.text;\n }\n if (child.type && child.type.spec && child.type.spec['toText']) {\n return child.type.spec['toText']({ node: child });\n }\n return '';\n })\n .join('');\n return `${funcName}(${childrenText})`;\n },\n parseHTML() {\n return [{ tag: 'div[data-type=\"func\"]' }];\n },\n addNodeView() {\n return ({ node }) => {\n const createElement = (tag: string, props: Record<string, any> = {}) => {\n const element = document.createElement(tag);\n Object.entries(props).forEach(([key, value]) => {\n if (key === 'style') {\n Object.entries(value).forEach(([styleKey, styleValue]) => {\n (element.style as any)[styleKey] = styleValue;\n });\n } else if (key === 'innerText') {\n element.innerText = value;\n } else if (key === 'className') {\n element.className = value;\n } else {\n element.setAttribute(key, value);\n }\n });\n return element;\n };\n\n const className = node.attrs['className'] || '';\n const funcName = node.attrs['name'];\n\n const container = createElement('span', {\n style: {\n display: 'inline-block',\n margin: '0 4px',\n fontSize: '13px'\n }\n });\n\n const content = createElement('span', {\n style: {\n whiteSpace: 'pre-wrap',\n display: 'inline-block'\n },\n contenteditable: 'true'\n });\n\n const before = createElement('span', {\n innerText: `${funcName} `,\n contenteditable: 'false',\n className\n });\n\n const bracket = (value: string, style: Record<string, any> = {}) => {\n return createElement('span', {\n innerText: value,\n contenteditable: 'false',\n style: {\n ...style\n }\n });\n };\n\n container.append(before, bracket('(', { marginRight: '2px' }), content, bracket(')', { marginLeft: '2px' }));\n\n return {\n dom: container,\n contentDOM: content\n };\n };\n }\n });\n }\n\n /**\n * 校验公式的JSON表示是否有效\n * @param formula 公式的JSON表示\n * @returns 校验结果,包含是否有效和错误信息数组\n */\n public validateFormula(formula: any): ValidationResult {\n const errors: string[] = [];\n\n if (!formula) {\n errors.push('公式不能为空');\n return { isValid: false, errors };\n }\n\n if (formula.type !== 'doc') {\n errors.push('公式根节点类型必须是 doc');\n }\n\n if (!formula.content || !Array.isArray(formula.content)) {\n errors.push('公式必须包含 content 数组');\n return { isValid: false, errors };\n }\n\n for (const paragraph of formula.content) {\n if (paragraph.type !== 'paragraph') {\n errors.push('段落类型必须是 paragraph');\n continue;\n }\n\n if (!paragraph.content || !Array.isArray(paragraph.content)) {\n continue;\n }\n\n for (const node of paragraph.content) {\n this.validateNode(node, errors);\n }\n }\n\n return {\n isValid: errors.length === 0,\n errors\n };\n }\n\n /**\n * 从JSON数据中提取内容文本或HTML\n * @param jsonData 公式的JSON表示\n * @param outputFormat 输出格式,'text'或'html',默认'text'\n * @returns 提取的内容文本或HTML字符串\n */\n public getContentFromJson(jsonData: NzSafeAny, outputFormat: 'text' | 'html' = 'text'): string | SafeHtml {\n if (!jsonData || !jsonData.content) return '';\n return outputFormat === 'html'\n ? this.sanitizer.bypassSecurityTrustHtml(this.processContentToHtml(jsonData.content))\n : this.processContent(jsonData.content);\n }\n\n private processContent(content: any[]): string {\n if (!content || !Array.isArray(content)) return '';\n return content.map(item => this.processNode(item)).join('');\n }\n\n private processNode(node: any): string {\n if (!node) return '';\n\n switch (node.type) {\n case 'func':\n return this.processFuncNode(node);\n case 'field':\n return `{${node.attrs?.name || ''}}`;\n case 'metric':\n return `[${node.attrs?.name || ''}]`;\n case 'text':\n return node.text || '';\n case 'paragraph':\n return this.processContent(node.content);\n case 'doc':\n return this.processContent(node.content);\n default:\n return '';\n }\n }\n\n private processFuncNode(node: any): string {\n const funcName = node.attrs?.name || '';\n const content = this.processContent(node.content);\n return `${funcName}(${content})`;\n }\n\n private processContentToHtml(content: any[]): string {\n if (!content || !Array.isArray(content)) return '';\n\n return content.map(item => this.processNodeToHtml(item)).join('');\n }\n\n private processNodeToHtml(node: any): string {\n if (!node) return '';\n\n switch (node.type) {\n case 'func':\n return this.processFuncNodeToHtml(node);\n case 'field':\n return `<span class=\"${node.attrs?.className || ''}\" style=\"display: inline-block; margin: 0 4px;height: 18px;line-height: 18px;\">${node.attrs?.name || ''}</span>`;\n case 'text':\n return this.escapeHtml(node.text || '');\n case 'paragraph':\n return this.processContentToHtml(node.content);\n case 'doc':\n return this.processContentToHtml(node.content);\n default:\n return '';\n }\n }\n\n private processFuncNodeToHtml(node: any): string {\n const funcName = node.attrs?.name || '';\n const className = node.attrs?.className || '';\n const content = this.processContentToHtml(node.content);\n\n return `<span style=\"display: inline-block; margin: 0 4px;\"><span contenteditable=\"false\" class=\"${className}\">${funcName}(</span><span style=\"white-space: pre-wrap; display: inline-block; margin: 0 4px;\" contenteditable=\"true\">${content}</span><span contenteditable=\"false\" class=\"${className}\">)</span></span>`;\n }\n\n private escapeHtml(text: string): string {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n\n private validateNode(node: any, errors: string[], path: string = ''): void {\n if (!node || !node.type) {\n return;\n }\n\n const currentPath = path ? `${path} > ${node.type}` : node.type;\n\n if (node.type === 'func') {\n this.validateFuncNode(node, errors, currentPath);\n }\n }\n\n private validateFuncNode(node: any, errors: string[], path: string): void {\n if (!node.content || !Array.isArray(node.content)) {\n return;\n }\n\n const content = node.content;\n const length = content.length;\n\n for (let i = 0; i < length; i++) {\n const currentItem = content[i];\n const nextItem = content[i + 1];\n\n if (currentItem.type === 'field' || currentItem.type === 'func') {\n if (i < length - 1) {\n if (nextItem && nextItem.type === 'text') {\n const text = nextItem.text || '';\n if (!text.startsWith(',')) {\n errors.push(`${path}: 参数之间必须用逗号分隔,位置 ${i + 1}`);\n }\n } else {\n errors.push(`${path}: 参数之间必须用逗号分隔,位置 ${i + 1}`);\n }\n }\n }\n\n if (currentItem.type === 'func') {\n this.validateFuncNode(currentItem, errors, `${path} > ${currentItem.attrs?.name || 'func'}`);\n }\n }\n }\n}\n","export const ICONS = {\r\n cheng: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M460.8 896c-7.1 0-12.8-5.7-12.8-12.8V614.8L268.8 794c-5 5-13.1 5.1-18.1 0.1l-0.1-0.1-49.5-49.8c-5-5-5.1-13.1-0.1-18.1l0.1-0.1L383 544.1H140.8c-7.1 0-12.8-5.7-12.8-12.8v-70.4c0-7.1 5.7-12.8 12.8-12.8h239.4L200.9 268.9c-5-5-5.1-13.1-0.1-18.1l0.1-0.1 49.5-49.8c5-5 13.1-5.1 18.1-0.1l0.1 0.1 179.2 179.2V140.8c0-7.1 5.7-12.8 12.8-12.8H531c7.1 0 12.8 5.7 12.8 12.8v242.3L725.9 201c5-4.9 12.9-4.9 17.9 0l49.8 49.8c5 5 5.1 13.1 0.1 18.1l-0.1 0.1-179.2 179.1h268.4c7.1 0 12.8 5.7 12.8 12.8v70.4c0 7.1-5.7 12.8-12.8 12.8H611.6L793.5 726c5 5 5.1 13.1 0.1 18.1l-0.1 0.1-49.8 49.8c-5 4.9-12.9 4.9-17.9 0L543.7 611.8v271.6c0 7.1-5.7 12.8-12.8 12.8l-70.1-0.2z\" /></svg>`,\r\n chu: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M808.3 283.6L283.6 808.3c-5 5-13.1 5-18.1 0l-49.8-49.8c-5-5-5-13.1 0-18.1l524.7-524.7c5-5 13.1-5 18.1 0l49.8 49.8c4.9 5 4.9 13.1 0 18.1z\" /></svg>`,\r\n jia: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M476.8 896c-7.1 0-12.8-5.7-12.8-12.8V560H140.8c-7.1 0-12.8-5.7-12.8-12.8v-70.4c0-7.1 5.7-12.8 12.8-12.8H464V140.8c0-7.1 5.7-12.8 12.8-12.8h70.4c7.1 0 12.8 5.7 12.8 12.8V464h323.2c7.1 0 12.8 5.7 12.8 12.8v70.4c0 7.1-5.7 12.8-12.8 12.8H560v323.2c-0.2 7-5.8 12.7-12.8 12.8h-70.4z\" /></svg>`,\r\n jian: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M140.8 464h742.4c7.1 0 12.8 5.7 12.8 12.8v70.4c0 7.1-5.7 12.8-12.8 12.8H140.8c-7.1 0-12.8-5.7-12.8-12.8v-70.4c0-7.1 5.7-12.8 12.8-12.8z\" /></svg>`,\r\n youkuohao: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M416 163c38.7 49.3 68.8 104.8 88.9 164.1 19.8 59.6 29.7 122.1 29.3 184.9 1.1 62.3-8.5 124.2-28.4 183.2-23.2 59.2-53.3 115.4-89.8 167.4l56.9 33.3c42.9-56 76.8-118.4 100.4-184.9 23.2-64.1 34.9-131.8 34.7-199.9 0.3-69.3-11.4-138-34.7-203.3-23.2-65-57.2-125.8-100.4-179.8L416 163z\" /></svg>`,\r\n zuokuohao: `<svg class=\"icon\" width=\"16px\" height=\"16px\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M608 163c-38.7 49.3-68.8 104.8-88.9 164.1-19.8 59.6-29.7 122.1-29.3 184.9-1.1 62.3 8.5 124.2 28.4 183.2 23.1 59.2 53.2 115.4 89.6 167.4L550.9 896c-42.8-56-76.6-118.4-100.2-184.9-23.2-64.1-34.9-131.8-34.7-199.9-0.3-69.3 11.4-138 34.7-203.3C473.9 242.8 507.9 182 551.1 128l56.9 35z\" /></svg>`\r\n};\r\n","import { CommonModule } from '@angular/common';\nimport {\n Component,\n effect,\n ElementRef,\n inject,\n input,\n signal,\n Signal,\n ViewChild,\n AfterViewInit,\n OnInit,\n TemplateRef,\n WritableSignal\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { Editor } from '@tiptap/core';\nimport StarterKit from '@tiptap/starter-kit';\nimport { NzButtonModule } from 'ng-zorro-antd/button';\nimport { NzHighlightPipe } from 'ng-zorro-antd/core/highlight';\nimport { NzColDirective, NzGridModule } from 'ng-zorro-antd/grid';\nimport { NzIconModule } from 'ng-zorro-antd/icon';\nimport { NzInputModule } from 'ng-zorro-antd/input';\nimport { NzMessageService } from 'ng-zorro-antd/message';\nimport { NzToolTipModule } from 'ng-zorro-antd/tooltip';\nimport { NzFormatEmitEvent, NzTreeModule, NzTreeNodeOptions } from 'ng-zorro-antd/tree';\n\nimport { FormulaEditorRequestService, FormulaEditorRequestServiceToken } from './formula-editor-request.service';\nimport { CheckFormatMethod, DEFAULT_TEXT, DefaultText, Field, Func, FuncListType, ItemType, OPERATOR_LIST } from './formula-editor.model';\nimport { FormulaEditorService, ValidationResult } from './formula-editor.service';\nimport { ICONS } from './formula-editor-icon';\nimport { DomSanitizer } from '@angular/platform-browser';\n\n/**\n * 公式编辑器组件\n * 用于创建和编辑计算公式,支持函数、指标和字段的插入与验证\n * 依赖className与在使用组件处使用穿透样式实现样式\n *\n * 例如:\n * ```typescript\n * // 1. 首先实现 FormulaEditorRequestService\n * @Injectable({ providedIn: 'root' })\n * export class MyFormulaRequestService extends FormulaEditorRequestService {\n * getFunctions(functionList: WritableSignal<NzTreeNodeOptions[]>) {\n * functionList.set([\n * {\n * title: '聚合函数',\n * key: 'agg',\n * children: [\n * { title: 'SUM', key: 'sum', className: 'agg', id: 'sum', description: '求和函数' },\n * { title: 'AVG', key: 'avg', className: 'agg', id: 'avg', description: '平均值函数' },\n * { title: 'COUNT', key: 'count', className: 'agg', id: 'count', description: '计数函数' }\n * ]\n * },\n * {\n * title: '数学函数',\n * key: 'math',\n * children: [\n * { title: 'ABS', key: 'abs', className: 'math', id: 'abs', description: '绝对值函数' },\n * { title: 'ROUND', key: 'round', className: 'math', id: 'round', description: '四舍五入函数' }\n * ]\n * }\n * ]);\n * }\n *\n * getFields(fieldList: WritableSignal<Field[]>) {\n * fieldList.set([\n * { id: 'user_count', name: '用户数量', className: 'field' },\n * { id: 'order_amount', name: '订单金额', className: 'field' },\n * { id: 'product_price', name: '商品价格', className: 'field' }\n * ]);\n * }\n *\n * validateFormula(formula: NzSafeAny, res: WritableSignal<ValidationResult | null>) {\n * // 调用后端API校验公式\n * this.http.post('/api/formula/validate', { formula }).subscribe({\n * next: (response) => {\n * res.set({\n * isValid: response.valid,\n * errors: response.errors || []\n * });\n * },\n * error: () => {\n * res.set({\n * isValid: false,\n * errors: ['校验失败,请稍后重试']\n * });\n * }\n * });\n * }\n *\n * getFieldDescription(description: WritableSignal<string>) {\n * description.set('选择字段后显示字段描述信息');\n * }\n * }\n *\n * // 2. 在模块中提供服务\n * providers: [\n * { provide: FormulaEditorRequestServiceToken, useClass: MyFormulaRequestService }\n * ]\n *\n * // 3. 在父组件中使用\n * @Component({\n * template: `\n * <app-formula-editor\n * [itemType]=\"itemType\"\n * [defaultText]=\"defaultText\"\n * [checkFormatMethod]=\"checkFormatMethod\"\n * [functionListType]=\"functionListType\"\n * [itemTemplate]=\"itemTemplate\">\n * </app-formula-editor>\n *\n * <button (click)=\"getFormula()\">获取公式JSON</button>\n * <button (click)=\"getFormulaText()\">获取公式文本</button>\n * <button (click)=\"loadExampleFormula()\">加载示例公式</button>\n * `\n * })\n * export class ParentComponent {\n * @ViewChild(FormulaEditorComponent) formulaEditor!: FormulaEditorComponent;\n *\n * itemType = ItemType.Field;\n * checkFormatMethod = CheckFormatMethod.self;\n * functionListType = FuncListType.Tree;\n *\n * defaultText = {\n * fieldTitle: '字段',\n * indicatorTitle: '指标',\n * checkFormatTitle: '格式校验'\n * };\n *\n * // 获取公式JSON\n * getFormula() {\n * const formula = this.formulaEditor.getFormula();\n * console.log('公式JSON:', formula);\n * }\n *\n * // 获取公式文本\n * getFormulaText() {\n * const text = this.formulaEditor.getFormulaText();\n * console.log('公式文本:', text);\n * }\n *\n * // 加载示例公式\n * loadExampleFormula() {\n * const exampleFormula = {\n * type: 'doc',\n * content: [\n * {\n * type: 'paragraph',\n * content: [\n * {\n * type: 'func',\n * attrs: {\n * name: 'SUM',\n * id: 'sum',\n * className: 'text-func-agg'\n * }\n * },\n * {\n * type: 'text',\n * text: '('\n * },\n * {\n * type: 'field',\n * attrs: {\n * name: 'order_amount',\n * id: 'order_amount',\n * className: 'text-field-field'\n * }\n * },\n * {\n * type: 'text',\n * text: ')'\n * }\n * ]\n * }\n * ]\n * };\n * this.formulaEditor.loadFormula(exampleFormula);\n * }\n * }\n *\n * // 4. 样式穿透(在父组件样式文件中)\n * // :host ::ng-deep .text-func-agg {\n * // color: #1890ff;\n * // background-color: #e6f7ff;\n * // padding: 2px 6px;\n * // border-radius: 4px;\n * // }\n *\n * // :host ::ng-deep .text-field-field {\n * // color: #52c41a;\n * // background-color: #f6ffed;\n * // padding: 2px 6px;\n * // border-radius: 4px;\n * // }\n * ```\n */\n@Component({\n selector: 'app-formula-editor',\n standalone: true,\n imports: [\n NzColDirective,\n NzGridModule,\n NzInputModule,\n FormsModule,\n NzIconModule,\n CommonModule,\n NzTreeModule,\n NzButtonModule,\n NzToolTipModule,\n NzHighlightPipe\n ],\n templateUrl: './formula-editor.component.html',\n styleUrls: ['./formula-editor.component.less'],\n providers: [FormulaEditorService]\n})\nexport class FormulaEditorComponent implements AfterViewInit, OnInit {\n private readonly formulaEditorService = inject(FormulaEditorService);\n private readonly sanitizer = inject(DomSanitizer);\n private readonly msg = inject(NzMessageService);\n private readonly formulaEditorRequestService = inject<FormulaEditorRequestService>(FormulaEditorRequestServiceToken);\n @ViewChild('editor') editor!: ElementRef;\n\n /**\n * 项目类型,决定显示字段或自定义\n * 默认值:ItemType.Field\n */\n itemType = input<ItemType>(ItemType.Field);\n\n /**\n * 字段标题,当项目类型为字段时显示\n * 默认值:'字段'\n */\n defaultText = input<DefaultText>({});\n\n /**\n * 格式检查方法\n * 默认值:CheckFormatMethod.self\n */\n checkFormatMethod = input<CheckFormatMethod>(CheckFormatMethod.self);\n\n /**\n * 函数列表显示类型\n * 默认值:FuncListType.Tree\n */\n functionListType = input<FuncListType>(FuncListType.Tree);\n\n itemTemplate = input<TemplateRef<void> | null>(null);\n\n readonly _itemType = ItemType;\n readonly _funcListType = FuncListType;\n readonly _defaultText = DEFAULT_TEXT;\n\n searchWord: string = '';\n\n fieldListOrigin: WritableSignal<Field[]> = signal([]);\n fieldList: Field[] = [];\n\n editorObj!: Editor;\n checkLoading: boolean = false;\n showDescription: boolean = true;\n\n funcNode: WritableSignal<NzTreeNodeOptions[]> = signal([]);\n fieldDescription: WritableSignal<string> = signal('');\n validationResult: WritableSignal<ValidationResult | null> = signal(null);\n\n editDescription: string = '请选择函数';\n\n editDescShow: 'func' | 'error' | 'none' = 'none';\n\n searchField: Signal<string> = signal('');\n searchFunction: Signal<string> = signal('');\n\n _operatorList = OPERATOR_LIST;\n\n getOperatorIcon(type: string): string {\n const iconMap: Record<string, string> = {\n add: ICONS.jia,\n minus: ICONS.jian,\n multiply: ICONS.cheng,\n divide: ICONS.chu,\n 'left-parenthesis': ICONS.zuokuohao,\n 'right-parenthesis': ICONS.youkuohao\n };\n return this.sanitizer.bypassSecurityTrustHtml(iconMap[type] || '') as string;\n }\n\n /**\n * 构造函数\n * 初始化信号监听,处理搜索和项目类型变化\n */\n\n constructor() {\n effect(() => {\n const searchWord = this.searchField();\n this.fieldList = this.fieldListOrigin().filter(item => item.name.includes(searchWord));\n });\n effect(\n () => {\n const itemType = this.itemType();\n if (itemType === ItemType.Field) {\n this.formulaEditorRequestService.getFields(this.fieldListOrigin);\n }\n },\n { allowSignalWrites: true }\n );\n effect(() => {\n const fieldListOrigin = this.fieldListOrigin();\n this.fieldList = [...fieldListOrigin];\n });\n effect(() => {\n const validationResult = this.validationResult();\n if (validationResult) {\n this.checkLoading = false;\n if (validationResult.isValid) {\n this.msg.success(`${this.defaultText().checkFormatTitle || this._defaultText.checkFormatTitle}通过`);\n } else {\n this.msg.error(\n `${this.defaultText().checkFormatTitle || this._defaultText.checkFormatTitle}不通过: ${validationResult.errors.join(', ')}`\n );\n this.editDescription = validationResult.errors.join(', ');\n this.editDescShow = 'error';\n }\n }\n });\n }\n\n ngOnInit() {\n this.formulaEditorRequestService.getFunctions(this.funcNode);\n this.formulaEditorRequestService.getFieldDescription(this.fieldDescription);\n }\n\n ngAfterViewInit() {\n this.formulaEditorService.initNodes();\n this.editorObj = new Editor({\n element: this.editor.nativeElement,\n extensions: [\n StarterKit.configure({\n blockquote: false,\n codeBlock: false,\n code: false\n }),\n this.formulaEditorService.funcNode!,\n this.formulaEditorService.fieldNode!\n ]\n });\n }\n\n insertFunc(func: Func) {\n this.editorObj\n .chain()\n .insertContent({\n type: 'func',\n attrs: {\n name: func.name,\n id: func.id,\n className: `text-func-${func.className}`\n },\n content: []\n })\n .focus()\n .run();\n }\n\n insertField(field: Field) {\n this.editorObj\n .chain()\n .insertContent({\n type: 'field',\n attrs: {\n name: field.name,\n id: field.id,\n className: `text-field-${field.className}`\n }\n })\n .focus()\n .run();\n }\n\n insertOperator(operator: string) {\n this.editorObj\n .chain()\n .insertContent({\n type: 'text',\n text: operator\n })\n .focus()\n .run();\n }\n\n functionClick(node: NzFormatEmitEvent) {\n const func = node.node!.origin as unknown as Func;\n this.editDescription = func.description || '';\n this.editDescShow = 'func';\n this.insertFunc(func);\n }\n\n /**\n * 获取公式JSON\n * @returns 公式的JSON表示\n * @example\n * // 返回示例\n * {\n * \"type\": \"doc\",\n * \"content\": [\n * {\n * \"type\": \"paragraph\",\n * \"content\": [\n * {\n * \"type\": \"func\",\n * \"attrs\": {\n * \"name\": \"SUM\",\n * \"id\": \"sum\",\n * \"className\": \"text-func-agg\"\n * }\n * }\n * ]\n * }\n * ]\n * }\n */\n public getFormula() {\n const formula = this.editorObj.getJSON();\n return formula;\n }\n\n /**\n * 获取公式文本\n * @returns 公式的纯文本表示\n * @example\n * // 返回示例\n * \"SUM(field1, field2)\"\n */\n public getFormulaText() {\n const formulaText = this.editorObj.getText();\n return formulaText;\n }\n\n checkFormat() {\n if (this.checkFormatMethod() === CheckFormatMethod.self) {\n const result = this.validateFormula();\n if (result.isValid) {\n this.msg.success(`${this.defaultText().checkFormatTitle || this._defaultText.checkFormatTitle}通过`);\n } else {\n this.msg.error(`${this.defaultText().checkFormatTitle || this._defaultText.checkFormatTitle}不通过: ${result.errors.join(', ')}`);\n this.editDescription = result.errors.join(', ');\n this.editDescShow = 'error';\n }\n } else {\n this.checkLoading = true;\n this.formulaEditorRequestService.validateFormula(this.getFormula(), this.validationResult);\n }\n }\n\n /**\n * 从JSON加载公式\n * @param formula 公式的JSON表示\n * @example\n * // 使用示例\n * const formula = {\n * \"type\": \"doc\",\n * \"content\": [\n * {\n * \"type\": \"paragraph\",\n * \"content\": [\n * {\n * \"type\": \"func\",\n * \"attrs\": {\n * \"name\": \"SUM\",\n * \"id\": \"sum\",\n * \"className\": \"text-func-agg\"\n * }\n * }\n * ]\n * }\n * ]\n * };\n * formulaEditor.loadFormula(formula);\n */\n public loadFormula(formula: any) {\n if (!formula || !this.editorObj) {\n return;\n }\n this.editorObj.commands.setContent(formula);\n }\n\n // 校验公式\n validateFormula(): ValidationResult {\n const formula = this.editorObj.getJSON();\n const result = this.formulaEditorService.validateFormula(formula);\n return result;\n }\n\n toggleDescription() {\n this.showDescription = !this.showDescription;\n }\n}\n","<div nz-row class=\"formula-editor\">\n <div nz-col nzSpan=\"10\" class=\"editor-box\">\n <div class=\"editor-title\">\n <div class=\"label-title label-require\">{{ defaultText().inputTitle || _defaultText.inputTitle }}</div>\n <button nz-button nzType=\"link\" nzSize=\"small\" [nzLoading]=\"checkLoading\" (click)=\"checkFormat()\">{{\n defaultText().checkFormatTitle || _defaultText.checkFormatTitle\n }}</button>\n </div>\n <div class=\"edit-box\">\n <div class=\"edit-operation-box\">\n @for (item of _operatorList; track item) {\n <div class=\"edit-operation-item\" (click)=\"insertOperator(item.name)\">\n <span class=\"operator-icon\" [innerHTML]=\"getOperatorIcon(item.type)\"></span>\n </div>\n }\n </div>\n <div #editor class=\"editor\"></div>\n @if (editDescShow !== 'none') {\n <div class=\"edit-description-box\">\n <div class=\"edit-description-head\" [style]=\"{ marginBottom: !showDescription ? '10px' : '0' }\">\n <span class=\"edit-description-title\">{{ editDescShow === 'func' ? '函数释义' : '校验错误信息' }}</span>\n <span\n class=\"edit-description-icon\"\n nz-icon\n [nzType]=\"showDescription ? 'down' : 'up'\"\n nzTheme=\"outline\"\n (click)=\"toggleDescription()\"\n ></span>\n </div>\n @if (showDescription) {\n <div class=\"edit-description-text\"> {{ editDescription }} </div>\n }\n </div>\n }\n </div>\n </div>\n @switch (itemType()) {\n @case (_itemType.Field) {\n <div nz-col nzSpan=\"7\" class=\"field-box\">\n <div class=\"label-title\"\n >{{ defaultText().fieldTitle || _defaultText.fieldTitle }}\n @if (fieldDescription()) {\n <span nz-icon nzType=\"question-circle\" nzTheme=\"outline\" nz-tooltip [nzTooltipTitle]=\"fieldDescription()\"></span>\n }\n </div>\n <nz-input-group [nzSuffix]=\"suffixIconSearch\">\n <input\n type=\"text\"\n nz-input\n [placeholder]=\"defaultText().searchFieldPlaceholder || _defaultText.searchFieldPlaceholder\"\n [(ngModel)]=\"searchField\"\n />\n </nz-input-group>\n <ng-template #suffixIconSearch>\n <i nz-icon nzType=\"search\"></i>\n </ng-template>\n <div class=\"field-list\">\n @for (item of fieldList; track item) {\n <div (click)=\"insertField(item)\" [class]=\"item.className ? 'item-field-' + item.className : ''\" class=\"field-list-item\">\n @if (item.image) {\n <img class=\"field-img\" [src]=\"item.image\" />\n }\n @if (item.icon) {\n <span class=\"field-icon\" nz-icon [nzIconfont]=\"item.icon\"></span>\n }\n <span class=\"field-name\" [innerHTML]=\"item.name | nzHighlight: searchField() : 'i' : 'node-highlight'\"></span>\n @if (item.description) {\n <span\n class=\"desc-icon\"\n nz-icon\n nzType=\"question-circle\"\n nzTheme=\"outline\"\n nz-tooltip\n [nzTooltipTitle]=\"item.description\"\n ></span>\n }\n </div>\n }\n </div>\n </div>\n }\n @case (_itemType.Template) {\n <div nz-col nzSpan=\"7\" class=\"field-box\">\n <ng-container *ngTemplateOutlet=\"itemTemplate()\"></ng-container>\n </div>\n }\n }\n <div nz-col nzSpan=\"7\" class=\"function-box\">\n <div class=\"label-title\">{{ defaultText().functionTitle || _defaultText.functionTitle }}</div>\n <nz-input-group [nzSuffix]=\"suffixIconSearch\">\n <input\n type=\"text\"\n nz-input\n [placeholder]=\"defaultText().searchFunctionPlaceholder || _defaultText.searchFunctionPlaceholder\"\n [(ngModel)]=\"searchFunction\"\n />\n </nz-input-group>\n <ng-template #suffixIconSearch>\n <i nz-icon nzType=\"search\"></i>\n </ng-template>\n <nz-tree\n class=\"function-tree\"\n [nzHideUnMatched]=\"true\"\n [nzSearchValue]=\"searchFunction()\"\n [nzTreeTemplate]=\"nzTreeTemplate\"\n [nzData]=\"funcNode()\"\n [nzShowExpand]=\"functionListType() === _funcListType.Tree\"\n (nzClick)=\"functionClick($event)\"\n ></nz-tree>\n <ng-template #nzTreeTemplate let-node let-origin=\"origin\">\n <span class=\"custom-node\" [innerHTML]=\"origin.name | nzHighlight: searchFunction() : 'i' : 'node-highlight'\">\n @if (origin.description) {\n <span\n class=\"desc-icon\"\n nz-icon\n nzType=\"question-circle\"\n nzTheme=\"outline\"\n nz-tooltip\n [nzTooltipTitle]=\"origin.description\"\n ></span>\n }\n </span>\n </ng-template>\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { InjectionToken } from '@angular/core';
|
|
1
|
+
import { InjectionToken, WritableSignal } from '@angular/core';
|
|
2
2
|
import { NzSafeAny } from 'ng-zorro-antd/core/types';
|
|
3
3
|
import { NzTreeNodeOptions } from 'ng-zorro-antd/tree';
|
|
4
4
|
import { Field } from './formula-editor.model';
|
|
@@ -12,22 +12,57 @@ export declare abstract class FormulaEditorRequestService {
|
|
|
12
12
|
constructor();
|
|
13
13
|
/**
|
|
14
14
|
* 获取函数列表
|
|
15
|
+
* 实现类需要根据前n个选择框的值来动态获取下一个选择框的选项
|
|
16
|
+
* 例如:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* getFunctions(functionList: WritableSignal<NzTreeNodeOptions[]>) {
|
|
19
|
+
* functionList.set([
|
|
20
|
+
* { title: 'SUM', key: 'sum', className: 'sum' },
|
|
21
|
+
* { title: 'AVG', key: 'avg', className: 'avg' }
|
|
22
|
+
* ]);
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
* @param functionList 函数列表信号量
|
|
15
26
|
*/
|
|
16
|
-
abstract getFunctions(
|
|
27
|
+
abstract getFunctions(functionList: WritableSignal<NzTreeNodeOptions[]>): void;
|
|
17
28
|
/**
|
|
18
29
|
* 获取字段列表
|
|
30
|
+
* 实现类需要根据前n个选择框的值来动态获取下一个选择框的选项
|
|
31
|
+
* 例如:
|
|
32
|
+
* ```typescript
|
|
33
|
+
* getFields(fieldList: WritableSignal<Field[]>) {
|
|
34
|
+
* fieldList.set([
|
|
35
|
+
* { id: 'user', name: '用户', className: 'user' },
|
|
36
|
+
* { id: 'order', name: '订单', className: 'user' }
|
|
37
|
+
* ]);
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
* @param fieldList 字段列表信号量
|
|
19
41
|
*/
|
|
20
|
-
abstract getFields(
|
|
42
|
+
abstract getFields(fieldList: WritableSignal<Field[]>): void;
|
|
21
43
|
/**
|
|
22
44
|
* 校验公式格式
|
|
45
|
+
* 实现类需要根据公式字符串来校验格式是否正确
|
|
46
|
+
* 例如:
|
|
47
|
+
* ```typescript
|
|
48
|
+
* validateFormula(formula: NzSafeAny, res: WritableSignal<ValidationResult | null>) {
|
|
49
|
+
* res.set({ valid: true, message: '' });
|
|
50
|
+
* }
|
|
51
|
+
* ```
|
|
23
52
|
* @param formula 公式字符串
|
|
24
|
-
* @
|
|
53
|
+
* @param res 字段列表信号量
|
|
25
54
|
*/
|
|
26
|
-
abstract validateFormula(formula: NzSafeAny
|
|
55
|
+
abstract validateFormula(formula: NzSafeAny, res: WritableSignal<ValidationResult | null>): void;
|
|
27
56
|
/**
|
|
28
57
|
* 获取字段的描述
|
|
29
|
-
*
|
|
30
|
-
*
|
|
58
|
+
* 实现类需要根据字段id来获取字段的描述
|
|
59
|
+
* 例如:
|
|
60
|
+
* ```typescript
|
|
61
|
+
* getFieldDescription(description: WritableSignal<string>) {
|
|
62
|
+
* description.set('');
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
* @param description 描述字符串信号量
|
|
31
66
|
*/
|
|
32
|
-
getFieldDescription(
|
|
67
|
+
getFieldDescription(description: WritableSignal<string>): void;
|
|
33
68
|
}
|
|
@@ -1,13 +1,173 @@
|
|
|
1
|
-
import { ElementRef, Signal, AfterViewInit, OnInit, TemplateRef } from '@angular/core';
|
|
1
|
+
import { ElementRef, Signal, AfterViewInit, OnInit, TemplateRef, WritableSignal } from '@angular/core';
|
|
2
2
|
import { Editor } from '@tiptap/core';
|
|
3
3
|
import { NzFormatEmitEvent, NzTreeNodeOptions } from 'ng-zorro-antd/tree';
|
|
4
|
-
import { CheckFormatMethod, Field, Func, FuncListType, ItemType } from './formula-editor.model';
|
|
4
|
+
import { CheckFormatMethod, DefaultText, Field, Func, FuncListType, ItemType } from './formula-editor.model';
|
|
5
5
|
import { ValidationResult } from './formula-editor.service';
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
7
|
/**
|
|
8
8
|
* 公式编辑器组件
|
|
9
9
|
* 用于创建和编辑计算公式,支持函数、指标和字段的插入与验证
|
|
10
10
|
* 依赖className与在使用组件处使用穿透样式实现样式
|
|
11
|
+
*
|
|
12
|
+
* 例如:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* // 1. 首先实现 FormulaEditorRequestService
|
|
15
|
+
* @Injectable({ providedIn: 'root' })
|
|
16
|
+
* export class MyFormulaRequestService extends FormulaEditorRequestService {
|
|
17
|
+
* getFunctions(functionList: WritableSignal<NzTreeNodeOptions[]>) {
|
|
18
|
+
* functionList.set([
|
|
19
|
+
* {
|
|
20
|
+
* title: '聚合函数',
|
|
21
|
+
* key: 'agg',
|
|
22
|
+
* children: [
|
|
23
|
+
* { title: 'SUM', key: 'sum', className: 'agg', id: 'sum', description: '求和函数' },
|
|
24
|
+
* { title: 'AVG', key: 'avg', className: 'agg', id: 'avg', description: '平均值函数' },
|
|
25
|
+
* { title: 'COUNT', key: 'count', className: 'agg', id: 'count', description: '计数函数' }
|
|
26
|
+
* ]
|
|
27
|
+
* },
|
|
28
|
+
* {
|
|
29
|
+
* title: '数学函数',
|
|
30
|
+
* key: 'math',
|
|
31
|
+
* children: [
|
|
32
|
+
* { title: 'ABS', key: 'abs', className: 'math', id: 'abs', description: '绝对值函数' },
|
|
33
|
+
* { title: 'ROUND', key: 'round', className: 'math', id: 'round', description: '四舍五入函数' }
|
|
34
|
+
* ]
|
|
35
|
+
* }
|
|
36
|
+
* ]);
|
|
37
|
+
* }
|
|
38
|
+
*
|
|
39
|
+
* getFields(fieldList: WritableSignal<Field[]>) {
|
|
40
|
+
* fieldList.set([
|
|
41
|
+
* { id: 'user_count', name: '用户数量', className: 'field' },
|
|
42
|
+
* { id: 'order_amount', name: '订单金额', className: 'field' },
|
|
43
|
+
* { id: 'product_price', name: '商品价格', className: 'field' }
|
|
44
|
+
* ]);
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* validateFormula(formula: NzSafeAny, res: WritableSignal<ValidationResult | null>) {
|
|
48
|
+
* // 调用后端API校验公式
|
|
49
|
+
* this.http.post('/api/formula/validate', { formula }).subscribe({
|
|
50
|
+
* next: (response) => {
|
|
51
|
+
* res.set({
|
|
52
|
+
* isValid: response.valid,
|
|
53
|
+
* errors: response.errors || []
|
|
54
|
+
* });
|
|
55
|
+
* },
|
|
56
|
+
* error: () => {
|
|
57
|
+
* res.set({
|
|
58
|
+
* isValid: false,
|
|
59
|
+
* errors: ['校验失败,请稍后重试']
|
|
60
|
+
* });
|
|
61
|
+
* }
|
|
62
|
+
* });
|
|
63
|
+
* }
|
|
64
|
+
*
|
|
65
|
+
* getFieldDescription(description: WritableSignal<string>) {
|
|
66
|
+
* description.set('选择字段后显示字段描述信息');
|
|
67
|
+
* }
|
|
68
|
+
* }
|
|
69
|
+
*
|
|
70
|
+
* // 2. 在模块中提供服务
|
|
71
|
+
* providers: [
|
|
72
|
+
* { provide: FormulaEditorRequestServiceToken, useClass: MyFormulaRequestService }
|
|
73
|
+
* ]
|
|
74
|
+
*
|
|
75
|
+
* // 3. 在父组件中使用
|
|
76
|
+
* @Component({
|
|
77
|
+
* template: `
|
|
78
|
+
* <app-formula-editor
|
|
79
|
+
* [itemType]="itemType"
|
|
80
|
+
* [defaultText]="defaultText"
|
|
81
|
+
* [checkFormatMethod]="checkFormatMethod"
|
|
82
|
+
* [functionListType]="functionListType"
|
|
83
|
+
* [itemTemplate]="itemTemplate">
|
|
84
|
+
* </app-formula-editor>
|
|
85
|
+
*
|
|
86
|
+
* <button (click)="getFormula()">获取公式JSON</button>
|
|
87
|
+
* <button (click)="getFormulaText()">获取公式文本</button>
|
|
88
|
+
* <button (click)="loadExampleFormula()">加载示例公式</button>
|
|
89
|
+
* `
|
|
90
|
+
* })
|
|
91
|
+
* export class ParentComponent {
|
|
92
|
+
* @ViewChild(FormulaEditorComponent) formulaEditor!: FormulaEditorComponent;
|
|
93
|
+
*
|
|
94
|
+
* itemType = ItemType.Field;
|
|
95
|
+
* checkFormatMethod = CheckFormatMethod.self;
|
|
96
|
+
* functionListType = FuncListType.Tree;
|
|
97
|
+
*
|
|
98
|
+
* defaultText = {
|
|
99
|
+
* fieldTitle: '字段',
|
|
100
|
+
* indicatorTitle: '指标',
|
|
101
|
+
* checkFormatTitle: '格式校验'
|
|
102
|
+
* };
|
|
103
|
+
*
|
|
104
|
+
* // 获取公式JSON
|
|
105
|
+
* getFormula() {
|
|
106
|
+
* const formula = this.formulaEditor.getFormula();
|
|
107
|
+
* console.log('公式JSON:', formula);
|
|
108
|
+
* }
|
|
109
|
+
*
|
|
110
|
+
* // 获取公式文本
|
|
111
|
+
* getFormulaText() {
|
|
112
|
+
* const text = this.formulaEditor.getFormulaText();
|
|
113
|
+
* console.log('公式文本:', text);
|
|
114
|
+
* }
|
|
115
|
+
*
|
|
116
|
+
* // 加载示例公式
|
|
117
|
+
* loadExampleFormula() {
|
|
118
|
+
* const exampleFormula = {
|
|
119
|
+
* type: 'doc',
|
|
120
|
+
* content: [
|
|
121
|
+
* {
|
|
122
|
+
* type: 'paragraph',
|
|
123
|
+
* content: [
|
|
124
|
+
* {
|
|
125
|
+
* type: 'func',
|
|
126
|
+
* attrs: {
|
|
127
|
+
* name: 'SUM',
|
|
128
|
+
* id: 'sum',
|
|
129
|
+
* className: 'text-func-agg'
|
|
130
|
+
* }
|
|
131
|
+
* },
|
|
132
|
+
* {
|
|
133
|
+
* type: 'text',
|
|
134
|
+
* text: '('
|
|
135
|
+
* },
|
|
136
|
+
* {
|
|
137
|
+
* type: 'field',
|
|
138
|
+
* attrs: {
|
|
139
|
+
* name: 'order_amount',
|
|
140
|
+
* id: 'order_amount',
|
|
141
|
+
* className: 'text-field-field'
|
|
142
|
+
* }
|
|
143
|
+
* },
|
|
144
|
+
* {
|
|
145
|
+
* type: 'text',
|
|
146
|
+
* text: ')'
|
|
147
|
+
* }
|
|
148
|
+
* ]
|
|
149
|
+
* }
|
|
150
|
+
* ]
|
|
151
|
+
* };
|
|
152
|
+
* this.formulaEditor.loadFormula(exampleFormula);
|
|
153
|
+
* }
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* // 4. 样式穿透(在父组件样式文件中)
|
|
157
|
+
* // :host ::ng-deep .text-func-agg {
|
|
158
|
+
* // color: #1890ff;
|
|
159
|
+
* // background-color: #e6f7ff;
|
|
160
|
+
* // padding: 2px 6px;
|
|
161
|
+
* // border-radius: 4px;
|
|
162
|
+
* // }
|
|
163
|
+
*
|
|
164
|
+
* // :host ::ng-deep .text-field-field {
|
|
165
|
+
* // color: #52c41a;
|
|
166
|
+
* // background-color: #f6ffed;
|
|
167
|
+
* // padding: 2px 6px;
|
|
168
|
+
* // border-radius: 4px;
|
|
169
|
+
* // }
|
|
170
|
+
* ```
|
|
11
171
|
*/
|
|
12
172
|
export declare class FormulaEditorComponent implements AfterViewInit, OnInit {
|
|
13
173
|
private readonly formulaEditorService;
|
|
@@ -24,7 +184,7 @@ export declare class FormulaEditorComponent implements AfterViewInit, OnInit {
|
|
|
24
184
|
* 字段标题,当项目类型为字段时显示
|
|
25
185
|
* 默认值:'字段'
|
|
26
186
|
*/
|
|
27
|
-
|
|
187
|
+
defaultText: import("@angular/core").InputSignal<DefaultText>;
|
|
28
188
|
/**
|
|
29
189
|
* 格式检查方法
|
|
30
190
|
* 默认值:CheckFormatMethod.self
|
|
@@ -38,14 +198,16 @@ export declare class FormulaEditorComponent implements AfterViewInit, OnInit {
|
|
|
38
198
|
itemTemplate: import("@angular/core").InputSignal<TemplateRef<void> | null>;
|
|
39
199
|
readonly _itemType: typeof ItemType;
|
|
40
200
|
readonly _funcListType: typeof FuncListType;
|
|
201
|
+
readonly _defaultText: DefaultText;
|
|
41
202
|
searchWord: string;
|
|
42
|
-
fieldListOrigin: Field[]
|
|
203
|
+
fieldListOrigin: WritableSignal<Field[]>;
|
|
43
204
|
fieldList: Field[];
|
|
44
205
|
editorObj: Editor;
|
|
45
206
|
checkLoading: boolean;
|
|
46
207
|
showDescription: boolean;
|
|
47
|
-
funcNode: NzTreeNodeOptions[]
|
|
48
|
-
fieldDescription: string
|
|
208
|
+
funcNode: WritableSignal<NzTreeNodeOptions[]>;
|
|
209
|
+
fieldDescription: WritableSignal<string>;
|
|
210
|
+
validationResult: WritableSignal<ValidationResult | null>;
|
|
49
211
|
editDescription: string;
|
|
50
212
|
editDescShow: 'func' | 'error' | 'none';
|
|
51
213
|
searchField: Signal<string>;
|
|
@@ -130,5 +292,5 @@ export declare class FormulaEditorComponent implements AfterViewInit, OnInit {
|
|
|
130
292
|
validateFormula(): ValidationResult;
|
|
131
293
|
toggleDescription(): void;
|
|
132
294
|
static ɵfac: i0.ɵɵFactoryDeclaration<FormulaEditorComponent, never>;
|
|
133
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<FormulaEditorComponent, "app-formula-editor", never, { "itemType": { "alias": "itemType"; "required": false; "isSignal": true; }; "
|
|
295
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<FormulaEditorComponent, "app-formula-editor", never, { "itemType": { "alias": "itemType"; "required": false; "isSignal": true; }; "defaultText": { "alias": "defaultText"; "required": false; "isSignal": true; }; "checkFormatMethod": { "alias": "checkFormatMethod"; "required": false; "isSignal": true; }; "functionListType": { "alias": "functionListType"; "required": false; "isSignal": true; }; "itemTemplate": { "alias": "itemTemplate"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
134
296
|
}
|
|
@@ -33,6 +33,15 @@ export declare enum FuncListType {
|
|
|
33
33
|
List = "list",// 列表模式
|
|
34
34
|
Tree = "tree"
|
|
35
35
|
}
|
|
36
|
+
export interface DefaultText {
|
|
37
|
+
inputTitle?: string;
|
|
38
|
+
fieldTitle?: string;
|
|
39
|
+
checkFormatTitle?: string;
|
|
40
|
+
functionTitle?: string;
|
|
41
|
+
searchFieldPlaceholder?: string;
|
|
42
|
+
searchFunctionPlaceholder?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare const DEFAULT_TEXT: DefaultText;
|
|
36
45
|
export declare const OPERATOR_LIST: {
|
|
37
46
|
type: string;
|
|
38
47
|
name: string;
|