@tmagic/editor 1.4.5 → 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.
Files changed (38) hide show
  1. package/dist/tmagic-editor.js +2293 -1984
  2. package/dist/tmagic-editor.umd.cjs +2294 -1982
  3. package/package.json +19 -14
  4. package/src/components/TreeNode.vue +3 -1
  5. package/src/editorProps.ts +0 -3
  6. package/src/fields/DataSourceInput.vue +7 -1
  7. package/src/fields/EventSelect.vue +90 -16
  8. package/src/hooks/use-code-block-edit.ts +0 -2
  9. package/src/hooks/use-stage.ts +1 -1
  10. package/src/index.ts +1 -0
  11. package/src/initService.ts +24 -18
  12. package/src/layouts/sidebar/code-block/CodeBlockList.vue +34 -16
  13. package/src/layouts/sidebar/data-source/DataSourceList.vue +17 -5
  14. package/src/services/codeBlock.ts +80 -9
  15. package/src/services/dataSource.ts +60 -4
  16. package/src/services/dep.ts +77 -5
  17. package/src/services/editor.ts +23 -14
  18. package/src/services/props.ts +19 -8
  19. package/src/services/stageOverlay.ts +1 -0
  20. package/src/type.ts +1 -0
  21. package/src/utils/data-source/index.ts +20 -13
  22. package/src/utils/editor.ts +2 -0
  23. package/src/utils/idle-task.ts +72 -0
  24. package/src/utils/operator.ts +6 -6
  25. package/types/editorProps.d.ts +0 -3
  26. package/types/index.d.ts +1 -0
  27. package/types/layouts/PropsPanel.vue.d.ts +33 -33
  28. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +1 -1
  29. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +1 -1
  30. package/types/services/codeBlock.d.ts +23 -2
  31. package/types/services/dataSource.d.ts +13 -1
  32. package/types/services/dep.d.ts +12 -2
  33. package/types/services/editor.d.ts +3 -2
  34. package/types/services/props.d.ts +2 -1
  35. package/types/type.d.ts +1 -0
  36. package/types/utils/editor.d.ts +2 -0
  37. package/types/utils/idle-task.d.ts +14 -0
  38. package/types/utils/operator.d.ts +2 -2
@@ -8,9 +8,9 @@ import * as monaco from 'monaco-editor';
8
8
  import { MContainer, MForm, filterFunction, createValues, MFormBox, MCascader, MSelect, MPanel } from '@tmagic/form';
9
9
  import { HookCodeType, HookType, NodeType, ActionType } from '@tmagic/schema';
10
10
  import { MagicTable } from '@tmagic/table';
11
- import { toLine, guid, isPage, isPageFragment, isPop, getNodePath, isNumber, calcValueByFontsize, getValueByKeyPath, setValueByKeyPath, convertToNumber, getDefaultValueFromFields, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, getKeys, addClassName, removeClassName, removeClassNameByClassName, getNodes } from '@tmagic/utils';
11
+ import { toLine, guid, getNodePath, getValueByKeyPath, setValueByKeyPath, isPage, isPageFragment, isPop, isNumber, calcValueByFontsize, convertToNumber, getDefaultValueFromFields, DATA_SOURCE_FIELDS_SELECT_VALUE_PREFIX, DATA_SOURCE_FIELDS_CHANGE_EVENT_PREFIX, getKeys, addClassName, removeClassName, removeClassNameByClassName, getNodes } from '@tmagic/utils';
12
12
  import VanillaMoveable from 'moveable';
13
- import { Watcher, DepTargetType, createRelatedCompTarget, createCodeBlockTarget, createDataSourceTarget, createDataSourceMethodTarget, createDataSourceCondTarget } from '@tmagic/dep';
13
+ import { Target, Watcher, DepTargetType, createCodeBlockTarget, createDataSourceTarget, createDataSourceMethodTarget, createDataSourceCondTarget } from '@tmagic/dep';
14
14
  export { DepTargetType } from '@tmagic/dep';
15
15
  import { EventEmitter } from 'events';
16
16
  import Gesto from 'gesto';
@@ -505,388 +505,94 @@ const _sfc_main$Q = /* @__PURE__ */ defineComponent({
505
505
  }
506
506
  });
507
507
 
508
- function BaseFormConfig() {
509
- return [
510
- {
511
- name: "id",
512
- type: "hidden"
513
- },
514
- {
515
- name: "type",
516
- text: "类型",
517
- type: "hidden",
518
- defaultValue: "base"
519
- },
520
- {
521
- name: "title",
522
- text: "名称",
523
- rules: [
524
- {
525
- required: true,
526
- message: "请输入名称"
508
+ const compose = (middleware, isAsync) => {
509
+ if (!Array.isArray(middleware))
510
+ throw new TypeError("Middleware 必须是一个数组!");
511
+ for (const fn of middleware) {
512
+ if (typeof fn !== "function")
513
+ throw new TypeError("Middleware 必须由函数组成!");
514
+ }
515
+ return (args, next) => {
516
+ let index = -1;
517
+ return dispatch(0);
518
+ function dispatch(i) {
519
+ if (i <= index) {
520
+ const error = new Error("next() 被多次调用");
521
+ if (isAsync) {
522
+ return Promise.reject(error);
527
523
  }
528
- ]
529
- },
530
- {
531
- name: "description",
532
- text: "描述"
533
- }
534
- ];
535
- }
536
-
537
- const HttpFormConfig = [
538
- {
539
- name: "autoFetch",
540
- text: "自动请求",
541
- type: "switch",
542
- defaultValue: true
543
- },
544
- {
545
- name: "responseOptions",
546
- items: [
547
- {
548
- name: "dataPath",
549
- text: "数据路径"
524
+ throw error;
550
525
  }
551
- ]
552
- },
553
- {
554
- type: "fieldset",
555
- name: "options",
556
- legend: "HTTP 配置",
557
- items: [
558
- {
559
- name: "url",
560
- text: "URL"
561
- },
562
- {
563
- name: "method",
564
- text: "Method",
565
- type: "select",
566
- options: [
567
- { text: "GET", value: "GET" },
568
- { text: "POST", value: "POST" },
569
- { text: "PUT", value: "PUT" },
570
- { text: "DELETE", value: "DELETE" }
571
- ]
572
- },
573
- {
574
- name: "params",
575
- type: "key-value",
576
- defaultValue: {},
577
- text: "参数"
578
- },
579
- {
580
- name: "data",
581
- type: "key-value",
582
- defaultValue: {},
583
- advanced: true,
584
- text: "请求体"
585
- },
586
- {
587
- name: "headers",
588
- type: "key-value",
589
- defaultValue: {},
590
- text: "请求头"
526
+ index = i;
527
+ let fn = middleware[i];
528
+ if (i === middleware.length && next)
529
+ fn = next;
530
+ if (!fn) {
531
+ if (isAsync) {
532
+ return Promise.resolve();
533
+ }
534
+ return;
591
535
  }
592
- ]
593
- }
594
- ];
536
+ if (isAsync) {
537
+ try {
538
+ return Promise.resolve(fn(...args, dispatch.bind(null, i + 1)));
539
+ } catch (err) {
540
+ return Promise.reject(err);
541
+ }
542
+ }
543
+ try {
544
+ return fn(...args, dispatch.bind(null, i + 1));
545
+ } catch (err) {
546
+ throw err;
547
+ }
548
+ }
549
+ };
550
+ };
595
551
 
596
- const fillConfig$1 = (config) => [
597
- ...BaseFormConfig(),
598
- ...config,
599
- {
600
- type: "tab",
601
- items: [
602
- {
603
- title: "数据定义",
604
- items: [
605
- {
606
- name: "fields",
607
- type: "data-source-fields",
608
- defaultValue: () => []
609
- }
610
- ]
611
- },
612
- {
613
- title: "方法定义",
614
- items: [
615
- {
616
- name: "methods",
617
- type: "data-source-methods",
618
- defaultValue: () => []
619
- }
620
- ]
621
- },
622
- {
623
- title: "事件配置",
624
- items: [
625
- {
626
- name: "events",
627
- src: "datasource",
628
- type: "event-select"
629
- }
630
- ]
631
- },
632
- {
633
- title: "mock数据",
634
- items: [
635
- {
636
- name: "mocks",
637
- type: "data-source-mocks",
638
- defaultValue: () => []
639
- }
640
- ]
641
- },
642
- {
643
- title: "请求参数裁剪",
644
- display: (formState, { model }) => model.type === "http",
645
- items: [
646
- {
647
- name: "beforeRequest",
648
- type: "vs-code",
649
- parse: true,
650
- height: "600px"
651
- }
652
- ]
653
- },
654
- {
655
- title: "响应数据裁剪",
656
- display: (formState, { model }) => model.type === "http",
657
- items: [
658
- {
659
- name: "afterResponse",
660
- type: "vs-code",
661
- parse: true,
662
- height: "600px"
663
- }
664
- ]
552
+ const methodName = (prefix, name) => `${prefix}${name[0].toUpperCase()}${name.substring(1)}`;
553
+ const isError = (error) => Object.prototype.toString.call(error) === "[object Error]";
554
+ const doAction = (args, scope, sourceMethod, beforeMethodName, afterMethodName, fn) => {
555
+ try {
556
+ let beforeArgs = args;
557
+ for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
558
+ beforeArgs = beforeMethod(...beforeArgs) || [];
559
+ if (isError(beforeArgs))
560
+ throw beforeArgs;
561
+ if (!Array.isArray(beforeArgs)) {
562
+ beforeArgs = [beforeArgs];
665
563
  }
666
- ]
667
- }
668
- ];
669
- const getFormConfig = (type, configs) => {
670
- switch (type) {
671
- case "base":
672
- return fillConfig$1([]);
673
- case "http":
674
- return fillConfig$1(HttpFormConfig);
675
- default:
676
- return fillConfig$1(configs[type] || []);
564
+ }
565
+ let returnValue = fn(beforeArgs, sourceMethod.bind(scope));
566
+ for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
567
+ returnValue = afterMethod(returnValue, ...beforeArgs);
568
+ if (isError(returnValue))
569
+ throw returnValue;
570
+ }
571
+ return returnValue;
572
+ } catch (error) {
573
+ throw error;
677
574
  }
678
575
  };
679
- const getFormValue = (type, values) => {
680
- if (type !== "http") {
681
- return values;
682
- }
683
- return {
684
- beforeRequest: `(options, context) => {
685
- /**
686
- * 用户可以直接编写函数,在原始接口调用之前,会运行该函数,将这个函数的返回值作为该数据源接口的入参
687
- *
688
- * options: HttpOptions
689
- *
690
- * interface HttpOptions {
691
- * // 请求链接
692
- * url: string;
693
- * // query参数
694
- * params?: Record<string, string>;
695
- * // body数据
696
- * data?: Record<string, any>;
697
- * // 请求头
698
- * headers?: Record<string, string>;
699
- * // 请求方法 GET/POST
700
- * method?: Method;
701
- * }
702
- *
703
- * context:上下文对象
704
- *
705
- * interface Content {
706
- * app: AppCore;
707
- * dataSource: HttpDataSource;
708
- * }
709
- *
710
- * return: HttpOptions
711
- */
712
-
713
- // 此处的返回值会作为这个接口的入参
714
- return options;
715
- }`,
716
- afterResponse: `(response, context) => {
717
- /**
718
- * 用户可以直接编写函数,在原始接口返回之后,会运行该函数,将这个函数的返回值作为该数据源接口的返回
719
-
720
- * context:上下文对象
721
- *
722
- * interface Content {
723
- * app: AppCore;
724
- * dataSource: HttpDataSource;
725
- * }
726
- *
727
- */
728
-
729
- // 此处的返回值会作为这个接口的返回值
730
- return response;
731
- }`,
732
- ...values
733
- };
734
- };
735
- const getDisplayField = (dataSources, key) => {
736
- const displayState = [];
737
- const matches = key.matchAll(/\$\{([\s\S]+?)\}/g);
738
- let index = 0;
739
- for (const match of matches) {
740
- if (typeof match.index === "undefined")
741
- break;
742
- displayState.push({
743
- type: "text",
744
- value: key.substring(index, match.index)
745
- });
746
- let dsText = "";
747
- let ds;
748
- let fields;
749
- match[1].split(".").forEach((item, index2) => {
750
- if (index2 === 0) {
751
- ds = dataSources.find((ds2) => ds2.id === item);
752
- dsText += ds?.title || item;
753
- fields = ds?.fields;
754
- return;
755
- }
756
- const field = fields?.find((field2) => field2.name === item);
757
- fields = field?.fields;
758
- dsText += `.${field?.title || item}`;
759
- });
760
- displayState.push({
761
- type: "var",
762
- value: dsText
763
- });
764
- index = match.index + match[0].length;
765
- }
766
- if (index < key.length) {
767
- displayState.push({
768
- type: "text",
769
- value: key.substring(index)
770
- });
771
- }
772
- return displayState;
773
- };
774
- const getCascaderOptionsFromFields = (fields = [], dataSourceFieldType = ["any"]) => {
775
- const child = [];
776
- fields.forEach((field) => {
777
- if (!dataSourceFieldType.length) {
778
- dataSourceFieldType.push("any");
779
- }
780
- const children = getCascaderOptionsFromFields(field.fields, dataSourceFieldType);
781
- const item = {
782
- label: field.title || field.name,
783
- value: field.name,
784
- children
785
- };
786
- const fieldType = field.type || "any";
787
- if (dataSourceFieldType.includes("any") || dataSourceFieldType.includes(fieldType)) {
788
- child.push(item);
789
- return;
790
- }
791
- if (!dataSourceFieldType.includes(fieldType) && !["array", "object", "any"].includes(fieldType)) {
792
- return;
793
- }
794
- if (!children.length && ["object", "array", "any"].includes(field.type || "")) {
795
- return;
796
- }
797
- child.push(item);
798
- });
799
- return child;
800
- };
801
-
802
- const compose = (middleware, isAsync) => {
803
- if (!Array.isArray(middleware))
804
- throw new TypeError("Middleware 必须是一个数组!");
805
- for (const fn of middleware) {
806
- if (typeof fn !== "function")
807
- throw new TypeError("Middleware 必须由函数组成!");
808
- }
809
- return (args, next) => {
810
- let index = -1;
811
- return dispatch(0);
812
- function dispatch(i) {
813
- if (i <= index) {
814
- const error = new Error("next() 被多次调用");
815
- if (isAsync) {
816
- return Promise.reject(error);
817
- }
818
- throw error;
819
- }
820
- index = i;
821
- let fn = middleware[i];
822
- if (i === middleware.length && next)
823
- fn = next;
824
- if (!fn) {
825
- if (isAsync) {
826
- return Promise.resolve();
827
- }
828
- return;
829
- }
830
- if (isAsync) {
831
- try {
832
- return Promise.resolve(fn(...args, dispatch.bind(null, i + 1)));
833
- } catch (err) {
834
- return Promise.reject(err);
835
- }
836
- }
837
- try {
838
- return fn(...args, dispatch.bind(null, i + 1));
839
- } catch (err) {
840
- throw err;
841
- }
842
- }
843
- };
844
- };
845
-
846
- const methodName = (prefix, name) => `${prefix}${name[0].toUpperCase()}${name.substring(1)}`;
847
- const isError = (error) => Object.prototype.toString.call(error) === "[object Error]";
848
- const doAction = (args, scope, sourceMethod, beforeMethodName, afterMethodName, fn) => {
849
- try {
850
- let beforeArgs = args;
851
- for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
852
- beforeArgs = beforeMethod(...beforeArgs) || [];
853
- if (isError(beforeArgs))
854
- throw beforeArgs;
855
- if (!Array.isArray(beforeArgs)) {
856
- beforeArgs = [beforeArgs];
857
- }
858
- }
859
- let returnValue = fn(beforeArgs, sourceMethod.bind(scope));
860
- for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
861
- returnValue = afterMethod(returnValue, ...beforeArgs);
862
- if (isError(returnValue))
863
- throw returnValue;
864
- }
865
- return returnValue;
866
- } catch (error) {
867
- throw error;
868
- }
869
- };
870
- const doAsyncAction = async (args, scope, sourceMethod, beforeMethodName, afterMethodName, fn) => {
871
- try {
872
- let beforeArgs = args;
873
- for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
874
- beforeArgs = await beforeMethod(...beforeArgs) || [];
875
- if (isError(beforeArgs))
876
- throw beforeArgs;
877
- if (!Array.isArray(beforeArgs)) {
878
- beforeArgs = [beforeArgs];
879
- }
880
- }
881
- let returnValue = await fn(beforeArgs, sourceMethod.bind(scope));
882
- for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
883
- returnValue = await afterMethod(returnValue, ...beforeArgs);
884
- if (isError(returnValue))
885
- throw returnValue;
886
- }
887
- return returnValue;
888
- } catch (error) {
889
- throw error;
576
+ const doAsyncAction = async (args, scope, sourceMethod, beforeMethodName, afterMethodName, fn) => {
577
+ try {
578
+ let beforeArgs = args;
579
+ for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
580
+ beforeArgs = await beforeMethod(...beforeArgs) || [];
581
+ if (isError(beforeArgs))
582
+ throw beforeArgs;
583
+ if (!Array.isArray(beforeArgs)) {
584
+ beforeArgs = [beforeArgs];
585
+ }
586
+ }
587
+ let returnValue = await fn(beforeArgs, sourceMethod.bind(scope));
588
+ for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
589
+ returnValue = await afterMethod(returnValue, ...beforeArgs);
590
+ if (isError(returnValue))
591
+ throw returnValue;
592
+ }
593
+ return returnValue;
594
+ } catch (error) {
595
+ throw error;
890
596
  }
891
597
  };
892
598
  class BaseService extends EventEmitter {
@@ -963,1077 +669,204 @@ class BaseService extends EventEmitter {
963
669
  }
964
670
 
965
671
  const canUsePluginMethods$6 = {
966
- async: [],
967
- sync: [
968
- "getFormConfig",
969
- "setFormConfig",
970
- "getFormValue",
971
- "setFormValue",
972
- "getFormEvent",
973
- "setFormEvent",
974
- "getFormMethod",
975
- "setFormMethod",
976
- "add",
977
- "update",
978
- "remove",
979
- "createId"
980
- ]
672
+ async: [
673
+ "setPropsConfig",
674
+ "getPropsConfig",
675
+ "setPropsValue",
676
+ "getPropsValue",
677
+ "fillConfig",
678
+ "getDefaultPropsValue"
679
+ ],
680
+ sync: ["createId", "setNewItemId"]
981
681
  };
982
- class DataSource extends BaseService {
682
+ class Props extends BaseService {
983
683
  state = reactive({
984
- datasourceTypeList: [],
985
- dataSources: [],
986
- editable: true,
987
- configs: {},
988
- values: {},
989
- events: {},
990
- methods: {}
684
+ propsConfigMap: {},
685
+ propsValueMap: {},
686
+ relateIdMap: {}
991
687
  });
992
688
  constructor() {
993
- super(canUsePluginMethods$6.sync.map((methodName) => ({ name: methodName, isAsync: false })));
994
- }
995
- set(name, value) {
996
- this.state[name] = value;
997
- }
998
- get(name) {
999
- return this.state[name];
689
+ super([
690
+ ...canUsePluginMethods$6.async.map((methodName) => ({ name: methodName, isAsync: true })),
691
+ ...canUsePluginMethods$6.sync.map((methodName) => ({ name: methodName, isAsync: false }))
692
+ ]);
1000
693
  }
1001
- getFormConfig(type = "base") {
1002
- return getFormConfig(toLine(type), this.get("configs"));
694
+ setPropsConfigs(configs) {
695
+ Object.keys(configs).forEach((type) => {
696
+ this.setPropsConfig(toLine(type), configs[type]);
697
+ });
698
+ this.emit("props-configs-change");
1003
699
  }
1004
- setFormConfig(type, config) {
1005
- this.get("configs")[toLine(type)] = config;
700
+ async fillConfig(config, labelWidth) {
701
+ return fillConfig(config, typeof labelWidth !== "function" ? labelWidth : "80px");
1006
702
  }
1007
- getFormValue(type = "base") {
1008
- return getFormValue(toLine(type), this.get("values")[type]);
703
+ async setPropsConfig(type, config) {
704
+ this.state.propsConfigMap[toLine(type)] = await this.fillConfig(Array.isArray(config) ? config : [config]);
1009
705
  }
1010
- setFormValue(type, value) {
1011
- this.get("values")[toLine(type)] = value;
1012
- }
1013
- getFormEvent(type = "base") {
1014
- return this.get("events")[toLine(type)] || [];
1015
- }
1016
- setFormEvent(type, value = []) {
1017
- this.get("events")[toLine(type)] = value;
706
+ /**
707
+ * 获取指点类型的组件属性表单配置
708
+ * @param type 组件类型
709
+ * @returns 组件属性表单配置
710
+ */
711
+ async getPropsConfig(type) {
712
+ if (type === "area") {
713
+ return await this.getPropsConfig("button");
714
+ }
715
+ return cloneDeep(this.state.propsConfigMap[toLine(type)] || await this.fillConfig([]));
1018
716
  }
1019
- getFormMethod(type = "base") {
1020
- return this.get("methods")[toLine(type)] || [];
717
+ setPropsValues(values) {
718
+ Object.keys(values).forEach((type) => {
719
+ this.setPropsValue(toLine(type), values[type]);
720
+ });
1021
721
  }
1022
- setFormMethod(type, value = []) {
1023
- this.get("methods")[toLine(type)] = value;
722
+ /**
723
+ * 为指点类型组件设置组件初始值
724
+ * @param type 组件类型
725
+ * @param value 组件初始值
726
+ */
727
+ async setPropsValue(type, value) {
728
+ this.state.propsValueMap[toLine(type)] = value;
1024
729
  }
1025
- add(config) {
1026
- const newConfig = {
1027
- ...config,
1028
- id: this.createId()
730
+ /**
731
+ * 获取指定类型的组件初始值
732
+ * @param type 组件类型
733
+ * @returns 组件初始值
734
+ */
735
+ async getPropsValue(componentType, { inputEvent, ...defaultValue } = {}) {
736
+ const type = toLine(componentType);
737
+ if (type === "area") {
738
+ const value = await this.getPropsValue("button");
739
+ value.className = "action-area";
740
+ value.text = "";
741
+ if (value.style) {
742
+ value.style.backgroundColor = "rgba(255, 255, 255, 0)";
743
+ }
744
+ return value;
745
+ }
746
+ const id = this.createId(type);
747
+ const defaultPropsValue = this.getDefaultPropsValue(type);
748
+ const data = this.setNewItemId(
749
+ cloneDeep({
750
+ type,
751
+ ...defaultValue
752
+ })
753
+ );
754
+ return {
755
+ id,
756
+ ...defaultPropsValue,
757
+ ...mergeWith({}, cloneDeep(this.state.propsValueMap[type] || {}), data)
1029
758
  };
1030
- this.get("dataSources").push(newConfig);
1031
- this.emit("add", newConfig);
1032
- return newConfig;
1033
759
  }
1034
- update(config) {
1035
- const dataSources = this.get("dataSources");
1036
- const index = dataSources.findIndex((ds) => ds.id === config.id);
1037
- dataSources[index] = cloneDeep(config);
1038
- this.emit("update", config);
760
+ createId(type) {
761
+ return `${type}_${guid()}`;
762
+ }
763
+ /**
764
+ * 将组件与组件的子元素配置中的id都设置成一个新的ID
765
+ * 如果没有相同ID并且force为false则保持不变
766
+ * @param {Object} config 组件配置
767
+ * @param {Boolean} force 是否强制设置新的ID
768
+ */
769
+ /* eslint no-param-reassign: ["error", { "props": false }] */
770
+ setNewItemId(config, force = true) {
771
+ if (force || editorService.getNodeById(config.id)) {
772
+ const newId = this.createId(config.type || "component");
773
+ this.setRelateId(config.id, newId);
774
+ config.id = newId;
775
+ }
776
+ if (config.items && Array.isArray(config.items)) {
777
+ for (const item of config.items) {
778
+ this.setNewItemId(item);
779
+ }
780
+ }
1039
781
  return config;
1040
782
  }
1041
- remove(id) {
1042
- const dataSources = this.get("dataSources");
1043
- const index = dataSources.findIndex((ds) => ds.id === id);
1044
- dataSources.splice(index, 1);
1045
- this.emit("remove", id);
783
+ /**
784
+ * 获取默认属性配置
785
+ * @param type 组件类型
786
+ * @returns Object
787
+ */
788
+ getDefaultPropsValue(type) {
789
+ return ["page", "container"].includes(type) ? {
790
+ type,
791
+ layout: "absolute",
792
+ style: {},
793
+ name: type,
794
+ items: []
795
+ } : {
796
+ type,
797
+ style: {},
798
+ name: type
799
+ };
1046
800
  }
1047
- createId() {
1048
- return `ds_${guid()}`;
801
+ resetState() {
802
+ this.state.propsConfigMap = {};
803
+ this.state.propsValueMap = {};
1049
804
  }
1050
- getDataSourceById(id) {
1051
- return this.get("dataSources").find((ds) => ds.id === id);
805
+ /**
806
+ * 替换关联ID
807
+ * @param originConfigs 原组件配置
808
+ * @param targetConfigs 待替换的组件配置
809
+ */
810
+ replaceRelateId(originConfigs, targetConfigs, collectorOptions) {
811
+ const relateIdMap = this.getRelateIdMap();
812
+ if (Object.keys(relateIdMap).length === 0)
813
+ return;
814
+ const target = new Target({
815
+ ...collectorOptions
816
+ });
817
+ const coperWatcher = new Watcher();
818
+ coperWatcher.addTarget(target);
819
+ coperWatcher.collect(originConfigs, {}, true, collectorOptions.type);
820
+ originConfigs.forEach((config) => {
821
+ const newId = relateIdMap[config.id];
822
+ const path = getNodePath(newId, targetConfigs);
823
+ const targetConfig = path[path.length - 1];
824
+ if (!targetConfig)
825
+ return;
826
+ target.deps[config.id]?.keys?.forEach((fullKey) => {
827
+ const relateOriginId = getValueByKeyPath(fullKey, config);
828
+ const relateTargetId = relateIdMap[relateOriginId];
829
+ if (!relateTargetId)
830
+ return;
831
+ setValueByKeyPath(fullKey, relateTargetId, targetConfig);
832
+ });
833
+ if (config.items && Array.isArray(config.items)) {
834
+ this.replaceRelateId(config.items, targetConfigs, collectorOptions);
835
+ }
836
+ });
1052
837
  }
1053
- resetState() {
1054
- this.set("dataSources", []);
838
+ /**
839
+ * 清除setNewItemId前后映射关系
840
+ */
841
+ clearRelateId() {
842
+ this.state.relateIdMap = {};
1055
843
  }
1056
844
  destroy() {
1057
- this.removeAllListeners();
1058
845
  this.resetState();
846
+ this.removeAllListeners();
1059
847
  this.removeAllPlugins();
1060
848
  }
1061
849
  usePlugin(options) {
1062
850
  super.usePlugin(options);
1063
851
  }
852
+ /**
853
+ * 获取setNewItemId前后映射关系
854
+ * @param oldId 原组件ID
855
+ * @returns 新旧ID映射
856
+ */
857
+ getRelateIdMap() {
858
+ return this.state.relateIdMap;
859
+ }
860
+ /**
861
+ * 记录setNewItemId前后映射关系
862
+ * @param oldId 原组件ID
863
+ * @param newId 分配的新ID
864
+ */
865
+ setRelateId(oldId, newId) {
866
+ this.state.relateIdMap[oldId] = newId;
867
+ }
1064
868
  }
1065
- const dataSourceService = new DataSource();
1066
-
1067
- const arrayOptions = [
1068
- { text: "包含", value: "include" },
1069
- { text: "不包含", value: "not_include" }
1070
- ];
1071
- const eqOptions = [
1072
- { text: "等于", value: "=" },
1073
- { text: "不等于", value: "!=" }
1074
- ];
1075
- const numberOptions = [
1076
- { text: "大于", value: ">" },
1077
- { text: "大于等于", value: ">=" },
1078
- { text: "小于", value: "<" },
1079
- { text: "小于等于", value: "<=" },
1080
- { text: "在范围内", value: "between" },
1081
- { text: "不在范围内", value: "not_between" }
1082
- ];
1083
- const styleTabConfig = {
1084
- title: "样式",
1085
- items: [
1086
- {
1087
- name: "style",
1088
- items: [
1089
- {
1090
- type: "fieldset",
1091
- legend: "位置",
1092
- items: [
1093
- {
1094
- type: "data-source-field-select",
1095
- name: "position",
1096
- text: "固定定位",
1097
- checkStrictly: false,
1098
- dataSourceFieldType: ["string"],
1099
- fieldConfig: {
1100
- type: "checkbox",
1101
- activeValue: "fixed",
1102
- inactiveValue: "absolute",
1103
- defaultValue: "absolute"
1104
- }
1105
- },
1106
- {
1107
- type: "data-source-field-select",
1108
- name: "left",
1109
- text: "left",
1110
- checkStrictly: false,
1111
- dataSourceFieldType: ["string", "number"],
1112
- fieldConfig: {
1113
- type: "text"
1114
- }
1115
- },
1116
- {
1117
- type: "data-source-field-select",
1118
- name: "top",
1119
- text: "top",
1120
- checkStrictly: false,
1121
- dataSourceFieldType: ["string", "number"],
1122
- fieldConfig: {
1123
- type: "text"
1124
- },
1125
- disabled: (vm, { model }) => model.position === "fixed" && model._magic_position === "fixedBottom"
1126
- },
1127
- {
1128
- type: "data-source-field-select",
1129
- name: "right",
1130
- text: "right",
1131
- checkStrictly: false,
1132
- dataSourceFieldType: ["string", "number"],
1133
- fieldConfig: {
1134
- type: "text"
1135
- }
1136
- },
1137
- {
1138
- type: "data-source-field-select",
1139
- name: "bottom",
1140
- text: "bottom",
1141
- checkStrictly: false,
1142
- dataSourceFieldType: ["string", "number"],
1143
- fieldConfig: {
1144
- type: "text"
1145
- },
1146
- disabled: (vm, { model }) => model.position === "fixed" && model._magic_position === "fixedTop"
1147
- }
1148
- ]
1149
- },
1150
- {
1151
- type: "fieldset",
1152
- legend: "盒子",
1153
- items: [
1154
- {
1155
- type: "data-source-field-select",
1156
- name: "width",
1157
- text: "宽度",
1158
- checkStrictly: false,
1159
- dataSourceFieldType: ["string", "number"],
1160
- fieldConfig: {
1161
- type: "text"
1162
- }
1163
- },
1164
- {
1165
- type: "data-source-field-select",
1166
- name: "height",
1167
- text: "高度",
1168
- checkStrictly: false,
1169
- dataSourceFieldType: ["string", "number"],
1170
- fieldConfig: {
1171
- type: "text"
1172
- }
1173
- },
1174
- {
1175
- type: "data-source-field-select",
1176
- text: "overflow",
1177
- name: "overflow",
1178
- checkStrictly: false,
1179
- dataSourceFieldType: ["string"],
1180
- fieldConfig: {
1181
- type: "select",
1182
- options: [
1183
- { text: "visible", value: "visible" },
1184
- { text: "hidden", value: "hidden" },
1185
- { text: "clip", value: "clip" },
1186
- { text: "scroll", value: "scroll" },
1187
- { text: "auto", value: "auto" },
1188
- { text: "overlay", value: "overlay" }
1189
- ]
1190
- }
1191
- }
1192
- ]
1193
- },
1194
- {
1195
- type: "fieldset",
1196
- legend: "边框",
1197
- items: [
1198
- {
1199
- type: "data-source-field-select",
1200
- name: "borderWidth",
1201
- text: "宽度",
1202
- defaultValue: "0",
1203
- checkStrictly: false,
1204
- dataSourceFieldType: ["string", "number"],
1205
- fieldConfig: {
1206
- type: "text"
1207
- }
1208
- },
1209
- {
1210
- type: "data-source-field-select",
1211
- name: "borderColor",
1212
- text: "颜色",
1213
- checkStrictly: false,
1214
- dataSourceFieldType: ["string"],
1215
- fieldConfig: {
1216
- type: "text"
1217
- }
1218
- },
1219
- {
1220
- type: "data-source-field-select",
1221
- name: "borderStyle",
1222
- text: "样式",
1223
- defaultValue: "none",
1224
- checkStrictly: false,
1225
- dataSourceFieldType: ["string"],
1226
- fieldConfig: {
1227
- type: "select",
1228
- options: [
1229
- { text: "none", value: "none" },
1230
- { text: "hidden", value: "hidden" },
1231
- { text: "dotted", value: "dotted" },
1232
- { text: "dashed", value: "dashed" },
1233
- { text: "solid", value: "solid" },
1234
- { text: "double", value: "double" },
1235
- { text: "groove", value: "groove" },
1236
- { text: "ridge", value: "ridge" },
1237
- { text: "inset", value: "inset" },
1238
- { text: "outset", value: "outset" }
1239
- ]
1240
- }
1241
- }
1242
- ]
1243
- },
1244
- {
1245
- type: "fieldset",
1246
- legend: "背景",
1247
- items: [
1248
- {
1249
- type: "data-source-field-select",
1250
- name: "backgroundImage",
1251
- text: "背景图",
1252
- checkStrictly: false,
1253
- dataSourceFieldType: ["string"],
1254
- fieldConfig: {
1255
- type: "text"
1256
- }
1257
- },
1258
- {
1259
- type: "data-source-field-select",
1260
- name: "backgroundColor",
1261
- text: "背景颜色",
1262
- checkStrictly: false,
1263
- dataSourceFieldType: ["string"],
1264
- fieldConfig: {
1265
- type: "colorPicker"
1266
- }
1267
- },
1268
- {
1269
- type: "data-source-field-select",
1270
- name: "backgroundRepeat",
1271
- text: "背景图重复",
1272
- defaultValue: "no-repeat",
1273
- checkStrictly: false,
1274
- dataSourceFieldType: ["string"],
1275
- fieldConfig: {
1276
- type: "select",
1277
- options: [
1278
- { text: "repeat", value: "repeat" },
1279
- { text: "repeat-x", value: "repeat-x" },
1280
- { text: "repeat-y", value: "repeat-y" },
1281
- { text: "no-repeat", value: "no-repeat" },
1282
- { text: "inherit", value: "inherit" }
1283
- ]
1284
- }
1285
- },
1286
- {
1287
- type: "data-source-field-select",
1288
- name: "backgroundSize",
1289
- text: "背景图大小",
1290
- defaultValue: "100% 100%",
1291
- checkStrictly: false,
1292
- dataSourceFieldType: ["string"],
1293
- fieldConfig: {
1294
- type: "text"
1295
- }
1296
- }
1297
- ]
1298
- },
1299
- {
1300
- type: "fieldset",
1301
- legend: "字体",
1302
- items: [
1303
- {
1304
- type: "data-source-field-select",
1305
- name: "color",
1306
- text: "颜色",
1307
- checkStrictly: false,
1308
- dataSourceFieldType: ["string"],
1309
- fieldConfig: {
1310
- type: "colorPicker"
1311
- }
1312
- },
1313
- {
1314
- type: "data-source-field-select",
1315
- name: "fontSize",
1316
- text: "大小",
1317
- checkStrictly: false,
1318
- dataSourceFieldType: ["string", "number"],
1319
- fieldConfig: {
1320
- type: "text"
1321
- }
1322
- },
1323
- {
1324
- type: "data-source-field-select",
1325
- name: "fontWeight",
1326
- text: "粗细",
1327
- checkStrictly: false,
1328
- dataSourceFieldType: ["string", "number"],
1329
- fieldConfig: {
1330
- type: "text"
1331
- }
1332
- }
1333
- ]
1334
- },
1335
- {
1336
- type: "fieldset",
1337
- legend: "变形",
1338
- name: "transform",
1339
- items: [
1340
- {
1341
- type: "data-source-field-select",
1342
- name: "rotate",
1343
- text: "旋转角度",
1344
- checkStrictly: false,
1345
- dataSourceFieldType: ["string"],
1346
- fieldConfig: {
1347
- type: "text"
1348
- }
1349
- },
1350
- {
1351
- type: "data-source-field-select",
1352
- name: "scale",
1353
- text: "缩放",
1354
- checkStrictly: false,
1355
- dataSourceFieldType: ["number", "string"],
1356
- fieldConfig: {
1357
- type: "text"
1358
- }
1359
- }
1360
- ]
1361
- }
1362
- ]
1363
- }
1364
- ]
1365
- };
1366
- const eventTabConfig = {
1367
- title: "事件",
1368
- items: [
1369
- {
1370
- name: "events",
1371
- src: "component",
1372
- labelWidth: "100px",
1373
- type: "event-select"
1374
- }
1375
- ]
1376
- };
1377
- const advancedTabConfig = {
1378
- title: "高级",
1379
- lazy: true,
1380
- items: [
1381
- {
1382
- name: "created",
1383
- text: "created",
1384
- type: "code-select"
1385
- },
1386
- {
1387
- name: "mounted",
1388
- text: "mounted",
1389
- type: "code-select"
1390
- }
1391
- ]
1392
- };
1393
- const displayTabConfig = {
1394
- title: "显示条件",
1395
- display: (vm, { model }) => model.type !== "page",
1396
- items: [
1397
- {
1398
- type: "groupList",
1399
- name: "displayConds",
1400
- titlePrefix: "条件组",
1401
- expandAll: true,
1402
- items: [
1403
- {
1404
- type: "table",
1405
- name: "cond",
1406
- items: [
1407
- {
1408
- type: "data-source-field-select",
1409
- name: "field",
1410
- value: "key",
1411
- label: "字段",
1412
- checkStrictly: false,
1413
- dataSourceFieldType: ["string", "number", "boolean", "any"]
1414
- },
1415
- {
1416
- type: "select",
1417
- options: (mForm, { model }) => {
1418
- const [id, ...fieldNames] = model.field;
1419
- const ds = dataSourceService.getDataSourceById(id);
1420
- let fields = ds?.fields || [];
1421
- let type = "";
1422
- (fieldNames || []).forEach((fieldName) => {
1423
- const field = fields.find((f) => f.name === fieldName);
1424
- fields = field?.fields || [];
1425
- type = field?.type || "";
1426
- });
1427
- if (type === "array") {
1428
- return arrayOptions;
1429
- }
1430
- if (type === "boolean") {
1431
- return [
1432
- { text: "是", value: "is" },
1433
- { text: "不是", value: "not" }
1434
- ];
1435
- }
1436
- if (type === "number") {
1437
- return [...eqOptions, ...numberOptions];
1438
- }
1439
- if (type === "string") {
1440
- return [...arrayOptions, ...eqOptions];
1441
- }
1442
- return [...arrayOptions, ...eqOptions, ...numberOptions];
1443
- },
1444
- label: "条件",
1445
- name: "op"
1446
- },
1447
- {
1448
- label: "值",
1449
- items: [
1450
- {
1451
- name: "value",
1452
- type: (mForm, { model }) => {
1453
- const [id, ...fieldNames] = model.field;
1454
- const ds = dataSourceService.getDataSourceById(id);
1455
- let fields = ds?.fields || [];
1456
- let type = "";
1457
- (fieldNames || []).forEach((fieldName) => {
1458
- const field = fields.find((f) => f.name === fieldName);
1459
- fields = field?.fields || [];
1460
- type = field?.type || "";
1461
- });
1462
- if (type === "number") {
1463
- return "number";
1464
- }
1465
- if (type === "boolean") {
1466
- return "select";
1467
- }
1468
- return "text";
1469
- },
1470
- options: [
1471
- { text: "true", value: true },
1472
- { text: "false", value: false }
1473
- ],
1474
- display: (vm, { model }) => !["between", "not_between"].includes(model.op)
1475
- },
1476
- {
1477
- name: "range",
1478
- type: "number-range",
1479
- display: (vm, { model }) => ["between", "not_between"].includes(model.op)
1480
- }
1481
- ]
1482
- }
1483
- ]
1484
- }
1485
- ]
1486
- }
1487
- ]
1488
- };
1489
- const fillConfig = (config = [], labelWidth = "80px") => [
1490
- {
1491
- type: "tab",
1492
- labelWidth,
1493
- items: [
1494
- {
1495
- title: "属性",
1496
- items: [
1497
- // 组件类型,必须要有
1498
- {
1499
- text: "type",
1500
- name: "type",
1501
- type: "hidden"
1502
- },
1503
- // 组件id,必须要有
1504
- {
1505
- name: "id",
1506
- type: "display",
1507
- text: "id"
1508
- },
1509
- {
1510
- name: "name",
1511
- text: "组件名称"
1512
- },
1513
- ...config
1514
- ]
1515
- },
1516
- { ...styleTabConfig },
1517
- { ...eventTabConfig },
1518
- { ...advancedTabConfig },
1519
- { ...displayTabConfig }
1520
- ]
1521
- }
1522
- ];
1523
-
1524
- const log = (...args) => {
1525
- if (process.env.NODE_ENV === "development") {
1526
- console.log("magic editor: ", ...args);
1527
- }
1528
- };
1529
- const info = (...args) => {
1530
- if (process.env.NODE_ENV === "development") {
1531
- console.info("magic editor: ", ...args);
1532
- }
1533
- };
1534
- const warn = (...args) => {
1535
- if (process.env.NODE_ENV === "development") {
1536
- console.warn("magic editor: ", ...args);
1537
- }
1538
- };
1539
- const debug = (...args) => {
1540
- if (process.env.NODE_ENV === "development") {
1541
- console.debug("magic editor: ", ...args);
1542
- }
1543
- };
1544
- const error = (...args) => {
1545
- if (process.env.NODE_ENV === "development") {
1546
- console.error("magic editor: ", ...args);
1547
- }
1548
- };
1549
-
1550
- var ColumnLayout = /* @__PURE__ */ ((ColumnLayout2) => {
1551
- ColumnLayout2["LEFT"] = "left";
1552
- ColumnLayout2["CENTER"] = "center";
1553
- ColumnLayout2["RIGHT"] = "right";
1554
- return ColumnLayout2;
1555
- })(ColumnLayout || {});
1556
- var SideItemKey = /* @__PURE__ */ ((SideItemKey2) => {
1557
- SideItemKey2["COMPONENT_LIST"] = "component-list";
1558
- SideItemKey2["LAYER"] = "layer";
1559
- SideItemKey2["CODE_BLOCK"] = "code-block";
1560
- SideItemKey2["DATA_SOURCE"] = "data-source";
1561
- return SideItemKey2;
1562
- })(SideItemKey || {});
1563
- var LayerOffset = /* @__PURE__ */ ((LayerOffset2) => {
1564
- LayerOffset2["TOP"] = "top";
1565
- LayerOffset2["BOTTOM"] = "bottom";
1566
- return LayerOffset2;
1567
- })(LayerOffset || {});
1568
- var Layout = /* @__PURE__ */ ((Layout2) => {
1569
- Layout2["FLEX"] = "flex";
1570
- Layout2["FIXED"] = "fixed";
1571
- Layout2["RELATIVE"] = "relative";
1572
- Layout2["ABSOLUTE"] = "absolute";
1573
- return Layout2;
1574
- })(Layout || {});
1575
- var Keys = /* @__PURE__ */ ((Keys2) => {
1576
- Keys2["ESCAPE"] = "Space";
1577
- return Keys2;
1578
- })(Keys || {});
1579
- const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
1580
- const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
1581
- var CodeDeleteErrorType = /* @__PURE__ */ ((CodeDeleteErrorType2) => {
1582
- CodeDeleteErrorType2["UNDELETEABLE"] = "undeleteable";
1583
- CodeDeleteErrorType2["BIND"] = "bind";
1584
- return CodeDeleteErrorType2;
1585
- })(CodeDeleteErrorType || {});
1586
- const CODE_DRAFT_STORAGE_KEY = "magicCodeDraft";
1587
- var KeyBindingCommand = /* @__PURE__ */ ((KeyBindingCommand2) => {
1588
- KeyBindingCommand2["COPY_NODE"] = "tmagic-system-copy-node";
1589
- KeyBindingCommand2["PASTE_NODE"] = "tmagic-system-paste-node";
1590
- KeyBindingCommand2["DELETE_NODE"] = "tmagic-system-delete-node";
1591
- KeyBindingCommand2["CUT_NODE"] = "tmagic-system-cut-node";
1592
- KeyBindingCommand2["UNDO"] = "tmagic-system-undo";
1593
- KeyBindingCommand2["REDO"] = "tmagic-system-redo";
1594
- KeyBindingCommand2["ZOOM_IN"] = "tmagic-system-zoom-in";
1595
- KeyBindingCommand2["ZOOM_OUT"] = "tmagic-system-zoom-out";
1596
- KeyBindingCommand2["ZOOM_RESET"] = "tmagic-system-zoom-reset";
1597
- KeyBindingCommand2["ZOOM_FIT"] = "tmagic-system-zoom-fit";
1598
- KeyBindingCommand2["MOVE_UP_1"] = "tmagic-system-move-up-1";
1599
- KeyBindingCommand2["MOVE_DOWN_1"] = "tmagic-system-move-down-1";
1600
- KeyBindingCommand2["MOVE_LEFT_1"] = "tmagic-system-move-left-1";
1601
- KeyBindingCommand2["MOVE_RIGHT_1"] = "tmagic-system-move-right-1";
1602
- KeyBindingCommand2["MOVE_UP_10"] = "tmagic-system-move-up-10";
1603
- KeyBindingCommand2["MOVE_DOWN_10"] = "tmagic-system-move-down-10";
1604
- KeyBindingCommand2["MOVE_LEFT_10"] = "tmagic-system-move-left-10";
1605
- KeyBindingCommand2["MOVE_RIGHT_10"] = "tmagic-system-move-right-10";
1606
- KeyBindingCommand2["SWITCH_NODE"] = "tmagic-system-switch-node";
1607
- return KeyBindingCommand2;
1608
- })(KeyBindingCommand || {});
1609
- var DragType = /* @__PURE__ */ ((DragType2) => {
1610
- DragType2["COMPONENT_LIST"] = "component-list";
1611
- DragType2["LAYER_TREE"] = "layer-tree";
1612
- return DragType2;
1613
- })(DragType || {});
1614
- const UI_SELECT_MODE_EVENT_NAME = "ui-select";
1615
-
1616
- const COPY_STORAGE_KEY = "$MagicEditorCopyData";
1617
- const getPageList = (root) => {
1618
- if (!root)
1619
- return [];
1620
- if (!Array.isArray(root.items))
1621
- return [];
1622
- return root.items.filter((item) => isPage(item));
1623
- };
1624
- const getPageFragmentList = (root) => {
1625
- if (!root)
1626
- return [];
1627
- if (!Array.isArray(root.items))
1628
- return [];
1629
- return root.items.filter((item) => isPageFragment(item));
1630
- };
1631
- const getPageNameList = (pages) => pages.map((page) => page.name || "index");
1632
- const generatePageName = (pageNameList, type) => {
1633
- let pageLength = pageNameList.length;
1634
- if (!pageLength)
1635
- return `${type}_index`;
1636
- let pageName = `${type}_${pageLength}`;
1637
- while (pageNameList.includes(pageName)) {
1638
- pageLength += 1;
1639
- pageName = `${type}_${pageLength}`;
1640
- }
1641
- return pageName;
1642
- };
1643
- const generatePageNameByApp = (app, type) => generatePageName(getPageNameList(type === "page" ? getPageList(app) : getPageFragmentList(app)), type);
1644
- const isFixed = (node) => node.style?.position === "fixed";
1645
- const getNodeIndex = (id, parent) => {
1646
- const items = parent?.items || [];
1647
- return items.findIndex((item) => `${item.id}` === `${id}`);
1648
- };
1649
- const getRelativeStyle = (style = {}) => ({
1650
- ...style,
1651
- position: "relative",
1652
- top: 0,
1653
- left: 0
1654
- });
1655
- const getMiddleTop = (node, parentNode, stage) => {
1656
- let height = node.style?.height || 0;
1657
- if (!stage || typeof node.style?.top !== "undefined" || !parentNode.style)
1658
- return node.style?.top;
1659
- if (!isNumber(height)) {
1660
- height = 0;
1661
- }
1662
- const { height: parentHeight } = parentNode.style;
1663
- const { scrollTop = 0, wrapperHeight } = stage.mask;
1664
- const wrapperHeightDeal = calcValueByFontsize(stage.renderer.getDocument(), wrapperHeight);
1665
- const scrollTopDeal = calcValueByFontsize(stage.renderer.getDocument(), scrollTop);
1666
- if (isPage(parentNode)) {
1667
- return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
1668
- }
1669
- return (Math.min(parentHeight, wrapperHeightDeal) - height) / 2;
1670
- };
1671
- const getInitPositionStyle = (style = {}, layout) => {
1672
- if (layout === Layout.ABSOLUTE) {
1673
- const newStyle = {
1674
- ...style,
1675
- position: "absolute"
1676
- };
1677
- if (typeof newStyle.left === "undefined" && typeof newStyle.right === "undefined") {
1678
- newStyle.left = 0;
1679
- }
1680
- return newStyle;
1681
- }
1682
- if (layout === Layout.RELATIVE) {
1683
- return getRelativeStyle(style);
1684
- }
1685
- return style;
1686
- };
1687
- const setChildrenLayout = (node, layout) => {
1688
- node.items?.forEach((child) => {
1689
- setLayout(child, layout);
1690
- });
1691
- return node;
1692
- };
1693
- const setLayout = (node, layout) => {
1694
- if (isPop(node))
1695
- return;
1696
- const style = node.style || {};
1697
- if (style.position === "fixed")
1698
- return;
1699
- if (layout !== Layout.RELATIVE) {
1700
- style.position = "absolute";
1701
- } else {
1702
- node.style = getRelativeStyle(style);
1703
- node.style.right = "auto";
1704
- node.style.bottom = "auto";
1705
- }
1706
- return node;
1707
- };
1708
- const change2Fixed = (node, root) => {
1709
- const path = getNodePath(node.id, root.items);
1710
- const offset = {
1711
- left: 0,
1712
- top: 0
1713
- };
1714
- path.forEach((value) => {
1715
- offset.left = offset.left + globalThis.parseFloat(value.style?.left || 0);
1716
- offset.top = offset.top + globalThis.parseFloat(value.style?.top || 0);
1717
- });
1718
- return {
1719
- ...node.style || {},
1720
- ...offset
1721
- };
1722
- };
1723
- const Fixed2Other = async (node, root, getLayout) => {
1724
- const path = getNodePath(node.id, root.items);
1725
- const cur = path.pop();
1726
- const offset = {
1727
- left: cur?.style?.left || 0,
1728
- top: cur?.style?.top || 0,
1729
- right: "",
1730
- bottom: ""
1731
- };
1732
- path.forEach((value) => {
1733
- offset.left = offset.left - globalThis.parseFloat(value.style?.left || 0);
1734
- offset.top = offset.top - globalThis.parseFloat(value.style?.top || 0);
1735
- });
1736
- const style = node.style || {};
1737
- const parent = path.pop();
1738
- if (!parent) {
1739
- return getRelativeStyle(style);
1740
- }
1741
- const layout = await getLayout(parent);
1742
- if (layout !== Layout.RELATIVE) {
1743
- return {
1744
- ...style,
1745
- ...offset,
1746
- position: "absolute"
1747
- };
1748
- }
1749
- return getRelativeStyle(style);
1750
- };
1751
- const getGuideLineFromCache = (key) => {
1752
- if (!key)
1753
- return [];
1754
- const guideLineCacheData = globalThis.localStorage.getItem(key);
1755
- if (guideLineCacheData) {
1756
- try {
1757
- return JSON.parse(guideLineCacheData) || [];
1758
- } catch (e) {
1759
- console.error(e);
1760
- }
1761
- }
1762
- return [];
1763
- };
1764
- const fixNodeLeft = (config, parent, doc) => {
1765
- if (!doc || !config.style || !isNumber(config.style.left))
1766
- return config.style?.left;
1767
- const el = doc.getElementById(`${config.id}`);
1768
- const parentEl = doc.getElementById(`${parent.id}`);
1769
- const left = Number(config.style?.left) || 0;
1770
- if (el && parentEl) {
1771
- const calcParentOffsetWidth = calcValueByFontsize(doc, parentEl.offsetWidth);
1772
- const calcElOffsetWidth = calcValueByFontsize(doc, el.offsetWidth);
1773
- if (calcElOffsetWidth + left > calcParentOffsetWidth) {
1774
- return calcParentOffsetWidth - calcElOffsetWidth;
1775
- }
1776
- }
1777
- return config.style.left;
1778
- };
1779
- const fixNodePosition = (config, parent, stage) => {
1780
- if (config.style?.position !== "absolute") {
1781
- return config.style;
1782
- }
1783
- return {
1784
- ...config.style || {},
1785
- top: getMiddleTop(config, parent, stage),
1786
- left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document)
1787
- };
1788
- };
1789
- const serializeConfig = (config) => serialize(config, {
1790
- space: 2,
1791
- unsafe: true
1792
- }).replace(/"(\w+)":\s/g, "$1: ");
1793
- const traverseNode = (node, cb, parents = []) => {
1794
- cb(node, parents);
1795
- if (node.items?.length) {
1796
- parents.push(node);
1797
- node.items.forEach((item) => {
1798
- traverseNode(item, cb, [...parents]);
1799
- });
1800
- }
1801
- };
1802
-
1803
- class Dep extends BaseService {
1804
- watcher = new Watcher({ initialTargets: reactive({}) });
1805
- removeTargets(type = DepTargetType.DEFAULT) {
1806
- this.watcher.removeTargets(type);
1807
- this.emit("remove-target");
1808
- }
1809
- getTargets(type = DepTargetType.DEFAULT) {
1810
- return this.watcher.getTargets(type);
1811
- }
1812
- getTarget(id, type = DepTargetType.DEFAULT) {
1813
- return this.watcher.getTarget(id, type);
1814
- }
1815
- addTarget(target) {
1816
- this.watcher.addTarget(target);
1817
- this.emit("add-target", target);
1818
- }
1819
- removeTarget(id, type = DepTargetType.DEFAULT) {
1820
- this.watcher.removeTarget(id, type);
1821
- this.emit("remove-target");
1822
- }
1823
- clearTargets() {
1824
- this.watcher.clearTargets();
1825
- }
1826
- collect(nodes, deep = false, type) {
1827
- this.watcher.collect(nodes, deep, type);
1828
- this.emit("collected", nodes, deep);
1829
- }
1830
- clear(nodes) {
1831
- return this.watcher.clear(nodes);
1832
- }
1833
- clearByType(type, nodes) {
1834
- return this.watcher.clearByType(type, nodes);
1835
- }
1836
- hasTarget(id, type = DepTargetType.DEFAULT) {
1837
- return this.watcher.hasTarget(id, type);
1838
- }
1839
- hasSpecifiedTypeTarget(type = DepTargetType.DEFAULT) {
1840
- return this.watcher.hasSpecifiedTypeTarget(type);
1841
- }
1842
- }
1843
- const depService = new Dep();
1844
-
1845
- const canUsePluginMethods$5 = {
1846
- async: [
1847
- "setPropsConfig",
1848
- "getPropsConfig",
1849
- "setPropsValue",
1850
- "getPropsValue",
1851
- "fillConfig",
1852
- "getDefaultPropsValue"
1853
- ],
1854
- sync: ["createId", "setNewItemId"]
1855
- };
1856
- class Props extends BaseService {
1857
- state = reactive({
1858
- propsConfigMap: {},
1859
- propsValueMap: {},
1860
- relateIdMap: {}
1861
- });
1862
- constructor() {
1863
- super([
1864
- ...canUsePluginMethods$5.async.map((methodName) => ({ name: methodName, isAsync: true })),
1865
- ...canUsePluginMethods$5.sync.map((methodName) => ({ name: methodName, isAsync: false }))
1866
- ]);
1867
- }
1868
- setPropsConfigs(configs) {
1869
- Object.keys(configs).forEach((type) => {
1870
- this.setPropsConfig(toLine(type), configs[type]);
1871
- });
1872
- this.emit("props-configs-change");
1873
- }
1874
- async fillConfig(config, labelWidth) {
1875
- return fillConfig(config, typeof labelWidth !== "function" ? labelWidth : "80px");
1876
- }
1877
- async setPropsConfig(type, config) {
1878
- this.state.propsConfigMap[toLine(type)] = await this.fillConfig(Array.isArray(config) ? config : [config]);
1879
- }
1880
- /**
1881
- * 获取指点类型的组件属性表单配置
1882
- * @param type 组件类型
1883
- * @returns 组件属性表单配置
1884
- */
1885
- async getPropsConfig(type) {
1886
- if (type === "area") {
1887
- return await this.getPropsConfig("button");
1888
- }
1889
- return cloneDeep(this.state.propsConfigMap[toLine(type)] || await this.fillConfig([]));
1890
- }
1891
- setPropsValues(values) {
1892
- Object.keys(values).forEach((type) => {
1893
- this.setPropsValue(toLine(type), values[type]);
1894
- });
1895
- }
1896
- /**
1897
- * 为指点类型组件设置组件初始值
1898
- * @param type 组件类型
1899
- * @param value 组件初始值
1900
- */
1901
- async setPropsValue(type, value) {
1902
- this.state.propsValueMap[toLine(type)] = value;
1903
- }
1904
- /**
1905
- * 获取指定类型的组件初始值
1906
- * @param type 组件类型
1907
- * @returns 组件初始值
1908
- */
1909
- async getPropsValue(componentType, { inputEvent, ...defaultValue } = {}) {
1910
- const type = toLine(componentType);
1911
- if (type === "area") {
1912
- const value = await this.getPropsValue("button");
1913
- value.className = "action-area";
1914
- value.text = "";
1915
- if (value.style) {
1916
- value.style.backgroundColor = "rgba(255, 255, 255, 0)";
1917
- }
1918
- return value;
1919
- }
1920
- const id = this.createId(type);
1921
- const defaultPropsValue = this.getDefaultPropsValue(type);
1922
- const data = this.setNewItemId(
1923
- cloneDeep({
1924
- type,
1925
- ...defaultValue
1926
- })
1927
- );
1928
- return {
1929
- id,
1930
- ...defaultPropsValue,
1931
- ...mergeWith({}, cloneDeep(this.state.propsValueMap[type] || {}), data)
1932
- };
1933
- }
1934
- createId(type) {
1935
- return `${type}_${guid()}`;
1936
- }
1937
- /**
1938
- * 将组件与组件的子元素配置中的id都设置成一个新的ID
1939
- * 如果没有相同ID并且force为false则保持不变
1940
- * @param {Object} config 组件配置
1941
- * @param {Boolean} force 是否强制设置新的ID
1942
- */
1943
- /* eslint no-param-reassign: ["error", { "props": false }] */
1944
- setNewItemId(config, force = true) {
1945
- if (force || editorService.getNodeById(config.id)) {
1946
- const newId = this.createId(config.type || "component");
1947
- this.setRelateId(config.id, newId);
1948
- config.id = newId;
1949
- }
1950
- if (config.items && Array.isArray(config.items)) {
1951
- for (const item of config.items) {
1952
- this.setNewItemId(item);
1953
- }
1954
- }
1955
- return config;
1956
- }
1957
- /**
1958
- * 获取默认属性配置
1959
- * @param type 组件类型
1960
- * @returns Object
1961
- */
1962
- getDefaultPropsValue(type) {
1963
- return ["page", "container"].includes(type) ? {
1964
- type,
1965
- layout: "absolute",
1966
- style: {},
1967
- name: type,
1968
- items: []
1969
- } : {
1970
- type,
1971
- style: {},
1972
- name: type
1973
- };
1974
- }
1975
- resetState() {
1976
- this.state.propsConfigMap = {};
1977
- this.state.propsValueMap = {};
1978
- }
1979
- /**
1980
- * 替换关联ID
1981
- * @param originConfigs 原组件配置
1982
- * @param targetConfigs 待替换的组件配置
1983
- */
1984
- replaceRelateId(originConfigs, targetConfigs) {
1985
- const relateIdMap = this.getRelateIdMap();
1986
- if (Object.keys(relateIdMap).length === 0)
1987
- return;
1988
- const target = depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY);
1989
- if (!target)
1990
- return;
1991
- originConfigs.forEach((config) => {
1992
- const newId = relateIdMap[config.id];
1993
- const targetConfig = targetConfigs.find((targetConfig2) => targetConfig2.id === newId);
1994
- if (!targetConfig)
1995
- return;
1996
- target.deps[config.id]?.keys?.forEach((fullKey) => {
1997
- const relateOriginId = getValueByKeyPath(fullKey, config);
1998
- const relateTargetId = relateIdMap[relateOriginId];
1999
- if (!relateTargetId)
2000
- return;
2001
- setValueByKeyPath(fullKey, relateTargetId, targetConfig);
2002
- });
2003
- });
2004
- }
2005
- /**
2006
- * 清除setNewItemId前后映射关系
2007
- */
2008
- clearRelateId() {
2009
- this.state.relateIdMap = {};
2010
- }
2011
- destroy() {
2012
- this.resetState();
2013
- this.removeAllListeners();
2014
- this.removeAllPlugins();
2015
- }
2016
- usePlugin(options) {
2017
- super.usePlugin(options);
2018
- }
2019
- /**
2020
- * 获取setNewItemId前后映射关系
2021
- * @param oldId 原组件ID
2022
- * @returns 新旧ID映射
2023
- */
2024
- getRelateIdMap() {
2025
- return this.state.relateIdMap;
2026
- }
2027
- /**
2028
- * 记录setNewItemId前后映射关系
2029
- * @param oldId 原组件ID
2030
- * @param newId 分配的新ID
2031
- */
2032
- setRelateId(oldId, newId) {
2033
- this.state.relateIdMap[oldId] = newId;
2034
- }
2035
- }
2036
- const propsService = new Props();
869
+ const propsService = new Props();
2037
870
 
2038
871
  class UndoRedo {
2039
872
  elementList;
@@ -2159,137 +992,462 @@ class History extends BaseService {
2159
992
  return null;
2160
993
  return this.state.pageSteps[this.state.pageId];
2161
994
  }
2162
- setCanUndoRedo() {
2163
- const undoRedo = this.getUndoRedo();
2164
- this.state.canRedo = undoRedo?.canRedo() || false;
2165
- this.state.canUndo = undoRedo?.canUndo() || false;
995
+ setCanUndoRedo() {
996
+ const undoRedo = this.getUndoRedo();
997
+ this.state.canRedo = undoRedo?.canRedo() || false;
998
+ this.state.canUndo = undoRedo?.canUndo() || false;
999
+ }
1000
+ }
1001
+ const historyService = new History();
1002
+
1003
+ var Protocol = /* @__PURE__ */ ((Protocol2) => {
1004
+ Protocol2["OBJECT"] = "object";
1005
+ Protocol2["JSON"] = "json";
1006
+ Protocol2["STRING"] = "string";
1007
+ Protocol2["NUMBER"] = "number";
1008
+ Protocol2["BOOLEAN"] = "boolean";
1009
+ return Protocol2;
1010
+ })(Protocol || {});
1011
+ const canUsePluginMethods$5 = {
1012
+ async: [],
1013
+ sync: ["getStorage", "getNamespace", "clear", "getItem", "removeItem", "setItem"]
1014
+ };
1015
+ class WebStorage extends BaseService {
1016
+ storage = globalThis.localStorage;
1017
+ namespace = "tmagic";
1018
+ constructor() {
1019
+ super(canUsePluginMethods$5.sync.map((methodName) => ({ name: methodName, isAsync: false })));
1020
+ }
1021
+ /**
1022
+ * 获取数据存储对象,可以通过
1023
+ * const storageService = new StorageService();
1024
+ * storageService.usePlugin({
1025
+ * // 替换存储对象为 sessionStorage
1026
+ * async afterGetStorage(): Promise<Storage> {
1027
+ * return window.sessionStorage;
1028
+ * },
1029
+ * });
1030
+ */
1031
+ getStorage() {
1032
+ return this.storage;
1033
+ }
1034
+ getNamespace() {
1035
+ return this.namespace;
1036
+ }
1037
+ /**
1038
+ * 清理,支持storageService.usePlugin
1039
+ */
1040
+ clear() {
1041
+ const storage = this.getStorage();
1042
+ storage.clear();
1043
+ }
1044
+ /**
1045
+ * 获取存储项,支持storageService.usePlugin
1046
+ */
1047
+ getItem(key, options = {}) {
1048
+ const storage = this.getStorage();
1049
+ const namespace = this.getNamespace();
1050
+ const { protocol = options.protocol, item } = this.getValueAndProtocol(
1051
+ storage.getItem(`${options.namespace || namespace}:${key}`)
1052
+ );
1053
+ if (item === null)
1054
+ return null;
1055
+ switch (protocol) {
1056
+ case "object" /* OBJECT */:
1057
+ return getConfig("parseDSL")(`(${item})`);
1058
+ case "json" /* JSON */:
1059
+ return JSON.parse(item);
1060
+ case "number" /* NUMBER */:
1061
+ return Number(item);
1062
+ case "boolean" /* BOOLEAN */:
1063
+ return Boolean(item);
1064
+ default:
1065
+ return item;
1066
+ }
1067
+ }
1068
+ /**
1069
+ * 获取指定索引位置的key
1070
+ */
1071
+ key(index) {
1072
+ const storage = this.getStorage();
1073
+ return storage.key(index);
1074
+ }
1075
+ /**
1076
+ * 移除存储项,支持storageService.usePlugin
1077
+ */
1078
+ removeItem(key, options = {}) {
1079
+ const storage = this.getStorage();
1080
+ const namespace = this.getNamespace();
1081
+ storage.removeItem(`${options.namespace || namespace}:${key}`);
1082
+ }
1083
+ /**
1084
+ * 设置存储项,支持storageService.usePlugin
1085
+ */
1086
+ setItem(key, value, options = {}) {
1087
+ const storage = this.getStorage();
1088
+ const namespace = this.getNamespace();
1089
+ let item = value;
1090
+ const protocol = options.protocol ? `${options.protocol}:` : "";
1091
+ if (typeof value === "string" /* STRING */ || typeof value === "number" /* NUMBER */) {
1092
+ item = `${protocol}${value}`;
1093
+ } else {
1094
+ item = `${protocol}${serialize(value)}`;
1095
+ }
1096
+ storage.setItem(`${options.namespace || namespace}:${key}`, item);
1097
+ }
1098
+ destroy() {
1099
+ this.removeAllListeners();
1100
+ this.removeAllPlugins();
1101
+ }
1102
+ usePlugin(options) {
1103
+ super.usePlugin(options);
1104
+ }
1105
+ getValueAndProtocol(value) {
1106
+ let protocol = "";
1107
+ if (value === null) {
1108
+ return {
1109
+ item: value,
1110
+ protocol
1111
+ };
1112
+ }
1113
+ const item = value.replace(new RegExp(`^(${Object.values(Protocol).join("|")})(:)(.+)`), (_$0, $1, _$2, $3) => {
1114
+ protocol = $1;
1115
+ return $3;
1116
+ });
1117
+ return {
1118
+ protocol,
1119
+ item
1120
+ };
1121
+ }
1122
+ }
1123
+ const storageService = new WebStorage();
1124
+
1125
+ var ColumnLayout = /* @__PURE__ */ ((ColumnLayout2) => {
1126
+ ColumnLayout2["LEFT"] = "left";
1127
+ ColumnLayout2["CENTER"] = "center";
1128
+ ColumnLayout2["RIGHT"] = "right";
1129
+ return ColumnLayout2;
1130
+ })(ColumnLayout || {});
1131
+ var SideItemKey = /* @__PURE__ */ ((SideItemKey2) => {
1132
+ SideItemKey2["COMPONENT_LIST"] = "component-list";
1133
+ SideItemKey2["LAYER"] = "layer";
1134
+ SideItemKey2["CODE_BLOCK"] = "code-block";
1135
+ SideItemKey2["DATA_SOURCE"] = "data-source";
1136
+ return SideItemKey2;
1137
+ })(SideItemKey || {});
1138
+ var LayerOffset = /* @__PURE__ */ ((LayerOffset2) => {
1139
+ LayerOffset2["TOP"] = "top";
1140
+ LayerOffset2["BOTTOM"] = "bottom";
1141
+ return LayerOffset2;
1142
+ })(LayerOffset || {});
1143
+ var Layout = /* @__PURE__ */ ((Layout2) => {
1144
+ Layout2["FLEX"] = "flex";
1145
+ Layout2["FIXED"] = "fixed";
1146
+ Layout2["RELATIVE"] = "relative";
1147
+ Layout2["ABSOLUTE"] = "absolute";
1148
+ return Layout2;
1149
+ })(Layout || {});
1150
+ var Keys = /* @__PURE__ */ ((Keys2) => {
1151
+ Keys2["ESCAPE"] = "Space";
1152
+ return Keys2;
1153
+ })(Keys || {});
1154
+ const H_GUIDE_LINE_STORAGE_KEY = "$MagicStageHorizontalGuidelinesData";
1155
+ const V_GUIDE_LINE_STORAGE_KEY = "$MagicStageVerticalGuidelinesData";
1156
+ var CodeDeleteErrorType = /* @__PURE__ */ ((CodeDeleteErrorType2) => {
1157
+ CodeDeleteErrorType2["UNDELETEABLE"] = "undeleteable";
1158
+ CodeDeleteErrorType2["BIND"] = "bind";
1159
+ return CodeDeleteErrorType2;
1160
+ })(CodeDeleteErrorType || {});
1161
+ const CODE_DRAFT_STORAGE_KEY = "magicCodeDraft";
1162
+ var KeyBindingCommand = /* @__PURE__ */ ((KeyBindingCommand2) => {
1163
+ KeyBindingCommand2["COPY_NODE"] = "tmagic-system-copy-node";
1164
+ KeyBindingCommand2["PASTE_NODE"] = "tmagic-system-paste-node";
1165
+ KeyBindingCommand2["DELETE_NODE"] = "tmagic-system-delete-node";
1166
+ KeyBindingCommand2["CUT_NODE"] = "tmagic-system-cut-node";
1167
+ KeyBindingCommand2["UNDO"] = "tmagic-system-undo";
1168
+ KeyBindingCommand2["REDO"] = "tmagic-system-redo";
1169
+ KeyBindingCommand2["ZOOM_IN"] = "tmagic-system-zoom-in";
1170
+ KeyBindingCommand2["ZOOM_OUT"] = "tmagic-system-zoom-out";
1171
+ KeyBindingCommand2["ZOOM_RESET"] = "tmagic-system-zoom-reset";
1172
+ KeyBindingCommand2["ZOOM_FIT"] = "tmagic-system-zoom-fit";
1173
+ KeyBindingCommand2["MOVE_UP_1"] = "tmagic-system-move-up-1";
1174
+ KeyBindingCommand2["MOVE_DOWN_1"] = "tmagic-system-move-down-1";
1175
+ KeyBindingCommand2["MOVE_LEFT_1"] = "tmagic-system-move-left-1";
1176
+ KeyBindingCommand2["MOVE_RIGHT_1"] = "tmagic-system-move-right-1";
1177
+ KeyBindingCommand2["MOVE_UP_10"] = "tmagic-system-move-up-10";
1178
+ KeyBindingCommand2["MOVE_DOWN_10"] = "tmagic-system-move-down-10";
1179
+ KeyBindingCommand2["MOVE_LEFT_10"] = "tmagic-system-move-left-10";
1180
+ KeyBindingCommand2["MOVE_RIGHT_10"] = "tmagic-system-move-right-10";
1181
+ KeyBindingCommand2["SWITCH_NODE"] = "tmagic-system-switch-node";
1182
+ return KeyBindingCommand2;
1183
+ })(KeyBindingCommand || {});
1184
+ var DragType = /* @__PURE__ */ ((DragType2) => {
1185
+ DragType2["COMPONENT_LIST"] = "component-list";
1186
+ DragType2["LAYER_TREE"] = "layer-tree";
1187
+ return DragType2;
1188
+ })(DragType || {});
1189
+ const UI_SELECT_MODE_EVENT_NAME = "ui-select";
1190
+
1191
+ const COPY_STORAGE_KEY = "$MagicEditorCopyData";
1192
+ const COPY_CODE_STORAGE_KEY = "$MagicEditorCopyCode";
1193
+ const COPY_DS_STORAGE_KEY = "$MagicEditorCopyDataSource";
1194
+ const getPageList = (root) => {
1195
+ if (!root)
1196
+ return [];
1197
+ if (!Array.isArray(root.items))
1198
+ return [];
1199
+ return root.items.filter((item) => isPage(item));
1200
+ };
1201
+ const getPageFragmentList = (root) => {
1202
+ if (!root)
1203
+ return [];
1204
+ if (!Array.isArray(root.items))
1205
+ return [];
1206
+ return root.items.filter((item) => isPageFragment(item));
1207
+ };
1208
+ const getPageNameList = (pages) => pages.map((page) => page.name || "index");
1209
+ const generatePageName = (pageNameList, type) => {
1210
+ let pageLength = pageNameList.length;
1211
+ if (!pageLength)
1212
+ return `${type}_index`;
1213
+ let pageName = `${type}_${pageLength}`;
1214
+ while (pageNameList.includes(pageName)) {
1215
+ pageLength += 1;
1216
+ pageName = `${type}_${pageLength}`;
1217
+ }
1218
+ return pageName;
1219
+ };
1220
+ const generatePageNameByApp = (app, type) => generatePageName(getPageNameList(type === "page" ? getPageList(app) : getPageFragmentList(app)), type);
1221
+ const isFixed = (node) => node.style?.position === "fixed";
1222
+ const getNodeIndex = (id, parent) => {
1223
+ const items = parent?.items || [];
1224
+ return items.findIndex((item) => `${item.id}` === `${id}`);
1225
+ };
1226
+ const getRelativeStyle = (style = {}) => ({
1227
+ ...style,
1228
+ position: "relative",
1229
+ top: 0,
1230
+ left: 0
1231
+ });
1232
+ const getMiddleTop = (node, parentNode, stage) => {
1233
+ let height = node.style?.height || 0;
1234
+ if (!stage || typeof node.style?.top !== "undefined" || !parentNode.style)
1235
+ return node.style?.top;
1236
+ if (!isNumber(height)) {
1237
+ height = 0;
1238
+ }
1239
+ const { height: parentHeight } = parentNode.style;
1240
+ const { scrollTop = 0, wrapperHeight } = stage.mask;
1241
+ const wrapperHeightDeal = calcValueByFontsize(stage.renderer.getDocument(), wrapperHeight);
1242
+ const scrollTopDeal = calcValueByFontsize(stage.renderer.getDocument(), scrollTop);
1243
+ if (isPage(parentNode)) {
1244
+ return (wrapperHeightDeal - height) / 2 + scrollTopDeal;
2166
1245
  }
2167
- }
2168
- const historyService = new History();
2169
-
2170
- var Protocol = /* @__PURE__ */ ((Protocol2) => {
2171
- Protocol2["OBJECT"] = "object";
2172
- Protocol2["JSON"] = "json";
2173
- Protocol2["STRING"] = "string";
2174
- Protocol2["NUMBER"] = "number";
2175
- Protocol2["BOOLEAN"] = "boolean";
2176
- return Protocol2;
2177
- })(Protocol || {});
2178
- const canUsePluginMethods$4 = {
2179
- async: [],
2180
- sync: ["getStorage", "getNamespace", "clear", "getItem", "removeItem", "setItem"]
1246
+ return (Math.min(parentHeight, wrapperHeightDeal) - height) / 2;
2181
1247
  };
2182
- class WebStorage extends BaseService {
2183
- storage = globalThis.localStorage;
2184
- namespace = "tmagic";
2185
- constructor() {
2186
- super(canUsePluginMethods$4.sync.map((methodName) => ({ name: methodName, isAsync: false })));
2187
- }
2188
- /**
2189
- * 获取数据存储对象,可以通过
2190
- * const storageService = new StorageService();
2191
- * storageService.usePlugin({
2192
- * // 替换存储对象为 sessionStorage
2193
- * async afterGetStorage(): Promise<Storage> {
2194
- * return window.sessionStorage;
2195
- * },
2196
- * });
2197
- */
2198
- getStorage() {
2199
- return this.storage;
1248
+ const getInitPositionStyle = (style = {}, layout) => {
1249
+ if (layout === Layout.ABSOLUTE) {
1250
+ const newStyle = {
1251
+ ...style,
1252
+ position: "absolute"
1253
+ };
1254
+ if (typeof newStyle.left === "undefined" && typeof newStyle.right === "undefined") {
1255
+ newStyle.left = 0;
1256
+ }
1257
+ return newStyle;
2200
1258
  }
2201
- getNamespace() {
2202
- return this.namespace;
1259
+ if (layout === Layout.RELATIVE) {
1260
+ return getRelativeStyle(style);
2203
1261
  }
2204
- /**
2205
- * 清理,支持storageService.usePlugin
2206
- */
2207
- clear() {
2208
- const storage = this.getStorage();
2209
- storage.clear();
1262
+ return style;
1263
+ };
1264
+ const setChildrenLayout = (node, layout) => {
1265
+ node.items?.forEach((child) => {
1266
+ setLayout(child, layout);
1267
+ });
1268
+ return node;
1269
+ };
1270
+ const setLayout = (node, layout) => {
1271
+ if (isPop(node))
1272
+ return;
1273
+ const style = node.style || {};
1274
+ if (style.position === "fixed")
1275
+ return;
1276
+ if (layout !== Layout.RELATIVE) {
1277
+ style.position = "absolute";
1278
+ } else {
1279
+ node.style = getRelativeStyle(style);
1280
+ node.style.right = "auto";
1281
+ node.style.bottom = "auto";
2210
1282
  }
2211
- /**
2212
- * 获取存储项,支持storageService.usePlugin
2213
- */
2214
- getItem(key, options = {}) {
2215
- const storage = this.getStorage();
2216
- const namespace = this.getNamespace();
2217
- const { protocol = options.protocol, item } = this.getValueAndProtocol(
2218
- storage.getItem(`${options.namespace || namespace}:${key}`)
2219
- );
2220
- if (item === null)
2221
- return null;
2222
- switch (protocol) {
2223
- case "object" /* OBJECT */:
2224
- return getConfig("parseDSL")(`(${item})`);
2225
- case "json" /* JSON */:
2226
- return JSON.parse(item);
2227
- case "number" /* NUMBER */:
2228
- return Number(item);
2229
- case "boolean" /* BOOLEAN */:
2230
- return Boolean(item);
2231
- default:
2232
- return item;
2233
- }
1283
+ return node;
1284
+ };
1285
+ const change2Fixed = (node, root) => {
1286
+ const path = getNodePath(node.id, root.items);
1287
+ const offset = {
1288
+ left: 0,
1289
+ top: 0
1290
+ };
1291
+ path.forEach((value) => {
1292
+ offset.left = offset.left + globalThis.parseFloat(value.style?.left || 0);
1293
+ offset.top = offset.top + globalThis.parseFloat(value.style?.top || 0);
1294
+ });
1295
+ return {
1296
+ ...node.style || {},
1297
+ ...offset
1298
+ };
1299
+ };
1300
+ const Fixed2Other = async (node, root, getLayout) => {
1301
+ const path = getNodePath(node.id, root.items);
1302
+ const cur = path.pop();
1303
+ const offset = {
1304
+ left: cur?.style?.left || 0,
1305
+ top: cur?.style?.top || 0,
1306
+ right: "",
1307
+ bottom: ""
1308
+ };
1309
+ path.forEach((value) => {
1310
+ offset.left = offset.left - globalThis.parseFloat(value.style?.left || 0);
1311
+ offset.top = offset.top - globalThis.parseFloat(value.style?.top || 0);
1312
+ });
1313
+ const style = node.style || {};
1314
+ const parent = path.pop();
1315
+ if (!parent) {
1316
+ return getRelativeStyle(style);
2234
1317
  }
2235
- /**
2236
- * 获取指定索引位置的key
2237
- */
2238
- key(index) {
2239
- const storage = this.getStorage();
2240
- return storage.key(index);
1318
+ const layout = await getLayout(parent);
1319
+ if (layout !== Layout.RELATIVE) {
1320
+ return {
1321
+ ...style,
1322
+ ...offset,
1323
+ position: "absolute"
1324
+ };
2241
1325
  }
2242
- /**
2243
- * 移除存储项,支持storageService.usePlugin
2244
- */
2245
- removeItem(key, options = {}) {
2246
- const storage = this.getStorage();
2247
- const namespace = this.getNamespace();
2248
- storage.removeItem(`${options.namespace || namespace}:${key}`);
1326
+ return getRelativeStyle(style);
1327
+ };
1328
+ const getGuideLineFromCache = (key) => {
1329
+ if (!key)
1330
+ return [];
1331
+ const guideLineCacheData = globalThis.localStorage.getItem(key);
1332
+ if (guideLineCacheData) {
1333
+ try {
1334
+ return JSON.parse(guideLineCacheData) || [];
1335
+ } catch (e) {
1336
+ console.error(e);
1337
+ }
2249
1338
  }
2250
- /**
2251
- * 设置存储项,支持storageService.usePlugin
2252
- */
2253
- setItem(key, value, options = {}) {
2254
- const storage = this.getStorage();
2255
- const namespace = this.getNamespace();
2256
- let item = value;
2257
- const protocol = options.protocol ? `${options.protocol}:` : "";
2258
- if (typeof value === "string" /* STRING */ || typeof value === "number" /* NUMBER */) {
2259
- item = `${protocol}${value}`;
2260
- } else {
2261
- item = `${protocol}${serialize(value)}`;
1339
+ return [];
1340
+ };
1341
+ const fixNodeLeft = (config, parent, doc) => {
1342
+ if (!doc || !config.style || !isNumber(config.style.left))
1343
+ return config.style?.left;
1344
+ const el = doc.getElementById(`${config.id}`);
1345
+ const parentEl = doc.getElementById(`${parent.id}`);
1346
+ const left = Number(config.style?.left) || 0;
1347
+ if (el && parentEl) {
1348
+ const calcParentOffsetWidth = calcValueByFontsize(doc, parentEl.offsetWidth);
1349
+ const calcElOffsetWidth = calcValueByFontsize(doc, el.offsetWidth);
1350
+ if (calcElOffsetWidth + left > calcParentOffsetWidth) {
1351
+ return calcParentOffsetWidth - calcElOffsetWidth;
2262
1352
  }
2263
- storage.setItem(`${options.namespace || namespace}:${key}`, item);
2264
1353
  }
2265
- destroy() {
2266
- this.removeAllListeners();
2267
- this.removeAllPlugins();
1354
+ return config.style.left;
1355
+ };
1356
+ const fixNodePosition = (config, parent, stage) => {
1357
+ if (config.style?.position !== "absolute") {
1358
+ return config.style;
2268
1359
  }
2269
- usePlugin(options) {
2270
- super.usePlugin(options);
1360
+ return {
1361
+ ...config.style || {},
1362
+ top: getMiddleTop(config, parent, stage),
1363
+ left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document)
1364
+ };
1365
+ };
1366
+ const serializeConfig = (config) => serialize(config, {
1367
+ space: 2,
1368
+ unsafe: true
1369
+ }).replace(/"(\w+)":\s/g, "$1: ");
1370
+ const traverseNode = (node, cb, parents = []) => {
1371
+ cb(node, parents);
1372
+ if (node.items?.length) {
1373
+ parents.push(node);
1374
+ node.items.forEach((item) => {
1375
+ traverseNode(item, cb, [...parents]);
1376
+ });
2271
1377
  }
2272
- getValueAndProtocol(value) {
2273
- let protocol = "";
2274
- if (value === null) {
2275
- return {
2276
- item: value,
2277
- protocol
1378
+ };
1379
+
1380
+ const beforePaste = (position, config, doc) => {
1381
+ if (!config[0]?.style)
1382
+ return config;
1383
+ const curNode = editorService.get("node");
1384
+ const { left: referenceLeft, top: referenceTop } = config[0].style;
1385
+ const pasteConfigs = config.map((configItem) => {
1386
+ const { offsetX = 0, offsetY = 0, ...positionClone } = position;
1387
+ let pastePosition = positionClone;
1388
+ if (!isEmpty(pastePosition) && curNode?.items) {
1389
+ pastePosition = getPositionInContainer(pastePosition, curNode.id, doc);
1390
+ }
1391
+ if (pastePosition.left && configItem.style?.left) {
1392
+ pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
1393
+ }
1394
+ if (pastePosition.top && configItem.style?.top) {
1395
+ pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
1396
+ }
1397
+ const pasteConfig = propsService.setNewItemId(configItem, false);
1398
+ if (pasteConfig.style) {
1399
+ const { left, top } = pasteConfig.style;
1400
+ if (typeof left === "number" || !!left && !isNaN(Number(left))) {
1401
+ pasteConfig.style.left = Number(left) + offsetX;
1402
+ }
1403
+ if (typeof top === "number" || !!top && !isNaN(Number(top))) {
1404
+ pasteConfig.style.top = Number(top) + offsetY;
1405
+ }
1406
+ pasteConfig.style = {
1407
+ ...pasteConfig.style,
1408
+ ...pastePosition
2278
1409
  };
2279
1410
  }
2280
- const item = value.replace(new RegExp(`^(${Object.values(Protocol).join("|")})(:)(.+)`), (_$0, $1, _$2, $3) => {
2281
- protocol = $1;
2282
- return $3;
2283
- });
2284
- return {
2285
- protocol,
2286
- item
2287
- };
1411
+ const root = editorService.get("root");
1412
+ if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
1413
+ pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
1414
+ }
1415
+ return pasteConfig;
1416
+ });
1417
+ return pasteConfigs;
1418
+ };
1419
+ const getPositionInContainer = (position = {}, id, doc) => {
1420
+ let { left = 0, top = 0 } = position;
1421
+ const parentEl = editorService.get("stage")?.renderer?.contentWindow?.document.getElementById(`${id}`);
1422
+ const parentElRect = parentEl?.getBoundingClientRect();
1423
+ left = left - calcValueByFontsize(doc, parentElRect?.left || 0);
1424
+ top = top - calcValueByFontsize(doc, parentElRect?.top || 0);
1425
+ return {
1426
+ left,
1427
+ top
1428
+ };
1429
+ };
1430
+ const getAddParent = (node) => {
1431
+ const curNode = editorService.get("node");
1432
+ let parentNode;
1433
+ if (isPage(node)) {
1434
+ parentNode = editorService.get("root");
1435
+ } else if (curNode?.items) {
1436
+ parentNode = curNode;
1437
+ } else if (curNode?.id) {
1438
+ parentNode = editorService.getParentById(curNode.id, false);
2288
1439
  }
2289
- }
2290
- const storageService = new WebStorage();
1440
+ return parentNode;
1441
+ };
1442
+ const getDefaultConfig = async (addNode, parentNode) => {
1443
+ const { type, inputEvent, ...config } = addNode;
1444
+ const layout = await editorService.getLayout(toRaw(parentNode), addNode);
1445
+ const newNode = { ...toRaw(await propsService.getPropsValue(type, config)) };
1446
+ newNode.style = getInitPositionStyle(newNode.style, layout);
1447
+ return newNode;
1448
+ };
2291
1449
 
2292
- const canUsePluginMethods$3 = {
1450
+ const canUsePluginMethods$4 = {
2293
1451
  async: [
2294
1452
  "getLayout",
2295
1453
  "highlight",
@@ -2334,7 +1492,7 @@ class Editor extends BaseService {
2334
1492
  isHistoryStateChange = false;
2335
1493
  constructor() {
2336
1494
  super(
2337
- canUsePluginMethods$3.async.map((methodName) => ({ name: methodName, isAsync: true })),
1495
+ canUsePluginMethods$4.async.map((methodName) => ({ name: methodName, isAsync: true })),
2338
1496
  // 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
2339
1497
  ["select", "update", "moveLayer"]
2340
1498
  );
@@ -2773,448 +1931,1311 @@ class Editor extends BaseService {
2773
1931
  this.pushHistoryState();
2774
1932
  }
2775
1933
  /**
2776
- * 将组件节点配置存储到localStorage中
2777
- * @param config 组件节点配置
2778
- * @returns
1934
+ * 将组件节点配置存储到localStorage中
1935
+ * @param config 组件节点配置
1936
+ * @returns
1937
+ */
1938
+ copy(config) {
1939
+ storageService.setItem(COPY_STORAGE_KEY, Array.isArray(config) ? config : [config], {
1940
+ protocol: Protocol.OBJECT
1941
+ });
1942
+ }
1943
+ /**
1944
+ * 复制时会带上组件关联的依赖
1945
+ * @param config 组件节点配置
1946
+ * @returns
1947
+ */
1948
+ copyWithRelated(config, collectorOptions) {
1949
+ const copyNodes = Array.isArray(config) ? config : [config];
1950
+ if (collectorOptions && typeof collectorOptions.isTarget === "function") {
1951
+ const customTarget = new Target({
1952
+ ...collectorOptions
1953
+ });
1954
+ const coperWatcher = new Watcher();
1955
+ coperWatcher.addTarget(customTarget);
1956
+ coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
1957
+ Object.keys(customTarget.deps).forEach((nodeId) => {
1958
+ const node = this.getNodeById(nodeId);
1959
+ if (!node)
1960
+ return;
1961
+ customTarget.deps[nodeId].keys.forEach((key) => {
1962
+ const relateNodeId = get(node, key);
1963
+ const isExist = copyNodes.find((node2) => node2.id === relateNodeId);
1964
+ if (!isExist) {
1965
+ const relateNode = this.getNodeById(relateNodeId);
1966
+ if (relateNode) {
1967
+ copyNodes.push(relateNode);
1968
+ }
1969
+ }
1970
+ });
1971
+ });
1972
+ }
1973
+ storageService.setItem(COPY_STORAGE_KEY, copyNodes, {
1974
+ protocol: Protocol.OBJECT
1975
+ });
1976
+ }
1977
+ /**
1978
+ * 从localStorage中获取节点,然后添加到当前容器中
1979
+ * @param position 粘贴的坐标
1980
+ * @returns 添加后的组件节点配置
1981
+ */
1982
+ async paste(position = {}, collectorOptions) {
1983
+ const config = storageService.getItem(COPY_STORAGE_KEY);
1984
+ if (!Array.isArray(config))
1985
+ return;
1986
+ const node = this.get("node");
1987
+ let parent = null;
1988
+ if (config.length === 1 && config[0].id === node?.id) {
1989
+ parent = this.get("parent");
1990
+ if (parent?.type === NodeType.ROOT) {
1991
+ parent = this.get("page");
1992
+ }
1993
+ }
1994
+ const pasteConfigs = await this.doPaste(config, position);
1995
+ if (collectorOptions && typeof collectorOptions.isTarget === "function") {
1996
+ propsService.replaceRelateId(config, pasteConfigs, collectorOptions);
1997
+ }
1998
+ return this.add(pasteConfigs, parent);
1999
+ }
2000
+ async doPaste(config, position = {}) {
2001
+ propsService.clearRelateId();
2002
+ const doc = this.get("stage")?.renderer.contentWindow?.document;
2003
+ const pasteConfigs = beforePaste(position, cloneDeep(config), doc);
2004
+ return pasteConfigs;
2005
+ }
2006
+ async doAlignCenter(config) {
2007
+ const parent = this.getParentById(config.id);
2008
+ if (!parent)
2009
+ throw new Error("找不到父节点");
2010
+ const node = cloneDeep(toRaw(config));
2011
+ const layout = await this.getLayout(parent, node);
2012
+ if (layout === Layout.RELATIVE) {
2013
+ return config;
2014
+ }
2015
+ if (!node.style)
2016
+ return config;
2017
+ const stage = this.get("stage");
2018
+ const doc = stage?.renderer.contentWindow?.document;
2019
+ if (doc) {
2020
+ const el = doc.getElementById(`${node.id}`);
2021
+ const parentEl = layout === Layout.FIXED ? doc.body : el?.offsetParent;
2022
+ if (parentEl && el) {
2023
+ node.style.left = calcValueByFontsize(doc, (parentEl.clientWidth - el.clientWidth) / 2);
2024
+ node.style.right = "";
2025
+ }
2026
+ } else if (parent.style && isNumber(parent.style?.width) && isNumber(node.style?.width)) {
2027
+ node.style.left = (parent.style.width - node.style.width) / 2;
2028
+ node.style.right = "";
2029
+ }
2030
+ return node;
2031
+ }
2032
+ /**
2033
+ * 将指点节点设置居中
2034
+ * @param config 组件节点配置
2035
+ * @returns 当前组件节点配置
2036
+ */
2037
+ async alignCenter(config) {
2038
+ const nodes = Array.isArray(config) ? config : [config];
2039
+ const stage = this.get("stage");
2040
+ const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
2041
+ const newNode = await this.update(newNodes);
2042
+ if (newNodes.length > 1) {
2043
+ await stage?.multiSelect(newNodes.map((node) => node.id));
2044
+ } else {
2045
+ await stage?.select(newNodes[0].id);
2046
+ }
2047
+ return newNode;
2048
+ }
2049
+ /**
2050
+ * 移动当前选中节点位置
2051
+ * @param offset 偏移量
2052
+ */
2053
+ async moveLayer(offset) {
2054
+ const root = this.get("root");
2055
+ if (!root)
2056
+ throw new Error("root为空");
2057
+ const parent = this.get("parent");
2058
+ if (!parent)
2059
+ throw new Error("父节点为空");
2060
+ const node = this.get("node");
2061
+ if (!node)
2062
+ throw new Error("当前节点为空");
2063
+ const brothers = parent.items || [];
2064
+ const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
2065
+ const layout = await this.getLayout(parent, node);
2066
+ const isRelative = layout === Layout.RELATIVE;
2067
+ let offsetIndex;
2068
+ if (offset === LayerOffset.TOP) {
2069
+ offsetIndex = isRelative ? 0 : brothers.length;
2070
+ } else if (offset === LayerOffset.BOTTOM) {
2071
+ offsetIndex = isRelative ? brothers.length : 0;
2072
+ } else {
2073
+ offsetIndex = index + (isRelative ? -offset : offset);
2074
+ }
2075
+ if (offsetIndex > 0 && offsetIndex > brothers.length || offsetIndex < 0) {
2076
+ return;
2077
+ }
2078
+ brothers.splice(index, 1);
2079
+ brothers.splice(offsetIndex, 0, node);
2080
+ const grandparent = this.getParentById(parent.id);
2081
+ this.get("stage")?.update({
2082
+ config: cloneDeep(toRaw(parent)),
2083
+ parentId: grandparent?.id,
2084
+ root: cloneDeep(root)
2085
+ });
2086
+ this.addModifiedNodeId(parent.id);
2087
+ this.pushHistoryState();
2088
+ this.emit("move-layer", offset);
2089
+ }
2090
+ /**
2091
+ * 移动到指定容器中
2092
+ * @param config 需要移动的节点
2093
+ * @param targetId 容器ID
2094
+ */
2095
+ async moveToContainer(config, targetId) {
2096
+ const root = this.get("root");
2097
+ const { node, parent } = this.getNodeInfo(config.id, false);
2098
+ const target = this.getNodeById(targetId, false);
2099
+ const stage = this.get("stage");
2100
+ if (root && node && parent && stage) {
2101
+ const index = getNodeIndex(node.id, parent);
2102
+ parent.items?.splice(index, 1);
2103
+ await stage.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
2104
+ const layout = await this.getLayout(target);
2105
+ const newConfig = mergeWith(cloneDeep(node), config, (objValue, srcValue) => {
2106
+ if (Array.isArray(srcValue)) {
2107
+ return srcValue;
2108
+ }
2109
+ });
2110
+ newConfig.style = getInitPositionStyle(newConfig.style, layout);
2111
+ target.items.push(newConfig);
2112
+ await stage.select(targetId);
2113
+ const targetParent = this.getParentById(target.id);
2114
+ await stage.update({ config: cloneDeep(target), parentId: targetParent?.id, root: cloneDeep(root) });
2115
+ await this.select(newConfig);
2116
+ stage.select(newConfig.id);
2117
+ this.addModifiedNodeId(target.id);
2118
+ this.addModifiedNodeId(parent.id);
2119
+ this.pushHistoryState();
2120
+ return newConfig;
2121
+ }
2122
+ }
2123
+ async dragTo(config, targetParent, targetIndex) {
2124
+ if (!targetParent || !Array.isArray(targetParent.items))
2125
+ return;
2126
+ const { parent, node: curNode } = this.getNodeInfo(config.id, false);
2127
+ if (!parent || !curNode)
2128
+ throw new Error("找不要删除的节点");
2129
+ const index = getNodeIndex(curNode.id, parent);
2130
+ if (typeof index !== "number" || index === -1)
2131
+ throw new Error("找不要删除的节点");
2132
+ if (parent.id === targetParent.id) {
2133
+ if (index === targetIndex)
2134
+ return;
2135
+ if (index < targetIndex) {
2136
+ targetIndex -= 1;
2137
+ }
2138
+ }
2139
+ const layout = await this.getLayout(parent);
2140
+ const newLayout = await this.getLayout(targetParent);
2141
+ if (newLayout !== layout) {
2142
+ setLayout(config, newLayout);
2143
+ }
2144
+ parent.items?.splice(index, 1);
2145
+ targetParent.items?.splice(targetIndex, 0, config);
2146
+ const page = this.get("page");
2147
+ const root = this.get("root");
2148
+ const stage = this.get("stage");
2149
+ if (stage && page && root) {
2150
+ stage.update({
2151
+ config: cloneDeep(page),
2152
+ parentId: root.id,
2153
+ root: cloneDeep(root)
2154
+ });
2155
+ }
2156
+ this.addModifiedNodeId(config.id);
2157
+ this.addModifiedNodeId(parent.id);
2158
+ this.pushHistoryState();
2159
+ this.emit("drag-to", { index, targetIndex, config, parent, targetParent });
2160
+ }
2161
+ /**
2162
+ * 撤销当前操作
2163
+ * @returns 上一次数据
2779
2164
  */
2780
- copy(config) {
2781
- storageService.setItem(COPY_STORAGE_KEY, Array.isArray(config) ? config : [config], {
2782
- protocol: Protocol.OBJECT
2783
- });
2165
+ async undo() {
2166
+ const value = historyService.undo();
2167
+ await this.changeHistoryState(value);
2168
+ return value;
2784
2169
  }
2785
2170
  /**
2786
- * 复制时会带上组件关联的依赖
2787
- * @param config 组件节点配置
2788
- * @returns
2171
+ * 恢复到下一步
2172
+ * @returns 下一步数据
2789
2173
  */
2790
- copyWithRelated(config) {
2791
- const copyNodes = Array.isArray(config) ? config : [config];
2792
- depService.clearByType(DepTargetType.RELATED_COMP_WHEN_COPY);
2793
- depService.collect(copyNodes, true, DepTargetType.RELATED_COMP_WHEN_COPY);
2794
- const customTarget = depService.getTarget(
2795
- DepTargetType.RELATED_COMP_WHEN_COPY,
2796
- DepTargetType.RELATED_COMP_WHEN_COPY
2797
- );
2798
- if (customTarget) {
2799
- Object.keys(customTarget.deps).forEach((nodeId) => {
2800
- const node = this.getNodeById(nodeId);
2801
- if (!node)
2802
- return;
2803
- customTarget.deps[nodeId].keys.forEach((key) => {
2804
- const relateNodeId = get(node, key);
2805
- const isExist = copyNodes.find((node2) => node2.id === relateNodeId);
2806
- if (!isExist) {
2807
- const relateNode = this.getNodeById(relateNodeId);
2808
- if (relateNode) {
2809
- copyNodes.push(relateNode);
2810
- }
2811
- }
2174
+ async redo() {
2175
+ const value = historyService.redo();
2176
+ await this.changeHistoryState(value);
2177
+ return value;
2178
+ }
2179
+ async move(left, top) {
2180
+ const node = toRaw(this.get("node"));
2181
+ if (!node || isPage(node))
2182
+ return;
2183
+ const { style, id, type } = node;
2184
+ if (!style || !["absolute", "fixed"].includes(style.position))
2185
+ return;
2186
+ const update = (style2) => this.update({
2187
+ id,
2188
+ type,
2189
+ style: style2
2190
+ });
2191
+ if (top) {
2192
+ if (isNumber(style.top)) {
2193
+ update({
2194
+ ...style,
2195
+ top: Number(style.top) + Number(top),
2196
+ bottom: ""
2197
+ });
2198
+ } else if (isNumber(style.bottom)) {
2199
+ update({
2200
+ ...style,
2201
+ bottom: Number(style.bottom) - Number(top),
2202
+ top: ""
2203
+ });
2204
+ }
2205
+ }
2206
+ if (left) {
2207
+ if (isNumber(style.left)) {
2208
+ update({
2209
+ ...style,
2210
+ left: Number(style.left) + Number(left),
2211
+ right: ""
2212
+ });
2213
+ } else if (isNumber(style.right)) {
2214
+ update({
2215
+ ...style,
2216
+ right: Number(style.right) - Number(left),
2217
+ left: ""
2812
2218
  });
2219
+ }
2220
+ }
2221
+ }
2222
+ resetState() {
2223
+ this.set("root", null);
2224
+ this.set("node", null);
2225
+ this.set("nodes", []);
2226
+ this.set("page", null);
2227
+ this.set("parent", null);
2228
+ this.set("stage", null);
2229
+ this.set("highlightNode", null);
2230
+ this.set("modifiedNodeIds", /* @__PURE__ */ new Map());
2231
+ this.set("pageLength", 0);
2232
+ }
2233
+ destroy() {
2234
+ this.removeAllListeners();
2235
+ this.resetState();
2236
+ this.removeAllPlugins();
2237
+ }
2238
+ resetModifiedNodeId() {
2239
+ this.get("modifiedNodeIds").clear();
2240
+ }
2241
+ usePlugin(options) {
2242
+ super.usePlugin(options);
2243
+ }
2244
+ addModifiedNodeId(id) {
2245
+ if (!this.isHistoryStateChange) {
2246
+ this.get("modifiedNodeIds").set(id, id);
2247
+ }
2248
+ }
2249
+ pushHistoryState() {
2250
+ const curNode = cloneDeep(toRaw(this.get("node")));
2251
+ const page = this.get("page");
2252
+ if (!this.isHistoryStateChange && curNode && page) {
2253
+ historyService.push({
2254
+ data: cloneDeep(toRaw(page)),
2255
+ modifiedNodeIds: this.get("modifiedNodeIds"),
2256
+ nodeId: curNode.id
2813
2257
  });
2814
2258
  }
2815
- storageService.setItem(COPY_STORAGE_KEY, copyNodes, {
2816
- protocol: Protocol.OBJECT
2817
- });
2259
+ this.isHistoryStateChange = false;
2260
+ }
2261
+ async changeHistoryState(value) {
2262
+ if (!value)
2263
+ return;
2264
+ this.isHistoryStateChange = true;
2265
+ await this.update(value.data);
2266
+ this.set("modifiedNodeIds", value.modifiedNodeIds);
2267
+ setTimeout(async () => {
2268
+ if (!value.nodeId)
2269
+ return;
2270
+ await this.select(value.nodeId);
2271
+ this.get("stage")?.select(value.nodeId);
2272
+ }, 0);
2273
+ this.emit("history-change", value.data);
2274
+ }
2275
+ async toggleFixedPosition(dist, src, root) {
2276
+ const newConfig = cloneDeep(dist);
2277
+ if (!isPop(src) && newConfig.style?.position) {
2278
+ if (isFixed(newConfig) && !isFixed(src)) {
2279
+ newConfig.style = change2Fixed(newConfig, root);
2280
+ } else if (!isFixed(newConfig) && isFixed(src)) {
2281
+ newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
2282
+ }
2283
+ }
2284
+ return newConfig;
2285
+ }
2286
+ selectedConfigExceptionHandler(config) {
2287
+ let id;
2288
+ if (typeof config === "string" || typeof config === "number") {
2289
+ id = config;
2290
+ } else {
2291
+ id = config.id;
2292
+ }
2293
+ if (!id) {
2294
+ throw new Error("没有ID,无法选中");
2295
+ }
2296
+ const { node, parent, page } = this.getNodeInfo(id);
2297
+ if (!node)
2298
+ throw new Error("获取不到组件信息");
2299
+ if (node.id === this.state.root?.id) {
2300
+ throw new Error("不能选根节点");
2301
+ }
2302
+ return {
2303
+ node,
2304
+ parent,
2305
+ page
2306
+ };
2307
+ }
2308
+ }
2309
+ const editorService = new Editor();
2310
+
2311
+ function BaseFormConfig() {
2312
+ return [
2313
+ {
2314
+ name: "id",
2315
+ type: "hidden"
2316
+ },
2317
+ {
2318
+ name: "type",
2319
+ text: "类型",
2320
+ type: "hidden",
2321
+ defaultValue: "base"
2322
+ },
2323
+ {
2324
+ name: "title",
2325
+ text: "名称",
2326
+ rules: [
2327
+ {
2328
+ required: true,
2329
+ message: "请输入名称"
2330
+ }
2331
+ ]
2332
+ },
2333
+ {
2334
+ name: "description",
2335
+ text: "描述"
2336
+ }
2337
+ ];
2338
+ }
2339
+
2340
+ const HttpFormConfig = [
2341
+ {
2342
+ name: "autoFetch",
2343
+ text: "自动请求",
2344
+ type: "switch",
2345
+ defaultValue: true
2346
+ },
2347
+ {
2348
+ name: "responseOptions",
2349
+ items: [
2350
+ {
2351
+ name: "dataPath",
2352
+ text: "数据路径"
2353
+ }
2354
+ ]
2355
+ },
2356
+ {
2357
+ type: "fieldset",
2358
+ name: "options",
2359
+ legend: "HTTP 配置",
2360
+ items: [
2361
+ {
2362
+ name: "url",
2363
+ text: "URL"
2364
+ },
2365
+ {
2366
+ name: "method",
2367
+ text: "Method",
2368
+ type: "select",
2369
+ options: [
2370
+ { text: "GET", value: "GET" },
2371
+ { text: "POST", value: "POST" },
2372
+ { text: "PUT", value: "PUT" },
2373
+ { text: "DELETE", value: "DELETE" }
2374
+ ]
2375
+ },
2376
+ {
2377
+ name: "params",
2378
+ type: "key-value",
2379
+ defaultValue: {},
2380
+ text: "参数"
2381
+ },
2382
+ {
2383
+ name: "data",
2384
+ type: "key-value",
2385
+ defaultValue: {},
2386
+ advanced: true,
2387
+ text: "请求体"
2388
+ },
2389
+ {
2390
+ name: "headers",
2391
+ type: "key-value",
2392
+ defaultValue: {},
2393
+ text: "请求头"
2394
+ }
2395
+ ]
2818
2396
  }
2819
- /**
2820
- * 从localStorage中获取节点,然后添加到当前容器中
2821
- * @param position 粘贴的坐标
2822
- * @returns 添加后的组件节点配置
2823
- */
2824
- async paste(position = {}) {
2825
- const config = storageService.getItem(COPY_STORAGE_KEY);
2826
- if (!Array.isArray(config))
2827
- return;
2828
- const node = this.get("node");
2829
- let parent = null;
2830
- if (config.length === 1 && config[0].id === node?.id) {
2831
- parent = this.get("parent");
2832
- if (parent?.type === NodeType.ROOT) {
2833
- parent = this.get("page");
2397
+ ];
2398
+
2399
+ const fillConfig$1 = (config) => [
2400
+ ...BaseFormConfig(),
2401
+ ...config,
2402
+ {
2403
+ type: "tab",
2404
+ items: [
2405
+ {
2406
+ title: "数据定义",
2407
+ items: [
2408
+ {
2409
+ name: "fields",
2410
+ type: "data-source-fields",
2411
+ defaultValue: () => []
2412
+ }
2413
+ ]
2414
+ },
2415
+ {
2416
+ title: "方法定义",
2417
+ items: [
2418
+ {
2419
+ name: "methods",
2420
+ type: "data-source-methods",
2421
+ defaultValue: () => []
2422
+ }
2423
+ ]
2424
+ },
2425
+ {
2426
+ title: "事件配置",
2427
+ items: [
2428
+ {
2429
+ name: "events",
2430
+ src: "datasource",
2431
+ type: "event-select"
2432
+ }
2433
+ ]
2434
+ },
2435
+ {
2436
+ title: "mock数据",
2437
+ items: [
2438
+ {
2439
+ name: "mocks",
2440
+ type: "data-source-mocks",
2441
+ defaultValue: () => []
2442
+ }
2443
+ ]
2444
+ },
2445
+ {
2446
+ title: "请求参数裁剪",
2447
+ display: (formState, { model }) => model.type === "http",
2448
+ items: [
2449
+ {
2450
+ name: "beforeRequest",
2451
+ type: "vs-code",
2452
+ parse: true,
2453
+ height: "600px"
2454
+ }
2455
+ ]
2456
+ },
2457
+ {
2458
+ title: "响应数据裁剪",
2459
+ display: (formState, { model }) => model.type === "http",
2460
+ items: [
2461
+ {
2462
+ name: "afterResponse",
2463
+ type: "vs-code",
2464
+ parse: true,
2465
+ height: "600px"
2466
+ }
2467
+ ]
2834
2468
  }
2835
- }
2836
- const pasteConfigs = await this.doPaste(config, position);
2837
- propsService.replaceRelateId(config, pasteConfigs);
2838
- return this.add(pasteConfigs, parent);
2469
+ ]
2839
2470
  }
2840
- async doPaste(config, position = {}) {
2841
- propsService.clearRelateId();
2842
- const pasteConfigs = beforePaste(position, cloneDeep(config));
2843
- return pasteConfigs;
2471
+ ];
2472
+ const getFormConfig = (type, configs) => {
2473
+ switch (type) {
2474
+ case "base":
2475
+ return fillConfig$1([]);
2476
+ case "http":
2477
+ return fillConfig$1(HttpFormConfig);
2478
+ default:
2479
+ return fillConfig$1(configs[type] || []);
2844
2480
  }
2845
- async doAlignCenter(config) {
2846
- const parent = this.getParentById(config.id);
2847
- if (!parent)
2848
- throw new Error("找不到父节点");
2849
- const node = cloneDeep(toRaw(config));
2850
- const layout = await this.getLayout(parent, node);
2851
- if (layout === Layout.RELATIVE) {
2852
- return config;
2853
- }
2854
- if (!node.style)
2855
- return config;
2856
- const stage = this.get("stage");
2857
- const doc = stage?.renderer.contentWindow?.document;
2858
- if (doc) {
2859
- const el = doc.getElementById(`${node.id}`);
2860
- const parentEl = layout === Layout.FIXED ? doc.body : el?.offsetParent;
2861
- if (parentEl && el) {
2862
- node.style.left = calcValueByFontsize(doc, (parentEl.clientWidth - el.clientWidth) / 2);
2863
- node.style.right = "";
2864
- }
2865
- } else if (parent.style && isNumber(parent.style?.width) && isNumber(node.style?.width)) {
2866
- node.style.left = (parent.style.width - node.style.width) / 2;
2867
- node.style.right = "";
2868
- }
2869
- return node;
2481
+ };
2482
+ const getFormValue = (type, values) => {
2483
+ if (type !== "http") {
2484
+ return values;
2870
2485
  }
2486
+ return {
2487
+ beforeRequest: `(options, context) => {
2871
2488
  /**
2872
- * 将指点节点设置居中
2873
- * @param config 组件节点配置
2874
- * @returns 当前组件节点配置
2489
+ * 用户可以直接编写函数,在原始接口调用之前,会运行该函数,将这个函数的返回值作为该数据源接口的入参
2490
+ *
2491
+ * options: HttpOptions
2492
+ *
2493
+ * interface HttpOptions {
2494
+ * // 请求链接
2495
+ * url: string;
2496
+ * // query参数
2497
+ * params?: Record<string, string>;
2498
+ * // body数据
2499
+ * data?: Record<string, any>;
2500
+ * // 请求头
2501
+ * headers?: Record<string, string>;
2502
+ * // 请求方法 GET/POST
2503
+ * method?: Method;
2504
+ * }
2505
+ *
2506
+ * context:上下文对象
2507
+ *
2508
+ * interface Content {
2509
+ * app: AppCore;
2510
+ * dataSource: HttpDataSource;
2511
+ * }
2512
+ *
2513
+ * return: HttpOptions
2875
2514
  */
2876
- async alignCenter(config) {
2877
- const nodes = Array.isArray(config) ? config : [config];
2878
- const stage = this.get("stage");
2879
- const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
2880
- const newNode = await this.update(newNodes);
2881
- if (newNodes.length > 1) {
2882
- await stage?.multiSelect(newNodes.map((node) => node.id));
2883
- } else {
2884
- await stage?.select(newNodes[0].id);
2885
- }
2886
- return newNode;
2887
- }
2515
+
2516
+ // 此处的返回值会作为这个接口的入参
2517
+ return options;
2518
+ }`,
2519
+ afterResponse: `(response, context) => {
2888
2520
  /**
2889
- * 移动当前选中节点位置
2890
- * @param offset 偏移量
2891
- */
2892
- async moveLayer(offset) {
2893
- const root = this.get("root");
2894
- if (!root)
2895
- throw new Error("root为空");
2896
- const parent = this.get("parent");
2897
- if (!parent)
2898
- throw new Error("父节点为空");
2899
- const node = this.get("node");
2900
- if (!node)
2901
- throw new Error("当前节点为空");
2902
- const brothers = parent.items || [];
2903
- const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
2904
- const layout = await this.getLayout(parent, node);
2905
- const isRelative = layout === Layout.RELATIVE;
2906
- let offsetIndex;
2907
- if (offset === LayerOffset.TOP) {
2908
- offsetIndex = isRelative ? 0 : brothers.length;
2909
- } else if (offset === LayerOffset.BOTTOM) {
2910
- offsetIndex = isRelative ? brothers.length : 0;
2911
- } else {
2912
- offsetIndex = index + (isRelative ? -offset : offset);
2913
- }
2914
- if (offsetIndex > 0 && offsetIndex > brothers.length || offsetIndex < 0) {
2915
- return;
2916
- }
2917
- brothers.splice(index, 1);
2918
- brothers.splice(offsetIndex, 0, node);
2919
- const grandparent = this.getParentById(parent.id);
2920
- this.get("stage")?.update({
2921
- config: cloneDeep(toRaw(parent)),
2922
- parentId: grandparent?.id,
2923
- root: cloneDeep(root)
2521
+ * 用户可以直接编写函数,在原始接口返回之后,会运行该函数,将这个函数的返回值作为该数据源接口的返回
2522
+
2523
+ * context:上下文对象
2524
+ *
2525
+ * interface Content {
2526
+ * app: AppCore;
2527
+ * dataSource: HttpDataSource;
2528
+ * }
2529
+ *
2530
+ */
2531
+
2532
+ // 此处的返回值会作为这个接口的返回值
2533
+ return response;
2534
+ }`,
2535
+ ...values
2536
+ };
2537
+ };
2538
+ const getDisplayField = (dataSources, key) => {
2539
+ const displayState = [];
2540
+ const matches = key.matchAll(/\$\{([\s\S]+?)\}/g);
2541
+ let index = 0;
2542
+ for (const match of matches) {
2543
+ if (typeof match.index === "undefined")
2544
+ break;
2545
+ displayState.push({
2546
+ type: "text",
2547
+ value: key.substring(index, match.index)
2548
+ });
2549
+ let dsText = "";
2550
+ let ds;
2551
+ let fields;
2552
+ match[1].replaceAll(/\[(\d+)\]/g, ".$1").split(".").forEach((item, index2) => {
2553
+ if (index2 === 0) {
2554
+ ds = dataSources.find((ds2) => ds2.id === item);
2555
+ dsText += ds?.title || item;
2556
+ fields = ds?.fields;
2557
+ return;
2558
+ }
2559
+ if (isNumber(item)) {
2560
+ dsText += `[${item}]`;
2561
+ } else {
2562
+ const field = fields?.find((field2) => field2.name === item);
2563
+ fields = field?.fields;
2564
+ dsText += `.${field?.title || item}`;
2565
+ }
2924
2566
  });
2925
- this.addModifiedNodeId(parent.id);
2926
- this.pushHistoryState();
2927
- this.emit("move-layer", offset);
2567
+ displayState.push({
2568
+ type: "var",
2569
+ value: dsText
2570
+ });
2571
+ index = match.index + match[0].length;
2928
2572
  }
2929
- /**
2930
- * 移动到指定容器中
2931
- * @param config 需要移动的节点
2932
- * @param targetId 容器ID
2933
- */
2934
- async moveToContainer(config, targetId) {
2935
- const root = this.get("root");
2936
- const { node, parent } = this.getNodeInfo(config.id, false);
2937
- const target = this.getNodeById(targetId, false);
2938
- const stage = this.get("stage");
2939
- if (root && node && parent && stage) {
2940
- const index = getNodeIndex(node.id, parent);
2941
- parent.items?.splice(index, 1);
2942
- await stage.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
2943
- const layout = await this.getLayout(target);
2944
- const newConfig = mergeWith(cloneDeep(node), config, (objValue, srcValue) => {
2945
- if (Array.isArray(srcValue)) {
2946
- return srcValue;
2947
- }
2948
- });
2949
- newConfig.style = getInitPositionStyle(newConfig.style, layout);
2950
- target.items.push(newConfig);
2951
- await stage.select(targetId);
2952
- const targetParent = this.getParentById(target.id);
2953
- await stage.update({ config: cloneDeep(target), parentId: targetParent?.id, root: cloneDeep(root) });
2954
- await this.select(newConfig);
2955
- stage.select(newConfig.id);
2956
- this.addModifiedNodeId(target.id);
2957
- this.addModifiedNodeId(parent.id);
2958
- this.pushHistoryState();
2959
- return newConfig;
2960
- }
2573
+ if (index < key.length) {
2574
+ displayState.push({
2575
+ type: "text",
2576
+ value: key.substring(index)
2577
+ });
2961
2578
  }
2962
- async dragTo(config, targetParent, targetIndex) {
2963
- if (!targetParent || !Array.isArray(targetParent.items))
2579
+ return displayState;
2580
+ };
2581
+ const getCascaderOptionsFromFields = (fields = [], dataSourceFieldType = ["any"]) => {
2582
+ const child = [];
2583
+ fields.forEach((field) => {
2584
+ if (!dataSourceFieldType.length) {
2585
+ dataSourceFieldType.push("any");
2586
+ }
2587
+ const children = getCascaderOptionsFromFields(field.fields, dataSourceFieldType);
2588
+ const item = {
2589
+ label: field.title || field.name,
2590
+ value: field.name,
2591
+ children
2592
+ };
2593
+ const fieldType = field.type || "any";
2594
+ if (dataSourceFieldType.includes("any") || dataSourceFieldType.includes(fieldType)) {
2595
+ child.push(item);
2964
2596
  return;
2965
- const { parent, node: curNode } = this.getNodeInfo(config.id, false);
2966
- if (!parent || !curNode)
2967
- throw new Error("找不要删除的节点");
2968
- const index = getNodeIndex(curNode.id, parent);
2969
- if (typeof index !== "number" || index === -1)
2970
- throw new Error("找不要删除的节点");
2971
- if (parent.id === targetParent.id) {
2972
- if (index === targetIndex)
2973
- return;
2974
- if (index < targetIndex) {
2975
- targetIndex -= 1;
2976
- }
2977
2597
  }
2978
- const layout = await this.getLayout(parent);
2979
- const newLayout = await this.getLayout(targetParent);
2980
- if (newLayout !== layout) {
2981
- setLayout(config, newLayout);
2598
+ if (!dataSourceFieldType.includes(fieldType) && !["array", "object", "any"].includes(fieldType)) {
2599
+ return;
2982
2600
  }
2983
- parent.items?.splice(index, 1);
2984
- targetParent.items?.splice(targetIndex, 0, config);
2985
- const page = this.get("page");
2986
- const root = this.get("root");
2987
- const stage = this.get("stage");
2988
- if (stage && page && root) {
2989
- stage.update({
2990
- config: cloneDeep(page),
2991
- parentId: root.id,
2992
- root: cloneDeep(root)
2993
- });
2601
+ if (!children.length && ["object", "array", "any"].includes(field.type || "")) {
2602
+ return;
2994
2603
  }
2995
- this.addModifiedNodeId(config.id);
2996
- this.addModifiedNodeId(parent.id);
2997
- this.pushHistoryState();
2998
- this.emit("drag-to", { index, targetIndex, config, parent, targetParent });
2604
+ child.push(item);
2605
+ });
2606
+ return child;
2607
+ };
2608
+
2609
+ const canUsePluginMethods$3 = {
2610
+ async: [],
2611
+ sync: [
2612
+ "getFormConfig",
2613
+ "setFormConfig",
2614
+ "getFormValue",
2615
+ "setFormValue",
2616
+ "getFormEvent",
2617
+ "setFormEvent",
2618
+ "getFormMethod",
2619
+ "setFormMethod",
2620
+ "add",
2621
+ "update",
2622
+ "remove",
2623
+ "createId"
2624
+ ]
2625
+ };
2626
+ class DataSource extends BaseService {
2627
+ state = reactive({
2628
+ datasourceTypeList: [],
2629
+ dataSources: [],
2630
+ editable: true,
2631
+ configs: {},
2632
+ values: {},
2633
+ events: {},
2634
+ methods: {}
2635
+ });
2636
+ constructor() {
2637
+ super(canUsePluginMethods$3.sync.map((methodName) => ({ name: methodName, isAsync: false })));
2999
2638
  }
3000
- /**
3001
- * 撤销当前操作
3002
- * @returns 上一次数据
3003
- */
3004
- async undo() {
3005
- const value = historyService.undo();
3006
- await this.changeHistoryState(value);
3007
- return value;
2639
+ set(name, value) {
2640
+ this.state[name] = value;
3008
2641
  }
3009
- /**
3010
- * 恢复到下一步
3011
- * @returns 下一步数据
3012
- */
3013
- async redo() {
3014
- const value = historyService.redo();
3015
- await this.changeHistoryState(value);
3016
- return value;
2642
+ get(name) {
2643
+ return this.state[name];
3017
2644
  }
3018
- async move(left, top) {
3019
- const node = toRaw(this.get("node"));
3020
- if (!node || isPage(node))
3021
- return;
3022
- const { style, id, type } = node;
3023
- if (!style || !["absolute", "fixed"].includes(style.position))
3024
- return;
3025
- const update = (style2) => this.update({
3026
- id,
3027
- type,
3028
- style: style2
3029
- });
3030
- if (top) {
3031
- if (isNumber(style.top)) {
3032
- update({
3033
- ...style,
3034
- top: Number(style.top) + Number(top),
3035
- bottom: ""
3036
- });
3037
- } else if (isNumber(style.bottom)) {
3038
- update({
3039
- ...style,
3040
- bottom: Number(style.bottom) - Number(top),
3041
- top: ""
3042
- });
3043
- }
3044
- }
3045
- if (left) {
3046
- if (isNumber(style.left)) {
3047
- update({
3048
- ...style,
3049
- left: Number(style.left) + Number(left),
3050
- right: ""
3051
- });
3052
- } else if (isNumber(style.right)) {
3053
- update({
3054
- ...style,
3055
- right: Number(style.right) - Number(left),
3056
- left: ""
3057
- });
3058
- }
3059
- }
2645
+ getFormConfig(type = "base") {
2646
+ return getFormConfig(toLine(type), this.get("configs"));
3060
2647
  }
3061
- resetState() {
3062
- this.set("root", null);
3063
- this.set("node", null);
3064
- this.set("nodes", []);
3065
- this.set("page", null);
3066
- this.set("parent", null);
3067
- this.set("stage", null);
3068
- this.set("highlightNode", null);
3069
- this.set("modifiedNodeIds", /* @__PURE__ */ new Map());
3070
- this.set("pageLength", 0);
2648
+ setFormConfig(type, config) {
2649
+ this.get("configs")[toLine(type)] = config;
2650
+ }
2651
+ getFormValue(type = "base") {
2652
+ return getFormValue(toLine(type), this.get("values")[type]);
2653
+ }
2654
+ setFormValue(type, value) {
2655
+ this.get("values")[toLine(type)] = value;
2656
+ }
2657
+ getFormEvent(type = "base") {
2658
+ return this.get("events")[toLine(type)] || [];
2659
+ }
2660
+ setFormEvent(type, value = []) {
2661
+ this.get("events")[toLine(type)] = value;
2662
+ }
2663
+ getFormMethod(type = "base") {
2664
+ return this.get("methods")[toLine(type)] || [];
2665
+ }
2666
+ setFormMethod(type, value = []) {
2667
+ this.get("methods")[toLine(type)] = value;
2668
+ }
2669
+ add(config) {
2670
+ const newConfig = {
2671
+ ...config,
2672
+ id: config.id && !this.getDataSourceById(config.id) ? config.id : this.createId()
2673
+ };
2674
+ this.get("dataSources").push(newConfig);
2675
+ this.emit("add", newConfig);
2676
+ return newConfig;
2677
+ }
2678
+ update(config) {
2679
+ const dataSources = this.get("dataSources");
2680
+ const index = dataSources.findIndex((ds) => ds.id === config.id);
2681
+ dataSources[index] = cloneDeep(config);
2682
+ this.emit("update", config);
2683
+ return config;
2684
+ }
2685
+ remove(id) {
2686
+ const dataSources = this.get("dataSources");
2687
+ const index = dataSources.findIndex((ds) => ds.id === id);
2688
+ dataSources.splice(index, 1);
2689
+ this.emit("remove", id);
2690
+ }
2691
+ createId() {
2692
+ return `ds_${guid()}`;
2693
+ }
2694
+ getDataSourceById(id) {
2695
+ return this.get("dataSources").find((ds) => ds.id === id);
2696
+ }
2697
+ resetState() {
2698
+ this.set("dataSources", []);
3071
2699
  }
3072
2700
  destroy() {
3073
2701
  this.removeAllListeners();
3074
2702
  this.resetState();
3075
2703
  this.removeAllPlugins();
3076
2704
  }
3077
- resetModifiedNodeId() {
3078
- this.get("modifiedNodeIds").clear();
3079
- }
3080
2705
  usePlugin(options) {
3081
2706
  super.usePlugin(options);
3082
2707
  }
3083
- addModifiedNodeId(id) {
3084
- if (!this.isHistoryStateChange) {
3085
- this.get("modifiedNodeIds").set(id, id);
3086
- }
3087
- }
3088
- pushHistoryState() {
3089
- const curNode = cloneDeep(toRaw(this.get("node")));
3090
- const page = this.get("page");
3091
- if (!this.isHistoryStateChange && curNode && page) {
3092
- historyService.push({
3093
- data: cloneDeep(toRaw(page)),
3094
- modifiedNodeIds: this.get("modifiedNodeIds"),
3095
- nodeId: curNode.id
2708
+ /**
2709
+ * 复制时会带上组件关联的数据源
2710
+ * @param config 组件节点配置
2711
+ * @returns
2712
+ */
2713
+ copyWithRelated(config, collectorOptions) {
2714
+ const copyNodes = Array.isArray(config) ? config : [config];
2715
+ const copyData = [];
2716
+ if (collectorOptions && typeof collectorOptions.isTarget === "function") {
2717
+ const customTarget = new Target({
2718
+ ...collectorOptions
2719
+ });
2720
+ const coperWatcher = new Watcher();
2721
+ coperWatcher.addTarget(customTarget);
2722
+ coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
2723
+ Object.keys(customTarget.deps).forEach((nodeId) => {
2724
+ const node = editorService.getNodeById(nodeId);
2725
+ if (!node)
2726
+ return;
2727
+ customTarget.deps[nodeId].keys.forEach((key) => {
2728
+ const [relateDsId] = get(node, key);
2729
+ const isExist = copyData.find((dsItem) => dsItem.id === relateDsId);
2730
+ if (!isExist) {
2731
+ const relateDs = this.getDataSourceById(relateDsId);
2732
+ if (relateDs) {
2733
+ copyData.push(relateDs);
2734
+ }
2735
+ }
2736
+ });
3096
2737
  });
3097
2738
  }
3098
- this.isHistoryStateChange = false;
3099
- }
3100
- async changeHistoryState(value) {
3101
- if (!value)
3102
- return;
3103
- this.isHistoryStateChange = true;
3104
- await this.update(value.data);
3105
- this.set("modifiedNodeIds", value.modifiedNodeIds);
3106
- setTimeout(async () => {
3107
- if (!value.nodeId)
3108
- return;
3109
- await this.select(value.nodeId);
3110
- this.get("stage")?.select(value.nodeId);
3111
- }, 0);
3112
- this.emit("history-change", value.data);
2739
+ storageService.setItem(COPY_DS_STORAGE_KEY, copyData, {
2740
+ protocol: Protocol.OBJECT
2741
+ });
3113
2742
  }
3114
- async toggleFixedPosition(dist, src, root) {
3115
- const newConfig = cloneDeep(dist);
3116
- if (!isPop(src) && newConfig.style?.position) {
3117
- if (isFixed(newConfig) && !isFixed(src)) {
3118
- newConfig.style = change2Fixed(newConfig, root);
3119
- } else if (!isFixed(newConfig) && isFixed(src)) {
3120
- newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
2743
+ /**
2744
+ * 粘贴数据源
2745
+ * @returns
2746
+ */
2747
+ paste() {
2748
+ const dataSource = storageService.getItem(COPY_DS_STORAGE_KEY);
2749
+ dataSource.forEach((item) => {
2750
+ if (!this.getDataSourceById(item.id)) {
2751
+ this.add(item);
3121
2752
  }
2753
+ });
2754
+ }
2755
+ }
2756
+ const dataSourceService = new DataSource();
2757
+
2758
+ const arrayOptions = [
2759
+ { text: "包含", value: "include" },
2760
+ { text: "不包含", value: "not_include" }
2761
+ ];
2762
+ const eqOptions = [
2763
+ { text: "等于", value: "=" },
2764
+ { text: "不等于", value: "!=" }
2765
+ ];
2766
+ const numberOptions = [
2767
+ { text: "大于", value: ">" },
2768
+ { text: "大于等于", value: ">=" },
2769
+ { text: "小于", value: "<" },
2770
+ { text: "小于等于", value: "<=" },
2771
+ { text: "在范围内", value: "between" },
2772
+ { text: "不在范围内", value: "not_between" }
2773
+ ];
2774
+ const styleTabConfig = {
2775
+ title: "样式",
2776
+ items: [
2777
+ {
2778
+ name: "style",
2779
+ items: [
2780
+ {
2781
+ type: "fieldset",
2782
+ legend: "位置",
2783
+ items: [
2784
+ {
2785
+ type: "data-source-field-select",
2786
+ name: "position",
2787
+ text: "固定定位",
2788
+ checkStrictly: false,
2789
+ dataSourceFieldType: ["string"],
2790
+ fieldConfig: {
2791
+ type: "checkbox",
2792
+ activeValue: "fixed",
2793
+ inactiveValue: "absolute",
2794
+ defaultValue: "absolute"
2795
+ }
2796
+ },
2797
+ {
2798
+ type: "data-source-field-select",
2799
+ name: "left",
2800
+ text: "left",
2801
+ checkStrictly: false,
2802
+ dataSourceFieldType: ["string", "number"],
2803
+ fieldConfig: {
2804
+ type: "text"
2805
+ }
2806
+ },
2807
+ {
2808
+ type: "data-source-field-select",
2809
+ name: "top",
2810
+ text: "top",
2811
+ checkStrictly: false,
2812
+ dataSourceFieldType: ["string", "number"],
2813
+ fieldConfig: {
2814
+ type: "text"
2815
+ },
2816
+ disabled: (vm, { model }) => model.position === "fixed" && model._magic_position === "fixedBottom"
2817
+ },
2818
+ {
2819
+ type: "data-source-field-select",
2820
+ name: "right",
2821
+ text: "right",
2822
+ checkStrictly: false,
2823
+ dataSourceFieldType: ["string", "number"],
2824
+ fieldConfig: {
2825
+ type: "text"
2826
+ }
2827
+ },
2828
+ {
2829
+ type: "data-source-field-select",
2830
+ name: "bottom",
2831
+ text: "bottom",
2832
+ checkStrictly: false,
2833
+ dataSourceFieldType: ["string", "number"],
2834
+ fieldConfig: {
2835
+ type: "text"
2836
+ },
2837
+ disabled: (vm, { model }) => model.position === "fixed" && model._magic_position === "fixedTop"
2838
+ }
2839
+ ]
2840
+ },
2841
+ {
2842
+ type: "fieldset",
2843
+ legend: "盒子",
2844
+ items: [
2845
+ {
2846
+ type: "data-source-field-select",
2847
+ name: "width",
2848
+ text: "宽度",
2849
+ checkStrictly: false,
2850
+ dataSourceFieldType: ["string", "number"],
2851
+ fieldConfig: {
2852
+ type: "text"
2853
+ }
2854
+ },
2855
+ {
2856
+ type: "data-source-field-select",
2857
+ name: "height",
2858
+ text: "高度",
2859
+ checkStrictly: false,
2860
+ dataSourceFieldType: ["string", "number"],
2861
+ fieldConfig: {
2862
+ type: "text"
2863
+ }
2864
+ },
2865
+ {
2866
+ type: "data-source-field-select",
2867
+ text: "overflow",
2868
+ name: "overflow",
2869
+ checkStrictly: false,
2870
+ dataSourceFieldType: ["string"],
2871
+ fieldConfig: {
2872
+ type: "select",
2873
+ options: [
2874
+ { text: "visible", value: "visible" },
2875
+ { text: "hidden", value: "hidden" },
2876
+ { text: "clip", value: "clip" },
2877
+ { text: "scroll", value: "scroll" },
2878
+ { text: "auto", value: "auto" },
2879
+ { text: "overlay", value: "overlay" }
2880
+ ]
2881
+ }
2882
+ }
2883
+ ]
2884
+ },
2885
+ {
2886
+ type: "fieldset",
2887
+ legend: "边框",
2888
+ items: [
2889
+ {
2890
+ type: "data-source-field-select",
2891
+ name: "borderWidth",
2892
+ text: "宽度",
2893
+ defaultValue: "0",
2894
+ checkStrictly: false,
2895
+ dataSourceFieldType: ["string", "number"],
2896
+ fieldConfig: {
2897
+ type: "text"
2898
+ }
2899
+ },
2900
+ {
2901
+ type: "data-source-field-select",
2902
+ name: "borderColor",
2903
+ text: "颜色",
2904
+ checkStrictly: false,
2905
+ dataSourceFieldType: ["string"],
2906
+ fieldConfig: {
2907
+ type: "text"
2908
+ }
2909
+ },
2910
+ {
2911
+ type: "data-source-field-select",
2912
+ name: "borderStyle",
2913
+ text: "样式",
2914
+ defaultValue: "none",
2915
+ checkStrictly: false,
2916
+ dataSourceFieldType: ["string"],
2917
+ fieldConfig: {
2918
+ type: "select",
2919
+ options: [
2920
+ { text: "none", value: "none" },
2921
+ { text: "hidden", value: "hidden" },
2922
+ { text: "dotted", value: "dotted" },
2923
+ { text: "dashed", value: "dashed" },
2924
+ { text: "solid", value: "solid" },
2925
+ { text: "double", value: "double" },
2926
+ { text: "groove", value: "groove" },
2927
+ { text: "ridge", value: "ridge" },
2928
+ { text: "inset", value: "inset" },
2929
+ { text: "outset", value: "outset" }
2930
+ ]
2931
+ }
2932
+ }
2933
+ ]
2934
+ },
2935
+ {
2936
+ type: "fieldset",
2937
+ legend: "背景",
2938
+ items: [
2939
+ {
2940
+ type: "data-source-field-select",
2941
+ name: "backgroundImage",
2942
+ text: "背景图",
2943
+ checkStrictly: false,
2944
+ dataSourceFieldType: ["string"],
2945
+ fieldConfig: {
2946
+ type: "text"
2947
+ }
2948
+ },
2949
+ {
2950
+ type: "data-source-field-select",
2951
+ name: "backgroundColor",
2952
+ text: "背景颜色",
2953
+ checkStrictly: false,
2954
+ dataSourceFieldType: ["string"],
2955
+ fieldConfig: {
2956
+ type: "colorPicker"
2957
+ }
2958
+ },
2959
+ {
2960
+ type: "data-source-field-select",
2961
+ name: "backgroundRepeat",
2962
+ text: "背景图重复",
2963
+ defaultValue: "no-repeat",
2964
+ checkStrictly: false,
2965
+ dataSourceFieldType: ["string"],
2966
+ fieldConfig: {
2967
+ type: "select",
2968
+ options: [
2969
+ { text: "repeat", value: "repeat" },
2970
+ { text: "repeat-x", value: "repeat-x" },
2971
+ { text: "repeat-y", value: "repeat-y" },
2972
+ { text: "no-repeat", value: "no-repeat" },
2973
+ { text: "inherit", value: "inherit" }
2974
+ ]
2975
+ }
2976
+ },
2977
+ {
2978
+ type: "data-source-field-select",
2979
+ name: "backgroundSize",
2980
+ text: "背景图大小",
2981
+ defaultValue: "100% 100%",
2982
+ checkStrictly: false,
2983
+ dataSourceFieldType: ["string"],
2984
+ fieldConfig: {
2985
+ type: "text"
2986
+ }
2987
+ }
2988
+ ]
2989
+ },
2990
+ {
2991
+ type: "fieldset",
2992
+ legend: "字体",
2993
+ items: [
2994
+ {
2995
+ type: "data-source-field-select",
2996
+ name: "color",
2997
+ text: "颜色",
2998
+ checkStrictly: false,
2999
+ dataSourceFieldType: ["string"],
3000
+ fieldConfig: {
3001
+ type: "colorPicker"
3002
+ }
3003
+ },
3004
+ {
3005
+ type: "data-source-field-select",
3006
+ name: "fontSize",
3007
+ text: "大小",
3008
+ checkStrictly: false,
3009
+ dataSourceFieldType: ["string", "number"],
3010
+ fieldConfig: {
3011
+ type: "text"
3012
+ }
3013
+ },
3014
+ {
3015
+ type: "data-source-field-select",
3016
+ name: "fontWeight",
3017
+ text: "粗细",
3018
+ checkStrictly: false,
3019
+ dataSourceFieldType: ["string", "number"],
3020
+ fieldConfig: {
3021
+ type: "text"
3022
+ }
3023
+ }
3024
+ ]
3025
+ },
3026
+ {
3027
+ type: "fieldset",
3028
+ legend: "变形",
3029
+ name: "transform",
3030
+ items: [
3031
+ {
3032
+ type: "data-source-field-select",
3033
+ name: "rotate",
3034
+ text: "旋转角度",
3035
+ checkStrictly: false,
3036
+ dataSourceFieldType: ["string"],
3037
+ fieldConfig: {
3038
+ type: "text"
3039
+ }
3040
+ },
3041
+ {
3042
+ type: "data-source-field-select",
3043
+ name: "scale",
3044
+ text: "缩放",
3045
+ checkStrictly: false,
3046
+ dataSourceFieldType: ["number", "string"],
3047
+ fieldConfig: {
3048
+ type: "text"
3049
+ }
3050
+ }
3051
+ ]
3052
+ }
3053
+ ]
3122
3054
  }
3123
- return newConfig;
3124
- }
3125
- selectedConfigExceptionHandler(config) {
3126
- let id;
3127
- if (typeof config === "string" || typeof config === "number") {
3128
- id = config;
3129
- } else {
3130
- id = config.id;
3055
+ ]
3056
+ };
3057
+ const eventTabConfig = {
3058
+ title: "事件",
3059
+ items: [
3060
+ {
3061
+ name: "events",
3062
+ src: "component",
3063
+ labelWidth: "100px",
3064
+ type: "event-select"
3131
3065
  }
3132
- if (!id) {
3133
- throw new Error("没有ID,无法选中");
3066
+ ]
3067
+ };
3068
+ const advancedTabConfig = {
3069
+ title: "高级",
3070
+ lazy: true,
3071
+ items: [
3072
+ {
3073
+ name: "created",
3074
+ text: "created",
3075
+ type: "code-select"
3076
+ },
3077
+ {
3078
+ name: "mounted",
3079
+ text: "mounted",
3080
+ type: "code-select"
3134
3081
  }
3135
- const { node, parent, page } = this.getNodeInfo(id);
3136
- if (!node)
3137
- throw new Error("获取不到组件信息");
3138
- if (node.id === this.state.root?.id) {
3139
- throw new Error("不能选根节点");
3082
+ ]
3083
+ };
3084
+ const displayTabConfig = {
3085
+ title: "显示条件",
3086
+ display: (vm, { model }) => model.type !== "page",
3087
+ items: [
3088
+ {
3089
+ type: "groupList",
3090
+ name: "displayConds",
3091
+ titlePrefix: "条件组",
3092
+ expandAll: true,
3093
+ items: [
3094
+ {
3095
+ type: "table",
3096
+ name: "cond",
3097
+ items: [
3098
+ {
3099
+ type: "data-source-field-select",
3100
+ name: "field",
3101
+ value: "key",
3102
+ label: "字段",
3103
+ checkStrictly: false,
3104
+ dataSourceFieldType: ["string", "number", "boolean", "any"]
3105
+ },
3106
+ {
3107
+ type: "select",
3108
+ options: (mForm, { model }) => {
3109
+ const [id, ...fieldNames] = model.field;
3110
+ const ds = dataSourceService.getDataSourceById(id);
3111
+ let fields = ds?.fields || [];
3112
+ let type = "";
3113
+ (fieldNames || []).forEach((fieldName) => {
3114
+ const field = fields.find((f) => f.name === fieldName);
3115
+ fields = field?.fields || [];
3116
+ type = field?.type || "";
3117
+ });
3118
+ if (type === "array") {
3119
+ return arrayOptions;
3120
+ }
3121
+ if (type === "boolean") {
3122
+ return [
3123
+ { text: "是", value: "is" },
3124
+ { text: "不是", value: "not" }
3125
+ ];
3126
+ }
3127
+ if (type === "number") {
3128
+ return [...eqOptions, ...numberOptions];
3129
+ }
3130
+ if (type === "string") {
3131
+ return [...arrayOptions, ...eqOptions];
3132
+ }
3133
+ return [...arrayOptions, ...eqOptions, ...numberOptions];
3134
+ },
3135
+ label: "条件",
3136
+ name: "op"
3137
+ },
3138
+ {
3139
+ label: "值",
3140
+ items: [
3141
+ {
3142
+ name: "value",
3143
+ type: (mForm, { model }) => {
3144
+ const [id, ...fieldNames] = model.field;
3145
+ const ds = dataSourceService.getDataSourceById(id);
3146
+ let fields = ds?.fields || [];
3147
+ let type = "";
3148
+ (fieldNames || []).forEach((fieldName) => {
3149
+ const field = fields.find((f) => f.name === fieldName);
3150
+ fields = field?.fields || [];
3151
+ type = field?.type || "";
3152
+ });
3153
+ if (type === "number") {
3154
+ return "number";
3155
+ }
3156
+ if (type === "boolean") {
3157
+ return "select";
3158
+ }
3159
+ return "text";
3160
+ },
3161
+ options: [
3162
+ { text: "true", value: true },
3163
+ { text: "false", value: false }
3164
+ ],
3165
+ display: (vm, { model }) => !["between", "not_between"].includes(model.op)
3166
+ },
3167
+ {
3168
+ name: "range",
3169
+ type: "number-range",
3170
+ display: (vm, { model }) => ["between", "not_between"].includes(model.op)
3171
+ }
3172
+ ]
3173
+ }
3174
+ ]
3175
+ }
3176
+ ]
3140
3177
  }
3141
- return {
3142
- node,
3143
- parent,
3144
- page
3145
- };
3178
+ ]
3179
+ };
3180
+ const fillConfig = (config = [], labelWidth = "80px") => [
3181
+ {
3182
+ type: "tab",
3183
+ labelWidth,
3184
+ items: [
3185
+ {
3186
+ title: "属性",
3187
+ items: [
3188
+ // 组件类型,必须要有
3189
+ {
3190
+ text: "type",
3191
+ name: "type",
3192
+ type: "hidden"
3193
+ },
3194
+ // 组件id,必须要有
3195
+ {
3196
+ name: "id",
3197
+ type: "display",
3198
+ text: "id"
3199
+ },
3200
+ {
3201
+ name: "name",
3202
+ text: "组件名称"
3203
+ },
3204
+ ...config
3205
+ ]
3206
+ },
3207
+ { ...styleTabConfig },
3208
+ { ...eventTabConfig },
3209
+ { ...advancedTabConfig },
3210
+ { ...displayTabConfig }
3211
+ ]
3146
3212
  }
3147
- }
3148
- const editorService = new Editor();
3213
+ ];
3149
3214
 
3150
- const beforePaste = (position, config) => {
3151
- if (!config[0]?.style)
3152
- return config;
3153
- const curNode = editorService.get("node");
3154
- const { left: referenceLeft, top: referenceTop } = config[0].style;
3155
- const pasteConfigs = config.map((configItem) => {
3156
- const { offsetX = 0, offsetY = 0, ...positionClone } = position;
3157
- let pastePosition = positionClone;
3158
- if (!isEmpty(pastePosition) && curNode?.items) {
3159
- pastePosition = getPositionInContainer(pastePosition, curNode.id);
3160
- }
3161
- if (pastePosition.left && configItem.style?.left) {
3162
- pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
3163
- }
3164
- if (pastePosition.top && configItem.style?.top) {
3165
- pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
3166
- }
3167
- const pasteConfig = propsService.setNewItemId(configItem, false);
3168
- if (pasteConfig.style) {
3169
- const { left, top } = pasteConfig.style;
3170
- if (typeof left === "number" || !!left && !isNaN(Number(left))) {
3171
- pasteConfig.style.left = Number(left) + offsetX;
3172
- }
3173
- if (typeof top === "number" || !!top && !isNaN(Number(top))) {
3174
- pasteConfig.style.top = Number(top) + offsetY;
3175
- }
3176
- pasteConfig.style = {
3177
- ...pasteConfig.style,
3178
- ...pastePosition
3179
- };
3180
- }
3181
- const root = editorService.get("root");
3182
- if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
3183
- pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
3184
- }
3185
- return pasteConfig;
3186
- });
3187
- return pasteConfigs;
3215
+ const log = (...args) => {
3216
+ if (process.env.NODE_ENV === "development") {
3217
+ console.log("magic editor: ", ...args);
3218
+ }
3188
3219
  };
3189
- const getPositionInContainer = (position = {}, id) => {
3190
- let { left = 0, top = 0 } = position;
3191
- const parentEl = editorService.get("stage")?.renderer?.contentWindow?.document.getElementById(`${id}`);
3192
- const parentElRect = parentEl?.getBoundingClientRect();
3193
- left = left - (parentElRect?.left || 0);
3194
- top = top - (parentElRect?.top || 0);
3195
- return {
3196
- left,
3197
- top
3198
- };
3220
+ const info = (...args) => {
3221
+ if (process.env.NODE_ENV === "development") {
3222
+ console.info("magic editor: ", ...args);
3223
+ }
3199
3224
  };
3200
- const getAddParent = (node) => {
3201
- const curNode = editorService.get("node");
3202
- let parentNode;
3203
- if (isPage(node)) {
3204
- parentNode = editorService.get("root");
3205
- } else if (curNode?.items) {
3206
- parentNode = curNode;
3207
- } else if (curNode?.id) {
3208
- parentNode = editorService.getParentById(curNode.id, false);
3225
+ const warn = (...args) => {
3226
+ if (process.env.NODE_ENV === "development") {
3227
+ console.warn("magic editor: ", ...args);
3209
3228
  }
3210
- return parentNode;
3211
3229
  };
3212
- const getDefaultConfig = async (addNode, parentNode) => {
3213
- const { type, inputEvent, ...config } = addNode;
3214
- const layout = await editorService.getLayout(toRaw(parentNode), addNode);
3215
- const newNode = { ...toRaw(await propsService.getPropsValue(type, config)) };
3216
- newNode.style = getInitPositionStyle(newNode.style, layout);
3217
- return newNode;
3230
+ const debug = (...args) => {
3231
+ if (process.env.NODE_ENV === "development") {
3232
+ console.debug("magic editor: ", ...args);
3233
+ }
3234
+ };
3235
+ const error = (...args) => {
3236
+ if (process.env.NODE_ENV === "development") {
3237
+ console.error("magic editor: ", ...args);
3238
+ }
3218
3239
  };
3219
3240
 
3220
3241
  const _sfc_main$P = /* @__PURE__ */ defineComponent({
@@ -3604,7 +3625,6 @@ const useCodeBlockEdit = (codeBlockService) => {
3604
3625
  if (!codeId.value)
3605
3626
  return;
3606
3627
  await codeBlockService?.setCodeDslById(codeId.value, values);
3607
- tMagicMessage.success("代码块保存成功");
3608
3628
  codeBlockEditor.value?.hide();
3609
3629
  };
3610
3630
  return {
@@ -3806,7 +3826,7 @@ const useStage = (stageOptions) => {
3806
3826
  const stage = new StageCore({
3807
3827
  render: stageOptions.render,
3808
3828
  runtimeUrl: stageOptions.runtimeUrl,
3809
- zoom: zoom.value,
3829
+ zoom: stageOptions.zoom ?? zoom.value,
3810
3830
  autoScrollIntoView: stageOptions.autoScrollIntoView,
3811
3831
  isContainer: stageOptions.isContainer,
3812
3832
  containerHighlightClassName: stageOptions.containerHighlightClassName,
@@ -4582,7 +4602,7 @@ const _sfc_main$K = /* @__PURE__ */ defineComponent({
4582
4602
  const fieldQuerySearch = (queryString, leftAngleIndex, dotIndex, cb) => {
4583
4603
  let result = [];
4584
4604
  const dsKey = queryString.substring(leftAngleIndex + 1, dotIndex);
4585
- const keys = dsKey.split(".");
4605
+ const keys = dsKey.replaceAll(/\[(\d+)\]/g, ".$1").split(".");
4586
4606
  const dsId = keys.shift();
4587
4607
  const ds = dataSources.value.find((ds2) => ds2.id === dsId);
4588
4608
  if (!ds) {
@@ -4592,6 +4612,10 @@ const _sfc_main$K = /* @__PURE__ */ defineComponent({
4592
4612
  let fields = ds.fields || [];
4593
4613
  let key = keys.shift();
4594
4614
  while (key) {
4615
+ if (isNumber(key)) {
4616
+ key = keys.shift();
4617
+ continue;
4618
+ }
4595
4619
  for (const field of fields) {
4596
4620
  if (field.name === key) {
4597
4621
  fields = field.fields || [];
@@ -5635,13 +5659,17 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
5635
5659
  const eventsService = services?.eventsService;
5636
5660
  const codeBlockService = services?.codeBlockService;
5637
5661
  const eventNameConfig = computed(() => {
5638
- const fieldType = props.config.src === "component" ? "select" : "cascader";
5639
5662
  const defaultEventNameConfig = {
5640
5663
  name: "name",
5641
5664
  text: "事件",
5642
- type: fieldType,
5665
+ type: (mForm, { formValue }) => {
5666
+ if (props.config.src !== "component" || formValue.type === "page-fragment-container" && formValue.pageFragmentId) {
5667
+ return "cascader";
5668
+ }
5669
+ return "select";
5670
+ },
5643
5671
  labelWidth: "40px",
5644
- checkStrictly: true,
5672
+ checkStrictly: () => props.config.src !== "component",
5645
5673
  valueSeparator: ".",
5646
5674
  options: (mForm, { formValue }) => {
5647
5675
  let events = [];
@@ -5649,6 +5677,29 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
5649
5677
  return events;
5650
5678
  if (props.config.src === "component") {
5651
5679
  events = eventsService.getEvent(formValue.type);
5680
+ if (formValue.type === "page-fragment-container" && formValue.pageFragmentId) {
5681
+ const pageFragment = editorService?.get("root")?.items?.find((page) => page.id === formValue.pageFragmentId);
5682
+ if (pageFragment) {
5683
+ events = [
5684
+ {
5685
+ label: pageFragment.name || "迭代器容器",
5686
+ value: pageFragment.id,
5687
+ children: events
5688
+ }
5689
+ ];
5690
+ pageFragment.items.forEach((node) => {
5691
+ traverseNode(node, (node2) => {
5692
+ const nodeEvents = node2.type && eventsService.getEvent(node2.type) || [];
5693
+ events.push({
5694
+ label: `${node2.name}_${node2.id}`,
5695
+ value: `${node2.id}`,
5696
+ children: nodeEvents
5697
+ });
5698
+ });
5699
+ });
5700
+ return events;
5701
+ }
5702
+ }
5652
5703
  return events.map((option) => ({
5653
5704
  text: option.label,
5654
5705
  value: option.value
@@ -5707,7 +5758,11 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
5707
5758
  name: "to",
5708
5759
  text: "联动组件",
5709
5760
  type: "ui-select",
5710
- display: (mForm, { model }) => model.actionType === ActionType.COMP
5761
+ display: (mForm, { model }) => model.actionType === ActionType.COMP,
5762
+ onChange: (MForm, v, { model }) => {
5763
+ model.method = "";
5764
+ return v;
5765
+ }
5711
5766
  };
5712
5767
  return { ...defaultTargetCompConfig, ...props.config.targetCompConfig };
5713
5768
  });
@@ -5715,15 +5770,43 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
5715
5770
  const defaultCompActionConfig = {
5716
5771
  name: "method",
5717
5772
  text: "动作",
5718
- type: "select",
5773
+ type: (mForm, { model }) => {
5774
+ const to = editorService?.getNodeById(model.to);
5775
+ if (to && to.type === "page-fragment-container" && to.pageFragmentId) {
5776
+ return "cascader";
5777
+ }
5778
+ return "select";
5779
+ },
5780
+ checkStrictly: () => props.config.src !== "component",
5719
5781
  display: (mForm, { model }) => model.actionType === ActionType.COMP,
5720
5782
  options: (mForm, { model }) => {
5721
5783
  const node = editorService?.getNodeById(model.to);
5722
5784
  if (!node?.type)
5723
5785
  return [];
5724
- return eventsService?.getMethod(node.type).map((option) => ({
5725
- text: option.label,
5726
- value: option.value
5786
+ let methods = [];
5787
+ methods = eventsService?.getMethod(node.type) || [];
5788
+ if (node.type === "page-fragment-container" && node.pageFragmentId) {
5789
+ const pageFragment = editorService?.get("root")?.items?.find((page) => page.id === node.pageFragmentId);
5790
+ if (pageFragment) {
5791
+ methods = [];
5792
+ pageFragment.items.forEach((node2) => {
5793
+ traverseNode(node2, (node3) => {
5794
+ const nodeMethods = node3.type && eventsService?.getMethod(node3.type) || [];
5795
+ if (nodeMethods.length) {
5796
+ methods.push({
5797
+ label: `${node3.name}_${node3.id}`,
5798
+ value: `${node3.id}`,
5799
+ children: nodeMethods
5800
+ });
5801
+ }
5802
+ });
5803
+ });
5804
+ return methods;
5805
+ }
5806
+ }
5807
+ return methods.map((method) => ({
5808
+ text: method.label,
5809
+ value: method.value
5727
5810
  }));
5728
5811
  }
5729
5812
  };
@@ -7619,7 +7702,9 @@ const _sfc_main$n = /* @__PURE__ */ defineComponent({
7619
7702
  const selected = computed(() => nodeStatus.value.selected);
7620
7703
  const visible = computed(() => nodeStatus.value.visible);
7621
7704
  const draggable = computed(() => nodeStatus.value.draggable);
7622
- const hasChildren = computed(() => props.data.items?.some((item) => props.nodeStatusMap.get(item.id)?.visible));
7705
+ const hasChildren = computed(
7706
+ () => Array.isArray(props.data.items) && props.data.items.some((item) => props.nodeStatusMap.get(item.id)?.visible)
7707
+ );
7623
7708
  const handleDragStart = (event) => {
7624
7709
  treeEmit?.("node-dragstart", event, props.data);
7625
7710
  };
@@ -7850,24 +7935,38 @@ const _sfc_main$l = /* @__PURE__ */ defineComponent({
7850
7935
  const services = inject("services");
7851
7936
  const { codeBlockService, depService, editorService } = services || {};
7852
7937
  const codeList = computed(
7853
- () => Object.values(depService?.getTargets(DepTargetType.CODE_BLOCK) || {}).map((target) => {
7854
- const compNodes = Object.entries(target.deps).map(([id, dep]) => ({
7855
- name: dep.name,
7938
+ () => Object.entries(codeBlockService?.getCodeDsl() || {}).map(([codeId, code]) => {
7939
+ const target = depService?.getTarget(codeId, DepTargetType.CODE_BLOCK);
7940
+ const pageList = editorService?.get("root")?.items.map((page) => ({
7941
+ name: page.devconfig?.tabName || page.name,
7856
7942
  type: "node",
7857
- id: `${target.id}_${id}`,
7858
- key: id,
7859
- items: dep.keys.map((key) => {
7860
- const data2 = { name: `${key}`, id: `${target.id}_${id}_${key}`, type: "key" };
7861
- return data2;
7862
- })
7863
- }));
7943
+ id: `${codeId}_${page.id}`,
7944
+ key: page.id,
7945
+ items: []
7946
+ })) || [];
7947
+ if (target) {
7948
+ Object.entries(target.deps).forEach(([id, dep]) => {
7949
+ const page = pageList.find((page2) => page2.key === dep.data?.pageId);
7950
+ page?.items?.push({
7951
+ name: dep.name,
7952
+ type: "node",
7953
+ id: `${page.id}_${id}`,
7954
+ key: id,
7955
+ items: dep.keys.map((key) => {
7956
+ const data2 = { name: `${key}`, id: `${target.id}_${id}_${key}`, type: "key" };
7957
+ return data2;
7958
+ })
7959
+ });
7960
+ });
7961
+ }
7864
7962
  const data = {
7865
- id: target.id,
7866
- key: target.id,
7867
- name: target.name,
7963
+ id: codeId,
7964
+ key: codeId,
7965
+ name: code.name,
7868
7966
  type: "code",
7869
- codeBlockContent: codeBlockService?.getCodeContentById(target.id),
7870
- items: compNodes
7967
+ codeBlockContent: codeBlockService?.getCodeContentById(codeId),
7968
+ // 只有一个页面不显示页面分类
7969
+ items: pageList.length > 1 ? pageList.filter((page) => page.items?.length) : pageList[0]?.items || []
7871
7970
  };
7872
7971
  return data;
7873
7972
  })
@@ -8182,13 +8281,14 @@ const _sfc_main$i = /* @__PURE__ */ defineComponent({
8182
8281
  key: id,
8183
8282
  items: getKeyTreeConfig(dep, type, `${parentKey}_${id}`)
8184
8283
  });
8185
- const mergeChildren = (dsId, items, deps, type) => {
8284
+ const mergeChildren = (dsId, pageItems, deps, type) => {
8186
8285
  Object.entries(deps).forEach(([id, dep]) => {
8187
- const nodeItem = items.find((item) => item.key === id);
8286
+ const page = pageItems.find((page2) => page2.key === dep.data?.pageId);
8287
+ const nodeItem = page?.items.find((item) => item.key === id);
8188
8288
  if (nodeItem) {
8189
8289
  nodeItem.items = nodeItem.items.concat(getKeyTreeConfig(dep, type, nodeItem.key));
8190
8290
  } else {
8191
- items.push(getNodeTreeConfig(id, dep, type, dsId));
8291
+ page?.items.push(getNodeTreeConfig(id, dep, type, page.id));
8192
8292
  }
8193
8293
  });
8194
8294
  };
@@ -8197,7 +8297,13 @@ const _sfc_main$i = /* @__PURE__ */ defineComponent({
8197
8297
  const dsDeps = dsDep.value[ds.id]?.deps || {};
8198
8298
  const dsMethodDeps = dsMethodDep.value[ds.id]?.deps || {};
8199
8299
  const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
8200
- const items = [];
8300
+ const items = editorService?.get("root")?.items.map((page) => ({
8301
+ name: page.devconfig?.tabName || page.name,
8302
+ type: "node",
8303
+ id: `${ds.id}_${page.id}`,
8304
+ key: page.id,
8305
+ items: []
8306
+ })) || [];
8201
8307
  mergeChildren(ds.id, items, dsDeps);
8202
8308
  mergeChildren(ds.id, items, dsMethodDeps, "method");
8203
8309
  mergeChildren(ds.id, items, dsCondDeps, "cond");
@@ -8206,7 +8312,8 @@ const _sfc_main$i = /* @__PURE__ */ defineComponent({
8206
8312
  key: ds.id,
8207
8313
  name: ds.title,
8208
8314
  type: "ds",
8209
- items
8315
+ // 只有一个页面不显示页面分类
8316
+ items: items.length > 1 ? items.filter((page) => page.items.length) : items[0]?.items || []
8210
8317
  };
8211
8318
  })
8212
8319
  );
@@ -10734,7 +10841,7 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
10734
10841
 
10735
10842
  const canUsePluginMethods$1 = {
10736
10843
  async: ["setCodeDslById", "setEditStatus", "setCombineIds", "setUndeleteableList", "deleteCodeDslByIds"],
10737
- sync: []
10844
+ sync: ["setCodeDslByIdSync"]
10738
10845
  };
10739
10846
  class CodeBlock extends BaseService {
10740
10847
  state = reactive({
@@ -10745,7 +10852,10 @@ class CodeBlock extends BaseService {
10745
10852
  paramsColConfig: void 0
10746
10853
  });
10747
10854
  constructor() {
10748
- super(canUsePluginMethods$1.async.map((methodName) => ({ name: methodName, isAsync: true })));
10855
+ super([
10856
+ ...canUsePluginMethods$1.async.map((methodName) => ({ name: methodName, isAsync: true })),
10857
+ ...canUsePluginMethods$1.sync.map((methodName) => ({ name: methodName, isAsync: false }))
10858
+ ]);
10749
10859
  }
10750
10860
  /**
10751
10861
  * 设置活动的代码块dsl数据源
@@ -10785,17 +10895,29 @@ class CodeBlock extends BaseService {
10785
10895
  * @returns {void}
10786
10896
  */
10787
10897
  async setCodeDslById(id, codeConfig) {
10898
+ this.setCodeDslByIdSync(id, codeConfig, true);
10899
+ }
10900
+ /**
10901
+ * 为了兼容历史原因
10902
+ * 设置代码块ID和代码内容到源dsl
10903
+ * @param {Id} id 代码块id
10904
+ * @param {CodeBlockContent} codeConfig 代码块内容配置信息
10905
+ * @param {boolean} force 是否强制写入,默认true
10906
+ * @returns {void}
10907
+ */
10908
+ setCodeDslByIdSync(id, codeConfig, force = true) {
10788
10909
  const codeDsl = this.getCodeDsl();
10789
10910
  if (!codeDsl) {
10790
10911
  throw new Error("dsl中没有codeBlocks");
10791
10912
  }
10792
- const codeConfigProcessed = codeConfig;
10793
- if (codeConfig.content) {
10913
+ if (codeDsl[id] && !force)
10914
+ return;
10915
+ const codeConfigProcessed = cloneDeep(codeConfig);
10916
+ if (codeConfigProcessed.content) {
10794
10917
  const parseDSL = getConfig("parseDSL");
10795
- if (typeof codeConfig.content === "string") {
10796
- codeConfig.content = parseDSL(codeConfig.content);
10918
+ if (typeof codeConfigProcessed.content === "string") {
10919
+ codeConfigProcessed.content = parseDSL(codeConfigProcessed.content);
10797
10920
  }
10798
- codeConfigProcessed.content = codeConfig.content;
10799
10921
  }
10800
10922
  const existContent = codeDsl[id] || {};
10801
10923
  codeDsl[id] = {
@@ -10907,6 +11029,51 @@ class CodeBlock extends BaseService {
10907
11029
  return newId;
10908
11030
  return await this.getUniqueId();
10909
11031
  }
11032
+ /**
11033
+ * 复制时会带上组件关联的代码块
11034
+ * @param config 组件节点配置
11035
+ * @returns
11036
+ */
11037
+ copyWithRelated(config, collectorOptions) {
11038
+ const copyNodes = Array.isArray(config) ? config : [config];
11039
+ const copyData = {};
11040
+ if (collectorOptions && typeof collectorOptions.isTarget === "function") {
11041
+ const customTarget = new Target({
11042
+ ...collectorOptions
11043
+ });
11044
+ const coperWatcher = new Watcher();
11045
+ coperWatcher.addTarget(customTarget);
11046
+ coperWatcher.collect(copyNodes, {}, true, collectorOptions.type);
11047
+ Object.keys(customTarget.deps).forEach((nodeId) => {
11048
+ const node = editorService.getNodeById(nodeId);
11049
+ if (!node)
11050
+ return;
11051
+ customTarget.deps[nodeId].keys.forEach((key) => {
11052
+ const relateCodeId = get(node, key);
11053
+ const isExist = Object.keys(copyData).find((codeId) => codeId === relateCodeId);
11054
+ if (!isExist) {
11055
+ const relateCode = this.getCodeContentById(relateCodeId);
11056
+ if (relateCode) {
11057
+ copyData[relateCodeId] = relateCode;
11058
+ }
11059
+ }
11060
+ });
11061
+ });
11062
+ }
11063
+ storageService.setItem(COPY_CODE_STORAGE_KEY, copyData, {
11064
+ protocol: Protocol.OBJECT
11065
+ });
11066
+ }
11067
+ /**
11068
+ * 粘贴代码块
11069
+ * @returns
11070
+ */
11071
+ paste() {
11072
+ const codeDsl = storageService.getItem(COPY_CODE_STORAGE_KEY);
11073
+ Object.keys(codeDsl).forEach((codeId) => {
11074
+ this.setCodeDslByIdSync(codeId, codeDsl[codeId], false);
11075
+ });
11076
+ }
10910
11077
  resetState() {
10911
11078
  this.state.codeDsl = null;
10912
11079
  this.state.editable = true;
@@ -10951,6 +11118,140 @@ class ComponentList extends BaseService {
10951
11118
  }
10952
11119
  const componentListService = new ComponentList();
10953
11120
 
11121
+ globalThis.requestIdleCallback = globalThis.requestIdleCallback || function(cb) {
11122
+ const start = Date.now();
11123
+ return setTimeout(() => {
11124
+ cb({
11125
+ didTimeout: false,
11126
+ timeRemaining() {
11127
+ return Math.max(0, 50 - (Date.now() - start));
11128
+ }
11129
+ });
11130
+ }, 1);
11131
+ };
11132
+ class IdleTask extends EventEmitter {
11133
+ taskList = [];
11134
+ taskHandle = null;
11135
+ enqueueTask(taskHandler, taskData) {
11136
+ this.taskList.push({
11137
+ handler: taskHandler,
11138
+ data: taskData
11139
+ });
11140
+ if (!this.taskHandle) {
11141
+ this.taskHandle = globalThis.requestIdleCallback(this.runTaskQueue.bind(this), { timeout: 1e4 });
11142
+ }
11143
+ }
11144
+ on(eventName, listener) {
11145
+ return super.on(eventName, listener);
11146
+ }
11147
+ once(eventName, listener) {
11148
+ return super.once(eventName, listener);
11149
+ }
11150
+ emit(eventName, ...args) {
11151
+ return super.emit(eventName, ...args);
11152
+ }
11153
+ runTaskQueue(deadline) {
11154
+ while ((deadline.timeRemaining() > 15 || deadline.didTimeout) && this.taskList.length) {
11155
+ const task = this.taskList.shift();
11156
+ task.handler(task.data);
11157
+ }
11158
+ if (this.taskList.length) {
11159
+ this.taskHandle = globalThis.requestIdleCallback(this.runTaskQueue.bind(this), { timeout: 1e4 });
11160
+ } else {
11161
+ this.taskHandle = 0;
11162
+ this.emit("finish");
11163
+ }
11164
+ }
11165
+ }
11166
+
11167
+ const idleTask = new IdleTask();
11168
+ class Dep extends BaseService {
11169
+ watcher = new Watcher({ initialTargets: reactive({}) });
11170
+ removeTargets(type = DepTargetType.DEFAULT) {
11171
+ this.watcher.removeTargets(type);
11172
+ const targets = this.watcher.getTargets(type);
11173
+ if (!targets)
11174
+ return;
11175
+ for (const target of Object.values(targets)) {
11176
+ this.emit("remove-target", target.id);
11177
+ }
11178
+ }
11179
+ getTargets(type = DepTargetType.DEFAULT) {
11180
+ return this.watcher.getTargets(type);
11181
+ }
11182
+ getTarget(id, type = DepTargetType.DEFAULT) {
11183
+ return this.watcher.getTarget(id, type);
11184
+ }
11185
+ addTarget(target) {
11186
+ this.watcher.addTarget(target);
11187
+ this.emit("add-target", target);
11188
+ }
11189
+ removeTarget(id, type = DepTargetType.DEFAULT) {
11190
+ this.watcher.removeTarget(id, type);
11191
+ this.emit("remove-target", id);
11192
+ }
11193
+ clearTargets() {
11194
+ this.watcher.clearTargets();
11195
+ }
11196
+ collect(nodes, depExtendedData = {}, deep = false, type) {
11197
+ this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
11198
+ this.collectNode(node, target, depExtendedData, deep);
11199
+ });
11200
+ this.emit("collected", nodes, deep);
11201
+ }
11202
+ collectIdle(nodes, depExtendedData = {}, deep = false, type) {
11203
+ this.watcher.collectByCallback(nodes, type, ({ node, target }) => {
11204
+ idleTask.enqueueTask(
11205
+ ({ node: node2, deep: deep2, target: target2 }) => {
11206
+ this.collectNode(node2, target2, depExtendedData, deep2);
11207
+ },
11208
+ {
11209
+ node,
11210
+ deep,
11211
+ target
11212
+ }
11213
+ );
11214
+ });
11215
+ idleTask.once("finish", () => {
11216
+ this.emit("collected", nodes, deep);
11217
+ });
11218
+ }
11219
+ collectNode(node, target, depExtendedData = {}, deep = false) {
11220
+ if (isPage(node)) {
11221
+ Object.entries(target.deps).forEach(([depKey, dep]) => {
11222
+ if (dep.data?.pageId && dep.data.pageId === depExtendedData.pageId) {
11223
+ delete target.deps[depKey];
11224
+ }
11225
+ });
11226
+ } else {
11227
+ this.watcher.removeTargetDep(target, node);
11228
+ }
11229
+ this.watcher.collectItem(node, target, depExtendedData, deep);
11230
+ }
11231
+ clear(nodes) {
11232
+ return this.watcher.clear(nodes);
11233
+ }
11234
+ clearByType(type, nodes) {
11235
+ return this.watcher.clearByType(type, nodes);
11236
+ }
11237
+ hasTarget(id, type = DepTargetType.DEFAULT) {
11238
+ return this.watcher.hasTarget(id, type);
11239
+ }
11240
+ hasSpecifiedTypeTarget(type = DepTargetType.DEFAULT) {
11241
+ return this.watcher.hasSpecifiedTypeTarget(type);
11242
+ }
11243
+ on(eventName, listener) {
11244
+ return super.on(eventName, listener);
11245
+ }
11246
+ once(eventName, listener) {
11247
+ return super.once(eventName, listener);
11248
+ }
11249
+ emit(eventName, ...args) {
11250
+ return super.emit(eventName, ...args);
11251
+ }
11252
+ }
11253
+ const depService = new Dep();
11254
+
10954
11255
  let eventMap = reactive({});
10955
11256
  let methodMap = reactive({});
10956
11257
  class Events extends BaseService {
@@ -11248,6 +11549,7 @@ class StageOverlay extends BaseService {
11248
11549
  createStage(stageOptions = {}) {
11249
11550
  return useStage({
11250
11551
  ...stageOptions,
11552
+ zoom: 1,
11251
11553
  runtimeUrl: "",
11252
11554
  autoScrollIntoView: false,
11253
11555
  render: async (stage) => {
@@ -11569,15 +11871,11 @@ const initServiceEvents = (props, emit, { editorService, codeBlockService, dataS
11569
11871
  delete root.dataSourceCondDeps[id];
11570
11872
  }
11571
11873
  };
11572
- const depUpdateHandler = (node) => {
11573
- updateNodeWhenDataSourceChange([node]);
11574
- };
11575
11874
  const collectedHandler = (nodes) => {
11576
11875
  updateNodeWhenDataSourceChange(nodes);
11577
11876
  };
11578
11877
  depService.on("add-target", targetAddHandler);
11579
11878
  depService.on("remove-target", targetRemoveHandler);
11580
- depService.on("dep-update", depUpdateHandler);
11581
11879
  depService.on("collected", collectedHandler);
11582
11880
  const initDataSourceDepTarget = (ds) => {
11583
11881
  depService.addTarget(createDataSourceTarget(ds, reactive({})));
@@ -11599,7 +11897,9 @@ const initServiceEvents = (props, emit, { editorService, codeBlockService, dataS
11599
11897
  initDataSourceDepTarget(ds);
11600
11898
  });
11601
11899
  if (Array.isArray(value.items)) {
11602
- depService.collect(value.items, true);
11900
+ value.items.forEach((page) => {
11901
+ depService.collectIdle([page], { pageId: page.id }, true);
11902
+ });
11603
11903
  } else {
11604
11904
  depService.clear();
11605
11905
  delete value.dataSourceDeps;
@@ -11622,17 +11922,29 @@ const initServiceEvents = (props, emit, { editorService, codeBlockService, dataS
11622
11922
  emit("update:modelValue", value);
11623
11923
  }
11624
11924
  };
11925
+ const collectIdle = (nodes, deep) => {
11926
+ nodes.forEach((node) => {
11927
+ let pageId;
11928
+ if (isPage(node)) {
11929
+ pageId = node.id;
11930
+ } else {
11931
+ const info = editorService.getNodeInfo(node.id);
11932
+ pageId = info.page?.id;
11933
+ }
11934
+ depService.collectIdle([node], { pageId }, deep);
11935
+ });
11936
+ };
11625
11937
  const nodeAddHandler = (nodes) => {
11626
- depService.collect(nodes);
11938
+ collectIdle(nodes, true);
11627
11939
  };
11628
11940
  const nodeUpdateHandler = (nodes) => {
11629
- depService.collect(nodes);
11941
+ collectIdle(nodes, false);
11630
11942
  };
11631
11943
  const nodeRemoveHandler = (nodes) => {
11632
11944
  depService.clear(nodes);
11633
11945
  };
11634
11946
  const historyChangeHandler = (page) => {
11635
- depService.collect([page], true);
11947
+ depService.collectIdle([page], { pageId: page.id }, true);
11636
11948
  };
11637
11949
  editorService.on("history-change", historyChangeHandler);
11638
11950
  editorService.on("root-change", rootChangeHandler);
@@ -11659,7 +11971,9 @@ const initServiceEvents = (props, emit, { editorService, codeBlockService, dataS
11659
11971
  const root = editorService.get("root");
11660
11972
  removeDataSourceTarget(config.id);
11661
11973
  initDataSourceDepTarget(config);
11662
- depService.collect(root?.items || [], true);
11974
+ (root?.items || []).forEach((page) => {
11975
+ depService.collectIdle([page], { pageId: page.id }, true);
11976
+ });
11663
11977
  const targets = depService.getTargets(DepTargetType.DATA_SOURCE);
11664
11978
  const nodes = getNodes(Object.keys(targets[config.id].deps), root?.items);
11665
11979
  updateNodeWhenDataSourceChange(nodes);
@@ -11676,13 +11990,9 @@ const initServiceEvents = (props, emit, { editorService, codeBlockService, dataS
11676
11990
  dataSourceService.on("add", dataSourceAddHandler);
11677
11991
  dataSourceService.on("update", dataSourceUpdateHandler);
11678
11992
  dataSourceService.on("remove", dataSourceRemoveHandler);
11679
- if (props.collectorOptions && !depService.hasTarget(DepTargetType.RELATED_COMP_WHEN_COPY)) {
11680
- depService.addTarget(createRelatedCompTarget(props.collectorOptions));
11681
- }
11682
11993
  onBeforeUnmount(() => {
11683
11994
  depService.off("add-target", targetAddHandler);
11684
11995
  depService.off("remove-target", targetRemoveHandler);
11685
- depService.off("dep-update", depUpdateHandler);
11686
11996
  depService.off("collected", collectedHandler);
11687
11997
  editorService.off("history-change", historyChangeHandler);
11688
11998
  editorService.off("root-change", rootChangeHandler);
@@ -11727,7 +12037,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
11727
12037
  stageRect: {},
11728
12038
  codeOptions: {},
11729
12039
  disabledDragStart: { type: Boolean },
11730
- collectorOptions: {},
11731
12040
  guidesOptions: {},
11732
12041
  disabledMultiSelect: { type: Boolean },
11733
12042
  disabledPageFragment: { type: Boolean },
@@ -11933,4 +12242,4 @@ const index = {
11933
12242
  }
11934
12243
  };
11935
12244
 
11936
- export { CODE_DRAFT_STORAGE_KEY, COPY_STORAGE_KEY, _sfc_main$J as CodeBlockEditor, _sfc_main$l as CodeBlockList, _sfc_main$k as CodeBlockListPanel, CodeDeleteErrorType, _sfc_main$Q as CodeSelect, _sfc_main$O as CodeSelectCol, ColumnLayout, _sfc_main$b as ComponentListPanel, _sfc_main$g as ContentMenu, _sfc_main$j as DataSourceConfigPanel, _sfc_main$L as DataSourceFieldSelect, _sfc_main$M as DataSourceFields, _sfc_main$K as DataSourceInput, _sfc_main$H as DataSourceMethodSelect, _sfc_main$I as DataSourceMethods, _sfc_main$G as DataSourceMocks, _sfc_main$F as DataSourceSelect, DragType, _sfc_main$E as EventSelect, Fixed2Other, H_GUIDE_LINE_STORAGE_KEY, _sfc_main$U as Icon, KeyBindingCommand, _sfc_main$C as KeyValue, Keys, LayerOffset, _sfc_main$c as LayerPanel, Layout, _sfc_main$y as LayoutContainer, _sfc_main$B as PageFragmentSelect, _sfc_main$p as PropsPanel, _sfc_main$z as Resizer, SideItemKey, _sfc_main$y as SplitView, _sfc_main$T as TMagicCodeEditor, _sfc_main as TMagicEditor, _sfc_main$x as ToolButton, UI_SELECT_MODE_EVENT_NAME, V_GUIDE_LINE_STORAGE_KEY, advancedTabConfig, beforePaste, change2Fixed, codeBlockService, dataSourceService, debug, index as default, depService, displayTabConfig, editorService, error, eventTabConfig, eventsService, fillConfig, fixNodeLeft, fixNodePosition, generatePageName, generatePageNameByApp, getAddParent, getCascaderOptionsFromFields, getConfig, getDefaultConfig, getDisplayField, getFormConfig, getFormValue, getGuideLineFromCache, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, getPageNameList, getPositionInContainer, getRelativeStyle, historyService, info, isFixed, log, propsService, serializeConfig, setChildrenLayout, setConfig, setLayout, stageOverlayService, storageService, styleTabConfig, traverseNode, uiService, useCodeBlockEdit, useDataSourceMethod, useEditorContentHeight, useFloatBox, useStage, useWindowRect, warn };
12245
+ export { CODE_DRAFT_STORAGE_KEY, COPY_CODE_STORAGE_KEY, COPY_DS_STORAGE_KEY, COPY_STORAGE_KEY, _sfc_main$J as CodeBlockEditor, _sfc_main$l as CodeBlockList, _sfc_main$k as CodeBlockListPanel, CodeDeleteErrorType, _sfc_main$Q as CodeSelect, _sfc_main$O as CodeSelectCol, ColumnLayout, _sfc_main$b as ComponentListPanel, _sfc_main$g as ContentMenu, _sfc_main$j as DataSourceConfigPanel, _sfc_main$L as DataSourceFieldSelect, _sfc_main$M as DataSourceFields, _sfc_main$K as DataSourceInput, _sfc_main$H as DataSourceMethodSelect, _sfc_main$I as DataSourceMethods, _sfc_main$G as DataSourceMocks, _sfc_main$F as DataSourceSelect, DragType, _sfc_main$E as EventSelect, Fixed2Other, _sfc_main$N as FloatingBox, H_GUIDE_LINE_STORAGE_KEY, _sfc_main$U as Icon, KeyBindingCommand, _sfc_main$C as KeyValue, Keys, LayerOffset, _sfc_main$c as LayerPanel, Layout, _sfc_main$y as LayoutContainer, _sfc_main$B as PageFragmentSelect, _sfc_main$p as PropsPanel, _sfc_main$z as Resizer, SideItemKey, _sfc_main$y as SplitView, _sfc_main$T as TMagicCodeEditor, _sfc_main as TMagicEditor, _sfc_main$x as ToolButton, UI_SELECT_MODE_EVENT_NAME, V_GUIDE_LINE_STORAGE_KEY, advancedTabConfig, beforePaste, change2Fixed, codeBlockService, dataSourceService, debug, index as default, depService, displayTabConfig, editorService, error, eventTabConfig, eventsService, fillConfig, fixNodeLeft, fixNodePosition, generatePageName, generatePageNameByApp, getAddParent, getCascaderOptionsFromFields, getConfig, getDefaultConfig, getDisplayField, getFormConfig, getFormValue, getGuideLineFromCache, getInitPositionStyle, getNodeIndex, getPageFragmentList, getPageList, getPageNameList, getPositionInContainer, getRelativeStyle, historyService, info, isFixed, log, propsService, serializeConfig, setChildrenLayout, setConfig, setLayout, stageOverlayService, storageService, styleTabConfig, traverseNode, uiService, useCodeBlockEdit, useDataSourceMethod, useEditorContentHeight, useFloatBox, useStage, useWindowRect, warn };