fix: source-editor bug & exp-setter bug

This commit is contained in:
zude.hzd 2020-09-09 16:21:03 +08:00
parent d41f481553
commit 5cd88d4b12
5 changed files with 102 additions and 66 deletions

View File

@ -21,10 +21,11 @@ const helpMap = {
'utils': '应用工具对象',
'dataSourceMap': '容器数据源Map',
'field': '表单Field对象'
}
};
export default class ExpressionView extends PureComponent {
static displayName = 'Expression';
static propTypes = {
context: PropTypes.object,
dataSource: PropTypes.array,
@ -32,8 +33,9 @@ export default class ExpressionView extends PureComponent {
messages: PropTypes.object,
onChange: PropTypes.func,
placeholder: PropTypes.string,
value: PropTypes.string
value: PropTypes.string,
};
static defaultProps = {
context: {},
dataSource: [],
@ -41,12 +43,17 @@ export default class ExpressionView extends PureComponent {
messages: zhCN,
onChange: () => {},
placeholder: '',
value: ''
value: '',
};
expression: React.RefObject<unknown>;
i18n: any;
t: void;
$input: any;
listenerFun: ((event: any) => void) | undefined;
static getInitValue(val: { value: any; match: (arg0: RegExp) => any; }) {
@ -54,12 +61,13 @@ export default class ExpressionView extends PureComponent {
if (typeof val === 'object') {
return val.value;
} else if (typeof val === 'string') {
let arr = val.match(/^\{\{(.*?)\}\}$/);
const arr = val.match(/^\{\{(.*?)\}\}$/);
if (arr) return arr[1];
}
}
return val;
}
constructor(props: Readonly<{}>) {
super(props);
this.expression = React.createRef();
@ -67,46 +75,48 @@ export default class ExpressionView extends PureComponent {
this.state = {
value: ExpressionView.getInitValue(props.value),
context: props.context || {},
dataSource: props.dataSource || []
dataSource: props.dataSource || [],
};
}
static getDerivedStateFromProps(props: { value: any; }, state: { preValue: any; }) {
let curValue = ExpressionView.getInitValue(props.value);
const curValue = ExpressionView.getInitValue(props.value);
if (curValue !== state.preValue) {
return {
preValue: curValue,
value: curValue
value: curValue,
};
}
return null;
}
onChange(value: string, actionType: string) {
let realInputValue = value;
let realDataSource = null;
const realDataSource = null;
let nextCursorIndex: number;
//更新值
// 更新值
if (actionType === 'itemClick' || actionType === 'enter') {
let curValue = this.state.value;
const curValue = this.state.value;
if (curValue) {
realInputValue = curValue + realInputValue;
}
}
//更新数据源
let newState = {
value: realInputValue
// 更新数据源
const newState = {
value: realInputValue,
};
if (realDataSource !== null) newState.dataSource = realDataSource;
this.setState(newState, () => {
nextCursorIndex && this.setInputCursorPosition(nextCursorIndex);
});
//默认加上变量表达式
// 默认加上变量表达式
this.t && clearTimeout(this.t);
this.t = setTimeout(() => {
const { onChange } = this.props;
// realInputValue = realInputValue ? `{{${realInputValue}}}` : undefined;
onChange && onChange({
type: 'JSExpression',
value: realInputValue
value: realInputValue,
});
}, 300);
}
@ -116,23 +126,33 @@ export default class ExpressionView extends PureComponent {
* @param {String}
* @return {Array}
*/
getDataSource(tempStr: string): Array<any> {
if (/[^\w\.]$/.test(tempStr)) {
return [];
} else if (tempStr === null || tempStr === '') {
return this.getContextKeys([]);
} else if (/\w\.$/.test(tempStr)) {
let currentField = this.getCurrentFiled(tempStr);
if (!currentField) return null;
let tempKeys = this.getObjectKeys(currentField.str);
tempKeys = this.getContextKeys(tempKeys);
if (!tempKeys) return null;
return tempKeys;
} else if (/\.$/.test(tempStr)) {
return [];
} else {
return null;
getDataSource(tempStr: string): any[] {
const {editor} = this.props.field;
const schema = editor.get('designer').project.getSchema();
const stateMap = schema.componentsTree[0].state;
let dataSource = [];
for (let key in stateMap){
dataSource.push(`this.state.${key}`);
}
// if (/[^\w\.]$/.test(tempStr)) {
// return [];
// } else if (tempStr === null || tempStr === '') {
// return this.getContextKeys([]);
// } else if (/\w\.$/.test(tempStr)) {
// const currentField = this.getCurrentFiled(tempStr);
// if (!currentField) return null;
// let tempKeys = this.getObjectKeys(currentField.str);
// tempKeys = this.getContextKeys(tempKeys);
// if (!tempKeys) return null;
// return tempKeys;
// } else if (/\.$/.test(tempStr)) {
// return [];
// } else {
// return null;
// }
return dataSource;
}
/**
@ -141,12 +161,12 @@ export default class ExpressionView extends PureComponent {
* @return {String}
*/
getCurrentFiled(str: string | any[]) {
str += 'x'; //.后面加一个x字符便于acorn解析
str += 'x'; // .后面加一个x字符便于acorn解析
try {
let astTree = acorn.parse(str);
let right = astTree.body[0].expression.right || astTree.body[0].expression;
const astTree = acorn.parse(str);
const right = astTree.body[0].expression.right || astTree.body[0].expression;
if (right.type === 'MemberExpression') {
let { start, end } = right;
const { start, end } = right;
str = str.slice(start, end);
return { str, start, end };
}
@ -161,7 +181,7 @@ export default class ExpressionView extends PureComponent {
* @return {Array}
*/
getContextKeys(keys: []) {
const editor = this.props.field.editor;
const { editor } = this.props.field;
console.log(editor);
const limitKeys = ['schema', 'utils', 'constants'];
if (keys.length === 0) return limitKeys;
@ -176,16 +196,16 @@ export default class ExpressionView extends PureComponent {
if (keyValue[item]) {
keyValue = keyValue[item];
}
})
});
if (assert) return [];
result = Object.keys(keyValue);
return result;
// return utilsKeys.concat(constantsKeys).concat(schemaKeys);
}
/*过滤key */
/* 过滤key */
filterKey(obj: any, name: string) {
let filterKeys = [
const filterKeys = [
'reloadDataSource',
'REACT_HOT_LOADER_RENDERED_GENERATION',
'refs',
@ -194,10 +214,10 @@ export default class ExpressionView extends PureComponent {
'isReactComponent',
'forceUpdate',
'setState',
'isPureReactComponent'
'isPureReactComponent',
];
let result = [];
for (let key in obj) {
const result = [];
for (const key in obj) {
if (key.indexOf('_') !== 0 && filterKeys.indexOf(key) === -1) {
result.push(`${name}.${key}`);
}
@ -213,8 +233,8 @@ export default class ExpressionView extends PureComponent {
*/
filterOption(inputValue: string, item: { value: string | any[]; }) {
const cursorIndex = this.getInputCursorPosition();
let preStr = inputValue.substr(0, cursorIndex);
let lastKey: string[] = preStr.split('.').slice(-1);
const preStr = inputValue.substr(0, cursorIndex);
const lastKey: string[] = preStr.split('.').slice(-1);
if (!lastKey) return true;
if (item.value.indexOf(lastKey) > -1) return true;
return false;
@ -228,11 +248,11 @@ export default class ExpressionView extends PureComponent {
const { value, dataSource } = this.state;
const { placeholder } = this.props;
const isValObject = !!(value == '[object Object]');
let title = isValObject
const title = isValObject
? this.i18n('valueIllegal')
: (value || placeholder || this.i18n('jsExpression')).toString();
const cursorIndex = this.getInputCursorPosition();
let childNode = cursorIndex ? (
const childNode = cursorIndex ? (
<div className="cursor-blink">
{title.substr(0, cursorIndex)}
<b>|</b>
@ -264,7 +284,7 @@ export default class ExpressionView extends PureComponent {
innerAfter={<span style={{ color: '#999', marginRight: 4 }}>{'}}'}</span>}
popupClassName="expression-setter-item-inner"
itemRender={({ value }) => {
console.log(value);
console.log('111:'+value);
return (
<Option key={value} text={value} value={value}>
<div className="code-input-value">{value}</div>
@ -289,12 +309,12 @@ export default class ExpressionView extends PureComponent {
this.$input = this.findInputElement();
if (this.$input) {
this.listenerFun = event => {
let isMoveKey = !!(event.type == 'keyup' && ~[37, 38, 39, 91].indexOf(event.keyCode));
let isMouseup = event.type == 'mouseup';
const isMoveKey = !!(event.type == 'keyup' && ~[37, 38, 39, 91].indexOf(event.keyCode));
const isMouseup = event.type == 'mouseup';
if (isMoveKey || isMouseup) {
let dataSource = this.getDataSource(this.state.value) || [];
const dataSource = this.getDataSource(this.state.value) || [];
this.setState({
dataSource
dataSource,
});
}
};
@ -302,18 +322,21 @@ export default class ExpressionView extends PureComponent {
this.$input.addEventListener('mouseup', this.listenerFun, false);
}
}
componentWillUnmount() {
if (this.listenerFun && this.$input) {
this.$input.removeEventListener('keyup', this.listenerFun, false);
this.$input.removeEventListener('mouseup', this.listenerFun, false);
}
}
/**
* Input输入框DOM节点
*/
findInputElement() {
return this.expression.current.children[0].getElementsByTagName('input')[0];
}
/**
*
*
@ -322,6 +345,7 @@ export default class ExpressionView extends PureComponent {
if (!this.$input) return;
return this.$input.selectionStart;
}
/*
* keys
*/
@ -330,6 +354,7 @@ export default class ExpressionView extends PureComponent {
if (str) keys = str.split('.');
return keys.slice(0, keys.length - 1);
}
/*
* input组件光标位置在闭合}
*/

View File

@ -1,6 +1,6 @@
{
"name": "@ali/lowcode-plugin-source-editor",
"version": "1.0.8-0",
"version": "1.0.8-beta-1",
"description": "alibaba lowcode editor source-editor plugin",
"files": [
"es",

View File

@ -13,6 +13,12 @@
height: 100%;
}
.button-container{
position: absolute;
top: 0px;
right: 10px;
}
.editor-context-container{
height: 100%;
width: 100%;

View File

@ -1,5 +1,5 @@
import { Component, isValidElement, ReactElement, ReactNode } from 'react';
import { Tab, Search, Input, Button } from '@alifd/next';
import { Tab, Search, Input, Button,Message } from '@alifd/next';
import { Editor } from '@ali/lowcode-editor-core';
import { js_beautify, css_beautify } from 'js-beautify';
import MonacoEditor from 'react-monaco-editor';
@ -15,7 +15,7 @@ import transfrom from './transform';
const defaultEditorOption = {
width: '100%',
height: '100%',
height: '95%',
options: {
readOnly: false,
automaticLayout: true,
@ -56,11 +56,13 @@ export default class SourceEditor extends Component<{
state = {
isFullScreen:false,
tabKey: TAB_KEY.JS_TAB,
isShowSaveBtn:true
};
componentWillMount() {
const { editor } = this.props;
// 添加函数
editor.on('sourceEditor.addFunction', (params: FunctionEventParam) => {
this.callEditorEvent('sourceEditor.addFunction', params);
@ -71,16 +73,13 @@ export default class SourceEditor extends Component<{
this.callEditorEvent('sourceEditor.focusByFunction', params);
});
// 插件面板关闭事件,监听规则同上
editor.on('skeleton.panel-dock.unactive',(pluginName,dock)=>{
if (pluginName == 'sourceEditor'){
this.saveSchema();
}
if (pluginName == 'sourceEditor'){
this.saveSchema();
}
})
// 插件面板打开事件,监听规则同上
editor.on('skeleton.panel-dock.active',(pluginName,dock)=>{
if (pluginName == 'sourceEditor'){
@ -269,21 +268,22 @@ export default class SourceEditor extends Component<{
};
saveSchema = () => {
saveSchema = (successFlag) => {
const {jsCode} = this.state;
const {editor} = this.props;
let functionMap = transfrom.code2Schema(jsCode);
let schema = editor.get('designer').project.getSchema();
let oldSchemaStr = JSON.stringify(schema);
//let oldSchemaStr = JSON.stringify(schema);
let newSchema = transfrom.setFunction2Schema(functionMap, schema);
if (newSchema!='' && JSON.stringify(newSchema) != oldSchemaStr){
if (newSchema!=''){
editor.get('designer').project.setSchema(newSchema);
successFlag && Message.success('保存成功')
}
}
render() {
const { selectTab, jsCode, css } = this.state;
const { selectTab, jsCode, css ,isShowSaveBtn} = this.state;
const tabs = [
{ tab: 'index.js', key: TAB_KEY.JS_TAB },
{ tab: 'style.css', key: TAB_KEY.CSS_TAB },
@ -291,12 +291,13 @@ export default class SourceEditor extends Component<{
return (
<div className="source-editor-container">
<Tab size="small" shape="wrapped" onChange={this.onTabChange} activeKey={selectTab}>
{tabs.map((item) => (
<Tab.Item key={item.key} title={item.tab} />
))}
</Tab>
{ isShowSaveBtn && <div className="button-container"><Button type="primary" onClick={()=>this.saveSchema(successFlag)}></Button></div>}
<div style={{ height: '100%' }} className="editor-context-container">
<div id="jsEditorDom" className="editor-context" ref={this.editorJsRef}>

View File

@ -55,6 +55,10 @@ const transfrom = {
setFunction2Schema(functionMap,schema){
let pageNode = schema.componentsTree[0];
// 先清除原有的schema的值
delete pageNode.state;
pageNode.lifeCycles = {};
pageNode.methods = {};
if (!pageNode) return '';
for (let key in functionMap){
if (key == 'state'){