diff --git a/packages/designer/src/designer/setting/setting-field.ts b/packages/designer/src/designer/setting/setting-field.ts index 0d86208f9..a024afaac 100644 --- a/packages/designer/src/designer/setting/setting-field.ts +++ b/packages/designer/src/designer/setting/setting-field.ts @@ -120,7 +120,7 @@ export class SettingField extends SettingPropEntry implements SettingEntry { // ======= compatibles for vision ====== getHotValue(): any { // avoid View modify - let v = cloneDeep(this.getValue()); + let v = cloneDeep(this.getMockOrValue()); if (v == null) { v = this.extraProps.defaultValue; } @@ -128,7 +128,17 @@ export class SettingField extends SettingPropEntry implements SettingEntry { } setHotValue(data: any) { - this.setValue(this.transducer.toNative(data)); + const v = this.transducer.toNative(data); + if (this.isUseVariable()) { + const ov = this.getValue(); + this.setValue({ + type: 'JSExpression', + value: ov.value, + mock: v, + }); + } else { + this.setValue(v); + } this.valueChange(); } diff --git a/packages/designer/src/designer/setting/setting-prop-entry.ts b/packages/designer/src/designer/setting/setting-prop-entry.ts index ac241ec05..303ef9caa 100644 --- a/packages/designer/src/designer/setting/setting-prop-entry.ts +++ b/packages/designer/src/designer/setting/setting-prop-entry.ts @@ -101,7 +101,7 @@ export class SettingPropEntry implements SettingEntry { * 获取当前属性值 */ @computed getValue(): any { - let val: any = null; + let val: any = undefined; if (this.type === 'field') { val = this.parent.getPropValue(this.name); } diff --git a/packages/designer/src/designer/setting/utils.js b/packages/designer/src/designer/setting/utils.js index c49011bbf..2aa3b6eaf 100644 --- a/packages/designer/src/designer/setting/utils.js +++ b/packages/designer/src/designer/setting/utils.js @@ -46,7 +46,7 @@ export class Transducer { setter = setter.componentName; } if (typeof setter === 'string') { - setter = getSetter(setter); + setter = getSetter(setter).component; } this.setterTransducer = combineTransducer( diff --git a/packages/designer/src/document/node/node.ts b/packages/designer/src/document/node/node.ts index 6239cfa60..bbe624cd0 100644 --- a/packages/designer/src/document/node/node.ts +++ b/packages/designer/src/document/node/node.ts @@ -504,7 +504,7 @@ export class Node { const schema: any = { ...baseSchema, props: this.document.designer.transformProps(props, this, stage), - ..._extras_, + ...this.document.designer.transformProps(_extras_, this, stage), }; if (this.isParental() && this.children.size > 0) { diff --git a/packages/editor-core/src/intl/ali-global-locale.ts b/packages/editor-core/src/intl/ali-global-locale.ts index 1d4127649..1f74d719b 100644 --- a/packages/editor-core/src/intl/ali-global-locale.ts +++ b/packages/editor-core/src/intl/ali-global-locale.ts @@ -35,7 +35,16 @@ class AliGlobalLocale { if (this._locale != null) { return this._locale; } - const { g_config, navigator } = window as any; + + // TODO: store 1 & store 2 abstract out as custom implements + + // store 1: config from window + let locale: string = getConfig('locale'); + if (locale) { + return languageMap[locale] || locale.replace('_', '-'); + } + + // store 2: config from storage if (hasLocalStorage(window)) { const store = window.localStorage; let config: any; @@ -47,20 +56,14 @@ class AliGlobalLocale { if (config?.locale) { return (config.locale || '').replace('_', '-'); } - } else if (g_config) { - if (g_config.locale) { - return languageMap[g_config.locale] || g_config.locale.replace('_', '-'); - } } - let locale: string = ''; + // store 2: config from system + const { navigator } = window as any; if (navigator.language) { const lang = (navigator.language as string); return languageMap[lang] || lang.replace('_', '-'); - } - - // IE10 及更低版本使用 browserLanguage - if (navigator.browserLanguage) { + } else if (navigator.browserLanguage) { const it = navigator.browserLanguage.split('-'); locale = it[0]; if (it[1]) { @@ -116,6 +119,15 @@ class AliGlobalLocale { } } +function getConfig(name: string) { + const win: any = window; + return ( + win[name] + || (win.g_config || {})[name] + || (win.pageConfig || {})[name] + ); +} + function hasLocalStorage(obj: any): obj is WindowLocalStorage { return obj.localStorage; } diff --git a/packages/editor-skeleton/src/icons/convert.tsx b/packages/editor-skeleton/src/icons/convert.tsx index 2db5e2063..f69d9e104 100644 --- a/packages/editor-skeleton/src/icons/convert.tsx +++ b/packages/editor-skeleton/src/icons/convert.tsx @@ -3,12 +3,7 @@ import { SVGIcon, IconProps } from "@ali/lowcode-utils"; export function IconConvert(props: IconProps) { return ( - - - - - - + ); } diff --git a/packages/editor-skeleton/src/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts index aad1cb86e..8c2f55639 100644 --- a/packages/editor-skeleton/src/transducers/addon-combine.ts +++ b/packages/editor-skeleton/src/transducers/addon-combine.ts @@ -13,7 +13,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp name: 'children', title: { type: 'i18n', 'zh-CN': '内容设置', 'en-US': 'Content' }, setter: { - componentName: 'MixinSetter', + componentName: 'MixedSetter', props: { // TODO: setters: [ @@ -41,11 +41,11 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }; } - const { props, events = {}, styles } = configure as any; + const { props, supports = {} } = configure as any; const isRoot: boolean = componentName === 'Page' || componentName === 'Component'; const eventsDefinition: any[] = []; const supportedLifecycles = - events.supportedLifecycles || + supports.lifecycles || (isRoot ? /*[ { @@ -73,11 +73,11 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp list: supportedLifecycles.map((event: any) => (typeof event === 'string' ? { name: event } : event)), }); } - if (events.supportedEvents) { + if (supports.events) { eventsDefinition.push({ type: 'events', title: '事件', - list: (events.supportedEvents || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)), + list: (supports.events || []).map((event: any) => (typeof event === 'string' ? { name: event } : event)), }); } // 通用设置 @@ -150,14 +150,14 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp items: propsGroup, }, ]; - if (styles?.supportClassName) { + if (supports.className) { stylesGroup.push({ name: 'className', title: { type: 'i18n', 'zh-CN': '类名绑定', 'en-US': 'ClassName' }, setter: 'ClassNameSetter', }); } - if (styles?.supportInlineStyle) { + if (supports.style) { stylesGroup.push({ name: 'style', title: { type: 'i18n', 'zh-CN': '行内样式', 'en-US': 'Style' }, @@ -201,8 +201,8 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp } if (!isRoot) { - advanceGroup = advanceGroup.concat([ - { + if (supports.condition !== false) { + advanceGroup.push({ name: '___condition', title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' }, defaultValue: true, @@ -211,14 +211,17 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }, { componentName: 'VariableSetter' }], - }, - { + }); + } + if (supports.loop !== false) { + advanceGroup.push({ name: '#loop', title: { type: 'i18n', 'zh-CN': '循环', 'en-US': 'Loop' }, items: [ { name: '___loop', title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' }, + defaultValue: [], setter: [{ componentName: 'JsonSetter', props: { @@ -258,8 +261,8 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }], }, ], - }, - ]) + }) + } } if (advanceGroup.length > 0) { combined.push({ diff --git a/packages/editor-skeleton/src/transducers/parse-props.ts b/packages/editor-skeleton/src/transducers/parse-props.ts index bbf107a81..2ea525ef2 100644 --- a/packages/editor-skeleton/src/transducers/parse-props.ts +++ b/packages/editor-skeleton/src/transducers/parse-props.ts @@ -143,7 +143,7 @@ function propTypeToSetter(propType: PropType): SetterType { }; case 'oneOfType': return { - componentName: 'MixinSetter', + componentName: 'MixedSetter', props: { // TODO: // setters: (propType as OneOfType).value.map(item => propTypeToSetter(item)), @@ -153,7 +153,7 @@ function propTypeToSetter(propType: PropType): SetterType { } return { - componentName: 'MixinSetter', + componentName: 'MixedSetter', isRequired, }; } @@ -175,8 +175,8 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }, }; } - const { component = {}, events = {}, styles = {} } = configure; - const supportedEvents: any[] | null = (events as any).supportedEvents ? null : []; + const { component = {}, supports = {} } = configure; + const supportedEvents: any[] | null = (supports as any).events ? null : []; const props: FieldConfig[] = []; metadata.props.forEach((prop) => { @@ -197,21 +197,21 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp name, description, }); - (events as any).supportedEvents = supportedEvents; + (supports as any).events = supportedEvents; } return; } if (name === 'className' && (propType === 'string' || propType === 'any')) { - if ((styles as any).supportClassName == null) { - (styles as any).supportClassName = true; + if ((supports as any).className == null) { + (supports as any).className = true; } return; } if (name === 'style' && (propType === 'object' || propType === 'any')) { - if ((styles as any).supportInlineStyle == null) { - (styles as any).supportInlineStyle = true; + if ((supports as any).style == null) { + (supports as any).style = true; } return; } @@ -224,8 +224,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp configure: { ...configure, props, - events, - styles, + supports, component, }, }; diff --git a/packages/react-renderer/src/engine/base.jsx b/packages/react-renderer/src/engine/base.jsx index 361c0057b..b2456deb4 100644 --- a/packages/react-renderer/src/engine/base.jsx +++ b/packages/react-renderer/src/engine/base.jsx @@ -233,7 +233,7 @@ export default class BaseEngine extends PureComponent { return null; } - if (schema.loop !== undefined) { + if (schema.loop != null) { return this.__createLoopVirtualDom( { ...schema, @@ -244,7 +244,7 @@ export default class BaseEngine extends PureComponent { idx, ); } - const condition = schema.condition === undefined ? true : parseData(schema.condition, self); + const condition = schema.condition == null ? true : parseData(schema.condition, self); if (!condition) return null; let scopeKey = ''; diff --git a/packages/types/src/metadata.ts b/packages/types/src/metadata.ts index 64e3e831f..b6fc5f0fc 100644 --- a/packages/types/src/metadata.ts +++ b/packages/types/src/metadata.ts @@ -78,9 +78,16 @@ export interface Experimental { export interface Configure { props?: FieldConfig[]; - styles?: object; - events?: object; component?: ComponentConfigure; + supports?: { + events?: any[]; + className?: boolean; + style?: boolean; + lifecycles?: any[]; + // general?: boolean; + loop?: boolean; + condition?: boolean; + }; } export interface ActionContentObject { diff --git a/packages/vision-preset/src/bundle/upgrade-metadata.ts b/packages/vision-preset/src/bundle/upgrade-metadata.ts index 437bdaff9..adecb0624 100644 --- a/packages/vision-preset/src/bundle/upgrade-metadata.ts +++ b/packages/vision-preset/src/bundle/upgrade-metadata.ts @@ -141,7 +141,8 @@ export interface OldPrototypeConfig { canDragging?: boolean; // => ? canOperating?: boolean; // => disabledActions - canSelecting?: boolean; + canUseCondition?: boolean; + canLoop?: boolean; canContain?: (dragment: Node) => boolean; // => nestingRule canDropTo?: ((container: Node) => boolean) | boolean | string | string[]; // => nestingRule @@ -545,6 +546,8 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { canDropto, canDropIn, canDroping, + canUseCondition, + canLoop, // hooks canDraging, @@ -727,9 +730,16 @@ export function upgradeMetadata(oldConfig: OldPrototypeConfig) { }); experimental.initials = initials; - const events = {}; - const styles = {}; - meta.configure = { props, component, events, styles }; + const supports: any = {}; + if (canUseCondition != null) { + console.info('canUseCondition', componentName); + supports.condition = canUseCondition; + } + if (canLoop != null) { + console.info('canLoop', componentName); + supports.loop = canLoop; + } + meta.configure = { props, component, supports }; meta.experimental = experimental; return meta; } diff --git a/packages/vision-preset/src/editor.ts b/packages/vision-preset/src/editor.ts index 0c46f4740..65e064c37 100644 --- a/packages/vision-preset/src/editor.ts +++ b/packages/vision-preset/src/editor.ts @@ -1,4 +1,4 @@ -import { isJSBlock } from '@ali/lowcode-types'; +import { isJSBlock, isJSExpression, isJSSlot } from '@ali/lowcode-types'; import { isPlainObject } from '@ali/lowcode-utils'; import { globalContext, Editor } from '@ali/lowcode-editor-core'; import { Designer, TransformStage, addBuiltinComponentAction } from '@ali/lowcode-designer'; @@ -20,6 +20,7 @@ editor.set(Skeleton, skeleton); export const designer = new Designer({ editor: editor }); editor.set(Designer, designer); +// 节点 props 初始化 designer.addPropsReducer((props, node) => { // run initials const initials = node.componentMeta.getMetadata().experimental?.initials; @@ -37,6 +38,7 @@ designer.addPropsReducer((props, node) => { return props; }, TransformStage.Init); +// 国际化渲染时处理 designer.addPropsReducer(i18nReducer, TransformStage.Render); function upgradePropsReducer(props: any) { @@ -64,6 +66,7 @@ function upgradePropsReducer(props: any) { }); return newProps; } +// 升级 Props designer.addPropsReducer(upgradePropsReducer, TransformStage.Init); // 设计器组件样式处理 @@ -97,6 +100,31 @@ function stylePropsReducer(props: any, node: any) { } designer.addPropsReducer(stylePropsReducer, TransformStage.Render); +// FIXME: 表达式使用 mock 值,未来live 模式直接使用原始值 +function expressionReducer(obj?: any): any { + if (!obj) { + return obj; + } + if (Array.isArray(obj)) { + return obj.map((item) => expressionReducer(item)); + } + if (isPlainObject(obj)) { + if (isJSExpression(obj)) { + return obj.mock; + } + if (isJSSlot(obj)) { + return obj; + } + const out: any = {}; + Object.keys(obj).forEach((key) => { + out[key] = expressionReducer(obj[key]); + }); + return out; + } + return obj; +} +designer.addPropsReducer(expressionReducer, TransformStage.Render); + skeleton.add({ area: 'mainArea', name: 'designer',