@tmagic/editor 1.4.5 → 1.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tmagic-editor.js +2329 -2205
- package/dist/tmagic-editor.umd.cjs +2344 -2217
- package/package.json +19 -14
- package/src/editorProps.ts +5 -1
- package/src/hooks/use-code-block-edit.ts +0 -2
- package/src/hooks/use-stage.ts +1 -1
- package/src/index.ts +1 -0
- package/src/initService.ts +12 -2
- package/src/services/codeBlock.ts +77 -9
- package/src/services/dataSource.ts +53 -4
- package/src/services/props.ts +10 -5
- package/src/services/stageOverlay.ts +1 -0
- package/src/type.ts +1 -0
- package/src/utils/editor.ts +2 -0
- package/types/editorProps.d.ts +5 -1
- package/types/index.d.ts +1 -0
- package/types/layouts/PropsPanel.vue.d.ts +24 -24
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +1 -1
- package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +1 -1
- package/types/services/codeBlock.d.ts +22 -2
- package/types/services/dataSource.d.ts +12 -1
- package/types/type.d.ts +1 -0
- package/types/utils/editor.d.ts +2 -0
|
@@ -510,388 +510,94 @@
|
|
|
510
510
|
}
|
|
511
511
|
});
|
|
512
512
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
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
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
{
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
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
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
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
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
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 {
|
|
@@ -967,590 +673,500 @@
|
|
|
967
673
|
}
|
|
968
674
|
}
|
|
969
675
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
"
|
|
975
|
-
"getFormValue",
|
|
976
|
-
"setFormValue",
|
|
977
|
-
"getFormEvent",
|
|
978
|
-
"setFormEvent",
|
|
979
|
-
"getFormMethod",
|
|
980
|
-
"setFormMethod",
|
|
981
|
-
"add",
|
|
982
|
-
"update",
|
|
983
|
-
"remove",
|
|
984
|
-
"createId"
|
|
985
|
-
]
|
|
986
|
-
};
|
|
987
|
-
class DataSource extends BaseService {
|
|
988
|
-
state = vue.reactive({
|
|
989
|
-
datasourceTypeList: [],
|
|
990
|
-
dataSources: [],
|
|
991
|
-
editable: true,
|
|
992
|
-
configs: {},
|
|
993
|
-
values: {},
|
|
994
|
-
events: {},
|
|
995
|
-
methods: {}
|
|
996
|
-
});
|
|
997
|
-
constructor() {
|
|
998
|
-
super(canUsePluginMethods$6.sync.map((methodName) => ({ name: methodName, isAsync: false })));
|
|
676
|
+
class Dep extends BaseService {
|
|
677
|
+
watcher = new dep.Watcher({ initialTargets: vue.reactive({}) });
|
|
678
|
+
removeTargets(type = dep.DepTargetType.DEFAULT) {
|
|
679
|
+
this.watcher.removeTargets(type);
|
|
680
|
+
this.emit("remove-target");
|
|
999
681
|
}
|
|
1000
|
-
|
|
1001
|
-
this.
|
|
682
|
+
getTargets(type = dep.DepTargetType.DEFAULT) {
|
|
683
|
+
return this.watcher.getTargets(type);
|
|
1002
684
|
}
|
|
1003
|
-
|
|
1004
|
-
return this.
|
|
685
|
+
getTarget(id, type = dep.DepTargetType.DEFAULT) {
|
|
686
|
+
return this.watcher.getTarget(id, type);
|
|
1005
687
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
688
|
+
addTarget(target) {
|
|
689
|
+
this.watcher.addTarget(target);
|
|
690
|
+
this.emit("add-target", target);
|
|
1008
691
|
}
|
|
1009
|
-
|
|
1010
|
-
this.
|
|
692
|
+
removeTarget(id, type = dep.DepTargetType.DEFAULT) {
|
|
693
|
+
this.watcher.removeTarget(id, type);
|
|
694
|
+
this.emit("remove-target");
|
|
1011
695
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
696
|
+
clearTargets() {
|
|
697
|
+
this.watcher.clearTargets();
|
|
1014
698
|
}
|
|
1015
|
-
|
|
1016
|
-
this.
|
|
699
|
+
collect(nodes, deep = false, type) {
|
|
700
|
+
this.watcher.collect(nodes, deep, type);
|
|
701
|
+
this.emit("collected", nodes, deep);
|
|
1017
702
|
}
|
|
1018
|
-
|
|
1019
|
-
return this.
|
|
703
|
+
clear(nodes) {
|
|
704
|
+
return this.watcher.clear(nodes);
|
|
1020
705
|
}
|
|
1021
|
-
|
|
1022
|
-
this.
|
|
706
|
+
clearByType(type, nodes) {
|
|
707
|
+
return this.watcher.clearByType(type, nodes);
|
|
1023
708
|
}
|
|
1024
|
-
|
|
1025
|
-
return this.
|
|
709
|
+
hasTarget(id, type = dep.DepTargetType.DEFAULT) {
|
|
710
|
+
return this.watcher.hasTarget(id, type);
|
|
1026
711
|
}
|
|
1027
|
-
|
|
1028
|
-
this.
|
|
712
|
+
hasSpecifiedTypeTarget(type = dep.DepTargetType.DEFAULT) {
|
|
713
|
+
return this.watcher.hasSpecifiedTypeTarget(type);
|
|
1029
714
|
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
715
|
+
}
|
|
716
|
+
const depService = new Dep();
|
|
717
|
+
|
|
718
|
+
const canUsePluginMethods$6 = {
|
|
719
|
+
async: [
|
|
720
|
+
"setPropsConfig",
|
|
721
|
+
"getPropsConfig",
|
|
722
|
+
"setPropsValue",
|
|
723
|
+
"getPropsValue",
|
|
724
|
+
"fillConfig",
|
|
725
|
+
"getDefaultPropsValue"
|
|
726
|
+
],
|
|
727
|
+
sync: ["createId", "setNewItemId"]
|
|
728
|
+
};
|
|
729
|
+
class Props extends BaseService {
|
|
730
|
+
state = vue.reactive({
|
|
731
|
+
propsConfigMap: {},
|
|
732
|
+
propsValueMap: {},
|
|
733
|
+
relateIdMap: {}
|
|
734
|
+
});
|
|
735
|
+
constructor() {
|
|
736
|
+
super([
|
|
737
|
+
...canUsePluginMethods$6.async.map((methodName) => ({ name: methodName, isAsync: true })),
|
|
738
|
+
...canUsePluginMethods$6.sync.map((methodName) => ({ name: methodName, isAsync: false }))
|
|
739
|
+
]);
|
|
740
|
+
}
|
|
741
|
+
setPropsConfigs(configs) {
|
|
742
|
+
Object.keys(configs).forEach((type) => {
|
|
743
|
+
this.setPropsConfig(utils.toLine(type), configs[type]);
|
|
744
|
+
});
|
|
745
|
+
this.emit("props-configs-change");
|
|
746
|
+
}
|
|
747
|
+
async fillConfig(config, labelWidth) {
|
|
748
|
+
return fillConfig(config, typeof labelWidth !== "function" ? labelWidth : "80px");
|
|
749
|
+
}
|
|
750
|
+
async setPropsConfig(type, config) {
|
|
751
|
+
this.state.propsConfigMap[utils.toLine(type)] = await this.fillConfig(Array.isArray(config) ? config : [config]);
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* 获取指点类型的组件属性表单配置
|
|
755
|
+
* @param type 组件类型
|
|
756
|
+
* @returns 组件属性表单配置
|
|
757
|
+
*/
|
|
758
|
+
async getPropsConfig(type) {
|
|
759
|
+
if (type === "area") {
|
|
760
|
+
return await this.getPropsConfig("button");
|
|
761
|
+
}
|
|
762
|
+
return lodashEs.cloneDeep(this.state.propsConfigMap[utils.toLine(type)] || await this.fillConfig([]));
|
|
763
|
+
}
|
|
764
|
+
setPropsValues(values) {
|
|
765
|
+
Object.keys(values).forEach((type) => {
|
|
766
|
+
this.setPropsValue(utils.toLine(type), values[type]);
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* 为指点类型组件设置组件初始值
|
|
771
|
+
* @param type 组件类型
|
|
772
|
+
* @param value 组件初始值
|
|
773
|
+
*/
|
|
774
|
+
async setPropsValue(type, value) {
|
|
775
|
+
this.state.propsValueMap[utils.toLine(type)] = value;
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* 获取指定类型的组件初始值
|
|
779
|
+
* @param type 组件类型
|
|
780
|
+
* @returns 组件初始值
|
|
781
|
+
*/
|
|
782
|
+
async getPropsValue(componentType, { inputEvent, ...defaultValue } = {}) {
|
|
783
|
+
const type = utils.toLine(componentType);
|
|
784
|
+
if (type === "area") {
|
|
785
|
+
const value = await this.getPropsValue("button");
|
|
786
|
+
value.className = "action-area";
|
|
787
|
+
value.text = "";
|
|
788
|
+
if (value.style) {
|
|
789
|
+
value.style.backgroundColor = "rgba(255, 255, 255, 0)";
|
|
790
|
+
}
|
|
791
|
+
return value;
|
|
792
|
+
}
|
|
793
|
+
const id = this.createId(type);
|
|
794
|
+
const defaultPropsValue = this.getDefaultPropsValue(type);
|
|
795
|
+
const data = this.setNewItemId(
|
|
796
|
+
lodashEs.cloneDeep({
|
|
797
|
+
type,
|
|
798
|
+
...defaultValue
|
|
799
|
+
})
|
|
800
|
+
);
|
|
801
|
+
return {
|
|
802
|
+
id,
|
|
803
|
+
...defaultPropsValue,
|
|
804
|
+
...lodashEs.mergeWith({}, lodashEs.cloneDeep(this.state.propsValueMap[type] || {}), data)
|
|
1034
805
|
};
|
|
1035
|
-
this.get("dataSources").push(newConfig);
|
|
1036
|
-
this.emit("add", newConfig);
|
|
1037
|
-
return newConfig;
|
|
1038
806
|
}
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
807
|
+
createId(type) {
|
|
808
|
+
return `${type}_${utils.guid()}`;
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* 将组件与组件的子元素配置中的id都设置成一个新的ID
|
|
812
|
+
* 如果没有相同ID并且force为false则保持不变
|
|
813
|
+
* @param {Object} config 组件配置
|
|
814
|
+
* @param {Boolean} force 是否强制设置新的ID
|
|
815
|
+
*/
|
|
816
|
+
/* eslint no-param-reassign: ["error", { "props": false }] */
|
|
817
|
+
setNewItemId(config, force = true) {
|
|
818
|
+
if (force || editorService.getNodeById(config.id)) {
|
|
819
|
+
const newId = this.createId(config.type || "component");
|
|
820
|
+
this.setRelateId(config.id, newId);
|
|
821
|
+
config.id = newId;
|
|
822
|
+
}
|
|
823
|
+
if (config.items && Array.isArray(config.items)) {
|
|
824
|
+
for (const item of config.items) {
|
|
825
|
+
this.setNewItemId(item);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
1044
828
|
return config;
|
|
1045
829
|
}
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
830
|
+
/**
|
|
831
|
+
* 获取默认属性配置
|
|
832
|
+
* @param type 组件类型
|
|
833
|
+
* @returns Object
|
|
834
|
+
*/
|
|
835
|
+
getDefaultPropsValue(type) {
|
|
836
|
+
return ["page", "container"].includes(type) ? {
|
|
837
|
+
type,
|
|
838
|
+
layout: "absolute",
|
|
839
|
+
style: {},
|
|
840
|
+
name: type,
|
|
841
|
+
items: []
|
|
842
|
+
} : {
|
|
843
|
+
type,
|
|
844
|
+
style: {},
|
|
845
|
+
name: type
|
|
846
|
+
};
|
|
1051
847
|
}
|
|
1052
|
-
|
|
1053
|
-
|
|
848
|
+
resetState() {
|
|
849
|
+
this.state.propsConfigMap = {};
|
|
850
|
+
this.state.propsValueMap = {};
|
|
1054
851
|
}
|
|
1055
|
-
|
|
1056
|
-
|
|
852
|
+
/**
|
|
853
|
+
* 替换关联ID
|
|
854
|
+
* @param originConfigs 原组件配置
|
|
855
|
+
* @param targetConfigs 待替换的组件配置
|
|
856
|
+
*/
|
|
857
|
+
replaceRelateId(originConfigs, targetConfigs) {
|
|
858
|
+
const relateIdMap = this.getRelateIdMap();
|
|
859
|
+
if (Object.keys(relateIdMap).length === 0)
|
|
860
|
+
return;
|
|
861
|
+
depService.clearByType(dep.DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
862
|
+
depService.collect(originConfigs, true, dep.DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
863
|
+
const target = depService.getTarget(dep.DepTargetType.RELATED_COMP_WHEN_COPY, dep.DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
864
|
+
if (!target)
|
|
865
|
+
return;
|
|
866
|
+
originConfigs.forEach((config) => {
|
|
867
|
+
const newId = relateIdMap[config.id];
|
|
868
|
+
const path = utils.getNodePath(newId, targetConfigs);
|
|
869
|
+
const targetConfig = path[path.length - 1];
|
|
870
|
+
if (!targetConfig)
|
|
871
|
+
return;
|
|
872
|
+
target.deps[config.id]?.keys?.forEach((fullKey) => {
|
|
873
|
+
const relateOriginId = utils.getValueByKeyPath(fullKey, config);
|
|
874
|
+
const relateTargetId = relateIdMap[relateOriginId];
|
|
875
|
+
if (!relateTargetId)
|
|
876
|
+
return;
|
|
877
|
+
utils.setValueByKeyPath(fullKey, relateTargetId, targetConfig);
|
|
878
|
+
});
|
|
879
|
+
if (config.items && Array.isArray(config.items)) {
|
|
880
|
+
this.replaceRelateId(config.items, targetConfigs);
|
|
881
|
+
}
|
|
882
|
+
});
|
|
1057
883
|
}
|
|
1058
|
-
|
|
1059
|
-
|
|
884
|
+
/**
|
|
885
|
+
* 清除setNewItemId前后映射关系
|
|
886
|
+
*/
|
|
887
|
+
clearRelateId() {
|
|
888
|
+
this.state.relateIdMap = {};
|
|
1060
889
|
}
|
|
1061
890
|
destroy() {
|
|
1062
|
-
this.removeAllListeners();
|
|
1063
891
|
this.resetState();
|
|
892
|
+
this.removeAllListeners();
|
|
1064
893
|
this.removeAllPlugins();
|
|
1065
894
|
}
|
|
1066
895
|
usePlugin(options) {
|
|
1067
896
|
super.usePlugin(options);
|
|
1068
897
|
}
|
|
898
|
+
/**
|
|
899
|
+
* 获取setNewItemId前后映射关系
|
|
900
|
+
* @param oldId 原组件ID
|
|
901
|
+
* @returns 新旧ID映射
|
|
902
|
+
*/
|
|
903
|
+
getRelateIdMap() {
|
|
904
|
+
return this.state.relateIdMap;
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* 记录setNewItemId前后映射关系
|
|
908
|
+
* @param oldId 原组件ID
|
|
909
|
+
* @param newId 分配的新ID
|
|
910
|
+
*/
|
|
911
|
+
setRelateId(oldId, newId) {
|
|
912
|
+
this.state.relateIdMap[oldId] = newId;
|
|
913
|
+
}
|
|
1069
914
|
}
|
|
1070
|
-
const
|
|
915
|
+
const propsService = new Props();
|
|
1071
916
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
{
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
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
|
-
]
|
|
917
|
+
class UndoRedo {
|
|
918
|
+
elementList;
|
|
919
|
+
listCursor;
|
|
920
|
+
listMaxSize;
|
|
921
|
+
constructor(listMaxSize = 20) {
|
|
922
|
+
const minListMaxSize = 2;
|
|
923
|
+
this.elementList = [];
|
|
924
|
+
this.listCursor = 0;
|
|
925
|
+
this.listMaxSize = listMaxSize > minListMaxSize ? listMaxSize : minListMaxSize;
|
|
926
|
+
}
|
|
927
|
+
pushElement(element) {
|
|
928
|
+
this.elementList.splice(this.listCursor, this.elementList.length - this.listCursor, lodashEs.cloneDeep(element));
|
|
929
|
+
this.listCursor += 1;
|
|
930
|
+
if (this.elementList.length > this.listMaxSize) {
|
|
931
|
+
this.elementList.shift();
|
|
932
|
+
this.listCursor -= 1;
|
|
1491
933
|
}
|
|
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
934
|
}
|
|
1527
|
-
|
|
935
|
+
canUndo() {
|
|
936
|
+
return this.listCursor > 1;
|
|
937
|
+
}
|
|
938
|
+
// 返回undo后的当前元素
|
|
939
|
+
undo() {
|
|
940
|
+
if (!this.canUndo()) {
|
|
941
|
+
return null;
|
|
942
|
+
}
|
|
943
|
+
this.listCursor -= 1;
|
|
944
|
+
return this.getCurrentElement();
|
|
945
|
+
}
|
|
946
|
+
canRedo() {
|
|
947
|
+
return this.elementList.length > this.listCursor;
|
|
948
|
+
}
|
|
949
|
+
// 返回redo后的当前元素
|
|
950
|
+
redo() {
|
|
951
|
+
if (!this.canRedo()) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
this.listCursor += 1;
|
|
955
|
+
return this.getCurrentElement();
|
|
956
|
+
}
|
|
957
|
+
getCurrentElement() {
|
|
958
|
+
if (this.listCursor < 1) {
|
|
959
|
+
return null;
|
|
960
|
+
}
|
|
961
|
+
return lodashEs.cloneDeep(this.elementList[this.listCursor - 1]);
|
|
962
|
+
}
|
|
963
|
+
}
|
|
1528
964
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
965
|
+
class History extends BaseService {
|
|
966
|
+
state = vue.reactive({
|
|
967
|
+
pageSteps: {},
|
|
968
|
+
pageId: void 0,
|
|
969
|
+
canRedo: false,
|
|
970
|
+
canUndo: false
|
|
971
|
+
});
|
|
972
|
+
constructor() {
|
|
973
|
+
super([]);
|
|
974
|
+
this.on("change", this.setCanUndoRedo);
|
|
975
|
+
}
|
|
976
|
+
reset() {
|
|
977
|
+
this.state.pageSteps = {};
|
|
978
|
+
this.resetPage();
|
|
979
|
+
}
|
|
980
|
+
resetPage() {
|
|
981
|
+
this.state.pageId = void 0;
|
|
982
|
+
this.state.canRedo = false;
|
|
983
|
+
this.state.canUndo = false;
|
|
984
|
+
}
|
|
985
|
+
changePage(page) {
|
|
986
|
+
if (!page)
|
|
987
|
+
return;
|
|
988
|
+
this.state.pageId = page.id;
|
|
989
|
+
if (!this.state.pageSteps[this.state.pageId]) {
|
|
990
|
+
const undoRedo = new UndoRedo();
|
|
991
|
+
undoRedo.pushElement({
|
|
992
|
+
data: page,
|
|
993
|
+
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
994
|
+
nodeId: page.id
|
|
995
|
+
});
|
|
996
|
+
this.state.pageSteps[this.state.pageId] = undoRedo;
|
|
997
|
+
}
|
|
998
|
+
this.setCanUndoRedo();
|
|
999
|
+
this.emit("page-change", this.state.pageSteps[this.state.pageId]);
|
|
1000
|
+
}
|
|
1001
|
+
resetState() {
|
|
1002
|
+
this.state.pageId = void 0;
|
|
1003
|
+
this.state.pageSteps = {};
|
|
1004
|
+
this.state.canRedo = false;
|
|
1005
|
+
this.state.canUndo = false;
|
|
1006
|
+
}
|
|
1007
|
+
push(state) {
|
|
1008
|
+
const undoRedo = this.getUndoRedo();
|
|
1009
|
+
if (!undoRedo)
|
|
1010
|
+
return null;
|
|
1011
|
+
undoRedo.pushElement(state);
|
|
1012
|
+
this.emit("change", state);
|
|
1013
|
+
return state;
|
|
1014
|
+
}
|
|
1015
|
+
undo() {
|
|
1016
|
+
const undoRedo = this.getUndoRedo();
|
|
1017
|
+
if (!undoRedo)
|
|
1018
|
+
return null;
|
|
1019
|
+
const state = undoRedo.undo();
|
|
1020
|
+
this.emit("change", state);
|
|
1021
|
+
return state;
|
|
1022
|
+
}
|
|
1023
|
+
redo() {
|
|
1024
|
+
const undoRedo = this.getUndoRedo();
|
|
1025
|
+
if (!undoRedo)
|
|
1026
|
+
return null;
|
|
1027
|
+
const state = undoRedo.redo();
|
|
1028
|
+
this.emit("change", state);
|
|
1029
|
+
return state;
|
|
1030
|
+
}
|
|
1031
|
+
destroy() {
|
|
1032
|
+
this.resetState();
|
|
1033
|
+
this.removeAllListeners();
|
|
1034
|
+
this.removeAllPlugins();
|
|
1035
|
+
}
|
|
1036
|
+
getUndoRedo() {
|
|
1037
|
+
if (!this.state.pageId)
|
|
1038
|
+
return null;
|
|
1039
|
+
return this.state.pageSteps[this.state.pageId];
|
|
1040
|
+
}
|
|
1041
|
+
setCanUndoRedo() {
|
|
1042
|
+
const undoRedo = this.getUndoRedo();
|
|
1043
|
+
this.state.canRedo = undoRedo?.canRedo() || false;
|
|
1044
|
+
this.state.canUndo = undoRedo?.canUndo() || false;
|
|
1532
1045
|
}
|
|
1046
|
+
}
|
|
1047
|
+
const historyService = new History();
|
|
1048
|
+
|
|
1049
|
+
var Protocol = /* @__PURE__ */ ((Protocol2) => {
|
|
1050
|
+
Protocol2["OBJECT"] = "object";
|
|
1051
|
+
Protocol2["JSON"] = "json";
|
|
1052
|
+
Protocol2["STRING"] = "string";
|
|
1053
|
+
Protocol2["NUMBER"] = "number";
|
|
1054
|
+
Protocol2["BOOLEAN"] = "boolean";
|
|
1055
|
+
return Protocol2;
|
|
1056
|
+
})(Protocol || {});
|
|
1057
|
+
const canUsePluginMethods$5 = {
|
|
1058
|
+
async: [],
|
|
1059
|
+
sync: ["getStorage", "getNamespace", "clear", "getItem", "removeItem", "setItem"]
|
|
1533
1060
|
};
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1061
|
+
class WebStorage extends BaseService {
|
|
1062
|
+
storage = globalThis.localStorage;
|
|
1063
|
+
namespace = "tmagic";
|
|
1064
|
+
constructor() {
|
|
1065
|
+
super(canUsePluginMethods$5.sync.map((methodName) => ({ name: methodName, isAsync: false })));
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* 获取数据存储对象,可以通过
|
|
1069
|
+
* const storageService = new StorageService();
|
|
1070
|
+
* storageService.usePlugin({
|
|
1071
|
+
* // 替换存储对象为 sessionStorage
|
|
1072
|
+
* async afterGetStorage(): Promise<Storage> {
|
|
1073
|
+
* return window.sessionStorage;
|
|
1074
|
+
* },
|
|
1075
|
+
* });
|
|
1076
|
+
*/
|
|
1077
|
+
getStorage() {
|
|
1078
|
+
return this.storage;
|
|
1079
|
+
}
|
|
1080
|
+
getNamespace() {
|
|
1081
|
+
return this.namespace;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* 清理,支持storageService.usePlugin
|
|
1085
|
+
*/
|
|
1086
|
+
clear() {
|
|
1087
|
+
const storage = this.getStorage();
|
|
1088
|
+
storage.clear();
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* 获取存储项,支持storageService.usePlugin
|
|
1092
|
+
*/
|
|
1093
|
+
getItem(key, options = {}) {
|
|
1094
|
+
const storage = this.getStorage();
|
|
1095
|
+
const namespace = this.getNamespace();
|
|
1096
|
+
const { protocol = options.protocol, item } = this.getValueAndProtocol(
|
|
1097
|
+
storage.getItem(`${options.namespace || namespace}:${key}`)
|
|
1098
|
+
);
|
|
1099
|
+
if (item === null)
|
|
1100
|
+
return null;
|
|
1101
|
+
switch (protocol) {
|
|
1102
|
+
case "object" /* OBJECT */:
|
|
1103
|
+
return getConfig("parseDSL")(`(${item})`);
|
|
1104
|
+
case "json" /* JSON */:
|
|
1105
|
+
return JSON.parse(item);
|
|
1106
|
+
case "number" /* NUMBER */:
|
|
1107
|
+
return Number(item);
|
|
1108
|
+
case "boolean" /* BOOLEAN */:
|
|
1109
|
+
return Boolean(item);
|
|
1110
|
+
default:
|
|
1111
|
+
return item;
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
/**
|
|
1115
|
+
* 获取指定索引位置的key
|
|
1116
|
+
*/
|
|
1117
|
+
key(index) {
|
|
1118
|
+
const storage = this.getStorage();
|
|
1119
|
+
return storage.key(index);
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* 移除存储项,支持storageService.usePlugin
|
|
1123
|
+
*/
|
|
1124
|
+
removeItem(key, options = {}) {
|
|
1125
|
+
const storage = this.getStorage();
|
|
1126
|
+
const namespace = this.getNamespace();
|
|
1127
|
+
storage.removeItem(`${options.namespace || namespace}:${key}`);
|
|
1537
1128
|
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1129
|
+
/**
|
|
1130
|
+
* 设置存储项,支持storageService.usePlugin
|
|
1131
|
+
*/
|
|
1132
|
+
setItem(key, value, options = {}) {
|
|
1133
|
+
const storage = this.getStorage();
|
|
1134
|
+
const namespace = this.getNamespace();
|
|
1135
|
+
let item = value;
|
|
1136
|
+
const protocol = options.protocol ? `${options.protocol}:` : "";
|
|
1137
|
+
if (typeof value === "string" /* STRING */ || typeof value === "number" /* NUMBER */) {
|
|
1138
|
+
item = `${protocol}${value}`;
|
|
1139
|
+
} else {
|
|
1140
|
+
item = `${protocol}${serialize(value)}`;
|
|
1141
|
+
}
|
|
1142
|
+
storage.setItem(`${options.namespace || namespace}:${key}`, item);
|
|
1542
1143
|
}
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
console.debug("magic editor: ", ...args);
|
|
1144
|
+
destroy() {
|
|
1145
|
+
this.removeAllListeners();
|
|
1146
|
+
this.removeAllPlugins();
|
|
1547
1147
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
if (process.env.NODE_ENV === "development") {
|
|
1551
|
-
console.error("magic editor: ", ...args);
|
|
1148
|
+
usePlugin(options) {
|
|
1149
|
+
super.usePlugin(options);
|
|
1552
1150
|
}
|
|
1553
|
-
|
|
1151
|
+
getValueAndProtocol(value) {
|
|
1152
|
+
let protocol = "";
|
|
1153
|
+
if (value === null) {
|
|
1154
|
+
return {
|
|
1155
|
+
item: value,
|
|
1156
|
+
protocol
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
const item = value.replace(new RegExp(`^(${Object.values(Protocol).join("|")})(:)(.+)`), (_$0, $1, _$2, $3) => {
|
|
1160
|
+
protocol = $1;
|
|
1161
|
+
return $3;
|
|
1162
|
+
});
|
|
1163
|
+
return {
|
|
1164
|
+
protocol,
|
|
1165
|
+
item
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
const storageService = new WebStorage();
|
|
1554
1170
|
|
|
1555
1171
|
var ColumnLayout = /* @__PURE__ */ ((ColumnLayout2) => {
|
|
1556
1172
|
ColumnLayout2["LEFT"] = "left";
|
|
@@ -1619,6 +1235,8 @@
|
|
|
1619
1235
|
const UI_SELECT_MODE_EVENT_NAME = "ui-select";
|
|
1620
1236
|
|
|
1621
1237
|
const COPY_STORAGE_KEY = "$MagicEditorCopyData";
|
|
1238
|
+
const COPY_CODE_STORAGE_KEY = "$MagicEditorCopyCode";
|
|
1239
|
+
const COPY_DS_STORAGE_KEY = "$MagicEditorCopyDataSource";
|
|
1622
1240
|
const getPageList = (root) => {
|
|
1623
1241
|
if (!root)
|
|
1624
1242
|
return [];
|
|
@@ -1805,1421 +1423,1855 @@
|
|
|
1805
1423
|
}
|
|
1806
1424
|
};
|
|
1807
1425
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1426
|
+
const beforePaste = (position, config) => {
|
|
1427
|
+
if (!config[0]?.style)
|
|
1428
|
+
return config;
|
|
1429
|
+
const curNode = editorService.get("node");
|
|
1430
|
+
const { left: referenceLeft, top: referenceTop } = config[0].style;
|
|
1431
|
+
const pasteConfigs = config.map((configItem) => {
|
|
1432
|
+
const { offsetX = 0, offsetY = 0, ...positionClone } = position;
|
|
1433
|
+
let pastePosition = positionClone;
|
|
1434
|
+
if (!lodashEs.isEmpty(pastePosition) && curNode?.items) {
|
|
1435
|
+
pastePosition = getPositionInContainer(pastePosition, curNode.id);
|
|
1436
|
+
}
|
|
1437
|
+
if (pastePosition.left && configItem.style?.left) {
|
|
1438
|
+
pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
|
|
1439
|
+
}
|
|
1440
|
+
if (pastePosition.top && configItem.style?.top) {
|
|
1441
|
+
pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
|
|
1442
|
+
}
|
|
1443
|
+
const pasteConfig = propsService.setNewItemId(configItem, false);
|
|
1444
|
+
if (pasteConfig.style) {
|
|
1445
|
+
const { left, top } = pasteConfig.style;
|
|
1446
|
+
if (typeof left === "number" || !!left && !isNaN(Number(left))) {
|
|
1447
|
+
pasteConfig.style.left = Number(left) + offsetX;
|
|
1448
|
+
}
|
|
1449
|
+
if (typeof top === "number" || !!top && !isNaN(Number(top))) {
|
|
1450
|
+
pasteConfig.style.top = Number(top) + offsetY;
|
|
1451
|
+
}
|
|
1452
|
+
pasteConfig.style = {
|
|
1453
|
+
...pasteConfig.style,
|
|
1454
|
+
...pastePosition
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
const root = editorService.get("root");
|
|
1458
|
+
if ((utils.isPage(pasteConfig) || utils.isPageFragment(pasteConfig)) && root) {
|
|
1459
|
+
pasteConfig.name = generatePageNameByApp(root, utils.isPage(pasteConfig) ? schema.NodeType.PAGE : schema.NodeType.PAGE_FRAGMENT);
|
|
1460
|
+
}
|
|
1461
|
+
return pasteConfig;
|
|
1462
|
+
});
|
|
1463
|
+
return pasteConfigs;
|
|
1464
|
+
};
|
|
1465
|
+
const getPositionInContainer = (position = {}, id) => {
|
|
1466
|
+
let { left = 0, top = 0 } = position;
|
|
1467
|
+
const parentEl = editorService.get("stage")?.renderer?.contentWindow?.document.getElementById(`${id}`);
|
|
1468
|
+
const parentElRect = parentEl?.getBoundingClientRect();
|
|
1469
|
+
left = left - (parentElRect?.left || 0);
|
|
1470
|
+
top = top - (parentElRect?.top || 0);
|
|
1471
|
+
return {
|
|
1472
|
+
left,
|
|
1473
|
+
top
|
|
1474
|
+
};
|
|
1475
|
+
};
|
|
1476
|
+
const getAddParent = (node) => {
|
|
1477
|
+
const curNode = editorService.get("node");
|
|
1478
|
+
let parentNode;
|
|
1479
|
+
if (utils.isPage(node)) {
|
|
1480
|
+
parentNode = editorService.get("root");
|
|
1481
|
+
} else if (curNode?.items) {
|
|
1482
|
+
parentNode = curNode;
|
|
1483
|
+
} else if (curNode?.id) {
|
|
1484
|
+
parentNode = editorService.getParentById(curNode.id, false);
|
|
1813
1485
|
}
|
|
1814
|
-
|
|
1815
|
-
|
|
1486
|
+
return parentNode;
|
|
1487
|
+
};
|
|
1488
|
+
const getDefaultConfig = async (addNode, parentNode) => {
|
|
1489
|
+
const { type, inputEvent, ...config } = addNode;
|
|
1490
|
+
const layout = await editorService.getLayout(vue.toRaw(parentNode), addNode);
|
|
1491
|
+
const newNode = { ...vue.toRaw(await propsService.getPropsValue(type, config)) };
|
|
1492
|
+
newNode.style = getInitPositionStyle(newNode.style, layout);
|
|
1493
|
+
return newNode;
|
|
1494
|
+
};
|
|
1495
|
+
|
|
1496
|
+
const canUsePluginMethods$4 = {
|
|
1497
|
+
async: [
|
|
1498
|
+
"getLayout",
|
|
1499
|
+
"highlight",
|
|
1500
|
+
"select",
|
|
1501
|
+
"multiSelect",
|
|
1502
|
+
"doAdd",
|
|
1503
|
+
"add",
|
|
1504
|
+
"doRemove",
|
|
1505
|
+
"remove",
|
|
1506
|
+
"doUpdate",
|
|
1507
|
+
"update",
|
|
1508
|
+
"sort",
|
|
1509
|
+
"copy",
|
|
1510
|
+
"paste",
|
|
1511
|
+
"doPaste",
|
|
1512
|
+
"doAlignCenter",
|
|
1513
|
+
"alignCenter",
|
|
1514
|
+
"moveLayer",
|
|
1515
|
+
"moveToContainer",
|
|
1516
|
+
"dragTo",
|
|
1517
|
+
"undo",
|
|
1518
|
+
"redo",
|
|
1519
|
+
"move"
|
|
1520
|
+
],
|
|
1521
|
+
sync: []
|
|
1522
|
+
};
|
|
1523
|
+
class Editor extends BaseService {
|
|
1524
|
+
state = vue.reactive({
|
|
1525
|
+
root: null,
|
|
1526
|
+
page: null,
|
|
1527
|
+
parent: null,
|
|
1528
|
+
node: null,
|
|
1529
|
+
nodes: [],
|
|
1530
|
+
stage: null,
|
|
1531
|
+
stageLoading: true,
|
|
1532
|
+
highlightNode: null,
|
|
1533
|
+
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
1534
|
+
pageLength: 0,
|
|
1535
|
+
pageFragmentLength: 0,
|
|
1536
|
+
disabledMultiSelect: false
|
|
1537
|
+
});
|
|
1538
|
+
isHistoryStateChange = false;
|
|
1539
|
+
constructor() {
|
|
1540
|
+
super(
|
|
1541
|
+
canUsePluginMethods$4.async.map((methodName) => ({ name: methodName, isAsync: true })),
|
|
1542
|
+
// 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
|
|
1543
|
+
["select", "update", "moveLayer"]
|
|
1544
|
+
);
|
|
1816
1545
|
}
|
|
1817
|
-
|
|
1818
|
-
|
|
1546
|
+
/**
|
|
1547
|
+
* 设置当前指点节点配置
|
|
1548
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
1549
|
+
* @param value MNode
|
|
1550
|
+
*/
|
|
1551
|
+
set(name, value) {
|
|
1552
|
+
const preValue = this.state[name];
|
|
1553
|
+
this.state[name] = value;
|
|
1554
|
+
if (name === "nodes" && Array.isArray(value)) {
|
|
1555
|
+
this.set("node", value[0]);
|
|
1556
|
+
}
|
|
1557
|
+
if (name === "root") {
|
|
1558
|
+
if (Array.isArray(value)) {
|
|
1559
|
+
throw new Error("root 不能为数组");
|
|
1560
|
+
}
|
|
1561
|
+
if (value && lodashEs.isObject(value)) {
|
|
1562
|
+
const app = value;
|
|
1563
|
+
this.state.pageLength = getPageList(app).length || 0;
|
|
1564
|
+
this.state.pageFragmentLength = getPageFragmentList(app).length || 0;
|
|
1565
|
+
this.state.stageLoading = this.state.pageLength !== 0;
|
|
1566
|
+
} else {
|
|
1567
|
+
this.state.pageLength = 0;
|
|
1568
|
+
this.state.pageFragmentLength = 0;
|
|
1569
|
+
this.state.stageLoading = false;
|
|
1570
|
+
}
|
|
1571
|
+
this.emit("root-change", value, preValue);
|
|
1572
|
+
}
|
|
1819
1573
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1574
|
+
/**
|
|
1575
|
+
* 获取当前指点节点配置
|
|
1576
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength'
|
|
1577
|
+
* @returns MNode
|
|
1578
|
+
*/
|
|
1579
|
+
get(name) {
|
|
1580
|
+
return this.state[name];
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* 根据id获取组件、组件的父组件以及组件所属的页面节点
|
|
1584
|
+
* @param {number | string} id 组件id
|
|
1585
|
+
* @param {boolean} raw 是否使用toRaw
|
|
1586
|
+
* @returns {EditorNodeInfo}
|
|
1587
|
+
*/
|
|
1588
|
+
getNodeInfo(id, raw = true) {
|
|
1589
|
+
let root = this.get("root");
|
|
1590
|
+
if (raw) {
|
|
1591
|
+
root = vue.toRaw(root);
|
|
1592
|
+
}
|
|
1593
|
+
const info = {
|
|
1594
|
+
node: null,
|
|
1595
|
+
parent: null,
|
|
1596
|
+
page: null
|
|
1597
|
+
};
|
|
1598
|
+
if (!root)
|
|
1599
|
+
return info;
|
|
1600
|
+
if (id === root.id) {
|
|
1601
|
+
info.node = root;
|
|
1602
|
+
return info;
|
|
1603
|
+
}
|
|
1604
|
+
const path = utils.getNodePath(id, root.items);
|
|
1605
|
+
if (!path.length)
|
|
1606
|
+
return info;
|
|
1607
|
+
path.unshift(root);
|
|
1608
|
+
info.node = path[path.length - 1];
|
|
1609
|
+
info.parent = path[path.length - 2];
|
|
1610
|
+
path.forEach((item) => {
|
|
1611
|
+
if (utils.isPage(item) || utils.isPageFragment(item)) {
|
|
1612
|
+
info.page = item;
|
|
1613
|
+
return;
|
|
1614
|
+
}
|
|
1615
|
+
});
|
|
1616
|
+
return info;
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* 根据ID获取指点节点配置
|
|
1620
|
+
* @param id 组件ID
|
|
1621
|
+
* @param {boolean} raw 是否使用toRaw
|
|
1622
|
+
* @returns 组件节点配置
|
|
1623
|
+
*/
|
|
1624
|
+
getNodeById(id, raw = true) {
|
|
1625
|
+
const { node } = this.getNodeInfo(id, raw);
|
|
1626
|
+
return node;
|
|
1823
1627
|
}
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1628
|
+
/**
|
|
1629
|
+
* 根据ID获取指点节点的父节点配置
|
|
1630
|
+
* @param id 组件ID
|
|
1631
|
+
* @param {boolean} raw 是否使用toRaw
|
|
1632
|
+
* @returns 指点组件的父节点配置
|
|
1633
|
+
*/
|
|
1634
|
+
getParentById(id, raw = true) {
|
|
1635
|
+
const { parent } = this.getNodeInfo(id, raw);
|
|
1636
|
+
return parent;
|
|
1827
1637
|
}
|
|
1828
|
-
|
|
1829
|
-
|
|
1638
|
+
/**
|
|
1639
|
+
* 只有容器拥有布局
|
|
1640
|
+
*/
|
|
1641
|
+
async getLayout(parent, node) {
|
|
1642
|
+
if (node && typeof node !== "function" && isFixed(node))
|
|
1643
|
+
return Layout.FIXED;
|
|
1644
|
+
if (parent.layout) {
|
|
1645
|
+
return parent.layout;
|
|
1646
|
+
}
|
|
1647
|
+
if (!parent.style?.position) {
|
|
1648
|
+
return Layout.RELATIVE;
|
|
1649
|
+
}
|
|
1650
|
+
return Layout.ABSOLUTE;
|
|
1830
1651
|
}
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1652
|
+
/**
|
|
1653
|
+
* 选中指定节点(将指定节点设置成当前选中状态)
|
|
1654
|
+
* @param config 指定节点配置或者ID
|
|
1655
|
+
* @returns 当前选中的节点配置
|
|
1656
|
+
*/
|
|
1657
|
+
async select(config) {
|
|
1658
|
+
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
|
1659
|
+
this.set("nodes", node ? [node] : []);
|
|
1660
|
+
this.set("page", page);
|
|
1661
|
+
this.set("parent", parent);
|
|
1662
|
+
if (page) {
|
|
1663
|
+
historyService.changePage(vue.toRaw(page));
|
|
1664
|
+
} else {
|
|
1665
|
+
historyService.resetState();
|
|
1666
|
+
}
|
|
1667
|
+
if (node?.id) {
|
|
1668
|
+
this.get("stage")?.renderer.runtime?.getApp?.()?.page?.emit(
|
|
1669
|
+
"editor:select",
|
|
1670
|
+
{
|
|
1671
|
+
node,
|
|
1672
|
+
page,
|
|
1673
|
+
parent
|
|
1674
|
+
},
|
|
1675
|
+
utils.getNodePath(node.id, this.get("root")?.items)
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
this.emit("select", node);
|
|
1679
|
+
return node;
|
|
1834
1680
|
}
|
|
1835
|
-
|
|
1836
|
-
|
|
1681
|
+
async selectNextNode() {
|
|
1682
|
+
const node = vue.toRaw(this.get("node"));
|
|
1683
|
+
if (!node || utils.isPage(node) || node.type === schema.NodeType.ROOT)
|
|
1684
|
+
return node;
|
|
1685
|
+
const parent = vue.toRaw(this.getParentById(node.id));
|
|
1686
|
+
if (!parent)
|
|
1687
|
+
return node;
|
|
1688
|
+
const index = getNodeIndex(node.id, parent);
|
|
1689
|
+
const nextNode = parent.items[index + 1] || parent.items[0];
|
|
1690
|
+
await this.select(nextNode);
|
|
1691
|
+
this.get("stage")?.select(nextNode.id);
|
|
1692
|
+
return nextNode;
|
|
1837
1693
|
}
|
|
1838
|
-
|
|
1839
|
-
|
|
1694
|
+
async selectNextPage() {
|
|
1695
|
+
const root = vue.toRaw(this.get("root"));
|
|
1696
|
+
const page = vue.toRaw(this.get("page"));
|
|
1697
|
+
if (!page)
|
|
1698
|
+
throw new Error("page不能为空");
|
|
1699
|
+
if (!root)
|
|
1700
|
+
throw new Error("root不能为空");
|
|
1701
|
+
const index = getNodeIndex(page.id, root);
|
|
1702
|
+
const nextPage = root.items[index + 1] || root.items[0];
|
|
1703
|
+
await this.select(nextPage);
|
|
1704
|
+
this.get("stage")?.select(nextPage.id);
|
|
1705
|
+
return nextPage;
|
|
1840
1706
|
}
|
|
1841
|
-
|
|
1842
|
-
|
|
1707
|
+
/**
|
|
1708
|
+
* 高亮指定节点
|
|
1709
|
+
* @param config 指定节点配置或者ID
|
|
1710
|
+
* @returns 当前高亮的节点配置
|
|
1711
|
+
*/
|
|
1712
|
+
highlight(config) {
|
|
1713
|
+
const { node } = this.selectedConfigExceptionHandler(config);
|
|
1714
|
+
const currentHighlightNode = this.get("highlightNode");
|
|
1715
|
+
if (currentHighlightNode === node)
|
|
1716
|
+
return;
|
|
1717
|
+
this.set("highlightNode", node);
|
|
1843
1718
|
}
|
|
1844
|
-
|
|
1845
|
-
|
|
1719
|
+
/**
|
|
1720
|
+
* 多选
|
|
1721
|
+
* @param ids 指定节点ID
|
|
1722
|
+
* @returns 加入多选的节点配置
|
|
1723
|
+
*/
|
|
1724
|
+
multiSelect(ids) {
|
|
1725
|
+
const nodes = [];
|
|
1726
|
+
const idsUnique = lodashEs.uniq(ids);
|
|
1727
|
+
idsUnique.forEach((id) => {
|
|
1728
|
+
const { node } = this.getNodeInfo(id);
|
|
1729
|
+
if (!node)
|
|
1730
|
+
return;
|
|
1731
|
+
nodes.push(node);
|
|
1732
|
+
});
|
|
1733
|
+
this.set("nodes", nodes);
|
|
1846
1734
|
}
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
"
|
|
1853
|
-
"
|
|
1854
|
-
"
|
|
1855
|
-
"
|
|
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
|
-
]);
|
|
1735
|
+
selectRoot() {
|
|
1736
|
+
const root = this.get("root");
|
|
1737
|
+
if (!root)
|
|
1738
|
+
return;
|
|
1739
|
+
this.set("nodes", [root]);
|
|
1740
|
+
this.set("parent", null);
|
|
1741
|
+
this.set("page", null);
|
|
1742
|
+
this.set("stage", null);
|
|
1743
|
+
this.set("highlightNode", null);
|
|
1872
1744
|
}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1745
|
+
async doAdd(node, parent) {
|
|
1746
|
+
const root = this.get("root");
|
|
1747
|
+
if (!root)
|
|
1748
|
+
throw new Error("root为空");
|
|
1749
|
+
const curNode = this.get("node");
|
|
1750
|
+
const stage = this.get("stage");
|
|
1751
|
+
if (!curNode)
|
|
1752
|
+
throw new Error("当前选中节点为空");
|
|
1753
|
+
if ((parent.type === schema.NodeType.ROOT || curNode?.type === schema.NodeType.ROOT) && !(utils.isPage(node) || utils.isPageFragment(node))) {
|
|
1754
|
+
throw new Error("app下不能添加组件");
|
|
1755
|
+
}
|
|
1756
|
+
if (parent.id !== curNode.id && !(utils.isPage(node) || utils.isPageFragment(node))) {
|
|
1757
|
+
const index = parent.items.indexOf(curNode);
|
|
1758
|
+
parent.items?.splice(index + 1, 0, node);
|
|
1759
|
+
} else {
|
|
1760
|
+
parent.items?.push(node);
|
|
1761
|
+
}
|
|
1762
|
+
const layout = await this.getLayout(vue.toRaw(parent), node);
|
|
1763
|
+
node.style = getInitPositionStyle(node.style, layout);
|
|
1764
|
+
await stage?.add({
|
|
1765
|
+
config: lodashEs.cloneDeep(node),
|
|
1766
|
+
parent: lodashEs.cloneDeep(parent),
|
|
1767
|
+
parentId: parent.id,
|
|
1768
|
+
root: lodashEs.cloneDeep(root)
|
|
1876
1769
|
});
|
|
1877
|
-
|
|
1770
|
+
const newStyle = fixNodePosition(node, parent, stage);
|
|
1771
|
+
if (newStyle && (newStyle.top !== node.style.top || newStyle.left !== node.style.left)) {
|
|
1772
|
+
node.style = newStyle;
|
|
1773
|
+
await stage?.update({ config: lodashEs.cloneDeep(node), parentId: parent.id, root: lodashEs.cloneDeep(root) });
|
|
1774
|
+
}
|
|
1775
|
+
this.addModifiedNodeId(node.id);
|
|
1776
|
+
return node;
|
|
1878
1777
|
}
|
|
1879
|
-
|
|
1880
|
-
|
|
1778
|
+
/**
|
|
1779
|
+
* 向指点容器添加组件节点
|
|
1780
|
+
* @param addConfig 将要添加的组件节点配置
|
|
1781
|
+
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
1782
|
+
* @returns 添加后的节点
|
|
1783
|
+
*/
|
|
1784
|
+
async add(addNode, parent) {
|
|
1785
|
+
const stage = this.get("stage");
|
|
1786
|
+
const addNodes = [];
|
|
1787
|
+
if (!Array.isArray(addNode)) {
|
|
1788
|
+
const { type, inputEvent, ...config } = addNode;
|
|
1789
|
+
if (!type)
|
|
1790
|
+
throw new Error("组件类型不能为空");
|
|
1791
|
+
addNodes.push({ ...vue.toRaw(await propsService.getPropsValue(type, config)) });
|
|
1792
|
+
} else {
|
|
1793
|
+
addNodes.push(...addNode);
|
|
1794
|
+
}
|
|
1795
|
+
const newNodes = await Promise.all(
|
|
1796
|
+
addNodes.map((node) => {
|
|
1797
|
+
const root = this.get("root");
|
|
1798
|
+
if ((utils.isPage(node) || utils.isPageFragment(node)) && root) {
|
|
1799
|
+
return this.doAdd(node, root);
|
|
1800
|
+
}
|
|
1801
|
+
const parentNode = parent && typeof parent !== "function" ? parent : getAddParent(node);
|
|
1802
|
+
if (!parentNode)
|
|
1803
|
+
throw new Error("未找到父元素");
|
|
1804
|
+
return this.doAdd(node, parentNode);
|
|
1805
|
+
})
|
|
1806
|
+
);
|
|
1807
|
+
if (newNodes.length > 1) {
|
|
1808
|
+
const newNodeIds = newNodes.map((node) => node.id);
|
|
1809
|
+
stage?.multiSelect(newNodeIds);
|
|
1810
|
+
await this.multiSelect(newNodeIds);
|
|
1811
|
+
} else {
|
|
1812
|
+
await this.select(newNodes[0]);
|
|
1813
|
+
if (utils.isPage(newNodes[0])) {
|
|
1814
|
+
this.state.pageLength += 1;
|
|
1815
|
+
} else if (utils.isPageFragment(newNodes[0])) {
|
|
1816
|
+
this.state.pageFragmentLength += 1;
|
|
1817
|
+
} else {
|
|
1818
|
+
stage?.select(newNodes[0].id);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
if (!(utils.isPage(newNodes[0]) || utils.isPageFragment(newNodes[0]))) {
|
|
1822
|
+
this.pushHistoryState();
|
|
1823
|
+
}
|
|
1824
|
+
this.emit("add", newNodes);
|
|
1825
|
+
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
1881
1826
|
}
|
|
1882
|
-
async
|
|
1883
|
-
|
|
1827
|
+
async doRemove(node) {
|
|
1828
|
+
const root = this.get("root");
|
|
1829
|
+
if (!root)
|
|
1830
|
+
throw new Error("root不能为空");
|
|
1831
|
+
const { parent, node: curNode } = this.getNodeInfo(node.id, false);
|
|
1832
|
+
if (!parent || !curNode)
|
|
1833
|
+
throw new Error("找不要删除的节点");
|
|
1834
|
+
const index = getNodeIndex(curNode.id, parent);
|
|
1835
|
+
if (typeof index !== "number" || index === -1)
|
|
1836
|
+
throw new Error("找不要删除的节点");
|
|
1837
|
+
parent.items?.splice(index, 1);
|
|
1838
|
+
const stage = this.get("stage");
|
|
1839
|
+
stage?.remove({ id: node.id, parentId: parent.id, root: lodashEs.cloneDeep(root) });
|
|
1840
|
+
const selectDefault = async (pages) => {
|
|
1841
|
+
if (pages[0]) {
|
|
1842
|
+
await this.select(pages[0]);
|
|
1843
|
+
stage?.select(pages[0].id);
|
|
1844
|
+
} else {
|
|
1845
|
+
this.selectRoot();
|
|
1846
|
+
historyService.resetPage();
|
|
1847
|
+
}
|
|
1848
|
+
};
|
|
1849
|
+
const rootItems = root.items || [];
|
|
1850
|
+
if (utils.isPage(node)) {
|
|
1851
|
+
this.state.pageLength -= 1;
|
|
1852
|
+
await selectDefault(getPageList(root));
|
|
1853
|
+
} else if (utils.isPageFragment(node)) {
|
|
1854
|
+
this.state.pageFragmentLength -= 1;
|
|
1855
|
+
await selectDefault(getPageFragmentList(root));
|
|
1856
|
+
} else {
|
|
1857
|
+
await this.select(parent);
|
|
1858
|
+
stage?.select(parent.id);
|
|
1859
|
+
this.addModifiedNodeId(parent.id);
|
|
1860
|
+
}
|
|
1861
|
+
if (!rootItems.length) {
|
|
1862
|
+
this.resetModifiedNodeId();
|
|
1863
|
+
historyService.reset();
|
|
1864
|
+
}
|
|
1884
1865
|
}
|
|
1885
1866
|
/**
|
|
1886
|
-
*
|
|
1887
|
-
* @param
|
|
1888
|
-
* @returns 组件属性表单配置
|
|
1867
|
+
* 删除组件
|
|
1868
|
+
* @param {Object} node
|
|
1889
1869
|
*/
|
|
1890
|
-
async
|
|
1891
|
-
|
|
1892
|
-
|
|
1870
|
+
async remove(nodeOrNodeList) {
|
|
1871
|
+
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
1872
|
+
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
1873
|
+
if (!(utils.isPage(nodes[0]) || utils.isPageFragment(nodes[0]))) {
|
|
1874
|
+
this.pushHistoryState();
|
|
1893
1875
|
}
|
|
1894
|
-
|
|
1876
|
+
this.emit("remove", nodes);
|
|
1895
1877
|
}
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1878
|
+
async doUpdate(config) {
|
|
1879
|
+
const root = this.get("root");
|
|
1880
|
+
if (!root)
|
|
1881
|
+
throw new Error("root为空");
|
|
1882
|
+
if (!config?.id)
|
|
1883
|
+
throw new Error("没有配置或者配置缺少id值");
|
|
1884
|
+
const info = this.getNodeInfo(config.id, false);
|
|
1885
|
+
if (!info.node)
|
|
1886
|
+
throw new Error(`获取不到id为${config.id}的节点`);
|
|
1887
|
+
const node = lodashEs.cloneDeep(vue.toRaw(info.node));
|
|
1888
|
+
let newConfig = await this.toggleFixedPosition(vue.toRaw(config), node, root);
|
|
1889
|
+
newConfig = lodashEs.mergeWith(lodashEs.cloneDeep(node), newConfig, (objValue, srcValue, key) => {
|
|
1890
|
+
if (typeof srcValue === "undefined" && Object.hasOwn(newConfig, key)) {
|
|
1891
|
+
return "";
|
|
1892
|
+
}
|
|
1893
|
+
if (lodashEs.isObject(srcValue) && Array.isArray(objValue)) {
|
|
1894
|
+
return srcValue;
|
|
1895
|
+
}
|
|
1896
|
+
if (Array.isArray(srcValue)) {
|
|
1897
|
+
return srcValue;
|
|
1898
|
+
}
|
|
1899
1899
|
});
|
|
1900
|
+
if (!newConfig.type)
|
|
1901
|
+
throw new Error("配置缺少type值");
|
|
1902
|
+
if (newConfig.type === schema.NodeType.ROOT) {
|
|
1903
|
+
this.set("root", newConfig);
|
|
1904
|
+
return newConfig;
|
|
1905
|
+
}
|
|
1906
|
+
const { parent } = info;
|
|
1907
|
+
if (!parent)
|
|
1908
|
+
throw new Error("获取不到父级节点");
|
|
1909
|
+
const parentNodeItems = parent.items;
|
|
1910
|
+
const index = getNodeIndex(newConfig.id, parent);
|
|
1911
|
+
if (!parentNodeItems || typeof index === "undefined" || index === -1)
|
|
1912
|
+
throw new Error("更新的节点未找到");
|
|
1913
|
+
const newLayout = await this.getLayout(newConfig);
|
|
1914
|
+
const layout = await this.getLayout(node);
|
|
1915
|
+
if (Array.isArray(newConfig.items) && newLayout !== layout) {
|
|
1916
|
+
newConfig = setChildrenLayout(newConfig, newLayout);
|
|
1917
|
+
}
|
|
1918
|
+
parentNodeItems[index] = newConfig;
|
|
1919
|
+
const nodes = this.get("nodes");
|
|
1920
|
+
const targetIndex = nodes.findIndex((nodeItem) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
1921
|
+
nodes.splice(targetIndex, 1, newConfig);
|
|
1922
|
+
this.set("nodes", [...nodes]);
|
|
1923
|
+
this.get("stage")?.update({
|
|
1924
|
+
config: lodashEs.cloneDeep(newConfig),
|
|
1925
|
+
parentId: parent.id,
|
|
1926
|
+
root: lodashEs.cloneDeep(root)
|
|
1927
|
+
});
|
|
1928
|
+
if (utils.isPage(newConfig) || utils.isPageFragment(newConfig)) {
|
|
1929
|
+
this.set("page", newConfig);
|
|
1930
|
+
}
|
|
1931
|
+
this.addModifiedNodeId(newConfig.id);
|
|
1932
|
+
return newConfig;
|
|
1900
1933
|
}
|
|
1901
1934
|
/**
|
|
1902
|
-
*
|
|
1903
|
-
* @param
|
|
1904
|
-
* @
|
|
1905
|
-
*/
|
|
1906
|
-
async setPropsValue(type, value) {
|
|
1907
|
-
this.state.propsValueMap[utils.toLine(type)] = value;
|
|
1908
|
-
}
|
|
1909
|
-
/**
|
|
1910
|
-
* 获取指定类型的组件初始值
|
|
1911
|
-
* @param type 组件类型
|
|
1912
|
-
* @returns 组件初始值
|
|
1935
|
+
* 更新节点
|
|
1936
|
+
* @param config 新的节点配置,配置中需要有id信息
|
|
1937
|
+
* @returns 更新后的节点配置
|
|
1913
1938
|
*/
|
|
1914
|
-
async
|
|
1915
|
-
const
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
value.text = "";
|
|
1920
|
-
if (value.style) {
|
|
1921
|
-
value.style.backgroundColor = "rgba(255, 255, 255, 0)";
|
|
1922
|
-
}
|
|
1923
|
-
return value;
|
|
1939
|
+
async update(config) {
|
|
1940
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
1941
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doUpdate(node)));
|
|
1942
|
+
if (newNodes[0]?.type !== schema.NodeType.ROOT) {
|
|
1943
|
+
this.pushHistoryState();
|
|
1924
1944
|
}
|
|
1925
|
-
|
|
1926
|
-
|
|
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()}`;
|
|
1945
|
+
this.emit("update", newNodes);
|
|
1946
|
+
return Array.isArray(config) ? newNodes : newNodes[0];
|
|
1941
1947
|
}
|
|
1942
1948
|
/**
|
|
1943
|
-
*
|
|
1944
|
-
*
|
|
1945
|
-
* @param
|
|
1946
|
-
* @
|
|
1949
|
+
* 将id为id1的组件移动到id为id2的组件位置上,例如:[1,2,3,4] -> sort(1,3) -> [2,1,3,4]
|
|
1950
|
+
* @param id1 组件ID
|
|
1951
|
+
* @param id2 组件ID
|
|
1952
|
+
* @returns void
|
|
1947
1953
|
*/
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
if (
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1954
|
+
async sort(id1, id2) {
|
|
1955
|
+
const root = this.get("root");
|
|
1956
|
+
if (!root)
|
|
1957
|
+
throw new Error("root为空");
|
|
1958
|
+
const node = this.get("node");
|
|
1959
|
+
if (!node)
|
|
1960
|
+
throw new Error("当前节点为空");
|
|
1961
|
+
const parent = lodashEs.cloneDeep(vue.toRaw(this.get("parent")));
|
|
1962
|
+
if (!parent)
|
|
1963
|
+
throw new Error("父节点为空");
|
|
1964
|
+
const index2 = parent.items.findIndex((node2) => `${node2.id}` === `${id2}`);
|
|
1965
|
+
if (index2 < 0)
|
|
1966
|
+
return;
|
|
1967
|
+
const index1 = parent.items.findIndex((node2) => `${node2.id}` === `${id1}`);
|
|
1968
|
+
parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
|
|
1969
|
+
await this.update(parent);
|
|
1970
|
+
await this.select(node);
|
|
1971
|
+
this.get("stage")?.update({
|
|
1972
|
+
config: lodashEs.cloneDeep(node),
|
|
1973
|
+
parentId: parent.id,
|
|
1974
|
+
root: lodashEs.cloneDeep(root)
|
|
1975
|
+
});
|
|
1976
|
+
this.addModifiedNodeId(parent.id);
|
|
1977
|
+
this.pushHistoryState();
|
|
1961
1978
|
}
|
|
1962
1979
|
/**
|
|
1963
|
-
*
|
|
1964
|
-
* @param
|
|
1965
|
-
* @returns
|
|
1980
|
+
* 将组件节点配置存储到localStorage中
|
|
1981
|
+
* @param config 组件节点配置
|
|
1982
|
+
* @returns
|
|
1966
1983
|
*/
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
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 = {};
|
|
1984
|
+
copy(config) {
|
|
1985
|
+
storageService.setItem(COPY_STORAGE_KEY, Array.isArray(config) ? config : [config], {
|
|
1986
|
+
protocol: Protocol.OBJECT
|
|
1987
|
+
});
|
|
1983
1988
|
}
|
|
1984
1989
|
/**
|
|
1985
|
-
*
|
|
1986
|
-
* @param
|
|
1987
|
-
* @
|
|
1990
|
+
* 复制时会带上组件关联的依赖
|
|
1991
|
+
* @param config 组件节点配置
|
|
1992
|
+
* @returns
|
|
1988
1993
|
*/
|
|
1989
|
-
|
|
1990
|
-
const
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
const
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
target.deps[config.id]?.keys?.forEach((fullKey) => {
|
|
2002
|
-
const relateOriginId = utils.getValueByKeyPath(fullKey, config);
|
|
2003
|
-
const relateTargetId = relateIdMap[relateOriginId];
|
|
2004
|
-
if (!relateTargetId)
|
|
1994
|
+
copyWithRelated(config) {
|
|
1995
|
+
const copyNodes = Array.isArray(config) ? config : [config];
|
|
1996
|
+
depService.clearByType(dep.DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
1997
|
+
depService.collect(copyNodes, true, dep.DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
1998
|
+
const customTarget = depService.getTarget(
|
|
1999
|
+
dep.DepTargetType.RELATED_COMP_WHEN_COPY,
|
|
2000
|
+
dep.DepTargetType.RELATED_COMP_WHEN_COPY
|
|
2001
|
+
);
|
|
2002
|
+
if (customTarget) {
|
|
2003
|
+
Object.keys(customTarget.deps).forEach((nodeId) => {
|
|
2004
|
+
const node = this.getNodeById(nodeId);
|
|
2005
|
+
if (!node)
|
|
2005
2006
|
return;
|
|
2006
|
-
|
|
2007
|
+
customTarget.deps[nodeId].keys.forEach((key) => {
|
|
2008
|
+
const relateNodeId = lodashEs.get(node, key);
|
|
2009
|
+
const isExist = copyNodes.find((node2) => node2.id === relateNodeId);
|
|
2010
|
+
if (!isExist) {
|
|
2011
|
+
const relateNode = this.getNodeById(relateNodeId);
|
|
2012
|
+
if (relateNode) {
|
|
2013
|
+
copyNodes.push(relateNode);
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
});
|
|
2007
2017
|
});
|
|
2018
|
+
}
|
|
2019
|
+
storageService.setItem(COPY_STORAGE_KEY, copyNodes, {
|
|
2020
|
+
protocol: Protocol.OBJECT
|
|
2008
2021
|
});
|
|
2009
2022
|
}
|
|
2010
2023
|
/**
|
|
2011
|
-
*
|
|
2012
|
-
|
|
2013
|
-
|
|
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
|
|
2024
|
+
* 从localStorage中获取节点,然后添加到当前容器中
|
|
2025
|
+
* @param position 粘贴的坐标
|
|
2026
|
+
* @returns 添加后的组件节点配置
|
|
2036
2027
|
*/
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
const minListMaxSize = 2;
|
|
2049
|
-
this.elementList = [];
|
|
2050
|
-
this.listCursor = 0;
|
|
2051
|
-
this.listMaxSize = listMaxSize > minListMaxSize ? listMaxSize : minListMaxSize;
|
|
2052
|
-
}
|
|
2053
|
-
pushElement(element) {
|
|
2054
|
-
this.elementList.splice(this.listCursor, this.elementList.length - this.listCursor, lodashEs.cloneDeep(element));
|
|
2055
|
-
this.listCursor += 1;
|
|
2056
|
-
if (this.elementList.length > this.listMaxSize) {
|
|
2057
|
-
this.elementList.shift();
|
|
2058
|
-
this.listCursor -= 1;
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
|
-
canUndo() {
|
|
2062
|
-
return this.listCursor > 1;
|
|
2063
|
-
}
|
|
2064
|
-
// 返回undo后的当前元素
|
|
2065
|
-
undo() {
|
|
2066
|
-
if (!this.canUndo()) {
|
|
2067
|
-
return null;
|
|
2028
|
+
async paste(position = {}) {
|
|
2029
|
+
const config = storageService.getItem(COPY_STORAGE_KEY);
|
|
2030
|
+
if (!Array.isArray(config))
|
|
2031
|
+
return;
|
|
2032
|
+
const node = this.get("node");
|
|
2033
|
+
let parent = null;
|
|
2034
|
+
if (config.length === 1 && config[0].id === node?.id) {
|
|
2035
|
+
parent = this.get("parent");
|
|
2036
|
+
if (parent?.type === schema.NodeType.ROOT) {
|
|
2037
|
+
parent = this.get("page");
|
|
2038
|
+
}
|
|
2068
2039
|
}
|
|
2069
|
-
this.
|
|
2070
|
-
|
|
2040
|
+
const pasteConfigs = await this.doPaste(config, position);
|
|
2041
|
+
propsService.replaceRelateId(config, pasteConfigs);
|
|
2042
|
+
return this.add(pasteConfigs, parent);
|
|
2071
2043
|
}
|
|
2072
|
-
|
|
2073
|
-
|
|
2044
|
+
async doPaste(config, position = {}) {
|
|
2045
|
+
propsService.clearRelateId();
|
|
2046
|
+
const pasteConfigs = beforePaste(position, lodashEs.cloneDeep(config));
|
|
2047
|
+
return pasteConfigs;
|
|
2074
2048
|
}
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
if (!
|
|
2078
|
-
|
|
2049
|
+
async doAlignCenter(config) {
|
|
2050
|
+
const parent = this.getParentById(config.id);
|
|
2051
|
+
if (!parent)
|
|
2052
|
+
throw new Error("找不到父节点");
|
|
2053
|
+
const node = lodashEs.cloneDeep(vue.toRaw(config));
|
|
2054
|
+
const layout = await this.getLayout(parent, node);
|
|
2055
|
+
if (layout === Layout.RELATIVE) {
|
|
2056
|
+
return config;
|
|
2079
2057
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
if (
|
|
2085
|
-
|
|
2058
|
+
if (!node.style)
|
|
2059
|
+
return config;
|
|
2060
|
+
const stage = this.get("stage");
|
|
2061
|
+
const doc = stage?.renderer.contentWindow?.document;
|
|
2062
|
+
if (doc) {
|
|
2063
|
+
const el = doc.getElementById(`${node.id}`);
|
|
2064
|
+
const parentEl = layout === Layout.FIXED ? doc.body : el?.offsetParent;
|
|
2065
|
+
if (parentEl && el) {
|
|
2066
|
+
node.style.left = utils.calcValueByFontsize(doc, (parentEl.clientWidth - el.clientWidth) / 2);
|
|
2067
|
+
node.style.right = "";
|
|
2068
|
+
}
|
|
2069
|
+
} else if (parent.style && utils.isNumber(parent.style?.width) && utils.isNumber(node.style?.width)) {
|
|
2070
|
+
node.style.left = (parent.style.width - node.style.width) / 2;
|
|
2071
|
+
node.style.right = "";
|
|
2086
2072
|
}
|
|
2087
|
-
return
|
|
2088
|
-
}
|
|
2089
|
-
}
|
|
2090
|
-
|
|
2091
|
-
class History extends BaseService {
|
|
2092
|
-
state = vue.reactive({
|
|
2093
|
-
pageSteps: {},
|
|
2094
|
-
pageId: void 0,
|
|
2095
|
-
canRedo: false,
|
|
2096
|
-
canUndo: false
|
|
2097
|
-
});
|
|
2098
|
-
constructor() {
|
|
2099
|
-
super([]);
|
|
2100
|
-
this.on("change", this.setCanUndoRedo);
|
|
2101
|
-
}
|
|
2102
|
-
reset() {
|
|
2103
|
-
this.state.pageSteps = {};
|
|
2104
|
-
this.resetPage();
|
|
2105
|
-
}
|
|
2106
|
-
resetPage() {
|
|
2107
|
-
this.state.pageId = void 0;
|
|
2108
|
-
this.state.canRedo = false;
|
|
2109
|
-
this.state.canUndo = false;
|
|
2073
|
+
return node;
|
|
2110
2074
|
}
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2075
|
+
/**
|
|
2076
|
+
* 将指点节点设置居中
|
|
2077
|
+
* @param config 组件节点配置
|
|
2078
|
+
* @returns 当前组件节点配置
|
|
2079
|
+
*/
|
|
2080
|
+
async alignCenter(config) {
|
|
2081
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
2082
|
+
const stage = this.get("stage");
|
|
2083
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
|
2084
|
+
const newNode = await this.update(newNodes);
|
|
2085
|
+
if (newNodes.length > 1) {
|
|
2086
|
+
await stage?.multiSelect(newNodes.map((node) => node.id));
|
|
2087
|
+
} else {
|
|
2088
|
+
await stage?.select(newNodes[0].id);
|
|
2123
2089
|
}
|
|
2124
|
-
|
|
2125
|
-
this.emit("page-change", this.state.pageSteps[this.state.pageId]);
|
|
2126
|
-
}
|
|
2127
|
-
resetState() {
|
|
2128
|
-
this.state.pageId = void 0;
|
|
2129
|
-
this.state.pageSteps = {};
|
|
2130
|
-
this.state.canRedo = false;
|
|
2131
|
-
this.state.canUndo = false;
|
|
2132
|
-
}
|
|
2133
|
-
push(state) {
|
|
2134
|
-
const undoRedo = this.getUndoRedo();
|
|
2135
|
-
if (!undoRedo)
|
|
2136
|
-
return null;
|
|
2137
|
-
undoRedo.pushElement(state);
|
|
2138
|
-
this.emit("change", state);
|
|
2139
|
-
return state;
|
|
2140
|
-
}
|
|
2141
|
-
undo() {
|
|
2142
|
-
const undoRedo = this.getUndoRedo();
|
|
2143
|
-
if (!undoRedo)
|
|
2144
|
-
return null;
|
|
2145
|
-
const state = undoRedo.undo();
|
|
2146
|
-
this.emit("change", state);
|
|
2147
|
-
return state;
|
|
2148
|
-
}
|
|
2149
|
-
redo() {
|
|
2150
|
-
const undoRedo = this.getUndoRedo();
|
|
2151
|
-
if (!undoRedo)
|
|
2152
|
-
return null;
|
|
2153
|
-
const state = undoRedo.redo();
|
|
2154
|
-
this.emit("change", state);
|
|
2155
|
-
return state;
|
|
2156
|
-
}
|
|
2157
|
-
destroy() {
|
|
2158
|
-
this.resetState();
|
|
2159
|
-
this.removeAllListeners();
|
|
2160
|
-
this.removeAllPlugins();
|
|
2161
|
-
}
|
|
2162
|
-
getUndoRedo() {
|
|
2163
|
-
if (!this.state.pageId)
|
|
2164
|
-
return null;
|
|
2165
|
-
return this.state.pageSteps[this.state.pageId];
|
|
2166
|
-
}
|
|
2167
|
-
setCanUndoRedo() {
|
|
2168
|
-
const undoRedo = this.getUndoRedo();
|
|
2169
|
-
this.state.canRedo = undoRedo?.canRedo() || false;
|
|
2170
|
-
this.state.canUndo = undoRedo?.canUndo() || false;
|
|
2171
|
-
}
|
|
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"]
|
|
2186
|
-
};
|
|
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 })));
|
|
2090
|
+
return newNode;
|
|
2192
2091
|
}
|
|
2193
2092
|
/**
|
|
2194
|
-
*
|
|
2195
|
-
*
|
|
2196
|
-
* storageService.usePlugin({
|
|
2197
|
-
* // 替换存储对象为 sessionStorage
|
|
2198
|
-
* async afterGetStorage(): Promise<Storage> {
|
|
2199
|
-
* return window.sessionStorage;
|
|
2200
|
-
* },
|
|
2201
|
-
* });
|
|
2093
|
+
* 移动当前选中节点位置
|
|
2094
|
+
* @param offset 偏移量
|
|
2202
2095
|
*/
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2096
|
+
async moveLayer(offset) {
|
|
2097
|
+
const root = this.get("root");
|
|
2098
|
+
if (!root)
|
|
2099
|
+
throw new Error("root为空");
|
|
2100
|
+
const parent = this.get("parent");
|
|
2101
|
+
if (!parent)
|
|
2102
|
+
throw new Error("父节点为空");
|
|
2103
|
+
const node = this.get("node");
|
|
2104
|
+
if (!node)
|
|
2105
|
+
throw new Error("当前节点为空");
|
|
2106
|
+
const brothers = parent.items || [];
|
|
2107
|
+
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
|
2108
|
+
const layout = await this.getLayout(parent, node);
|
|
2109
|
+
const isRelative = layout === Layout.RELATIVE;
|
|
2110
|
+
let offsetIndex;
|
|
2111
|
+
if (offset === LayerOffset.TOP) {
|
|
2112
|
+
offsetIndex = isRelative ? 0 : brothers.length;
|
|
2113
|
+
} else if (offset === LayerOffset.BOTTOM) {
|
|
2114
|
+
offsetIndex = isRelative ? brothers.length : 0;
|
|
2115
|
+
} else {
|
|
2116
|
+
offsetIndex = index + (isRelative ? -offset : offset);
|
|
2117
|
+
}
|
|
2118
|
+
if (offsetIndex > 0 && offsetIndex > brothers.length || offsetIndex < 0) {
|
|
2119
|
+
return;
|
|
2120
|
+
}
|
|
2121
|
+
brothers.splice(index, 1);
|
|
2122
|
+
brothers.splice(offsetIndex, 0, node);
|
|
2123
|
+
const grandparent = this.getParentById(parent.id);
|
|
2124
|
+
this.get("stage")?.update({
|
|
2125
|
+
config: lodashEs.cloneDeep(vue.toRaw(parent)),
|
|
2126
|
+
parentId: grandparent?.id,
|
|
2127
|
+
root: lodashEs.cloneDeep(root)
|
|
2128
|
+
});
|
|
2129
|
+
this.addModifiedNodeId(parent.id);
|
|
2130
|
+
this.pushHistoryState();
|
|
2131
|
+
this.emit("move-layer", offset);
|
|
2208
2132
|
}
|
|
2209
2133
|
/**
|
|
2210
|
-
*
|
|
2134
|
+
* 移动到指定容器中
|
|
2135
|
+
* @param config 需要移动的节点
|
|
2136
|
+
* @param targetId 容器ID
|
|
2211
2137
|
*/
|
|
2212
|
-
|
|
2213
|
-
const
|
|
2214
|
-
|
|
2138
|
+
async moveToContainer(config, targetId) {
|
|
2139
|
+
const root = this.get("root");
|
|
2140
|
+
const { node, parent } = this.getNodeInfo(config.id, false);
|
|
2141
|
+
const target = this.getNodeById(targetId, false);
|
|
2142
|
+
const stage = this.get("stage");
|
|
2143
|
+
if (root && node && parent && stage) {
|
|
2144
|
+
const index = getNodeIndex(node.id, parent);
|
|
2145
|
+
parent.items?.splice(index, 1);
|
|
2146
|
+
await stage.remove({ id: node.id, parentId: parent.id, root: lodashEs.cloneDeep(root) });
|
|
2147
|
+
const layout = await this.getLayout(target);
|
|
2148
|
+
const newConfig = lodashEs.mergeWith(lodashEs.cloneDeep(node), config, (objValue, srcValue) => {
|
|
2149
|
+
if (Array.isArray(srcValue)) {
|
|
2150
|
+
return srcValue;
|
|
2151
|
+
}
|
|
2152
|
+
});
|
|
2153
|
+
newConfig.style = getInitPositionStyle(newConfig.style, layout);
|
|
2154
|
+
target.items.push(newConfig);
|
|
2155
|
+
await stage.select(targetId);
|
|
2156
|
+
const targetParent = this.getParentById(target.id);
|
|
2157
|
+
await stage.update({ config: lodashEs.cloneDeep(target), parentId: targetParent?.id, root: lodashEs.cloneDeep(root) });
|
|
2158
|
+
await this.select(newConfig);
|
|
2159
|
+
stage.select(newConfig.id);
|
|
2160
|
+
this.addModifiedNodeId(target.id);
|
|
2161
|
+
this.addModifiedNodeId(parent.id);
|
|
2162
|
+
this.pushHistoryState();
|
|
2163
|
+
return newConfig;
|
|
2164
|
+
}
|
|
2215
2165
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
const
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
if (
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2166
|
+
async dragTo(config, targetParent, targetIndex) {
|
|
2167
|
+
if (!targetParent || !Array.isArray(targetParent.items))
|
|
2168
|
+
return;
|
|
2169
|
+
const { parent, node: curNode } = this.getNodeInfo(config.id, false);
|
|
2170
|
+
if (!parent || !curNode)
|
|
2171
|
+
throw new Error("找不要删除的节点");
|
|
2172
|
+
const index = getNodeIndex(curNode.id, parent);
|
|
2173
|
+
if (typeof index !== "number" || index === -1)
|
|
2174
|
+
throw new Error("找不要删除的节点");
|
|
2175
|
+
if (parent.id === targetParent.id) {
|
|
2176
|
+
if (index === targetIndex)
|
|
2177
|
+
return;
|
|
2178
|
+
if (index < targetIndex) {
|
|
2179
|
+
targetIndex -= 1;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
const layout = await this.getLayout(parent);
|
|
2183
|
+
const newLayout = await this.getLayout(targetParent);
|
|
2184
|
+
if (newLayout !== layout) {
|
|
2185
|
+
setLayout(config, newLayout);
|
|
2186
|
+
}
|
|
2187
|
+
parent.items?.splice(index, 1);
|
|
2188
|
+
targetParent.items?.splice(targetIndex, 0, config);
|
|
2189
|
+
const page = this.get("page");
|
|
2190
|
+
const root = this.get("root");
|
|
2191
|
+
const stage = this.get("stage");
|
|
2192
|
+
if (stage && page && root) {
|
|
2193
|
+
stage.update({
|
|
2194
|
+
config: lodashEs.cloneDeep(page),
|
|
2195
|
+
parentId: root.id,
|
|
2196
|
+
root: lodashEs.cloneDeep(root)
|
|
2197
|
+
});
|
|
2238
2198
|
}
|
|
2199
|
+
this.addModifiedNodeId(config.id);
|
|
2200
|
+
this.addModifiedNodeId(parent.id);
|
|
2201
|
+
this.pushHistoryState();
|
|
2202
|
+
this.emit("drag-to", { index, targetIndex, config, parent, targetParent });
|
|
2239
2203
|
}
|
|
2240
2204
|
/**
|
|
2241
|
-
*
|
|
2205
|
+
* 撤销当前操作
|
|
2206
|
+
* @returns 上一次数据
|
|
2242
2207
|
*/
|
|
2243
|
-
|
|
2244
|
-
const
|
|
2245
|
-
|
|
2208
|
+
async undo() {
|
|
2209
|
+
const value = historyService.undo();
|
|
2210
|
+
await this.changeHistoryState(value);
|
|
2211
|
+
return value;
|
|
2246
2212
|
}
|
|
2247
2213
|
/**
|
|
2248
|
-
*
|
|
2214
|
+
* 恢复到下一步
|
|
2215
|
+
* @returns 下一步数据
|
|
2249
2216
|
*/
|
|
2250
|
-
|
|
2251
|
-
const
|
|
2252
|
-
|
|
2253
|
-
|
|
2217
|
+
async redo() {
|
|
2218
|
+
const value = historyService.redo();
|
|
2219
|
+
await this.changeHistoryState(value);
|
|
2220
|
+
return value;
|
|
2254
2221
|
}
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
const
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
const
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2222
|
+
async move(left, top) {
|
|
2223
|
+
const node = vue.toRaw(this.get("node"));
|
|
2224
|
+
if (!node || utils.isPage(node))
|
|
2225
|
+
return;
|
|
2226
|
+
const { style, id, type } = node;
|
|
2227
|
+
if (!style || !["absolute", "fixed"].includes(style.position))
|
|
2228
|
+
return;
|
|
2229
|
+
const update = (style2) => this.update({
|
|
2230
|
+
id,
|
|
2231
|
+
type,
|
|
2232
|
+
style: style2
|
|
2233
|
+
});
|
|
2234
|
+
if (top) {
|
|
2235
|
+
if (utils.isNumber(style.top)) {
|
|
2236
|
+
update({
|
|
2237
|
+
...style,
|
|
2238
|
+
top: Number(style.top) + Number(top),
|
|
2239
|
+
bottom: ""
|
|
2240
|
+
});
|
|
2241
|
+
} else if (utils.isNumber(style.bottom)) {
|
|
2242
|
+
update({
|
|
2243
|
+
...style,
|
|
2244
|
+
bottom: Number(style.bottom) - Number(top),
|
|
2245
|
+
top: ""
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2267
2248
|
}
|
|
2268
|
-
|
|
2249
|
+
if (left) {
|
|
2250
|
+
if (utils.isNumber(style.left)) {
|
|
2251
|
+
update({
|
|
2252
|
+
...style,
|
|
2253
|
+
left: Number(style.left) + Number(left),
|
|
2254
|
+
right: ""
|
|
2255
|
+
});
|
|
2256
|
+
} else if (utils.isNumber(style.right)) {
|
|
2257
|
+
update({
|
|
2258
|
+
...style,
|
|
2259
|
+
right: Number(style.right) - Number(left),
|
|
2260
|
+
left: ""
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
resetState() {
|
|
2266
|
+
this.set("root", null);
|
|
2267
|
+
this.set("node", null);
|
|
2268
|
+
this.set("nodes", []);
|
|
2269
|
+
this.set("page", null);
|
|
2270
|
+
this.set("parent", null);
|
|
2271
|
+
this.set("stage", null);
|
|
2272
|
+
this.set("highlightNode", null);
|
|
2273
|
+
this.set("modifiedNodeIds", /* @__PURE__ */ new Map());
|
|
2274
|
+
this.set("pageLength", 0);
|
|
2269
2275
|
}
|
|
2270
2276
|
destroy() {
|
|
2271
2277
|
this.removeAllListeners();
|
|
2278
|
+
this.resetState();
|
|
2272
2279
|
this.removeAllPlugins();
|
|
2273
2280
|
}
|
|
2281
|
+
resetModifiedNodeId() {
|
|
2282
|
+
this.get("modifiedNodeIds").clear();
|
|
2283
|
+
}
|
|
2274
2284
|
usePlugin(options) {
|
|
2275
2285
|
super.usePlugin(options);
|
|
2276
2286
|
}
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2287
|
+
addModifiedNodeId(id) {
|
|
2288
|
+
if (!this.isHistoryStateChange) {
|
|
2289
|
+
this.get("modifiedNodeIds").set(id, id);
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
pushHistoryState() {
|
|
2293
|
+
const curNode = lodashEs.cloneDeep(vue.toRaw(this.get("node")));
|
|
2294
|
+
const page = this.get("page");
|
|
2295
|
+
if (!this.isHistoryStateChange && curNode && page) {
|
|
2296
|
+
historyService.push({
|
|
2297
|
+
data: lodashEs.cloneDeep(vue.toRaw(page)),
|
|
2298
|
+
modifiedNodeIds: this.get("modifiedNodeIds"),
|
|
2299
|
+
nodeId: curNode.id
|
|
2300
|
+
});
|
|
2301
|
+
}
|
|
2302
|
+
this.isHistoryStateChange = false;
|
|
2303
|
+
}
|
|
2304
|
+
async changeHistoryState(value) {
|
|
2305
|
+
if (!value)
|
|
2306
|
+
return;
|
|
2307
|
+
this.isHistoryStateChange = true;
|
|
2308
|
+
await this.update(value.data);
|
|
2309
|
+
this.set("modifiedNodeIds", value.modifiedNodeIds);
|
|
2310
|
+
setTimeout(async () => {
|
|
2311
|
+
if (!value.nodeId)
|
|
2312
|
+
return;
|
|
2313
|
+
await this.select(value.nodeId);
|
|
2314
|
+
this.get("stage")?.select(value.nodeId);
|
|
2315
|
+
}, 0);
|
|
2316
|
+
this.emit("history-change", value.data);
|
|
2317
|
+
}
|
|
2318
|
+
async toggleFixedPosition(dist, src, root) {
|
|
2319
|
+
const newConfig = lodashEs.cloneDeep(dist);
|
|
2320
|
+
if (!utils.isPop(src) && newConfig.style?.position) {
|
|
2321
|
+
if (isFixed(newConfig) && !isFixed(src)) {
|
|
2322
|
+
newConfig.style = change2Fixed(newConfig, root);
|
|
2323
|
+
} else if (!isFixed(newConfig) && isFixed(src)) {
|
|
2324
|
+
newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
return newConfig;
|
|
2328
|
+
}
|
|
2329
|
+
selectedConfigExceptionHandler(config) {
|
|
2330
|
+
let id;
|
|
2331
|
+
if (typeof config === "string" || typeof config === "number") {
|
|
2332
|
+
id = config;
|
|
2333
|
+
} else {
|
|
2334
|
+
id = config.id;
|
|
2335
|
+
}
|
|
2336
|
+
if (!id) {
|
|
2337
|
+
throw new Error("没有ID,无法选中");
|
|
2338
|
+
}
|
|
2339
|
+
const { node, parent, page } = this.getNodeInfo(id);
|
|
2340
|
+
if (!node)
|
|
2341
|
+
throw new Error("获取不到组件信息");
|
|
2342
|
+
if (node.id === this.state.root?.id) {
|
|
2343
|
+
throw new Error("不能选根节点");
|
|
2284
2344
|
}
|
|
2285
|
-
const item = value.replace(new RegExp(`^(${Object.values(Protocol).join("|")})(:)(.+)`), (_$0, $1, _$2, $3) => {
|
|
2286
|
-
protocol = $1;
|
|
2287
|
-
return $3;
|
|
2288
|
-
});
|
|
2289
2345
|
return {
|
|
2290
|
-
|
|
2291
|
-
|
|
2346
|
+
node,
|
|
2347
|
+
parent,
|
|
2348
|
+
page
|
|
2292
2349
|
};
|
|
2293
2350
|
}
|
|
2294
2351
|
}
|
|
2295
|
-
const
|
|
2352
|
+
const editorService = new Editor();
|
|
2296
2353
|
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
sync: []
|
|
2323
|
-
};
|
|
2324
|
-
class Editor extends BaseService {
|
|
2325
|
-
state = vue.reactive({
|
|
2326
|
-
root: null,
|
|
2327
|
-
page: null,
|
|
2328
|
-
parent: null,
|
|
2329
|
-
node: null,
|
|
2330
|
-
nodes: [],
|
|
2331
|
-
stage: null,
|
|
2332
|
-
stageLoading: true,
|
|
2333
|
-
highlightNode: null,
|
|
2334
|
-
modifiedNodeIds: /* @__PURE__ */ new Map(),
|
|
2335
|
-
pageLength: 0,
|
|
2336
|
-
pageFragmentLength: 0,
|
|
2337
|
-
disabledMultiSelect: false
|
|
2338
|
-
});
|
|
2339
|
-
isHistoryStateChange = false;
|
|
2340
|
-
constructor() {
|
|
2341
|
-
super(
|
|
2342
|
-
canUsePluginMethods$3.async.map((methodName) => ({ name: methodName, isAsync: true })),
|
|
2343
|
-
// 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
|
|
2344
|
-
["select", "update", "moveLayer"]
|
|
2345
|
-
);
|
|
2346
|
-
}
|
|
2347
|
-
/**
|
|
2348
|
-
* 设置当前指点节点配置
|
|
2349
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
2350
|
-
* @param value MNode
|
|
2351
|
-
*/
|
|
2352
|
-
set(name, value) {
|
|
2353
|
-
const preValue = this.state[name];
|
|
2354
|
-
this.state[name] = value;
|
|
2355
|
-
if (name === "nodes" && Array.isArray(value)) {
|
|
2356
|
-
this.set("node", value[0]);
|
|
2354
|
+
function BaseFormConfig() {
|
|
2355
|
+
return [
|
|
2356
|
+
{
|
|
2357
|
+
name: "id",
|
|
2358
|
+
type: "hidden"
|
|
2359
|
+
},
|
|
2360
|
+
{
|
|
2361
|
+
name: "type",
|
|
2362
|
+
text: "类型",
|
|
2363
|
+
type: "hidden",
|
|
2364
|
+
defaultValue: "base"
|
|
2365
|
+
},
|
|
2366
|
+
{
|
|
2367
|
+
name: "title",
|
|
2368
|
+
text: "名称",
|
|
2369
|
+
rules: [
|
|
2370
|
+
{
|
|
2371
|
+
required: true,
|
|
2372
|
+
message: "请输入名称"
|
|
2373
|
+
}
|
|
2374
|
+
]
|
|
2375
|
+
},
|
|
2376
|
+
{
|
|
2377
|
+
name: "description",
|
|
2378
|
+
text: "描述"
|
|
2357
2379
|
}
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2380
|
+
];
|
|
2381
|
+
}
|
|
2382
|
+
|
|
2383
|
+
const HttpFormConfig = [
|
|
2384
|
+
{
|
|
2385
|
+
name: "autoFetch",
|
|
2386
|
+
text: "自动请求",
|
|
2387
|
+
type: "switch",
|
|
2388
|
+
defaultValue: true
|
|
2389
|
+
},
|
|
2390
|
+
{
|
|
2391
|
+
name: "responseOptions",
|
|
2392
|
+
items: [
|
|
2393
|
+
{
|
|
2394
|
+
name: "dataPath",
|
|
2395
|
+
text: "数据路径"
|
|
2361
2396
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2397
|
+
]
|
|
2398
|
+
},
|
|
2399
|
+
{
|
|
2400
|
+
type: "fieldset",
|
|
2401
|
+
name: "options",
|
|
2402
|
+
legend: "HTTP 配置",
|
|
2403
|
+
items: [
|
|
2404
|
+
{
|
|
2405
|
+
name: "url",
|
|
2406
|
+
text: "URL"
|
|
2407
|
+
},
|
|
2408
|
+
{
|
|
2409
|
+
name: "method",
|
|
2410
|
+
text: "Method",
|
|
2411
|
+
type: "select",
|
|
2412
|
+
options: [
|
|
2413
|
+
{ text: "GET", value: "GET" },
|
|
2414
|
+
{ text: "POST", value: "POST" },
|
|
2415
|
+
{ text: "PUT", value: "PUT" },
|
|
2416
|
+
{ text: "DELETE", value: "DELETE" }
|
|
2417
|
+
]
|
|
2418
|
+
},
|
|
2419
|
+
{
|
|
2420
|
+
name: "params",
|
|
2421
|
+
type: "key-value",
|
|
2422
|
+
defaultValue: {},
|
|
2423
|
+
text: "参数"
|
|
2424
|
+
},
|
|
2425
|
+
{
|
|
2426
|
+
name: "data",
|
|
2427
|
+
type: "key-value",
|
|
2428
|
+
defaultValue: {},
|
|
2429
|
+
advanced: true,
|
|
2430
|
+
text: "请求体"
|
|
2431
|
+
},
|
|
2432
|
+
{
|
|
2433
|
+
name: "headers",
|
|
2434
|
+
type: "key-value",
|
|
2435
|
+
defaultValue: {},
|
|
2436
|
+
text: "请求头"
|
|
2437
|
+
}
|
|
2438
|
+
]
|
|
2439
|
+
}
|
|
2440
|
+
];
|
|
2441
|
+
|
|
2442
|
+
const fillConfig$1 = (config) => [
|
|
2443
|
+
...BaseFormConfig(),
|
|
2444
|
+
...config,
|
|
2445
|
+
{
|
|
2446
|
+
type: "tab",
|
|
2447
|
+
items: [
|
|
2448
|
+
{
|
|
2449
|
+
title: "数据定义",
|
|
2450
|
+
items: [
|
|
2451
|
+
{
|
|
2452
|
+
name: "fields",
|
|
2453
|
+
type: "data-source-fields",
|
|
2454
|
+
defaultValue: () => []
|
|
2455
|
+
}
|
|
2456
|
+
]
|
|
2457
|
+
},
|
|
2458
|
+
{
|
|
2459
|
+
title: "方法定义",
|
|
2460
|
+
items: [
|
|
2461
|
+
{
|
|
2462
|
+
name: "methods",
|
|
2463
|
+
type: "data-source-methods",
|
|
2464
|
+
defaultValue: () => []
|
|
2465
|
+
}
|
|
2466
|
+
]
|
|
2467
|
+
},
|
|
2468
|
+
{
|
|
2469
|
+
title: "事件配置",
|
|
2470
|
+
items: [
|
|
2471
|
+
{
|
|
2472
|
+
name: "events",
|
|
2473
|
+
src: "datasource",
|
|
2474
|
+
type: "event-select"
|
|
2475
|
+
}
|
|
2476
|
+
]
|
|
2477
|
+
},
|
|
2478
|
+
{
|
|
2479
|
+
title: "mock数据",
|
|
2480
|
+
items: [
|
|
2481
|
+
{
|
|
2482
|
+
name: "mocks",
|
|
2483
|
+
type: "data-source-mocks",
|
|
2484
|
+
defaultValue: () => []
|
|
2485
|
+
}
|
|
2486
|
+
]
|
|
2487
|
+
},
|
|
2488
|
+
{
|
|
2489
|
+
title: "请求参数裁剪",
|
|
2490
|
+
display: (formState, { model }) => model.type === "http",
|
|
2491
|
+
items: [
|
|
2492
|
+
{
|
|
2493
|
+
name: "beforeRequest",
|
|
2494
|
+
type: "vs-code",
|
|
2495
|
+
parse: true,
|
|
2496
|
+
height: "600px"
|
|
2497
|
+
}
|
|
2498
|
+
]
|
|
2499
|
+
},
|
|
2500
|
+
{
|
|
2501
|
+
title: "响应数据裁剪",
|
|
2502
|
+
display: (formState, { model }) => model.type === "http",
|
|
2503
|
+
items: [
|
|
2504
|
+
{
|
|
2505
|
+
name: "afterResponse",
|
|
2506
|
+
type: "vs-code",
|
|
2507
|
+
parse: true,
|
|
2508
|
+
height: "600px"
|
|
2509
|
+
}
|
|
2510
|
+
]
|
|
2371
2511
|
}
|
|
2372
|
-
|
|
2373
|
-
}
|
|
2512
|
+
]
|
|
2374
2513
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2514
|
+
];
|
|
2515
|
+
const getFormConfig = (type, configs) => {
|
|
2516
|
+
switch (type) {
|
|
2517
|
+
case "base":
|
|
2518
|
+
return fillConfig$1([]);
|
|
2519
|
+
case "http":
|
|
2520
|
+
return fillConfig$1(HttpFormConfig);
|
|
2521
|
+
default:
|
|
2522
|
+
return fillConfig$1(configs[type] || []);
|
|
2382
2523
|
}
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2524
|
+
};
|
|
2525
|
+
const getFormValue = (type, values) => {
|
|
2526
|
+
if (type !== "http") {
|
|
2527
|
+
return values;
|
|
2528
|
+
}
|
|
2529
|
+
return {
|
|
2530
|
+
beforeRequest: `(options, context) => {
|
|
2531
|
+
/**
|
|
2532
|
+
* 用户可以直接编写函数,在原始接口调用之前,会运行该函数,将这个函数的返回值作为该数据源接口的入参
|
|
2533
|
+
*
|
|
2534
|
+
* options: HttpOptions
|
|
2535
|
+
*
|
|
2536
|
+
* interface HttpOptions {
|
|
2537
|
+
* // 请求链接
|
|
2538
|
+
* url: string;
|
|
2539
|
+
* // query参数
|
|
2540
|
+
* params?: Record<string, string>;
|
|
2541
|
+
* // body数据
|
|
2542
|
+
* data?: Record<string, any>;
|
|
2543
|
+
* // 请求头
|
|
2544
|
+
* headers?: Record<string, string>;
|
|
2545
|
+
* // 请求方法 GET/POST
|
|
2546
|
+
* method?: Method;
|
|
2547
|
+
* }
|
|
2548
|
+
*
|
|
2549
|
+
* context:上下文对象
|
|
2550
|
+
*
|
|
2551
|
+
* interface Content {
|
|
2552
|
+
* app: AppCore;
|
|
2553
|
+
* dataSource: HttpDataSource;
|
|
2554
|
+
* }
|
|
2555
|
+
*
|
|
2556
|
+
* return: HttpOptions
|
|
2557
|
+
*/
|
|
2558
|
+
|
|
2559
|
+
// 此处的返回值会作为这个接口的入参
|
|
2560
|
+
return options;
|
|
2561
|
+
}`,
|
|
2562
|
+
afterResponse: `(response, context) => {
|
|
2563
|
+
/**
|
|
2564
|
+
* 用户可以直接编写函数,在原始接口返回之后,会运行该函数,将这个函数的返回值作为该数据源接口的返回
|
|
2565
|
+
|
|
2566
|
+
* context:上下文对象
|
|
2567
|
+
*
|
|
2568
|
+
* interface Content {
|
|
2569
|
+
* app: AppCore;
|
|
2570
|
+
* dataSource: HttpDataSource;
|
|
2571
|
+
* }
|
|
2572
|
+
*
|
|
2573
|
+
*/
|
|
2574
|
+
|
|
2575
|
+
// 此处的返回值会作为这个接口的返回值
|
|
2576
|
+
return response;
|
|
2577
|
+
}`,
|
|
2578
|
+
...values
|
|
2579
|
+
};
|
|
2580
|
+
};
|
|
2581
|
+
const getDisplayField = (dataSources, key) => {
|
|
2582
|
+
const displayState = [];
|
|
2583
|
+
const matches = key.matchAll(/\$\{([\s\S]+?)\}/g);
|
|
2584
|
+
let index = 0;
|
|
2585
|
+
for (const match of matches) {
|
|
2586
|
+
if (typeof match.index === "undefined")
|
|
2587
|
+
break;
|
|
2588
|
+
displayState.push({
|
|
2589
|
+
type: "text",
|
|
2590
|
+
value: key.substring(index, match.index)
|
|
2591
|
+
});
|
|
2592
|
+
let dsText = "";
|
|
2593
|
+
let ds;
|
|
2594
|
+
let fields;
|
|
2595
|
+
match[1].split(".").forEach((item, index2) => {
|
|
2596
|
+
if (index2 === 0) {
|
|
2597
|
+
ds = dataSources.find((ds2) => ds2.id === item);
|
|
2598
|
+
dsText += ds?.title || item;
|
|
2599
|
+
fields = ds?.fields;
|
|
2414
2600
|
return;
|
|
2415
2601
|
}
|
|
2602
|
+
const field = fields?.find((field2) => field2.name === item);
|
|
2603
|
+
fields = field?.fields;
|
|
2604
|
+
dsText += `.${field?.title || item}`;
|
|
2416
2605
|
});
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
* @param {boolean} raw 是否使用toRaw
|
|
2423
|
-
* @returns 组件节点配置
|
|
2424
|
-
*/
|
|
2425
|
-
getNodeById(id, raw = true) {
|
|
2426
|
-
const { node } = this.getNodeInfo(id, raw);
|
|
2427
|
-
return node;
|
|
2606
|
+
displayState.push({
|
|
2607
|
+
type: "var",
|
|
2608
|
+
value: dsText
|
|
2609
|
+
});
|
|
2610
|
+
index = match.index + match[0].length;
|
|
2428
2611
|
}
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
*/
|
|
2435
|
-
getParentById(id, raw = true) {
|
|
2436
|
-
const { parent } = this.getNodeInfo(id, raw);
|
|
2437
|
-
return parent;
|
|
2612
|
+
if (index < key.length) {
|
|
2613
|
+
displayState.push({
|
|
2614
|
+
type: "text",
|
|
2615
|
+
value: key.substring(index)
|
|
2616
|
+
});
|
|
2438
2617
|
}
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
return parent.layout;
|
|
2618
|
+
return displayState;
|
|
2619
|
+
};
|
|
2620
|
+
const getCascaderOptionsFromFields = (fields = [], dataSourceFieldType = ["any"]) => {
|
|
2621
|
+
const child = [];
|
|
2622
|
+
fields.forEach((field) => {
|
|
2623
|
+
if (!dataSourceFieldType.length) {
|
|
2624
|
+
dataSourceFieldType.push("any");
|
|
2447
2625
|
}
|
|
2448
|
-
|
|
2449
|
-
|
|
2626
|
+
const children = getCascaderOptionsFromFields(field.fields, dataSourceFieldType);
|
|
2627
|
+
const item = {
|
|
2628
|
+
label: field.title || field.name,
|
|
2629
|
+
value: field.name,
|
|
2630
|
+
children
|
|
2631
|
+
};
|
|
2632
|
+
const fieldType = field.type || "any";
|
|
2633
|
+
if (dataSourceFieldType.includes("any") || dataSourceFieldType.includes(fieldType)) {
|
|
2634
|
+
child.push(item);
|
|
2635
|
+
return;
|
|
2450
2636
|
}
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
/**
|
|
2454
|
-
* 选中指定节点(将指定节点设置成当前选中状态)
|
|
2455
|
-
* @param config 指定节点配置或者ID
|
|
2456
|
-
* @returns 当前选中的节点配置
|
|
2457
|
-
*/
|
|
2458
|
-
async select(config) {
|
|
2459
|
-
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
|
2460
|
-
this.set("nodes", node ? [node] : []);
|
|
2461
|
-
this.set("page", page);
|
|
2462
|
-
this.set("parent", parent);
|
|
2463
|
-
if (page) {
|
|
2464
|
-
historyService.changePage(vue.toRaw(page));
|
|
2465
|
-
} else {
|
|
2466
|
-
historyService.resetState();
|
|
2637
|
+
if (!dataSourceFieldType.includes(fieldType) && !["array", "object", "any"].includes(fieldType)) {
|
|
2638
|
+
return;
|
|
2467
2639
|
}
|
|
2468
|
-
if (
|
|
2469
|
-
|
|
2470
|
-
"editor:select",
|
|
2471
|
-
{
|
|
2472
|
-
node,
|
|
2473
|
-
page,
|
|
2474
|
-
parent
|
|
2475
|
-
},
|
|
2476
|
-
utils.getNodePath(node.id, this.get("root")?.items)
|
|
2477
|
-
);
|
|
2640
|
+
if (!children.length && ["object", "array", "any"].includes(field.type || "")) {
|
|
2641
|
+
return;
|
|
2478
2642
|
}
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2643
|
+
child.push(item);
|
|
2644
|
+
});
|
|
2645
|
+
return child;
|
|
2646
|
+
};
|
|
2647
|
+
|
|
2648
|
+
const canUsePluginMethods$3 = {
|
|
2649
|
+
async: [],
|
|
2650
|
+
sync: [
|
|
2651
|
+
"getFormConfig",
|
|
2652
|
+
"setFormConfig",
|
|
2653
|
+
"getFormValue",
|
|
2654
|
+
"setFormValue",
|
|
2655
|
+
"getFormEvent",
|
|
2656
|
+
"setFormEvent",
|
|
2657
|
+
"getFormMethod",
|
|
2658
|
+
"setFormMethod",
|
|
2659
|
+
"add",
|
|
2660
|
+
"update",
|
|
2661
|
+
"remove",
|
|
2662
|
+
"createId"
|
|
2663
|
+
]
|
|
2664
|
+
};
|
|
2665
|
+
class DataSource extends BaseService {
|
|
2666
|
+
state = vue.reactive({
|
|
2667
|
+
datasourceTypeList: [],
|
|
2668
|
+
dataSources: [],
|
|
2669
|
+
editable: true,
|
|
2670
|
+
configs: {},
|
|
2671
|
+
values: {},
|
|
2672
|
+
events: {},
|
|
2673
|
+
methods: {}
|
|
2674
|
+
});
|
|
2675
|
+
constructor() {
|
|
2676
|
+
super(canUsePluginMethods$3.sync.map((methodName) => ({ name: methodName, isAsync: false })));
|
|
2494
2677
|
}
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
const page = vue.toRaw(this.get("page"));
|
|
2498
|
-
if (!page)
|
|
2499
|
-
throw new Error("page不能为空");
|
|
2500
|
-
if (!root)
|
|
2501
|
-
throw new Error("root不能为空");
|
|
2502
|
-
const index = getNodeIndex(page.id, root);
|
|
2503
|
-
const nextPage = root.items[index + 1] || root.items[0];
|
|
2504
|
-
await this.select(nextPage);
|
|
2505
|
-
this.get("stage")?.select(nextPage.id);
|
|
2506
|
-
return nextPage;
|
|
2678
|
+
set(name, value) {
|
|
2679
|
+
this.state[name] = value;
|
|
2507
2680
|
}
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
* @param config 指定节点配置或者ID
|
|
2511
|
-
* @returns 当前高亮的节点配置
|
|
2512
|
-
*/
|
|
2513
|
-
highlight(config) {
|
|
2514
|
-
const { node } = this.selectedConfigExceptionHandler(config);
|
|
2515
|
-
const currentHighlightNode = this.get("highlightNode");
|
|
2516
|
-
if (currentHighlightNode === node)
|
|
2517
|
-
return;
|
|
2518
|
-
this.set("highlightNode", node);
|
|
2681
|
+
get(name) {
|
|
2682
|
+
return this.state[name];
|
|
2519
2683
|
}
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
* @param ids 指定节点ID
|
|
2523
|
-
* @returns 加入多选的节点配置
|
|
2524
|
-
*/
|
|
2525
|
-
multiSelect(ids) {
|
|
2526
|
-
const nodes = [];
|
|
2527
|
-
const idsUnique = lodashEs.uniq(ids);
|
|
2528
|
-
idsUnique.forEach((id) => {
|
|
2529
|
-
const { node } = this.getNodeInfo(id);
|
|
2530
|
-
if (!node)
|
|
2531
|
-
return;
|
|
2532
|
-
nodes.push(node);
|
|
2533
|
-
});
|
|
2534
|
-
this.set("nodes", nodes);
|
|
2684
|
+
getFormConfig(type = "base") {
|
|
2685
|
+
return getFormConfig(utils.toLine(type), this.get("configs"));
|
|
2535
2686
|
}
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
if (!root)
|
|
2539
|
-
return;
|
|
2540
|
-
this.set("nodes", [root]);
|
|
2541
|
-
this.set("parent", null);
|
|
2542
|
-
this.set("page", null);
|
|
2543
|
-
this.set("stage", null);
|
|
2544
|
-
this.set("highlightNode", null);
|
|
2687
|
+
setFormConfig(type, config) {
|
|
2688
|
+
this.get("configs")[utils.toLine(type)] = config;
|
|
2545
2689
|
}
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
if (!root)
|
|
2549
|
-
throw new Error("root为空");
|
|
2550
|
-
const curNode = this.get("node");
|
|
2551
|
-
const stage = this.get("stage");
|
|
2552
|
-
if (!curNode)
|
|
2553
|
-
throw new Error("当前选中节点为空");
|
|
2554
|
-
if ((parent.type === schema.NodeType.ROOT || curNode?.type === schema.NodeType.ROOT) && !(utils.isPage(node) || utils.isPageFragment(node))) {
|
|
2555
|
-
throw new Error("app下不能添加组件");
|
|
2556
|
-
}
|
|
2557
|
-
if (parent.id !== curNode.id && !(utils.isPage(node) || utils.isPageFragment(node))) {
|
|
2558
|
-
const index = parent.items.indexOf(curNode);
|
|
2559
|
-
parent.items?.splice(index + 1, 0, node);
|
|
2560
|
-
} else {
|
|
2561
|
-
parent.items?.push(node);
|
|
2562
|
-
}
|
|
2563
|
-
const layout = await this.getLayout(vue.toRaw(parent), node);
|
|
2564
|
-
node.style = getInitPositionStyle(node.style, layout);
|
|
2565
|
-
await stage?.add({
|
|
2566
|
-
config: lodashEs.cloneDeep(node),
|
|
2567
|
-
parent: lodashEs.cloneDeep(parent),
|
|
2568
|
-
parentId: parent.id,
|
|
2569
|
-
root: lodashEs.cloneDeep(root)
|
|
2570
|
-
});
|
|
2571
|
-
const newStyle = fixNodePosition(node, parent, stage);
|
|
2572
|
-
if (newStyle && (newStyle.top !== node.style.top || newStyle.left !== node.style.left)) {
|
|
2573
|
-
node.style = newStyle;
|
|
2574
|
-
await stage?.update({ config: lodashEs.cloneDeep(node), parentId: parent.id, root: lodashEs.cloneDeep(root) });
|
|
2575
|
-
}
|
|
2576
|
-
this.addModifiedNodeId(node.id);
|
|
2577
|
-
return node;
|
|
2690
|
+
getFormValue(type = "base") {
|
|
2691
|
+
return getFormValue(utils.toLine(type), this.get("values")[type]);
|
|
2578
2692
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
* @param addConfig 将要添加的组件节点配置
|
|
2582
|
-
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
2583
|
-
* @returns 添加后的节点
|
|
2584
|
-
*/
|
|
2585
|
-
async add(addNode, parent) {
|
|
2586
|
-
const stage = this.get("stage");
|
|
2587
|
-
const addNodes = [];
|
|
2588
|
-
if (!Array.isArray(addNode)) {
|
|
2589
|
-
const { type, inputEvent, ...config } = addNode;
|
|
2590
|
-
if (!type)
|
|
2591
|
-
throw new Error("组件类型不能为空");
|
|
2592
|
-
addNodes.push({ ...vue.toRaw(await propsService.getPropsValue(type, config)) });
|
|
2593
|
-
} else {
|
|
2594
|
-
addNodes.push(...addNode);
|
|
2595
|
-
}
|
|
2596
|
-
const newNodes = await Promise.all(
|
|
2597
|
-
addNodes.map((node) => {
|
|
2598
|
-
const root = this.get("root");
|
|
2599
|
-
if ((utils.isPage(node) || utils.isPageFragment(node)) && root) {
|
|
2600
|
-
return this.doAdd(node, root);
|
|
2601
|
-
}
|
|
2602
|
-
const parentNode = parent && typeof parent !== "function" ? parent : getAddParent(node);
|
|
2603
|
-
if (!parentNode)
|
|
2604
|
-
throw new Error("未找到父元素");
|
|
2605
|
-
return this.doAdd(node, parentNode);
|
|
2606
|
-
})
|
|
2607
|
-
);
|
|
2608
|
-
if (newNodes.length > 1) {
|
|
2609
|
-
const newNodeIds = newNodes.map((node) => node.id);
|
|
2610
|
-
stage?.multiSelect(newNodeIds);
|
|
2611
|
-
await this.multiSelect(newNodeIds);
|
|
2612
|
-
} else {
|
|
2613
|
-
await this.select(newNodes[0]);
|
|
2614
|
-
if (utils.isPage(newNodes[0])) {
|
|
2615
|
-
this.state.pageLength += 1;
|
|
2616
|
-
} else if (utils.isPageFragment(newNodes[0])) {
|
|
2617
|
-
this.state.pageFragmentLength += 1;
|
|
2618
|
-
} else {
|
|
2619
|
-
stage?.select(newNodes[0].id);
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2622
|
-
if (!(utils.isPage(newNodes[0]) || utils.isPageFragment(newNodes[0]))) {
|
|
2623
|
-
this.pushHistoryState();
|
|
2624
|
-
}
|
|
2625
|
-
this.emit("add", newNodes);
|
|
2626
|
-
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
2693
|
+
setFormValue(type, value) {
|
|
2694
|
+
this.get("values")[utils.toLine(type)] = value;
|
|
2627
2695
|
}
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
if (!root)
|
|
2631
|
-
throw new Error("root不能为空");
|
|
2632
|
-
const { parent, node: curNode } = this.getNodeInfo(node.id, false);
|
|
2633
|
-
if (!parent || !curNode)
|
|
2634
|
-
throw new Error("找不要删除的节点");
|
|
2635
|
-
const index = getNodeIndex(curNode.id, parent);
|
|
2636
|
-
if (typeof index !== "number" || index === -1)
|
|
2637
|
-
throw new Error("找不要删除的节点");
|
|
2638
|
-
parent.items?.splice(index, 1);
|
|
2639
|
-
const stage = this.get("stage");
|
|
2640
|
-
stage?.remove({ id: node.id, parentId: parent.id, root: lodashEs.cloneDeep(root) });
|
|
2641
|
-
const selectDefault = async (pages) => {
|
|
2642
|
-
if (pages[0]) {
|
|
2643
|
-
await this.select(pages[0]);
|
|
2644
|
-
stage?.select(pages[0].id);
|
|
2645
|
-
} else {
|
|
2646
|
-
this.selectRoot();
|
|
2647
|
-
historyService.resetPage();
|
|
2648
|
-
}
|
|
2649
|
-
};
|
|
2650
|
-
const rootItems = root.items || [];
|
|
2651
|
-
if (utils.isPage(node)) {
|
|
2652
|
-
this.state.pageLength -= 1;
|
|
2653
|
-
await selectDefault(getPageList(root));
|
|
2654
|
-
} else if (utils.isPageFragment(node)) {
|
|
2655
|
-
this.state.pageFragmentLength -= 1;
|
|
2656
|
-
await selectDefault(getPageFragmentList(root));
|
|
2657
|
-
} else {
|
|
2658
|
-
await this.select(parent);
|
|
2659
|
-
stage?.select(parent.id);
|
|
2660
|
-
this.addModifiedNodeId(parent.id);
|
|
2661
|
-
}
|
|
2662
|
-
if (!rootItems.length) {
|
|
2663
|
-
this.resetModifiedNodeId();
|
|
2664
|
-
historyService.reset();
|
|
2665
|
-
}
|
|
2696
|
+
getFormEvent(type = "base") {
|
|
2697
|
+
return this.get("events")[utils.toLine(type)] || [];
|
|
2666
2698
|
}
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
* @param {Object} node
|
|
2670
|
-
*/
|
|
2671
|
-
async remove(nodeOrNodeList) {
|
|
2672
|
-
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
2673
|
-
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
2674
|
-
if (!(utils.isPage(nodes[0]) || utils.isPageFragment(nodes[0]))) {
|
|
2675
|
-
this.pushHistoryState();
|
|
2676
|
-
}
|
|
2677
|
-
this.emit("remove", nodes);
|
|
2699
|
+
setFormEvent(type, value = []) {
|
|
2700
|
+
this.get("events")[utils.toLine(type)] = value;
|
|
2678
2701
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
return "";
|
|
2693
|
-
}
|
|
2694
|
-
if (lodashEs.isObject(srcValue) && Array.isArray(objValue)) {
|
|
2695
|
-
return srcValue;
|
|
2696
|
-
}
|
|
2697
|
-
if (Array.isArray(srcValue)) {
|
|
2698
|
-
return srcValue;
|
|
2699
|
-
}
|
|
2700
|
-
});
|
|
2701
|
-
if (!newConfig.type)
|
|
2702
|
-
throw new Error("配置缺少type值");
|
|
2703
|
-
if (newConfig.type === schema.NodeType.ROOT) {
|
|
2704
|
-
this.set("root", newConfig);
|
|
2705
|
-
return newConfig;
|
|
2706
|
-
}
|
|
2707
|
-
const { parent } = info;
|
|
2708
|
-
if (!parent)
|
|
2709
|
-
throw new Error("获取不到父级节点");
|
|
2710
|
-
const parentNodeItems = parent.items;
|
|
2711
|
-
const index = getNodeIndex(newConfig.id, parent);
|
|
2712
|
-
if (!parentNodeItems || typeof index === "undefined" || index === -1)
|
|
2713
|
-
throw new Error("更新的节点未找到");
|
|
2714
|
-
const newLayout = await this.getLayout(newConfig);
|
|
2715
|
-
const layout = await this.getLayout(node);
|
|
2716
|
-
if (Array.isArray(newConfig.items) && newLayout !== layout) {
|
|
2717
|
-
newConfig = setChildrenLayout(newConfig, newLayout);
|
|
2718
|
-
}
|
|
2719
|
-
parentNodeItems[index] = newConfig;
|
|
2720
|
-
const nodes = this.get("nodes");
|
|
2721
|
-
const targetIndex = nodes.findIndex((nodeItem) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
2722
|
-
nodes.splice(targetIndex, 1, newConfig);
|
|
2723
|
-
this.set("nodes", [...nodes]);
|
|
2724
|
-
this.get("stage")?.update({
|
|
2725
|
-
config: lodashEs.cloneDeep(newConfig),
|
|
2726
|
-
parentId: parent.id,
|
|
2727
|
-
root: lodashEs.cloneDeep(root)
|
|
2728
|
-
});
|
|
2729
|
-
if (utils.isPage(newConfig) || utils.isPageFragment(newConfig)) {
|
|
2730
|
-
this.set("page", newConfig);
|
|
2731
|
-
}
|
|
2732
|
-
this.addModifiedNodeId(newConfig.id);
|
|
2702
|
+
getFormMethod(type = "base") {
|
|
2703
|
+
return this.get("methods")[utils.toLine(type)] || [];
|
|
2704
|
+
}
|
|
2705
|
+
setFormMethod(type, value = []) {
|
|
2706
|
+
this.get("methods")[utils.toLine(type)] = value;
|
|
2707
|
+
}
|
|
2708
|
+
add(config) {
|
|
2709
|
+
const newConfig = {
|
|
2710
|
+
...config,
|
|
2711
|
+
id: config.id && !this.getDataSourceById(config.id) ? config.id : this.createId()
|
|
2712
|
+
};
|
|
2713
|
+
this.get("dataSources").push(newConfig);
|
|
2714
|
+
this.emit("add", newConfig);
|
|
2733
2715
|
return newConfig;
|
|
2734
2716
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
const nodes = Array.isArray(config) ? config : [config];
|
|
2742
|
-
const newNodes = await Promise.all(nodes.map((node) => this.doUpdate(node)));
|
|
2743
|
-
if (newNodes[0]?.type !== schema.NodeType.ROOT) {
|
|
2744
|
-
this.pushHistoryState();
|
|
2745
|
-
}
|
|
2746
|
-
this.emit("update", newNodes);
|
|
2747
|
-
return Array.isArray(config) ? newNodes : newNodes[0];
|
|
2717
|
+
update(config) {
|
|
2718
|
+
const dataSources = this.get("dataSources");
|
|
2719
|
+
const index = dataSources.findIndex((ds) => ds.id === config.id);
|
|
2720
|
+
dataSources[index] = lodashEs.cloneDeep(config);
|
|
2721
|
+
this.emit("update", config);
|
|
2722
|
+
return config;
|
|
2748
2723
|
}
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
*/
|
|
2755
|
-
async sort(id1, id2) {
|
|
2756
|
-
const root = this.get("root");
|
|
2757
|
-
if (!root)
|
|
2758
|
-
throw new Error("root为空");
|
|
2759
|
-
const node = this.get("node");
|
|
2760
|
-
if (!node)
|
|
2761
|
-
throw new Error("当前节点为空");
|
|
2762
|
-
const parent = lodashEs.cloneDeep(vue.toRaw(this.get("parent")));
|
|
2763
|
-
if (!parent)
|
|
2764
|
-
throw new Error("父节点为空");
|
|
2765
|
-
const index2 = parent.items.findIndex((node2) => `${node2.id}` === `${id2}`);
|
|
2766
|
-
if (index2 < 0)
|
|
2767
|
-
return;
|
|
2768
|
-
const index1 = parent.items.findIndex((node2) => `${node2.id}` === `${id1}`);
|
|
2769
|
-
parent.items.splice(index2, 0, ...parent.items.splice(index1, 1));
|
|
2770
|
-
await this.update(parent);
|
|
2771
|
-
await this.select(node);
|
|
2772
|
-
this.get("stage")?.update({
|
|
2773
|
-
config: lodashEs.cloneDeep(node),
|
|
2774
|
-
parentId: parent.id,
|
|
2775
|
-
root: lodashEs.cloneDeep(root)
|
|
2776
|
-
});
|
|
2777
|
-
this.addModifiedNodeId(parent.id);
|
|
2778
|
-
this.pushHistoryState();
|
|
2724
|
+
remove(id) {
|
|
2725
|
+
const dataSources = this.get("dataSources");
|
|
2726
|
+
const index = dataSources.findIndex((ds) => ds.id === id);
|
|
2727
|
+
dataSources.splice(index, 1);
|
|
2728
|
+
this.emit("remove", id);
|
|
2779
2729
|
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2730
|
+
createId() {
|
|
2731
|
+
return `ds_${utils.guid()}`;
|
|
2732
|
+
}
|
|
2733
|
+
getDataSourceById(id) {
|
|
2734
|
+
return this.get("dataSources").find((ds) => ds.id === id);
|
|
2735
|
+
}
|
|
2736
|
+
resetState() {
|
|
2737
|
+
this.set("dataSources", []);
|
|
2738
|
+
}
|
|
2739
|
+
destroy() {
|
|
2740
|
+
this.removeAllListeners();
|
|
2741
|
+
this.resetState();
|
|
2742
|
+
this.removeAllPlugins();
|
|
2743
|
+
}
|
|
2744
|
+
usePlugin(options) {
|
|
2745
|
+
super.usePlugin(options);
|
|
2789
2746
|
}
|
|
2790
2747
|
/**
|
|
2791
|
-
*
|
|
2748
|
+
* 复制时会带上组件关联的数据源
|
|
2792
2749
|
* @param config 组件节点配置
|
|
2793
2750
|
* @returns
|
|
2794
2751
|
*/
|
|
2795
2752
|
copyWithRelated(config) {
|
|
2796
2753
|
const copyNodes = Array.isArray(config) ? config : [config];
|
|
2797
|
-
depService.clearByType(dep.DepTargetType.
|
|
2798
|
-
depService.collect(copyNodes, true, dep.DepTargetType.
|
|
2799
|
-
const customTarget = depService.getTarget(
|
|
2800
|
-
|
|
2801
|
-
dep.DepTargetType.RELATED_COMP_WHEN_COPY
|
|
2802
|
-
);
|
|
2754
|
+
depService.clearByType(dep.DepTargetType.RELATED_DS_WHEN_COPY);
|
|
2755
|
+
depService.collect(copyNodes, true, dep.DepTargetType.RELATED_DS_WHEN_COPY);
|
|
2756
|
+
const customTarget = depService.getTarget(dep.DepTargetType.RELATED_DS_WHEN_COPY, dep.DepTargetType.RELATED_DS_WHEN_COPY);
|
|
2757
|
+
const copyData = [];
|
|
2803
2758
|
if (customTarget) {
|
|
2804
2759
|
Object.keys(customTarget.deps).forEach((nodeId) => {
|
|
2805
|
-
const node =
|
|
2760
|
+
const node = editorService.getNodeById(nodeId);
|
|
2806
2761
|
if (!node)
|
|
2807
2762
|
return;
|
|
2808
2763
|
customTarget.deps[nodeId].keys.forEach((key) => {
|
|
2809
|
-
const
|
|
2810
|
-
const isExist =
|
|
2764
|
+
const [relateDsId] = lodashEs.get(node, key);
|
|
2765
|
+
const isExist = copyData.find((dsItem) => dsItem.id === relateDsId);
|
|
2811
2766
|
if (!isExist) {
|
|
2812
|
-
const
|
|
2813
|
-
if (
|
|
2814
|
-
|
|
2767
|
+
const relateDs = this.getDataSourceById(relateDsId);
|
|
2768
|
+
if (relateDs) {
|
|
2769
|
+
copyData.push(relateDs);
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
});
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
storageService.setItem(COPY_DS_STORAGE_KEY, copyData, {
|
|
2776
|
+
protocol: Protocol.OBJECT
|
|
2777
|
+
});
|
|
2778
|
+
}
|
|
2779
|
+
/**
|
|
2780
|
+
* 粘贴数据源
|
|
2781
|
+
* @returns
|
|
2782
|
+
*/
|
|
2783
|
+
paste() {
|
|
2784
|
+
const dataSource = storageService.getItem(COPY_DS_STORAGE_KEY);
|
|
2785
|
+
dataSource.forEach((item) => {
|
|
2786
|
+
if (!this.getDataSourceById(item.id)) {
|
|
2787
|
+
this.add(item);
|
|
2788
|
+
}
|
|
2789
|
+
});
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
const dataSourceService = new DataSource();
|
|
2793
|
+
|
|
2794
|
+
const arrayOptions = [
|
|
2795
|
+
{ text: "包含", value: "include" },
|
|
2796
|
+
{ text: "不包含", value: "not_include" }
|
|
2797
|
+
];
|
|
2798
|
+
const eqOptions = [
|
|
2799
|
+
{ text: "等于", value: "=" },
|
|
2800
|
+
{ text: "不等于", value: "!=" }
|
|
2801
|
+
];
|
|
2802
|
+
const numberOptions = [
|
|
2803
|
+
{ text: "大于", value: ">" },
|
|
2804
|
+
{ text: "大于等于", value: ">=" },
|
|
2805
|
+
{ text: "小于", value: "<" },
|
|
2806
|
+
{ text: "小于等于", value: "<=" },
|
|
2807
|
+
{ text: "在范围内", value: "between" },
|
|
2808
|
+
{ text: "不在范围内", value: "not_between" }
|
|
2809
|
+
];
|
|
2810
|
+
const styleTabConfig = {
|
|
2811
|
+
title: "样式",
|
|
2812
|
+
items: [
|
|
2813
|
+
{
|
|
2814
|
+
name: "style",
|
|
2815
|
+
items: [
|
|
2816
|
+
{
|
|
2817
|
+
type: "fieldset",
|
|
2818
|
+
legend: "位置",
|
|
2819
|
+
items: [
|
|
2820
|
+
{
|
|
2821
|
+
type: "data-source-field-select",
|
|
2822
|
+
name: "position",
|
|
2823
|
+
text: "固定定位",
|
|
2824
|
+
checkStrictly: false,
|
|
2825
|
+
dataSourceFieldType: ["string"],
|
|
2826
|
+
fieldConfig: {
|
|
2827
|
+
type: "checkbox",
|
|
2828
|
+
activeValue: "fixed",
|
|
2829
|
+
inactiveValue: "absolute",
|
|
2830
|
+
defaultValue: "absolute"
|
|
2831
|
+
}
|
|
2832
|
+
},
|
|
2833
|
+
{
|
|
2834
|
+
type: "data-source-field-select",
|
|
2835
|
+
name: "left",
|
|
2836
|
+
text: "left",
|
|
2837
|
+
checkStrictly: false,
|
|
2838
|
+
dataSourceFieldType: ["string", "number"],
|
|
2839
|
+
fieldConfig: {
|
|
2840
|
+
type: "text"
|
|
2841
|
+
}
|
|
2842
|
+
},
|
|
2843
|
+
{
|
|
2844
|
+
type: "data-source-field-select",
|
|
2845
|
+
name: "top",
|
|
2846
|
+
text: "top",
|
|
2847
|
+
checkStrictly: false,
|
|
2848
|
+
dataSourceFieldType: ["string", "number"],
|
|
2849
|
+
fieldConfig: {
|
|
2850
|
+
type: "text"
|
|
2851
|
+
},
|
|
2852
|
+
disabled: (vm, { model }) => model.position === "fixed" && model._magic_position === "fixedBottom"
|
|
2853
|
+
},
|
|
2854
|
+
{
|
|
2855
|
+
type: "data-source-field-select",
|
|
2856
|
+
name: "right",
|
|
2857
|
+
text: "right",
|
|
2858
|
+
checkStrictly: false,
|
|
2859
|
+
dataSourceFieldType: ["string", "number"],
|
|
2860
|
+
fieldConfig: {
|
|
2861
|
+
type: "text"
|
|
2862
|
+
}
|
|
2863
|
+
},
|
|
2864
|
+
{
|
|
2865
|
+
type: "data-source-field-select",
|
|
2866
|
+
name: "bottom",
|
|
2867
|
+
text: "bottom",
|
|
2868
|
+
checkStrictly: false,
|
|
2869
|
+
dataSourceFieldType: ["string", "number"],
|
|
2870
|
+
fieldConfig: {
|
|
2871
|
+
type: "text"
|
|
2872
|
+
},
|
|
2873
|
+
disabled: (vm, { model }) => model.position === "fixed" && model._magic_position === "fixedTop"
|
|
2874
|
+
}
|
|
2875
|
+
]
|
|
2876
|
+
},
|
|
2877
|
+
{
|
|
2878
|
+
type: "fieldset",
|
|
2879
|
+
legend: "盒子",
|
|
2880
|
+
items: [
|
|
2881
|
+
{
|
|
2882
|
+
type: "data-source-field-select",
|
|
2883
|
+
name: "width",
|
|
2884
|
+
text: "宽度",
|
|
2885
|
+
checkStrictly: false,
|
|
2886
|
+
dataSourceFieldType: ["string", "number"],
|
|
2887
|
+
fieldConfig: {
|
|
2888
|
+
type: "text"
|
|
2889
|
+
}
|
|
2890
|
+
},
|
|
2891
|
+
{
|
|
2892
|
+
type: "data-source-field-select",
|
|
2893
|
+
name: "height",
|
|
2894
|
+
text: "高度",
|
|
2895
|
+
checkStrictly: false,
|
|
2896
|
+
dataSourceFieldType: ["string", "number"],
|
|
2897
|
+
fieldConfig: {
|
|
2898
|
+
type: "text"
|
|
2899
|
+
}
|
|
2900
|
+
},
|
|
2901
|
+
{
|
|
2902
|
+
type: "data-source-field-select",
|
|
2903
|
+
text: "overflow",
|
|
2904
|
+
name: "overflow",
|
|
2905
|
+
checkStrictly: false,
|
|
2906
|
+
dataSourceFieldType: ["string"],
|
|
2907
|
+
fieldConfig: {
|
|
2908
|
+
type: "select",
|
|
2909
|
+
options: [
|
|
2910
|
+
{ text: "visible", value: "visible" },
|
|
2911
|
+
{ text: "hidden", value: "hidden" },
|
|
2912
|
+
{ text: "clip", value: "clip" },
|
|
2913
|
+
{ text: "scroll", value: "scroll" },
|
|
2914
|
+
{ text: "auto", value: "auto" },
|
|
2915
|
+
{ text: "overlay", value: "overlay" }
|
|
2916
|
+
]
|
|
2917
|
+
}
|
|
2918
|
+
}
|
|
2919
|
+
]
|
|
2920
|
+
},
|
|
2921
|
+
{
|
|
2922
|
+
type: "fieldset",
|
|
2923
|
+
legend: "边框",
|
|
2924
|
+
items: [
|
|
2925
|
+
{
|
|
2926
|
+
type: "data-source-field-select",
|
|
2927
|
+
name: "borderWidth",
|
|
2928
|
+
text: "宽度",
|
|
2929
|
+
defaultValue: "0",
|
|
2930
|
+
checkStrictly: false,
|
|
2931
|
+
dataSourceFieldType: ["string", "number"],
|
|
2932
|
+
fieldConfig: {
|
|
2933
|
+
type: "text"
|
|
2934
|
+
}
|
|
2935
|
+
},
|
|
2936
|
+
{
|
|
2937
|
+
type: "data-source-field-select",
|
|
2938
|
+
name: "borderColor",
|
|
2939
|
+
text: "颜色",
|
|
2940
|
+
checkStrictly: false,
|
|
2941
|
+
dataSourceFieldType: ["string"],
|
|
2942
|
+
fieldConfig: {
|
|
2943
|
+
type: "text"
|
|
2944
|
+
}
|
|
2945
|
+
},
|
|
2946
|
+
{
|
|
2947
|
+
type: "data-source-field-select",
|
|
2948
|
+
name: "borderStyle",
|
|
2949
|
+
text: "样式",
|
|
2950
|
+
defaultValue: "none",
|
|
2951
|
+
checkStrictly: false,
|
|
2952
|
+
dataSourceFieldType: ["string"],
|
|
2953
|
+
fieldConfig: {
|
|
2954
|
+
type: "select",
|
|
2955
|
+
options: [
|
|
2956
|
+
{ text: "none", value: "none" },
|
|
2957
|
+
{ text: "hidden", value: "hidden" },
|
|
2958
|
+
{ text: "dotted", value: "dotted" },
|
|
2959
|
+
{ text: "dashed", value: "dashed" },
|
|
2960
|
+
{ text: "solid", value: "solid" },
|
|
2961
|
+
{ text: "double", value: "double" },
|
|
2962
|
+
{ text: "groove", value: "groove" },
|
|
2963
|
+
{ text: "ridge", value: "ridge" },
|
|
2964
|
+
{ text: "inset", value: "inset" },
|
|
2965
|
+
{ text: "outset", value: "outset" }
|
|
2966
|
+
]
|
|
2967
|
+
}
|
|
2815
2968
|
}
|
|
2816
|
-
|
|
2817
|
-
}
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
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;
|
|
2969
|
+
]
|
|
2970
|
+
},
|
|
2971
|
+
{
|
|
2972
|
+
type: "fieldset",
|
|
2973
|
+
legend: "背景",
|
|
2974
|
+
items: [
|
|
2975
|
+
{
|
|
2976
|
+
type: "data-source-field-select",
|
|
2977
|
+
name: "backgroundImage",
|
|
2978
|
+
text: "背景图",
|
|
2979
|
+
checkStrictly: false,
|
|
2980
|
+
dataSourceFieldType: ["string"],
|
|
2981
|
+
fieldConfig: {
|
|
2982
|
+
type: "text"
|
|
2983
|
+
}
|
|
2984
|
+
},
|
|
2985
|
+
{
|
|
2986
|
+
type: "data-source-field-select",
|
|
2987
|
+
name: "backgroundColor",
|
|
2988
|
+
text: "背景颜色",
|
|
2989
|
+
checkStrictly: false,
|
|
2990
|
+
dataSourceFieldType: ["string"],
|
|
2991
|
+
fieldConfig: {
|
|
2992
|
+
type: "colorPicker"
|
|
2993
|
+
}
|
|
2994
|
+
},
|
|
2995
|
+
{
|
|
2996
|
+
type: "data-source-field-select",
|
|
2997
|
+
name: "backgroundRepeat",
|
|
2998
|
+
text: "背景图重复",
|
|
2999
|
+
defaultValue: "no-repeat",
|
|
3000
|
+
checkStrictly: false,
|
|
3001
|
+
dataSourceFieldType: ["string"],
|
|
3002
|
+
fieldConfig: {
|
|
3003
|
+
type: "select",
|
|
3004
|
+
options: [
|
|
3005
|
+
{ text: "repeat", value: "repeat" },
|
|
3006
|
+
{ text: "repeat-x", value: "repeat-x" },
|
|
3007
|
+
{ text: "repeat-y", value: "repeat-y" },
|
|
3008
|
+
{ text: "no-repeat", value: "no-repeat" },
|
|
3009
|
+
{ text: "inherit", value: "inherit" }
|
|
3010
|
+
]
|
|
3011
|
+
}
|
|
3012
|
+
},
|
|
3013
|
+
{
|
|
3014
|
+
type: "data-source-field-select",
|
|
3015
|
+
name: "backgroundSize",
|
|
3016
|
+
text: "背景图大小",
|
|
3017
|
+
defaultValue: "100% 100%",
|
|
3018
|
+
checkStrictly: false,
|
|
3019
|
+
dataSourceFieldType: ["string"],
|
|
3020
|
+
fieldConfig: {
|
|
3021
|
+
type: "text"
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
]
|
|
3025
|
+
},
|
|
3026
|
+
{
|
|
3027
|
+
type: "fieldset",
|
|
3028
|
+
legend: "字体",
|
|
3029
|
+
items: [
|
|
3030
|
+
{
|
|
3031
|
+
type: "data-source-field-select",
|
|
3032
|
+
name: "color",
|
|
3033
|
+
text: "颜色",
|
|
3034
|
+
checkStrictly: false,
|
|
3035
|
+
dataSourceFieldType: ["string"],
|
|
3036
|
+
fieldConfig: {
|
|
3037
|
+
type: "colorPicker"
|
|
3038
|
+
}
|
|
3039
|
+
},
|
|
3040
|
+
{
|
|
3041
|
+
type: "data-source-field-select",
|
|
3042
|
+
name: "fontSize",
|
|
3043
|
+
text: "大小",
|
|
3044
|
+
checkStrictly: false,
|
|
3045
|
+
dataSourceFieldType: ["string", "number"],
|
|
3046
|
+
fieldConfig: {
|
|
3047
|
+
type: "text"
|
|
3048
|
+
}
|
|
3049
|
+
},
|
|
3050
|
+
{
|
|
3051
|
+
type: "data-source-field-select",
|
|
3052
|
+
name: "fontWeight",
|
|
3053
|
+
text: "粗细",
|
|
3054
|
+
checkStrictly: false,
|
|
3055
|
+
dataSourceFieldType: ["string", "number"],
|
|
3056
|
+
fieldConfig: {
|
|
3057
|
+
type: "text"
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
]
|
|
3061
|
+
},
|
|
3062
|
+
{
|
|
3063
|
+
type: "fieldset",
|
|
3064
|
+
legend: "变形",
|
|
3065
|
+
name: "transform",
|
|
3066
|
+
items: [
|
|
3067
|
+
{
|
|
3068
|
+
type: "data-source-field-select",
|
|
3069
|
+
name: "rotate",
|
|
3070
|
+
text: "旋转角度",
|
|
3071
|
+
checkStrictly: false,
|
|
3072
|
+
dataSourceFieldType: ["string"],
|
|
3073
|
+
fieldConfig: {
|
|
3074
|
+
type: "text"
|
|
3075
|
+
}
|
|
3076
|
+
},
|
|
3077
|
+
{
|
|
3078
|
+
type: "data-source-field-select",
|
|
3079
|
+
name: "scale",
|
|
3080
|
+
text: "缩放",
|
|
3081
|
+
checkStrictly: false,
|
|
3082
|
+
dataSourceFieldType: ["number", "string"],
|
|
3083
|
+
fieldConfig: {
|
|
3084
|
+
type: "text"
|
|
3085
|
+
}
|
|
3086
|
+
}
|
|
3087
|
+
]
|
|
2952
3088
|
}
|
|
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
|
-
}
|
|
2966
|
-
}
|
|
2967
|
-
async dragTo(config, targetParent, targetIndex) {
|
|
2968
|
-
if (!targetParent || !Array.isArray(targetParent.items))
|
|
2969
|
-
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
|
-
}
|
|
2983
|
-
const layout = await this.getLayout(parent);
|
|
2984
|
-
const newLayout = await this.getLayout(targetParent);
|
|
2985
|
-
if (newLayout !== layout) {
|
|
2986
|
-
setLayout(config, newLayout);
|
|
2987
|
-
}
|
|
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
|
-
});
|
|
2999
|
-
}
|
|
3000
|
-
this.addModifiedNodeId(config.id);
|
|
3001
|
-
this.addModifiedNodeId(parent.id);
|
|
3002
|
-
this.pushHistoryState();
|
|
3003
|
-
this.emit("drag-to", { index, targetIndex, config, parent, targetParent });
|
|
3004
|
-
}
|
|
3005
|
-
/**
|
|
3006
|
-
* 撤销当前操作
|
|
3007
|
-
* @returns 上一次数据
|
|
3008
|
-
*/
|
|
3009
|
-
async undo() {
|
|
3010
|
-
const value = historyService.undo();
|
|
3011
|
-
await this.changeHistoryState(value);
|
|
3012
|
-
return value;
|
|
3013
|
-
}
|
|
3014
|
-
/**
|
|
3015
|
-
* 恢复到下一步
|
|
3016
|
-
* @returns 下一步数据
|
|
3017
|
-
*/
|
|
3018
|
-
async redo() {
|
|
3019
|
-
const value = historyService.redo();
|
|
3020
|
-
await this.changeHistoryState(value);
|
|
3021
|
-
return value;
|
|
3022
|
-
}
|
|
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
|
-
}
|
|
3089
|
+
]
|
|
3049
3090
|
}
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
right: Number(style.right) - Number(left),
|
|
3061
|
-
left: ""
|
|
3062
|
-
});
|
|
3063
|
-
}
|
|
3091
|
+
]
|
|
3092
|
+
};
|
|
3093
|
+
const eventTabConfig = {
|
|
3094
|
+
title: "事件",
|
|
3095
|
+
items: [
|
|
3096
|
+
{
|
|
3097
|
+
name: "events",
|
|
3098
|
+
src: "component",
|
|
3099
|
+
labelWidth: "100px",
|
|
3100
|
+
type: "event-select"
|
|
3064
3101
|
}
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
this.removeAllPlugins();
|
|
3081
|
-
}
|
|
3082
|
-
resetModifiedNodeId() {
|
|
3083
|
-
this.get("modifiedNodeIds").clear();
|
|
3084
|
-
}
|
|
3085
|
-
usePlugin(options) {
|
|
3086
|
-
super.usePlugin(options);
|
|
3087
|
-
}
|
|
3088
|
-
addModifiedNodeId(id) {
|
|
3089
|
-
if (!this.isHistoryStateChange) {
|
|
3090
|
-
this.get("modifiedNodeIds").set(id, id);
|
|
3102
|
+
]
|
|
3103
|
+
};
|
|
3104
|
+
const advancedTabConfig = {
|
|
3105
|
+
title: "高级",
|
|
3106
|
+
lazy: true,
|
|
3107
|
+
items: [
|
|
3108
|
+
{
|
|
3109
|
+
name: "created",
|
|
3110
|
+
text: "created",
|
|
3111
|
+
type: "code-select"
|
|
3112
|
+
},
|
|
3113
|
+
{
|
|
3114
|
+
name: "mounted",
|
|
3115
|
+
text: "mounted",
|
|
3116
|
+
type: "code-select"
|
|
3091
3117
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3118
|
+
]
|
|
3119
|
+
};
|
|
3120
|
+
const displayTabConfig = {
|
|
3121
|
+
title: "显示条件",
|
|
3122
|
+
display: (vm, { model }) => model.type !== "page",
|
|
3123
|
+
items: [
|
|
3124
|
+
{
|
|
3125
|
+
type: "groupList",
|
|
3126
|
+
name: "displayConds",
|
|
3127
|
+
titlePrefix: "条件组",
|
|
3128
|
+
expandAll: true,
|
|
3129
|
+
items: [
|
|
3130
|
+
{
|
|
3131
|
+
type: "table",
|
|
3132
|
+
name: "cond",
|
|
3133
|
+
items: [
|
|
3134
|
+
{
|
|
3135
|
+
type: "data-source-field-select",
|
|
3136
|
+
name: "field",
|
|
3137
|
+
value: "key",
|
|
3138
|
+
label: "字段",
|
|
3139
|
+
checkStrictly: false,
|
|
3140
|
+
dataSourceFieldType: ["string", "number", "boolean", "any"]
|
|
3141
|
+
},
|
|
3142
|
+
{
|
|
3143
|
+
type: "select",
|
|
3144
|
+
options: (mForm, { model }) => {
|
|
3145
|
+
const [id, ...fieldNames] = model.field;
|
|
3146
|
+
const ds = dataSourceService.getDataSourceById(id);
|
|
3147
|
+
let fields = ds?.fields || [];
|
|
3148
|
+
let type = "";
|
|
3149
|
+
(fieldNames || []).forEach((fieldName) => {
|
|
3150
|
+
const field = fields.find((f) => f.name === fieldName);
|
|
3151
|
+
fields = field?.fields || [];
|
|
3152
|
+
type = field?.type || "";
|
|
3153
|
+
});
|
|
3154
|
+
if (type === "array") {
|
|
3155
|
+
return arrayOptions;
|
|
3156
|
+
}
|
|
3157
|
+
if (type === "boolean") {
|
|
3158
|
+
return [
|
|
3159
|
+
{ text: "是", value: "is" },
|
|
3160
|
+
{ text: "不是", value: "not" }
|
|
3161
|
+
];
|
|
3162
|
+
}
|
|
3163
|
+
if (type === "number") {
|
|
3164
|
+
return [...eqOptions, ...numberOptions];
|
|
3165
|
+
}
|
|
3166
|
+
if (type === "string") {
|
|
3167
|
+
return [...arrayOptions, ...eqOptions];
|
|
3168
|
+
}
|
|
3169
|
+
return [...arrayOptions, ...eqOptions, ...numberOptions];
|
|
3170
|
+
},
|
|
3171
|
+
label: "条件",
|
|
3172
|
+
name: "op"
|
|
3173
|
+
},
|
|
3174
|
+
{
|
|
3175
|
+
label: "值",
|
|
3176
|
+
items: [
|
|
3177
|
+
{
|
|
3178
|
+
name: "value",
|
|
3179
|
+
type: (mForm, { model }) => {
|
|
3180
|
+
const [id, ...fieldNames] = model.field;
|
|
3181
|
+
const ds = dataSourceService.getDataSourceById(id);
|
|
3182
|
+
let fields = ds?.fields || [];
|
|
3183
|
+
let type = "";
|
|
3184
|
+
(fieldNames || []).forEach((fieldName) => {
|
|
3185
|
+
const field = fields.find((f) => f.name === fieldName);
|
|
3186
|
+
fields = field?.fields || [];
|
|
3187
|
+
type = field?.type || "";
|
|
3188
|
+
});
|
|
3189
|
+
if (type === "number") {
|
|
3190
|
+
return "number";
|
|
3191
|
+
}
|
|
3192
|
+
if (type === "boolean") {
|
|
3193
|
+
return "select";
|
|
3194
|
+
}
|
|
3195
|
+
return "text";
|
|
3196
|
+
},
|
|
3197
|
+
options: [
|
|
3198
|
+
{ text: "true", value: true },
|
|
3199
|
+
{ text: "false", value: false }
|
|
3200
|
+
],
|
|
3201
|
+
display: (vm, { model }) => !["between", "not_between"].includes(model.op)
|
|
3202
|
+
},
|
|
3203
|
+
{
|
|
3204
|
+
name: "range",
|
|
3205
|
+
type: "number-range",
|
|
3206
|
+
display: (vm, { model }) => ["between", "not_between"].includes(model.op)
|
|
3207
|
+
}
|
|
3208
|
+
]
|
|
3209
|
+
}
|
|
3210
|
+
]
|
|
3211
|
+
}
|
|
3212
|
+
]
|
|
3102
3213
|
}
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3214
|
+
]
|
|
3215
|
+
};
|
|
3216
|
+
const fillConfig = (config = [], labelWidth = "80px") => [
|
|
3217
|
+
{
|
|
3218
|
+
type: "tab",
|
|
3219
|
+
labelWidth,
|
|
3220
|
+
items: [
|
|
3221
|
+
{
|
|
3222
|
+
title: "属性",
|
|
3223
|
+
items: [
|
|
3224
|
+
// 组件类型,必须要有
|
|
3225
|
+
{
|
|
3226
|
+
text: "type",
|
|
3227
|
+
name: "type",
|
|
3228
|
+
type: "hidden"
|
|
3229
|
+
},
|
|
3230
|
+
// 组件id,必须要有
|
|
3231
|
+
{
|
|
3232
|
+
name: "id",
|
|
3233
|
+
type: "display",
|
|
3234
|
+
text: "id"
|
|
3235
|
+
},
|
|
3236
|
+
{
|
|
3237
|
+
name: "name",
|
|
3238
|
+
text: "组件名称"
|
|
3239
|
+
},
|
|
3240
|
+
...config
|
|
3241
|
+
]
|
|
3242
|
+
},
|
|
3243
|
+
{ ...styleTabConfig },
|
|
3244
|
+
{ ...eventTabConfig },
|
|
3245
|
+
{ ...advancedTabConfig },
|
|
3246
|
+
{ ...displayTabConfig }
|
|
3247
|
+
]
|
|
3118
3248
|
}
|
|
3119
|
-
|
|
3120
|
-
|
|
3121
|
-
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
} else if (!isFixed(newConfig) && isFixed(src)) {
|
|
3125
|
-
newConfig.style = await Fixed2Other(newConfig, root, this.getLayout);
|
|
3126
|
-
}
|
|
3127
|
-
}
|
|
3128
|
-
return newConfig;
|
|
3249
|
+
];
|
|
3250
|
+
|
|
3251
|
+
const log = (...args) => {
|
|
3252
|
+
if (process.env.NODE_ENV === "development") {
|
|
3253
|
+
console.log("magic editor: ", ...args);
|
|
3129
3254
|
}
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
} else {
|
|
3135
|
-
id = config.id;
|
|
3136
|
-
}
|
|
3137
|
-
if (!id) {
|
|
3138
|
-
throw new Error("没有ID,无法选中");
|
|
3139
|
-
}
|
|
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("不能选根节点");
|
|
3145
|
-
}
|
|
3146
|
-
return {
|
|
3147
|
-
node,
|
|
3148
|
-
parent,
|
|
3149
|
-
page
|
|
3150
|
-
};
|
|
3255
|
+
};
|
|
3256
|
+
const info = (...args) => {
|
|
3257
|
+
if (process.env.NODE_ENV === "development") {
|
|
3258
|
+
console.info("magic editor: ", ...args);
|
|
3151
3259
|
}
|
|
3152
|
-
}
|
|
3153
|
-
const editorService = new Editor();
|
|
3154
|
-
|
|
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;
|
|
3193
3260
|
};
|
|
3194
|
-
const
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
left = left - (parentElRect?.left || 0);
|
|
3199
|
-
top = top - (parentElRect?.top || 0);
|
|
3200
|
-
return {
|
|
3201
|
-
left,
|
|
3202
|
-
top
|
|
3203
|
-
};
|
|
3261
|
+
const warn = (...args) => {
|
|
3262
|
+
if (process.env.NODE_ENV === "development") {
|
|
3263
|
+
console.warn("magic editor: ", ...args);
|
|
3264
|
+
}
|
|
3204
3265
|
};
|
|
3205
|
-
const
|
|
3206
|
-
|
|
3207
|
-
|
|
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);
|
|
3266
|
+
const debug = (...args) => {
|
|
3267
|
+
if (process.env.NODE_ENV === "development") {
|
|
3268
|
+
console.debug("magic editor: ", ...args);
|
|
3214
3269
|
}
|
|
3215
|
-
return parentNode;
|
|
3216
3270
|
};
|
|
3217
|
-
const
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
newNode.style = getInitPositionStyle(newNode.style, layout);
|
|
3222
|
-
return newNode;
|
|
3271
|
+
const error = (...args) => {
|
|
3272
|
+
if (process.env.NODE_ENV === "development") {
|
|
3273
|
+
console.error("magic editor: ", ...args);
|
|
3274
|
+
}
|
|
3223
3275
|
};
|
|
3224
3276
|
|
|
3225
3277
|
const _sfc_main$P = /* @__PURE__ */ vue.defineComponent({
|
|
@@ -3609,7 +3661,6 @@
|
|
|
3609
3661
|
if (!codeId.value)
|
|
3610
3662
|
return;
|
|
3611
3663
|
await codeBlockService?.setCodeDslById(codeId.value, values);
|
|
3612
|
-
design.tMagicMessage.success("代码块保存成功");
|
|
3613
3664
|
codeBlockEditor.value?.hide();
|
|
3614
3665
|
};
|
|
3615
3666
|
return {
|
|
@@ -3811,7 +3862,7 @@
|
|
|
3811
3862
|
const stage = new StageCore({
|
|
3812
3863
|
render: stageOptions.render,
|
|
3813
3864
|
runtimeUrl: stageOptions.runtimeUrl,
|
|
3814
|
-
zoom: zoom.value,
|
|
3865
|
+
zoom: stageOptions.zoom ?? zoom.value,
|
|
3815
3866
|
autoScrollIntoView: stageOptions.autoScrollIntoView,
|
|
3816
3867
|
isContainer: stageOptions.isContainer,
|
|
3817
3868
|
containerHighlightClassName: stageOptions.containerHighlightClassName,
|
|
@@ -10739,7 +10790,7 @@
|
|
|
10739
10790
|
|
|
10740
10791
|
const canUsePluginMethods$1 = {
|
|
10741
10792
|
async: ["setCodeDslById", "setEditStatus", "setCombineIds", "setUndeleteableList", "deleteCodeDslByIds"],
|
|
10742
|
-
sync: []
|
|
10793
|
+
sync: ["setCodeDslByIdSync"]
|
|
10743
10794
|
};
|
|
10744
10795
|
class CodeBlock extends BaseService {
|
|
10745
10796
|
state = vue.reactive({
|
|
@@ -10750,7 +10801,10 @@
|
|
|
10750
10801
|
paramsColConfig: void 0
|
|
10751
10802
|
});
|
|
10752
10803
|
constructor() {
|
|
10753
|
-
super(
|
|
10804
|
+
super([
|
|
10805
|
+
...canUsePluginMethods$1.async.map((methodName) => ({ name: methodName, isAsync: true })),
|
|
10806
|
+
...canUsePluginMethods$1.sync.map((methodName) => ({ name: methodName, isAsync: false }))
|
|
10807
|
+
]);
|
|
10754
10808
|
}
|
|
10755
10809
|
/**
|
|
10756
10810
|
* 设置活动的代码块dsl数据源
|
|
@@ -10790,17 +10844,29 @@
|
|
|
10790
10844
|
* @returns {void}
|
|
10791
10845
|
*/
|
|
10792
10846
|
async setCodeDslById(id, codeConfig) {
|
|
10847
|
+
this.setCodeDslByIdSync(id, codeConfig, true);
|
|
10848
|
+
}
|
|
10849
|
+
/**
|
|
10850
|
+
* 为了兼容历史原因
|
|
10851
|
+
* 设置代码块ID和代码内容到源dsl
|
|
10852
|
+
* @param {Id} id 代码块id
|
|
10853
|
+
* @param {CodeBlockContent} codeConfig 代码块内容配置信息
|
|
10854
|
+
* @param {boolean} force 是否强制写入,默认true
|
|
10855
|
+
* @returns {void}
|
|
10856
|
+
*/
|
|
10857
|
+
setCodeDslByIdSync(id, codeConfig, force = true) {
|
|
10793
10858
|
const codeDsl = this.getCodeDsl();
|
|
10794
10859
|
if (!codeDsl) {
|
|
10795
10860
|
throw new Error("dsl中没有codeBlocks");
|
|
10796
10861
|
}
|
|
10797
|
-
|
|
10798
|
-
|
|
10862
|
+
if (codeDsl[id] && !force)
|
|
10863
|
+
return;
|
|
10864
|
+
const codeConfigProcessed = lodashEs.cloneDeep(codeConfig);
|
|
10865
|
+
if (codeConfigProcessed.content) {
|
|
10799
10866
|
const parseDSL = getConfig("parseDSL");
|
|
10800
|
-
if (typeof
|
|
10801
|
-
|
|
10867
|
+
if (typeof codeConfigProcessed.content === "string") {
|
|
10868
|
+
codeConfigProcessed.content = parseDSL(codeConfigProcessed.content);
|
|
10802
10869
|
}
|
|
10803
|
-
codeConfigProcessed.content = codeConfig.content;
|
|
10804
10870
|
}
|
|
10805
10871
|
const existContent = codeDsl[id] || {};
|
|
10806
10872
|
codeDsl[id] = {
|
|
@@ -10912,6 +10978,51 @@
|
|
|
10912
10978
|
return newId;
|
|
10913
10979
|
return await this.getUniqueId();
|
|
10914
10980
|
}
|
|
10981
|
+
/**
|
|
10982
|
+
* 复制时会带上组件关联的代码块
|
|
10983
|
+
* @param config 组件节点配置
|
|
10984
|
+
* @returns
|
|
10985
|
+
*/
|
|
10986
|
+
copyWithRelated(config) {
|
|
10987
|
+
const copyNodes = Array.isArray(config) ? config : [config];
|
|
10988
|
+
depService.clearByType(dep.DepTargetType.RELATED_CODE_WHEN_COPY);
|
|
10989
|
+
depService.collect(copyNodes, true, dep.DepTargetType.RELATED_CODE_WHEN_COPY);
|
|
10990
|
+
const customTarget = depService.getTarget(
|
|
10991
|
+
dep.DepTargetType.RELATED_CODE_WHEN_COPY,
|
|
10992
|
+
dep.DepTargetType.RELATED_CODE_WHEN_COPY
|
|
10993
|
+
);
|
|
10994
|
+
const copyData = {};
|
|
10995
|
+
if (customTarget) {
|
|
10996
|
+
Object.keys(customTarget.deps).forEach((nodeId) => {
|
|
10997
|
+
const node = editorService.getNodeById(nodeId);
|
|
10998
|
+
if (!node)
|
|
10999
|
+
return;
|
|
11000
|
+
customTarget.deps[nodeId].keys.forEach((key) => {
|
|
11001
|
+
const relateCodeId = lodashEs.get(node, key);
|
|
11002
|
+
const isExist = Object.keys(copyData).find((codeId) => codeId === relateCodeId);
|
|
11003
|
+
if (!isExist) {
|
|
11004
|
+
const relateCode = this.getCodeContentById(relateCodeId);
|
|
11005
|
+
if (relateCode) {
|
|
11006
|
+
copyData[relateCodeId] = relateCode;
|
|
11007
|
+
}
|
|
11008
|
+
}
|
|
11009
|
+
});
|
|
11010
|
+
});
|
|
11011
|
+
}
|
|
11012
|
+
storageService.setItem(COPY_CODE_STORAGE_KEY, copyData, {
|
|
11013
|
+
protocol: Protocol.OBJECT
|
|
11014
|
+
});
|
|
11015
|
+
}
|
|
11016
|
+
/**
|
|
11017
|
+
* 粘贴代码块
|
|
11018
|
+
* @returns
|
|
11019
|
+
*/
|
|
11020
|
+
paste() {
|
|
11021
|
+
const codeDsl = storageService.getItem(COPY_CODE_STORAGE_KEY);
|
|
11022
|
+
Object.keys(codeDsl).forEach((codeId) => {
|
|
11023
|
+
this.setCodeDslByIdSync(codeId, codeDsl[codeId], false);
|
|
11024
|
+
});
|
|
11025
|
+
}
|
|
10915
11026
|
resetState() {
|
|
10916
11027
|
this.state.codeDsl = null;
|
|
10917
11028
|
this.state.editable = true;
|
|
@@ -11253,6 +11364,7 @@
|
|
|
11253
11364
|
createStage(stageOptions = {}) {
|
|
11254
11365
|
return useStage({
|
|
11255
11366
|
...stageOptions,
|
|
11367
|
+
zoom: 1,
|
|
11256
11368
|
runtimeUrl: "",
|
|
11257
11369
|
autoScrollIntoView: false,
|
|
11258
11370
|
render: async (stage) => {
|
|
@@ -11682,7 +11794,17 @@
|
|
|
11682
11794
|
dataSourceService.on("update", dataSourceUpdateHandler);
|
|
11683
11795
|
dataSourceService.on("remove", dataSourceRemoveHandler);
|
|
11684
11796
|
if (props.collectorOptions && !depService.hasTarget(dep.DepTargetType.RELATED_COMP_WHEN_COPY)) {
|
|
11685
|
-
depService.addTarget(dep.
|
|
11797
|
+
depService.addTarget(dep.createRelatedTargetForCopy(props.collectorOptions, dep.DepTargetType.RELATED_COMP_WHEN_COPY));
|
|
11798
|
+
}
|
|
11799
|
+
if (props.collectorOptionsForCode && !depService.hasTarget(dep.DepTargetType.RELATED_CODE_WHEN_COPY)) {
|
|
11800
|
+
depService.addTarget(
|
|
11801
|
+
dep.createRelatedTargetForCopy(props.collectorOptionsForCode, dep.DepTargetType.RELATED_CODE_WHEN_COPY)
|
|
11802
|
+
);
|
|
11803
|
+
}
|
|
11804
|
+
if (props.collectorOptionsForDataSource && !depService.hasTarget(dep.DepTargetType.RELATED_DS_WHEN_COPY)) {
|
|
11805
|
+
depService.addTarget(
|
|
11806
|
+
dep.createRelatedTargetForCopy(props.collectorOptionsForDataSource, dep.DepTargetType.RELATED_DS_WHEN_COPY)
|
|
11807
|
+
);
|
|
11686
11808
|
}
|
|
11687
11809
|
vue.onBeforeUnmount(() => {
|
|
11688
11810
|
depService.off("add-target", targetAddHandler);
|
|
@@ -11733,6 +11855,8 @@
|
|
|
11733
11855
|
codeOptions: {},
|
|
11734
11856
|
disabledDragStart: { type: Boolean },
|
|
11735
11857
|
collectorOptions: {},
|
|
11858
|
+
collectorOptionsForCode: {},
|
|
11859
|
+
collectorOptionsForDataSource: {},
|
|
11736
11860
|
guidesOptions: {},
|
|
11737
11861
|
disabledMultiSelect: { type: Boolean },
|
|
11738
11862
|
disabledPageFragment: { type: Boolean },
|
|
@@ -11943,6 +12067,8 @@
|
|
|
11943
12067
|
get: () => dep.DepTargetType
|
|
11944
12068
|
});
|
|
11945
12069
|
exports.CODE_DRAFT_STORAGE_KEY = CODE_DRAFT_STORAGE_KEY;
|
|
12070
|
+
exports.COPY_CODE_STORAGE_KEY = COPY_CODE_STORAGE_KEY;
|
|
12071
|
+
exports.COPY_DS_STORAGE_KEY = COPY_DS_STORAGE_KEY;
|
|
11946
12072
|
exports.COPY_STORAGE_KEY = COPY_STORAGE_KEY;
|
|
11947
12073
|
exports.CodeBlockEditor = _sfc_main$J;
|
|
11948
12074
|
exports.CodeBlockList = _sfc_main$l;
|
|
@@ -11964,6 +12090,7 @@
|
|
|
11964
12090
|
exports.DragType = DragType;
|
|
11965
12091
|
exports.EventSelect = _sfc_main$E;
|
|
11966
12092
|
exports.Fixed2Other = Fixed2Other;
|
|
12093
|
+
exports.FloatingBox = _sfc_main$N;
|
|
11967
12094
|
exports.H_GUIDE_LINE_STORAGE_KEY = H_GUIDE_LINE_STORAGE_KEY;
|
|
11968
12095
|
exports.Icon = _sfc_main$U;
|
|
11969
12096
|
exports.KeyBindingCommand = KeyBindingCommand;
|