mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 03:01:16 +00:00
feat: support for NotFoundComponent design state is optional (#1013)
This commit is contained in:
parent
438cccd58e
commit
d3c891e2a4
@ -232,6 +232,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||||||
return engineConfig.get('thisRequiredInJSE') ?? true;
|
return engineConfig.get('thisRequiredInJSE') ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get enableStrictNotFoundMode(): any {
|
||||||
|
return engineConfig.get('enableStrictNotFoundMode') ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
@computed get componentsAsset(): Asset | undefined {
|
@computed get componentsAsset(): Asset | undefined {
|
||||||
return this.get('componentsAsset');
|
return this.get('componentsAsset');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -176,12 +176,29 @@ export class ComponentMeta {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private parseMetadata(metadata: ComponentMetadata) {
|
private parseMetadata(metadata: ComponentMetadata) {
|
||||||
const { componentName, npm } = metadata;
|
const { componentName, npm, ...others } = metadata;
|
||||||
|
let _metadata = metadata;
|
||||||
|
if (!npm && !Object.keys(others).length) {
|
||||||
|
// 没有注册的组件,只能删除,不支持复制、移动等操作
|
||||||
|
_metadata = {
|
||||||
|
componentName,
|
||||||
|
configure: {
|
||||||
|
component: {
|
||||||
|
disableBehaviors: ['copy', 'move', 'lock', 'unlock'],
|
||||||
|
},
|
||||||
|
advanced: {
|
||||||
|
callbacks: {
|
||||||
|
onMoveHook: () => false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
this._npm = npm || this._npm;
|
this._npm = npm || this._npm;
|
||||||
this._componentName = componentName;
|
this._componentName = componentName;
|
||||||
|
|
||||||
// 额外转换逻辑
|
// 额外转换逻辑
|
||||||
this._transformedMetadata = this.transformMetadata(metadata);
|
this._transformedMetadata = this.transformMetadata(_metadata);
|
||||||
|
|
||||||
const { title } = this._transformedMetadata;
|
const { title } = this._transformedMetadata;
|
||||||
if (title) {
|
if (title) {
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import {
|
|||||||
setShaken,
|
setShaken,
|
||||||
} from '../../src/designer/dragon';
|
} from '../../src/designer/dragon';
|
||||||
import { Project } from '../../src/project/project';
|
import { Project } from '../../src/project/project';
|
||||||
|
import pageMetadata from '../fixtures/component-metadata/page';
|
||||||
import { Node } from '../../src/document/node/node';
|
import { Node } from '../../src/document/node/node';
|
||||||
import { Designer } from '../../src/designer/designer';
|
import { Designer } from '../../src/designer/designer';
|
||||||
import { DocumentModel } from '../../src/document/document-model';
|
import { DocumentModel } from '../../src/document/document-model';
|
||||||
@ -46,6 +47,7 @@ describe('Host 测试', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
designer = new Designer({ editor });
|
designer = new Designer({ editor });
|
||||||
project = designer.project;
|
project = designer.project;
|
||||||
|
designer.createComponentMeta(pageMetadata);
|
||||||
doc = project.createDocument(formSchema);
|
doc = project.createDocument(formSchema);
|
||||||
host = new BuiltinSimulatorHost(designer.project);
|
host = new BuiltinSimulatorHost(designer.project);
|
||||||
});
|
});
|
||||||
@ -373,6 +375,14 @@ describe('Host 测试', () => {
|
|||||||
},
|
},
|
||||||
})).toBeNull();
|
})).toBeNull();
|
||||||
});
|
});
|
||||||
|
it('notFoundComponent', () => {
|
||||||
|
expect(host.locate({
|
||||||
|
dragObject: {
|
||||||
|
type: DragObjectType.Node,
|
||||||
|
nodes: [doc.getNode('form')],
|
||||||
|
},
|
||||||
|
})).toBeUndefined();
|
||||||
|
})
|
||||||
it('locate', () => {
|
it('locate', () => {
|
||||||
host.locate({
|
host.locate({
|
||||||
dragObject: {
|
dragObject: {
|
||||||
|
|||||||
@ -137,6 +137,10 @@ const VALID_ENGINE_OPTIONS = {
|
|||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
description: 'JSExpression 是否只支持使用 this 来访问上下文变量',
|
description: 'JSExpression 是否只支持使用 this 来访问上下文变量',
|
||||||
},
|
},
|
||||||
|
enableStrictNotFoundMode: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: '当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
export interface EngineOptions {
|
export interface EngineOptions {
|
||||||
/**
|
/**
|
||||||
@ -258,6 +262,12 @@ export interface EngineOptions {
|
|||||||
* JSExpression 是否只支持使用 this 来访问上下文变量,假如需要兼容原来的 'state.xxx',则设置为 false
|
* JSExpression 是否只支持使用 this 来访问上下文变量,假如需要兼容原来的 'state.xxx',则设置为 false
|
||||||
*/
|
*/
|
||||||
thisRequiredInJSE?: boolean;
|
thisRequiredInJSE?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
|
||||||
|
*/
|
||||||
|
enableStrictNotFoundMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean): boolean => {
|
const getStrictModeValue = (engineOptions: EngineOptions, defaultValue: boolean): boolean => {
|
||||||
|
|||||||
@ -255,6 +255,7 @@ class Renderer extends Component<{
|
|||||||
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
onCompGetRef={(schema: any, ref: ReactInstance | null) => {
|
||||||
documentInstance.mountInstance(schema.id, ref);
|
documentInstance.mountInstance(schema.id, ref);
|
||||||
}}
|
}}
|
||||||
|
enableStrictNotFoundMode={host.enableStrictNotFoundMode}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ exports[`Base should be render NotFoundComponent 1`] = `
|
|||||||
<div
|
<div
|
||||||
componentName="Text"
|
componentName="Text"
|
||||||
>
|
>
|
||||||
Component Not Found
|
Text Component Not Found
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -21,21 +21,21 @@ class Adapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
initRuntime() {
|
initRuntime() {
|
||||||
const Component: IGeneralConstructor = class {
|
const Component: IGeneralConstructor = class <T = any, S = any> {
|
||||||
setState() {}
|
setState() {}
|
||||||
forceUpdate() {}
|
forceUpdate() {}
|
||||||
render() {}
|
render() {}
|
||||||
state: Record<string, unknown>;
|
state: Readonly<S>;
|
||||||
props: Record<string, unknown>;
|
props: Readonly<T> & Readonly<{ children?: any | undefined }>;
|
||||||
refs: Record<string, unknown>;
|
refs: Record<string, unknown>;
|
||||||
context: Record<string, unknown>;
|
context: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
const PureComponent: IGeneralConstructor = class {
|
const PureComponent = class <T = any, S = any> {
|
||||||
setState() {}
|
setState() {}
|
||||||
forceUpdate() {}
|
forceUpdate() {}
|
||||||
render() {}
|
render() {}
|
||||||
state: Record<string, unknown>;
|
state: Readonly<S>;
|
||||||
props: Record<string, unknown>;
|
props: Readonly<T> & Readonly<{ children?: any | undefined }>;
|
||||||
refs: Record<string, unknown>;
|
refs: Record<string, unknown>;
|
||||||
context: Record<string, unknown>;
|
context: Record<string, unknown>;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -104,13 +104,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
|||||||
return customBaseRenderer;
|
return customBaseRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const runtime = adapter.getRuntime();
|
const { Component, createElement } = adapter.getRuntime();
|
||||||
const Component = runtime.Component as IGeneralConstructor<
|
|
||||||
IBaseRendererProps,
|
|
||||||
Record<string, any>,
|
|
||||||
any
|
|
||||||
>;
|
|
||||||
const { createElement } = runtime;
|
|
||||||
const Div = divFactory();
|
const Div = divFactory();
|
||||||
const VisualDom = visualDomFactory();
|
const VisualDom = visualDomFactory();
|
||||||
const AppContext = contextFactory();
|
const AppContext = contextFactory();
|
||||||
@ -125,7 +119,7 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
|||||||
const DEFAULT_LOOP_ARG_INDEX = 'index';
|
const DEFAULT_LOOP_ARG_INDEX = 'index';
|
||||||
let scopeIdx = 0;
|
let scopeIdx = 0;
|
||||||
|
|
||||||
return class BaseRenderer extends Component {
|
return class BaseRenderer extends Component<IBaseRendererProps, Record<string, any>> {
|
||||||
static displayName = 'BaseRenderer';
|
static displayName = 'BaseRenderer';
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -533,6 +527,10 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
|||||||
{
|
{
|
||||||
componentName: schema.componentName,
|
componentName: schema.componentName,
|
||||||
componentId: schema.id,
|
componentId: schema.id,
|
||||||
|
enableStrictNotFoundMode: engine.props.enableStrictNotFoundMode,
|
||||||
|
ref: (ref: any) => {
|
||||||
|
ref && engine.props?.onCompGetRef(schema, ref);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
this.__getSchemaChildrenVirtualDom(schema, scope, Comp),
|
this.__getSchemaChildrenVirtualDom(schema, scope, Comp),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -4,14 +4,11 @@ import contextFactory from '../context';
|
|||||||
import { isFileSchema, isEmpty } from '../utils';
|
import { isFileSchema, isEmpty } from '../utils';
|
||||||
import baseRendererFactory from './base';
|
import baseRendererFactory from './base';
|
||||||
import divFactory from '../components/Div';
|
import divFactory from '../components/Div';
|
||||||
import { IGeneralConstructor, IRenderComponent, IRendererProps, IRendererState } from '../types';
|
import { IRenderComponent, IRendererProps, IRendererState } from '../types';
|
||||||
import { RootSchema } from '@alilc/lowcode-types';
|
import { NodeSchema, RootSchema } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
export default function rendererFactory(): IRenderComponent {
|
export default function rendererFactory(): IRenderComponent {
|
||||||
const runtime = adapter.getRuntime();
|
const { PureComponent, Component, createElement, findDOMNode } = adapter.getRuntime();
|
||||||
const Component = runtime.Component as IGeneralConstructor<IRendererProps, Record<string, any>>;
|
|
||||||
const PureComponent = runtime.PureComponent as IGeneralConstructor<IRendererProps, Record<string, any>>;
|
|
||||||
const { createElement, findDOMNode } = runtime;
|
|
||||||
const RENDERER_COMPS: any = adapter.getRenderers();
|
const RENDERER_COMPS: any = adapter.getRenderers();
|
||||||
const BaseRenderer = baseRendererFactory();
|
const BaseRenderer = baseRendererFactory();
|
||||||
const AppContext = contextFactory();
|
const AppContext = contextFactory();
|
||||||
@ -21,7 +18,7 @@ export default function rendererFactory(): IRenderComponent {
|
|||||||
|
|
||||||
const debug = Debug('renderer:entry');
|
const debug = Debug('renderer:entry');
|
||||||
|
|
||||||
class FaultComponent extends PureComponent {
|
class FaultComponent extends PureComponent<NodeSchema> {
|
||||||
render() {
|
render() {
|
||||||
// FIXME: errorlog
|
// FIXME: errorlog
|
||||||
console.error('render error', this.props);
|
console.error('render error', this.props);
|
||||||
@ -35,17 +32,22 @@ export default function rendererFactory(): IRenderComponent {
|
|||||||
color: '#ff0000',
|
color: '#ff0000',
|
||||||
border: '2px solid #ff0000',
|
border: '2px solid #ff0000',
|
||||||
},
|
},
|
||||||
}, '组件渲染异常,请查看控制台日志');
|
}, `${this.props.componentName || ''} 组件渲染异常,请查看控制台日志`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NotFoundComponent extends PureComponent {
|
class NotFoundComponent extends PureComponent<{
|
||||||
|
componentName: string;
|
||||||
|
} & IRendererProps> {
|
||||||
render() {
|
render() {
|
||||||
return createElement(Div, this.props, this.props.children || 'Component Not Found');
|
if (this.props.enableStrictNotFoundMode) {
|
||||||
|
return `${this.props.componentName || ''} Component Not Found`;
|
||||||
|
}
|
||||||
|
return createElement(Div, this.props, this.props.children || `${this.props.componentName || ''} Component Not Found`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return class Renderer extends Component {
|
return class Renderer extends Component<IRendererProps> {
|
||||||
static displayName = 'Renderer';
|
static displayName = 'Renderer';
|
||||||
|
|
||||||
state: Partial<IRendererState> = {};
|
state: Partial<IRendererState> = {};
|
||||||
|
|||||||
@ -21,12 +21,12 @@ interface IGeneralComponent<P = {}, S = {}, SS = any> extends ComponentLifecycle
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IGeneralConstructor<
|
export type IGeneralConstructor<
|
||||||
P = {
|
T = {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}, S = {
|
}, S = {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}, SS = any
|
}, D = any
|
||||||
> = new (props: any, context: any) => IGeneralComponent<P, S, SS>;
|
> = new <TT = T, SS = S, DD = D>(props: TT, context: any) => IGeneralComponent<TT, SS, DD>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* duck-typed History
|
* duck-typed History
|
||||||
@ -133,6 +133,11 @@ export interface IRendererProps {
|
|||||||
* JSExpression 是否只支持使用 this 来访问上下文变量
|
* JSExpression 是否只支持使用 this 来访问上下文变量
|
||||||
*/
|
*/
|
||||||
thisRequiredInJSE?: boolean;
|
thisRequiredInJSE?: boolean;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
* 当开启组件未找到严格模式时,渲染模块不会默认给一个容器组件
|
||||||
|
*/
|
||||||
|
enableStrictNotFoundMode?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRendererState {
|
export interface IRendererState {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user