@tmagic/editor 1.3.15 → 1.4.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/style.css +17 -3
  2. package/dist/tmagic-editor.js +875 -530
  3. package/dist/tmagic-editor.umd.cjs +891 -545
  4. package/package.json +23 -21
  5. package/src/Editor.vue +8 -0
  6. package/src/components/CodeBlockEditor.vue +50 -24
  7. package/src/components/FloatingBox.vue +53 -12
  8. package/src/fields/Code.vue +12 -10
  9. package/src/fields/CodeLink.vue +9 -9
  10. package/src/fields/CodeSelect.vue +7 -5
  11. package/src/fields/CodeSelectCol.vue +1 -1
  12. package/src/fields/DataSourceFieldSelect.vue +118 -27
  13. package/src/fields/DataSourceFields.vue +10 -3
  14. package/src/fields/DataSourceInput.vue +7 -7
  15. package/src/fields/DataSourceMethodSelect.vue +1 -1
  16. package/src/fields/DataSourceMethods.vue +3 -3
  17. package/src/fields/DataSourceMocks.vue +3 -3
  18. package/src/fields/DataSourceSelect.vue +6 -18
  19. package/src/fields/EventSelect.vue +1 -1
  20. package/src/fields/KeyValue.vue +8 -8
  21. package/src/fields/PageFragmentSelect.vue +1 -1
  22. package/src/fields/UISelect.vue +5 -5
  23. package/src/hooks/use-code-block-edit.ts +0 -1
  24. package/src/index.ts +3 -2
  25. package/src/layouts/NavMenu.vue +21 -2
  26. package/src/layouts/sidebar/Sidebar.vue +16 -1
  27. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +0 -1
  28. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +3 -0
  29. package/src/services/BaseService.ts +5 -2
  30. package/src/services/codeBlock.ts +14 -8
  31. package/src/services/dataSource.ts +39 -26
  32. package/src/services/editor.ts +46 -25
  33. package/src/services/events.ts +4 -4
  34. package/src/services/props.ts +44 -35
  35. package/src/services/stageOverlay.ts +14 -7
  36. package/src/services/storage.ts +14 -8
  37. package/src/services/ui.ts +20 -19
  38. package/src/theme/code-editor.scss +6 -0
  39. package/src/theme/component-list-panel.scss +79 -71
  40. package/src/theme/floating-box.scss +2 -0
  41. package/src/theme/layer-panel.scss +1 -0
  42. package/src/theme/sidebar.scss +6 -3
  43. package/src/type.ts +82 -37
  44. package/src/utils/operator.ts +37 -39
  45. package/src/utils/props.ts +174 -37
  46. package/types/components/CodeBlockEditor.vue.d.ts +4 -4
  47. package/types/components/CodeParams.vue.d.ts +5 -5
  48. package/types/components/ContentMenu.vue.d.ts +12 -12
  49. package/types/components/FloatingBox.vue.d.ts +14 -12
  50. package/types/components/Icon.vue.d.ts +3 -3
  51. package/types/components/Resizer.vue.d.ts +3 -3
  52. package/types/components/ScrollBar.vue.d.ts +3 -3
  53. package/types/components/ScrollViewer.vue.d.ts +12 -12
  54. package/types/components/SearchInput.vue.d.ts +1 -1
  55. package/types/components/SplitView.vue.d.ts +11 -11
  56. package/types/components/ToolButton.vue.d.ts +13 -13
  57. package/types/components/Tree.vue.d.ts +24 -14
  58. package/types/components/TreeNode.vue.d.ts +22 -12
  59. package/types/fields/Code.vue.d.ts +14 -14
  60. package/types/fields/CodeLink.vue.d.ts +6 -10
  61. package/types/fields/CodeSelect.vue.d.ts +14 -14
  62. package/types/fields/CodeSelectCol.vue.d.ts +11 -11
  63. package/types/fields/DataSourceFieldSelect.vue.d.ts +11 -11
  64. package/types/fields/DataSourceFields.vue.d.ts +11 -11
  65. package/types/fields/DataSourceInput.vue.d.ts +14 -18
  66. package/types/fields/DataSourceMethodSelect.vue.d.ts +11 -11
  67. package/types/fields/DataSourceMethods.vue.d.ts +11 -11
  68. package/types/fields/DataSourceMocks.vue.d.ts +11 -11
  69. package/types/fields/DataSourceSelect.vue.d.ts +13 -26
  70. package/types/fields/EventSelect.vue.d.ts +3 -3
  71. package/types/fields/KeyValue.vue.d.ts +14 -18
  72. package/types/fields/PageFragmentSelect.vue.d.ts +11 -11
  73. package/types/fields/UISelect.vue.d.ts +8 -4
  74. package/types/hooks/use-code-block-edit.d.ts +51 -89
  75. package/types/hooks/use-data-source-method.d.ts +51 -89
  76. package/types/hooks/use-node-status.d.ts +6 -1
  77. package/types/icons/AppManageIcon.vue.d.ts +1 -1
  78. package/types/icons/CenterIcon.vue.d.ts +1 -1
  79. package/types/icons/CodeIcon.vue.d.ts +1 -1
  80. package/types/icons/FolderMinusIcon.vue.d.ts +1 -1
  81. package/types/icons/PinIcon.vue.d.ts +1 -1
  82. package/types/icons/PinnedIcon.vue.d.ts +1 -1
  83. package/types/index.d.ts +1 -0
  84. package/types/layouts/AddPageBox.vue.d.ts +3 -3
  85. package/types/layouts/CodeEditor.vue.d.ts +12 -12
  86. package/types/layouts/Framework.vue.d.ts +9 -9
  87. package/types/layouts/NavMenu.vue.d.ts +11 -11
  88. package/types/layouts/PropsPanel.vue.d.ts +193 -243
  89. package/types/layouts/page-bar/AddButton.vue.d.ts +3 -3
  90. package/types/layouts/page-bar/PageBar.vue.d.ts +8 -8
  91. package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +8 -8
  92. package/types/layouts/page-bar/SwitchTypeButton.vue.d.ts +3 -3
  93. package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
  94. package/types/layouts/sidebar/Sidebar.vue.d.ts +12 -12
  95. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +10 -10
  96. package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +9 -9
  97. package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -3
  98. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +3 -3
  99. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +9 -9
  100. package/types/layouts/sidebar/layer/LayerMenu.vue.d.ts +11 -11
  101. package/types/layouts/sidebar/layer/LayerNodeTool.vue.d.ts +3 -3
  102. package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +9 -9
  103. package/types/layouts/sidebar/layer/use-click.d.ts +42 -76
  104. package/types/layouts/sidebar/layer/use-node-status.d.ts +6 -1
  105. package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -1
  106. package/types/layouts/workspace/Workspace.vue.d.ts +12 -12
  107. package/types/layouts/workspace/viewer/NodeListMenu.vue.d.ts +1 -1
  108. package/types/layouts/workspace/viewer/Stage.vue.d.ts +11 -11
  109. package/types/layouts/workspace/viewer/StageOverlay.vue.d.ts +1 -1
  110. package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +12 -12
  111. package/types/services/BaseService.d.ts +5 -2
  112. package/types/services/codeBlock.d.ts +8 -0
  113. package/types/services/dataSource.d.ts +9 -2
  114. package/types/services/editor.d.ts +8 -1
  115. package/types/services/props.d.ts +15 -22
  116. package/types/services/stageOverlay.d.ts +8 -1
  117. package/types/services/storage.d.ts +8 -0
  118. package/types/services/ui.d.ts +15 -9
  119. package/types/type.d.ts +51 -32
  120. package/types/utils/operator.d.ts +1 -1
  121. package/types/utils/props.d.ts +2 -13
@@ -72,12 +72,15 @@
72
72
  }
73
73
 
74
74
  .m-editor-slide-list-box {
75
- min-width: 270px;
75
+ display: flex;
76
+ min-width: 240px;
76
77
  min-height: 500px;
77
- max-height: 1024px;
78
78
  > div {
79
79
  &:first-child {
80
- width: 100%;
80
+ min-width: 240px;
81
81
  }
82
82
  }
83
+ .m-form-box {
84
+ border-left: 1px solid #e0e0e0;
85
+ }
83
86
  }
package/src/type.ts CHANGED
@@ -17,9 +17,20 @@
17
17
  */
18
18
 
19
19
  import type { Component } from 'vue';
20
+ import type { PascalCasedProperties } from 'type-fest';
20
21
 
21
- import type { ColumnConfig, FilterFunction, FormConfig, FormItem } from '@tmagic/form';
22
- import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
22
+ import type { ChildConfig, ColumnConfig, FilterFunction, FormConfig, FormItem, Input } from '@tmagic/form';
23
+ import type {
24
+ CodeBlockContent,
25
+ CodeBlockDSL,
26
+ DataSourceFieldType,
27
+ Id,
28
+ MApp,
29
+ MContainer,
30
+ MNode,
31
+ MPage,
32
+ MPageFragment,
33
+ } from '@tmagic/schema';
23
34
  import type StageCore from '@tmagic/stage';
24
35
  import type {
25
36
  ContainerHighlightType,
@@ -81,6 +92,7 @@ export interface CodeBlockListSlots {
81
92
 
82
93
  export interface DataSourceListSlots {
83
94
  'data-source-panel-tool'(props: { data: any }): any;
95
+ 'data-source-panel-search'(props: {}): any;
84
96
  }
85
97
 
86
98
  export interface LayerNodeSlots {
@@ -224,20 +236,16 @@ export interface UiState {
224
236
  propsPanelSize: 'large' | 'default' | 'small';
225
237
  /** 是否显示新增页面按钮 */
226
238
  showAddPageButton: boolean;
227
-
228
- /** slide 拖拽悬浮窗 state */
229
- floatBox: Map<
230
- string,
231
- {
232
- status: boolean;
233
- zIndex: number;
234
- top: number;
235
- left: number;
236
- }
237
- >;
238
-
239
239
  /** 是否隐藏侧边栏 */
240
240
  hideSlideBar: boolean;
241
+
242
+ // navMenu 的宽高
243
+ navMenuRect: {
244
+ left: number;
245
+ top: number;
246
+ width: number;
247
+ height: number;
248
+ };
241
249
  }
242
250
 
243
251
  export interface EditorNodeInfo {
@@ -594,42 +602,44 @@ export interface KeyBindingCacheItem {
594
602
  bound: boolean;
595
603
  }
596
604
 
597
- export interface CodeSelectColConfig {
605
+ export interface CodeSelectColConfig extends FormItem {
598
606
  type: 'code-select-col';
599
- name: string;
600
- text: string;
601
- labelWidth?: number | string;
602
- disabled?: boolean | FilterFunction;
607
+ /** 是否可以编辑代码块,disable表示的是是否可以选择代码块 */
603
608
  notEditable?: boolean | FilterFunction;
604
- display?: boolean | FilterFunction;
605
609
  }
606
610
 
607
- export interface PageFragmentSelectConfig {
611
+ export interface PageFragmentSelectConfig extends FormItem {
608
612
  type: 'page-fragment-select';
609
- name: string;
610
- text: string;
611
- labelWidth?: number | string;
612
- disabled?: boolean | FilterFunction;
613
- display?: boolean | FilterFunction;
614
613
  }
615
614
 
616
- export interface DataSourceMethodSelectConfig {
615
+ export interface DataSourceSelect extends FormItem, Input {
616
+ type: 'data-source-select';
617
+ /** 数据源类型: base、http... */
618
+ dataSourceType?: string;
619
+ /** 是否要编译成数据源的data。
620
+ * id: 不编译,就是要数据源id;
621
+ * value: 要编译(数据源data)
622
+ * */
623
+ value?: 'id' | 'value';
624
+ }
625
+
626
+ export interface DataSourceMethodSelectConfig extends FormItem {
617
627
  type: 'data-source-method-select';
618
- name: string;
619
- text: string;
620
- labelWidth?: number | string;
621
- disabled?: boolean | FilterFunction;
628
+ /** 是否可以编辑数据源,disable表示的是是否可以选择数据源 */
622
629
  notEditable?: boolean | FilterFunction;
623
- display?: boolean | FilterFunction;
624
630
  }
625
631
 
626
- export interface DataSourceFieldSelectConfig {
632
+ export interface DataSourceFieldSelectConfig extends FormItem {
627
633
  type: 'data-source-field-select';
628
- name: string;
634
+ /** 是否要编译成数据源的data。
635
+ * key: 不编译,就是要数据源id和field name;
636
+ * value: 要编译(数据源data[`${filed}`])
637
+ * */
629
638
  value?: 'key' | 'value';
630
- labelWidth?: number | string;
631
- disabled?: boolean | FilterFunction;
632
- display?: boolean | FilterFunction;
639
+ /** 是否严格的遵守父子节点不互相关联 */
640
+ checkStrictly?: boolean;
641
+ dataSourceFieldType?: DataSourceFieldType[];
642
+ fieldConfig?: ChildConfig;
633
643
  }
634
644
 
635
645
  /** 可新增的数据源类型选项 */
@@ -669,3 +679,38 @@ export interface TreeNodeData {
669
679
  items?: TreeNodeData[];
670
680
  [key: string]: any;
671
681
  }
682
+
683
+ export type AsyncBeforeHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
684
+ [K in Value[number]]?: (...args: Parameters<C[K]>) => Promise<Parameters<C[K]>> | Parameters<C[K]>;
685
+ };
686
+
687
+ export type AsyncAfterHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
688
+ [K in Value[number]]?: (
689
+ result: Awaited<ReturnType<C[K]>>,
690
+ ...args: Parameters<C[K]>
691
+ ) => ReturnType<C[K]> | Awaited<ReturnType<C[K]>>;
692
+ };
693
+
694
+ export type SyncBeforeHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
695
+ [K in Value[number]]?: (...args: Parameters<C[K]>) => Parameters<C[K]>;
696
+ };
697
+
698
+ export type SyncAfterHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
699
+ [K in Value[number]]?: (result: ReturnType<C[K]>, ...args: Parameters<C[K]>) => ReturnType<C[K]>;
700
+ };
701
+
702
+ export type AddPrefixToObject<T, P extends string> = {
703
+ [K in keyof T as K extends string ? `${P}${K}` : never]: T[K];
704
+ };
705
+
706
+ export type AsyncHookPlugin<
707
+ T extends Array<string>,
708
+ C extends Record<T[number], (...args: any) => any>,
709
+ > = AddPrefixToObject<PascalCasedProperties<AsyncBeforeHook<T, C>>, 'before'> &
710
+ AddPrefixToObject<PascalCasedProperties<AsyncAfterHook<T, C>>, 'after'>;
711
+
712
+ export type SyncHookPlugin<
713
+ T extends Array<string>,
714
+ C extends Record<T[number], (...args: any) => any>,
715
+ > = AddPrefixToObject<PascalCasedProperties<SyncBeforeHook<T, C>>, 'before'> &
716
+ AddPrefixToObject<PascalCasedProperties<SyncAfterHook<T, C>>, 'after'>;
@@ -15,55 +15,53 @@ import { generatePageNameByApp, getInitPositionStyle } from '@editor/utils/edito
15
15
  * @param config 待粘贴的元素配置(复制时保存的那份配置)
16
16
  * @returns
17
17
  */
18
- export const beforePaste = async (position: PastePosition, config: MNode[]): Promise<MNode[]> => {
18
+ export const beforePaste = (position: PastePosition, config: MNode[]): MNode[] => {
19
19
  if (!config[0]?.style) return config;
20
20
  const curNode = editorService.get('node');
21
21
  // 将数组中第一个元素的坐标作为参照点
22
22
  const { left: referenceLeft, top: referenceTop } = config[0].style;
23
23
  // 坐标校准后的粘贴数据
24
- const pasteConfigs: MNode[] = await Promise.all(
25
- config.map(async (configItem: MNode): Promise<MNode> => {
26
- // 解构 position 对象,从 position 删除 offsetX、offsetY字段
27
- const { offsetX = 0, offsetY = 0, ...positionClone } = position;
28
- let pastePosition = positionClone;
24
+ const pasteConfigs: MNode[] = config.map((configItem: MNode): MNode => {
25
+ // 解构 position 对象,从 position 删除 offsetX、offsetY字段
26
+ const { offsetX = 0, offsetY = 0, ...positionClone } = position;
27
+ let pastePosition = positionClone;
29
28
 
30
- if (!isEmpty(pastePosition) && curNode?.items) {
31
- // 如果没有传入粘贴坐标则可能为键盘操作,不再转换
32
- // 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
33
- pastePosition = getPositionInContainer(pastePosition, curNode.id);
34
- }
29
+ if (!isEmpty(pastePosition) && curNode?.items) {
30
+ // 如果没有传入粘贴坐标则可能为键盘操作,不再转换
31
+ // 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
32
+ pastePosition = getPositionInContainer(pastePosition, curNode.id);
33
+ }
35
34
 
36
- // 将所有待粘贴元素坐标相对于多选第一个元素坐标重新计算,以保证多选粘贴后元素间距不变
37
- if (pastePosition.left && configItem.style?.left) {
38
- pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
39
- }
40
- if (pastePosition.top && configItem.style?.top) {
41
- pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
42
- }
43
- const pasteConfig = await propsService.setNewItemId(configItem, false);
35
+ // 将所有待粘贴元素坐标相对于多选第一个元素坐标重新计算,以保证多选粘贴后元素间距不变
36
+ if (pastePosition.left && configItem.style?.left) {
37
+ pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
38
+ }
39
+ if (pastePosition.top && configItem.style?.top) {
40
+ pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
41
+ }
42
+ const pasteConfig = propsService.setNewItemId(configItem, false);
44
43
 
45
- if (pasteConfig.style) {
46
- const { left, top } = pasteConfig.style;
47
- // 判断能转换为数字时,做粘贴偏移量计算
48
- if (typeof left === 'number' || (!!left && !isNaN(Number(left)))) {
49
- pasteConfig.style.left = Number(left) + offsetX;
50
- }
51
- if (typeof top === 'number' || (!!top && !isNaN(Number(top)))) {
52
- pasteConfig.style.top = Number(top) + offsetY;
53
- }
54
-
55
- pasteConfig.style = {
56
- ...pasteConfig.style,
57
- ...pastePosition,
58
- };
44
+ if (pasteConfig.style) {
45
+ const { left, top } = pasteConfig.style;
46
+ // 判断能转换为数字时,做粘贴偏移量计算
47
+ if (typeof left === 'number' || (!!left && !isNaN(Number(left)))) {
48
+ pasteConfig.style.left = Number(left) + offsetX;
59
49
  }
60
- const root = editorService.get('root');
61
- if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
62
- pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
50
+ if (typeof top === 'number' || (!!top && !isNaN(Number(top)))) {
51
+ pasteConfig.style.top = Number(top) + offsetY;
63
52
  }
64
- return pasteConfig as MNode;
65
- }),
66
- );
53
+
54
+ pasteConfig.style = {
55
+ ...pasteConfig.style,
56
+ ...pastePosition,
57
+ };
58
+ }
59
+ const root = editorService.get('root');
60
+ if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
61
+ pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
62
+ }
63
+ return pasteConfig as MNode;
64
+ });
67
65
  return pasteConfigs;
68
66
  };
69
67
 
@@ -41,7 +41,6 @@ const numberOptions = [
41
41
 
42
42
  export const styleTabConfig: TabPaneConfig = {
43
43
  title: '样式',
44
- labelWidth: '80px',
45
44
  items: [
46
45
  {
47
46
  name: 'style',
@@ -51,30 +50,59 @@ export const styleTabConfig: TabPaneConfig = {
51
50
  legend: '位置',
52
51
  items: [
53
52
  {
53
+ type: 'data-source-field-select',
54
54
  name: 'position',
55
- type: 'checkbox',
56
- activeValue: 'fixed',
57
- inactiveValue: 'absolute',
58
- defaultValue: 'absolute',
59
55
  text: '固定定位',
56
+ checkStrictly: false,
57
+ dataSourceFieldType: ['string'],
58
+ fieldConfig: {
59
+ type: 'checkbox',
60
+ activeValue: 'fixed',
61
+ inactiveValue: 'absolute',
62
+ defaultValue: 'absolute',
63
+ },
60
64
  },
61
65
  {
66
+ type: 'data-source-field-select',
62
67
  name: 'left',
63
68
  text: 'left',
69
+ checkStrictly: false,
70
+ dataSourceFieldType: ['string', 'number'],
71
+ fieldConfig: {
72
+ type: 'text',
73
+ },
64
74
  },
65
75
  {
76
+ type: 'data-source-field-select',
66
77
  name: 'top',
67
78
  text: 'top',
79
+ checkStrictly: false,
80
+ dataSourceFieldType: ['string', 'number'],
81
+ fieldConfig: {
82
+ type: 'text',
83
+ },
68
84
  disabled: (vm: FormState, { model }: any) =>
69
85
  model.position === 'fixed' && model._magic_position === 'fixedBottom',
70
86
  },
71
87
  {
88
+ type: 'data-source-field-select',
72
89
  name: 'right',
73
90
  text: 'right',
91
+ checkStrictly: false,
92
+ dataSourceFieldType: ['string', 'number'],
93
+ fieldConfig: {
94
+ type: 'text',
95
+ },
74
96
  },
75
97
  {
98
+ type: 'data-source-field-select',
76
99
  name: 'bottom',
77
100
  text: 'bottom',
101
+ checkStrictly: false,
102
+ dataSourceFieldType: ['string', 'number'],
103
+ fieldConfig: {
104
+ type: 'text',
105
+ },
78
106
  disabled: (vm: FormState, { model }: any) =>
79
107
  model.position === 'fixed' && model._magic_position === 'fixedTop',
80
108
  },
@@ -85,12 +113,42 @@ export const styleTabConfig: TabPaneConfig = {
85
113
  legend: '盒子',
86
114
  items: [
87
115
  {
116
+ type: 'data-source-field-select',
88
117
  name: 'width',
89
118
  text: '宽度',
119
+ checkStrictly: false,
120
+ dataSourceFieldType: ['string', 'number'],
121
+ fieldConfig: {
122
+ type: 'text',
123
+ },
90
124
  },
91
125
  {
126
+ type: 'data-source-field-select',
92
127
  name: 'height',
93
128
  text: '高度',
129
+ checkStrictly: false,
130
+ dataSourceFieldType: ['string', 'number'],
131
+ fieldConfig: {
132
+ type: 'text',
133
+ },
134
+ },
135
+ {
136
+ type: 'data-source-field-select',
137
+ text: 'overflow',
138
+ name: 'overflow',
139
+ checkStrictly: false,
140
+ dataSourceFieldType: ['string'],
141
+ fieldConfig: {
142
+ type: 'select',
143
+ options: [
144
+ { text: 'visible', value: 'visible' },
145
+ { text: 'hidden', value: 'hidden' },
146
+ { text: 'clip', value: 'clip' },
147
+ { text: 'scroll', value: 'scroll' },
148
+ { text: 'auto', value: 'auto' },
149
+ { text: 'overlay', value: 'overlay' },
150
+ ],
151
+ },
94
152
  },
95
153
  ],
96
154
  },
@@ -99,32 +157,48 @@ export const styleTabConfig: TabPaneConfig = {
99
157
  legend: '边框',
100
158
  items: [
101
159
  {
160
+ type: 'data-source-field-select',
102
161
  name: 'borderWidth',
103
162
  text: '宽度',
104
163
  defaultValue: '0',
164
+ checkStrictly: false,
165
+ dataSourceFieldType: ['string', 'number'],
166
+ fieldConfig: {
167
+ type: 'text',
168
+ },
105
169
  },
106
170
  {
171
+ type: 'data-source-field-select',
107
172
  name: 'borderColor',
108
173
  text: '颜色',
109
- type: 'colorPicker',
174
+ checkStrictly: false,
175
+ dataSourceFieldType: ['string'],
176
+ fieldConfig: {
177
+ type: 'text',
178
+ },
110
179
  },
111
180
  {
181
+ type: 'data-source-field-select',
112
182
  name: 'borderStyle',
113
183
  text: '样式',
114
- type: 'select',
115
184
  defaultValue: 'none',
116
- options: [
117
- { text: 'none', value: 'none' },
118
- { text: 'hidden', value: 'hidden' },
119
- { text: 'dotted', value: 'dotted' },
120
- { text: 'dashed', value: 'dashed' },
121
- { text: 'solid', value: 'solid' },
122
- { text: 'double', value: 'double' },
123
- { text: 'groove', value: 'groove' },
124
- { text: 'ridge', value: 'ridge' },
125
- { text: 'inset', value: 'inset' },
126
- { text: 'outset', value: 'outset' },
127
- ],
185
+ checkStrictly: false,
186
+ dataSourceFieldType: ['string'],
187
+ fieldConfig: {
188
+ type: 'select',
189
+ options: [
190
+ { text: 'none', value: 'none' },
191
+ { text: 'hidden', value: 'hidden' },
192
+ { text: 'dotted', value: 'dotted' },
193
+ { text: 'dashed', value: 'dashed' },
194
+ { text: 'solid', value: 'solid' },
195
+ { text: 'double', value: 'double' },
196
+ { text: 'groove', value: 'groove' },
197
+ { text: 'ridge', value: 'ridge' },
198
+ { text: 'inset', value: 'inset' },
199
+ { text: 'outset', value: 'outset' },
200
+ ],
201
+ },
128
202
  },
129
203
  ],
130
204
  },
@@ -133,31 +207,53 @@ export const styleTabConfig: TabPaneConfig = {
133
207
  legend: '背景',
134
208
  items: [
135
209
  {
210
+ type: 'data-source-field-select',
136
211
  name: 'backgroundImage',
137
212
  text: '背景图',
213
+ checkStrictly: false,
214
+ dataSourceFieldType: ['string'],
215
+ fieldConfig: {
216
+ type: 'text',
217
+ },
138
218
  },
139
219
  {
220
+ type: 'data-source-field-select',
140
221
  name: 'backgroundColor',
141
222
  text: '背景颜色',
142
- type: 'colorPicker',
223
+ checkStrictly: false,
224
+ dataSourceFieldType: ['string'],
225
+ fieldConfig: {
226
+ type: 'colorPicker',
227
+ },
143
228
  },
144
229
  {
230
+ type: 'data-source-field-select',
145
231
  name: 'backgroundRepeat',
146
232
  text: '背景图重复',
147
- type: 'select',
148
233
  defaultValue: 'no-repeat',
149
- options: [
150
- { text: 'repeat', value: 'repeat' },
151
- { text: 'repeat-x', value: 'repeat-x' },
152
- { text: 'repeat-y', value: 'repeat-y' },
153
- { text: 'no-repeat', value: 'no-repeat' },
154
- { text: 'inherit', value: 'inherit' },
155
- ],
234
+ checkStrictly: false,
235
+ dataSourceFieldType: ['string'],
236
+ fieldConfig: {
237
+ type: 'select',
238
+ options: [
239
+ { text: 'repeat', value: 'repeat' },
240
+ { text: 'repeat-x', value: 'repeat-x' },
241
+ { text: 'repeat-y', value: 'repeat-y' },
242
+ { text: 'no-repeat', value: 'no-repeat' },
243
+ { text: 'inherit', value: 'inherit' },
244
+ ],
245
+ },
156
246
  },
157
247
  {
248
+ type: 'data-source-field-select',
158
249
  name: 'backgroundSize',
159
250
  text: '背景图大小',
160
251
  defaultValue: '100% 100%',
252
+ checkStrictly: false,
253
+ dataSourceFieldType: ['string'],
254
+ fieldConfig: {
255
+ type: 'text',
256
+ },
161
257
  },
162
258
  ],
163
259
  },
@@ -166,17 +262,34 @@ export const styleTabConfig: TabPaneConfig = {
166
262
  legend: '字体',
167
263
  items: [
168
264
  {
265
+ type: 'data-source-field-select',
169
266
  name: 'color',
170
267
  text: '颜色',
171
- type: 'colorPicker',
268
+ checkStrictly: false,
269
+ dataSourceFieldType: ['string'],
270
+ fieldConfig: {
271
+ type: 'colorPicker',
272
+ },
172
273
  },
173
274
  {
275
+ type: 'data-source-field-select',
174
276
  name: 'fontSize',
175
277
  text: '大小',
278
+ checkStrictly: false,
279
+ dataSourceFieldType: ['string', 'number'],
280
+ fieldConfig: {
281
+ type: 'text',
282
+ },
176
283
  },
177
284
  {
285
+ type: 'data-source-field-select',
178
286
  name: 'fontWeight',
179
287
  text: '粗细',
288
+ checkStrictly: false,
289
+ dataSourceFieldType: ['string', 'number'],
290
+ fieldConfig: {
291
+ type: 'text',
292
+ },
180
293
  },
181
294
  ],
182
295
  },
@@ -186,12 +299,24 @@ export const styleTabConfig: TabPaneConfig = {
186
299
  name: 'transform',
187
300
  items: [
188
301
  {
302
+ type: 'data-source-field-select',
189
303
  name: 'rotate',
190
304
  text: '旋转角度',
305
+ checkStrictly: false,
306
+ dataSourceFieldType: ['string'],
307
+ fieldConfig: {
308
+ type: 'text',
309
+ },
191
310
  },
192
311
  {
312
+ type: 'data-source-field-select',
193
313
  name: 'scale',
194
314
  text: '缩放',
315
+ checkStrictly: false,
316
+ dataSourceFieldType: ['number', 'string'],
317
+ fieldConfig: {
318
+ type: 'text',
319
+ },
195
320
  },
196
321
  ],
197
322
  },
@@ -219,13 +344,11 @@ export const advancedTabConfig: TabPaneConfig = {
219
344
  {
220
345
  name: 'created',
221
346
  text: 'created',
222
- labelWidth: '100px',
223
347
  type: 'code-select',
224
348
  },
225
349
  {
226
350
  name: 'mounted',
227
351
  text: 'mounted',
228
- labelWidth: '100px',
229
352
  type: 'code-select',
230
353
  },
231
354
  ],
@@ -250,15 +373,23 @@ export const displayTabConfig: TabPaneConfig = {
250
373
  name: 'field',
251
374
  value: 'key',
252
375
  label: '字段',
376
+ checkStrictly: false,
377
+ dataSourceFieldType: ['string', 'number', 'boolean', 'any'],
253
378
  },
254
379
  {
255
380
  type: 'select',
256
381
  options: (mForm, { model }) => {
257
- const [id, field] = model.field;
382
+ const [id, ...fieldNames] = model.field;
258
383
 
259
384
  const ds = dataSourceService.getDataSourceById(id);
260
385
 
261
- const type = ds?.fields.find((f) => f.name === field)?.type;
386
+ let fields = ds?.fields || [];
387
+ let type = '';
388
+ (fieldNames || []).forEach((fieldName: string) => {
389
+ const field = fields.find((f) => f.name === fieldName);
390
+ fields = field?.fields || [];
391
+ type = field?.type || '';
392
+ });
262
393
 
263
394
  if (type === 'array') {
264
395
  return arrayOptions;
@@ -290,11 +421,17 @@ export const displayTabConfig: TabPaneConfig = {
290
421
  {
291
422
  name: 'value',
292
423
  type: (mForm, { model }) => {
293
- const [id, field] = model.field;
424
+ const [id, ...fieldNames] = model.field;
294
425
 
295
426
  const ds = dataSourceService.getDataSourceById(id);
296
427
 
297
- const type = ds?.fields.find((f) => f.name === field)?.type;
428
+ let fields = ds?.fields || [];
429
+ let type = '';
430
+ (fieldNames || []).forEach((fieldName: string) => {
431
+ const field = fields.find((f) => f.name === fieldName);
432
+ fields = field?.fields || [];
433
+ type = field?.type || '';
434
+ });
298
435
 
299
436
  if (type === 'number') {
300
437
  return 'number';
@@ -331,13 +468,13 @@ export const displayTabConfig: TabPaneConfig = {
331
468
  * @param config 组件属性配置
332
469
  * @returns Object
333
470
  */
334
- export const fillConfig = (config: FormConfig = []) => [
471
+ export const fillConfig = (config: FormConfig = [], labelWidth = '80px'): FormConfig => [
335
472
  {
336
473
  type: 'tab',
474
+ labelWidth,
337
475
  items: [
338
476
  {
339
477
  title: '属性',
340
- labelWidth: '80px',
341
478
  items: [
342
479
  // 组件类型,必须要有
343
480
  {