@tmagic/editor 1.2.0-beta.1 → 1.2.0-beta.11
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/style.css +14 -8
- package/dist/tmagic-editor.mjs +1112 -981
- package/dist/tmagic-editor.mjs.map +1 -1
- package/dist/tmagic-editor.umd.js +1124 -991
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/package.json +11 -10
- package/src/Editor.vue +11 -13
- package/src/components/ContentMenu.vue +4 -4
- package/src/components/Icon.vue +7 -5
- package/src/{layouts → components}/Layout.vue +14 -4
- package/src/components/ScrollBar.vue +1 -1
- package/src/components/ScrollViewer.vue +10 -1
- package/src/components/ToolButton.vue +30 -15
- package/src/fields/Code.vue +5 -2
- package/src/fields/CodeLink.vue +20 -12
- package/src/fields/CodeSelect.vue +19 -27
- package/src/fields/UISelect.vue +9 -8
- package/src/index.ts +3 -1
- package/src/layouts/AddPageBox.vue +13 -20
- package/src/layouts/CodeEditor.vue +106 -120
- package/src/layouts/Framework.vue +62 -40
- package/src/layouts/NavMenu.vue +1 -1
- package/src/layouts/PropsPanel.vue +4 -9
- package/src/layouts/Resizer.vue +1 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +15 -13
- package/src/layouts/sidebar/LayerMenu.vue +89 -92
- package/src/layouts/sidebar/LayerPanel.vue +273 -178
- package/src/layouts/sidebar/Sidebar.vue +126 -46
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +28 -24
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +22 -22
- package/src/layouts/workspace/Breadcrumb.vue +32 -0
- package/src/layouts/workspace/PageBar.vue +12 -11
- package/src/layouts/workspace/PageBarScrollContainer.vue +1 -1
- package/src/layouts/workspace/Stage.vue +15 -7
- package/src/layouts/workspace/ViewerMenu.vue +8 -7
- package/src/layouts/workspace/Workspace.vue +10 -3
- package/src/services/codeBlock.ts +16 -10
- package/src/services/editor.ts +12 -8
- package/src/theme/breadcrumb.scss +6 -0
- package/src/theme/component-list-panel.scss +3 -7
- package/src/theme/index.scss +1 -15
- package/src/theme/layer-panel.scss +7 -2
- package/src/theme/theme.scss +16 -0
- package/src/type.ts +2 -1
- package/src/utils/scroll-viewer.ts +18 -2
- package/src/utils/stage.ts +7 -0
- package/types/Editor.vue.d.ts +2 -2
- package/types/components/ContentMenu.vue.d.ts +1 -3
- package/types/components/Icon.vue.d.ts +1 -3
- package/types/{layouts → components}/Layout.vue.d.ts +0 -0
- package/types/components/ScrollBar.vue.d.ts +1 -3
- package/types/components/ScrollViewer.vue.d.ts +45 -1
- package/types/components/ToolButton.vue.d.ts +1 -3
- package/types/fields/Code.vue.d.ts +9 -3
- package/types/fields/CodeLink.vue.d.ts +5 -3
- package/types/fields/CodeSelect.vue.d.ts +1 -3
- package/types/fields/UISelect.vue.d.ts +1 -3
- package/types/index.d.ts +2 -0
- package/types/layouts/AddPageBox.vue.d.ts +43 -3
- package/types/layouts/CodeEditor.vue.d.ts +158 -45
- package/types/layouts/NavMenu.vue.d.ts +1 -3
- package/types/layouts/sidebar/LayerMenu.vue.d.ts +31 -63
- package/types/layouts/sidebar/LayerPanel.vue.d.ts +38 -1074
- package/types/layouts/sidebar/Sidebar.vue.d.ts +119 -17
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +1 -0
- package/types/layouts/workspace/Breadcrumb.vue.d.ts +44 -0
- package/types/layouts/workspace/Stage.vue.d.ts +23 -7
- package/types/layouts/workspace/ViewerMenu.vue.d.ts +6 -3
- package/types/layouts/workspace/Workspace.vue.d.ts +23 -5
- package/types/services/codeBlock.d.ts +1 -1
- package/types/services/editor.d.ts +2 -2
- package/types/services/ui.d.ts +1 -1
- package/types/type.d.ts +2 -1
- package/types/utils/scroll-viewer.d.ts +5 -0
- package/src/layouts/sidebar/TabPane.vue +0 -126
- package/types/layouts/sidebar/TabPane.vue.d.ts +0 -14
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.2.0-beta.
|
|
2
|
+
"version": "1.2.0-beta.11",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"dist/*",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@babel/core": "^7.18.0",
|
|
47
47
|
"@element-plus/icons-vue": "^2.0.9",
|
|
48
|
-
"@tmagic/core": "1.2.0-beta.
|
|
49
|
-
"@tmagic/
|
|
50
|
-
"@tmagic/
|
|
51
|
-
"@tmagic/
|
|
52
|
-
"@tmagic/
|
|
48
|
+
"@tmagic/core": "1.2.0-beta.11",
|
|
49
|
+
"@tmagic/design": "1.2.0-beta.11",
|
|
50
|
+
"@tmagic/form": "1.2.0-beta.11",
|
|
51
|
+
"@tmagic/schema": "1.2.0-beta.11",
|
|
52
|
+
"@tmagic/stage": "1.2.0-beta.11",
|
|
53
|
+
"@tmagic/utils": "1.2.0-beta.11",
|
|
53
54
|
"buffer": "^6.0.3",
|
|
54
55
|
"color": "^3.1.3",
|
|
55
|
-
"element-plus": "^2.2.17",
|
|
56
56
|
"events": "^3.3.0",
|
|
57
57
|
"gesto": "^1.7.0",
|
|
58
58
|
"keycon": "^1.1.2",
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"vue": "^3.2.37"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@tmagic/
|
|
66
|
-
"
|
|
65
|
+
"@tmagic/design": "1.2.0-beta.11",
|
|
66
|
+
"@tmagic/form": "1.2.0-beta.11",
|
|
67
67
|
"monaco-editor": "^0.34.0",
|
|
68
68
|
"vue": "^3.2.37"
|
|
69
69
|
},
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
"sass": "^1.35.1",
|
|
80
80
|
"typescript": "^4.7.4",
|
|
81
81
|
"vite": "^3.1.3",
|
|
82
|
-
"vue-
|
|
82
|
+
"vite-plugin-vue-setup-extend": "^0.4.0",
|
|
83
|
+
"vue-tsc": "^1.0.8"
|
|
83
84
|
}
|
|
84
85
|
}
|
package/src/Editor.vue
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<Framework :code-options="codeOptions">
|
|
3
3
|
<template #nav>
|
|
4
|
-
<slot name="nav" :editorService="editorService"><
|
|
4
|
+
<slot name="nav" :editorService="editorService"><NavMenu :data="menu"></NavMenu></slot>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<template #sidebar>
|
|
8
8
|
<slot name="sidebar" :editorService="editorService">
|
|
9
|
-
<
|
|
9
|
+
<Sidebar :data="sidebar" :layer-content-menu="layerContentMenu">
|
|
10
10
|
<template #layer-panel-header>
|
|
11
11
|
<slot name="layer-panel-header"></slot>
|
|
12
12
|
</template>
|
|
@@ -27,40 +27,40 @@
|
|
|
27
27
|
<slot name="code-block-panel-header"></slot>
|
|
28
28
|
</template>
|
|
29
29
|
|
|
30
|
-
<template #code-block-panel-tool="{ id }">
|
|
31
|
-
<slot name="code-block-panel-tool" :id="id"></slot>
|
|
30
|
+
<template #code-block-panel-tool="{ id, data }">
|
|
31
|
+
<slot name="code-block-panel-tool" :id="id" :data="data"></slot>
|
|
32
32
|
</template>
|
|
33
33
|
|
|
34
34
|
<template #code-block-edit-panel-header="{ id }">
|
|
35
35
|
<slot name="code-block-edit-panel-header" :id="id"></slot>
|
|
36
36
|
</template>
|
|
37
|
-
</
|
|
37
|
+
</Sidebar>
|
|
38
38
|
</slot>
|
|
39
39
|
</template>
|
|
40
40
|
|
|
41
41
|
<template #workspace>
|
|
42
42
|
<slot name="workspace" :editorService="editorService">
|
|
43
|
-
<
|
|
43
|
+
<Workspace :stage-content-menu="stageContentMenu">
|
|
44
44
|
<template #stage><slot name="stage"></slot></template>
|
|
45
45
|
<template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
|
|
46
46
|
<template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
|
|
47
47
|
<template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
|
|
48
|
-
</
|
|
48
|
+
</Workspace>
|
|
49
49
|
</slot>
|
|
50
50
|
</template>
|
|
51
51
|
|
|
52
52
|
<template #props-panel>
|
|
53
53
|
<slot name="props-panel">
|
|
54
|
-
<
|
|
54
|
+
<PropsPanel @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
|
|
55
55
|
<template #props-panel-header>
|
|
56
56
|
<slot name="props-panel-header"></slot>
|
|
57
57
|
</template>
|
|
58
|
-
</
|
|
58
|
+
</PropsPanel>
|
|
59
59
|
</slot>
|
|
60
60
|
</template>
|
|
61
61
|
|
|
62
62
|
<template #empty><slot name="empty" :editorService="editorService"></slot></template>
|
|
63
|
-
</
|
|
63
|
+
</Framework>
|
|
64
64
|
</template>
|
|
65
65
|
|
|
66
66
|
<script lang="ts">
|
|
@@ -319,8 +319,6 @@ export default defineComponent({
|
|
|
319
319
|
|
|
320
320
|
provide('services', services);
|
|
321
321
|
|
|
322
|
-
provide('layerContentMenu', props.layerContentMenu);
|
|
323
|
-
provide('stageContentMenu', props.stageContentMenu);
|
|
324
322
|
provide(
|
|
325
323
|
'stageOptions',
|
|
326
324
|
reactive({
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-if="menuData.length
|
|
2
|
+
<div v-if="menuData.length" v-show="visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
|
|
3
3
|
<div>
|
|
4
|
-
<
|
|
4
|
+
<ToolButton
|
|
5
5
|
v-for="(item, index) in menuData"
|
|
6
6
|
event-type="mouseup"
|
|
7
7
|
:data="item"
|
|
8
8
|
:key="index"
|
|
9
9
|
@mouseup="hide"
|
|
10
10
|
@mouseenter="showSubMenu(item)"
|
|
11
|
-
></
|
|
11
|
+
></ToolButton>
|
|
12
12
|
</div>
|
|
13
13
|
<teleport to="body">
|
|
14
14
|
<content-menu
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
</template>
|
|
24
24
|
|
|
25
|
-
<script lang="ts" setup>
|
|
25
|
+
<script lang="ts" setup name="MEditorContentMenu">
|
|
26
26
|
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
|
|
27
27
|
|
|
28
28
|
import { MenuButton, MenuComponent } from '../type';
|
package/src/components/Icon.vue
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
2
|
+
<TMagicIcon v-if="!icon" class="magic-editor-icon"><Edit></Edit></TMagicIcon>
|
|
3
|
+
<TMagicIcon v-else-if="typeof icon === 'string' && icon.startsWith('http')" class="magic-editor-icon"
|
|
4
4
|
><img :src="icon"
|
|
5
|
-
/></
|
|
5
|
+
/></TMagicIcon>
|
|
6
6
|
<i v-else-if="typeof icon === 'string'" class="magic-editor-icon" :class="icon"></i>
|
|
7
|
-
<
|
|
7
|
+
<TMagicIcon v-else class="magic-editor-icon"><component :is="toRaw(icon)"></component></TMagicIcon>
|
|
8
8
|
</template>
|
|
9
9
|
|
|
10
|
-
<script lang="ts" setup>
|
|
10
|
+
<script lang="ts" setup name="MEditorIcon">
|
|
11
11
|
import { toRaw } from 'vue';
|
|
12
12
|
import { Edit } from '@element-plus/icons-vue';
|
|
13
13
|
|
|
14
|
+
import { TMagicIcon } from '@tmagic/design';
|
|
15
|
+
|
|
14
16
|
defineProps<{
|
|
15
17
|
icon?: any;
|
|
16
18
|
}>();
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
</template>
|
|
22
22
|
|
|
23
|
-
<script lang="ts" setup>
|
|
23
|
+
<script lang="ts" setup name="MEditorLayout">
|
|
24
24
|
import { onMounted, onUnmounted, ref } from 'vue';
|
|
25
25
|
|
|
26
|
-
import Resizer from '
|
|
26
|
+
import Resizer from '../layouts/Resizer.vue';
|
|
27
27
|
|
|
28
28
|
const emit = defineEmits(['update:left', 'change', 'update:right']);
|
|
29
29
|
|
|
@@ -74,8 +74,13 @@ const center = ref(0);
|
|
|
74
74
|
|
|
75
75
|
const changeLeft = (deltaX: number) => {
|
|
76
76
|
if (typeof props.left === 'undefined') return;
|
|
77
|
-
|
|
77
|
+
let left = Math.max(props.left + deltaX, props.minLeft) || 0;
|
|
78
78
|
emit('update:left', left);
|
|
79
|
+
|
|
80
|
+
if (clientWidth - left - (props.right || 0) <= 0) {
|
|
81
|
+
left = props.left;
|
|
82
|
+
}
|
|
83
|
+
|
|
79
84
|
center.value = clientWidth - left - (props.right || 0);
|
|
80
85
|
|
|
81
86
|
emit('change', {
|
|
@@ -87,8 +92,13 @@ const changeLeft = (deltaX: number) => {
|
|
|
87
92
|
|
|
88
93
|
const changeRight = (deltaX: number) => {
|
|
89
94
|
if (typeof props.right === 'undefined') return;
|
|
90
|
-
|
|
95
|
+
let right = Math.max(props.right - deltaX, props.minRight) || 0;
|
|
91
96
|
emit('update:right', right);
|
|
97
|
+
|
|
98
|
+
if (clientWidth - (props.left || 0) - right <= 0) {
|
|
99
|
+
right = props.right;
|
|
100
|
+
}
|
|
101
|
+
|
|
92
102
|
center.value = clientWidth - (props.left || 0) - right;
|
|
93
103
|
|
|
94
104
|
emit('change', {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
</div>
|
|
23
23
|
</template>
|
|
24
24
|
|
|
25
|
-
<script lang="ts" setup>
|
|
25
|
+
<script lang="ts" setup name="MEditorScrollViewer">
|
|
26
26
|
import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
27
27
|
|
|
28
28
|
import { ScrollViewerEvent } from '../type';
|
|
@@ -37,6 +37,10 @@ const props = withDefaults(
|
|
|
37
37
|
wrapWidth?: number;
|
|
38
38
|
wrapHeight?: number;
|
|
39
39
|
zoom?: number;
|
|
40
|
+
correctionScrollSize?: {
|
|
41
|
+
width: number;
|
|
42
|
+
height: number;
|
|
43
|
+
};
|
|
40
44
|
}>(),
|
|
41
45
|
{
|
|
42
46
|
width: 0,
|
|
@@ -44,6 +48,10 @@ const props = withDefaults(
|
|
|
44
48
|
wrapWidth: 0,
|
|
45
49
|
wrapHeight: 0,
|
|
46
50
|
zoom: 1,
|
|
51
|
+
correctionScrollSize: () => ({
|
|
52
|
+
width: 0,
|
|
53
|
+
height: 0,
|
|
54
|
+
}),
|
|
47
55
|
},
|
|
48
56
|
);
|
|
49
57
|
|
|
@@ -69,6 +77,7 @@ onMounted(() => {
|
|
|
69
77
|
container: container.value,
|
|
70
78
|
target: el.value,
|
|
71
79
|
zoom: props.zoom,
|
|
80
|
+
correctionScrollSize: props.correctionScrollSize,
|
|
72
81
|
});
|
|
73
82
|
|
|
74
83
|
scrollViewer.on('scroll', (data: ScrollViewerEvent) => {
|
|
@@ -7,41 +7,56 @@
|
|
|
7
7
|
@mousedown="mousedownHandler(data, $event)"
|
|
8
8
|
@mouseup="mouseupHandler(data, $event)"
|
|
9
9
|
>
|
|
10
|
-
<
|
|
10
|
+
<TMagicDivider v-if="data.type === 'divider'" :direction="data.direction || 'vertical'"></TMagicDivider>
|
|
11
11
|
<div v-else-if="data.type === 'text'" class="menu-item-text">{{ data.text }}</div>
|
|
12
12
|
|
|
13
13
|
<template v-else-if="data.type === 'button'">
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></
|
|
14
|
+
<TMagicTooltip v-if="data.tooltip" effect="dark" placement="bottom-start" :content="data.tooltip">
|
|
15
|
+
<TMagicButton size="small" text :disabled="disabled"
|
|
16
|
+
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></TMagicButton
|
|
17
17
|
>
|
|
18
|
-
</
|
|
19
|
-
<
|
|
20
|
-
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></
|
|
18
|
+
</TMagicTooltip>
|
|
19
|
+
<TMagicButton v-else size="small" text :disabled="disabled"
|
|
20
|
+
><MIcon v-if="data.icon" :icon="data.icon"></MIcon><span>{{ data.text }}</span></TMagicButton
|
|
21
21
|
>
|
|
22
22
|
</template>
|
|
23
23
|
|
|
24
|
-
<
|
|
24
|
+
<TMagicDropdown
|
|
25
|
+
v-else-if="data.type === 'dropdown'"
|
|
26
|
+
trigger="click"
|
|
27
|
+
:disabled="disabled"
|
|
28
|
+
@command="dropdownHandler"
|
|
29
|
+
>
|
|
25
30
|
<span class="el-dropdown-link menubar-menu-button">
|
|
26
|
-
{{ data.text }}<
|
|
31
|
+
{{ data.text }}<TMagicIcon class="el-icon--right"><ArrowDown></ArrowDown></TMagicIcon>
|
|
27
32
|
</span>
|
|
28
33
|
<template #dropdown>
|
|
29
|
-
<
|
|
30
|
-
<
|
|
34
|
+
<TMagicDropdownMenu v-if="data.items && data.items.length">
|
|
35
|
+
<TMagicDropdownItem v-for="(subItem, index) in data.items" :key="index" :command="{ data, subItem }">{{
|
|
31
36
|
subItem.text
|
|
32
|
-
}}</
|
|
33
|
-
</
|
|
37
|
+
}}</TMagicDropdownItem>
|
|
38
|
+
</TMagicDropdownMenu>
|
|
34
39
|
</template>
|
|
35
|
-
</
|
|
40
|
+
</TMagicDropdown>
|
|
36
41
|
|
|
37
42
|
<component v-else-if="data.type === 'component'" v-bind="data.props || {}" :is="data.component"></component>
|
|
38
43
|
</div>
|
|
39
44
|
</template>
|
|
40
45
|
|
|
41
|
-
<script lang="ts" setup>
|
|
46
|
+
<script lang="ts" setup name="MEditorToolButton">
|
|
42
47
|
import { computed, inject } from 'vue';
|
|
43
48
|
import { ArrowDown } from '@element-plus/icons-vue';
|
|
44
49
|
|
|
50
|
+
import {
|
|
51
|
+
TMagicButton,
|
|
52
|
+
TMagicDivider,
|
|
53
|
+
TMagicDropdown,
|
|
54
|
+
TMagicDropdownItem,
|
|
55
|
+
TMagicDropdownMenu,
|
|
56
|
+
TMagicIcon,
|
|
57
|
+
TMagicTooltip,
|
|
58
|
+
} from '@tmagic/design';
|
|
59
|
+
|
|
45
60
|
import MIcon from '../components/Icon.vue';
|
|
46
61
|
import type { MenuButton, MenuComponent, Services } from '../type';
|
|
47
62
|
|
package/src/fields/Code.vue
CHANGED
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
:style="`height: ${height}`"
|
|
4
4
|
:init-values="model[name]"
|
|
5
5
|
:language="language"
|
|
6
|
+
:options="config.options"
|
|
6
7
|
@save="save"
|
|
7
8
|
></magic-code-editor>
|
|
8
9
|
</template>
|
|
9
10
|
|
|
10
|
-
<script lang="ts" setup>
|
|
11
|
+
<script lang="ts" setup name="MEditorCode">
|
|
11
12
|
import { computed } from 'vue';
|
|
12
13
|
|
|
13
14
|
const emit = defineEmits(['change']);
|
|
@@ -17,12 +18,14 @@ const props = defineProps<{
|
|
|
17
18
|
name: string;
|
|
18
19
|
config: {
|
|
19
20
|
language?: string;
|
|
21
|
+
options?: Object;
|
|
22
|
+
height?: string;
|
|
20
23
|
};
|
|
21
24
|
prop: string;
|
|
22
25
|
}>();
|
|
23
26
|
|
|
24
27
|
const language = computed(() => props.config.language || 'javascript');
|
|
25
|
-
const height = computed(() => `${document.body.clientHeight - 168}px`);
|
|
28
|
+
const height = computed(() => props.config.height || `${document.body.clientHeight - 168}px`);
|
|
26
29
|
|
|
27
30
|
const save = (v: string) => {
|
|
28
31
|
props.model[props.name] = v;
|
package/src/fields/CodeLink.vue
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<m-fields-link :config="formConfig" :model="modelValue" name="form" @change="changeHandler"></m-fields-link>
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
|
-
<script lang="ts" setup>
|
|
5
|
+
<script lang="ts" setup name="MEditorCodeLink">
|
|
6
6
|
import { computed, reactive, watch } from 'vue';
|
|
7
7
|
import serialize from 'serialize-javascript';
|
|
8
8
|
|
|
@@ -12,6 +12,7 @@ const props = defineProps<{
|
|
|
12
12
|
name: string;
|
|
13
13
|
text?: string;
|
|
14
14
|
formTitle?: string;
|
|
15
|
+
codeOptions?: Object;
|
|
15
16
|
};
|
|
16
17
|
model: any;
|
|
17
18
|
name: string;
|
|
@@ -20,17 +21,24 @@ const props = defineProps<{
|
|
|
20
21
|
|
|
21
22
|
const emit = defineEmits(['change']);
|
|
22
23
|
|
|
23
|
-
const formConfig = computed(() =>
|
|
24
|
-
...props.config
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
const formConfig = computed(() => {
|
|
25
|
+
const { codeOptions, ...config } = props.config;
|
|
26
|
+
return {
|
|
27
|
+
...config,
|
|
28
|
+
text: '',
|
|
29
|
+
type: 'link',
|
|
30
|
+
form: [
|
|
31
|
+
{
|
|
32
|
+
name: props.name,
|
|
33
|
+
type: 'vs-code',
|
|
34
|
+
options: {
|
|
35
|
+
tabSize: 2,
|
|
36
|
+
...(codeOptions || {}),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
});
|
|
34
42
|
|
|
35
43
|
const modelValue = reactive<{ form: Record<string, string> }>({
|
|
36
44
|
form: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-fields-code-select" :key="fieldKey">
|
|
3
|
-
<
|
|
3
|
+
<TMagicCard shadow="never">
|
|
4
4
|
<template #header>
|
|
5
5
|
<m-fields-select
|
|
6
6
|
:config="selectConfig"
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
></m-fields-select>
|
|
13
13
|
</template>
|
|
14
14
|
<div class="tool-bar">
|
|
15
|
-
<
|
|
15
|
+
<TMagicTooltip class="tool-item" effect="dark" content="查看代码块" placement="top">
|
|
16
16
|
<svg
|
|
17
17
|
@click="viewHandler"
|
|
18
18
|
preserveAspectRatio="xMidYMid meet"
|
|
@@ -26,23 +26,23 @@
|
|
|
26
26
|
d="m23 12l-7.071 7.071l-1.414-1.414L20.172 12l-5.657-5.657l1.414-1.414L23 12zM3.828 12l5.657 5.657l-1.414 1.414L1 12l7.071-7.071l1.414 1.414L3.828 12z"
|
|
27
27
|
></path>
|
|
28
28
|
</svg>
|
|
29
|
-
</
|
|
29
|
+
</TMagicTooltip>
|
|
30
30
|
</div>
|
|
31
|
-
</
|
|
31
|
+
</TMagicCard>
|
|
32
32
|
</div>
|
|
33
33
|
</template>
|
|
34
34
|
|
|
35
|
-
<script lang="ts" setup>
|
|
35
|
+
<script lang="ts" setup name="MEditorCodeSelect">
|
|
36
36
|
import { computed, defineEmits, defineProps, inject, ref, watchEffect } from 'vue';
|
|
37
|
-
import {
|
|
38
|
-
import { cloneDeep, map, xor } from 'lodash-es';
|
|
37
|
+
import { map, xor } from 'lodash-es';
|
|
39
38
|
|
|
40
|
-
import {
|
|
39
|
+
import { TMagicCard, tMagicMessage, TMagicTooltip } from '@tmagic/design';
|
|
40
|
+
import { FormState, SelectConfig } from '@tmagic/form';
|
|
41
41
|
|
|
42
42
|
import type { Services } from '../type';
|
|
43
43
|
import { CodeEditorMode, CodeSelectOp } from '../type';
|
|
44
44
|
const services = inject<Services>('services');
|
|
45
|
-
|
|
45
|
+
const form = inject<FormState>('mForm');
|
|
46
46
|
const emit = defineEmits(['change']);
|
|
47
47
|
|
|
48
48
|
const props = defineProps<{
|
|
@@ -77,12 +77,12 @@ const selectConfig = computed(() => {
|
|
|
77
77
|
});
|
|
78
78
|
const fieldKey = ref('');
|
|
79
79
|
const multiple = ref(true);
|
|
80
|
-
const
|
|
81
|
-
let lastTagSnapshot = cloneDeep(props.model[props.name]) || [];
|
|
80
|
+
const lastTagSnapshot = ref<string[]>([]);
|
|
82
81
|
|
|
83
82
|
watchEffect(async () => {
|
|
83
|
+
if (!props.model[props.name]) return;
|
|
84
84
|
const combineNames = await Promise.all(
|
|
85
|
-
|
|
85
|
+
props.model[props.name].map(async (id: string) => {
|
|
86
86
|
const { name = '' } = (await services?.codeBlockService.getCodeContentById(id)) || {};
|
|
87
87
|
return name;
|
|
88
88
|
}),
|
|
@@ -94,7 +94,6 @@ const changeHandler = async (value: any) => {
|
|
|
94
94
|
let codeIds = value;
|
|
95
95
|
if (typeof value === 'string') {
|
|
96
96
|
multiple.value = false;
|
|
97
|
-
lastTagSnapshot = [lastTagSnapshot];
|
|
98
97
|
codeIds = value ? [value] : [];
|
|
99
98
|
}
|
|
100
99
|
await setCombineRelation(codeIds);
|
|
@@ -110,30 +109,23 @@ const setCombineRelation = async (codeIds: string[]) => {
|
|
|
110
109
|
let opFlag = CodeSelectOp.CHANGE;
|
|
111
110
|
let diffValues = codeIds;
|
|
112
111
|
if (multiple.value) {
|
|
113
|
-
|
|
114
|
-
|
|
112
|
+
// initValues为表单初始值,当表单内容发生变化时,initValues也会更新,可以理解为上一次表单内容的快照
|
|
113
|
+
lastTagSnapshot.value = form?.initValues[props.name] || [];
|
|
114
|
+
opFlag = codeIds.length < lastTagSnapshot.value.length ? CodeSelectOp.DELETE : CodeSelectOp.ADD;
|
|
115
|
+
diffValues = xor(codeIds, lastTagSnapshot.value) as string[];
|
|
115
116
|
}
|
|
116
|
-
|
|
117
117
|
// 记录绑定关系
|
|
118
118
|
await services?.codeBlockService.setCombineRelation(id, diffValues, opFlag, props.prop);
|
|
119
|
-
lastTagSnapshot = codeIds;
|
|
120
|
-
await setCombineIds(codeIds);
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
// 记录当前已被绑定的代码块,为查看弹窗的展示内容
|
|
124
|
-
const setCombineIds = async (codeIds: string[]) => {
|
|
125
|
-
combineIds.value = codeIds;
|
|
126
|
-
await services?.codeBlockService.setCombineIds(codeIds);
|
|
127
119
|
};
|
|
128
120
|
|
|
129
121
|
const viewHandler = async () => {
|
|
130
122
|
if (props.model[props.name].length === 0) {
|
|
131
|
-
|
|
123
|
+
tMagicMessage.error('请先绑定代码块');
|
|
132
124
|
return;
|
|
133
125
|
}
|
|
134
126
|
// 记录当前已被绑定的代码块,为查看弹窗的展示内容
|
|
135
|
-
await setCombineIds(props.model[props.name]);
|
|
127
|
+
await services?.codeBlockService.setCombineIds(props.model[props.name]);
|
|
136
128
|
await services?.codeBlockService.setMode(CodeEditorMode.LIST);
|
|
137
|
-
services?.codeBlockService.setCodeEditorContent(true,
|
|
129
|
+
services?.codeBlockService.setCodeEditorContent(true, props.model[props.name][0]);
|
|
138
130
|
};
|
|
139
131
|
</script>
|
package/src/fields/UISelect.vue
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-fields-ui-select" v-if="uiSelectMode" @click="cancelHandler">
|
|
3
|
-
<
|
|
3
|
+
<TMagicButton type="danger" :icon="Delete" text style="padding: 0">取消</TMagicButton>
|
|
4
4
|
</div>
|
|
5
5
|
<div class="m-fields-ui-select" v-else @click="startSelect" style="display: flex">
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
</
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
</
|
|
6
|
+
<TMagicTooltip v-if="val" content="清除">
|
|
7
|
+
<TMagicButton style="padding: 0" type="danger" :icon="Close" text @click.stop="deleteHandler"></TMagicButton>
|
|
8
|
+
</TMagicTooltip>
|
|
9
|
+
<TMagicTooltip :content="val ? toName + '_' + val : '点击此处选择'">
|
|
10
|
+
<TMagicButton text style="padding: 0; margin: 0">{{ val ? toName + '_' + val : '点击此处选择' }}</TMagicButton>
|
|
11
|
+
</TMagicTooltip>
|
|
12
12
|
</div>
|
|
13
13
|
</template>
|
|
14
14
|
|
|
15
|
-
<script lang="ts" setup>
|
|
15
|
+
<script lang="ts" setup name="MEditorUISelect">
|
|
16
16
|
import { computed, inject, ref } from 'vue';
|
|
17
17
|
import { Close, Delete } from '@element-plus/icons-vue';
|
|
18
18
|
|
|
19
|
+
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
|
19
20
|
import { FormState } from '@tmagic/form';
|
|
20
21
|
|
|
21
22
|
import { Services } from '../type';
|
package/src/index.ts
CHANGED
|
@@ -42,11 +42,13 @@ export { default as uiService } from './services/ui';
|
|
|
42
42
|
export { default as codeBlockService } from './services/codeBlock';
|
|
43
43
|
export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPanel.vue';
|
|
44
44
|
export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
|
|
45
|
+
export { default as CodeSelect } from './fields/CodeSelect.vue';
|
|
45
46
|
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
|
46
47
|
export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
47
48
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
48
49
|
export { default as ContentMenu } from './components/ContentMenu.vue';
|
|
49
50
|
export { default as Icon } from './components/Icon.vue';
|
|
51
|
+
export { default as LayoutContainer } from './components/Layout.vue';
|
|
50
52
|
|
|
51
53
|
const defaultInstallOpt: InstallOptions = {
|
|
52
54
|
// @todo, 自定义图片上传方法等编辑器依赖的外部选项
|
|
@@ -63,7 +65,7 @@ export default {
|
|
|
63
65
|
app.component('m-fields-ui-select', uiSelect);
|
|
64
66
|
app.component('m-fields-code-link', CodeLink);
|
|
65
67
|
app.component('m-fields-vs-code', Code);
|
|
66
|
-
app.component(
|
|
68
|
+
app.component('magic-code-editor', CodeEditor);
|
|
67
69
|
app.component('m-fields-code-select', CodeSelect);
|
|
68
70
|
},
|
|
69
71
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="m-editor-empty-content">
|
|
4
4
|
<div class="m-editor-empty-button" @click="clickHandler">
|
|
5
5
|
<div>
|
|
6
|
-
<
|
|
6
|
+
<MIcon :icon="Plus"></MIcon>
|
|
7
7
|
</div>
|
|
8
8
|
<p>新增页面</p>
|
|
9
9
|
</div>
|
|
@@ -11,33 +11,26 @@
|
|
|
11
11
|
</div>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
|
-
<script lang="ts">
|
|
15
|
-
import {
|
|
14
|
+
<script lang="ts" setup name="MEditorAddPageBox">
|
|
15
|
+
import { inject, toRaw } from 'vue';
|
|
16
16
|
import { Plus } from '@element-plus/icons-vue';
|
|
17
17
|
|
|
18
18
|
import { NodeType } from '@tmagic/schema';
|
|
19
19
|
|
|
20
|
+
import MIcon from '../components/Icon.vue';
|
|
20
21
|
import type { Services } from '../type';
|
|
21
22
|
import { generatePageNameByApp } from '../utils';
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
components: { Plus },
|
|
24
|
+
const services = inject<Services>('services');
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
const clickHandler = () => {
|
|
27
|
+
const { editorService } = services || {};
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
clickHandler() {
|
|
31
|
-
const { editorService } = services || {};
|
|
29
|
+
if (!editorService) return;
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
},
|
|
42
|
-
});
|
|
31
|
+
editorService.add({
|
|
32
|
+
type: NodeType.PAGE,
|
|
33
|
+
name: generatePageNameByApp(toRaw(editorService.get('root'))),
|
|
34
|
+
});
|
|
35
|
+
};
|
|
43
36
|
</script>
|