@tmagic/editor 1.2.14 → 1.3.0-alpha.0
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 +173 -80
- package/dist/tmagic-editor.js +975 -222
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +984 -230
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +10 -9
- package/src/Editor.vue +2 -0
- package/src/components/CodeDraftEditor.vue +2 -2
- package/src/components/SearchInput.vue +6 -3
- package/src/editorProps.ts +5 -0
- package/src/fields/CodeSelect.vue +1 -0
- package/src/fields/DataSourceFields.vue +178 -0
- package/src/fields/EventSelect.vue +1 -0
- package/src/fields/KeyValue.vue +93 -0
- package/src/icons/AppManageIcon.vue +1 -1
- package/src/icons/CodeIcon.vue +1 -10
- package/src/index.ts +6 -0
- package/src/initService.ts +59 -3
- package/src/layouts/sidebar/LayerPanel.vue +2 -0
- package/src/layouts/sidebar/Sidebar.vue +24 -14
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +11 -4
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +84 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +130 -0
- package/src/services/codeBlock.ts +0 -2
- package/src/services/dataSource.ts +90 -0
- package/src/services/props.ts +2 -15
- package/src/theme/code-block.scss +4 -66
- package/src/theme/data-source-fields.scss +13 -0
- package/src/theme/data-source.scss +17 -0
- package/src/theme/dep-list.scss +59 -0
- package/src/theme/key-value.scss +13 -0
- package/src/theme/sidebar.scss +26 -6
- package/src/theme/theme.scss +4 -0
- package/src/type.ts +3 -1
- package/src/utils/data-source/formConfigs/base.ts +32 -0
- package/src/utils/data-source/formConfigs/http.ts +50 -0
- package/src/utils/data-source/index.ts +31 -0
- package/src/utils/dep.ts +9 -1
- package/src/utils/props.ts +1 -0
- package/types/Editor.vue.d.ts +9 -0
- package/types/components/ContentMenu.vue.d.ts +2 -2
- package/types/components/ScrollViewer.vue.d.ts +1 -1
- package/types/editorProps.d.ts +4 -0
- package/types/fields/DataSourceFields.vue.d.ts +40 -0
- package/types/fields/KeyValue.vue.d.ts +50 -0
- package/types/index.d.ts +2 -0
- package/types/initService.d.ts +1 -1
- package/types/layouts/CodeEditor.vue.d.ts +1 -1
- package/types/layouts/sidebar/Sidebar.vue.d.ts +2 -2
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +22 -0
- package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +12 -0
- package/types/services/dataSource.d.ts +25 -0
- package/types/services/props.d.ts +17 -12
- package/types/type.d.ts +3 -1
- package/types/utils/data-source/formConfigs/base.d.ts +3 -0
- package/types/utils/data-source/formConfigs/http.d.ts +3 -0
- package/types/utils/data-source/index.d.ts +2 -0
- package/types/utils/dep.d.ts +2 -1
- package/types/utils/props.d.ts +2 -3
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.3.0-alpha.0",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -46,12 +46,13 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@babel/core": "^7.18.0",
|
|
48
48
|
"@element-plus/icons-vue": "^2.0.9",
|
|
49
|
-
"@tmagic/core": "1.
|
|
50
|
-
"@tmagic/design": "1.
|
|
51
|
-
"@tmagic/form": "1.
|
|
52
|
-
"@tmagic/schema": "1.
|
|
53
|
-
"@tmagic/stage": "1.
|
|
54
|
-
"@tmagic/
|
|
49
|
+
"@tmagic/core": "1.3.0-alpha.0",
|
|
50
|
+
"@tmagic/design": "1.3.0-alpha.0",
|
|
51
|
+
"@tmagic/form": "1.3.0-alpha.0",
|
|
52
|
+
"@tmagic/schema": "1.3.0-alpha.0",
|
|
53
|
+
"@tmagic/stage": "1.3.0-alpha.0",
|
|
54
|
+
"@tmagic/table": "1.3.0-alpha.0",
|
|
55
|
+
"@tmagic/utils": "1.3.0-alpha.0",
|
|
55
56
|
"buffer": "^6.0.3",
|
|
56
57
|
"color": "^3.1.3",
|
|
57
58
|
"events": "^3.3.0",
|
|
@@ -63,8 +64,8 @@
|
|
|
63
64
|
"vue": "^3.2.37"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
|
-
"@tmagic/design": "1.
|
|
67
|
-
"@tmagic/form": "1.
|
|
67
|
+
"@tmagic/design": "1.3.0-alpha.0",
|
|
68
|
+
"@tmagic/form": "1.3.0-alpha.0",
|
|
68
69
|
"monaco-editor": "^0.34.0",
|
|
69
70
|
"vue": "^3.2.37"
|
|
70
71
|
},
|
package/src/Editor.vue
CHANGED
|
@@ -73,6 +73,7 @@ import Sidebar from './layouts/sidebar/Sidebar.vue';
|
|
|
73
73
|
import Workspace from './layouts/workspace/Workspace.vue';
|
|
74
74
|
import codeBlockService from './services/codeBlock';
|
|
75
75
|
import componentListService from './services/componentList';
|
|
76
|
+
import dataSourceService from './services/dataSource';
|
|
76
77
|
import depService from './services/dep';
|
|
77
78
|
import editorService from './services/editor';
|
|
78
79
|
import eventsService from './services/events';
|
|
@@ -110,6 +111,7 @@ export default defineComponent({
|
|
|
110
111
|
storageService,
|
|
111
112
|
codeBlockService,
|
|
112
113
|
depService,
|
|
114
|
+
dataSourceService,
|
|
113
115
|
};
|
|
114
116
|
|
|
115
117
|
initServiceEvents(props, emit, services);
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
{{ isFullScreen ? '退出全屏' : '全屏' }}</TMagicButton
|
|
14
14
|
>
|
|
15
15
|
<TMagicButton type="primary" class="button" @click="saveAndClose">确认</TMagicButton>
|
|
16
|
-
<TMagicButton
|
|
16
|
+
<TMagicButton class="button" @click="close">关闭</TMagicButton>
|
|
17
17
|
</div>
|
|
18
18
|
<div class="m-editor-content-bottom" v-else>
|
|
19
19
|
<TMagicButton type="primary" class="button" @click="toggleFullScreen">
|
|
20
20
|
{{ isFullScreen ? '退出全屏' : '全屏' }}</TMagicButton
|
|
21
21
|
>
|
|
22
|
-
<TMagicButton
|
|
22
|
+
<TMagicButton class="button" @click="close">关闭</TMagicButton>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
</template>
|
|
@@ -5,16 +5,19 @@
|
|
|
5
5
|
size="small"
|
|
6
6
|
placeholder="输入关键字进行过滤"
|
|
7
7
|
clearable
|
|
8
|
-
:prefix-icon="Search"
|
|
9
8
|
@input="filterTextChangeHandler"
|
|
10
|
-
|
|
9
|
+
>
|
|
10
|
+
<template #prefix>
|
|
11
|
+
<TMagicIcon><Search /></TMagicIcon>
|
|
12
|
+
</template>
|
|
13
|
+
</TMagicInput>
|
|
11
14
|
</template>
|
|
12
15
|
|
|
13
16
|
<script setup lang="ts">
|
|
14
17
|
import { ref } from 'vue';
|
|
15
18
|
import { Search } from '@element-plus/icons-vue';
|
|
16
19
|
|
|
17
|
-
import { TMagicInput } from '@tmagic/design';
|
|
20
|
+
import { TMagicIcon, TMagicInput } from '@tmagic/design';
|
|
18
21
|
|
|
19
22
|
const emit = defineEmits(['search']);
|
|
20
23
|
|
package/src/editorProps.ts
CHANGED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-editor-data-source-fields">
|
|
3
|
+
<MagicTable :data="model[name]" :columns="filedColumns"></MagicTable>
|
|
4
|
+
|
|
5
|
+
<div class="m-editor-data-source-fields-footer">
|
|
6
|
+
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<MFormDialog
|
|
10
|
+
ref="addDialog"
|
|
11
|
+
:title="filedTitle"
|
|
12
|
+
:config="dataSourceFieldsConfig"
|
|
13
|
+
:values="fieldValues"
|
|
14
|
+
:parentValues="model[name]"
|
|
15
|
+
@submit="fieldChange"
|
|
16
|
+
></MFormDialog>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
import { ref } from 'vue';
|
|
22
|
+
|
|
23
|
+
import { TMagicButton, tMagicMessageBox } from '@tmagic/design';
|
|
24
|
+
import { FormConfig, FormState, MFormDialog } from '@tmagic/form';
|
|
25
|
+
import { MagicTable } from '@tmagic/table';
|
|
26
|
+
|
|
27
|
+
const props = withDefaults(
|
|
28
|
+
defineProps<{
|
|
29
|
+
config: {
|
|
30
|
+
type: 'data-source-fields';
|
|
31
|
+
};
|
|
32
|
+
model: any;
|
|
33
|
+
prop: string;
|
|
34
|
+
disabled: boolean;
|
|
35
|
+
name: string;
|
|
36
|
+
}>(),
|
|
37
|
+
{
|
|
38
|
+
disabled: false,
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits(['change']);
|
|
43
|
+
|
|
44
|
+
const addDialog = ref<InstanceType<typeof MFormDialog>>();
|
|
45
|
+
const fieldValues = ref<Record<string, any>>({});
|
|
46
|
+
const filedTitle = ref('');
|
|
47
|
+
|
|
48
|
+
const newHandler = () => {
|
|
49
|
+
if (!addDialog.value) return;
|
|
50
|
+
fieldValues.value = {};
|
|
51
|
+
filedTitle.value = '新增属性';
|
|
52
|
+
addDialog.value.dialogVisible = true;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const fieldChange = ({ index, ...value }: Record<string, any>) => {
|
|
56
|
+
if (!addDialog.value) return;
|
|
57
|
+
|
|
58
|
+
if (index > -1) {
|
|
59
|
+
props.model[props.name][index] = value;
|
|
60
|
+
} else {
|
|
61
|
+
props.model[props.name].push(value);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
addDialog.value.dialogVisible = false;
|
|
65
|
+
|
|
66
|
+
emit('change', props.model[props.name]);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const filedColumns = [
|
|
70
|
+
{
|
|
71
|
+
label: '属性名称',
|
|
72
|
+
prop: 'title',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
label: '属性key',
|
|
76
|
+
prop: 'name',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: '属性描述',
|
|
80
|
+
prop: 'desc',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
label: '操作',
|
|
84
|
+
fixed: 'right',
|
|
85
|
+
actions: [
|
|
86
|
+
{
|
|
87
|
+
text: '编辑',
|
|
88
|
+
handler: (row: Record<string, any>, index: number) => {
|
|
89
|
+
if (!addDialog.value) return;
|
|
90
|
+
fieldValues.value = {
|
|
91
|
+
...row,
|
|
92
|
+
index,
|
|
93
|
+
};
|
|
94
|
+
filedTitle.value = `编辑${row.title}`;
|
|
95
|
+
addDialog.value.dialogVisible = true;
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
text: '删除',
|
|
100
|
+
buttonType: 'danger',
|
|
101
|
+
handler: async (row: Record<string, any>, index: number) => {
|
|
102
|
+
await tMagicMessageBox.confirm(`确定删除${row.title}(${row.name})?`, '提示');
|
|
103
|
+
props.model[props.name].splice(index, 1);
|
|
104
|
+
emit('change', props.model[props.name]);
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const dataSourceFieldsConfig: FormConfig = [
|
|
112
|
+
{ name: 'index', type: 'hidden', filter: 'number', defaultValue: -1 },
|
|
113
|
+
{
|
|
114
|
+
name: 'type',
|
|
115
|
+
text: '数据类型',
|
|
116
|
+
type: 'select',
|
|
117
|
+
defaultValue: 'string',
|
|
118
|
+
options: [
|
|
119
|
+
{ text: '字符串', value: 'string' },
|
|
120
|
+
{ text: '数字', value: 'number' },
|
|
121
|
+
{ text: '布尔值', value: 'boolean' },
|
|
122
|
+
{ text: '对象', value: 'object' },
|
|
123
|
+
{ text: '数组', value: 'array' },
|
|
124
|
+
{ text: 'null', value: 'null' },
|
|
125
|
+
{ text: 'any', value: 'any' },
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'name',
|
|
130
|
+
text: '字段名称',
|
|
131
|
+
rules: [
|
|
132
|
+
{
|
|
133
|
+
required: true,
|
|
134
|
+
message: '请输入字段名称',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
validator: ({ value, callback }, { model, parent }) => {
|
|
138
|
+
const index = parent.findIndex((item: Record<string, any>) => item.name === value);
|
|
139
|
+
if ((model.index === -1 && index > -1) || (model.index > -1 && index !== model.index)) {
|
|
140
|
+
return callback(`属性key(${value})已存在`);
|
|
141
|
+
}
|
|
142
|
+
callback();
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'title',
|
|
149
|
+
text: '展示名称',
|
|
150
|
+
rules: [
|
|
151
|
+
{
|
|
152
|
+
required: true,
|
|
153
|
+
message: '请输入展示名称',
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'description',
|
|
159
|
+
text: '描述',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'defaultValue',
|
|
163
|
+
text: '默认值',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'enable',
|
|
167
|
+
text: '是否可用',
|
|
168
|
+
type: 'switch',
|
|
169
|
+
defaultValue: true,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'fields',
|
|
173
|
+
type: 'data-source-fields',
|
|
174
|
+
defaultValue: [],
|
|
175
|
+
display: (formState: FormState | undefined, { model }: any) => model.type === 'object',
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
</script>
|
|
@@ -132,6 +132,7 @@ const compActionConfig = computed(() => {
|
|
|
132
132
|
const codeActionConfig = computed(() => {
|
|
133
133
|
const defaultCodeActionConfig = {
|
|
134
134
|
type: 'code-select-col',
|
|
135
|
+
labelWidth: 0,
|
|
135
136
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.CODE,
|
|
136
137
|
};
|
|
137
138
|
return { ...defaultCodeActionConfig, ...props.config.codeActionConfig };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-fields-key-value">
|
|
3
|
+
<div class="m-fields-key-value-item" v-for="(item, index) in records" :key="index">
|
|
4
|
+
<TMagicInput
|
|
5
|
+
placeholder="key"
|
|
6
|
+
v-model="records[index][0]"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
:size="size"
|
|
9
|
+
@change="keyChangeHandler"
|
|
10
|
+
></TMagicInput>
|
|
11
|
+
<span class="m-fileds-key-value-delimiter">:</span>
|
|
12
|
+
<TMagicInput
|
|
13
|
+
placeholder="value"
|
|
14
|
+
v-model="records[index][1]"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
:size="size"
|
|
17
|
+
@change="valueChangeHandler"
|
|
18
|
+
></TMagicInput>
|
|
19
|
+
|
|
20
|
+
<TMagicButton
|
|
21
|
+
class="m-fileds-key-value-delete"
|
|
22
|
+
type="danger"
|
|
23
|
+
:size="size"
|
|
24
|
+
circle
|
|
25
|
+
plain
|
|
26
|
+
:icon="Delete"
|
|
27
|
+
@click="deleteHandler(index)"
|
|
28
|
+
></TMagicButton>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<TMagicButton type="primary" :size="size" plain :icon="Plus" @click="addHandler">添加</TMagicButton>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script setup lang="ts">
|
|
36
|
+
import { ref, watchEffect } from 'vue';
|
|
37
|
+
import { Delete, Plus } from '@element-plus/icons-vue';
|
|
38
|
+
|
|
39
|
+
import { TMagicButton, TMagicInput } from '@tmagic/design';
|
|
40
|
+
|
|
41
|
+
const props = withDefaults(
|
|
42
|
+
defineProps<{
|
|
43
|
+
config: {
|
|
44
|
+
type: 'key-value';
|
|
45
|
+
name: string;
|
|
46
|
+
text: string;
|
|
47
|
+
};
|
|
48
|
+
model: Record<string, any>;
|
|
49
|
+
name: string;
|
|
50
|
+
prop: string;
|
|
51
|
+
disabled: boolean;
|
|
52
|
+
lastValues?: Record<string, any>;
|
|
53
|
+
size?: 'large' | 'default' | 'small';
|
|
54
|
+
}>(),
|
|
55
|
+
{
|
|
56
|
+
disabled: false,
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const emit = defineEmits<(e: 'change', value: Record<string, any>) => void>();
|
|
61
|
+
|
|
62
|
+
const records = ref<[string, string][]>([]);
|
|
63
|
+
|
|
64
|
+
watchEffect(() => {
|
|
65
|
+
records.value = Object.entries(props.model[props.name] || {});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const getValue = () => {
|
|
69
|
+
const record: Record<string, string> = {};
|
|
70
|
+
records.value.forEach(([key, value]) => {
|
|
71
|
+
if (key) {
|
|
72
|
+
record[key] = value;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return record;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const keyChangeHandler = () => {
|
|
79
|
+
emit('change', getValue());
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const valueChangeHandler = () => {
|
|
83
|
+
emit('change', getValue());
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const addHandler = () => {
|
|
87
|
+
records.value.push(['', '']);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const deleteHandler = (index: number) => {
|
|
91
|
+
records.value.splice(index, 1);
|
|
92
|
+
};
|
|
93
|
+
</script>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<!-- app-manage cdn链接:https://cloudcache.tencent-cloud.com/qcloud/ui/static/console_aside_v4/6638c8a5-2e7f-477a-83b1-a413a0e4ba39.svg -->
|
|
3
|
-
<svg
|
|
3
|
+
<svg xmlns="http://www.w3.org/2000/svg">
|
|
4
4
|
<g fill="#7C878E" fill-rule="evenodd">
|
|
5
5
|
<path d="M15.3,5.5 L8,0 L0.7,5.5 L8,11 L15.3,5.5 Z M8,2.5 L12,5.5 L8,8.5 L4,5.5 L8,2.5 Z" fill-rule="nonzero" />
|
|
6
6
|
<path d="M8 13.5L2.3 9.2 0.7 10.5 8 16 15.3 10.5 13.7 9.2z" />
|
package/src/icons/CodeIcon.vue
CHANGED
|
@@ -1,16 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<!-- 代码icon,cdn链接:https://cloudcache.tencent-cloud.com/qcloud/ui/static/government/0d463ed5-6407-4498-8865-3d05b5e70115.svg -->
|
|
3
|
-
<svg
|
|
4
|
-
width="32px"
|
|
5
|
-
height="32px"
|
|
6
|
-
viewBox="0 0 32 32"
|
|
7
|
-
version="1.1"
|
|
8
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
-
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
10
|
-
>
|
|
3
|
+
<svg viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
11
4
|
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
|
|
12
|
-
<title>gsd-icon-line-Universal-code</title>
|
|
13
|
-
<desc>Created with Sketch.</desc>
|
|
14
5
|
<defs><rect id="path-1" x="0" y="0" width="32" height="32"></rect></defs>
|
|
15
6
|
<g id="组件规范" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
16
7
|
<g id="03图标" transform="translate(-561.000000, -2356.000000)">
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,9 @@ import Code from './fields/Code.vue';
|
|
|
21
21
|
import CodeLink from './fields/CodeLink.vue';
|
|
22
22
|
import CodeSelect from './fields/CodeSelect.vue';
|
|
23
23
|
import CodeSelectCol from './fields/CodeSelectCol.vue';
|
|
24
|
+
import DataSourceFields from './fields/DataSourceFields.vue';
|
|
24
25
|
import EventSelect from './fields/EventSelect.vue';
|
|
26
|
+
import KeyValue from './fields/KeyValue.vue';
|
|
25
27
|
import uiSelect from './fields/UISelect.vue';
|
|
26
28
|
import CodeEditor from './layouts/CodeEditor.vue';
|
|
27
29
|
import { setConfig } from './utils/config';
|
|
@@ -47,7 +49,9 @@ export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPa
|
|
|
47
49
|
export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
|
|
48
50
|
export { default as CodeSelect } from './fields/CodeSelect.vue';
|
|
49
51
|
export { default as CodeSelectCol } from './fields/CodeSelectCol.vue';
|
|
52
|
+
export { default as DataSourceFields } from './fields/DataSourceFields.vue';
|
|
50
53
|
export { default as EventSelect } from './fields/EventSelect.vue';
|
|
54
|
+
export { default as KeyValue } from './fields/KeyValue.vue';
|
|
51
55
|
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
|
52
56
|
export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
53
57
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
@@ -74,5 +78,7 @@ export default {
|
|
|
74
78
|
app.component('m-fields-code-select', CodeSelect);
|
|
75
79
|
app.component('m-fields-code-select-col', CodeSelectCol);
|
|
76
80
|
app.component('m-fields-event-select', EventSelect);
|
|
81
|
+
app.component('m-fields-data-source-fields', DataSourceFields);
|
|
82
|
+
app.component('m-fields-key-value', KeyValue);
|
|
77
83
|
},
|
|
78
84
|
};
|
package/src/initService.ts
CHANGED
|
@@ -2,9 +2,10 @@ import type { ExtractPropTypes } from 'vue';
|
|
|
2
2
|
import { onUnmounted, toRaw, watch } from 'vue';
|
|
3
3
|
|
|
4
4
|
import type { EventOption } from '@tmagic/core';
|
|
5
|
-
import type { CodeBlockContent, Id, MApp, MNode, MPage } from '@tmagic/schema';
|
|
5
|
+
import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage } from '@tmagic/schema';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import type { Target } from './services/dep';
|
|
8
|
+
import { createCodeBlockTarget, createDataSourceTarget } from './utils/dep';
|
|
8
9
|
import editorProps from './editorProps';
|
|
9
10
|
import type { Services } from './type';
|
|
10
11
|
|
|
@@ -107,8 +108,31 @@ export const initServiceState = (
|
|
|
107
108
|
export const initServiceEvents = (
|
|
108
109
|
props: Readonly<LooseRequired<Readonly<ExtractPropTypes<typeof editorProps>>>>,
|
|
109
110
|
emit: (event: 'props-panel-mounted' | 'update:modelValue', ...args: any[]) => void,
|
|
110
|
-
{ editorService, codeBlockService, depService }: Services,
|
|
111
|
+
{ editorService, codeBlockService, dataSourceService, depService }: Services,
|
|
111
112
|
) => {
|
|
113
|
+
const targetAddHandler = (target: Target) => {
|
|
114
|
+
if (target.type !== 'data-source') return;
|
|
115
|
+
|
|
116
|
+
const root = editorService.get('root');
|
|
117
|
+
if (!root) return;
|
|
118
|
+
|
|
119
|
+
if (!root.dataSourceDeps) {
|
|
120
|
+
root.dataSourceDeps = {};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
root.dataSourceDeps[target.id] = target.deps;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const targetRemoveHandler = (id: string | number) => {
|
|
127
|
+
const root = editorService.get('root');
|
|
128
|
+
if (!root?.dataSourceDeps) return;
|
|
129
|
+
|
|
130
|
+
delete root.dataSourceDeps[id];
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
depService.on('add-target', targetAddHandler);
|
|
134
|
+
depService.on('remove-target', targetRemoveHandler);
|
|
135
|
+
|
|
112
136
|
const rootChangeHandler = async (value: MApp, preValue?: MApp | null) => {
|
|
113
137
|
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
|
114
138
|
let node;
|
|
@@ -131,8 +155,10 @@ export const initServiceEvents = (
|
|
|
131
155
|
}
|
|
132
156
|
|
|
133
157
|
value.codeBlocks = value.codeBlocks || {};
|
|
158
|
+
value.dataSources = value.dataSources || [];
|
|
134
159
|
|
|
135
160
|
codeBlockService.setCodeDsl(value.codeBlocks);
|
|
161
|
+
dataSourceService.set('dataSources', value.dataSources);
|
|
136
162
|
|
|
137
163
|
depService.removeTargets('code-block');
|
|
138
164
|
|
|
@@ -140,10 +166,15 @@ export const initServiceEvents = (
|
|
|
140
166
|
depService.addTarget(createCodeBlockTarget(id, code));
|
|
141
167
|
});
|
|
142
168
|
|
|
169
|
+
value.dataSources.forEach((ds) => {
|
|
170
|
+
depService.addTarget(createDataSourceTarget(ds.id, ds));
|
|
171
|
+
});
|
|
172
|
+
|
|
143
173
|
if (value && Array.isArray(value.items)) {
|
|
144
174
|
depService.collect(value.items, true);
|
|
145
175
|
} else {
|
|
146
176
|
depService.clear();
|
|
177
|
+
delete value.dataSourceDeps;
|
|
147
178
|
}
|
|
148
179
|
};
|
|
149
180
|
|
|
@@ -185,7 +216,28 @@ export const initServiceEvents = (
|
|
|
185
216
|
codeBlockService.on('addOrUpdate', codeBlockAddOrUpdateHandler);
|
|
186
217
|
codeBlockService.on('remove', codeBlockRemoveHandler);
|
|
187
218
|
|
|
219
|
+
const dataSourceAddHandler = (config: DataSourceSchema) => {
|
|
220
|
+
depService.addTarget(createDataSourceTarget(config.id, config));
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const dataSourceUpdateHandler = (config: DataSourceSchema) => {
|
|
224
|
+
if (config.title) {
|
|
225
|
+
depService.getTarget(config.id)!.name = config.title;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const dataSourceRemoveHandler = (id: string) => {
|
|
230
|
+
depService.removeTarget(id);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
dataSourceService.on('add', dataSourceAddHandler);
|
|
234
|
+
dataSourceService.on('update', dataSourceUpdateHandler);
|
|
235
|
+
dataSourceService.on('remove', dataSourceRemoveHandler);
|
|
236
|
+
|
|
188
237
|
onUnmounted(() => {
|
|
238
|
+
depService.off('add-target', targetAddHandler);
|
|
239
|
+
depService.off('remove-target', targetRemoveHandler);
|
|
240
|
+
|
|
189
241
|
editorService.off('history-change', historyChangeHandler);
|
|
190
242
|
editorService.off('root-change', rootChangeHandler);
|
|
191
243
|
editorService.off('add', nodeAddHandler);
|
|
@@ -194,5 +246,9 @@ export const initServiceEvents = (
|
|
|
194
246
|
|
|
195
247
|
codeBlockService.off('addOrUpdate', codeBlockAddOrUpdateHandler);
|
|
196
248
|
codeBlockService.off('remove', codeBlockRemoveHandler);
|
|
249
|
+
|
|
250
|
+
dataSourceService.off('add', dataSourceAddHandler);
|
|
251
|
+
dataSourceService.off('update', dataSourceUpdateHandler);
|
|
252
|
+
dataSourceService.off('remove', dataSourceRemoveHandler);
|
|
197
253
|
});
|
|
198
254
|
};
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<component
|
|
3
3
|
v-if="data.type === 'tabs' && data.items.length"
|
|
4
|
-
class="m-editor-sidebar"
|
|
5
4
|
v-model="activeTabName"
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
class="m-editor-sidebar tmagic-design-tabs"
|
|
6
|
+
v-bind="tabsComponent.props({ type: 'card', tabPosition: 'left' })"
|
|
7
|
+
:is="tabsComponent.component"
|
|
8
8
|
>
|
|
9
9
|
<component
|
|
10
|
-
:is="uiComponent.component"
|
|
11
10
|
v-for="(config, index) in sideBarItems"
|
|
11
|
+
v-bind="tabPaneComponent.props({ name: config.text })"
|
|
12
|
+
:is="tabPaneComponent.component"
|
|
12
13
|
:key="config.$key || index"
|
|
13
|
-
:name="config.text"
|
|
14
14
|
>
|
|
15
15
|
<template #label>
|
|
16
16
|
<div :key="config.text">
|
|
@@ -80,34 +80,36 @@
|
|
|
80
80
|
</template>
|
|
81
81
|
</component>
|
|
82
82
|
</component>
|
|
83
|
-
</
|
|
83
|
+
</component>
|
|
84
84
|
</template>
|
|
85
85
|
|
|
86
86
|
<script lang="ts" setup name="MEditorSidebar">
|
|
87
87
|
import { computed, ref, watch } from 'vue';
|
|
88
|
-
import { Coin, EditPen,
|
|
88
|
+
import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
|
|
89
89
|
|
|
90
|
-
import { getConfig
|
|
90
|
+
import { getConfig } from '@tmagic/design';
|
|
91
91
|
|
|
92
92
|
import MIcon from '@editor/components/Icon.vue';
|
|
93
93
|
import type { MenuButton, MenuComponent, SideComponent, SideItem } from '@editor/type';
|
|
94
94
|
import { SideBarData } from '@editor/type';
|
|
95
95
|
|
|
96
96
|
import CodeBlockList from './code-block/CodeBlockList.vue';
|
|
97
|
+
import DataSourceListPanel from './data-source/DataSourceListPanel.vue';
|
|
97
98
|
import ComponentListPanel from './ComponentListPanel.vue';
|
|
98
99
|
import LayerPanel from './LayerPanel.vue';
|
|
99
100
|
|
|
100
101
|
const props = withDefaults(
|
|
101
102
|
defineProps<{
|
|
102
|
-
data
|
|
103
|
+
data: SideBarData;
|
|
103
104
|
layerContentMenu: (MenuButton | MenuComponent)[];
|
|
104
105
|
}>(),
|
|
105
106
|
{
|
|
106
|
-
data: () => ({ type: 'tabs', status: '组件', items: ['component-list', 'layer', 'code-block'] }),
|
|
107
|
+
data: () => ({ type: 'tabs', status: '组件', items: ['component-list', 'layer', 'code-block', 'data-source'] }),
|
|
107
108
|
},
|
|
108
109
|
);
|
|
109
110
|
|
|
110
|
-
const
|
|
111
|
+
const tabPaneComponent = getConfig('components').tabPane;
|
|
112
|
+
const tabsComponent = getConfig('components').tabs;
|
|
111
113
|
|
|
112
114
|
const activeTabName = ref(props.data?.status);
|
|
113
115
|
|
|
@@ -116,7 +118,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
116
118
|
'component-list': {
|
|
117
119
|
$key: 'component-list',
|
|
118
120
|
type: 'component',
|
|
119
|
-
icon:
|
|
121
|
+
icon: Goods,
|
|
120
122
|
text: '组件',
|
|
121
123
|
component: ComponentListPanel,
|
|
122
124
|
slots: {},
|
|
@@ -124,7 +126,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
124
126
|
layer: {
|
|
125
127
|
$key: 'layer',
|
|
126
128
|
type: 'component',
|
|
127
|
-
icon:
|
|
129
|
+
icon: List,
|
|
128
130
|
text: '已选组件',
|
|
129
131
|
props: {
|
|
130
132
|
layerContentMenu: props.layerContentMenu,
|
|
@@ -140,6 +142,14 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
140
142
|
component: CodeBlockList,
|
|
141
143
|
slots: {},
|
|
142
144
|
},
|
|
145
|
+
'data-source': {
|
|
146
|
+
$key: 'data-source',
|
|
147
|
+
type: 'component',
|
|
148
|
+
icon: Coin,
|
|
149
|
+
text: '数据源',
|
|
150
|
+
component: DataSourceListPanel,
|
|
151
|
+
slots: {},
|
|
152
|
+
},
|
|
143
153
|
};
|
|
144
154
|
|
|
145
155
|
return typeof data === 'string' ? map[data] : data;
|