feat: improve lowcode component error state in simulator renderer (#1818)
* feat: improve lowcode component error state in simulator renderer * chore: use faultComponentMap instead of ComponentRender.FaultComponent
This commit is contained in:
parent
d0c3c0f13c
commit
d64da1e065
|
@ -52,6 +52,8 @@ module.exports = {
|
|||
'error',
|
||||
{ default: ['signature', 'field', 'constructor', 'method'] }
|
||||
],
|
||||
'@typescript-eslint/no-unused-vars': ['error']
|
||||
'@typescript-eslint/no-unused-vars': ['error'],
|
||||
'no-redeclare': 0,
|
||||
'@typescript-eslint/no-redeclare': 1,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -234,6 +234,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
|
|||
return engineConfig.get('faultComponent') ?? null;
|
||||
}
|
||||
|
||||
get faultComponentMap(): any {
|
||||
return engineConfig.get('faultComponentMap') ?? null;
|
||||
}
|
||||
|
||||
@computed get componentsAsset(): Asset | undefined {
|
||||
return this.get('componentsAsset');
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ class Renderer extends Component<{
|
|||
thisRequiredInJSE={host.thisRequiredInJSE}
|
||||
notFoundComponent={host.notFoundComponent}
|
||||
faultComponent={host.faultComponent}
|
||||
faultComponentMap={host.faultComponentMap}
|
||||
customCreateElement={(Component: any, props: any, children: any) => {
|
||||
const { __id, ...viewProps } = props;
|
||||
viewProps.componentId = __id;
|
||||
|
|
|
@ -465,6 +465,7 @@ export class SimulatorRendererContainer implements BuiltinSimulatorRenderer {
|
|||
rendererName: 'LowCodeRenderer',
|
||||
thisRequiredInJSE: host.thisRequiredInJSE,
|
||||
faultComponent: host.faultComponent,
|
||||
faultComponentMap: host.faultComponentMap,
|
||||
customCreateElement: (Comp: any, props: any, children: any) => {
|
||||
const componentMeta = host.currentDocument?.getComponentMeta(Comp.displayName);
|
||||
if (componentMeta?.isModal) {
|
||||
|
@ -629,6 +630,7 @@ function getLowCodeComponentProps(props: any) {
|
|||
}
|
||||
newProps[k] = props[k];
|
||||
});
|
||||
newProps['componentName'] = props['_componentName'];
|
||||
return newProps;
|
||||
}
|
||||
|
||||
|
|
|
@ -161,7 +161,9 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
|||
constructor(props: IBaseRendererProps, context: IBaseRendererContext) {
|
||||
super(props, context);
|
||||
this.context = context;
|
||||
this.__parseExpression = props?.thisRequiredInJSE ? parseThisRequiredExpression : parseExpression;
|
||||
this.__parseExpression = (str: string, self: any) => {
|
||||
return parseExpression({ str, self, thisRequired: props?.thisRequiredInJSE, logScope: props.componentName });
|
||||
};
|
||||
this.__beforeInit(props);
|
||||
this.__init(props);
|
||||
this.__afterInit(props);
|
||||
|
@ -299,8 +301,8 @@ export default function baseRendererFactory(): IBaseRenderComponent {
|
|||
};
|
||||
|
||||
__parseData = (data: any, ctx?: Record<string, any>) => {
|
||||
const { __ctx, thisRequiredInJSE } = this.props;
|
||||
return parseData(data, ctx || __ctx || this, { thisRequiredInJSE });
|
||||
const { __ctx, thisRequiredInJSE, componentName } = this.props;
|
||||
return parseData(data, ctx || __ctx || this, { thisRequiredInJSE, logScope: componentName });
|
||||
};
|
||||
|
||||
__initDataSource = (props: IBaseRendererProps) => {
|
||||
|
|
|
@ -21,7 +21,7 @@ export default function rendererFactory(): IRenderComponent {
|
|||
|
||||
class FaultComponent extends PureComponent<IPublicTypeNodeSchema | any> {
|
||||
render() {
|
||||
logger.error(`%c组件渲染异常, 异常原因: ${this.props.error?.message || this.props.error || '未知'}`, 'color: #ff0000;');
|
||||
logger.error(`%c${this.props.componentName || ''} 组件渲染异常, 异常原因: ${this.props.error?.message || this.props.error || '未知'}`, 'color: #ff0000;');
|
||||
return createElement(Div, {
|
||||
style: {
|
||||
width: '100%',
|
||||
|
@ -159,7 +159,25 @@ export default function rendererFactory(): IRenderComponent {
|
|||
}
|
||||
|
||||
getFaultComponent() {
|
||||
return this.props.faultComponent || FaultComponent;
|
||||
const { faultComponent, faultComponentMap, schema } = this.props;
|
||||
if (faultComponentMap) {
|
||||
const { componentName } = schema;
|
||||
return faultComponentMap[componentName] || faultComponent || FaultComponent;
|
||||
}
|
||||
return faultComponent || FaultComponent;
|
||||
}
|
||||
|
||||
getComp() {
|
||||
const { schema, components } = this.props;
|
||||
const { componentName } = schema;
|
||||
const allComponents = { ...RENDERER_COMPS, ...components };
|
||||
let Comp = allComponents[componentName] || RENDERER_COMPS[`${componentName}Renderer`];
|
||||
if (Comp && Comp.prototype) {
|
||||
if (!(Comp.prototype instanceof BaseRenderer)) {
|
||||
Comp = RENDERER_COMPS[`${componentName}Renderer`];
|
||||
}
|
||||
}
|
||||
return Comp;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -173,14 +191,8 @@ export default function rendererFactory(): IRenderComponent {
|
|||
return '模型结构异常';
|
||||
}
|
||||
debug('entry.render');
|
||||
const { componentName } = schema;
|
||||
const allComponents = { ...RENDERER_COMPS, ...components };
|
||||
let Comp = allComponents[componentName] || RENDERER_COMPS[`${componentName}Renderer`];
|
||||
if (Comp && Comp.prototype) {
|
||||
if (!(Comp.prototype instanceof BaseRenderer)) {
|
||||
Comp = RENDERER_COMPS[`${componentName}Renderer`];
|
||||
}
|
||||
}
|
||||
let Comp = this.getComp();
|
||||
|
||||
if (this.state && this.state.engineRenderError) {
|
||||
return createElement(this.getFaultComponent(), {
|
||||
|
@ -190,11 +202,13 @@ export default function rendererFactory(): IRenderComponent {
|
|||
}
|
||||
|
||||
if (Comp) {
|
||||
return createElement(AppContext.Provider, { value: {
|
||||
appHelper,
|
||||
components: allComponents,
|
||||
engine: this,
|
||||
} }, createElement(ConfigProvider, {
|
||||
return createElement(AppContext.Provider, {
|
||||
value: {
|
||||
appHelper,
|
||||
components: allComponents,
|
||||
engine: this,
|
||||
},
|
||||
}, createElement(ConfigProvider, {
|
||||
device: this.props.device,
|
||||
locale: this.props.locale,
|
||||
}, createElement(Comp, {
|
||||
|
|
|
@ -160,6 +160,11 @@ export interface IRendererProps {
|
|||
/** 当组件渲染异常时,显示的组件 */
|
||||
faultComponent?: IGeneralComponent;
|
||||
|
||||
/** */
|
||||
faultComponentMap?: {
|
||||
[prop: string]: IGeneralComponent;
|
||||
};
|
||||
|
||||
/** 设备信息 */
|
||||
device?: string;
|
||||
|
||||
|
@ -208,6 +213,7 @@ export interface IBaseRendererProps {
|
|||
* 设备类型,默认值:'default'
|
||||
*/
|
||||
device?: 'default' | 'mobile' | string;
|
||||
componentName?: string;
|
||||
}
|
||||
|
||||
export interface INodeInfo {
|
||||
|
|
|
@ -157,6 +157,7 @@ export function canAcceptsRef(Comp: any) {
|
|||
// eslint-disable-next-line max-len
|
||||
return Comp?.$$typeof === REACT_FORWARD_REF_TYPE || Comp?.prototype?.isReactComponent || Comp?.prototype?.setState || Comp._forwardRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* transform array to a object
|
||||
* @param arr array to be transformed
|
||||
|
@ -207,7 +208,6 @@ export function checkPropTypes(value: any, name: string, rule: any, componentNam
|
|||
return !err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* transform string to a function
|
||||
* @param str function in string form
|
||||
|
@ -230,7 +230,26 @@ export function transformStringToFunction(str: string) {
|
|||
* @param self scope object
|
||||
* @returns funtion
|
||||
*/
|
||||
export function parseExpression(str: any, self: any, thisRequired = false) {
|
||||
|
||||
function parseExpression(options: {
|
||||
str: any; self: any; thisRequired?: boolean; logScope?: string;
|
||||
}): any;
|
||||
function parseExpression(str: any, self: any, thisRequired?: boolean): any;
|
||||
function parseExpression(a: any, b?: any, c = false) {
|
||||
let str;
|
||||
let self;
|
||||
let thisRequired;
|
||||
let logScope;
|
||||
if (typeof a === 'object' && b === undefined) {
|
||||
str = a.str;
|
||||
self = a.self;
|
||||
thisRequired = a.thisRequired;
|
||||
logScope = a.logScope;
|
||||
} else {
|
||||
str = a;
|
||||
self = b;
|
||||
thisRequired = c;
|
||||
}
|
||||
try {
|
||||
const contextArr = ['"use strict";', 'var __self = arguments[0];'];
|
||||
contextArr.push('return ');
|
||||
|
@ -250,11 +269,15 @@ export function parseExpression(str: any, self: any, thisRequired = false) {
|
|||
const code = `with(${thisRequired ? '{}' : '$scope || {}'}) { ${tarStr} }`;
|
||||
return new Function('$scope', code)(self);
|
||||
} catch (err) {
|
||||
logger.error('parseExpression.error', err, str, self?.__self ?? self);
|
||||
logger.error(`${logScope || ''} parseExpression.error`, err, str, self?.__self ?? self);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
parseExpression,
|
||||
};
|
||||
|
||||
export function parseThisRequiredExpression(str: any, self: any) {
|
||||
return parseExpression(str, self, true);
|
||||
}
|
||||
|
@ -320,11 +343,17 @@ export function forEach(targetObj: any, fn: any, context?: any) {
|
|||
|
||||
interface IParseOptions {
|
||||
thisRequiredInJSE?: boolean;
|
||||
logScope?: string;
|
||||
}
|
||||
|
||||
export function parseData(schema: unknown, self: any, options: IParseOptions = {}): any {
|
||||
if (isJSExpression(schema)) {
|
||||
return parseExpression(schema, self, options.thisRequiredInJSE);
|
||||
return parseExpression({
|
||||
str: schema,
|
||||
self,
|
||||
thisRequired: options.thisRequiredInJSE,
|
||||
logScope: options.logScope,
|
||||
});
|
||||
} else if (isI18nData(schema)) {
|
||||
return parseI18n(schema, self);
|
||||
} else if (typeof schema === 'string') {
|
||||
|
|
Loading…
Reference in New Issue