From 59f4e0edac47e986a83a3f9b7862cf92650b7fee Mon Sep 17 00:00:00 2001 From: roymondchen Date: Thu, 28 May 2026 19:49:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(editor):=20=E5=8E=86=E5=8F=B2=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E9=9D=A2=E6=9D=BF=E6=94=AF=E6=8C=81=E5=B7=AE=E5=BC=82?= =?UTF-8?q?=E5=AF=B9=E6=AF=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 HistoryDiffDialog 历史差异对比弹窗 - 新增 CompareForm 表单对比组件 - 抽取 code-block 工具函数到 utils/code-block.ts - 历史列表面板支持选择两个版本进行对比 --- packages/editor/src/Editor.vue | 6 + .../editor/src/components/CodeBlockEditor.vue | 125 ++---------- .../editor/src/components/CompareForm.vue | 192 ++++++++++++++++++ packages/editor/src/index.ts | 1 + .../src/layouts/history-list/Bucket.vue | 6 + .../src/layouts/history-list/CodeBlockTab.vue | 9 +- .../layouts/history-list/DataSourceTab.vue | 9 +- .../src/layouts/history-list/GroupRow.vue | 31 ++- .../history-list/HistoryDiffDialog.vue | 157 ++++++++++++++ .../layouts/history-list/HistoryListPanel.vue | 94 ++++++++- .../src/layouts/history-list/PageTab.vue | 19 +- .../editor/src/theme/history-list-panel.scss | 74 +++++++ packages/editor/src/utils/code-block.ts | 150 ++++++++++++++ packages/editor/src/utils/index.ts | 1 + 14 files changed, 760 insertions(+), 114 deletions(-) create mode 100644 packages/editor/src/components/CompareForm.vue create mode 100644 packages/editor/src/layouts/history-list/HistoryDiffDialog.vue create mode 100644 packages/editor/src/utils/code-block.ts diff --git a/packages/editor/src/Editor.vue b/packages/editor/src/Editor.vue index 2252e0ac..525bf6c8 100644 --- a/packages/editor/src/Editor.vue +++ b/packages/editor/src/Editor.vue @@ -229,6 +229,12 @@ provide('services', services); provide('codeOptions', props.codeOptions); provide('stageOptions', stageOptions); +/** + * 把顶层 `extendFormState` 提供给非 PropsPanel 链路上的组件使用(例如历史差异对话框 HistoryDiffDialog + * 内部的 CompareForm)。这样所有依赖业务上下文的表单 filterFunction 都能拿到一致的扩展状态, + * 与 PropsPanel 通过 `:extend-state` 显式传入的方式保持等价。 + */ +provide('extendFormState', props.extendFormState); provide('eventBus', new EventEmitter()); diff --git a/packages/editor/src/components/CodeBlockEditor.vue b/packages/editor/src/components/CodeBlockEditor.vue index 276ce781..20a981c5 100644 --- a/packages/editor/src/components/CodeBlockEditor.vue +++ b/packages/editor/src/components/CodeBlockEditor.vue @@ -63,14 +63,7 @@ import { computed, inject, nextTick, Ref, ref, useTemplateRef, watch } from 'vue import type { CodeBlockContent } from '@tmagic/core'; import { TMagicButton, TMagicDialog, tMagicMessage, tMagicMessageBox, TMagicTag } from '@tmagic/design'; -import { - type ContainerChangeEventData, - defineFormConfig, - defineFormItem, - type FormConfig, - MFormBox, - type TableColumnConfig, -} from '@tmagic/form'; +import { type ContainerChangeEventData, type FormConfig, MFormBox } from '@tmagic/form'; import FloatingBox from '@editor/components/FloatingBox.vue'; import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height'; @@ -78,6 +71,7 @@ import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-positi import { useServices } from '@editor/hooks/use-services'; import { useWindowRect } from '@editor/hooks/use-window-rect'; import CodeEditor from '@editor/layouts/CodeEditor.vue'; +import { getCodeBlockFormConfig } from '@editor/utils/code-block'; import { getEditorConfig } from '@editor/utils/config'; defineOptions({ @@ -119,106 +113,23 @@ const diffChange = () => { difVisible.value = false; }; -const defaultParamColConfig = defineFormItem({ - type: 'row', - label: '参数类型', - items: [ - { - text: '参数类型', - labelWidth: '70px', - type: 'select', - name: 'type', - options: [ - { - text: '数字', - label: '数字', - value: 'number', - }, - { - text: '字符串', - label: '字符串', - value: 'text', - }, - { - text: '组件', - label: '组件', - value: 'ui-select', - }, - ], - }, - ], -}); +const codeOptions = inject>('codeOptions', {}); -const functionConfig = computed( - () => - defineFormConfig([ - { - text: '名称', - name: 'name', - rules: [{ required: true, message: '请输入名称', trigger: 'blur' }], - }, - { - text: '描述', - name: 'desc', - }, - { - text: '执行时机', - name: 'timing', - type: 'select', - options: () => { - const options = [ - { text: '初始化前', value: 'beforeInit' }, - { text: '初始化后', value: 'afterInit' }, - ]; - if (props.dataSourceType !== 'base') { - options.push({ text: '请求前', value: 'beforeRequest' }); - options.push({ text: '请求后', value: 'afterRequest' }); - } - return options; - }, - display: () => props.isDataSource, - }, - { - type: 'table', - border: true, - text: '参数', - enableFullscreen: false, - enableToggleMode: false, - name: 'params', - dropSort: false, - items: [ - { - type: 'text', - label: '参数名', - name: 'name', - }, - { - type: 'text', - label: '描述', - name: 'extra', - }, - codeBlockService.getParamsColConfig() || defaultParamColConfig, - ], - }, - { - name: 'content', - type: 'vs-code', - options: inject('codeOptions', {}), - autosize: { minRows: 10, maxRows: 30 }, - onChange: (_formState, code: string) => { - try { - // 检测js代码是否存在语法错误 - getEditorConfig('parseDSL')(code); - - return code; - } catch (error: any) { - tMagicMessage.error(error.message); - - throw error; - } - }, - }, - ]) as FormConfig, +/** + * 代码块编辑表单配置。统一委托到 utils/code-block 的 `getCodeBlockFormConfig`, + * 与 CompareForm 等其它使用方共享同一份 schema,避免双份维护。 + * + * 这里以 computed 包裹是为了让 `props.isDataSource` / `props.dataSourceType` 变化时 + * "执行时机"字段的可见性与可选项实时刷新。 + */ +const functionConfig = computed(() => + getCodeBlockFormConfig({ + paramColConfig: codeBlockService.getParamsColConfig(), + isDataSource: () => Boolean(props.isDataSource), + dataSourceType: () => props.dataSourceType, + codeOptions, + editable: true, + }), ); const parseContent = (content: any) => { diff --git a/packages/editor/src/components/CompareForm.vue b/packages/editor/src/components/CompareForm.vue new file mode 100644 index 00000000..52142741 --- /dev/null +++ b/packages/editor/src/components/CompareForm.vue @@ -0,0 +1,192 @@ + + + diff --git a/packages/editor/src/index.ts b/packages/editor/src/index.ts index 45781463..2cc2198c 100644 --- a/packages/editor/src/index.ts +++ b/packages/editor/src/index.ts @@ -70,6 +70,7 @@ export { default as LayoutContainer } from './components/SplitView.vue'; export { default as SplitView } from './components/SplitView.vue'; export { default as Resizer } from './components/Resizer.vue'; export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue'; +export { default as CompareForm } from './components/CompareForm.vue'; export { default as FloatingBox } from './components/FloatingBox.vue'; export { default as Tree } from './components/Tree.vue'; export { default as TreeNode } from './components/TreeNode.vue'; diff --git a/packages/editor/src/layouts/history-list/Bucket.vue b/packages/editor/src/layouts/history-list/Bucket.vue index 4051b01c..86ee43bf 100644 --- a/packages/editor/src/layouts/history-list/Bucket.vue +++ b/packages/editor/src/layouts/history-list/Bucket.vue @@ -22,12 +22,14 @@ applied: s.applied, isCurrent: s.isCurrent, desc: describeStep(s.step), + diffable: isStepDiffable ? isStepDiffable(s.step) : false, })) " :is-current="group.isCurrent" :expanded="!!expanded[`${prefix}-${bucketId}-${gIdx}`]" @toggle="(key: string) => $emit('toggle', key)" @goto="(index: number) => $emit('goto', bucketId, index)" + @diff-step="(index: number) => $emit('diff-step', bucketId, index)" />