@tmagic/editor 1.2.0-beta.9 → 1.2.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.
- package/dist/style.css +62 -34
- package/dist/{tmagic-editor.mjs → tmagic-editor.js} +1641 -1266
- package/dist/tmagic-editor.js.map +1 -0
- package/dist/{tmagic-editor.umd.js → tmagic-editor.umd.cjs} +1649 -1270
- package/dist/tmagic-editor.umd.cjs.map +1 -0
- package/package.json +16 -14
- package/src/Editor.vue +66 -40
- package/src/components/CodeDraftEditor.vue +137 -0
- package/src/components/ContentMenu.vue +1 -1
- package/src/components/FunctionEditor.vue +190 -0
- package/src/components/Icon.vue +1 -1
- package/src/{layouts → components}/Layout.vue +54 -15
- package/src/components/ScrollBar.vue +1 -1
- package/src/components/ScrollViewer.vue +10 -1
- package/src/components/ToolButton.vue +1 -1
- package/src/fields/Code.vue +1 -1
- package/src/fields/CodeLink.vue +1 -1
- package/src/fields/CodeSelect.vue +102 -99
- package/src/fields/UISelect.vue +3 -3
- package/src/index.ts +2 -1
- package/src/layouts/AddPageBox.vue +5 -2
- package/src/layouts/CodeEditor.vue +2 -3
- package/src/layouts/Framework.vue +12 -10
- package/src/layouts/NavMenu.vue +11 -8
- package/src/layouts/PropsPanel.vue +12 -9
- package/src/layouts/Resizer.vue +1 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +2 -3
- package/src/layouts/sidebar/LayerMenu.vue +9 -7
- package/src/layouts/sidebar/LayerPanel.vue +130 -178
- package/src/layouts/sidebar/Sidebar.vue +110 -26
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +33 -118
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +93 -126
- package/src/layouts/workspace/Breadcrumb.vue +6 -7
- package/src/layouts/workspace/PageBar.vue +3 -3
- package/src/layouts/workspace/PageBarScrollContainer.vue +5 -3
- package/src/layouts/workspace/Stage.vue +36 -18
- package/src/layouts/workspace/ViewerMenu.vue +16 -15
- package/src/layouts/workspace/Workspace.vue +9 -6
- package/src/services/BaseService.ts +11 -2
- package/src/services/codeBlock.ts +136 -146
- package/src/services/componentList.ts +7 -2
- package/src/services/editor.ts +161 -85
- package/src/services/events.ts +7 -2
- package/src/services/history.ts +8 -17
- package/src/services/props.ts +8 -3
- package/src/services/storage.ts +1 -0
- package/src/services/ui.ts +20 -10
- package/src/theme/code-block.scss +46 -23
- package/src/theme/component-list-panel.scss +8 -5
- package/src/type.ts +84 -63
- package/src/utils/config.ts +1 -1
- package/src/utils/editor.ts +17 -3
- package/src/utils/index.ts +2 -1
- package/src/utils/logger.ts +1 -1
- package/src/utils/operator.ts +12 -12
- package/src/utils/props.ts +3 -3
- package/src/utils/scroll-viewer.ts +18 -2
- package/src/utils/stage.ts +10 -9
- package/src/utils/undo-redo.ts +1 -1
- package/types/Editor.vue.d.ts +48 -28
- package/types/components/CodeDraftEditor.vue.d.ts +55 -0
- package/types/components/ContentMenu.vue.d.ts +11 -87
- package/types/components/FunctionEditor.vue.d.ts +60 -0
- package/types/components/Icon.vue.d.ts +4 -50
- package/types/{layouts → components}/Layout.vue.d.ts +12 -1
- package/types/components/ScrollBar.vue.d.ts +7 -65
- package/types/components/ScrollViewer.vue.d.ts +45 -1
- package/types/components/ToolButton.vue.d.ts +12 -78
- package/types/fields/Code.vue.d.ts +11 -77
- package/types/fields/CodeLink.vue.d.ts +12 -82
- package/types/fields/CodeSelect.vue.d.ts +13 -77
- package/types/fields/UISelect.vue.d.ts +7 -65
- package/types/index.d.ts +1 -0
- package/types/layouts/AddPageBox.vue.d.ts +1 -43
- package/types/layouts/CodeEditor.vue.d.ts +22 -130
- package/types/layouts/NavMenu.vue.d.ts +9 -69
- package/types/layouts/sidebar/LayerMenu.vue.d.ts +16 -48
- package/types/layouts/sidebar/LayerPanel.vue.d.ts +24 -7
- package/types/layouts/sidebar/Sidebar.vue.d.ts +10 -5
- package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +24 -6
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +11 -5
- package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -43
- package/types/layouts/workspace/Stage.vue.d.ts +15 -43
- package/types/layouts/workspace/ViewerMenu.vue.d.ts +11 -66
- package/types/layouts/workspace/Workspace.vue.d.ts +25 -8
- package/types/services/BaseService.d.ts +2 -1
- package/types/services/codeBlock.d.ts +56 -47
- package/types/services/componentList.d.ts +1 -0
- package/types/services/editor.d.ts +10 -11
- package/types/services/events.d.ts +1 -0
- package/types/services/history.d.ts +5 -15
- package/types/services/props.d.ts +3 -2
- package/types/services/ui.d.ts +24 -24
- package/types/type.d.ts +70 -59
- package/types/utils/editor.d.ts +1 -0
- package/types/utils/index.d.ts +1 -0
- package/types/utils/operator.d.ts +1 -1
- package/types/utils/props.d.ts +1 -1
- package/types/utils/scroll-viewer.d.ts +5 -0
- package/dist/tmagic-editor.mjs.map +0 -1
- package/dist/tmagic-editor.umd.js.map +0 -1
- package/src/layouts/sidebar/TabPane.vue +0 -118
- package/types/layouts/sidebar/TabPane.vue.d.ts +0 -82
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="el" class="m-editor-layout">
|
|
3
|
-
<template v-if="
|
|
3
|
+
<template v-if="hasLeft">
|
|
4
4
|
<div class="m-editor-layout-left" :class="leftClass" :style="`width: ${left}px`">
|
|
5
5
|
<slot name="left"></slot>
|
|
6
6
|
</div>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<slot name="center"></slot>
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
|
-
<template v-if="
|
|
14
|
+
<template v-if="hasRight">
|
|
15
15
|
<Resizer @change="changeRight"></Resizer>
|
|
16
16
|
<div class="m-editor-layout-right" :class="rightClass" :style="`width: ${right}px`">
|
|
17
17
|
<slot name="right"></slot>
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
</template>
|
|
22
22
|
|
|
23
|
-
<script lang="ts" setup>
|
|
24
|
-
import { onMounted, onUnmounted, ref } from 'vue';
|
|
23
|
+
<script lang="ts" setup name="MEditorLayout">
|
|
24
|
+
import { computed, 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
|
|
|
@@ -33,29 +33,64 @@ const props = withDefaults(
|
|
|
33
33
|
right?: number;
|
|
34
34
|
minLeft?: number;
|
|
35
35
|
minRight?: number;
|
|
36
|
+
minCenter?: number;
|
|
36
37
|
leftClass?: string;
|
|
37
38
|
rightClass?: string;
|
|
38
39
|
centerClass?: string;
|
|
39
40
|
}>(),
|
|
40
41
|
{
|
|
41
|
-
minLeft:
|
|
42
|
+
minLeft: 46,
|
|
42
43
|
minRight: 1,
|
|
44
|
+
minCenter: 5,
|
|
43
45
|
},
|
|
44
46
|
);
|
|
45
47
|
|
|
46
48
|
const el = ref<HTMLElement>();
|
|
47
49
|
|
|
50
|
+
const hasLeft = computed(() => typeof props.left !== 'undefined');
|
|
51
|
+
const hasRight = computed(() => typeof props.right !== 'undefined');
|
|
52
|
+
|
|
53
|
+
const getCenterWidth = (clientWidth: number, left: number, right: number) => {
|
|
54
|
+
let center = clientWidth - left - right;
|
|
55
|
+
if (center < props.minCenter) {
|
|
56
|
+
center = props.minCenter;
|
|
57
|
+
if (left < right) {
|
|
58
|
+
right = clientWidth - left - props.minCenter;
|
|
59
|
+
} else {
|
|
60
|
+
left = clientWidth - right - props.minCenter;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
center,
|
|
65
|
+
left,
|
|
66
|
+
right,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
48
70
|
let clientWidth = 0;
|
|
49
71
|
const resizerObserver = new ResizeObserver((entries) => {
|
|
50
72
|
for (const { contentRect } of entries) {
|
|
51
73
|
clientWidth = contentRect.width;
|
|
52
74
|
|
|
53
|
-
|
|
75
|
+
let left = props.left || 0;
|
|
76
|
+
let right = props.right || 0;
|
|
77
|
+
|
|
78
|
+
if (left > clientWidth) {
|
|
79
|
+
left = clientWidth / 3;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (right > clientWidth) {
|
|
83
|
+
right = clientWidth / 3;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const columnWidth = getCenterWidth(clientWidth, left, right);
|
|
87
|
+
|
|
88
|
+
center.value = columnWidth.center;
|
|
54
89
|
|
|
55
90
|
emit('change', {
|
|
56
|
-
left:
|
|
91
|
+
left: columnWidth.left,
|
|
57
92
|
center: center.value,
|
|
58
|
-
right:
|
|
93
|
+
right: columnWidth.right,
|
|
59
94
|
});
|
|
60
95
|
}
|
|
61
96
|
});
|
|
@@ -81,12 +116,14 @@ const changeLeft = (deltaX: number) => {
|
|
|
81
116
|
left = props.left;
|
|
82
117
|
}
|
|
83
118
|
|
|
84
|
-
|
|
119
|
+
const columnWidth = getCenterWidth(clientWidth, left, props.right || 0);
|
|
120
|
+
|
|
121
|
+
center.value = columnWidth.center;
|
|
85
122
|
|
|
86
123
|
emit('change', {
|
|
87
|
-
left,
|
|
124
|
+
left: columnWidth.left,
|
|
88
125
|
center: center.value,
|
|
89
|
-
right:
|
|
126
|
+
right: columnWidth.right,
|
|
90
127
|
});
|
|
91
128
|
};
|
|
92
129
|
|
|
@@ -99,12 +136,14 @@ const changeRight = (deltaX: number) => {
|
|
|
99
136
|
right = props.right;
|
|
100
137
|
}
|
|
101
138
|
|
|
102
|
-
|
|
139
|
+
const columnWidth = getCenterWidth(clientWidth, props.left || 0, right);
|
|
140
|
+
|
|
141
|
+
center.value = columnWidth.center;
|
|
103
142
|
|
|
104
143
|
emit('change', {
|
|
105
|
-
left:
|
|
144
|
+
left: columnWidth.left,
|
|
106
145
|
center: center.value,
|
|
107
|
-
right,
|
|
146
|
+
right: columnWidth.right,
|
|
108
147
|
});
|
|
109
148
|
};
|
|
110
149
|
</script>
|
|
@@ -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) => {
|
package/src/fields/Code.vue
CHANGED
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
|
|
|
@@ -1,131 +1,134 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-fields-code-select"
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
<div class="m-fields-code-select">
|
|
3
|
+
<m-form-table
|
|
4
|
+
:config="tableConfig"
|
|
5
|
+
:model="model[name]"
|
|
6
|
+
name="hookData"
|
|
7
|
+
:enableToggleMode="false"
|
|
8
|
+
:prop="prop"
|
|
9
|
+
:size="size"
|
|
10
|
+
@change="changeHandler"
|
|
11
|
+
>
|
|
12
|
+
<template #operateCol="{ scope }">
|
|
13
|
+
<Icon
|
|
14
|
+
v-if="scope.row.codeId"
|
|
15
|
+
:icon="editable ? Edit : View"
|
|
16
|
+
class="edit-icon"
|
|
17
|
+
@click="editCode(scope.row.codeId)"
|
|
18
|
+
></Icon>
|
|
13
19
|
</template>
|
|
14
|
-
|
|
15
|
-
<TMagicTooltip class="tool-item" effect="dark" content="查看代码块" placement="top">
|
|
16
|
-
<svg
|
|
17
|
-
@click="viewHandler"
|
|
18
|
-
preserveAspectRatio="xMidYMid meet"
|
|
19
|
-
viewBox="0 0 24 24"
|
|
20
|
-
width="15px"
|
|
21
|
-
height="15px"
|
|
22
|
-
data-v-65a7fb6c=""
|
|
23
|
-
>
|
|
24
|
-
<path
|
|
25
|
-
fill="currentColor"
|
|
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
|
-
></path>
|
|
28
|
-
</svg>
|
|
29
|
-
</TMagicTooltip>
|
|
30
|
-
</div>
|
|
31
|
-
</TMagicCard>
|
|
20
|
+
</m-form-table>
|
|
32
21
|
</div>
|
|
33
22
|
</template>
|
|
34
23
|
|
|
35
|
-
<script lang="ts" setup>
|
|
36
|
-
import { computed, defineEmits, defineProps, inject,
|
|
37
|
-
import {
|
|
24
|
+
<script lang="ts" setup name="MEditorCodeSelect">
|
|
25
|
+
import { computed, defineEmits, defineProps, inject, watch } from 'vue';
|
|
26
|
+
import { Edit, View } from '@element-plus/icons-vue';
|
|
27
|
+
import { isEmpty, map } from 'lodash-es';
|
|
38
28
|
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
29
|
+
import { createValues, FormItem, FormState, TableConfig } from '@tmagic/form';
|
|
30
|
+
import { HookType, Id } from '@tmagic/schema';
|
|
41
31
|
|
|
42
|
-
import
|
|
43
|
-
import {
|
|
32
|
+
import Icon from '../components/Icon.vue';
|
|
33
|
+
import { CodeParamStatement, HookData, Services } from '../type';
|
|
44
34
|
const services = inject<Services>('services');
|
|
45
|
-
const
|
|
35
|
+
const mForm = inject<FormState>('mForm');
|
|
46
36
|
const emit = defineEmits(['change']);
|
|
47
37
|
|
|
48
38
|
const props = defineProps<{
|
|
49
39
|
config: {
|
|
50
|
-
|
|
40
|
+
tableConfig?: TableConfig;
|
|
51
41
|
};
|
|
52
42
|
model: any;
|
|
53
43
|
prop: string;
|
|
54
44
|
name: string;
|
|
55
|
-
size:
|
|
45
|
+
size: 'mini' | 'small' | 'medium';
|
|
56
46
|
}>();
|
|
47
|
+
const codeDsl = computed(() => services?.codeBlockService.getCodeDslSync());
|
|
57
48
|
|
|
58
|
-
const
|
|
49
|
+
const tableConfig = computed<FormItem>(() => {
|
|
59
50
|
const defaultConfig = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
51
|
+
dropSort: false,
|
|
52
|
+
enableFullscreen: false,
|
|
53
|
+
border: true,
|
|
54
|
+
operateColWidth: 60,
|
|
55
|
+
items: [
|
|
56
|
+
{
|
|
57
|
+
type: 'select',
|
|
58
|
+
label: '代码块',
|
|
59
|
+
name: 'codeId',
|
|
60
|
+
width: '200px',
|
|
61
|
+
options: () => {
|
|
62
|
+
if (codeDsl.value) {
|
|
63
|
+
return map(codeDsl.value, (value, key) => ({
|
|
64
|
+
text: `${value.name}(${key})`,
|
|
65
|
+
label: `${value.name}(${key})`,
|
|
66
|
+
value: key,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
return [];
|
|
70
|
+
},
|
|
71
|
+
onChange: (formState: any, codeId: Id, { model }: any) => {
|
|
72
|
+
// 参数的items是根据函数生成的,当codeId变化后修正model的值,避免写入其他codeId的params
|
|
73
|
+
model.params = {};
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'params',
|
|
78
|
+
label: '参数',
|
|
79
|
+
defaultValue: {},
|
|
80
|
+
itemsFunction: (row: HookData) => {
|
|
81
|
+
const paramsConfig = getParamsConfig(row.codeId);
|
|
82
|
+
// 如果参数没有填值,则使用createValues补全空值
|
|
83
|
+
if (isEmpty(row.params) || !row.params) {
|
|
84
|
+
createValues(mForm, paramsConfig, {}, row.params);
|
|
85
|
+
}
|
|
86
|
+
return paramsConfig;
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
],
|
|
72
90
|
};
|
|
73
91
|
return {
|
|
74
92
|
...defaultConfig,
|
|
75
|
-
...props.config.
|
|
93
|
+
...props.config.tableConfig,
|
|
76
94
|
};
|
|
77
95
|
});
|
|
78
|
-
const fieldKey = ref('');
|
|
79
|
-
const multiple = ref(true);
|
|
80
|
-
const lastTagSnapshot = ref<string[]>([]);
|
|
81
96
|
|
|
82
|
-
|
|
83
|
-
if (!props.model[props.name]) return;
|
|
84
|
-
const combineNames = await Promise.all(
|
|
85
|
-
props.model[props.name].map(async (id: string) => {
|
|
86
|
-
const { name = '' } = (await services?.codeBlockService.getCodeContentById(id)) || {};
|
|
87
|
-
return name;
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
fieldKey.value = combineNames.join('-');
|
|
91
|
-
});
|
|
97
|
+
const editable = computed(() => services?.codeBlockService.getEditStatus());
|
|
92
98
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
watch(
|
|
100
|
+
() => props.model[props.name],
|
|
101
|
+
(value) => {
|
|
102
|
+
// 兼容旧的数据结构
|
|
103
|
+
if (isEmpty(value)) {
|
|
104
|
+
// 空值或者空数组
|
|
105
|
+
props.model[props.name] = {
|
|
106
|
+
hookType: HookType.CODE,
|
|
107
|
+
hookData: [],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
immediate: true,
|
|
113
|
+
},
|
|
114
|
+
);
|
|
102
115
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const { id = '' } = services?.editorService.get('node') || {};
|
|
116
|
+
const changeHandler = async () => {
|
|
117
|
+
emit('change', props.model[props.name]);
|
|
118
|
+
};
|
|
107
119
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
// 记录绑定关系
|
|
118
|
-
await services?.codeBlockService.setCombineRelation(id, diffValues, opFlag, props.prop);
|
|
120
|
+
const getParamsConfig = (codeId: Id): CodeParamStatement[] => {
|
|
121
|
+
if (!codeDsl.value) return [];
|
|
122
|
+
const paramStatements = codeDsl.value[codeId]?.params;
|
|
123
|
+
if (isEmpty(paramStatements)) return [];
|
|
124
|
+
return paramStatements.map((paramState: CodeParamStatement) => ({
|
|
125
|
+
labelWidth: '100px',
|
|
126
|
+
text: paramState.name,
|
|
127
|
+
...paramState,
|
|
128
|
+
}));
|
|
119
129
|
};
|
|
120
130
|
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
tMagicMessage.error('请先绑定代码块');
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
// 记录当前已被绑定的代码块,为查看弹窗的展示内容
|
|
127
|
-
await services?.codeBlockService.setCombineIds(props.model[props.name]);
|
|
128
|
-
await services?.codeBlockService.setMode(CodeEditorMode.LIST);
|
|
129
|
-
services?.codeBlockService.setCodeEditorContent(true, props.model[props.name][0]);
|
|
131
|
+
const editCode = (codeId: Id) => {
|
|
132
|
+
services?.codeBlockService.setCodeEditorContent(true, codeId);
|
|
130
133
|
};
|
|
131
134
|
</script>
|
package/src/fields/UISelect.vue
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
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
|
|
|
@@ -37,7 +37,7 @@ const uiSelectMode = ref(false);
|
|
|
37
37
|
|
|
38
38
|
const cancelHandler = () => {
|
|
39
39
|
if (!services?.uiService) return;
|
|
40
|
-
services.uiService.set
|
|
40
|
+
services.uiService.set('uiSelectMode', false);
|
|
41
41
|
uiSelectMode.value = false;
|
|
42
42
|
globalThis.document.removeEventListener('ui-select', clickHandler as EventListener);
|
|
43
43
|
};
|
|
@@ -61,7 +61,7 @@ const toName = computed(() => {
|
|
|
61
61
|
|
|
62
62
|
const startSelect = () => {
|
|
63
63
|
if (!services?.uiService) return;
|
|
64
|
-
services.uiService.set
|
|
64
|
+
services.uiService.set('uiSelectMode', true);
|
|
65
65
|
uiSelectMode.value = true;
|
|
66
66
|
globalThis.document.addEventListener('ui-select', clickHandler as EventListener);
|
|
67
67
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
3
|
*
|
|
4
|
-
* Copyright (C)
|
|
4
|
+
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
5
|
*
|
|
6
6
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
7
|
* you may not use this file except in compliance with the License.
|
|
@@ -48,6 +48,7 @@ export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
|
48
48
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
49
49
|
export { default as ContentMenu } from './components/ContentMenu.vue';
|
|
50
50
|
export { default as Icon } from './components/Icon.vue';
|
|
51
|
+
export { default as LayoutContainer } from './components/Layout.vue';
|
|
51
52
|
|
|
52
53
|
const defaultInstallOpt: InstallOptions = {
|
|
53
54
|
// @todo, 自定义图片上传方法等编辑器依赖的外部选项
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</div>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
|
-
<script lang="ts" setup>
|
|
14
|
+
<script lang="ts" setup name="MEditorAddPageBox">
|
|
15
15
|
import { inject, toRaw } from 'vue';
|
|
16
16
|
import { Plus } from '@element-plus/icons-vue';
|
|
17
17
|
|
|
@@ -28,9 +28,12 @@ const clickHandler = () => {
|
|
|
28
28
|
|
|
29
29
|
if (!editorService) return;
|
|
30
30
|
|
|
31
|
+
const root = toRaw(editorService.get('root'));
|
|
32
|
+
if (!root) throw new Error('root 不能为空');
|
|
33
|
+
|
|
31
34
|
editorService.add({
|
|
32
35
|
type: NodeType.PAGE,
|
|
33
|
-
name: generatePageNameByApp(
|
|
36
|
+
name: generatePageNameByApp(root),
|
|
34
37
|
});
|
|
35
38
|
};
|
|
36
39
|
</script>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div ref="codeEditor" class="magic-code-editor"></div>
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
|
-
<script lang="ts" setup>
|
|
5
|
+
<script lang="ts" setup name="MEditorCodeEditor">
|
|
6
6
|
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
|
7
7
|
import { throttle } from 'lodash-es';
|
|
8
8
|
import * as monaco from 'monaco-editor';
|
|
@@ -12,7 +12,7 @@ const props = withDefaults(
|
|
|
12
12
|
defineProps<{
|
|
13
13
|
initValues?: string | Object;
|
|
14
14
|
modifiedValues?: string | Object;
|
|
15
|
-
type?:
|
|
15
|
+
type?: 'diff';
|
|
16
16
|
language?: string;
|
|
17
17
|
options?: {
|
|
18
18
|
[key: string]: any;
|
|
@@ -20,7 +20,6 @@ const props = withDefaults(
|
|
|
20
20
|
autoSave?: boolean;
|
|
21
21
|
}>(),
|
|
22
22
|
{
|
|
23
|
-
type: '',
|
|
24
23
|
autoSave: true,
|
|
25
24
|
language: 'javascript',
|
|
26
25
|
options: () => ({
|
|
@@ -42,16 +42,15 @@
|
|
|
42
42
|
</div>
|
|
43
43
|
</template>
|
|
44
44
|
|
|
45
|
-
<script lang="ts" setup>
|
|
45
|
+
<script lang="ts" setup name="MEditorFramework">
|
|
46
46
|
import { computed, inject, ref, watch } from 'vue';
|
|
47
47
|
|
|
48
48
|
import { TMagicScrollbar } from '@tmagic/design';
|
|
49
|
-
import type { MApp } from '@tmagic/schema';
|
|
50
49
|
|
|
50
|
+
import Layout from '../components/Layout.vue';
|
|
51
51
|
import { GetColumnWidth, Services } from '../type';
|
|
52
52
|
|
|
53
53
|
import AddPageBox from './AddPageBox.vue';
|
|
54
|
-
import Layout from './Layout.vue';
|
|
55
54
|
|
|
56
55
|
const DEFAULT_LEFT_COLUMN_WIDTH = 310;
|
|
57
56
|
const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
@@ -67,11 +66,11 @@ withDefaults(
|
|
|
67
66
|
|
|
68
67
|
const { editorService, uiService } = inject<Services>('services') || {};
|
|
69
68
|
|
|
70
|
-
const root = computed(() => editorService?.get
|
|
71
|
-
const nodes = computed(() => editorService?.get
|
|
69
|
+
const root = computed(() => editorService?.get('root'));
|
|
70
|
+
const nodes = computed(() => editorService?.get('nodes') || []);
|
|
72
71
|
|
|
73
|
-
const pageLength = computed(() => editorService?.get
|
|
74
|
-
const showSrc = computed(() => uiService?.get
|
|
72
|
+
const pageLength = computed(() => editorService?.get('pageLength') || 0);
|
|
73
|
+
const showSrc = computed(() => uiService?.get('showSrc'));
|
|
75
74
|
|
|
76
75
|
const LEFT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorLeftColumnWidthData';
|
|
77
76
|
const RIGHT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorRightColumnWidthData';
|
|
@@ -101,7 +100,7 @@ watch(
|
|
|
101
100
|
columnWidth.value.center = globalThis.document.body.clientWidth - left - right;
|
|
102
101
|
}
|
|
103
102
|
|
|
104
|
-
uiService?.set('columnWidth', columnWidth);
|
|
103
|
+
uiService?.set('columnWidth', columnWidth.value as GetColumnWidth);
|
|
105
104
|
},
|
|
106
105
|
{
|
|
107
106
|
immediate: true,
|
|
@@ -123,8 +122,11 @@ watch(
|
|
|
123
122
|
},
|
|
124
123
|
);
|
|
125
124
|
|
|
126
|
-
const columnWidthChange = (
|
|
127
|
-
|
|
125
|
+
const columnWidthChange = (columnW: GetColumnWidth) => {
|
|
126
|
+
columnWidth.value.left = columnW.left;
|
|
127
|
+
columnWidth.value.center = columnW.center;
|
|
128
|
+
columnWidth.value.right = columnW.right;
|
|
129
|
+
uiService?.set('columnWidth', columnW);
|
|
128
130
|
};
|
|
129
131
|
|
|
130
132
|
const saveCode = (value: string) => {
|
package/src/layouts/NavMenu.vue
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-nav-menu" :style="{ height: `${height}px` }">
|
|
3
3
|
<div v-for="key in keys" :class="`menu-${key}`" :key="key" :style="`width: ${columnWidth?.[key]}px`">
|
|
4
|
-
<
|
|
4
|
+
<ToolButton :data="item" v-for="(item, index) in buttons[key]" :key="index"></ToolButton>
|
|
5
5
|
</div>
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
8
8
|
|
|
9
|
-
<script lang="ts" setup>
|
|
9
|
+
<script lang="ts" setup name="MEditorNavMenu">
|
|
10
10
|
import { computed, inject, markRaw } from 'vue';
|
|
11
11
|
import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
|
|
12
12
|
|
|
13
13
|
import { NodeType } from '@tmagic/schema';
|
|
14
14
|
|
|
15
15
|
import ToolButton from '../components/ToolButton.vue';
|
|
16
|
-
import { ColumnLayout,
|
|
16
|
+
import { ColumnLayout, MenuBarData, MenuButton, MenuComponent, MenuItem, Services } from '../type';
|
|
17
17
|
|
|
18
18
|
const props = withDefaults(
|
|
19
19
|
defineProps<{
|
|
@@ -29,12 +29,12 @@ const props = withDefaults(
|
|
|
29
29
|
const services = inject<Services>('services');
|
|
30
30
|
const uiService = services?.uiService;
|
|
31
31
|
|
|
32
|
-
const columnWidth = computed(() => services?.uiService.get
|
|
32
|
+
const columnWidth = computed(() => services?.uiService.get('columnWidth'));
|
|
33
33
|
const keys = Object.values(ColumnLayout);
|
|
34
34
|
|
|
35
|
-
const showGuides = computed((): boolean => uiService?.get
|
|
36
|
-
const showRule = computed((): boolean => uiService?.get
|
|
37
|
-
const zoom = computed((): number => uiService?.get
|
|
35
|
+
const showGuides = computed((): boolean => uiService?.get('showGuides') ?? true);
|
|
36
|
+
const showRule = computed((): boolean => uiService?.get('showRule') ?? true);
|
|
37
|
+
const zoom = computed((): number => uiService?.get('zoom') ?? 1);
|
|
38
38
|
|
|
39
39
|
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
|
40
40
|
const ctrl = isMac ? 'Command' : 'Ctrl';
|
|
@@ -67,7 +67,10 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
|
|
|
67
67
|
icon: markRaw(Delete),
|
|
68
68
|
tooltip: `刪除(Delete)`,
|
|
69
69
|
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
|
|
70
|
-
handler: () =>
|
|
70
|
+
handler: () => {
|
|
71
|
+
const node = services?.editorService.get('node');
|
|
72
|
+
node && services?.editorService.remove(node);
|
|
73
|
+
},
|
|
71
74
|
});
|
|
72
75
|
break;
|
|
73
76
|
case 'undo':
|