mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-12 17:08:14 +00:00
Merge branch 'fix/ducheng0907-bugs' into 'release/1.0.0'
fix: source-editor bug & exp-setter bug See merge request !972619
This commit is contained in:
commit
653dc7f9c8
@ -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组件光标位置在闭合}前
|
||||
*/
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -13,6 +13,12 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.button-container{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.editor-context-container{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
@ -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}>
|
||||
|
||||
@ -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'){
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user