feat: 添加组件支持添加组合

This commit is contained in:
roymondchen 2022-06-13 16:42:52 +08:00 committed by jia000
parent c8c692b69c
commit 5e3125706c
7 changed files with 132 additions and 120 deletions

View File

@ -38,7 +38,6 @@ import {
initPosition,
isFixed,
setLayout,
setNewItemId,
} from '@editor/utils/editor';
import { log } from '@editor/utils/logger';
@ -495,7 +494,7 @@ class Editor extends BaseService {
return;
}
setNewItemId(config, this.get('root'));
await propsService.setNewItemId(config, this.get('root'));
if (config.style) {
config.style = {
...config.style,

View File

@ -17,11 +17,12 @@
*/
import { reactive } from 'vue';
import { cloneDeep, mergeWith } from 'lodash-es';
import { cloneDeep, mergeWith, random } from 'lodash-es';
import type { FormConfig } from '@tmagic/form';
import type { MComponent, MNode } from '@tmagic/schema';
import { toLine } from '@tmagic/utils';
import type { Id, MComponent, MNode, MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import { isPop, toLine } from '@tmagic/utils';
import type { PropsState } from '@editor/type';
import { DEFAULT_CONFIG, fillConfig, getDefaultPropsValue } from '@editor/utils/props';
@ -35,7 +36,7 @@ class Props extends BaseService {
});
constructor() {
super(['setPropsConfig', 'getPropsConfig', 'setPropsValue', 'getPropsValue']);
super(['setPropsConfig', 'getPropsConfig', 'setPropsValue', 'getPropsValue', 'createId', 'setNewItemId']);
}
public setPropsConfigs(configs: Record<string, FormConfig>) {
@ -87,7 +88,7 @@ class Props extends BaseService {
* @param type
* @returns
*/
public async getPropsValue(type: string, defaultValue = {}) {
public async getPropsValue(type: string, defaultValue: Record<string, any> = {}) {
if (type === 'area') {
const value = (await this.getPropsValue('button')) as MComponent;
value.className = 'action-area';
@ -98,13 +99,67 @@ class Props extends BaseService {
return value;
}
const data = cloneDeep(defaultValue as any);
await this.setNewItemId(data);
return {
...getDefaultPropsValue(type),
...mergeWith(cloneDeep(this.state.propsValueMap[type] || {}), cloneDeep(defaultValue)),
...getDefaultPropsValue(type, await this.createId(type)),
...mergeWith(cloneDeep(this.state.propsValueMap[type] || {}), data),
};
}
public async createId(type: string | number): Promise<string> {
return `${type}_${random(10000, false)}`;
}
/**
* id都设置成一个新的ID
* @param {Object} config
*/
/* eslint no-param-reassign: ["error", { "props": false }] */
public async setNewItemId(config: MNode, parent?: MPage) {
const oldId = config.id;
config.id = await this.createId(config.type || 'component');
// 只有弹窗在页面下的一级子元素才有效
if (isPop(config) && parent?.type === NodeType.PAGE) {
updatePopId(oldId, config.id, parent);
}
if (config.items && Array.isArray(config.items)) {
for (const item of config.items) {
await this.setNewItemId(item, config as MPage);
}
}
}
}
/**
* id换测复制出来的弹窗的id
* @param {number} oldId id
* @param {number} popId id
* @param {Object} pageConfig
*/
const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
pageConfig.items?.forEach((config) => {
if (config.pop === oldId) {
config.pop = popId;
return;
}
if (config.popId === oldId) {
config.popId = popId;
return;
}
if (Array.isArray(config.items)) {
updatePopId(oldId, popId, config as MPage);
}
});
};
export type PropsService = Props;
export default new Props();

View File

@ -16,9 +16,7 @@
* limitations under the License.
*/
import { random } from 'lodash-es';
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
import { NodeType } from '@tmagic/schema';
import type StageCore from '@tmagic/stage';
import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
@ -27,8 +25,6 @@ import { Layout } from '@editor/type';
export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
export const generateId = (type: string | number): string => `${type}_${random(10000, false)}`;
/**
*
* @param app DSL跟节点
@ -74,51 +70,6 @@ export const generatePageName = (pageNameList: string[]): string => {
*/
export const generatePageNameByApp = (app: MApp): string => generatePageName(getPageNameList(getPageList(app)));
/**
* id换测复制出来的弹窗的id
* @param {number} oldId id
* @param {number} popId id
* @param {Object} pageConfig
*/
const updatePopId = (oldId: Id, popId: Id, pageConfig: MPage) => {
pageConfig.items?.forEach((config) => {
if (config.pop === oldId) {
config.pop = popId;
return;
}
if (config.popId === oldId) {
config.popId = popId;
return;
}
if (Array.isArray(config.items)) {
updatePopId(oldId, popId, config as MPage);
}
});
};
/**
* id都设置成一个新的ID
* @param {Object} config
*/
/* eslint no-param-reassign: ["error", { "props": false }] */
export const setNewItemId = (config: MNode, parent?: MPage) => {
const oldId = config.id;
config.id = generateId(config.type || 'component');
config.name = `${config.name?.replace(/_(\d+)$/, '')}_${config.id}`;
// 只有弹窗在页面下的一级子元素才有效
if (isPop(config) && parent?.type === NodeType.PAGE) {
updatePopId(oldId, config.id, parent);
}
if (config.items && Array.isArray(config.items)) {
config.items.forEach((item) => setNewItemId(item, config as MPage));
}
};
/**
* @param {Object} node
* @returns {boolean}

View File

@ -20,7 +20,6 @@ import { FormConfig, FormState } from '@tmagic/form';
import editorService from '@editor/services/editor';
import eventsService from '@editor/services/events';
import { generateId } from '@editor/utils/editor';
/**
*
@ -244,9 +243,9 @@ export const DEFAULT_CONFIG: FormConfig = fillConfig([]);
* @param type
* @returns Object
*/
export const getDefaultPropsValue = (type: string) => ({
export const getDefaultPropsValue = (type: string, id: string) => ({
type,
id: generateId(type),
id,
style: {},
name: type,
});

View File

@ -0,0 +1,63 @@
import { describe, expect, test } from 'vitest';
import { NodeType } from '@tmagic/schema';
import props from '@editor/services/props';
test('createId', async () => {
const id = await props.createId('text');
console.log(id);
expect(id.startsWith('text')).toBeTruthy();
});
describe('setNewItemId', () => {
test('普通', async () => {
const config = {
id: 1,
type: 'text',
};
// 将组件与组件的子元素配置中的id都设置成一个新的ID
await props.setNewItemId(config);
expect(config.id === 1).toBeFalsy();
});
test('items', async () => {
const config = {
id: 1,
type: NodeType.PAGE,
items: [
{
type: 'text',
id: 2,
},
],
};
await props.setNewItemId(config);
expect(config.id === 1).toBeFalsy();
expect(config.items[0].id === 2).toBeFalsy();
});
test('pop', async () => {
const config = {
id: 1,
type: NodeType.PAGE,
items: [
{
type: 'button',
id: 2,
pop: 3,
},
{
type: 'pop',
id: 3,
},
],
};
await props.setNewItemId(config);
expect(config.items[0].pop === 3).toBeFalsy();
expect(config.items[1].id === 3).toBeFalsy();
expect(config.items[1].id === config.items[0].pop).toBeTruthy();
});
});

View File

@ -23,12 +23,6 @@ import { NodeType } from '@tmagic/schema';
import * as editor from '@editor/utils/editor';
describe('util form', () => {
test('generateId', () => {
const id = editor.generateId('text');
expect(id.startsWith('text')).toBeTruthy();
});
test('getPageList', () => {
const pageList = editor.getPageList({
id: 'app_1',
@ -67,56 +61,6 @@ describe('util form', () => {
});
});
describe('setNewItemId', () => {
test('普通', () => {
const config = {
id: 1,
type: 'text',
};
// 将组件与组件的子元素配置中的id都设置成一个新的ID
editor.setNewItemId(config);
expect(config.id === 1).toBeFalsy();
});
test('items', () => {
const config = {
id: 1,
type: NodeType.PAGE,
items: [
{
type: 'text',
id: 2,
},
],
};
editor.setNewItemId(config);
expect(config.id === 1).toBeFalsy();
expect(config.items[0].id === 2).toBeFalsy();
});
test('pop', () => {
const config = {
id: 1,
type: NodeType.PAGE,
items: [
{
type: 'button',
id: 2,
pop: 3,
},
{
type: 'pop',
id: 3,
},
],
};
editor.setNewItemId(config);
expect(config.items[0].pop === 3).toBeFalsy();
expect(config.items[1].id === 3).toBeFalsy();
expect(config.items[1].id === config.items[0].pop).toBeTruthy();
});
});
describe('isFixed', () => {
test('true', () => {
expect(

View File

@ -44,7 +44,8 @@ describe('util form', () => {
});
test('getDefaultValue', () => {
const value = props.getDefaultPropsValue('text');
expect(value.id.startsWith('text')).toBeTruthy();
const value = props.getDefaultPropsValue('text', '1');
expect(value.id).toBe('1');
expect(value.type).toBe('text');
});
});