@tmagic/editor 1.4.6 → 1.4.7

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/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.4.6",
2
+ "version": "1.4.7",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -50,8 +50,8 @@
50
50
  "lodash-es": "^4.17.21",
51
51
  "moveable": "^0.53.0",
52
52
  "serialize-javascript": "^6.0.0",
53
- "@tmagic/dep": "1.4.6",
54
- "@tmagic/table": "1.4.6"
53
+ "@tmagic/dep": "1.4.7",
54
+ "@tmagic/table": "1.4.7"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/events": "^3.0.0",
@@ -72,12 +72,12 @@
72
72
  "monaco-editor": "^0.48.0",
73
73
  "vue": "^3.4.27",
74
74
  "typescript": "*",
75
- "@tmagic/form": "1.4.6",
76
- "@tmagic/schema": "1.4.6",
77
- "@tmagic/design": "1.4.6",
78
- "@tmagic/core": "1.4.6",
79
- "@tmagic/utils": "1.4.6",
80
- "@tmagic/stage": "1.4.6"
75
+ "@tmagic/core": "1.4.7",
76
+ "@tmagic/design": "1.4.7",
77
+ "@tmagic/form": "1.4.7",
78
+ "@tmagic/schema": "1.4.7",
79
+ "@tmagic/stage": "1.4.7",
80
+ "@tmagic/utils": "1.4.7"
81
81
  },
82
82
  "peerDependenciesMeta": {
83
83
  "typescript": {
@@ -114,7 +114,9 @@ const selected = computed(() => nodeStatus.value.selected);
114
114
  const visible = computed(() => nodeStatus.value.visible);
115
115
  const draggable = computed(() => nodeStatus.value.draggable);
116
116
 
117
- const hasChildren = computed(() => props.data.items?.some((item) => props.nodeStatusMap.get(item.id)?.visible));
117
+ const hasChildren = computed(
118
+ () => Array.isArray(props.data.items) && props.data.items.some((item) => props.nodeStatusMap.get(item.id)?.visible),
119
+ );
118
120
 
119
121
  const handleDragStart = (event: DragEvent) => {
120
122
  treeEmit?.('node-dragstart', event, props.data);
@@ -1,5 +1,4 @@
1
1
  import type { EventOption } from '@tmagic/core';
2
- import type { CustomTargetOptions } from '@tmagic/dep';
3
2
  import type { FormConfig, FormState } from '@tmagic/form';
4
3
  import type { DataSourceSchema, Id, MApp, MNode } from '@tmagic/schema';
5
4
  import StageCore, {
@@ -70,12 +69,6 @@ export interface EditorProps {
70
69
  codeOptions?: { [key: string]: any };
71
70
  /** 禁用鼠标左键按下时就开始拖拽,需要先选中再可以拖拽 */
72
71
  disabledDragStart?: boolean;
73
- /** 自定义依赖收集器,复制组件时会将关联组件一并复制 */
74
- collectorOptions?: CustomTargetOptions;
75
- /** 自定义依赖收集器,复制组件时会将关联代码块一并复制 */
76
- collectorOptionsForCode?: CustomTargetOptions;
77
- /** 自定义依赖收集器,复制组件时会将关联数据源一并复制 */
78
- collectorOptionsForDataSource?: CustomTargetOptions;
79
72
  /** 标尺配置 */
80
73
  guidesOptions?: Partial<GuidesOptions>;
81
74
  /** 禁止多选 */
@@ -54,6 +54,7 @@ import { Coin } from '@element-plus/icons-vue';
54
54
  import { getConfig, TMagicAutocomplete, TMagicTag } from '@tmagic/design';
55
55
  import type { FieldProps, FormItem } from '@tmagic/form';
56
56
  import type { DataSchema, DataSourceSchema } from '@tmagic/schema';
57
+ import { isNumber } from '@tmagic/utils';
57
58
 
58
59
  import Icon from '@editor/components/Icon.vue';
59
60
  import type { Services } from '@editor/type';
@@ -209,7 +210,7 @@ const fieldQuerySearch = (
209
210
  const dsKey = queryString.substring(leftAngleIndex + 1, dotIndex);
210
211
 
211
212
  // 可能是xx.xx.xx,存在链式调用
212
- const keys = dsKey.split('.');
213
+ const keys = dsKey.replaceAll(/\[(\d+)\]/g, '.$1').split('.');
213
214
 
214
215
  // 最前的是数据源id
215
216
  const dsId = keys.shift();
@@ -224,6 +225,11 @@ const fieldQuerySearch = (
224
225
  // 后面这些是字段
225
226
  let key = keys.shift();
226
227
  while (key) {
228
+ if (isNumber(key)) {
229
+ key = keys.shift();
230
+ continue;
231
+ }
232
+
227
233
  for (const field of fields) {
228
234
  if (field.name === key) {
229
235
  fields = field.fields || [];
@@ -26,14 +26,14 @@
26
26
  @change="onChangeHandler"
27
27
  >
28
28
  <template #header>
29
- <MContainer
29
+ <MFormContainer
30
30
  class="fullWidth"
31
31
  :config="eventNameConfig"
32
32
  :model="cardItem"
33
33
  :disabled="disabled"
34
34
  :size="size"
35
35
  @change="onChangeHandler"
36
- ></MContainer>
36
+ ></MFormContainer>
37
37
  <TMagicButton
38
38
  style="color: #f56c6c"
39
39
  link
@@ -55,13 +55,13 @@ import { has } from 'lodash-es';
55
55
 
56
56
  import type { EventOption } from '@tmagic/core';
57
57
  import { TMagicButton } from '@tmagic/design';
58
- import type { CascaderOption, FieldProps, FormState, PanelConfig } from '@tmagic/form';
59
- import { MContainer, MPanel } from '@tmagic/form';
60
- import { ActionType } from '@tmagic/schema';
58
+ import type { CascaderOption, ChildConfig, FieldProps, FormState, PanelConfig } from '@tmagic/form';
59
+ import { MContainer as MFormContainer, MPanel } from '@tmagic/form';
60
+ import { ActionType, type MComponent, type MContainer } from '@tmagic/schema';
61
61
  import { DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX } from '@tmagic/utils';
62
62
 
63
63
  import type { CodeSelectColConfig, DataSourceMethodSelectConfig, EventSelectConfig, Services } from '@editor/type';
64
- import { getCascaderOptionsFromFields } from '@editor/utils';
64
+ import { getCascaderOptionsFromFields, traverseNode } from '@editor/utils';
65
65
 
66
66
  defineOptions({
67
67
  name: 'MFieldsEventSelect',
@@ -80,13 +80,20 @@ const codeBlockService = services?.codeBlockService;
80
80
 
81
81
  // 事件名称下拉框表单配置
82
82
  const eventNameConfig = computed(() => {
83
- const fieldType = props.config.src === 'component' ? 'select' : 'cascader';
84
- const defaultEventNameConfig = {
83
+ const defaultEventNameConfig: ChildConfig = {
85
84
  name: 'name',
86
85
  text: '事件',
87
- type: fieldType,
86
+ type: (mForm, { formValue }: any) => {
87
+ if (
88
+ props.config.src !== 'component' ||
89
+ (formValue.type === 'page-fragment-container' && formValue.pageFragmentId)
90
+ ) {
91
+ return 'cascader';
92
+ }
93
+ return 'select';
94
+ },
88
95
  labelWidth: '40px',
89
- checkStrictly: true,
96
+ checkStrictly: () => props.config.src !== 'component',
90
97
  valueSeparator: '.',
91
98
  options: (mForm: FormState, { formValue }: any) => {
92
99
  let events: EventOption[] | CascaderOption[] = [];
@@ -95,11 +102,39 @@ const eventNameConfig = computed(() => {
95
102
 
96
103
  if (props.config.src === 'component') {
97
104
  events = eventsService.getEvent(formValue.type);
105
+
106
+ if (formValue.type === 'page-fragment-container' && formValue.pageFragmentId) {
107
+ const pageFragment = editorService?.get('root')?.items?.find((page) => page.id === formValue.pageFragmentId);
108
+ if (pageFragment) {
109
+ events = [
110
+ {
111
+ label: pageFragment.name || '迭代器容器',
112
+ value: pageFragment.id,
113
+ children: events,
114
+ },
115
+ ];
116
+ pageFragment.items.forEach((node) => {
117
+ traverseNode<MComponent | MContainer>(node, (node) => {
118
+ const nodeEvents = (node.type && eventsService.getEvent(node.type)) || [];
119
+
120
+ events.push({
121
+ label: `${node.name}_${node.id}`,
122
+ value: `${node.id}`,
123
+ children: nodeEvents,
124
+ });
125
+ });
126
+ });
127
+
128
+ return events;
129
+ }
130
+ }
131
+
98
132
  return events.map((option) => ({
99
133
  text: option.label,
100
134
  value: option.value,
101
135
  }));
102
136
  }
137
+
103
138
  if (props.config.src === 'datasource') {
104
139
  // 从数据源类型中获取到相关事件
105
140
  events = dataSourceService.getFormEvent(formValue.type);
@@ -163,24 +198,63 @@ const targetCompConfig = computed(() => {
163
198
  text: '联动组件',
164
199
  type: 'ui-select',
165
200
  display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
201
+ onChange: (MForm: FormState, v: string, { model }: any) => {
202
+ model.method = '';
203
+ return v;
204
+ },
166
205
  };
167
206
  return { ...defaultTargetCompConfig, ...props.config.targetCompConfig };
168
207
  });
169
208
 
170
209
  // 联动组件动作配置
171
210
  const compActionConfig = computed(() => {
172
- const defaultCompActionConfig = {
211
+ const defaultCompActionConfig: ChildConfig = {
173
212
  name: 'method',
174
213
  text: '动作',
175
- type: 'select',
176
- display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
214
+ type: (mForm, { model }: any) => {
215
+ const to = editorService?.getNodeById(model.to);
216
+
217
+ if (to && to.type === 'page-fragment-container' && to.pageFragmentId) {
218
+ return 'cascader';
219
+ }
220
+
221
+ return 'select';
222
+ },
223
+ checkStrictly: () => props.config.src !== 'component',
224
+ display: (mForm, { model }: any) => model.actionType === ActionType.COMP,
177
225
  options: (mForm: FormState, { model }: any) => {
178
226
  const node = editorService?.getNodeById(model.to);
179
227
  if (!node?.type) return [];
180
228
 
181
- return eventsService?.getMethod(node.type).map((option: any) => ({
182
- text: option.label,
183
- value: option.value,
229
+ let methods: EventOption[] | CascaderOption[] = [];
230
+
231
+ methods = eventsService?.getMethod(node.type) || [];
232
+
233
+ if (node.type === 'page-fragment-container' && node.pageFragmentId) {
234
+ const pageFragment = editorService?.get('root')?.items?.find((page) => page.id === node.pageFragmentId);
235
+ if (pageFragment) {
236
+ methods = [];
237
+ pageFragment.items.forEach((node: MComponent | MContainer) => {
238
+ traverseNode<MComponent | MContainer>(node, (node) => {
239
+ const nodeMethods = (node.type && eventsService?.getMethod(node.type)) || [];
240
+
241
+ if (nodeMethods.length) {
242
+ methods.push({
243
+ label: `${node.name}_${node.id}`,
244
+ value: `${node.id}`,
245
+ children: nodeMethods,
246
+ });
247
+ }
248
+ });
249
+ });
250
+
251
+ return methods;
252
+ }
253
+ }
254
+
255
+ return methods.map((method) => ({
256
+ text: method.label,
257
+ value: method.value,
184
258
  }));
185
259
  },
186
260
  };
@@ -7,12 +7,11 @@ import {
7
7
  createDataSourceCondTarget,
8
8
  createDataSourceMethodTarget,
9
9
  createDataSourceTarget,
10
- createRelatedTargetForCopy,
11
10
  DepTargetType,
12
11
  Target,
13
12
  } from '@tmagic/dep';
14
13
  import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage, MPageFragment } from '@tmagic/schema';
15
- import { getNodes } from '@tmagic/utils';
14
+ import { getNodes, isPage } from '@tmagic/utils';
16
15
 
17
16
  import PropsPanel from './layouts/PropsPanel.vue';
18
17
  import { EditorProps } from './editorProps';
@@ -268,17 +267,12 @@ export const initServiceEvents = (
268
267
  }
269
268
  };
270
269
 
271
- const depUpdateHandler = (node: MNode) => {
272
- updateNodeWhenDataSourceChange([node]);
273
- };
274
-
275
270
  const collectedHandler = (nodes: MNode[]) => {
276
271
  updateNodeWhenDataSourceChange(nodes);
277
272
  };
278
273
 
279
274
  depService.on('add-target', targetAddHandler);
280
275
  depService.on('remove-target', targetRemoveHandler);
281
- depService.on('dep-update', depUpdateHandler);
282
276
  depService.on('collected', collectedHandler);
283
277
 
284
278
  const initDataSourceDepTarget = (ds: DataSourceSchema) => {
@@ -307,7 +301,9 @@ export const initServiceEvents = (
307
301
  });
308
302
 
309
303
  if (Array.isArray(value.items)) {
310
- depService.collect(value.items, true);
304
+ value.items.forEach((page) => {
305
+ depService.collectIdle([page], { pageId: page.id }, true);
306
+ });
311
307
  } else {
312
308
  depService.clear();
313
309
  delete value.dataSourceDeps;
@@ -334,14 +330,28 @@ export const initServiceEvents = (
334
330
  }
335
331
  };
336
332
 
333
+ const collectIdle = (nodes: MNode[], deep: boolean) => {
334
+ nodes.forEach((node) => {
335
+ let pageId: Id | undefined;
336
+
337
+ if (isPage(node)) {
338
+ pageId = node.id;
339
+ } else {
340
+ const info = editorService.getNodeInfo(node.id);
341
+ pageId = info.page?.id;
342
+ }
343
+ depService.collectIdle([node], { pageId }, deep);
344
+ });
345
+ };
346
+
337
347
  // 新增节点,收集依赖
338
348
  const nodeAddHandler = (nodes: MNode[]) => {
339
- depService.collect(nodes);
349
+ collectIdle(nodes, true);
340
350
  };
341
351
 
342
352
  // 节点更新,收集依赖
343
353
  const nodeUpdateHandler = (nodes: MNode[]) => {
344
- depService.collect(nodes);
354
+ collectIdle(nodes, false);
345
355
  };
346
356
 
347
357
  // 节点删除,清除对齐的依赖收集
@@ -351,7 +361,7 @@ export const initServiceEvents = (
351
361
 
352
362
  // 由于历史记录变化是更新整个page,所以历史记录变化时,需要重新收集依赖
353
363
  const historyChangeHandler = (page: MPage | MPageFragment) => {
354
- depService.collect([page], true);
364
+ depService.collectIdle([page], { pageId: page.id }, true);
355
365
  };
356
366
 
357
367
  editorService.on('history-change', historyChangeHandler);
@@ -386,7 +396,9 @@ export const initServiceEvents = (
386
396
  removeDataSourceTarget(config.id);
387
397
  initDataSourceDepTarget(config);
388
398
 
389
- depService.collect(root?.items || [], true);
399
+ (root?.items || []).forEach((page) => {
400
+ depService.collectIdle([page], { pageId: page.id }, true);
401
+ });
390
402
 
391
403
  const targets = depService.getTargets(DepTargetType.DATA_SOURCE);
392
404
 
@@ -410,25 +422,9 @@ export const initServiceEvents = (
410
422
  dataSourceService.on('update', dataSourceUpdateHandler);
411
423
  dataSourceService.on('remove', dataSourceRemoveHandler);
412
424
 
413
- // 初始化复制组件相关的依赖收集器
414
- if (props.collectorOptions && !depService.hasTarget(DepTargetType.RELATED_COMP_WHEN_COPY)) {
415
- depService.addTarget(createRelatedTargetForCopy(props.collectorOptions, DepTargetType.RELATED_COMP_WHEN_COPY));
416
- }
417
- if (props.collectorOptionsForCode && !depService.hasTarget(DepTargetType.RELATED_CODE_WHEN_COPY)) {
418
- depService.addTarget(
419
- createRelatedTargetForCopy(props.collectorOptionsForCode, DepTargetType.RELATED_CODE_WHEN_COPY),
420
- );
421
- }
422
- if (props.collectorOptionsForDataSource && !depService.hasTarget(DepTargetType.RELATED_DS_WHEN_COPY)) {
423
- depService.addTarget(
424
- createRelatedTargetForCopy(props.collectorOptionsForDataSource, DepTargetType.RELATED_DS_WHEN_COPY),
425
- );
426
- }
427
-
428
425
  onBeforeUnmount(() => {
429
426
  depService.off('add-target', targetAddHandler);
430
427
  depService.off('remove-target', targetRemoveHandler);
431
- depService.off('dep-update', depUpdateHandler);
432
428
  depService.off('collected', collectedHandler);
433
429
 
434
430
  editorService.off('history-change', historyChangeHandler);
@@ -58,26 +58,44 @@ const { codeBlockService, depService, editorService } = services || {};
58
58
 
59
59
  // 代码块列表
60
60
  const codeList = computed<TreeNodeData[]>(() =>
61
- Object.values(depService?.getTargets(DepTargetType.CODE_BLOCK) || {}).map((target) => {
61
+ Object.entries(codeBlockService?.getCodeDsl() || {}).map(([codeId, code]) => {
62
+ const target = depService?.getTarget(codeId, DepTargetType.CODE_BLOCK);
63
+
64
+ // 按页面分类显示
65
+ const pageList: TreeNodeData[] =
66
+ editorService?.get('root')?.items.map((page) => ({
67
+ name: page.devconfig?.tabName || page.name,
68
+ type: 'node',
69
+ id: `${codeId}_${page.id}`,
70
+ key: page.id,
71
+ items: [],
72
+ })) || [];
73
+
62
74
  // 组件节点
63
- const compNodes: TreeNodeData[] = Object.entries(target.deps).map(([id, dep]) => ({
64
- name: dep.name,
65
- type: 'node',
66
- id: `${target.id}_${id}`,
67
- key: id,
68
- items: dep.keys.map((key) => {
69
- const data: TreeNodeData = { name: `${key}`, id: `${target.id}_${id}_${key}`, type: 'key' };
70
- return data;
71
- }),
72
- }));
75
+ if (target) {
76
+ Object.entries(target.deps).forEach(([id, dep]) => {
77
+ const page = pageList.find((page) => page.key === dep.data?.pageId);
78
+ page?.items?.push({
79
+ name: dep.name,
80
+ type: 'node',
81
+ id: `${page.id}_${id}`,
82
+ key: id,
83
+ items: dep.keys.map((key) => {
84
+ const data: TreeNodeData = { name: `${key}`, id: `${target.id}_${id}_${key}`, type: 'key' };
85
+ return data;
86
+ }),
87
+ });
88
+ });
89
+ }
73
90
 
74
91
  const data: TreeNodeData = {
75
- id: target.id,
76
- key: target.id,
77
- name: target.name,
92
+ id: codeId,
93
+ key: codeId,
94
+ name: code.name,
78
95
  type: 'code',
79
- codeBlockContent: codeBlockService?.getCodeContentById(target.id),
80
- items: compNodes,
96
+ codeBlockContent: codeBlockService?.getCodeContentById(codeId),
97
+ // 只有一个页面不显示页面分类
98
+ items: pageList.length > 1 ? pageList.filter((page) => page.items?.length) : pageList[0]?.items || [],
81
99
  };
82
100
 
83
101
  return data;
@@ -81,16 +81,19 @@ const getNodeTreeConfig = (id: string, dep: DepData[string], type?: string, pare
81
81
  * @param deps 依赖
82
82
  * @param type 依赖类型
83
83
  */
84
- const mergeChildren = (dsId: Id, items: any[], deps: DepData, type?: string) => {
84
+ const mergeChildren = (dsId: Id, pageItems: any[], deps: DepData, type?: string) => {
85
85
  Object.entries(deps).forEach(([id, dep]) => {
86
+ // 按页面分类显示
87
+ const page = pageItems.find((page) => page.key === dep.data?.pageId);
88
+
86
89
  // 已经生成过的节点
87
- const nodeItem = items.find((item) => item.key === id);
90
+ const nodeItem = page?.items.find((item: any) => item.key === id);
88
91
  // 节点存在,则追加依赖的key
89
92
  if (nodeItem) {
90
93
  nodeItem.items = nodeItem.items.concat(getKeyTreeConfig(dep, type, nodeItem.key));
91
94
  } else {
92
95
  // 节点不存在,则生成
93
- items.push(getNodeTreeConfig(id, dep, type, dsId));
96
+ page?.items.push(getNodeTreeConfig(id, dep, type, page.id));
94
97
  }
95
98
  });
96
99
  };
@@ -101,7 +104,15 @@ const list = computed(() =>
101
104
  const dsMethodDeps = dsMethodDep.value[ds.id]?.deps || {};
102
105
  const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
103
106
 
104
- const items: any[] = [];
107
+ const items =
108
+ editorService?.get('root')?.items.map((page) => ({
109
+ name: page.devconfig?.tabName || page.name,
110
+ type: 'node',
111
+ id: `${ds.id}_${page.id}`,
112
+ key: page.id,
113
+ items: [],
114
+ })) || [];
115
+
105
116
  // 数据源依赖分为三种类型:key/node、method、cond,是分开存储,这里将其合并展示
106
117
  mergeChildren(ds.id, items, dsDeps);
107
118
  mergeChildren(ds.id, items, dsMethodDeps, 'method');
@@ -112,7 +123,8 @@ const list = computed(() =>
112
123
  key: ds.id,
113
124
  name: ds.title,
114
125
  type: 'ds',
115
- items,
126
+ // 只有一个页面不显示页面分类
127
+ items: items.length > 1 ? items.filter((page) => page.items.length) : items[0]?.items || [],
116
128
  };
117
129
  }),
118
130
  );
@@ -20,11 +20,10 @@ import { reactive } from 'vue';
20
20
  import { cloneDeep, get, keys, pick } from 'lodash-es';
21
21
  import type { Writable } from 'type-fest';
22
22
 
23
- import { DepTargetType } from '@tmagic/dep';
23
+ import { Target, type TargetOptions, Watcher } from '@tmagic/dep';
24
24
  import type { ColumnConfig } from '@tmagic/form';
25
25
  import type { CodeBlockContent, CodeBlockDSL, Id, MNode } from '@tmagic/schema';
26
26
 
27
- import depService from '@editor/services/dep';
28
27
  import editorService from '@editor/services/editor';
29
28
  import storageService, { Protocol } from '@editor/services/storage';
30
29
  import type { AsyncHookPlugin, CodeState } from '@editor/type';
@@ -258,17 +257,21 @@ class CodeBlock extends BaseService {
258
257
  * @param config 组件节点配置
259
258
  * @returns
260
259
  */
261
- public copyWithRelated(config: MNode | MNode[]): void {
260
+ public copyWithRelated(config: MNode | MNode[], collectorOptions?: TargetOptions): void {
262
261
  const copyNodes: MNode[] = Array.isArray(config) ? config : [config];
263
- // 关联的代码块也一并复制
264
- depService.clearByType(DepTargetType.RELATED_CODE_WHEN_COPY);
265
- depService.collect(copyNodes, true, DepTargetType.RELATED_CODE_WHEN_COPY);
266
- const customTarget = depService.getTarget(
267
- DepTargetType.RELATED_CODE_WHEN_COPY,
268
- DepTargetType.RELATED_CODE_WHEN_COPY,
269
- );
270
262
  const copyData: CodeBlockDSL = {};
271
- if (customTarget) {
263
+
264
+ if (collectorOptions && typeof collectorOptions.isTarget === 'function') {
265
+ const customTarget = new Target({
266
+ ...collectorOptions,
267
+ });
268
+
269
+ const coperWatcher = new Watcher();
270
+
271
+ coperWatcher.addTarget(customTarget);
272
+
273
+ coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
274
+
272
275
  Object.keys(customTarget.deps).forEach((nodeId: Id) => {
273
276
  const node = editorService.getNodeById(nodeId);
274
277
  if (!node) return;
@@ -3,12 +3,11 @@ import { cloneDeep, get } from 'lodash-es';
3
3
  import { Writable } from 'type-fest';
4
4
 
5
5
  import type { EventOption } from '@tmagic/core';
6
- import { DepTargetType } from '@tmagic/dep';
6
+ import { Target, type TargetOptions, Watcher } from '@tmagic/dep';
7
7
  import type { FormConfig } from '@tmagic/form';
8
8
  import type { DataSourceSchema, Id, MNode } from '@tmagic/schema';
9
9
  import { guid, toLine } from '@tmagic/utils';
10
10
 
11
- import depService from '@editor/services/dep';
12
11
  import editorService from '@editor/services/editor';
13
12
  import storageService, { Protocol } from '@editor/services/storage';
14
13
  import type { DatasourceTypeOption, SyncHookPlugin } from '@editor/type';
@@ -163,13 +162,21 @@ class DataSource extends BaseService {
163
162
  * @param config 组件节点配置
164
163
  * @returns
165
164
  */
166
- public copyWithRelated(config: MNode | MNode[]): void {
165
+ public copyWithRelated(config: MNode | MNode[], collectorOptions?: TargetOptions): void {
167
166
  const copyNodes: MNode[] = Array.isArray(config) ? config : [config];
168
- depService.clearByType(DepTargetType.RELATED_DS_WHEN_COPY);
169
- depService.collect(copyNodes, true, DepTargetType.RELATED_DS_WHEN_COPY);
170
- const customTarget = depService.getTarget(DepTargetType.RELATED_DS_WHEN_COPY, DepTargetType.RELATED_DS_WHEN_COPY);
171
167
  const copyData: DataSourceSchema[] = [];
172
- if (customTarget) {
168
+
169
+ if (collectorOptions && typeof collectorOptions.isTarget === 'function') {
170
+ const customTarget = new Target({
171
+ ...collectorOptions,
172
+ });
173
+
174
+ const coperWatcher = new Watcher();
175
+
176
+ coperWatcher.addTarget(customTarget);
177
+
178
+ coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
179
+
173
180
  Object.keys(customTarget.deps).forEach((nodeId: Id) => {
174
181
  const node = editorService.getNodeById(nodeId);
175
182
  if (!node) return;