diff --git a/packages/designer/src/builtin-simulator/renderer.ts b/packages/designer/src/builtin-simulator/renderer.ts index 43a153222..bd94f24f6 100644 --- a/packages/designer/src/builtin-simulator/renderer.ts +++ b/packages/designer/src/builtin-simulator/renderer.ts @@ -1,12 +1,12 @@ import { Component } from '../simulator'; -import { IPublicTypeNodeSchema, IPublicTypeComponentInstance, IPublicTypeNodeInstance, Asset } from '@alilc/lowcode-types'; +import { IPublicTypeComponentInstance, IPublicTypeNodeInstance, Asset, IPublicTypeComponentSchema, IPublicTypeProjectSchema, IPublicTypeLowCodeComponent } from '@alilc/lowcode-types'; export interface BuiltinSimulatorRenderer { readonly isSimulatorRenderer: true; autoRepaintNode?: boolean; components: Record; rerender: () => void; - createComponent(schema: IPublicTypeNodeSchema): Component | null; + createComponent(schema: IPublicTypeProjectSchema): Component | null; getComponent(componentName: string): Component; getClosestNodeInstance( from: IPublicTypeComponentInstance, diff --git a/packages/rax-simulator-renderer/src/renderer.ts b/packages/rax-simulator-renderer/src/renderer.ts index 2dca4506e..64ec2d2c6 100644 --- a/packages/rax-simulator-renderer/src/renderer.ts +++ b/packages/rax-simulator-renderer/src/renderer.ts @@ -1,6 +1,6 @@ -import { BuiltinSimulatorRenderer, Component, DocumentModel, Node } from '@alilc/lowcode-designer'; -import { IPublicTypeComponentSchema, IPublicTypeNodeSchema, IPublicTypeNpmInfo, IPublicEnumTransformStage, IPublicTypeNodeInstance } from '@alilc/lowcode-types'; -import { Asset, compatibleLegaoSchema, cursor, isElement, isESModule, isPlainObject, isReactComponent, setNativeSelection } from '@alilc/lowcode-utils'; +import { BuiltinSimulatorRenderer, Component, IBaseNode, IDocumentModel } from '@alilc/lowcode-designer'; +import { IPublicTypeComponentSchema, IPublicTypeNodeSchema, IPublicTypeNpmInfo, IPublicEnumTransformStage, IPublicTypeNodeInstance, IPublicTypeProjectSchema } from '@alilc/lowcode-types'; +import { Asset, compatibleLegaoSchema, cursor, isElement, isESModule, isLowcodeProjectSchema, isComponentSchema, isPlainObject, isReactComponent, setNativeSelection } from '@alilc/lowcode-utils'; import LowCodeRenderer from '@alilc/lowcode-rax-renderer'; import { computed, observable as obx, makeObservable, configure } from 'mobx'; import DriverUniversal from 'driver-universal'; @@ -47,15 +47,23 @@ const builtinComponents = { function buildComponents( libraryMap: LibraryMap, componentsMap: { [componentName: string]: IPublicTypeNpmInfo | ComponentType | IPublicTypeComponentSchema }, - createComponent: (schema: IPublicTypeComponentSchema) => Component | null, + createComponent: (schema: IPublicTypeProjectSchema) => Component | null, ) { const components: any = { ...builtinComponents, }; Object.keys(componentsMap).forEach((componentName) => { let component = componentsMap[componentName]; - if (component && (component as IPublicTypeComponentSchema).componentName === 'Component') { - components[componentName] = createComponent(component as IPublicTypeComponentSchema); + if (component && (isLowcodeProjectSchema(component) || isComponentSchema(component))) { + if (isComponentSchema(component)) { + components[componentName] = createComponent({ + version: '', + componentsMap: [], + componentsTree: [component], + }); + } else { + components[componentName] = createComponent(component); + } } else if (isReactComponent(component)) { components[componentName] = component; } else { @@ -110,7 +118,7 @@ export class DocumentInstance { return this.document.export(IPublicEnumTransformStage.Render); } - constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) { + constructor(readonly container: SimulatorRendererContainer, readonly document: IDocumentModel) { makeObservable(this); } @@ -221,7 +229,7 @@ export class DocumentInstance { return this.instancesMap.get(id) || null; } - getNode(id: string): Node | null { + getNode(id: string): IBaseNode | null { return this.document.getNode(id); } } @@ -256,6 +264,8 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { // sync designMode this._designMode = host.designMode; + this._locale = host.locale; + // sync requestHandlersMap this._requestHandlersMap = host.requestHandlersMap; @@ -343,11 +353,11 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { // TODO: remove this.createComponent this._components = buildComponents(this._libraryMap, this._componentsMap, this.createComponent.bind(this)); } - @obx.ref private _components: any = {}; - @computed get components(): object { + @obx.ref private _components: Record | null = {}; + @computed get components(): Record { // 根据 device 选择不同组件,进行响应式 // 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl - return this._components; + return this._components || {}; } // context from: utils、constants、history、location、match @obx.ref private _appContext = {}; @@ -362,6 +372,10 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { @computed get device() { return this._device; } + @obx.ref private _locale: string | undefined = undefined; + @computed get locale() { + return this._locale; + } @obx.ref private _requestHandlersMap = null; @computed get requestHandlersMap(): any { return this._requestHandlersMap; @@ -378,12 +392,15 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { return loader.load(asset); } + async loadAsyncLibrary(asyncLibraryMap: Record) { + } + getComponent(componentName: string) { const paths = componentName.split('.'); const subs: string[] = []; while (true) { - const component = this._components[componentName]; + const component = this._components?.[componentName]; if (component) { return getSubComponent(component, subs); } @@ -416,7 +433,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { // if (instance && SYMBOL_VNID in instance) { // const docId = (instance.props as any).schema.docId; return { - docId: instance.props._leaf.document.id, + docId: instance.props._leaf.document?.id || '', nodeId: instance.props._leaf.getId(), instance, node: instance.props._leaf, @@ -497,17 +514,26 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { this.currentDocumentInstance?.refresh(); } - createComponent(schema: IPublicTypeNodeSchema): Component | null { - const _schema: any = { - ...compatibleLegaoSchema(schema), + stopAutoRepaintNode() { + } + + enableAutoRepaintNode() { + } + + createComponent(schema: IPublicTypeProjectSchema): Component | null { + const _schema: IPublicTypeProjectSchema = { + ...schema, + componentsTree: schema.componentsTree.map(compatibleLegaoSchema), }; - if (schema.componentName === 'Component' && (schema as IPublicTypeComponentSchema).css) { + const componentsTreeSchema = _schema.componentsTree[0]; + + if (componentsTreeSchema.componentName === 'Component' && componentsTreeSchema.css) { const doc = window.document; const s = doc.createElement('style'); s.setAttribute('type', 'text/css'); - s.setAttribute('id', `Component-${schema.id || ''}`); - s.appendChild(doc.createTextNode((schema as IPublicTypeComponentSchema).css || '')); + s.setAttribute('id', `Component-${componentsTreeSchema.id || ''}`); + s.appendChild(doc.createTextNode(componentsTreeSchema.css || '')); doc.getElementsByTagName('head')[0].appendChild(s); } @@ -520,9 +546,11 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { // @ts-ignore return createElement(LowCodeRenderer, { ...extraProps, - schema: _schema, + schema: componentsTreeSchema, components, designMode: '', + locale: renderer.locale, + messages: _schema.i18n || {}, device: renderer.device, appHelper: renderer.context, rendererName: 'LowCodeRenderer', diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts index 1832ca99d..dbb24a5bb 100644 --- a/packages/react-simulator-renderer/src/renderer.ts +++ b/packages/react-simulator-renderer/src/renderer.ts @@ -17,9 +17,9 @@ import { AssetLoader, getProjectUtils, } from '@alilc/lowcode-utils'; -import { IPublicTypeComponentSchema, IPublicEnumTransformStage, IPublicTypeNodeSchema, IPublicTypeNodeInstance } from '@alilc/lowcode-types'; +import { IPublicTypeComponentSchema, IPublicEnumTransformStage, IPublicTypeNodeInstance, IPublicTypeProjectSchema } from '@alilc/lowcode-types'; // just use types -import { BuiltinSimulatorRenderer, Component, DocumentModel, Node } from '@alilc/lowcode-designer'; +import { BuiltinSimulatorRenderer, Component, IDocumentModel, INode } from '@alilc/lowcode-designer'; import LowCodeRenderer from '@alilc/lowcode-react-renderer'; import { createMemoryHistory, MemoryHistory } from 'history'; import Slot from './builtin-components/slot'; @@ -94,7 +94,7 @@ export class DocumentInstance { return this.document.id; } - constructor(readonly container: SimulatorRendererContainer, readonly document: DocumentModel) { + constructor(readonly container: SimulatorRendererContainer, readonly document: IDocumentModel) { makeObservable(this); } @@ -173,7 +173,7 @@ export class DocumentInstance { mountContext() { } - getNode(id: string): Node | null { + getNode(id: string): INode | null { return this.document.getNode(id); } @@ -207,12 +207,12 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { private _libraryMap: { [key: string]: string } = {}; - private _components: any = {}; + private _components: Record | null = {}; - get components(): object { + get components(): Record { // 根据 device 选择不同组件,进行响应式 // 更好的做法是,根据 device 选择加载不同的组件资源,甚至是 simulatorUrl - return this._components; + return this._components || {}; } // context from: utils、constants、history、location、match @obx.ref private _appContext: any = {}; @@ -388,7 +388,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { const subs: string[] = []; while (true) { - const component = this._components[componentName]; + const component = this._components?.[componentName]; if (component) { return getSubComponent(component, subs); } @@ -430,17 +430,20 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { cursor.release(); } - createComponent(schema: IPublicTypeNodeSchema): Component | null { - const _schema: any = { - ...compatibleLegaoSchema(schema), + createComponent(schema: IPublicTypeProjectSchema): Component | null { + const _schema: IPublicTypeProjectSchema = { + ...schema, + componentsTree: schema.componentsTree.map(compatibleLegaoSchema), }; - if (schema.componentName === 'Component' && (schema as IPublicTypeComponentSchema).css) { + const componentsTreeSchema = _schema.componentsTree[0]; + + if (componentsTreeSchema.componentName === 'Component' && componentsTreeSchema.css) { const doc = window.document; const s = doc.createElement('style'); s.setAttribute('type', 'text/css'); - s.setAttribute('id', `Component-${schema.id || ''}`); - s.appendChild(doc.createTextNode((schema as IPublicTypeComponentSchema).css || '')); + s.setAttribute('id', `Component-${componentsTreeSchema.id || ''}`); + s.appendChild(doc.createTextNode(componentsTreeSchema.css || '')); doc.getElementsByTagName('head')[0].appendChild(s); } @@ -452,9 +455,11 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer { return createElement(LowCodeRenderer, { ...extraProps, // 防止覆盖下面内置属性 // 使用 _schema 为了使低代码组件在页面设计中使用变量,同 react 组件使用效果一致 - schema: _schema, + schema: componentsTreeSchema, components: renderer.components, designMode: '', + locale: renderer.locale, + messages: _schema.i18n || {}, device: renderer.device, appHelper: renderer.context, rendererName: 'LowCodeRenderer', diff --git a/packages/types/src/shell/type/package.ts b/packages/types/src/shell/type/package.ts index 6df8fdd0b..b33fa3f94 100644 --- a/packages/types/src/shell/type/package.ts +++ b/packages/types/src/shell/type/package.ts @@ -1,5 +1,5 @@ import { EitherOr } from '../../utils'; -import { IPublicTypeComponentSchema } from './'; +import { IPublicTypeComponentSchema, IPublicTypeProjectSchema } from './'; /** * 定义组件大包及 external 资源的信息 @@ -51,5 +51,5 @@ export type IPublicTypePackage = EitherOr<{ /** * 低代码组件 schema 内容 */ - schema?: IPublicTypeComponentSchema; + schema?: IPublicTypeProjectSchema; }, 'package', 'id'>; diff --git a/packages/types/src/shell/type/project-schema.ts b/packages/types/src/shell/type/project-schema.ts index 647208531..66a5aaa8a 100644 --- a/packages/types/src/shell/type/project-schema.ts +++ b/packages/types/src/shell/type/project-schema.ts @@ -19,7 +19,7 @@ export type IPublicTypeUtilsMap = IPublicTypeUtilItem[]; * 应用描述 */ -export interface IPublicTypeProjectSchema { +export interface IPublicTypeProjectSchema { id?: string; /** * 当前应用协议版本号 @@ -34,7 +34,7 @@ export interface IPublicTypeProjectSchema { * 低代码业务组件树描述 * 是长度固定为 1 的数组,即数组内仅包含根容器的描述(低代码业务组件容器类型) */ - componentsTree: IPublicTypeRootSchema[]; + componentsTree: T[]; /** * 国际化语料 */ diff --git a/packages/utils/src/build-components.ts b/packages/utils/src/build-components.ts index af4c64699..e3b1797df 100644 --- a/packages/utils/src/build-components.ts +++ b/packages/utils/src/build-components.ts @@ -1,8 +1,10 @@ import { ComponentType, forwardRef, createElement, FunctionComponent } from 'react'; -import { IPublicTypeNpmInfo, IPublicTypeComponentSchema } from '@alilc/lowcode-types'; +import { IPublicTypeNpmInfo, IPublicTypeComponentSchema, IPublicTypeProjectSchema } from '@alilc/lowcode-types'; import { isESModule } from './is-es-module'; import { isReactComponent, acceptsRef, wrapReactClass } from './is-react'; import { isObject } from './is-object'; +import { isLowcodeProjectSchema } from './check-types'; +import { isComponentSchema } from './check-types/is-component-schema'; type Component = ComponentType | object; interface LibraryMap { @@ -95,12 +97,20 @@ function isMixinComponent(components: any) { export function buildComponents(libraryMap: LibraryMap, componentsMap: { [componentName: string]: IPublicTypeNpmInfo | ComponentType | IPublicTypeComponentSchema }, - createComponent: (schema: IPublicTypeComponentSchema) => Component | null) { + createComponent: (schema: IPublicTypeProjectSchema) => Component | null) { const components: any = {}; Object.keys(componentsMap).forEach((componentName) => { let component = componentsMap[componentName]; - if (component && (component as IPublicTypeComponentSchema).componentName === 'Component') { - components[componentName] = createComponent(component as IPublicTypeComponentSchema); + if (component && (isLowcodeProjectSchema(component) || isComponentSchema(component))) { + if (isComponentSchema(component)) { + components[componentName] = createComponent({ + version: '', + componentsMap: [], + componentsTree: [component], + }); + } else { + components[componentName] = createComponent(component); + } } else if (isReactComponent(component)) { if (!acceptsRef(component)) { component = wrapReactClass(component as FunctionComponent); diff --git a/packages/utils/src/check-types/index.ts b/packages/utils/src/check-types/index.ts index 1e3835021..3155926ef 100644 --- a/packages/utils/src/check-types/index.ts +++ b/packages/utils/src/check-types/index.ts @@ -20,4 +20,7 @@ export * from './is-drag-any-object'; export * from './is-location-children-detail'; export * from './is-node'; export * from './is-location-data'; -export * from './is-setting-field'; \ No newline at end of file +export * from './is-setting-field'; +export * from './is-lowcode-component-type'; +export * from './is-lowcode-project-schema'; +export * from './is-component-schema'; \ No newline at end of file diff --git a/packages/utils/src/check-types/is-component-schema.ts b/packages/utils/src/check-types/is-component-schema.ts new file mode 100644 index 000000000..508d153b9 --- /dev/null +++ b/packages/utils/src/check-types/is-component-schema.ts @@ -0,0 +1,8 @@ +import { IPublicTypeComponentSchema } from "@alilc/lowcode-types"; + +export function isComponentSchema(schema: any): schema is IPublicTypeComponentSchema { + if (typeof schema === 'object') { + return schema.componentName === 'Component'; + } + return false +} diff --git a/packages/utils/src/check-types/is-lowcode-component-type.ts b/packages/utils/src/check-types/is-lowcode-component-type.ts index 22ab539b4..ce19c23e8 100644 --- a/packages/utils/src/check-types/is-lowcode-component-type.ts +++ b/packages/utils/src/check-types/is-lowcode-component-type.ts @@ -1,7 +1,7 @@ import { isProCodeComponentType } from './is-procode-component-type'; -import { IPublicTypeComponentMap } from '@alilc/lowcode-types'; +import { IPublicTypeComponentMap, IPublicTypeLowCodeComponent } from '@alilc/lowcode-types'; -export function isLowCodeComponentType(desc: IPublicTypeComponentMap): boolean { +export function isLowCodeComponentType(desc: IPublicTypeComponentMap): desc is IPublicTypeLowCodeComponent { return !isProCodeComponentType(desc); } diff --git a/packages/utils/src/check-types/is-lowcode-project-schema.ts b/packages/utils/src/check-types/is-lowcode-project-schema.ts new file mode 100644 index 000000000..0fffaea2f --- /dev/null +++ b/packages/utils/src/check-types/is-lowcode-project-schema.ts @@ -0,0 +1,6 @@ +import { IPublicTypeComponentSchema, IPublicTypeProjectSchema } from "@alilc/lowcode-types"; +import { isComponentSchema } from "./is-component-schema"; + +export function isLowcodeProjectSchema(data: any): data is IPublicTypeProjectSchema { + return data && data.componentsTree && data.componentsTree.length && isComponentSchema(data.componentsTree[0]); +} diff --git a/packages/utils/src/check-types/is-project-schema.ts b/packages/utils/src/check-types/is-project-schema.ts index aa1961072..b228d481e 100644 --- a/packages/utils/src/check-types/is-project-schema.ts +++ b/packages/utils/src/check-types/is-project-schema.ts @@ -1,3 +1,5 @@ -export function isProjectSchema(data: any): boolean { +import { IPublicTypeProjectSchema } from "@alilc/lowcode-types"; + +export function isProjectSchema(data: any): data is IPublicTypeProjectSchema { return data && data.componentsTree; }