From c743ae2efd472dfab2a980de61b397c800cd6598 Mon Sep 17 00:00:00 2001 From: liujuping Date: Tue, 14 Mar 2023 18:56:46 +0800 Subject: [PATCH] feat: fix designer:entry ts errors --- docs/docs/specs/material-spec.md | 10 +- packages/designer/src/component-meta.ts | 11 +- packages/designer/src/designer/designer.ts | 2 +- .../designer/src/designer/setting/index.ts | 3 +- .../designer/setting/setting-entry-type.ts | 45 ++++ .../src/designer/setting/setting-entry.ts | 26 --- .../src/designer/setting/setting-field.ts | 50 ++++- .../designer/setting/setting-prop-entry.ts | 61 ++++-- .../src/designer/setting/setting-top-entry.ts | 52 +++-- packages/designer/src/document/node/node.ts | 24 ++- .../designer/setting/setting-field.test.ts | 2 +- .../src/components/field/index.ts | 2 +- .../src/components/settings/settings-pane.tsx | 18 +- .../src/transducers/addon-combine.ts | 6 +- .../engine/src/modules/shell-model-factory.ts | 11 +- packages/engine/src/modules/symbols.ts | 4 +- packages/shell/src/index.ts | 5 +- packages/shell/src/model/index.ts | 2 +- packages/shell/src/model/props.ts | 2 +- ...setting-prop-entry.ts => setting-field.ts} | 107 +++++----- packages/shell/src/model/setting-top-entry.ts | 20 +- packages/shell/src/symbols.ts | 2 +- packages/types/src/shell-model-factory.ts | 5 +- packages/types/src/shell/model/index.ts | 1 - packages/types/src/shell/model/props.ts | 4 +- .../types/src/shell/model/setting-entry.ts | 20 -- .../types/src/shell/model/setting-field.ts | 197 +++++++++++++++++- .../src/shell/model/setting-prop-entry.ts | 188 +---------------- .../types/src/shell/model/setting-target.ts | 105 +--------- .../src/shell/model/setting-top-entry.ts | 17 +- packages/types/src/shell/type/advanced.ts | 4 +- .../types/src/shell/type/dynamic-props.ts | 4 +- .../types/src/shell/type/field-extra-props.ts | 12 +- packages/types/src/shell/type/metadata.ts | 6 +- .../types/src/shell/type/setter-config.ts | 7 +- 35 files changed, 533 insertions(+), 502 deletions(-) create mode 100644 packages/designer/src/designer/setting/setting-entry-type.ts delete mode 100644 packages/designer/src/designer/setting/setting-entry.ts rename packages/shell/src/model/{setting-prop-entry.ts => setting-field.ts} (56%) delete mode 100644 packages/types/src/shell/model/setting-entry.ts diff --git a/docs/docs/specs/material-spec.md b/docs/docs/specs/material-spec.md index 3bee847c0..8b7928430 100644 --- a/docs/docs/specs/material-spec.md +++ b/docs/docs/specs/material-spec.md @@ -833,11 +833,11 @@ props 数组下对象字段描述: | name | 属性名 | String | type = 'field' 生效 | | defaultValue | 默认值 | Any(视字段类型而定) | type = 'field' 生效 | | supportVariable | 是否支持配置变量 | Boolean | type = 'field' 生效 | -| condition | 配置当前 prop 是否展示 | (target: SettingTarget) => boolean; | - | +| condition | 配置当前 prop 是否展示 | (target: IPublicModelSettingField) => boolean; | - | | setter | 单个控件 (setter) 描述,搭建基础协议组件的描述对象,支持 JSExpression / JSFunction / JSSlot | `String\|Object\|Function` | type = 'field' 生效 | | extraProps | 其他配置属性(不做流通要求) | Object | 其他配置 | -| extraProps.getValue | setter 渲染时被调用,setter 会根据该函数的返回值设置 setter 当前值 | Function | (target: SettingTarget, value: any) => any; | -| extraProps.setValue | setter 内容修改时调用,开发者可在该函数内部修改节点 schema 或者进行其他操作 | Function | (target: SettingTarget, value: any) => void; | +| extraProps.getValue | setter 渲染时被调用,setter 会根据该函数的返回值设置 setter 当前值 | Function | (target: IPublicModelSettingField, value: any) => any; | +| extraProps.setValue | setter 内容修改时调用,开发者可在该函数内部修改节点 schema 或者进行其他操作 | Function | (target: IPublicModelSettingField, value: any) => void; | 根据属性值类型 propType,确定对应控件类型 (setter) 。 @@ -922,7 +922,7 @@ props 数组下对象字段描述: | 字段 | 用途 | 类型 | 备注 | | ------------------------------- | --------------------------------------------------------------------------------------------------- | ------- | --- | -|initialChildren | 组件拖入“设计器”时根据此配置自动生成 children 节点 schema |NodeData[]/Function NodeData[] | ((target: SettingTarget) => NodeData[]);| +|initialChildren | 组件拖入“设计器”时根据此配置自动生成 children 节点 schema |NodeData[]/Function NodeData[] | ((target: IPublicModelSettingField) => NodeData[]);| |getResizingHandlers| 用于配置设计器中组件 resize 操作工具的样式和内容 | Function| (currentNode: any) => Array<{ type: 'N' | 'W' | 'S' | 'E' | 'NW' | 'NE' | 'SE' | 'SW'; content?: ReactElement; propTarget?: string; appearOn?: 'mouse-enter' | 'mouse-hover' | 'selected' | 'always'; }> / ReactElement[]; |callbacks| 配置 callbacks 可捕获引擎抛出的一些事件,例如 onNodeAdd、onResize 等 | Callback| - |callbacks.onNodeAdd| 在容器中拖入组件时触发的事件回调 | Function| (e: MouseEvent, currentNode: any) => any @@ -1098,7 +1098,7 @@ export interface Advanced { /** * 拖入容器时,自动带入 children 列表 */ - initialChildren?: NodeData[] | ((target: SettingTarget) => NodeData[]); + initialChildren?: NodeData[] | ((target: IPublicModelSettingField) => NodeData[]); /** * @todo 待补充文档 */ diff --git a/packages/designer/src/component-meta.ts b/packages/designer/src/component-meta.ts index 80f99c05b..4b0a613cb 100644 --- a/packages/designer/src/component-meta.ts +++ b/packages/designer/src/component-meta.ts @@ -8,10 +8,11 @@ import { IPublicTypeTransformedComponentMetadata, IPublicTypeNestingFilter, IPublicTypeI18nData, - IPublicTypePluginConfig, IPublicTypeFieldConfig, IPublicModelComponentMeta, IPublicTypeAdvanced, + IPublicTypeDisposable, + IPublicTypeLiveTextEditingConfig, } from '@alilc/lowcode-types'; import { deprecate, isRegExp, isTitleConfig, isNode } from '@alilc/lowcode-utils'; import { computed, createModuleEventBus, IEventBus } from '@alilc/lowcode-editor-core'; @@ -59,9 +60,11 @@ export function buildFilter(rule?: string | string[] | RegExp | IPublicTypeNesti export interface IComponentMeta extends IPublicModelComponentMeta { prototype?: any; + get rootSelector(): string | undefined; + setMetadata(metadata: IPublicTypeComponentMetadata): void; - get rootSelector(): string | undefined; + onMetadataChange(fn: (args: any) => void): IPublicTypeDisposable; } export class ComponentMeta implements IComponentMeta { @@ -120,7 +123,7 @@ export class ComponentMeta implements IComponentMeta { return config?.combined || config?.props || []; } - private _liveTextEditing?: IPublicTypePluginConfig[]; + private _liveTextEditing?: IPublicTypeLiveTextEditingConfig[]; get liveTextEditing() { return this._liveTextEditing; @@ -357,7 +360,7 @@ export class ComponentMeta implements IComponentMeta { return true; } - onMetadataChange(fn: (args: any) => void): () => void { + onMetadataChange(fn: (args: any) => void): IPublicTypeDisposable { this.emitter.on('metadata_change', fn); return () => { this.emitter.removeListener('metadata_change', fn); diff --git a/packages/designer/src/designer/designer.ts b/packages/designer/src/designer/designer.ts index c26d9fb4b..a1d05a8dd 100644 --- a/packages/designer/src/designer/designer.ts +++ b/packages/designer/src/designer/designer.ts @@ -140,7 +140,7 @@ export class Designer implements IDesigner { @obx.ref private _simulatorComponent?: ComponentType; - @obx.ref private _simulatorProps?: object | ((project: Project) => object); + @obx.ref private _simulatorProps?: Record | ((project: Project) => object); @obx.ref private _suspensed = false; diff --git a/packages/designer/src/designer/setting/index.ts b/packages/designer/src/designer/setting/index.ts index a8319e5b2..6cfa914e6 100644 --- a/packages/designer/src/designer/setting/index.ts +++ b/packages/designer/src/designer/setting/index.ts @@ -1,3 +1,4 @@ export * from './setting-field'; export * from './setting-top-entry'; -export * from './setting-entry'; +export * from './setting-entry-type'; +export * from './setting-prop-entry'; diff --git a/packages/designer/src/designer/setting/setting-entry-type.ts b/packages/designer/src/designer/setting/setting-entry-type.ts new file mode 100644 index 000000000..1aee9016e --- /dev/null +++ b/packages/designer/src/designer/setting/setting-entry-type.ts @@ -0,0 +1,45 @@ +import { IPublicApiSetters, IPublicModelEditor } from '@alilc/lowcode-types'; +import { IDesigner } from '../designer'; +import { INode } from '../../document'; +import { ISettingField } from './setting-field'; + +export interface ISettingEntry { + readonly designer: IDesigner | undefined; + + readonly id: string; + + /** + * 同样类型的节点 + */ + readonly isSameComponent: boolean; + + /** + * 一个 + */ + readonly isSingle: boolean; + + /** + * 多个 + */ + readonly isMultiple: boolean; + + /** + * 编辑器引用 + */ + readonly editor: IPublicModelEditor; + + readonly setters: IPublicApiSetters; + + /** + * 取得子项 + */ + get: (propName: string | number) => ISettingField | null; + + readonly nodes: INode[]; + + // @todo 补充 node 定义 + /** + * 获取 node 中的第一项 + */ + getNode: () => any; +} diff --git a/packages/designer/src/designer/setting/setting-entry.ts b/packages/designer/src/designer/setting/setting-entry.ts deleted file mode 100644 index 9b0d4846a..000000000 --- a/packages/designer/src/designer/setting/setting-entry.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { IBaseModelSettingEntry, IPublicModelSettingPropEntry, IPublicTypeSetValueOptions } from '@alilc/lowcode-types'; -import { IComponentMeta } from '../../component-meta'; -import { IDesigner } from '../designer'; -import { INode } from '../../document'; - -export interface ISettingEntry extends IBaseModelSettingEntry< - INode, - IComponentMeta, - ISettingEntry -> { - readonly designer: IDesigner; - - readonly isGroup: boolean; - - readonly id: string; - - get name(): string | number | undefined; - - internalToShellPropEntry(): IPublicModelSettingPropEntry; - - valueChange(options: IPublicTypeSetValueOptions): void; - - get valueState(): number; - - clearValue(): void; -} diff --git a/packages/designer/src/designer/setting/setting-field.ts b/packages/designer/src/designer/setting/setting-field.ts index da374f9bb..36a30eb1c 100644 --- a/packages/designer/src/designer/setting/setting-field.ts +++ b/packages/designer/src/designer/setting/setting-field.ts @@ -7,14 +7,18 @@ import { IPublicTypeFieldConfig, IPublicTypeCustomView, IPublicTypeSetValueOptions, + IPublicTypeDisposable, + IPublicModelSettingField, + IBaseModelSettingField, } from '@alilc/lowcode-types'; import { Transducer } from './utils'; -import { SettingPropEntry } from './setting-prop-entry'; -import { ISettingEntry } from './setting-entry'; +import { ISettingPropEntry, SettingPropEntry } from './setting-prop-entry'; import { computed, obx, makeObservable, action, untracked, intl } from '@alilc/lowcode-editor-core'; import { cloneDeep, isCustomView, isDynamicSetter } from '@alilc/lowcode-utils'; +import { ISettingTopEntry } from './setting-top-entry'; +import { IComponentMeta, INode } from '@alilc/lowcode-designer'; -function getSettingFieldCollectorKey(parent: ISettingEntry, config: IPublicTypeFieldConfig) { +function getSettingFieldCollectorKey(parent: ISettingTopEntry | ISettingField, config: IPublicTypeFieldConfig) { let cur = parent; const path = [config.name]; while (cur !== parent.top) { @@ -26,11 +30,18 @@ function getSettingFieldCollectorKey(parent: ISettingEntry, config: IPublicTypeF return path.join('.'); } -export interface ISettingField extends Omit { +export interface ISettingField extends ISettingPropEntry, Omit, 'setValue' | 'key' | 'node'> { get items(): Array; get title(): string | ReactNode | undefined; + readonly isSettingField: true; + purge(): void; extraProps: IPublicTypeFieldExtraProps; @@ -41,6 +52,10 @@ export interface ISettingField extends Omit { readonly isRequired: boolean; + readonly isGroup: boolean; + + get valueState(): number; + setExpanded(value: boolean): void; setValue( @@ -49,6 +64,16 @@ export interface ISettingField extends Omit { force?: boolean, extraOptions?: IPublicTypeSetValueOptions, ): void; + + clearValue(): void; + + valueChange(options: IPublicTypeSetValueOptions): void; + + createField(config: IPublicTypeFieldConfig): ISettingField; + + onEffect(action: () => void): IPublicTypeDisposable; + + internalToShell(): IPublicModelSettingField; } export class SettingField extends SettingPropEntry implements ISettingField { @@ -62,7 +87,7 @@ export class SettingField extends SettingPropEntry implements ISettingField { private hotValue: any; - parent: ISettingEntry; + parent: ISettingTopEntry | ISettingField; extraProps: IPublicTypeFieldExtraProps; @@ -82,7 +107,7 @@ export class SettingField extends SettingPropEntry implements ISettingField { private _items: Array = []; constructor( - parent: ISettingEntry, + parent: ISettingTopEntry | ISettingField, config: IPublicTypeFieldConfig, private settingFieldCollector?: (name: string | number, field: ISettingField) => void, ) { @@ -118,8 +143,8 @@ export class SettingField extends SettingPropEntry implements ISettingField { } if (isDynamicSetter(this._setter)) { return untracked(() => { - const shellThis = this.internalToShellPropEntry(); - return (this._setter as IPublicTypeDynamicSetter)?.call(shellThis, shellThis); + const shellThis = this.internalToShell(); + return (this._setter as IPublicTypeDynamicSetter)?.call(shellThis, shellThis!); }); } return this._setter; @@ -266,8 +291,13 @@ export class SettingField extends SettingPropEntry implements ISettingField { this.valueChange(options); } - onEffect(action: () => void): () => void { - return this.designer.autorun(action, true); + onEffect(action: () => void): IPublicTypeDisposable { + return this.designer!.autorun(action, true); + } + + + internalToShell() { + return this.designer!.shellModelFactory.createSettingField(this); } } diff --git a/packages/designer/src/designer/setting/setting-prop-entry.ts b/packages/designer/src/designer/setting/setting-prop-entry.ts index 392301b7d..e2f1be615 100644 --- a/packages/designer/src/designer/setting/setting-prop-entry.ts +++ b/packages/designer/src/designer/setting/setting-prop-entry.ts @@ -1,13 +1,44 @@ import { obx, computed, makeObservable, runInAction, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; -import { GlobalEvent, IPublicApiSetters, IPublicModelEditor, IPublicTypeSetValueOptions } from '@alilc/lowcode-types'; -import { uniqueId, isJSExpression, isSettingField } from '@alilc/lowcode-utils'; -import { ISettingEntry } from './setting-entry'; +import { GlobalEvent, IPublicApiSetters, IPublicModelEditor, IPublicModelSettingField, IPublicTypeFieldExtraProps, IPublicTypeSetValueOptions } from '@alilc/lowcode-types'; +import { uniqueId, isJSExpression } from '@alilc/lowcode-utils'; +import { ISettingEntry } from './setting-entry-type'; import { INode } from '../../document'; import { IComponentMeta } from '../../component-meta'; import { IDesigner } from '../designer'; -import { ISettingField } from './setting-field'; +import { ISettingTopEntry } from './setting-top-entry'; +import { ISettingField, isSettingField } from './setting-field'; -export class SettingPropEntry implements ISettingEntry { +export interface ISettingPropEntry extends ISettingEntry { + get props(): ISettingTopEntry; + + readonly isGroup: boolean; + + get name(): string | number | undefined; + + valueChange(options: IPublicTypeSetValueOptions): void; + + getKey(): string | number | undefined; + + setKey(key: string | number): void; + + getDefaultValue(): any; + + setUseVariable(flag: boolean): void; + + getProps(): ISettingTopEntry; + + isUseVariable(): boolean; + + getMockOrValue(): any; + + remove(): void; + + setValue(val: any, isHotValue?: boolean, force?: boolean, extraOptions?: IPublicTypeSetValueOptions): void; + + internalToShell(): IPublicModelSettingField; +} + +export class SettingPropEntry implements ISettingPropEntry { // === static properties === readonly editor: IPublicModelEditor; @@ -23,9 +54,9 @@ export class SettingPropEntry implements ISettingEntry { readonly componentMeta: IComponentMeta | null; - readonly designer: IDesigner; + readonly designer: IDesigner | undefined; - readonly top: ISettingEntry; + readonly top: ISettingTopEntry; readonly isGroup: boolean; @@ -50,9 +81,9 @@ export class SettingPropEntry implements ISettingEntry { return path; } - extraProps: any = {}; + extraProps: IPublicTypeFieldExtraProps = {}; - constructor(readonly parent: ISettingEntry | ISettingField, name: string | number | undefined, type?: 'field' | 'group') { + constructor(readonly parent: ISettingTopEntry | ISettingField, name: string | number | undefined, type?: 'field' | 'group') { makeObservable(this); if (type == null) { const c = typeof name === 'string' ? name.slice(0, 1) : ''; @@ -126,7 +157,7 @@ export class SettingPropEntry implements ISettingEntry { if (this.type !== 'field') { const { getValue } = this.extraProps; return getValue - ? getValue(this.internalToShellPropEntry(), undefined) === undefined + ? getValue(this.internalToShell()!, undefined) === undefined ? 0 : 1 : 0; @@ -165,7 +196,7 @@ export class SettingPropEntry implements ISettingEntry { } const { getValue } = this.extraProps; try { - return getValue ? getValue(this.internalToShellPropEntry(), val) : val; + return getValue ? getValue(this.internalToShell()!, val) : val; } catch (e) { console.warn(e); return val; @@ -184,7 +215,7 @@ export class SettingPropEntry implements ISettingEntry { const { setValue } = this.extraProps; if (setValue && !extraOptions?.disableMutator) { try { - setValue(this.internalToShellPropEntry(), val); + setValue(this.internalToShell()!, val); } catch (e) { /* istanbul ignore next */ console.warn(e); @@ -207,7 +238,7 @@ export class SettingPropEntry implements ISettingEntry { const { setValue } = this.extraProps; if (setValue) { try { - setValue(this.internalToShellPropEntry(), undefined); + setValue(this.internalToShell()!, undefined); } catch (e) { /* istanbul ignore next */ console.warn(e); @@ -363,7 +394,7 @@ export class SettingPropEntry implements ISettingEntry { return v; } - internalToShellPropEntry() { - return this.designer.shellModelFactory.createSettingPropEntry(this); + internalToShell(): IPublicModelSettingField { + return this.designer!.shellModelFactory.createSettingField(this);; } } diff --git a/packages/designer/src/designer/setting/setting-top-entry.ts b/packages/designer/src/designer/setting/setting-top-entry.ts index 04f00afc3..62efd5f53 100644 --- a/packages/designer/src/designer/setting/setting-top-entry.ts +++ b/packages/designer/src/designer/setting/setting-top-entry.ts @@ -1,11 +1,10 @@ -import { IPublicTypeCustomView, IPublicModelEditor } from '@alilc/lowcode-types'; +import { IPublicTypeCustomView, IPublicModelEditor, IPublicModelSettingTopEntry } from '@alilc/lowcode-types'; import { isCustomView } from '@alilc/lowcode-utils'; import { computed, IEventBus, createModuleEventBus } from '@alilc/lowcode-editor-core'; -import { ISettingEntry } from './setting-entry'; -import { SettingField } from './setting-field'; -import { SettingPropEntry } from './setting-prop-entry'; +import { ISettingEntry } from './setting-entry-type'; +import { ISettingField, SettingField } from './setting-field'; import { INode } from '../../document'; -import { ComponentMeta } from '../../component-meta'; +import { IComponentMeta } from '../../component-meta'; import { IDesigner } from '../designer'; import { Setters } from '@alilc/lowcode-shell'; @@ -16,8 +15,25 @@ function generateSessionId(nodes: INode[]) { .join(','); } -export interface ISettingTopEntry extends ISettingEntry { +export interface ISettingTopEntry extends ISettingEntry, IPublicModelSettingTopEntry< + INode, + ISettingField +> { purge(): void; + + items: Array; + + readonly top: ISettingTopEntry; + + readonly parent: ISettingTopEntry; + + readonly path: never[]; + + componentMeta: IComponentMeta | null; + + getExtraPropValue(propName: string): void; + + setExtraPropValue(propName: string, value: any): void; } export class SettingTopEntry implements ISettingTopEntry { @@ -25,11 +41,11 @@ export class SettingTopEntry implements ISettingTopEntry { private _items: Array = []; - private _componentMeta: ComponentMeta | null = null; + private _componentMeta: IComponentMeta | null = null; private _isSame = true; - private _settingFieldMap: { [prop: string]: SettingField } = {}; + private _settingFieldMap: { [prop: string]: ISettingField } = {}; readonly path = []; @@ -122,8 +138,8 @@ export class SettingTopEntry implements ISettingTopEntry { private setupItems() { if (this.componentMeta) { - const settingFieldMap: { [prop: string]: SettingField } = {}; - const settingFieldCollector = (name: string | number, field: SettingField) => { + const settingFieldMap: { [prop: string]: ISettingField } = {}; + const settingFieldCollector = (name: string | number, field: ISettingField) => { settingFieldMap[name] = field; }; this._items = this.componentMeta.configure.map((item) => { @@ -160,34 +176,34 @@ export class SettingTopEntry implements ISettingTopEntry { /** * 获取子项 */ - get(propName: string | number): SettingPropEntry | null { + get(propName: string | number): ISettingField | null { if (!propName) return null; - return this._settingFieldMap[propName] || (new SettingPropEntry(this, propName)); + return this._settingFieldMap[propName] || (new SettingField(this, { name: propName })); } /** * 设置子级属性值 */ - setPropValue(propName: string, value: any) { + setPropValue(propName: string | number, value: any) { this.nodes.forEach((node) => { - node.setPropValue(propName, value); + node.setPropValue(propName.toString(), value); }); } /** * 清除已设置值 */ - clearPropValue(propName: string) { + clearPropValue(propName: string | number) { this.nodes.forEach((node) => { - node.clearPropValue(propName); + node.clearPropValue(propName.toString()); }); } /** * 获取子级属性值 */ - getPropValue(propName: string): any { - return this.first.getProp(propName, true)?.getValue(); + getPropValue(propName: string | number): any { + return this.first.getProp(propName.toString(), true)?.getValue(); } /** diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 691c22844..d8b371ddf 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -153,6 +153,12 @@ export interface IBaseNode