@tmagic/editor 1.8.0-beta.2 → 1.8.0-beta.4

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.
Files changed (84) hide show
  1. package/dist/es/Editor.vue_vue_type_script_setup_true_lang.js +9 -0
  2. package/dist/es/components/CompareForm.vue_vue_type_script_setup_true_lang.js +46 -28
  3. package/dist/es/editorProps.js +2 -0
  4. package/dist/es/fields/CodeLink.vue_vue_type_script_setup_true_lang.js +2 -5
  5. package/dist/es/hooks/use-code-block-edit.js +6 -3
  6. package/dist/es/hooks/use-data-source-edit.js +5 -2
  7. package/dist/es/hooks/use-stage.js +8 -4
  8. package/dist/es/index.js +3 -1
  9. package/dist/es/layouts/CodeEditor.vue_vue_type_script_setup_true_lang.js +2 -5
  10. package/dist/es/layouts/NavMenu.vue_vue_type_script_setup_true_lang.js +1 -1
  11. package/dist/es/layouts/history-list/Bucket.vue_vue_type_script_setup_true_lang.js +37 -14
  12. package/dist/es/layouts/history-list/BucketTab.js +5 -0
  13. package/dist/es/layouts/history-list/{CodeBlockTab.vue_vue_type_script_setup_true_lang.js → BucketTab.vue_vue_type_script_setup_true_lang.js} +30 -16
  14. package/dist/es/layouts/history-list/GroupRow.vue_vue_type_script_setup_true_lang.js +91 -60
  15. package/dist/es/layouts/history-list/HistoryDiffDialog.vue_vue_type_script_setup_true_lang.js +82 -30
  16. package/dist/es/layouts/history-list/HistoryListPanel.vue_vue_type_script_setup_true_lang.js +140 -66
  17. package/dist/es/layouts/history-list/InitialRow.vue_vue_type_script_setup_true_lang.js +15 -9
  18. package/dist/es/layouts/history-list/PageTab.vue_vue_type_script_setup_true_lang.js +15 -6
  19. package/dist/es/layouts/history-list/composables.js +72 -2
  20. package/dist/es/layouts/props-panel/PropsPanel.vue_vue_type_script_setup_true_lang.js +5 -1
  21. package/dist/es/layouts/sidebar/ComponentListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  22. package/dist/es/layouts/sidebar/code-block/CodeBlockList.vue_vue_type_script_setup_true_lang.js +3 -3
  23. package/dist/es/layouts/sidebar/code-block/CodeBlockListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  24. package/dist/es/layouts/sidebar/code-block/useContentMenu.js +1 -1
  25. package/dist/es/layouts/sidebar/data-source/DataSourceListPanel.vue_vue_type_script_setup_true_lang.js +1 -1
  26. package/dist/es/layouts/sidebar/data-source/useContentMenu.js +1 -1
  27. package/dist/es/layouts/sidebar/layer/LayerMenu.vue_vue_type_script_setup_true_lang.js +5 -5
  28. package/dist/es/layouts/sidebar/layer/LayerNodeTool.vue_vue_type_script_setup_true_lang.js +1 -1
  29. package/dist/es/layouts/workspace/viewer/Stage.vue_vue_type_script_setup_true_lang.js +1 -1
  30. package/dist/es/layouts/workspace/viewer/ViewerMenu.vue_vue_type_script_setup_true_lang.js +8 -8
  31. package/dist/es/services/codeBlock.js +25 -10
  32. package/dist/es/services/dataSource.js +24 -10
  33. package/dist/es/services/editor.js +98 -46
  34. package/dist/es/services/history.js +7 -2
  35. package/dist/es/services/keybinding.js +3 -3
  36. package/dist/es/style.css +60 -16
  37. package/dist/es/utils/content-menu.js +17 -9
  38. package/dist/style.css +60 -16
  39. package/dist/tmagic-editor.umd.cjs +795 -443
  40. package/package.json +7 -7
  41. package/src/Editor.vue +8 -0
  42. package/src/components/CompareForm.vue +50 -19
  43. package/src/editorProps.ts +7 -0
  44. package/src/fields/CodeLink.vue +2 -5
  45. package/src/hooks/use-code-block-edit.ts +4 -3
  46. package/src/hooks/use-data-source-edit.ts +2 -2
  47. package/src/hooks/use-stage.ts +4 -3
  48. package/src/index.ts +2 -0
  49. package/src/layouts/CodeEditor.vue +2 -5
  50. package/src/layouts/NavMenu.vue +1 -1
  51. package/src/layouts/history-list/Bucket.vue +58 -29
  52. package/src/layouts/history-list/BucketTab.vue +80 -0
  53. package/src/layouts/history-list/GroupRow.vue +110 -58
  54. package/src/layouts/history-list/HistoryDiffDialog.vue +53 -33
  55. package/src/layouts/history-list/HistoryListPanel.vue +165 -52
  56. package/src/layouts/history-list/InitialRow.vue +17 -6
  57. package/src/layouts/history-list/PageTab.vue +25 -7
  58. package/src/layouts/history-list/composables.ts +92 -1
  59. package/src/layouts/props-panel/PropsPanel.vue +5 -1
  60. package/src/layouts/sidebar/ComponentListPanel.vue +9 -5
  61. package/src/layouts/sidebar/code-block/CodeBlockList.vue +5 -5
  62. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +1 -1
  63. package/src/layouts/sidebar/code-block/useContentMenu.ts +1 -1
  64. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
  65. package/src/layouts/sidebar/data-source/useContentMenu.ts +1 -1
  66. package/src/layouts/sidebar/layer/LayerMenu.vue +19 -11
  67. package/src/layouts/sidebar/layer/LayerNodeTool.vue +7 -4
  68. package/src/layouts/workspace/viewer/Stage.vue +1 -1
  69. package/src/layouts/workspace/viewer/ViewerMenu.vue +8 -8
  70. package/src/services/codeBlock.ts +33 -9
  71. package/src/services/dataSource.ts +30 -8
  72. package/src/services/editor.ts +111 -34
  73. package/src/services/history.ts +10 -0
  74. package/src/services/keybinding.ts +3 -3
  75. package/src/theme/history-list-panel.scss +67 -14
  76. package/src/theme/props-panel.scss +3 -3
  77. package/src/type.ts +146 -0
  78. package/src/utils/content-menu.ts +18 -9
  79. package/types/index.d.ts +387 -156
  80. package/dist/es/layouts/history-list/CodeBlockTab.js +0 -5
  81. package/dist/es/layouts/history-list/DataSourceTab.js +0 -5
  82. package/dist/es/layouts/history-list/DataSourceTab.vue_vue_type_script_setup_true_lang.js +0 -62
  83. package/src/layouts/history-list/CodeBlockTab.vue +0 -61
  84. package/src/layouts/history-list/DataSourceTab.vue +0 -61
@@ -12,15 +12,18 @@
12
12
  <span class="m-editor-history-list-item-index" :title="headIndexTitle">{{ headIndexLabel }}</span>
13
13
  <span class="m-editor-history-list-item-op" :class="`op-${opType}`">{{ opLabel(opType) }}</span>
14
14
  <span class="m-editor-history-list-item-desc">{{ desc }}</span>
15
- <span v-if="isCurrent" class="m-editor-history-list-item-current">当前</span>
15
+
16
16
  <span
17
- v-if="!merged && headDiffable"
18
- class="m-editor-history-list-item-diff"
19
- title="查看修改差异"
20
- @click.stop="onDiffClick(subSteps[0].index)"
21
- >查看差异</span
17
+ v-if="!merged && sourceLabel(source)"
18
+ class="m-editor-history-list-item-source"
19
+ :title="`操作途径:${sourceLabel(source)}`"
20
+ >{{ sourceLabel(source) }}</span
22
21
  >
22
+
23
+ <span v-if="!merged && time" class="m-editor-history-list-item-time" :title="timeTitle || time">{{ time }}</span>
24
+
23
25
  <span v-if="merged" class="m-editor-history-list-item-merge">合并 {{ stepCount }} 步</span>
26
+
24
27
  <span
25
28
  v-if="!merged && headRevertable"
26
29
  class="m-editor-history-list-item-revert"
@@ -28,6 +31,20 @@
28
31
  @click.stop="onRevertClick(subSteps[0].index)"
29
32
  >回滚</span
30
33
  >
34
+ <span
35
+ v-if="!merged && gotoEnabled && !isCurrent && subSteps.length"
36
+ class="m-editor-history-list-item-goto"
37
+ title="回到该记录"
38
+ @click.stop="onGotoClick(subSteps[0].index)"
39
+ >回到</span
40
+ >
41
+ <span
42
+ v-if="!merged && headDiffable"
43
+ class="m-editor-history-list-item-diff"
44
+ title="查看修改差异"
45
+ @click.stop="onDiffClick(subSteps[0].index)"
46
+ >查看差异</span
47
+ >
31
48
  <span v-if="merged" class="m-editor-history-list-group-toggle" :class="{ 'is-expanded': expanded }">▾</span>
32
49
  </div>
33
50
 
@@ -35,20 +52,18 @@
35
52
  <li
36
53
  v-for="s in subStepsDisplay"
37
54
  :key="s.index"
38
- :class="{ 'is-undone': !s.applied, 'is-current': s.isCurrent, 'is-clickable': !s.isCurrent }"
39
- :title="s.isCurrent ? '当前所在记录' : '点击跳转到该记录'"
40
- @click="onSubStepClick(s)"
55
+ :class="{ 'is-undone': !s.applied, 'is-current': s.isCurrent }"
56
+ :title="subStepTitle(s)"
41
57
  >
42
58
  <span class="m-editor-history-list-item-index">#{{ s.index + 1 }}</span>
43
59
  <span class="m-editor-history-list-substep-desc">{{ s.desc }}</span>
44
- <span v-if="s.isCurrent" class="m-editor-history-list-item-current">当前</span>
45
60
  <span
46
- v-if="s.diffable"
47
- class="m-editor-history-list-item-diff"
48
- title="查看修改差异"
49
- @click.stop="onDiffClick(s.index)"
50
- >查看差异</span
61
+ v-if="sourceLabel(s.source)"
62
+ class="m-editor-history-list-item-source"
63
+ :title="`操作途径:${sourceLabel(s.source)}`"
64
+ >{{ sourceLabel(s.source) }}</span
51
65
  >
66
+ <span v-if="s.time" class="m-editor-history-list-item-time" :title="s.timeTitle || s.time">{{ s.time }}</span>
52
67
  <span
53
68
  v-if="s.revertable"
54
69
  class="m-editor-history-list-item-revert"
@@ -56,6 +71,20 @@
56
71
  @click.stop="onRevertClick(s.index)"
57
72
  >回滚</span
58
73
  >
74
+ <span
75
+ v-if="gotoEnabled && !s.isCurrent"
76
+ class="m-editor-history-list-item-goto"
77
+ title="回到该记录"
78
+ @click.stop="onGotoClick(s.index)"
79
+ >回到</span
80
+ >
81
+ <span
82
+ v-if="s.diffable"
83
+ class="m-editor-history-list-item-diff"
84
+ title="查看修改差异"
85
+ @click.stop="onDiffClick(s.index)"
86
+ >查看差异</span
87
+ >
59
88
  </li>
60
89
  </ul>
61
90
  </li>
@@ -64,42 +93,66 @@
64
93
  <script lang="ts" setup>
65
94
  import { computed } from 'vue';
66
95
 
67
- import type { HistoryOpType } from '@editor/type';
96
+ import type { HistoryOpSource, HistoryOpType } from '@editor/type';
68
97
 
69
- import { opLabel } from './composables';
98
+ import { opLabel, sourceLabel } from './composables';
70
99
 
71
100
  defineOptions({
72
101
  name: 'MEditorHistoryListGroupRow',
73
102
  });
74
103
 
75
- const props = defineProps<{
76
- /** 唯一标识当前组的 key,作为 toggle 事件的 payload 回传给上层。形如 `pg-${idx}` / `ds-${id}-${idx}` / `cb-${id}-${idx}`。 */
77
- groupKey: string;
78
- /** 该组当前是否处于已应用状态(false 表示已被 undo 撤销,UI 会显示为灰态)。 */
79
- applied: boolean;
80
- /** 是否为合并组(即组内 step 数大于 1,由多次连续操作合并而来)。决定是否展示合并标记与可展开的子步列表。 */
81
- merged: boolean;
82
- /** 操作类型:`add` / `remove` / `update`,用于决定操作徽标的颜色和文案。 */
83
- opType: HistoryOpType;
84
- /** 组的整体描述文案,由上层根据 step / group 计算后传入,例如 "修改 button · style.color"。 */
85
- desc: string;
86
- /** 组内的 step 总数,仅在 merged 为 true 时显示为 "合并 N 步"。 */
87
- stepCount: number;
88
- /** 子步列表,用于在展开状态下逐条展示每个 step 的索引、应用状态与描述文案。 */
89
- subSteps: {
90
- index: number;
104
+ const props = withDefaults(
105
+ defineProps<{
106
+ /** 唯一标识当前组的 key,作为 toggle 事件的 payload 回传给上层。形如 `pg-${首步 index}` / `ds-${id}-${首步 index}` / `cb-${id}-${首步 index}`,以稳定的 step 索引标识分组。 */
107
+ groupKey: string;
108
+ /** 该组当前是否处于已应用状态(false 表示已被 undo 撤销,UI 会显示为灰态)。 */
91
109
  applied: boolean;
110
+ /** 是否为合并组(即组内 step 数大于 1,由多次连续操作合并而来)。决定是否展示合并标记与可展开的子步列表。 */
111
+ merged: boolean;
112
+ /** 操作类型:`add` / `remove` / `update`,用于决定操作徽标的颜色和文案。 */
113
+ opType: HistoryOpType;
114
+ /** 组的整体描述文案,由上层根据 step / group 计算后传入,例如 "修改 button · style.color"。 */
92
115
  desc: string;
116
+ /** 组的操作途径(一般取组内最近一步),用于头部展示「画布 / 树面板 / 配置面板…」标签。 */
117
+ source?: HistoryOpSource;
118
+ /** 组头部展示的时间文案(一般为组内最近一步的时间),为空时不渲染。 */
119
+ time?: string;
120
+ /** 组头部时间的 title 悬浮提示(完整时间),缺省时回退为 time。 */
121
+ timeTitle?: string;
122
+ /** 组内的 step 总数,仅在 merged 为 true 时显示为 "合并 N 步"。 */
123
+ stepCount: number;
124
+ /** 子步列表,用于在展开状态下逐条展示每个 step 的索引、应用状态与描述文案。 */
125
+ subSteps: {
126
+ index: number;
127
+ applied: boolean;
128
+ desc: string;
129
+ isCurrent?: boolean;
130
+ diffable?: boolean;
131
+ /** 是否可对该子步执行「回滚」(已应用 + 业务侧确认支持反向)。父级根据 step 与 applied 决定。 */
132
+ revertable?: boolean;
133
+ /** 该子步的操作途径,用于展示「画布 / 树面板 / 配置面板…」标签。 */
134
+ source?: HistoryOpSource;
135
+ /** 该子步的时间文案,为空时不渲染。 */
136
+ time?: string;
137
+ /** 该子步时间的 title 悬浮提示(完整时间),缺省时回退为 time。 */
138
+ timeTitle?: string;
139
+ }[];
140
+ /** 当前组是否处于展开状态。仅在 merged 为 true 时生效,控制子步列表是否渲染。 */
141
+ expanded: boolean;
142
+ /** 是否为当前所在的分组(包含栈中最近一次已应用步骤的那一组),UI 高亮展示。 */
93
143
  isCurrent?: boolean;
94
- diffable?: boolean;
95
- /** 是否可对该子步执行「回滚」(已应用 + 业务侧确认支持反向)。父级根据 step 与 applied 决定。 */
96
- revertable?: boolean;
97
- }[];
98
- /** 当前组是否处于展开状态。仅在 merged 为 true 时生效,控制子步列表是否渲染。 */
99
- expanded: boolean;
100
- /** 是否为当前所在的分组(包含栈中最近一次已应用步骤的那一组),UI 高亮展示。 */
101
- isCurrent?: boolean;
102
- }>();
144
+ /**
145
+ * 是否支持「跳转到该记录」(goto)。默认 true。
146
+ * 为 false 时:单步组头部与子步条目都不再可点击跳转、也不会触发 goto 事件,
147
+ * 仅保留合并组头部的展开 / 收起能力,以及查看差异、回滚等其它入口。
148
+ */
149
+ gotoEnabled?: boolean;
150
+ }>(),
151
+ {
152
+ isCurrent: false,
153
+ gotoEnabled: true,
154
+ },
155
+ );
103
156
 
104
157
  const emit = defineEmits<{
105
158
  /**
@@ -129,36 +182,35 @@ const emit = defineEmits<{
129
182
  (_e: 'revert-step', _index: number): void;
130
183
  }>();
131
184
 
132
- /** 单步组:头部可点击 goto;合并组:头部可点击切换展开。当前组(isCurrent)的单步组头部不可点击。 */
133
- const isHeadClickable = computed(() => {
134
- if (props.merged) return true;
135
- return !props.isCurrent;
136
- });
185
+ /**
186
+ * 仅合并组头部可点击(切换展开 / 收起);
187
+ * 单步组的跳转改由头部的「回退」按钮触发,整行不再可点击。
188
+ */
189
+ const isHeadClickable = computed(() => props.merged);
137
190
 
138
191
  const headTitle = computed(() => {
139
192
  if (props.merged) return props.expanded ? '点击收起子步' : '点击展开子步';
140
193
  if (props.isCurrent) return '当前所在记录';
141
- return '点击跳转到该记录';
194
+ return '';
142
195
  });
143
196
 
144
197
  /**
145
- * 头部点击行为分流:
146
- * - 合并组:仅切换展开 / 收起,不触发 goto;
147
- * - 单步组:跳转到该唯一步骤;当前组忽略点击。
198
+ * 头部点击行为:仅合并组切换展开 / 收起;单步组不再响应整行点击。
148
199
  */
149
200
  const onHeadClick = () => {
150
201
  if (props.merged) {
151
202
  emit('toggle', props.groupKey);
152
- return;
153
203
  }
154
- if (props.isCurrent) return;
155
- if (!props.subSteps.length) return;
156
- emit('goto', props.subSteps[0].index);
157
204
  };
158
205
 
159
- const onSubStepClick = (s: { index: number; isCurrent?: boolean }) => {
160
- if (s.isCurrent) return;
161
- emit('goto', s.index);
206
+ const onGotoClick = (index: number) => {
207
+ if (!props.gotoEnabled) return;
208
+ emit('goto', index);
209
+ };
210
+
211
+ const subStepTitle = (s: { isCurrent?: boolean }) => {
212
+ if (s.isCurrent) return '当前所在记录';
213
+ return '';
162
214
  };
163
215
 
164
216
  /** 单步组头部是否展示"查看差异"入口:要求该唯一子步本身可对比。 */
@@ -3,13 +3,16 @@
3
3
  <TMagicDialog
4
4
  v-model="visible"
5
5
  class="m-editor-history-diff-dialog"
6
- title="查看修改差异"
7
- width="900px"
6
+ :title="dialogTitle"
8
7
  top="5vh"
9
8
  destroy-on-close
10
9
  append-to-body
10
+ :width="width"
11
+ @close="onClose"
11
12
  >
12
13
  <div v-if="payload" class="m-editor-history-diff-dialog-body">
14
+ <div v-if="onConfirm" class="m-editor-history-diff-dialog-notice">仅回滚有差异的字段</div>
15
+
13
16
  <div class="m-editor-history-diff-dialog-header">
14
17
  <span class="m-editor-history-diff-dialog-target">{{ targetText }}</span>
15
18
  <div class="m-editor-history-diff-dialog-controls">
@@ -42,6 +45,8 @@
42
45
  :value="rightValue"
43
46
  :last-value="leftValue"
44
47
  :extend-state="extendState"
48
+ :load-config="loadConfig"
49
+ :self-diff-field-types="selfDiffFieldTypes"
45
50
  height="70vh"
46
51
  />
47
52
 
@@ -58,7 +63,11 @@
58
63
  </div>
59
64
 
60
65
  <template #footer>
61
- <TMagicButton size="small" @click="visible = false">关闭</TMagicButton>
66
+ <template v-if="onConfirm">
67
+ <TMagicButton size="small" @click="visible = false">取消</TMagicButton>
68
+ <TMagicButton size="small" type="primary" @click="onConfirmClick">确定回滚</TMagicButton>
69
+ </template>
70
+ <TMagicButton v-else size="small" @click="visible = false">关闭</TMagicButton>
62
71
  </template>
63
72
  </TMagicDialog>
64
73
  </Teleport>
@@ -71,41 +80,37 @@ import { isEqual } from 'lodash-es';
71
80
  import { TMagicButton, TMagicDialog, TMagicRadioButton, TMagicRadioGroup, TMagicTag } from '@tmagic/design';
72
81
  import type { FormState } from '@tmagic/form';
73
82
 
74
- import CompareForm, { type CompareCategory } from '@editor/components/CompareForm.vue';
83
+ import CompareForm from '@editor/components/CompareForm.vue';
75
84
  import CodeEditor from '@editor/layouts/CodeEditor.vue';
85
+ import type { CompareCategory, CompareFormLoadConfig, DiffDialogPayload } from '@editor/type';
76
86
 
77
87
  defineOptions({
78
88
  name: 'MEditorHistoryDiffDialog',
79
89
  });
80
90
 
81
- defineProps<{
82
- /**
83
- * 来自 Editor 顶层的 `extendFormState`,用于扩展 MForm.formState。
84
- * 透传给 CompareForm,从而让差异对比时表单 item 中依赖业务上下文的
85
- * `display` / `disabled` 等 filterFunction 正常工作。
86
- */
87
- extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
88
- }>();
89
-
90
- /** 差异对话框的入参 */
91
- export interface DiffDialogPayload {
92
- /** 表单类别 */
93
- category: CompareCategory;
94
- /** 节点类型 / 数据源类型 */
95
- type?: string;
96
- /** 代码块场景下的数据源类型 */
97
- dataSourceType?: string;
98
- /** 该 step 修改前的值(oldNode / oldSchema / oldContent) */
99
- lastValue: Record<string, any>;
100
- /** 该 step 修改后的值(newNode / newSchema / newContent) */
101
- value: Record<string, any>;
102
- /** 当前编辑器中实际的最新值;不传或为 null 时禁用「与当前对比」 */
103
- currentValue?: Record<string, any> | null;
104
- /** 用于标题展示的目标名称 */
105
- targetLabel?: string;
106
- /** 用于标题展示的目标 id */
107
- id?: string | number;
108
- }
91
+ const props = withDefaults(
92
+ defineProps<{
93
+ /**
94
+ * 来自 Editor 顶层的 `extendFormState`,用于扩展 MForm.formState。
95
+ * 透传给 CompareForm,从而让差异对比时表单 item 中依赖业务上下文的
96
+ * `display` / `disabled` 等 filterFunction 正常工作。
97
+ */
98
+ extendState?: (_state: FormState) => Record<string, any> | Promise<Record<string, any>>;
99
+ /**
100
+ * 自定义 FormConfig 加载逻辑,透传给 CompareForm。传入后将接管内置的按 `category`
101
+ * 取配置逻辑,可通过 `ctx.defaultLoadConfig()` 复用默认结果再做二次加工。
102
+ */
103
+ loadConfig?: CompareFormLoadConfig;
104
+ width?: string;
105
+ onConfirm?: () => void;
106
+ selfDiffFieldTypes?: string[];
107
+ }>(),
108
+ {
109
+ width: '900px',
110
+ },
111
+ );
112
+
113
+ const emit = defineEmits(['close']);
109
114
 
110
115
  /**
111
116
  * 差异对比模式:
@@ -146,6 +151,8 @@ const codeDiffOptions = {
146
151
  },
147
152
  };
148
153
 
154
+ const dialogTitle = computed(() => (props.onConfirm ? '确认回滚' : '查看修改差异'));
155
+
149
156
  const hasCurrent = computed(() => payload.value?.currentValue !== undefined && payload.value?.currentValue !== null);
150
157
 
151
158
  /** 左侧(旧/参照)值 */
@@ -171,6 +178,14 @@ const isSameAsCurrent = computed(() => {
171
178
  return isEqual(payload.value.value, payload.value.currentValue);
172
179
  });
173
180
 
181
+ const onConfirmClick = () => {
182
+ const cb = props.onConfirm;
183
+
184
+ cb?.();
185
+
186
+ visible.value = false;
187
+ };
188
+
174
189
  const targetText = computed(() => {
175
190
  if (!payload.value) return '';
176
191
  const categoryText: Record<CompareCategory, string> = {
@@ -178,7 +193,8 @@ const targetText = computed(() => {
178
193
  'data-source': '数据源',
179
194
  'code-block': '代码块',
180
195
  };
181
- const prefix = categoryText[payload.value.category] || '';
196
+ const { category } = payload.value;
197
+ const prefix = category ? categoryText[category] : '';
182
198
  const label = payload.value.targetLabel || payload.value.type || '';
183
199
  const { id } = payload.value;
184
200
  const labelWithId = id !== undefined && id !== '' ? `${label}(${id})` : label;
@@ -205,6 +221,10 @@ watch(visible, (v) => {
205
221
  }
206
222
  });
207
223
 
224
+ const onClose = () => {
225
+ emit('close');
226
+ };
227
+
208
228
  defineExpose({
209
229
  open,
210
230
  close,