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