diff --git a/packages/demo/public/assets.json b/packages/demo/public/assets.json index 6bd972220..2de653885 100644 --- a/packages/demo/public/assets.json +++ b/packages/demo/public/assets.json @@ -300,6 +300,13 @@ "configure": { "component": { "isContainer": true + }, + "props": { + "isExtends": true, + "override": [{ + "name": "dataSource", + "setter": "JsonSetter" + }] } } }, diff --git a/packages/editor-setters/src/json-setter/index.tsx b/packages/editor-setters/src/json-setter/index.tsx index d699bd373..c455e232e 100644 --- a/packages/editor-setters/src/json-setter/index.tsx +++ b/packages/editor-setters/src/json-setter/index.tsx @@ -21,8 +21,8 @@ class MonacoEditorView extends PureComponent { static displayName = 'MonacoEditor'; render() { const { type, ...restProps } = this.props; - let Node = type == 'button' ? MonacoEditorButtonView : MonacoEditorDefaultView; - return Object.assign(this, apis)} />; + const Node = type == 'button' ? MonacoEditorButtonView : MonacoEditorDefaultView; + return Object.assign(this, apis)} />; } } @@ -33,14 +33,15 @@ class MonacoEditorDefaultView extends PureComponent { static displayName = 'MonacoEditorDefault'; static propTypes = { locale: PropTypes.string, - messages: PropTypes.object + messages: PropTypes.object, + language: PropTypes.string, }; static defaultProps = { locale: 'zh-CN', messages: zhCN, width: '100%', height: '300px', - language: 'javascript', + language: 'json', autoFocus: false, //自动获得焦点 autoSubmit: true, //自动提交 placeholder: '', //默认占位内容 @@ -60,14 +61,14 @@ class MonacoEditorDefaultView extends PureComponent { fixedOverflowWidgets: false, snippetSuggestions: 'top', minimap: { - enabled: true + enabled: true, }, scrollbar: { vertical: 'hidden', horizontal: 'hidden', - verticalScrollbarSize: 0 - } - } + verticalScrollbarSize: 0, + }, + }, }; strValue: string; i18n: any; @@ -90,11 +91,11 @@ class MonacoEditorDefaultView extends PureComponent { folding: true, scrollBeyondLastLine: true, minimap: { - enabled: true - } + enabled: true, + }, }; this.state = { - isFullScreen: false + isFullScreen: false, }; this.onChange = this.onChange.bind(this); this.onSubmit = this.onSubmit.bind(this); @@ -118,18 +119,18 @@ class MonacoEditorDefaultView extends PureComponent { setTimeout(() => { this.editor.setPosition({ column: 4, - lineNumber: 2 + lineNumber: 2, }); this.editor.focus(); }, 100); } //快捷键编码 - let CtrlCmd = 2048; - let KEY_S = 49; - let Shift = 1024; - let KEY_F = 36; - let KEY_B = 32; - let Escape = 9; + const CtrlCmd = 2048; + const KEY_S = 49; + const Shift = 1024; + const KEY_F = 36; + const KEY_B = 32; + const Escape = 9; this.editor.addCommand(CtrlCmd | KEY_S, () => { this.onSubmit(); //保存快捷键 @@ -152,12 +153,12 @@ class MonacoEditorDefaultView extends PureComponent { this.editor.toFunction = this.toFunction; //针对object情况,改写setValue和getValue api if (this.props.language === 'object') { - let getValue = this.editor.getValue; - let setValue = this.editor.setValue; + const getValue = this.editor.getValue; + const setValue = this.editor.setValue; this.editor.getValue = () => { return getValue.call(this.editor).substring(this.valuePrefix.length); }; - this.editor.setValue = value => { + this.editor.setValue = (value) => { return setValue.call(this.editor, [this.valuePrefix + value]); }; } @@ -175,7 +176,7 @@ class MonacoEditorDefaultView extends PureComponent { theme, editorWillMount, editorDidMount, - registerApi + registerApi, } = this.props; const { isFullScreen } = this.state; @@ -183,8 +184,8 @@ class MonacoEditorDefaultView extends PureComponent { if (language === 'object') this.valuePrefix = 'export default '; if (!this.isFullScreenAction) { //将值转换成目标值 - let nowValue = this.valueHandler(value || placeholder, language); - let curValue = this.valueHandler(this.strValue, language); + const nowValue = this.valueHandler(value || placeholder, language); + const curValue = this.valueHandler(this.strValue, language); if (nowValue !== curValue) this.strValue = nowValue; if (language === 'object') this.strValue = this.strValue || placeholder || '{\n\t\n}'; //设置初始化值 if (language === 'json' && this.strValue === '{}') this.strValue = '{\n\t\n}'; @@ -195,16 +196,24 @@ class MonacoEditorDefaultView extends PureComponent { if (language === 'object' || language === 'function') { tarLanguage = 'javascript'; } - let classes = classNames('monaco-editor-wrap', { - ['monaco-fullscreen']: !!isFullScreen, - ['monaco-nofullscreen']: !isFullScreen + const classes = classNames('monaco-editor-wrap', { + 'monaco-fullscreen': !!isFullScreen, + 'monaco-nofullscreen': !isFullScreen, }); - let tarStyle = Object.assign({ minHeight: 60, width, height }, style); + const tarStyle = Object.assign({ minHeight: 60, width, height }, style); + let tempValue = this.valuePrefix + this.strValue; + if (tarLanguage === 'json') { + try { + tempValue = JSON.stringify(JSON.parse(tempValue || '{}'), null, 2); + } catch (err) { + console.log(err); + } + } return (
{ this.position = this.editor.getPosition(); - let ret = this.resultHandler(curValue, language); + const ret = this.resultHandler(curValue, language); if (autoSubmit) onChange && onChange(ret.value); onAfterChange && onAfterChange(ret.value, ret.error, this.editor); }, 300); @@ -250,8 +259,8 @@ class MonacoEditorDefaultView extends PureComponent { //提交动作 onSubmit() { const { onSubmit, onChange, language } = this.props; - let curValue = this.editor.getValue(); - let ret = this.resultHandler(curValue, language); + const curValue = this.editor.getValue(); + const ret = this.resultHandler(curValue, language); if (!ret.error) onChange && onChange(ret.value); onSubmit && onSubmit(ret.value, ret.error, this.editor); } @@ -264,7 +273,7 @@ class MonacoEditorDefaultView extends PureComponent { tarValue = JSON.stringify(value, null, 2); } else if (value && typeof value === 'string') { try { - let ret = this.toJson(value); + const ret = this.toJson(value); if (!ret.error) tarValue = JSON.stringify(ret.value, null, 2); } catch (err) {} } @@ -285,7 +294,7 @@ class MonacoEditorDefaultView extends PureComponent { } catch (err) {} } else if (typeof value === 'string') { try { - let ret = this.resultHandler(value, 'object'); + const ret = this.resultHandler(value, 'object'); tarValue = ret.error ? ret.value : serialize(ret.value, { unsafe: true }); tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true }); } catch (err) {} @@ -323,27 +332,28 @@ class MonacoEditorDefaultView extends PureComponent { } else { document.body.appendChild(this.editorNode); } - let nextFs = !this.state.isFullScreen; + const nextFs = !this.state.isFullScreen; this.isFullScreenAction = true; //记录是全屏幕操作 this.setState( { - isFullScreen: nextFs + isFullScreen: nextFs, }, () => { this.editor.updateOptions(nextFs ? this.fullScreenOptions : this.options); - } + }, ); } //美化代码 format() { + const { language } = this.props; if (!this.editor) return; if (/^\$_obj?\{.*?\}$/m.test(this.editor.getValue())) return; if (this.props.language === 'json' || this.props.language === 'object' || this.props.language === 'function') { - let tarValue = js_beautify(this.editor.getValue(), { indent_size: 2 }); + const tarValue = js_beautify(this.editor.getValue(), { indent_size: 2 }); this.editor.setValue(tarValue); } else if (this.props.language === 'less' || this.props.language === 'css' || this.props.language === 'scss') { - let tarValue = css_beautify(this.editor.getValue(), { indent_size: 2 }); + const tarValue = css_beautify(this.editor.getValue(), { indent_size: 2 }); this.editor.setValue(tarValue); } else { this.editor.getAction('editor.action.formatDocument').run(); @@ -353,9 +363,9 @@ class MonacoEditorDefaultView extends PureComponent { //校验是否是json toJson(value) { try { - let obj = new Function(`'use strict'; return ${value.replace(/[\r\n\t]/g, '')}`)(); + const obj = new Function(`'use strict'; return ${value.replace(/[\r\n\t]/g, '')}`)(); if (typeof obj === 'object' && obj) { - let tarValue = new Function(`'use strict'; return ${value}`)(); + const tarValue = new Function(`'use strict'; return ${value}`)(); return { value: JSON.parse(JSON.stringify(tarValue)) }; } return { error: this.i18n('jsonIllegal'), value }; @@ -367,7 +377,7 @@ class MonacoEditorDefaultView extends PureComponent { //校验是否为object对象 toObject(value) { try { - let obj = new Function(`'use strict';return ${value}`)(); + const obj = new Function(`'use strict';return ${value}`)(); if (obj && typeof obj === 'object') { if (jsonuri.isCircular(obj)) return { error: this.i18n('circularRef'), value }; return { value: obj }; @@ -382,7 +392,7 @@ class MonacoEditorDefaultView extends PureComponent { //校验是否为function toFunction(value) { try { - let fun = new Function(`'use strict';return ${value}`)(); + const fun = new Function(`'use strict';return ${value}`)(); if (fun && typeof fun === 'function') { return { value: fun }; } else { @@ -398,13 +408,13 @@ class MonacoEditorDefaultView extends PureComponent { if (registerApiAndSnippetStatus) return; registerApiAndSnippetStatus = true; //注册this.提示的方法; - let thisSuggestions = []; - Snippets.map(item => { + const thisSuggestions = []; + Snippets.map((item) => { if (!item.label || !item.kind || !item.insertText) return; - let tarItem = Object.assign(item, { + const tarItem = Object.assign(item, { label: item.label, kind: monaco.languages.CompletionItemKind[item.kind], - insertText: item.insertText + insertText: item.insertText, }); if (item.insertTextRules) tarItem.insertTextRules = monaco.languages.CompletionItemInsertTextRule[item.insertTextRules]; @@ -412,17 +422,17 @@ class MonacoEditorDefaultView extends PureComponent { }); monaco.languages.registerCompletionItemProvider('javascript', { provideCompletionItems: (model, position) => { - let textUntilPosition = model.getValueInRange({ + const textUntilPosition = model.getValueInRange({ startLineNumber: position.lineNumber, startColumn: 1, endLineNumber: position.lineNumber, - endColumn: position.column + endColumn: position.column, }); - let match = textUntilPosition.match(/(^this\.)|(\sthis\.)/); - let suggestions = match ? thisSuggestions : []; + const match = textUntilPosition.match(/(^this\.)|(\sthis\.)/); + const suggestions = match ? thisSuggestions : []; return { suggestions: suggestions }; }, - triggerCharacters: ['.'] + triggerCharacters: ['.'], }); } } @@ -448,18 +458,18 @@ window.MonacoEnvironment = { } return `${prefix}${encodeURIComponent(` importScripts('${baseUrl}editor.worker.js');`)}`; - } + }, }; export default class MonacoEditorButtonView extends PureComponent { static displayName = 'MonacoEditorButton'; static propTypes = { locale: PropTypes.string, - messages: PropTypes.object + messages: PropTypes.object, }; static defaultProps = { locale: 'zh-CN', - messages: zhCN + messages: zhCN, }; i18n: any; objectButtonRef: React.RefObject; @@ -470,7 +480,7 @@ export default class MonacoEditorButtonView extends PureComponent { // 兼容代码,待去除 window.__ctx.appHelper.constants = window.__ctx.appHelper.constants || {}; } - afterHandler(value: { nrs_temp_field: any; }) { + afterHandler(value: { nrs_temp_field: any }) { if (!value) return; return value.nrs_temp_field; } @@ -485,32 +495,32 @@ export default class MonacoEditorButtonView extends PureComponent { duration: 1000, align: 'cc cc', overlayProps: { - target: dom - } + target: dom, + }, }); } componentDidMount() { const { registerApi } = this.props; - let objectButtonThis = this.objectButtonRef; + const objectButtonThis = this.objectButtonRef; registerApi && registerApi({ show: objectButtonThis.showModal, hide: objectButtonThis.hideModal, submit: objectButtonThis.submitHandler, - setValues: objectButtonThis.setValues + setValues: objectButtonThis.setValues, }); } render() { const self = this; - const { locale, messages, value, onChange, field, ...restProps } = this.props; + const { locale, messages, value, onChange, field, languages, ...restProps } = this.props; const { id } = field; - let tarRestProps = { ...restProps }; + const tarRestProps = { ...restProps }; tarRestProps.autoSubmit = true; tarRestProps.autoFocus = true; - let tarOnSubmit = tarRestProps.onSubmit; + const tarOnSubmit = tarRestProps.onSubmit; //确保monaco快捷键保存,能出发最外层的保存 tarRestProps.onSubmit = (value, error) => { - let msgDom = document.querySelector('.object-button-overlay .next-dialog-body'); + const msgDom = document.querySelector('.object-button-overlay .next-dialog-body'); if (error) return this.message('error', this.i18n('formatError'), msgDom); this.objectButtonRef && this.objectButtonRef.current && @@ -518,16 +528,17 @@ export default class MonacoEditorButtonView extends PureComponent { this.message('success', this.i18n('saved'), msgDom); }); }; - let tarObjProps = { }; + const tarObjProps = {}; tarObjProps.className = 'luna-monaco-button'; if (tarRestProps['data-meta']) { delete tarRestProps['data-meta']; tarObjProps['data-meta'] = 'Field'; } + tarObjProps.id = id; tarObjProps.value = value || ''; tarObjProps.onChange = onChange; - let tarRule = []; + const tarRule = []; //判断,如果是json,function, object等类型,自动追加校验规则; if (tarRestProps.language && ['json', 'function', 'object'].includes(tarRestProps.language)) { if (['json', 'object'].includes(tarRestProps.language)) { @@ -538,7 +549,7 @@ export default class MonacoEditorButtonView extends PureComponent { } else { callback(); } - } + }, }); } else { tarRule.push({ @@ -548,7 +559,7 @@ export default class MonacoEditorButtonView extends PureComponent { } else { callback(); } - } + }, }); } } @@ -564,10 +575,10 @@ export default class MonacoEditorButtonView extends PureComponent { onSubmit={tarOnSubmit} > - Object.assign(this, apis)} /> + Object.assign(this, apis)} />
); } -} \ No newline at end of file +} diff --git a/packages/editor-skeleton/src/components/array-setter/index.tsx b/packages/editor-skeleton/src/components/array-setter/index.tsx index 2f12b6e8f..5617b0f35 100644 --- a/packages/editor-skeleton/src/components/array-setter/index.tsx +++ b/packages/editor-skeleton/src/components/array-setter/index.tsx @@ -39,7 +39,7 @@ export class ListSetter extends Component { } const itemsMap = state ? state.itemsMap : new Map(); - let items = state ? state.items.slice() : []; + const items = state ? state.items.slice() : []; if (newLength > originLength) { for (let i = originLength; i < newLength; i++) { const item = field.createField({ @@ -82,9 +82,10 @@ export class ListSetter extends Component { }); } - private scrollToLast: boolean = false; + private scrollToLast = false; onAdd() { const { items, itemsMap } = this.state; + debugger; const { itemSetter } = this.props; const initialValue = typeof itemSetter === 'object' ? (itemSetter as any).initialValue : null; const item = this.props.field.createField({ @@ -134,7 +135,9 @@ export class ListSetter extends Component { render() { let columns: any = null; if (this.props.columns) { - columns = this.props.columns.map((column) => ); + columns = this.props.columns.map((column) => ( + <Title key={column.name} title={column.title || (column.name as string)} /> + )); } const { items } = this.state; diff --git a/packages/editor-skeleton/src/register-defaults.ts b/packages/editor-skeleton/src/register-defaults.ts index 3c114e43d..b18decb13 100644 --- a/packages/editor-skeleton/src/register-defaults.ts +++ b/packages/editor-skeleton/src/register-defaults.ts @@ -37,7 +37,7 @@ registerSetter('SlotSetter', { title: { type: 'i18n', 'zh-CN': '插槽输入', - 'en-US': 'Slot Setter' + 'en-US': 'Slot Setter', }, condition: (field: any) => { return isJSSlot(field.getValue()); @@ -48,7 +48,7 @@ registerSetter('SlotSetter', { } return { type: 'JSSlot', - value: value + value: value, }; }, recommend: true, diff --git a/packages/editor-skeleton/src/transducers/addon-combine.ts b/packages/editor-skeleton/src/transducers/addon-combine.ts index a3b2f066f..890fa5742 100644 --- a/packages/editor-skeleton/src/transducers/addon-combine.ts +++ b/packages/editor-skeleton/src/transducers/addon-combine.ts @@ -46,7 +46,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp const isRoot: boolean = componentName === 'Page' || componentName === 'Component'; const eventsDefinition: any[] = []; const supportedLifecycles = - supports.lifecycles || + supports.lifecycles || (isRoot ? /*[ { @@ -87,22 +87,24 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp if (componentName === 'Slot') { if (!configure.component) { configure.component = { - isContainer: true - } - } else if (typeof configure.component === 'object'){ + isContainer: true, + }; + } else if (typeof configure.component === 'object') { configure.component.isContainer = true; } basicInfo.icon = IconSlot; - propsGroup = [{ - name: getConvertedExtraKey('title'), - title: { - type: 'i18n', - 'en-US': 'Slot Title', - 'zh-CN': '插槽标题' + propsGroup = [ + { + name: getConvertedExtraKey('title'), + title: { + type: 'i18n', + 'en-US': 'Slot Title', + 'zh-CN': '插槽标题', + }, + setter: 'StringSetter', + defaultValue: '插槽容器', }, - setter: 'StringSetter', - defaultValue: '插槽容器' - }] + ]; } /* propsGroup.push({ @@ -199,13 +201,13 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp }, setValue(field: SettingTarget, eventDataList: any[]) { - eventDataList.map((item)=>{ - field.parent.setPropValue(item.name,{ + eventDataList.map((item) => { + field.parent.setPropValue(item.name, { type: 'JSFunction', - value: `function(){ this.${item.relatedEventName}() }` - }) + value: `function(){ this.${item.relatedEventName}() }`, + }); return item; - }) + }); return; }, }, @@ -219,11 +221,14 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp name: getConvertedExtraKey('condition'), title: { type: 'i18n', 'zh-CN': '是否渲染', 'en-US': 'Condition' }, defaultValue: true, - setter: [{ - componentName: 'BoolSetter', - }, { - componentName: 'VariableSetter' - }], + setter: [ + { + componentName: 'BoolSetter', + }, + { + componentName: 'VariableSetter', + }, + ], }); } if (supports.loop !== false) { @@ -235,14 +240,17 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp name: getConvertedExtraKey('loop'), title: { type: 'i18n', 'zh-CN': '循环数据', 'en-US': 'Loop Data' }, defaultValue: [], - setter: [{ - componentName: 'JsonSetter', - props: { - label: { type: 'i18n', 'zh-CN': '编辑数据', 'en-US': 'Edit Data'}, + setter: [ + { + componentName: 'JsonSetter', + props: { + label: { type: 'i18n', 'zh-CN': '编辑数据', 'en-US': 'Edit Data' }, + }, }, - }, { - componentName: 'VariableSetter' - }], + { + componentName: 'VariableSetter', + }, + ], }, { name: getConvertedExtraKey('loopArgs.0'), @@ -251,7 +259,7 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp componentName: 'StringSetter', props: { placeholder: { type: 'i18n', 'zh-CN': '默认为: item', 'en-US': 'Defaults: item' }, - } + }, }, }, { @@ -261,20 +269,23 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp componentName: 'StringSetter', props: { placeholder: { type: 'i18n', 'zh-CN': '默认为: index', 'en-US': 'Defaults: index' }, - } + }, }, }, { name: 'key', title: '循环 Key', - setter: [{ - componentName: 'StringSetter', - }, { - componentName: 'VariableSetter' - }], + setter: [ + { + componentName: 'StringSetter', + }, + { + componentName: 'VariableSetter', + }, + ], }, ], - }) + }); } } if (advanceGroup.length > 0) { diff --git a/packages/editor-skeleton/src/transducers/parse-props.ts b/packages/editor-skeleton/src/transducers/parse-props.ts index 4d2659873..0bf803e41 100644 --- a/packages/editor-skeleton/src/transducers/parse-props.ts +++ b/packages/editor-skeleton/src/transducers/parse-props.ts @@ -23,7 +23,8 @@ function propConfigToFieldConfig(propConfig: PropConfig): FieldConfig { return { title, ...propConfig, - setter: propTypeToSetter(propConfig.propType), + // TODO 这边直接用propConfig,将setter丢在propconfig里,需要确认是否在PropConfig扩展还是换实现 + setter: propConfig.setter ? propConfig.setter : propTypeToSetter(propConfig.propType), }; } @@ -32,7 +33,7 @@ function propTypeToSetter(propType: PropType): SetterType { let isRequired: boolean | undefined = false; if (typeof propType === 'string') { typeName = propType; - } else if (typeof propType === 'object'){ + } else if (typeof propType === 'object') { typeName = propType.type; isRequired = propType.isRequired; } else { @@ -123,6 +124,7 @@ function propTypeToSetter(propType: PropType): SetterType { }, }, isRequired, + initialValue: {}, }; case 'array': case 'arrayOf': @@ -163,9 +165,29 @@ function propTypeToSetter(propType: PropType): SetterType { const EVENT_RE = /^on[A-Z][\w]*$/; export default function(metadata: TransformedComponentMetadata): TransformedComponentMetadata { - const { configure } = metadata; + const { configure = {} } = metadata; + // TODO types后续补充 + let extendsProps: any = null; if (configure.props) { - return metadata; + if (Array.isArray(configure.props)) { + return metadata; + } + const { isExtends, override = [] } = configure.props; + // 不开启继承时,直接返回configure配置 + if (!isExtends) { + return { + ...metadata, + configure: { + props: [...override], + }, + }; + } + + extendsProps = {}; + // 开启继承后,缓存重写内容的配置 + override.forEach((prop: any) => { + extendsProps[prop.name] = prop; + }); } if (!metadata.props) { @@ -218,6 +240,14 @@ export default function(metadata: TransformedComponentMetadata): TransformedComp return; } + // 存在覆盖配置时 + if (extendsProps) { + debugger; + if (name in extendsProps) { + prop = extendsProps[name]; + } + } + props.push(propConfigToFieldConfig(prop)); }); diff --git a/packages/types/src/field-config.ts b/packages/types/src/field-config.ts index 8dc176fe8..e95d07081 100644 --- a/packages/types/src/field-config.ts +++ b/packages/types/src/field-config.ts @@ -51,7 +51,7 @@ export interface FieldExtraProps { mode?: 'plaintext' | 'paragraph' | 'article'; // 从 contentEditable 获取内容并设置到属性 onSaveContent?: (content: string, prop: any) => any; - } + }; } export interface FieldConfig extends FieldExtraProps {