style(editor): 完善service use-plugin的ts类型定义

This commit is contained in:
roymondchen 2024-03-05 14:55:41 +08:00
parent 5cf137e5e8
commit 16e45cb45d
16 changed files with 263 additions and 156 deletions

View File

@ -84,6 +84,7 @@
"rimraf": "^3.0.2",
"sass": "^1.35.1",
"tsc-alias": "^1.8.5",
"type-fest": "^4.10.3",
"typescript": "^5.0.4",
"vite": "^5.0.7",
"vue-tsc": "^1.8.25"

View File

@ -194,6 +194,9 @@ export default class extends EventEmitter {
});
}
/**
* @deprecated 使usePlugin代替
*/
public use(options: Record<string, Function>) {
Object.entries(options).forEach(([methodName, method]: [string, Function]) => {
if (typeof method === 'function') this.middleware[methodName].push(method);

View File

@ -18,16 +18,24 @@
import { reactive } from 'vue';
import { keys, pick } from 'lodash-es';
import type { Writable } from 'type-fest';
import type { ColumnConfig } from '@tmagic/form';
import type { CodeBlockContent, CodeBlockDSL, Id } from '@tmagic/schema';
import type { CodeState } from '@editor/type';
import type { AsyncHookPlugin, CodeState } from '@editor/type';
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
import { getConfig } from '@editor/utils/config';
import BaseService from './BaseService';
const canUsePluginMethods = {
async: ['setCodeDslById', 'setEditStatus', 'setCombineIds', 'setUndeleteableList', 'deleteCodeDslByIds'] as const,
sync: [],
};
type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
class CodeBlock extends BaseService {
private state = reactive<CodeState>({
codeDsl: null,
@ -38,13 +46,7 @@ class CodeBlock extends BaseService {
});
constructor() {
super([
{ name: 'setCodeDslById', isAsync: true },
{ name: 'setEditStatus', isAsync: true },
{ name: 'setCombineIds', isAsync: true },
{ name: 'setUndeleteableList', isAsync: true },
{ name: 'deleteCodeDslByIds', isAsync: true },
]);
super(canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })));
}
/**
@ -243,6 +245,10 @@ class CodeBlock extends BaseService {
this.removeAllListeners();
this.removeAllPlugins();
}
public usePlugin(options: AsyncHookPlugin<AsyncMethodName, CodeBlock>): void {
super.usePlugin(options);
}
}
export type CodeBlockService = CodeBlock;

View File

@ -1,12 +1,13 @@
import { reactive } from 'vue';
import { cloneDeep } from 'lodash-es';
import { Writable } from 'type-fest';
import type { EventOption } from '@tmagic/core';
import type { FormConfig } from '@tmagic/form';
import type { DataSourceSchema } from '@tmagic/schema';
import { guid } from '@tmagic/utils';
import type { DatasourceTypeOption } from '@editor/type';
import type { DatasourceTypeOption, SyncHookPlugin } from '@editor/type';
import { getFormConfig, getFormValue } from '@editor/utils/data-source';
import BaseService from './BaseService';
@ -22,6 +23,27 @@ interface State {
}
type StateKey = keyof State;
const canUsePluginMethods = {
async: [],
sync: [
'getFormConfig',
'setFormConfig',
'getFormValue',
'setFormValue',
'getFormEvent',
'setFormEvent',
'getFormMethod',
'setFormMethod',
'add',
'update',
'remove',
'createId',
] as const,
};
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
class DataSource extends BaseService {
private state = reactive<State>({
datasourceTypeList: [],
@ -34,20 +56,7 @@ class DataSource extends BaseService {
});
constructor() {
super([
{ name: 'getFormConfig', isAsync: false },
{ name: 'setFormConfig', isAsync: false },
{ name: 'getFormValue', isAsync: false },
{ name: 'setFormValue', isAsync: false },
{ name: 'getFormEvent', isAsync: false },
{ name: 'setFormEvent', isAsync: false },
{ name: 'getFormMethod', isAsync: false },
{ name: 'setFormMethod', isAsync: false },
{ name: 'add', isAsync: false },
{ name: 'update', isAsync: false },
{ name: 'remove', isAsync: false },
{ name: 'createId', isAsync: false },
]);
super(canUsePluginMethods.sync.map((methodName) => ({ name: methodName, isAsync: false })));
}
public set<K extends StateKey, T extends State[K]>(name: K, value: T) {
@ -123,6 +132,10 @@ class DataSource extends BaseService {
this.emit('remove', id);
}
public createId(): string {
return `ds_${guid()}`;
}
public getDataSourceById(id: string) {
return this.get('dataSources').find((ds) => ds.id === id);
}
@ -137,8 +150,8 @@ class DataSource extends BaseService {
this.removeAllPlugins();
}
private createId(): string {
return `ds_${guid()}`;
public usePlugin(options: SyncHookPlugin<SyncMethodName, DataSource>): void {
super.usePlugin(options);
}
}

View File

@ -18,6 +18,7 @@
import { reactive, toRaw } from 'vue';
import { cloneDeep, get, isObject, mergeWith, uniq } from 'lodash-es';
import { Writable } from 'type-fest';
import { DepTargetType } from '@tmagic/dep';
import type { Id, MApp, MComponent, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
@ -29,7 +30,15 @@ import propsService from '@editor/services//props';
import depService from '@editor/services/dep';
import historyService from '@editor/services/history';
import storageService, { Protocol } from '@editor/services/storage';
import type { AddMNode, EditorNodeInfo, PastePosition, StepValue, StoreState, StoreStateKey } from '@editor/type';
import type {
AddMNode,
AsyncHookPlugin,
EditorNodeInfo,
PastePosition,
StepValue,
StoreState,
StoreStateKey,
} from '@editor/type';
import { LayerOffset, Layout } from '@editor/type';
import {
change2Fixed,
@ -46,6 +55,36 @@ import {
} from '@editor/utils/editor';
import { beforePaste, getAddParent } from '@editor/utils/operator';
const canUsePluginMethods = {
async: [
'getLayout',
'highlight',
'select',
'multiSelect',
'doAdd',
'add',
'doRemove',
'remove',
'doUpdate',
'update',
'sort',
'copy',
'paste',
'doPaste',
'doAlignCenter',
'alignCenter',
'moveLayer',
'moveToContainer',
'dragTo',
'undo',
'redo',
'move',
] as const,
sync: [],
};
type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
class Editor extends BaseService {
public state: StoreState = reactive({
root: null,
@ -65,29 +104,7 @@ class Editor extends BaseService {
constructor() {
super(
[
{ name: 'getLayout', isAsync: true },
{ name: 'select', isAsync: true },
{ name: 'doAdd', isAsync: true },
{ name: 'add', isAsync: true },
{ name: 'doRemove', isAsync: true },
{ name: 'remove', isAsync: true },
{ name: 'doUpdate', isAsync: true },
{ name: 'update', isAsync: true },
{ name: 'sort', isAsync: true },
{ name: 'copy', isAsync: true },
{ name: 'paste', isAsync: true },
{ name: 'doPaste', isAsync: true },
{ name: 'doAlignCenter', isAsync: true },
{ name: 'alignCenter', isAsync: true },
{ name: 'moveLayer', isAsync: true },
{ name: 'moveToContainer', isAsync: true },
{ name: 'move', isAsync: true },
{ name: 'undo', isAsync: true },
{ name: 'redo', isAsync: true },
{ name: 'highlight', isAsync: true },
{ name: 'dragTo', isAsync: true },
],
canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })),
// 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
['select', 'update', 'moveLayer'],
);
@ -696,7 +713,7 @@ class Editor extends BaseService {
public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
propsService.clearRelateId();
const pasteConfigs = await beforePaste(position, cloneDeep(config));
const pasteConfigs = beforePaste(position, cloneDeep(config));
return pasteConfigs;
}
@ -985,6 +1002,10 @@ class Editor extends BaseService {
this.get('modifiedNodeIds').clear();
}
public usePlugin(options: AsyncHookPlugin<AsyncMethodName, Editor>): void {
super.usePlugin(options);
}
private addModifiedNodeId(id: Id) {
if (!this.isHistoryStateChange) {
this.get('modifiedNodeIds').set(id, id);

View File

@ -18,6 +18,7 @@
import { reactive } from 'vue';
import { cloneDeep, mergeWith } from 'lodash-es';
import { Writable } from 'type-fest';
import { DepTargetType } from '@tmagic/dep';
import type { FormConfig } from '@tmagic/form';
@ -26,11 +27,26 @@ import { getValueByKeyPath, guid, setValueByKeyPath, toLine } from '@tmagic/util
import depService from '@editor/services/dep';
import editorService from '@editor/services/editor';
import type { PropsState } from '@editor/type';
import type { AsyncHookPlugin, PropsState, SyncHookPlugin } from '@editor/type';
import { fillConfig } from '@editor/utils/props';
import BaseService from './BaseService';
const canUsePluginMethods = {
async: [
'setPropsConfig',
'getPropsConfig',
'setPropsValue',
'getPropsValue',
'fillConfig',
'getDefaultPropsValue',
] as const,
sync: ['createId', 'setNewItemId'] as const,
};
type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
class Props extends BaseService {
private state = reactive<PropsState>({
propsConfigMap: {},
@ -40,14 +56,8 @@ class Props extends BaseService {
constructor() {
super([
{ name: 'setPropsConfig', isAsync: true },
{ name: 'getPropsConfig', isAsync: true },
{ name: 'setPropsValue', isAsync: true },
{ name: 'getPropsValue', isAsync: true },
{ name: 'createId', isAsync: false },
{ name: 'setNewItemId', isAsync: true },
{ name: 'fillConfig', isAsync: true },
{ name: 'getDefaultPropsValue', isAsync: true },
...canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })),
...canUsePluginMethods.sync.map((methodName) => ({ name: methodName, isAsync: false })),
]);
}
@ -62,11 +72,6 @@ class Props extends BaseService {
return fillConfig(config, typeof labelWidth !== 'function' ? labelWidth : '80px');
}
/**
*
* @param type
* @param config
*/
public async setPropsConfig(type: string, config: FormConfig) {
this.state.propsConfigMap[type] = await this.fillConfig(Array.isArray(config) ? config : [config]);
}
@ -115,16 +120,14 @@ class Props extends BaseService {
return value;
}
const [id, defaultPropsValue, data] = await Promise.all([
this.createId(type),
this.getDefaultPropsValue(type),
this.setNewItemId(
cloneDeep({
type,
...defaultValue,
} as any),
),
]);
const id = this.createId(type);
const defaultPropsValue = this.getDefaultPropsValue(type);
const data = this.setNewItemId(
cloneDeep({
type,
...defaultValue,
} as any),
);
return {
id,
@ -133,7 +136,7 @@ class Props extends BaseService {
};
}
public async createId(type: string | number): Promise<string> {
public createId(type: string | number): string {
return `${type}_${guid()}`;
}
@ -144,16 +147,16 @@ class Props extends BaseService {
* @param {Boolean} force ID
*/
/* eslint no-param-reassign: ["error", { "props": false }] */
public async setNewItemId(config: MNode, force = true) {
public setNewItemId(config: MNode, force = true) {
if (force || editorService.getNodeById(config.id)) {
const newId = await this.createId(config.type || 'component');
const newId = this.createId(config.type || 'component');
this.setRelateId(config.id, newId);
config.id = newId;
}
if (config.items && Array.isArray(config.items)) {
for (const item of config.items) {
await this.setNewItemId(item);
this.setNewItemId(item);
}
}
@ -165,7 +168,7 @@ class Props extends BaseService {
* @param type
* @returns Object
*/
public async getDefaultPropsValue(type: string) {
public getDefaultPropsValue(type: string) {
return ['page', 'container'].includes(type)
? {
type,
@ -227,6 +230,10 @@ class Props extends BaseService {
this.removeAllPlugins();
}
public usePlugin(options: AsyncHookPlugin<AsyncMethodName, Props> & SyncHookPlugin<SyncMethodName, Props>): void {
super.usePlugin(options);
}
/**
* setNewItemId前后映射关系
* @param oldId ID

View File

@ -1,11 +1,19 @@
import { reactive } from 'vue';
import type { Writable } from 'type-fest';
import StageCore from '@tmagic/stage';
import { useStage } from '@editor/hooks/use-stage';
import BaseService from '@editor/services//BaseService';
import editorService from '@editor/services//editor';
import type { StageOptions, StageOverlayState } from '@editor/type';
import type { StageOptions, StageOverlayState, SyncHookPlugin } from '@editor/type';
const canUsePluginMethods = {
async: [],
sync: ['openOverlay', 'closeOverlay', 'updateOverlay', 'createStage'] as const,
};
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
class StageOverlay extends BaseService {
private state: StageOverlayState = reactive({
@ -20,12 +28,7 @@ class StageOverlay extends BaseService {
});
constructor() {
super([
{ name: 'openOverlay', isAsync: false },
{ name: 'closeOverlay', isAsync: false },
{ name: 'updateOverlay', isAsync: false },
{ name: 'createStage', isAsync: false },
]);
super(canUsePluginMethods.sync.map((methodName) => ({ name: methodName, isAsync: false })));
this.get('wrapDiv').classList.add('tmagic-editor-sub-stage-wrap');
}
@ -111,6 +114,10 @@ class StageOverlay extends BaseService {
});
}
public usePlugin(options: SyncHookPlugin<SyncMethodName, StageOverlay>): void {
super.usePlugin(options);
}
private createContentEl() {
const sourceEl = this.get('sourceEl');
if (!sourceEl) return;

View File

@ -1,5 +1,7 @@
import serialize from 'serialize-javascript';
import type { Writable } from 'type-fest';
import type { SyncHookPlugin } from '@editor/type';
import { getConfig } from '@editor/utils/config';
import BaseService from './BaseService';
@ -17,6 +19,13 @@ export enum Protocol {
BOOLEAN = 'boolean',
}
const canUsePluginMethods = {
async: [],
sync: ['getStorage', 'getNamespace', 'clear', 'getItem', 'removeItem', 'setItem'] as const,
};
type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
/**
*
*/
@ -25,14 +34,7 @@ export class WebStorage extends BaseService {
private namespace = 'tmagic';
constructor() {
super([
{ name: 'getStorage', isAsync: false },
{ name: 'getNamespace', isAsync: false },
{ name: 'clear', isAsync: false },
{ name: 'getItem', isAsync: false },
{ name: 'removeItem', isAsync: false },
{ name: 'setItem', isAsync: false },
]);
super(canUsePluginMethods.sync.map((methodName) => ({ name: methodName, isAsync: false })));
}
/**
@ -123,6 +125,10 @@ export class WebStorage extends BaseService {
this.removeAllPlugins();
}
public usePlugin(options: SyncHookPlugin<SyncMethodName, WebStorage>): void {
super.usePlugin(options);
}
private getValueAndProtocol(value: string | null) {
let protocol = '';

View File

@ -17,11 +17,12 @@
*/
import { reactive } from 'vue';
import type { Writable } from 'type-fest';
import { convertToNumber } from '@tmagic/utils';
import editorService from '@editor/services/editor';
import type { StageRect, UiState } from '@editor/type';
import type { AsyncHookPlugin, StageRect, UiState } from '@editor/type';
import BaseService from './BaseService';
@ -50,12 +51,16 @@ const state = reactive<UiState>({
hideSlideBar: false,
});
const canUsePluginMethods = {
async: ['zoom', 'calcZoom'] as const,
sync: [] as const,
};
type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
class Ui extends BaseService {
constructor() {
super([
{ name: 'zoom', isAsync: true },
{ name: 'calcZoom', isAsync: true },
]);
super(canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })));
}
public set<K extends keyof UiState, T extends UiState[K]>(name: K, value: T) {
@ -134,6 +139,10 @@ class Ui extends BaseService {
this.removeAllPlugins();
}
public usePlugin(options: AsyncHookPlugin<AsyncMethodName, Ui>): void {
super.usePlugin(options);
}
private async setStageRect(value: StageRect) {
state.stageRect = {
...state.stageRect,

View File

@ -17,6 +17,7 @@
*/
import type { Component } from 'vue';
import type { PascalCasedProperties } from 'type-fest';
import type { ColumnConfig, FilterFunction, FormConfig, FormItem } from '@tmagic/form';
import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
@ -670,3 +671,35 @@ export interface TreeNodeData {
items?: TreeNodeData[];
[key: string]: any;
}
export type AsyncBeforeHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
[K in Value[number]]?: (...args: Parameters<C[K]>) => Promise<Parameters<C[K]>>;
};
export type AsyncAfterHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
[K in Value[number]]?: (result: Awaited<ReturnType<C[K]>>, ...args: Parameters<C[K]>) => ReturnType<C[K]>;
};
export type SyncBeforeHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
[K in Value[number]]?: (...args: Parameters<C[K]>) => Parameters<C[K]>;
};
export type SyncAfterHook<Value extends Array<string>, C extends Record<Value[number], (...args: any) => any>> = {
[K in Value[number]]?: (result: ReturnType<C[K]>, ...args: Parameters<C[K]>) => ReturnType<C[K]>;
};
export type AddPrefixToObject<T, P extends string> = {
[K in keyof T as K extends string ? `${P}${K}` : never]: T[K];
};
export type AsyncHookPlugin<
T extends Array<string>,
C extends Record<T[number], (...args: any) => any>,
> = AddPrefixToObject<PascalCasedProperties<AsyncBeforeHook<T, C>>, 'before'> &
AddPrefixToObject<PascalCasedProperties<AsyncAfterHook<T, C>>, 'after'>;
export type SyncHookPlugin<
T extends Array<string>,
C extends Record<T[number], (...args: any) => any>,
> = AddPrefixToObject<PascalCasedProperties<SyncBeforeHook<T, C>>, 'before'> &
AddPrefixToObject<PascalCasedProperties<SyncAfterHook<T, C>>, 'after'>;

View File

@ -15,55 +15,53 @@ import { generatePageNameByApp, getInitPositionStyle } from '@editor/utils/edito
* @param config ()
* @returns
*/
export const beforePaste = async (position: PastePosition, config: MNode[]): Promise<MNode[]> => {
export const beforePaste = (position: PastePosition, config: MNode[]): MNode[] => {
if (!config[0]?.style) return config;
const curNode = editorService.get('node');
// 将数组中第一个元素的坐标作为参照点
const { left: referenceLeft, top: referenceTop } = config[0].style;
// 坐标校准后的粘贴数据
const pasteConfigs: MNode[] = await Promise.all(
config.map(async (configItem: MNode): Promise<MNode> => {
// 解构 position 对象,从 position 删除 offsetX、offsetY字段
const { offsetX = 0, offsetY = 0, ...positionClone } = position;
let pastePosition = positionClone;
const pasteConfigs: MNode[] = config.map((configItem: MNode): MNode => {
// 解构 position 对象,从 position 删除 offsetX、offsetY字段
const { offsetX = 0, offsetY = 0, ...positionClone } = position;
let pastePosition = positionClone;
if (!isEmpty(pastePosition) && curNode?.items) {
// 如果没有传入粘贴坐标则可能为键盘操作,不再转换
// 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
pastePosition = getPositionInContainer(pastePosition, curNode.id);
if (!isEmpty(pastePosition) && curNode?.items) {
// 如果没有传入粘贴坐标则可能为键盘操作,不再转换
// 如果粘贴时选中了容器,则将元素粘贴到容器内,坐标需要转换为相对于容器的坐标
pastePosition = getPositionInContainer(pastePosition, curNode.id);
}
// 将所有待粘贴元素坐标相对于多选第一个元素坐标重新计算,以保证多选粘贴后元素间距不变
if (pastePosition.left && configItem.style?.left) {
pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
}
if (pastePosition.top && configItem.style?.top) {
pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
}
const pasteConfig = propsService.setNewItemId(configItem, false);
if (pasteConfig.style) {
const { left, top } = pasteConfig.style;
// 判断能转换为数字时,做粘贴偏移量计算
if (typeof left === 'number' || (!!left && !isNaN(Number(left)))) {
pasteConfig.style.left = Number(left) + offsetX;
}
if (typeof top === 'number' || (!!top && !isNaN(Number(top)))) {
pasteConfig.style.top = Number(top) + offsetY;
}
// 将所有待粘贴元素坐标相对于多选第一个元素坐标重新计算,以保证多选粘贴后元素间距不变
if (pastePosition.left && configItem.style?.left) {
pastePosition.left = configItem.style.left - referenceLeft + pastePosition.left;
}
if (pastePosition.top && configItem.style?.top) {
pastePosition.top = configItem.style?.top - referenceTop + pastePosition.top;
}
const pasteConfig = await propsService.setNewItemId(configItem, false);
if (pasteConfig.style) {
const { left, top } = pasteConfig.style;
// 判断能转换为数字时,做粘贴偏移量计算
if (typeof left === 'number' || (!!left && !isNaN(Number(left)))) {
pasteConfig.style.left = Number(left) + offsetX;
}
if (typeof top === 'number' || (!!top && !isNaN(Number(top)))) {
pasteConfig.style.top = Number(top) + offsetY;
}
pasteConfig.style = {
...pasteConfig.style,
...pastePosition,
};
}
const root = editorService.get('root');
if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
}
return pasteConfig as MNode;
}),
);
pasteConfig.style = {
...pasteConfig.style,
...pastePosition,
};
}
const root = editorService.get('root');
if ((isPage(pasteConfig) || isPageFragment(pasteConfig)) && root) {
pasteConfig.name = generatePageNameByApp(root, isPage(pasteConfig) ? NodeType.PAGE : NodeType.PAGE_FRAGMENT);
}
return pasteConfig as MNode;
});
return pasteConfigs;
};

View File

@ -328,7 +328,7 @@ export const displayTabConfig: TabPaneConfig = {
* @param config
* @returns Object
*/
export const fillConfig = (config: FormConfig = [], labelWidth = '80px') => [
export const fillConfig = (config: FormConfig = [], labelWidth = '80px'): FormConfig => [
{
type: 'tab',
labelWidth,

View File

@ -11,17 +11,17 @@ test('createId', async () => {
});
describe('setNewItemId', () => {
test('普通', async () => {
test('普通', () => {
const config = {
id: 1,
type: 'text',
};
// 将组件与组件的子元素配置中的id都设置成一个新的ID
await props.setNewItemId(config);
props.setNewItemId(config);
expect(config.id === 1).toBeFalsy();
});
test('items', async () => {
test('items', () => {
const config = {
id: 1,
type: NodeType.PAGE,
@ -32,7 +32,7 @@ describe('setNewItemId', () => {
},
],
};
await props.setNewItemId(config);
props.setNewItemId(config);
expect(config.id === 1).toBeFalsy();
expect(config.items[0].id === 2).toBeFalsy();
});

View File

@ -227,7 +227,7 @@ asyncLoadJs(`${VITE_ENTRY_PATH}/ds-value/index.umd.cjs`).then(() => {
save();
editorService.usePlugin({
beforeDoAdd: (config: MNode, parent?: MContainer | null) => {
beforeDoAdd: async (config: MNode, parent: MContainer) => {
if (config.type === 'overlay') {
config.style = {
...config.style,
@ -235,7 +235,7 @@ editorService.usePlugin({
top: 0,
};
return [config, editorService.get('page')];
return [config, editorService.get('page') as MContainer];
}
return [config, parent];

11
pnpm-lock.yaml generated
View File

@ -377,6 +377,9 @@ importers:
tsc-alias:
specifier: ^1.8.5
version: 1.8.5
type-fest:
specifier: ^4.10.3
version: 4.11.1
typescript:
specifier: ^5.0.4
version: 5.0.4
@ -9552,7 +9555,7 @@ packages:
dependencies:
find-up: 6.3.0
read-pkg: 8.1.0
type-fest: 4.6.0
type-fest: 4.11.1
dev: true
/read-pkg-up@7.0.1:
@ -9581,7 +9584,7 @@ packages:
'@types/normalize-package-data': 2.4.1
normalize-package-data: 6.0.0
parse-json: 7.1.1
type-fest: 4.6.0
type-fest: 4.11.1
dev: true
/readable-stream@3.6.2:
@ -10491,8 +10494,8 @@ packages:
engines: {node: '>=14.16'}
dev: true
/type-fest@4.6.0:
resolution: {integrity: sha512-rLjWJzQFOq4xw7MgJrCZ6T1jIOvvYElXT12r+y0CC6u67hegDHaxcPqb2fZHOGlqxugGQPNB1EnTezjBetkwkw==}
/type-fest@4.11.1:
resolution: {integrity: sha512-MFMf6VkEVZAETidGGSYW2B1MjXbGX+sWIywn2QPEaJ3j08V+MwVRHMXtf2noB8ENJaD0LIun9wh5Z6OPNf1QzQ==}
engines: {node: '>=16'}
dev: true

View File

@ -21,7 +21,7 @@ export const useRuntime = ({
fillConfig = (config) => config,
}: {
plugins?: Plugin[];
fillConfig?: (config: FormConfig) => FormConfig;
fillConfig?: (config: FormConfig, mForm: any) => FormConfig;
} = {}) => {
const render = (stage: StageCore) => {
injectStyle(stage.renderer.getDocument()!, cssStyle);
@ -60,24 +60,24 @@ export const useRuntime = ({
};
propsService.usePlugin({
afterFillConfig(config: FormConfig, itemConfig: FormConfig) {
async afterFillConfig(config: FormConfig, itemConfig: FormConfig, labelWidth = '80px') {
return [
{
type: 'tab',
items: [
{
title: '属性',
labelWidth: '80px',
labelWidth,
items: [...commonConfig, ...itemConfig],
},
],
},
];
] as FormConfig;
},
});
editorService.usePlugin({
afterGetLayout() {
async afterGetLayout() {
return Layout.RELATIVE;
},
});