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