diff --git a/.eslintrc.js b/.eslintrc.js index 4d573688f..972882ce7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -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, }, }; diff --git a/packages/designer/src/builtin-simulator/host.ts b/packages/designer/src/builtin-simulator/host.ts index 91ab1a17b..fdf26c06c 100644 --- a/packages/designer/src/builtin-simulator/host.ts +++ b/packages/designer/src/builtin-simulator/host.ts @@ -234,6 +234,10 @@ export class BuiltinSimulatorHost implements ISimulatorHost { const { __id, ...viewProps } = props; viewProps.componentId = __id; diff --git a/packages/react-simulator-renderer/src/renderer.ts b/packages/react-simulator-renderer/src/renderer.ts index b3ba1df24..efebeda04 100644 --- a/packages/react-simulator-renderer/src/renderer.ts +++ b/packages/react-simulator-renderer/src/renderer.ts @@ -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; } diff --git a/packages/renderer-core/src/renderer/base.tsx b/packages/renderer-core/src/renderer/base.tsx index a96554908..56f58599b 100644 --- a/packages/renderer-core/src/renderer/base.tsx +++ b/packages/renderer-core/src/renderer/base.tsx @@ -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) => { - 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) => { diff --git a/packages/renderer-core/src/renderer/renderer.tsx b/packages/renderer-core/src/renderer/renderer.tsx index 4968f269a..88cc0ce02 100644 --- a/packages/renderer-core/src/renderer/renderer.tsx +++ b/packages/renderer-core/src/renderer/renderer.tsx @@ -21,7 +21,7 @@ export default function rendererFactory(): IRenderComponent { class FaultComponent extends PureComponent { 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, { diff --git a/packages/renderer-core/src/types/index.ts b/packages/renderer-core/src/types/index.ts index 067bf2153..a49fe8992 100644 --- a/packages/renderer-core/src/types/index.ts +++ b/packages/renderer-core/src/types/index.ts @@ -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 { diff --git a/packages/renderer-core/src/utils/common.ts b/packages/renderer-core/src/utils/common.ts index f2cfc1300..29381b547 100644 --- a/packages/renderer-core/src/utils/common.ts +++ b/packages/renderer-core/src/utils/common.ts @@ -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') {