style(editor): 将节点类型改成枚举

This commit is contained in:
roymondchen 2022-03-30 19:33:54 +08:00 committed by khuntoriia
parent 148d4547b0
commit 6dbda7b565
14 changed files with 67 additions and 43 deletions

View File

@ -41,6 +41,8 @@
import { computed, defineComponent, inject, PropType } from 'vue';
import { ArrowDown, Back, Delete, Grid, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons';
import { NodeType } from '@tmagic/schema';
import MIcon from '@editor/components/Icon.vue';
import type { MenuButton, MenuComponent, MenuItem, Services } from '@editor/type';
@ -87,7 +89,7 @@ export default defineComponent({
type: 'button',
icon: Delete,
tooltip: '刪除',
disabled: () => services?.editorService.get('node')?.type === 'page',
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
handler: () => services?.editorService.remove(services?.editorService.get('node')),
};
case 'undo':

View File

@ -15,6 +15,8 @@
import { defineComponent, inject, toRaw } from 'vue';
import { Plus } from '@element-plus/icons';
import { NodeType } from '@tmagic/schema';
import { Services } from '@editor/type';
import { generatePageNameByApp } from '@editor/utils';
@ -31,7 +33,7 @@ export default defineComponent({
if (!editorService) return;
editorService.add({
type: 'page',
type: NodeType.PAGE,
name: generatePageNameByApp(toRaw(editorService.get('root'))),
});
},

View File

@ -58,6 +58,7 @@ import type { ElTree } from 'element-plus';
import { throttle } from 'lodash-es';
import type { MNode, MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import type { EditorService } from '@editor/services/editor';
import type { Services } from '@editor/type';
@ -88,8 +89,8 @@ const useDrop = (tree: Ref<InstanceType<typeof ElTree> | undefined>, editorServi
const { type: ingType } = ingData;
if (ingType !== 'page' && data.type === 'page') return false;
if (ingType === 'page' && data.type !== 'page') return false;
if (ingType !== NodeType.PAGE && data.type === NodeType.PAGE) return false;
if (ingType === NodeType.PAGE && data.type !== NodeType.PAGE) return false;
if (!data || !data.type) return false;
if (['prev', 'next'].includes(type)) return true;
if (data.items || data.type === 'container') return true;

View File

@ -38,6 +38,7 @@ import { computed, defineComponent, inject, toRaw } from 'vue';
import { CaretBottom, Plus } from '@element-plus/icons';
import type { MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import type { Services } from '@editor/type';
import { generatePageNameByApp } from '@editor/utils/editor';
@ -60,7 +61,7 @@ export default defineComponent({
addPage() {
if (!editorService) return;
const pageConfig = {
type: 'page',
type: NodeType.PAGE,
name: generatePageNameByApp(toRaw(editorService.get('root'))),
};
editorService.add(pageConfig);

View File

@ -24,6 +24,7 @@
<script lang="ts">
import { computed, defineComponent, inject, onMounted, ref, watch } from 'vue';
import { NodeType } from '@tmagic/schema';
import type StageCore from '@tmagic/stage';
import { LayerOffset, Layout, Services } from '@editor/type';
@ -53,7 +54,8 @@ export default defineComponent({
if (!parent.value || !editorService) return (canCenter.value = false);
const layout = await editorService.getLayout(parent.value);
canCenter.value =
[Layout.ABSOLUTE, Layout.FIXED].includes(layout) && !['app', 'page', 'pop'].includes(`${node.value?.type}`);
[Layout.ABSOLUTE, Layout.FIXED].includes(layout) &&
![NodeType.ROOT, NodeType.PAGE, 'pop'].includes(`${node.value?.type}`);
},
{ immediate: true },
);
@ -62,8 +64,8 @@ export default defineComponent({
menu,
canPaste,
canDelete: computed(() => node.value?.type !== 'page'),
canMoveZPos: computed(() => node.value?.type !== 'page'),
canDelete: computed(() => node.value?.type !== NodeType.PAGE),
canMoveZPos: computed(() => node.value?.type !== NodeType.PAGE),
canCenter,
center() {

View File

@ -21,6 +21,7 @@ import { cloneDeep, mergeWith } from 'lodash-es';
import serialize from 'serialize-javascript';
import type { Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import type StageCore from '@tmagic/stage';
import { getNodePath, isPop } from '@tmagic/utils';
@ -121,7 +122,7 @@ class Editor extends BaseService {
info.parent = path[path.length - 2] as MContainer;
path.forEach((item) => {
if (item.type === 'page') {
if (item.type === NodeType.PAGE) {
info.page = item as MPage;
return;
}
@ -209,7 +210,7 @@ class Editor extends BaseService {
let parentNode: MNode | undefined;
if (type === 'page') {
if (type === NodeType.PAGE) {
parentNode = this.get<MApp>('root');
// 由于支持中间件扩展在parent参数为undefined时parent会变成next函数
} else if (parent && typeof parent !== 'function') {
@ -225,7 +226,7 @@ class Editor extends BaseService {
const layout = await this.getLayout(parentNode);
const newNode = initPosition({ ...toRaw(await propsService.getPropsValue(type)), ...config }, layout);
if ((parentNode?.type === 'app' || curNode.type === 'app') && newNode.type !== 'page') {
if ((parentNode?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && newNode.type !== NodeType.PAGE) {
throw new Error('app下不能添加组件');
}
@ -264,7 +265,7 @@ class Editor extends BaseService {
parent.items?.splice(index, 1);
this.get<StageCore>('stage')?.remove({ id: node.id, root: this.get('root') });
if (node.type === 'page') {
if (node.type === NodeType.PAGE) {
await this.select(root.items[0] || root);
} else {
await this.select(parent);
@ -300,7 +301,7 @@ class Editor extends BaseService {
if (!newConfig.type) throw new Error('配置缺少type值');
if (newConfig.type === 'app') {
if (newConfig.type === NodeType.ROOT) {
this.set('root', newConfig);
return newConfig;
}
@ -327,7 +328,7 @@ class Editor extends BaseService {
this.get<StageCore>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
if (newConfig.type === 'page') {
if (newConfig.type === NodeType.PAGE) {
this.set('page', newConfig);
}

View File

@ -18,7 +18,8 @@
import { random } from 'lodash-es';
import { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import { getNodePath, isPop } from '@tmagic/utils';
import { Layout } from '@editor/type';
@ -34,7 +35,7 @@ export const generateId = (type: string | number): string => `${type}_${random(1
*/
export const getPageList = (app: MApp): MPage[] => {
if (app.items && Array.isArray(app.items)) {
return app.items.filter((item: MPage) => item.type === 'page');
return app.items.filter((item: MPage) => item.type === NodeType.PAGE);
}
return [];
};
@ -108,7 +109,7 @@ export const setNewItemId = (config: MNode, parent?: MPage) => {
config.name = `${config.name?.replace(/_(\d+)$/, '')}_${config.id}`;
// 只有弹窗在页面下的一级子元素才有效
if (isPop(config) && parent?.type === 'page') {
if (isPop(config) && parent?.type === NodeType.PAGE) {
updatePopId(oldId, config.id, parent);
}

View File

@ -20,6 +20,7 @@ import { mount } from '@vue/test-utils';
import ElementPlus from 'element-plus';
import MagicForm from '@tmagic/form';
import { NodeType } from '@tmagic/schema';
import Editor from '@editor/Editor.vue';
@ -47,14 +48,14 @@ describe('编辑器', () => {
},
props: {
modelValue: {
type: 'app',
type: NodeType.ROOT,
id: 1,
name: 'app',
items: [
{
type: 'page',
type: NodeType.PAGE,
id: 2,
name: 'page',
name: NodeType.PAGE,
items: [],
},
],

View File

@ -19,13 +19,15 @@
import { mount } from '@vue/test-utils';
import ElementPlus from 'element-plus';
import { NodeType } from '@tmagic/schema';
import PageBar from '@editor/layouts/workspace/PageBar.vue';
const editorState: Record<string, any> = {
root: {
items: [{ key: 0, id: 1, name: 'testName', type: 'page' }],
items: [{ key: 0, id: 1, name: 'testName', type: NodeType.PAGE }],
},
page: { id: 1, type: 'page' },
page: { id: 1, type: NodeType.PAGE },
};
const editorService = {
@ -54,7 +56,7 @@ describe('PageBar', () => {
await wrapper.find('i[class="el-icon m-editor-page-bar-menu-add-icon"]').trigger('click');
expect(editorService.add.mock.calls[0][0]).toEqual({
type: 'page',
type: NodeType.PAGE,
name: 'page_1',
});
done();

View File

@ -18,6 +18,8 @@
import { mount } from '@vue/test-utils';
import { NodeType } from '@tmagic/schema';
import Stage from '@editor/layouts/workspace/Stage.vue';
globalThis.ResizeObserver =
@ -40,7 +42,7 @@ describe('Stage.vue', () => {
);
const page = {
type: 'page',
type: NodeType.PAGE,
id: '2',
items: [
{
@ -55,7 +57,7 @@ describe('Stage.vue', () => {
runtimeUrl: '',
root: {
id: '1',
type: 'app',
type: NodeType.ROOT,
items: [page],
},

View File

@ -18,7 +18,8 @@
import { cloneDeep } from 'lodash-es';
import { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import editorService from '@editor/services/editor';
import { COPY_STORAGE_KEY } from '@editor/utils';
@ -72,12 +73,12 @@ enum NodeId {
// mock 页面数据,包含一个页面,两个组件
const root: MNode = {
id: NodeId.ROOT_ID,
type: 'app',
type: NodeType.ROOT,
items: [
{
id: NodeId.PAGE_ID,
layout: 'absolute',
type: 'page',
type: NodeType.PAGE,
style: {
width: 375,
},
@ -237,7 +238,7 @@ describe('add', () => {
const rootNode = editorService.get<MApp>('root');
const newNode = await editorService.add(
{
type: 'page',
type: NodeType.PAGE,
},
rootNode,
);
@ -279,7 +280,7 @@ describe('remove', () => {
// 先加一个页面
const newPage = await editorService.add(
{
type: 'page',
type: NodeType.PAGE,
},
rootNode,
);
@ -395,7 +396,7 @@ describe('alignCenter', () => {
it('正常', async () => {
// 设置当前编辑的页面
await editorService.select(NodeId.PAGE_ID);
await editorService.update({ id: NodeId.PAGE_ID, isAbsoluteLayout: true, type: 'page' });
await editorService.update({ id: NodeId.PAGE_ID, isAbsoluteLayout: true, type: NodeType.PAGE });
await editorService.select(NodeId.NODE_ID);
const node = editorService.get<MNode>('node');
await editorService.alignCenter(node);

View File

@ -16,7 +16,8 @@
* limitations under the License.
*/
import { MNode } from '@tmagic/schema';
import type { MNode } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import * as editor from '@editor/utils/editor';
@ -30,12 +31,12 @@ describe('util form', () => {
it('getPageList', () => {
const pageList = editor.getPageList({
id: 'app_1',
type: 'app',
type: NodeType.ROOT,
items: [
{
id: 'page_1',
name: 'index',
type: 'page',
type: NodeType.PAGE,
items: [],
},
],
@ -49,7 +50,7 @@ describe('util form', () => {
{
id: 'page_1',
name: 'index',
type: 'page',
type: NodeType.PAGE,
items: [],
},
]);
@ -79,7 +80,7 @@ describe('setNewItemId', () => {
it('items', () => {
const config = {
id: 1,
type: 'page',
type: NodeType.PAGE,
items: [
{
type: 'text',
@ -95,7 +96,7 @@ describe('setNewItemId', () => {
it('pop', () => {
const config = {
id: 1,
type: 'page',
type: NodeType.PAGE,
items: [
{
type: 'button',
@ -158,7 +159,7 @@ describe('getNodeIndex', () => {
},
{
id: 2,
type: 'page',
type: NodeType.PAGE,
items: [
{
type: 'text',
@ -179,7 +180,7 @@ describe('getNodeIndex', () => {
},
{
id: 2,
type: 'page',
type: NodeType.PAGE,
items: [
{
type: 'text',

View File

@ -16,6 +16,12 @@
* limitations under the License.
*/
export enum NodeType {
CONTAINER = 'container',
PAGE = 'page',
ROOT = 'app',
}
export type Id = string | number;
export interface EventItemConfig {
@ -47,19 +53,19 @@ export interface MComponent {
export interface MContainer extends MComponent {
/** 容器类型,默认为'container' */
type: 'container' | string;
type: NodeType.CONTAINER | string;
/** 容器子元素 */
items: (MComponent | MContainer)[];
}
export interface MPage extends MContainer {
/** 页面类型 */
type: 'page';
type: NodeType.PAGE;
}
export interface MApp extends MComponent {
/** App页面类型app作为整个结构的根节点有且只有一个 */
type: 'app';
type: NodeType.ROOT;
/** */
items: MPage[];
}

View File

@ -31,6 +31,7 @@ import { ElMessage } from 'element-plus';
import serialize from 'serialize-javascript';
import type { MenuBarData, MoveableOptions, TMagicEditor } from '@tmagic/editor';
import { NodeType } from '@tmagic/schema';
import StageCore from '@tmagic/stage';
import { asyncLoadJs } from '@tmagic/utils';
@ -155,7 +156,7 @@ export default defineComponent({
if (!node) return options;
const isPage = node.type === 'page';
const isPage = node.type === NodeType.PAGE;
options.draggable = !isPage;
options.resizable = !isPage;