@tmagic/editor 1.5.0-beta.9 → 1.5.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 (99) hide show
  1. package/dist/{style.css → tmagic-editor.css} +228 -22
  2. package/dist/tmagic-editor.js +1670 -1012
  3. package/dist/tmagic-editor.umd.cjs +1705 -1048
  4. package/package.json +14 -12
  5. package/src/Editor.vue +24 -6
  6. package/src/components/CodeBlockEditor.vue +14 -8
  7. package/src/components/CodeParams.vue +5 -5
  8. package/src/components/ContentMenu.vue +18 -18
  9. package/src/components/FloatingBox.vue +3 -3
  10. package/src/components/Resizer.vue +4 -4
  11. package/src/components/ScrollBar.vue +3 -3
  12. package/src/components/ScrollViewer.vue +3 -3
  13. package/src/components/SplitView.vue +2 -2
  14. package/src/components/ToolButton.vue +2 -1
  15. package/src/editorProps.ts +6 -2
  16. package/src/fields/Code.vue +1 -2
  17. package/src/fields/CodeSelect.vue +13 -11
  18. package/src/fields/CodeSelectCol.vue +32 -5
  19. package/src/fields/CondOpSelect.vue +5 -2
  20. package/src/fields/DataSourceFields.vue +31 -12
  21. package/src/fields/DataSourceInput.vue +2 -2
  22. package/src/fields/DataSourceMethods.vue +72 -14
  23. package/src/fields/DataSourceMocks.vue +0 -1
  24. package/src/fields/DisplayConds.vue +8 -3
  25. package/src/fields/EventSelect.vue +28 -12
  26. package/src/fields/KeyValue.vue +17 -12
  27. package/src/fields/UISelect.vue +6 -3
  28. package/src/hooks/index.ts +0 -1
  29. package/src/hooks/use-code-block-edit.ts +3 -3
  30. package/src/hooks/use-data-source-edit.ts +3 -2
  31. package/src/hooks/use-filter.ts +1 -1
  32. package/src/hooks/use-getso.ts +7 -7
  33. package/src/hooks/use-node-status.ts +2 -2
  34. package/src/index.ts +2 -1
  35. package/src/initService.ts +177 -74
  36. package/src/layouts/CodeEditor.vue +2 -2
  37. package/src/layouts/Framework.vue +13 -12
  38. package/src/layouts/NavMenu.vue +2 -2
  39. package/src/layouts/page-bar/AddButton.vue +29 -9
  40. package/src/layouts/page-bar/PageBar.vue +79 -66
  41. package/src/layouts/page-bar/PageBarScrollContainer.vue +84 -98
  42. package/src/layouts/page-bar/PageList.vue +5 -3
  43. package/src/layouts/page-bar/Search.vue +67 -0
  44. package/src/layouts/props-panel/FormPanel.vue +123 -0
  45. package/src/layouts/props-panel/PropsPanel.vue +146 -0
  46. package/src/layouts/props-panel/use-style-panel.ts +29 -0
  47. package/src/layouts/sidebar/Sidebar.vue +7 -1
  48. package/src/layouts/sidebar/code-block/CodeBlockList.vue +18 -2
  49. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +35 -4
  50. package/src/layouts/sidebar/code-block/useContentMenu.ts +83 -0
  51. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +7 -5
  52. package/src/layouts/sidebar/data-source/DataSourceList.vue +13 -8
  53. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +40 -4
  54. package/src/layouts/sidebar/data-source/useContentMenu.ts +81 -0
  55. package/src/layouts/sidebar/layer/LayerMenu.vue +7 -13
  56. package/src/layouts/sidebar/layer/LayerPanel.vue +11 -4
  57. package/src/layouts/sidebar/layer/use-click.ts +2 -2
  58. package/src/layouts/sidebar/layer/use-keybinding.ts +2 -2
  59. package/src/layouts/sidebar/layer/use-node-status.ts +2 -3
  60. package/src/layouts/workspace/Workspace.vue +13 -3
  61. package/src/layouts/workspace/viewer/NodeListMenu.vue +3 -3
  62. package/src/layouts/workspace/viewer/Stage.vue +41 -11
  63. package/src/layouts/workspace/viewer/StageOverlay.vue +2 -2
  64. package/src/layouts/workspace/viewer/ViewerMenu.vue +4 -6
  65. package/src/services/dataSource.ts +12 -5
  66. package/src/services/dep.ts +61 -13
  67. package/src/services/editor.ts +46 -51
  68. package/src/services/storage.ts +2 -1
  69. package/src/services/ui.ts +1 -0
  70. package/src/theme/common/var.scss +12 -10
  71. package/src/theme/component-list-panel.scss +9 -7
  72. package/src/theme/content-menu.scss +7 -5
  73. package/src/theme/data-source.scss +3 -1
  74. package/src/theme/floating-box.scss +4 -2
  75. package/src/theme/framework.scss +7 -5
  76. package/src/theme/index.scss +4 -5
  77. package/src/theme/key-value.scss +2 -2
  78. package/src/theme/layer-panel.scss +3 -1
  79. package/src/theme/layout.scss +1 -1
  80. package/src/theme/nav-menu.scss +7 -5
  81. package/src/theme/page-bar.scss +51 -27
  82. package/src/theme/props-panel.scss +81 -1
  83. package/src/theme/resizer.scss +1 -1
  84. package/src/theme/search-input.scss +1 -0
  85. package/src/theme/sidebar.scss +4 -2
  86. package/src/theme/stage.scss +3 -1
  87. package/src/theme/theme.scss +28 -28
  88. package/src/theme/tree.scss +14 -12
  89. package/src/type.ts +10 -1
  90. package/src/utils/content-menu.ts +2 -2
  91. package/src/utils/data-source/formConfigs/http.ts +2 -0
  92. package/src/utils/data-source/index.ts +2 -2
  93. package/src/utils/editor.ts +78 -22
  94. package/src/utils/idle-task.ts +36 -4
  95. package/src/utils/props.ts +48 -6
  96. package/types/index.d.ts +2312 -2080
  97. package/src/hooks/use-data-source-method.ts +0 -100
  98. package/src/layouts/PropsPanel.vue +0 -131
  99. package/src/layouts/page-bar/SwitchTypeButton.vue +0 -45
@@ -1,5 +1,78 @@
1
+ @use "common/var" as *;
2
+
1
3
  .m-editor-props-panel {
2
- padding: 0 10px 50px 10px;
4
+ height: 100%;
5
+ position: relative;
6
+
7
+ --props-style-panel-width: 300px;
8
+
9
+ .m-editor-props-form-panel {
10
+ padding-bottom: 10px;
11
+ position: relative;
12
+ height: 100%;
13
+ box-sizing: border-box;
14
+
15
+ .tmagic-design-scrollbar {
16
+ height: 100%;
17
+ }
18
+ }
19
+
20
+ .m-editor-props-property-panel {
21
+ &.show-style-panel {
22
+ padding-right: var(--props-style-panel-width);
23
+
24
+ .m-editor-props-panel-src-icon {
25
+ right: calc(15px + var(--props-style-panel-width));
26
+ }
27
+ }
28
+
29
+ .tmagic-design-form {
30
+ padding-right: 10px;
31
+ padding-left: 10px;
32
+
33
+ > .m-container-tab {
34
+ > .tmagic-design-tabs {
35
+ > .el-tabs__content {
36
+ padding-top: 55px;
37
+ }
38
+ > .el-tabs__header.is-top {
39
+ position: absolute;
40
+ top: 0;
41
+ width: 100%;
42
+ background: #fff;
43
+ z-index: 2;
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+
50
+ .m-editor-props-style-panel {
51
+ position: absolute;
52
+ width: var(--props-style-panel-width);
53
+ right: 0;
54
+ top: 0;
55
+ background: #fff;
56
+ z-index: 12;
57
+
58
+ $style-panel-title-height: 38px;
59
+
60
+ .tmagic-design-scrollbar {
61
+ height: calc(100% - $style-panel-title-height - 1px);
62
+ }
63
+
64
+ .m-editor-props-style-panel-title {
65
+ text-align: center;
66
+ font-size: 14px;
67
+ font-weight: 600;
68
+ padding: 0 5px;
69
+ height: $style-panel-title-height;
70
+ display: flex;
71
+ justify-content: space-between;
72
+ align-items: center;
73
+ border-bottom: 2px solid $border-color;
74
+ }
75
+ }
3
76
 
4
77
  .m-editor-props-panel-src-icon {
5
78
  position: absolute;
@@ -8,6 +81,13 @@
8
81
  z-index: 30;
9
82
  }
10
83
 
84
+ .m-editor-props-panel-style-icon {
85
+ position: absolute;
86
+ right: 15px;
87
+ bottom: 60px;
88
+ z-index: 30;
89
+ }
90
+
11
91
  .m-editor-props-panel-src-code.magic-code-editor {
12
92
  position: absolute;
13
93
  left: 0;
@@ -20,7 +20,7 @@
20
20
  }
21
21
  }
22
22
 
23
- &.m-editor-resizer-draging {
23
+ &.m-editor-resizer-dragging {
24
24
  &::after {
25
25
  content: "";
26
26
  position: absolute;
@@ -7,6 +7,7 @@
7
7
  left: 0;
8
8
  box-sizing: border-box;
9
9
  z-index: 1;
10
+ background: transparent;
10
11
 
11
12
  .el-input__prefix {
12
13
  padding: 7px;
@@ -1,9 +1,11 @@
1
+ @use "common/var" as *;
2
+
1
3
  .m-editor-sidebar {
2
4
  display: flex;
3
5
  height: 100%;
4
6
 
5
7
  .m-editor-sidebar-header {
6
- background: $--sidebar-heder-background-color;
8
+ background: $sidebar-heder-background-color;
7
9
  height: 100%;
8
10
  width: 40px;
9
11
 
@@ -16,7 +18,7 @@
16
18
  cursor: pointer;
17
19
 
18
20
  &.is-active {
19
- background: $--sidebar-content-background-color;
21
+ background: $sidebar-content-background-color;
20
22
 
21
23
  i {
22
24
  color: #353140;
@@ -1,7 +1,9 @@
1
+ @use "common/var" as *;
2
+
1
3
  .m-editor-stage {
2
4
  position: relative;
3
5
  width: 100%;
4
- height: calc(100% - #{$--page-bar-height});
6
+ height: calc(100% - #{$page-bar-height});
5
7
  overflow: hidden;
6
8
  display: flex;
7
9
  justify-content: center;
@@ -1,28 +1,28 @@
1
- @import "./search-input.scss";
2
- @import "./nav-menu.scss";
3
- @import "./framework.scss";
4
- @import "./sidebar.scss";
5
- @import "./layer-panel.scss";
6
- @import "./component-list-panel.scss";
7
- @import "./resizer.scss";
8
- @import "./workspace.scss";
9
- @import "./page-bar.scss";
10
- @import "./props-panel.scss";
11
- @import "./content-menu.scss";
12
- @import "./stage.scss";
13
- @import "./code-editor.scss";
14
- @import "./icon.scss";
15
- @import "./code-block.scss";
16
- @import "./event.scss";
17
- @import "./layout.scss";
18
- @import "./breadcrumb.scss";
19
- @import "./data-source.scss";
20
- @import "./data-source-fields.scss";
21
- @import "./data-source-methods.scss";
22
- @import "./data-source-input.scss";
23
- @import "./key-value.scss";
24
- @import "./tree.scss";
25
- @import "./floating-box.scss";
26
- @import "./page-fragment-select.scss";
27
- @import "./data-source-field.scss";
28
- @import "./data-source-field-select.scss";
1
+ @use "./search-input.scss";
2
+ @use "./nav-menu.scss";
3
+ @use "./framework.scss";
4
+ @use "./sidebar.scss";
5
+ @use "./layer-panel.scss";
6
+ @use "./component-list-panel.scss";
7
+ @use "./resizer.scss";
8
+ @use "./workspace.scss";
9
+ @use "./page-bar.scss";
10
+ @use "./props-panel.scss";
11
+ @use "./content-menu.scss";
12
+ @use "./stage.scss";
13
+ @use "./code-editor.scss";
14
+ @use "./icon.scss";
15
+ @use "./code-block.scss";
16
+ @use "./event.scss";
17
+ @use "./layout.scss";
18
+ @use "./breadcrumb.scss";
19
+ @use "./data-source.scss";
20
+ @use "./data-source-fields.scss";
21
+ @use "./data-source-methods.scss";
22
+ @use "./data-source-input.scss";
23
+ @use "./key-value.scss";
24
+ @use "./tree.scss";
25
+ @use "./floating-box.scss";
26
+ @use "./page-fragment-select.scss";
27
+ @use "./data-source-field.scss";
28
+ @use "./data-source-field-select.scss";
@@ -1,6 +1,8 @@
1
+ @use "common/var" as *;
2
+
1
3
  .m-editor-tree {
2
- $--node-height: 22px;
3
- color: $--font-color;
4
+ $node-height: 22px;
5
+ color: $font-color;
4
6
  font-size: 13px;
5
7
 
6
8
  .m-editor-tree-node {
@@ -12,31 +14,31 @@
12
14
  align-items: center;
13
15
 
14
16
  &:hover {
15
- background-color: $--hover-color;
16
- color: $--font-color;
17
+ background-color: $hover-color;
18
+ color: $font-color;
17
19
  }
18
20
 
19
21
  &.selected {
20
- background-color: $--theme-color;
21
- color: $--hover-color;
22
+ background-color: $theme-color;
23
+ color: $hover-color;
22
24
  }
23
25
 
24
26
  &.drag-inner {
25
27
  .tree-node-content {
26
- background-color: rgba($color: $--theme-color, $alpha: 0.5);
27
- color: $--hover-color;
28
+ background-color: rgba($color: $theme-color, $alpha: 0.5);
29
+ color: $hover-color;
28
30
  }
29
31
  }
30
32
 
31
33
  &.drag-before {
32
34
  .tree-node-content {
33
- border-top-color: rgba($color: $--theme-color, $alpha: 0.5);
35
+ border-top-color: rgba($color: $theme-color, $alpha: 0.5);
34
36
  }
35
37
  }
36
38
 
37
39
  &.drag-after {
38
40
  .tree-node-content {
39
- border-bottom-color: rgba($color: $--theme-color, $alpha: 0.5);
41
+ border-bottom-color: rgba($color: $theme-color, $alpha: 0.5);
40
42
  }
41
43
  }
42
44
 
@@ -50,11 +52,11 @@
50
52
  display: flex;
51
53
  flex: 1;
52
54
  justify-content: space-between;
53
- height: $--node-height;
55
+ height: $node-height;
54
56
  border-top: 2px solid transparent;
55
57
  border-bottom: 2px solid transparent;
56
58
  .tree-node-label {
57
- line-height: $--node-height;
59
+ line-height: $node-height;
58
60
  flex: 1;
59
61
  width: 100px;
60
62
  overflow: hidden;
package/src/type.ts CHANGED
@@ -77,9 +77,10 @@ export interface FrameworkSlots {
77
77
  'props-panel'(props: {}): any;
78
78
  'footer'(props: {}): any;
79
79
  'page-bar'(props: {}): any;
80
+ 'page-bar-add-button'(props: {}): any;
80
81
  'page-bar-title'(props: { page: MPage | MPageFragment }): any;
81
82
  'page-bar-popover'(props: { page: MPage | MPageFragment }): any;
82
- 'page-list-popover'(props: { list: MPage[] | MPageFragment[] }): any;
83
+ 'page-list-popover'(props: { list: (MPage | MPageFragment)[] }): any;
83
84
  }
84
85
 
85
86
  export interface WorkspaceSlots {
@@ -230,6 +231,8 @@ export interface UiState {
230
231
  uiSelectMode: boolean;
231
232
  /** 是否显示整个配置源码, true: 显示, false: 不显示,默认为false */
232
233
  showSrc: boolean;
234
+ /** 是否将样式配置单独一列显示, true: 显示, false: 不显示,默认为true */
235
+ showStylePanel: boolean;
233
236
  /** 画布显示放大倍数,默认为 1 */
234
237
  zoom: number;
235
238
  /** 画布容器的宽高 */
@@ -765,6 +768,7 @@ export type SyncHookPlugin<
765
768
 
766
769
  export interface EventBusEvent {
767
770
  'edit-data-source': [id: string];
771
+ 'remove-data-source': [id: string];
768
772
  'edit-code': [id: string];
769
773
  }
770
774
 
@@ -786,3 +790,8 @@ export interface PageBarSortOptions extends PartSortableOptions {
786
790
  /** 在onStart之前调用 */
787
791
  beforeStart?: (event: SortableEvent, sortable: Sortable) => void | Promise<void>;
788
792
  }
793
+
794
+ export type CustomContentMenuFunction = (
795
+ menus: (MenuButton | MenuComponent)[],
796
+ type: 'layer' | 'data-source' | 'viewer' | 'code-block',
797
+ ) => (MenuButton | MenuComponent)[];
@@ -1,4 +1,4 @@
1
- import { computed, markRaw, Ref } from 'vue';
1
+ import { computed, markRaw, type ShallowRef } from 'vue';
2
2
  import { CopyDocument, Delete, DocumentCopy } from '@element-plus/icons-vue';
3
3
 
4
4
  import { Id, MContainer, NodeType } from '@tmagic/core';
@@ -33,7 +33,7 @@ export const useCopyMenu = (): MenuButton => ({
33
33
  },
34
34
  });
35
35
 
36
- export const usePasteMenu = (menu?: Ref<InstanceType<typeof ContentMenu> | undefined>): MenuButton => ({
36
+ export const usePasteMenu = (menu?: ShallowRef<InstanceType<typeof ContentMenu> | null>): MenuButton => ({
37
37
  type: 'button',
38
38
  text: '粘贴',
39
39
  icon: markRaw(DocumentCopy),
@@ -40,6 +40,7 @@ export default [
40
40
  name: 'params',
41
41
  type: 'key-value',
42
42
  defaultValue: {},
43
+ advanced: true,
43
44
  text: '参数',
44
45
  },
45
46
  {
@@ -53,6 +54,7 @@ export default [
53
54
  name: 'headers',
54
55
  type: 'key-value',
55
56
  defaultValue: {},
57
+ advanced: true,
56
58
  text: '请求头',
57
59
  },
58
60
  ],
@@ -58,7 +58,7 @@ const fillConfig = (config: FormConfig): FormConfig => [
58
58
  },
59
59
  {
60
60
  title: '请求参数裁剪',
61
- display: (formState: FormState, { model }: any) => model.type === 'http',
61
+ display: (_formState: FormState, { model }: any) => model.type === 'http',
62
62
  items: [
63
63
  {
64
64
  name: 'beforeRequest',
@@ -70,7 +70,7 @@ const fillConfig = (config: FormConfig): FormConfig => [
70
70
  },
71
71
  {
72
72
  title: '响应数据裁剪',
73
- display: (formState: FormState, { model }: any) => model.type === 'http',
73
+ display: (_formState: FormState, { model }: any) => model.type === 'http',
74
74
  items: [
75
75
  {
76
76
  name: 'afterResponse',
@@ -16,12 +16,23 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ import { detailedDiff } from 'deep-object-diff';
20
+ import { isObject } from 'lodash-es';
19
21
  import serialize from 'serialize-javascript';
20
22
 
21
23
  import type { Id, MApp, MContainer, MNode, MPage, MPageFragment } from '@tmagic/core';
22
- import { NodeType } from '@tmagic/core';
24
+ import { NODE_CONDS_KEY, NodeType } from '@tmagic/core';
23
25
  import type StageCore from '@tmagic/stage';
24
- import { calcValueByFontsize, getElById, getNodePath, isNumber, isPage, isPageFragment, isPop } from '@tmagic/utils';
26
+ import {
27
+ calcValueByFontsize,
28
+ getElById,
29
+ getNodePath,
30
+ isNumber,
31
+ isPage,
32
+ isPageFragment,
33
+ isPop,
34
+ isValueIncludeDataSource,
35
+ } from '@tmagic/utils';
25
36
 
26
37
  import { Layout } from '@editor/type';
27
38
 
@@ -272,26 +283,6 @@ export const serializeConfig = (config: any) =>
272
283
  unsafe: true,
273
284
  }).replace(/"(\w+)":\s/g, '$1: ');
274
285
 
275
- export interface NodeItem {
276
- items?: NodeItem[];
277
- [key: string]: any;
278
- }
279
-
280
- export const traverseNode = <T extends NodeItem = NodeItem>(
281
- node: T,
282
- cb: (node: T, parents: T[]) => void,
283
- parents: T[] = [],
284
- ) => {
285
- cb(node, parents);
286
-
287
- if (Array.isArray(node.items) && node.items.length) {
288
- parents.push(node);
289
- node.items.forEach((item) => {
290
- traverseNode(item as T, cb, [...parents]);
291
- });
292
- }
293
- };
294
-
295
286
  export const moveItemsInContainer = (sourceIndices: number[], parent: MContainer, targetIndex: number) => {
296
287
  sourceIndices.sort((a, b) => a - b);
297
288
  for (let i = sourceIndices.length - 1; i >= 0; i--) {
@@ -310,3 +301,68 @@ export const moveItemsInContainer = (sourceIndices: number[], parent: MContainer
310
301
  }
311
302
  }
312
303
  };
304
+
305
+ const isIncludeDataSourceByDiffAddResult = (diffResult: any) => {
306
+ for (const value of Object.values(diffResult)) {
307
+ const result = isValueIncludeDataSource(value);
308
+
309
+ if (result) {
310
+ return true;
311
+ }
312
+
313
+ if (isObject(value)) {
314
+ return isIncludeDataSourceByDiffAddResult(value);
315
+ }
316
+ }
317
+ return false;
318
+ };
319
+
320
+ const isIncludeDataSourceByDiffUpdatedResult = (diffResult: any, oldNode: any) => {
321
+ for (const [key, value] of Object.entries<any>(diffResult)) {
322
+ if (isValueIncludeDataSource(value)) {
323
+ return true;
324
+ }
325
+
326
+ if (isValueIncludeDataSource(oldNode[key])) {
327
+ return true;
328
+ }
329
+
330
+ if (isObject(value)) {
331
+ return isIncludeDataSourceByDiffUpdatedResult(value, oldNode[key]);
332
+ }
333
+ }
334
+ return false;
335
+ };
336
+
337
+ export const isIncludeDataSource = (node: MNode, oldNode: MNode) => {
338
+ const diffResult = detailedDiff(oldNode, node);
339
+
340
+ let isIncludeDataSource = false;
341
+
342
+ if (diffResult.updated) {
343
+ // 修改了显示条件
344
+ if ((diffResult.updated as any)[NODE_CONDS_KEY]) {
345
+ return true;
346
+ }
347
+
348
+ isIncludeDataSource = isIncludeDataSourceByDiffUpdatedResult(diffResult.updated, oldNode);
349
+ if (isIncludeDataSource) return true;
350
+ }
351
+
352
+ if (diffResult.added) {
353
+ isIncludeDataSource = isIncludeDataSourceByDiffAddResult(diffResult.added);
354
+ if (isIncludeDataSource) return true;
355
+ }
356
+
357
+ if (diffResult.deleted) {
358
+ // 删除了显示条件
359
+ if ((diffResult.deleted as any)[NODE_CONDS_KEY]) {
360
+ return true;
361
+ }
362
+
363
+ isIncludeDataSource = isIncludeDataSourceByDiffAddResult(diffResult.deleted);
364
+ if (isIncludeDataSource) return true;
365
+ }
366
+
367
+ return isIncludeDataSource;
368
+ };
@@ -26,6 +26,11 @@ export class IdleTask<T = any> extends EventEmitter {
26
26
 
27
27
  private taskHandle: number | null = null;
28
28
 
29
+ constructor() {
30
+ super();
31
+ this.setMaxListeners(1000);
32
+ }
33
+
29
34
  public enqueueTask(taskHandler: (data: T) => void, taskData: T) {
30
35
  this.taskList.push({
31
36
  handler: taskHandler,
@@ -37,6 +42,10 @@ export class IdleTask<T = any> extends EventEmitter {
37
42
  }
38
43
  }
39
44
 
45
+ public clearTasks() {
46
+ this.taskList = [];
47
+ }
48
+
40
49
  public on<Name extends keyof IdleTaskEvents, Param extends IdleTaskEvents[Name]>(
41
50
  eventName: Name,
42
51
  listener: (...args: Param) => void | Promise<void>,
@@ -56,13 +65,36 @@ export class IdleTask<T = any> extends EventEmitter {
56
65
  }
57
66
 
58
67
  private runTaskQueue(deadline: IdleDeadline) {
59
- while ((deadline.timeRemaining() > 15 || deadline.didTimeout) && this.taskList.length) {
60
- const task = this.taskList.shift();
61
- task!.handler(task!.data);
68
+ // 动画会占用空闲时间,当任务一直无法执行时,看看是否有动画正在播放
69
+ // 根据空闲时间的多少来决定执行的任务数,保证页面不卡死的情况下尽量多执行任务,不然当任务数巨大时,执行时间会很久
70
+ // 执行不完不会影响配置,但是会影响画布渲染
71
+ while (deadline.timeRemaining() > 0 && this.taskList.length) {
72
+ const timeRemaining = deadline.timeRemaining();
73
+ let times = 0;
74
+ if (timeRemaining <= 5) {
75
+ times = 10;
76
+ } else if (timeRemaining <= 10) {
77
+ times = 100;
78
+ } else if (timeRemaining <= 15) {
79
+ times = 300;
80
+ } else {
81
+ times = 600;
82
+ }
83
+
84
+ for (let i = 0; i < times; i++) {
85
+ const task = this.taskList.shift();
86
+ if (task) {
87
+ task.handler(task.data);
88
+ }
89
+
90
+ if (this.taskList.length === 0) {
91
+ break;
92
+ }
93
+ }
62
94
  }
63
95
 
64
96
  if (this.taskList.length) {
65
- this.taskHandle = globalThis.requestIdleCallback(this.runTaskQueue.bind(this), { timeout: 10000 });
97
+ this.taskHandle = globalThis.requestIdleCallback(this.runTaskQueue.bind(this), { timeout: 300 });
66
98
  } else {
67
99
  this.taskHandle = 0;
68
100
 
@@ -18,6 +18,7 @@
18
18
  */
19
19
 
20
20
  import { NODE_CONDS_KEY } from '@tmagic/core';
21
+ import { tMagicMessage } from '@tmagic/design';
21
22
  import type { FormConfig, FormState, TabPaneConfig } from '@tmagic/form';
22
23
 
23
24
  export const arrayOptions = [
@@ -41,6 +42,7 @@ export const numberOptions = [
41
42
 
42
43
  export const styleTabConfig: TabPaneConfig = {
43
44
  title: '样式',
45
+ display: ({ services }: any) => !(services.uiService.get('showStylePanel') ?? true),
44
46
  items: [
45
47
  {
46
48
  name: 'style',
@@ -53,6 +55,7 @@ export const styleTabConfig: TabPaneConfig = {
53
55
  type: 'data-source-field-select',
54
56
  name: 'position',
55
57
  text: '固定定位',
58
+ labelPosition: 'left',
56
59
  checkStrictly: false,
57
60
  dataSourceFieldType: ['string'],
58
61
  fieldConfig: {
@@ -81,7 +84,7 @@ export const styleTabConfig: TabPaneConfig = {
81
84
  fieldConfig: {
82
85
  type: 'text',
83
86
  },
84
- disabled: (vm: FormState, { model }: any) =>
87
+ disabled: (_vm: FormState, { model }: any) =>
85
88
  model.position === 'fixed' && model._magic_position === 'fixedBottom',
86
89
  },
87
90
  {
@@ -103,7 +106,7 @@ export const styleTabConfig: TabPaneConfig = {
103
106
  fieldConfig: {
104
107
  type: 'text',
105
108
  },
106
- disabled: (vm: FormState, { model }: any) =>
109
+ disabled: (_vm: FormState, { model }: any) =>
107
110
  model.position === 'fixed' && model._magic_position === 'fixedTop',
108
111
  },
109
112
  ],
@@ -112,6 +115,27 @@ export const styleTabConfig: TabPaneConfig = {
112
115
  type: 'fieldset',
113
116
  legend: '盒子',
114
117
  items: [
118
+ {
119
+ type: 'data-source-field-select',
120
+ name: 'display',
121
+ text: 'display',
122
+ checkStrictly: false,
123
+ dataSourceFieldType: ['string'],
124
+ fieldConfig: {
125
+ type: 'select',
126
+ clearable: true,
127
+ allowCreate: true,
128
+ options: [
129
+ { text: 'block', value: 'block' },
130
+ { text: 'flex', value: 'flex' },
131
+ { text: 'none', value: 'none' },
132
+ { text: 'inline-block', value: 'inline-block' },
133
+ { text: 'grid', value: 'grid' },
134
+ { text: 'inline', value: 'inline' },
135
+ { text: 'initial', value: 'initial' },
136
+ ],
137
+ },
138
+ },
115
139
  {
116
140
  type: 'data-source-field-select',
117
141
  name: 'width',
@@ -140,6 +164,8 @@ export const styleTabConfig: TabPaneConfig = {
140
164
  dataSourceFieldType: ['string'],
141
165
  fieldConfig: {
142
166
  type: 'select',
167
+ clearable: true,
168
+ allowCreate: true,
143
169
  options: [
144
170
  { text: 'visible', value: 'visible' },
145
171
  { text: 'hidden', value: 'hidden' },
@@ -147,6 +173,7 @@ export const styleTabConfig: TabPaneConfig = {
147
173
  { text: 'scroll', value: 'scroll' },
148
174
  { text: 'auto', value: 'auto' },
149
175
  { text: 'overlay', value: 'overlay' },
176
+ { text: 'initial', value: 'initial' },
150
177
  ],
151
178
  },
152
179
  },
@@ -213,7 +240,7 @@ export const styleTabConfig: TabPaneConfig = {
213
240
  checkStrictly: false,
214
241
  dataSourceFieldType: ['string'],
215
242
  fieldConfig: {
216
- type: 'text',
243
+ type: 'img-upload',
217
244
  },
218
245
  },
219
246
  {
@@ -344,11 +371,13 @@ export const advancedTabConfig: TabPaneConfig = {
344
371
  {
345
372
  name: 'created',
346
373
  text: 'created',
374
+ labelPosition: 'top',
347
375
  type: 'code-select',
348
376
  },
349
377
  {
350
378
  name: 'mounted',
351
379
  text: 'mounted',
380
+ labelPosition: 'top',
352
381
  type: 'code-select',
353
382
  },
354
383
  ],
@@ -356,7 +385,7 @@ export const advancedTabConfig: TabPaneConfig = {
356
385
 
357
386
  export const displayTabConfig: TabPaneConfig = {
358
387
  title: '显示条件',
359
- display: (vm: FormState, { model }: any) => model.type !== 'page',
388
+ display: (_vm: FormState, { model }: any) => model.type !== 'page',
360
389
  items: [
361
390
  {
362
391
  type: 'display-conds',
@@ -389,8 +418,21 @@ export const fillConfig = (config: FormConfig = [], labelWidth = '80px'): FormCo
389
418
  // 组件id,必须要有
390
419
  {
391
420
  name: 'id',
392
- type: 'display',
393
- text: 'id',
421
+ text: 'ID',
422
+ type: 'text',
423
+ disabled: true,
424
+ append: {
425
+ type: 'button',
426
+ text: '复制',
427
+ handler: async (vm, { model }) => {
428
+ try {
429
+ await navigator.clipboard.writeText(`${model.id}`);
430
+ tMagicMessage.success('已复制');
431
+ } catch (err) {
432
+ tMagicMessage.error('复制失败');
433
+ }
434
+ },
435
+ },
394
436
  },
395
437
  {
396
438
  name: 'name',