修改表格datasource,支持setter继承特性

This commit is contained in:
荣彬 2020-07-26 12:43:05 +08:00
parent f9bfb0a7c7
commit 1da85ced92
7 changed files with 180 additions and 118 deletions

View File

@ -300,6 +300,13 @@
"configure": {
"component": {
"isContainer": true
},
"props": {
"isExtends": true,
"override": [{
"name": "dataSource",
"setter": "JsonSetter"
}]
}
}
},

View File

@ -21,8 +21,8 @@ class MonacoEditorView extends PureComponent {
static displayName = 'MonacoEditor';
render() {
const { type, ...restProps } = this.props;
let Node = type == 'button' ? MonacoEditorButtonView : MonacoEditorDefaultView;
return <Node {...restProps} registerApi={apis => Object.assign(this, apis)} />;
const Node = type == 'button' ? MonacoEditorButtonView : MonacoEditorDefaultView;
return <Node {...restProps} registerApi={(apis) => 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 (
<div className={className} style={tarStyle}>
<div ref={this.editorRef} style={{ height: '100%' }} className={classes}>
<MonacoEditor
value={this.valuePrefix + this.strValue}
value={tempValue}
width="100%"
height="300"
language={tarLanguage}
@ -241,7 +250,7 @@ class MonacoEditorDefaultView extends PureComponent {
if (this.ct) clearTimeout(this.ct);
this.ct = setTimeout(() => {
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<unknown>;
@ -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 = [];
//判断如果是jsonfunction, 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}
>
<FormItem name="nrs_temp_field" rules={tarRule}>
<MonacoEditorDefaultView {...tarRestProps} registerApi={(apis: any) => Object.assign(this, apis)} />
<MonacoEditorDefaultView {...tarRestProps} registerApi={(apis: any) => Object.assign(this, apis)} />
</FormItem>
</ObjectButton>
</div>
);
}
}
}

View File

@ -39,7 +39,7 @@ export class ListSetter extends Component<ArraySetterProps, ArraySetterState> {
}
const itemsMap = state ? state.itemsMap : new Map<string | number, SettingField>();
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<ArraySetterProps, ArraySetterState> {
});
}
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<ArraySetterProps, ArraySetterState> {
render() {
let columns: any = null;
if (this.props.columns) {
columns = this.props.columns.map((column) => <Title key={column.name} title={column.title || (column.name as string)} />);
columns = this.props.columns.map((column) => (
<Title key={column.name} title={column.title || (column.name as string)} />
));
}
const { items } = this.state;

View File

@ -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,

View File

@ -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) {

View File

@ -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));
});

View File

@ -51,7 +51,7 @@ export interface FieldExtraProps {
mode?: 'plaintext' | 'paragraph' | 'article';
// 从 contentEditable 获取内容并设置到属性
onSaveContent?: (content: string, prop: any) => any;
}
};
}
export interface FieldConfig extends FieldExtraProps {