mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-23 10:19:17 +08:00
refactor(playground): 整理代码
This commit is contained in:
parent
bdd59cff9b
commit
3b1e41b217
@ -40,62 +40,35 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, markRaw, nextTick, onBeforeUnmount, Ref, ref, toRaw } from 'vue';
|
import { computed, onBeforeUnmount, ref, shallowRef, toRaw } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { Coin, Connection, CopyDocument, Document, DocumentCopy } from '@element-plus/icons-vue';
|
|
||||||
import { cloneDeep } from 'lodash-es';
|
|
||||||
import serialize from 'serialize-javascript';
|
import serialize from 'serialize-javascript';
|
||||||
|
|
||||||
import type { MApp, MContainer, MNode } from '@tmagic/core';
|
import type { MApp, MContainer, MNode } from '@tmagic/core';
|
||||||
import { NodeType } from '@tmagic/core';
|
import { NodeType } from '@tmagic/core';
|
||||||
import type {
|
import type { CustomizeMoveableOptionsCallbackConfig, DatasourceTypeOption, MoveableOptions } from '@tmagic/editor';
|
||||||
CustomizeMoveableOptionsCallbackConfig,
|
import { editorService, propsService, TMagicDialog, TMagicEditor, tMagicMessage } from '@tmagic/editor';
|
||||||
DatasourceTypeOption,
|
|
||||||
MenuBarData,
|
|
||||||
MenuButton,
|
|
||||||
MoveableOptions,
|
|
||||||
Services,
|
|
||||||
} from '@tmagic/editor';
|
|
||||||
import {
|
|
||||||
asyncLoadJs,
|
|
||||||
calcValueByFontsize,
|
|
||||||
ContentMenu,
|
|
||||||
COPY_STORAGE_KEY,
|
|
||||||
editorService,
|
|
||||||
propsService,
|
|
||||||
TMagicDialog,
|
|
||||||
TMagicEditor,
|
|
||||||
tMagicMessage,
|
|
||||||
tMagicMessageBox,
|
|
||||||
} from '@tmagic/editor';
|
|
||||||
|
|
||||||
import DeviceGroup from '../components/DeviceGroup.vue';
|
import DeviceGroup from '../components/DeviceGroup.vue';
|
||||||
import componentGroupList from '../configs/componentGroupList';
|
import componentGroupList from '../configs/componentGroupList';
|
||||||
import dsl from '../configs/dsl';
|
import dsl from '../configs/dsl';
|
||||||
import { uaMap } from '../const';
|
|
||||||
|
|
||||||
const { VITE_RUNTIME_PATH, VITE_ENTRY_PATH } = import.meta.env;
|
import { useEditorContentMenuData } from './composables/use-editor-content-menu-data';
|
||||||
|
import { useEditorMenu } from './composables/use-editor-menu';
|
||||||
|
import { useEditorRes } from './composables/use-editor-res';
|
||||||
|
|
||||||
|
const { VITE_RUNTIME_PATH } = import.meta.env;
|
||||||
|
|
||||||
const datasourceList: DatasourceTypeOption[] = [];
|
const datasourceList: DatasourceTypeOption[] = [];
|
||||||
const runtimeUrl = `${VITE_RUNTIME_PATH}/playground/index.html`;
|
const runtimeUrl = `${VITE_RUNTIME_PATH}/playground/index.html`;
|
||||||
const router = useRouter();
|
|
||||||
const editor = ref<InstanceType<typeof TMagicEditor>>();
|
const { propsValues, propsConfigs, eventMethodList, datasourceConfigs, datasourceValues, datasourceEventMethodList } =
|
||||||
const deviceGroup = ref<InstanceType<typeof DeviceGroup>>();
|
useEditorRes();
|
||||||
const iframe = ref<HTMLIFrameElement>();
|
const { contentMenuData } = useEditorContentMenuData();
|
||||||
const previewVisible = ref(false);
|
|
||||||
|
const editor = shallowRef<InstanceType<typeof TMagicEditor>>();
|
||||||
const value = ref<MApp>(dsl);
|
const value = ref<MApp>(dsl);
|
||||||
const defaultSelected = ref(dsl.items[0].id);
|
const defaultSelected = ref(dsl.items[0].id);
|
||||||
const propsValues = ref<Record<string, any>>({});
|
|
||||||
const propsConfigs = ref<Record<string, any>>({});
|
|
||||||
const eventMethodList = ref<Record<string, any>>({});
|
|
||||||
const datasourceEventMethodList = ref<Record<string, any>>({
|
|
||||||
base: {
|
|
||||||
events: [],
|
|
||||||
methods: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const datasourceConfigs = ref<Record<string, any>>({});
|
|
||||||
const datasourceValues = ref<Record<string, any>>({});
|
|
||||||
const stageRect = ref({
|
const stageRect = ref({
|
||||||
width: 375,
|
width: 375,
|
||||||
height: 817,
|
height: 817,
|
||||||
@ -105,130 +78,6 @@ const previewUrl = computed(
|
|||||||
() => `${VITE_RUNTIME_PATH}/page/index.html?localPreview=1&page=${editor.value?.editorService.get('page')?.id}`,
|
() => `${VITE_RUNTIME_PATH}/page/index.html?localPreview=1&page=${editor.value?.editorService.get('page')?.id}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const collectorOptions = {
|
|
||||||
id: '',
|
|
||||||
name: '蒙层',
|
|
||||||
isTarget: (key: string | number, value: any) =>
|
|
||||||
typeof key === 'string' && typeof value === 'string' && key.includes('events') && value.startsWith('overlay_'),
|
|
||||||
isCollectByDefault: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const usePasteMenu = (menu?: Ref<InstanceType<typeof ContentMenu> | undefined>): MenuButton => ({
|
|
||||||
type: 'button',
|
|
||||||
text: '粘贴(带关联信息)',
|
|
||||||
icon: markRaw(DocumentCopy),
|
|
||||||
display: (services) => !!services?.storageService?.getItem(COPY_STORAGE_KEY),
|
|
||||||
handler: (services) => {
|
|
||||||
const nodes = services?.editorService?.get('nodes');
|
|
||||||
if (!nodes || nodes.length === 0) return;
|
|
||||||
|
|
||||||
if (menu?.value?.$el) {
|
|
||||||
const stage = services?.editorService?.get('stage');
|
|
||||||
const rect = menu.value.$el.getBoundingClientRect();
|
|
||||||
const parentRect = stage?.container?.getBoundingClientRect();
|
|
||||||
const initialLeft =
|
|
||||||
calcValueByFontsize(stage?.renderer?.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) /
|
|
||||||
services.uiService.get('zoom');
|
|
||||||
const initialTop =
|
|
||||||
calcValueByFontsize(stage?.renderer?.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) /
|
|
||||||
services.uiService.get('zoom');
|
|
||||||
services?.editorService?.paste({ left: initialLeft, top: initialTop }, collectorOptions);
|
|
||||||
} else {
|
|
||||||
services?.editorService?.paste({}, collectorOptions);
|
|
||||||
services?.codeBlockService?.paste();
|
|
||||||
services?.dataSourceService?.paste();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const contentMenuData = computed<MenuButton[]>(() => [
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: '复制(带关联信息)',
|
|
||||||
icon: markRaw(CopyDocument),
|
|
||||||
handler: (services: Services) => {
|
|
||||||
const nodes = services?.editorService?.get('nodes');
|
|
||||||
nodes && services?.editorService?.copyWithRelated(cloneDeep(nodes), collectorOptions);
|
|
||||||
nodes && services?.codeBlockService?.copyWithRelated(cloneDeep(nodes));
|
|
||||||
nodes && services?.dataSourceService?.copyWithRelated(cloneDeep(nodes));
|
|
||||||
},
|
|
||||||
},
|
|
||||||
usePasteMenu(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const menu: MenuBarData = {
|
|
||||||
left: [
|
|
||||||
{
|
|
||||||
type: 'text',
|
|
||||||
text: '魔方',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
center: ['delete', 'undo', 'redo', 'guides', 'rule', 'zoom'],
|
|
||||||
right: [
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: 'Form Playground',
|
|
||||||
handler: () => router.push('form'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: 'Form Editor Playground',
|
|
||||||
handler: () => router.push('form-editor'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: 'Table Playground',
|
|
||||||
handler: () => router.push('table'),
|
|
||||||
},
|
|
||||||
'/',
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: '预览',
|
|
||||||
icon: Connection,
|
|
||||||
handler: async (services) => {
|
|
||||||
if (services?.editorService.get('modifiedNodeIds').size > 0) {
|
|
||||||
try {
|
|
||||||
await tMagicMessageBox.confirm('有修改未保存,是否先保存再预览', '提示', {
|
|
||||||
confirmButtonText: '保存并预览',
|
|
||||||
cancelButtonText: '预览',
|
|
||||||
type: 'warning',
|
|
||||||
});
|
|
||||||
save();
|
|
||||||
tMagicMessage.success('保存成功');
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
previewVisible.value = true;
|
|
||||||
|
|
||||||
await nextTick();
|
|
||||||
|
|
||||||
if (!iframe.value?.contentWindow || !deviceGroup.value?.viewerDevice) return;
|
|
||||||
Object.defineProperty(iframe.value.contentWindow.navigator, 'userAgent', {
|
|
||||||
value: uaMap[deviceGroup.value.viewerDevice],
|
|
||||||
writable: true,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
text: '保存',
|
|
||||||
icon: Coin,
|
|
||||||
handler: () => {
|
|
||||||
save();
|
|
||||||
tMagicMessage.success('保存成功');
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'/',
|
|
||||||
{
|
|
||||||
type: 'button',
|
|
||||||
icon: Document,
|
|
||||||
tooltip: '源码',
|
|
||||||
handler: (service) => service?.uiService.set('showSrc', !service?.uiService.get('showSrc')),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const moveableOptions = (config?: CustomizeMoveableOptionsCallbackConfig): MoveableOptions => {
|
const moveableOptions = (config?: CustomizeMoveableOptionsCallbackConfig): MoveableOptions => {
|
||||||
const options: MoveableOptions = {};
|
const options: MoveableOptions = {};
|
||||||
|
|
||||||
@ -272,21 +121,7 @@ const save = () => {
|
|||||||
editor.value?.editorService.resetModifiedNodeId();
|
editor.value?.editorService.resetModifiedNodeId();
|
||||||
};
|
};
|
||||||
|
|
||||||
asyncLoadJs(`${VITE_ENTRY_PATH}/config/index.umd.cjs`).then(() => {
|
const { menu, deviceGroup, iframe, previewVisible } = useEditorMenu(value, save);
|
||||||
propsConfigs.value = (globalThis as any).magicPresetConfigs;
|
|
||||||
});
|
|
||||||
asyncLoadJs(`${VITE_ENTRY_PATH}/value/index.umd.cjs`).then(() => {
|
|
||||||
propsValues.value = (globalThis as any).magicPresetValues;
|
|
||||||
});
|
|
||||||
asyncLoadJs(`${VITE_ENTRY_PATH}/event/index.umd.cjs`).then(() => {
|
|
||||||
eventMethodList.value = (globalThis as any).magicPresetEvents;
|
|
||||||
});
|
|
||||||
asyncLoadJs(`${VITE_ENTRY_PATH}/ds-config/index.umd.cjs`).then(() => {
|
|
||||||
datasourceConfigs.value = (globalThis as any).magicPresetDsConfigs;
|
|
||||||
});
|
|
||||||
asyncLoadJs(`${VITE_ENTRY_PATH}/ds-value/index.umd.cjs`).then(() => {
|
|
||||||
datasourceValues.value = (globalThis as any).magicPresetDsValues;
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line no-eval
|
// eslint-disable-next-line no-eval
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
import { computed, markRaw, type Ref } from 'vue';
|
||||||
|
import { CopyDocument, DocumentCopy } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import { cloneDeep } from '@tmagic/core';
|
||||||
|
import { calcValueByFontsize, ContentMenu, COPY_STORAGE_KEY, type MenuButton, Services } from '@tmagic/editor';
|
||||||
|
|
||||||
|
export const useEditorContentMenuData = () => {
|
||||||
|
const collectorOptions = {
|
||||||
|
id: '',
|
||||||
|
name: '蒙层',
|
||||||
|
isTarget: (key: string | number, value: any) =>
|
||||||
|
typeof key === 'string' && typeof value === 'string' && key.includes('events') && value.startsWith('overlay_'),
|
||||||
|
isCollectByDefault: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const usePasteMenu = (menu?: Ref<InstanceType<typeof ContentMenu> | undefined>): MenuButton => ({
|
||||||
|
type: 'button',
|
||||||
|
text: '粘贴(带关联信息)',
|
||||||
|
icon: markRaw(DocumentCopy),
|
||||||
|
display: (services) => !!services?.storageService?.getItem(COPY_STORAGE_KEY),
|
||||||
|
handler: (services) => {
|
||||||
|
const nodes = services?.editorService?.get('nodes');
|
||||||
|
if (!nodes || nodes.length === 0) return;
|
||||||
|
|
||||||
|
if (menu?.value?.$el) {
|
||||||
|
const stage = services?.editorService?.get('stage');
|
||||||
|
const rect = menu.value.$el.getBoundingClientRect();
|
||||||
|
const parentRect = stage?.container?.getBoundingClientRect();
|
||||||
|
const initialLeft =
|
||||||
|
calcValueByFontsize(stage?.renderer?.getDocument(), (rect.left || 0) - (parentRect?.left || 0)) /
|
||||||
|
services.uiService.get('zoom');
|
||||||
|
const initialTop =
|
||||||
|
calcValueByFontsize(stage?.renderer?.getDocument(), (rect.top || 0) - (parentRect?.top || 0)) /
|
||||||
|
services.uiService.get('zoom');
|
||||||
|
services?.editorService?.paste({ left: initialLeft, top: initialTop }, collectorOptions);
|
||||||
|
} else {
|
||||||
|
services?.editorService?.paste({}, collectorOptions);
|
||||||
|
services?.codeBlockService?.paste();
|
||||||
|
services?.dataSourceService?.paste();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const contentMenuData = computed<MenuButton[]>(() => [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: '复制(带关联信息)',
|
||||||
|
icon: markRaw(CopyDocument),
|
||||||
|
handler: (services: Services) => {
|
||||||
|
const nodes = services?.editorService?.get('nodes');
|
||||||
|
nodes && services?.editorService?.copyWithRelated(cloneDeep(nodes), collectorOptions);
|
||||||
|
nodes && services?.codeBlockService?.copyWithRelated(cloneDeep(nodes));
|
||||||
|
nodes && services?.dataSourceService?.copyWithRelated(cloneDeep(nodes));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
usePasteMenu(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
contentMenuData,
|
||||||
|
};
|
||||||
|
};
|
98
playground/src/pages/composables/use-editor-menu.ts
Normal file
98
playground/src/pages/composables/use-editor-menu.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { nextTick, type Ref, ref, shallowRef } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { Coin, Connection, Document } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
import type { MApp } from '@tmagic/core';
|
||||||
|
import { type MenuBarData, tMagicMessage, tMagicMessageBox } from '@tmagic/editor';
|
||||||
|
|
||||||
|
import DeviceGroup from '../../components/DeviceGroup.vue';
|
||||||
|
import { uaMap } from '../../const';
|
||||||
|
|
||||||
|
export const useEditorMenu = (value: Ref<MApp>, save: () => void) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const deviceGroup = shallowRef<InstanceType<typeof DeviceGroup>>();
|
||||||
|
const iframe = shallowRef<HTMLIFrameElement>();
|
||||||
|
const previewVisible = ref(false);
|
||||||
|
|
||||||
|
const menu: MenuBarData = {
|
||||||
|
left: [
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: '魔方',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
center: ['delete', 'undo', 'redo', 'guides', 'rule', 'zoom'],
|
||||||
|
right: [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Form Playground',
|
||||||
|
handler: () => router.push('form'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Form Editor Playground',
|
||||||
|
handler: () => router.push('form-editor'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: 'Table Playground',
|
||||||
|
handler: () => router.push('table'),
|
||||||
|
},
|
||||||
|
'/',
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: '预览',
|
||||||
|
icon: Connection,
|
||||||
|
handler: async (services) => {
|
||||||
|
if (services?.editorService.get('modifiedNodeIds').size > 0) {
|
||||||
|
try {
|
||||||
|
await tMagicMessageBox.confirm('有修改未保存,是否先保存再预览', '提示', {
|
||||||
|
confirmButtonText: '保存并预览',
|
||||||
|
cancelButtonText: '预览',
|
||||||
|
type: 'warning',
|
||||||
|
});
|
||||||
|
save();
|
||||||
|
tMagicMessage.success('保存成功');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previewVisible.value = true;
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
if (!iframe.value?.contentWindow || !deviceGroup.value?.viewerDevice) return;
|
||||||
|
Object.defineProperty(iframe.value.contentWindow.navigator, 'userAgent', {
|
||||||
|
value: uaMap[deviceGroup.value.viewerDevice],
|
||||||
|
writable: true,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
text: '保存',
|
||||||
|
icon: Coin,
|
||||||
|
handler: () => {
|
||||||
|
save();
|
||||||
|
tMagicMessage.success('保存成功');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'/',
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
icon: Document,
|
||||||
|
tooltip: '源码',
|
||||||
|
handler: (service) => service?.uiService.set('showSrc', !service?.uiService.get('showSrc')),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
menu,
|
||||||
|
deviceGroup,
|
||||||
|
iframe,
|
||||||
|
previewVisible,
|
||||||
|
save,
|
||||||
|
};
|
||||||
|
};
|
45
playground/src/pages/composables/use-editor-res.ts
Normal file
45
playground/src/pages/composables/use-editor-res.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
import { asyncLoadJs } from '@tmagic/editor';
|
||||||
|
|
||||||
|
const { VITE_ENTRY_PATH } = import.meta.env;
|
||||||
|
|
||||||
|
export const useEditorRes = () => {
|
||||||
|
const propsValues = ref<Record<string, any>>({});
|
||||||
|
const propsConfigs = ref<Record<string, any>>({});
|
||||||
|
const eventMethodList = ref<Record<string, any>>({});
|
||||||
|
const datasourceConfigs = ref<Record<string, any>>({});
|
||||||
|
const datasourceValues = ref<Record<string, any>>({});
|
||||||
|
|
||||||
|
const datasourceEventMethodList = ref<Record<string, any>>({
|
||||||
|
base: {
|
||||||
|
events: [],
|
||||||
|
methods: [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncLoadJs(`${VITE_ENTRY_PATH}/config/index.umd.cjs`).then(() => {
|
||||||
|
propsConfigs.value = (globalThis as any).magicPresetConfigs;
|
||||||
|
});
|
||||||
|
asyncLoadJs(`${VITE_ENTRY_PATH}/value/index.umd.cjs`).then(() => {
|
||||||
|
propsValues.value = (globalThis as any).magicPresetValues;
|
||||||
|
});
|
||||||
|
asyncLoadJs(`${VITE_ENTRY_PATH}/event/index.umd.cjs`).then(() => {
|
||||||
|
eventMethodList.value = (globalThis as any).magicPresetEvents;
|
||||||
|
});
|
||||||
|
asyncLoadJs(`${VITE_ENTRY_PATH}/ds-config/index.umd.cjs`).then(() => {
|
||||||
|
datasourceConfigs.value = (globalThis as any).magicPresetDsConfigs;
|
||||||
|
});
|
||||||
|
asyncLoadJs(`${VITE_ENTRY_PATH}/ds-value/index.umd.cjs`).then(() => {
|
||||||
|
datasourceValues.value = (globalThis as any).magicPresetDsValues;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
propsValues,
|
||||||
|
propsConfigs,
|
||||||
|
eventMethodList,
|
||||||
|
datasourceConfigs,
|
||||||
|
datasourceValues,
|
||||||
|
datasourceEventMethodList,
|
||||||
|
};
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user