mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-02-28 12:50:38 +00:00
feat: add expression-setter AutoComplete tips
This commit is contained in:
parent
8fc74de204
commit
9c62a490c9
@ -1,130 +1,17 @@
|
||||
// mixin
|
||||
.lowcode-setter-mixin > * {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.lowcode-setter-mixin {
|
||||
width: 86%;
|
||||
}
|
||||
.lowcode-setter-mixin .next-input {
|
||||
width: 100%;
|
||||
}
|
||||
.lowcode-setter-mixin .next-select-trigger {
|
||||
width: 100%;
|
||||
}
|
||||
// json-setter
|
||||
// :global {
|
||||
.nrs-monaco-form {
|
||||
.next-form-item:last-child {
|
||||
margin: 0 !important;
|
||||
}
|
||||
.expression-setter-item-inner {
|
||||
.next-menu-item-text {
|
||||
vertical-align: middle;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.monaco-editor-wrap {
|
||||
.luna-monaco-button .next-icon-first {
|
||||
height: 26px;
|
||||
}
|
||||
.monaco_fullscreen_icon {
|
||||
position: absolute;
|
||||
line-height: 1;
|
||||
z-index: 7;
|
||||
color: #ddd;
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.btns-eare {
|
||||
text-align: left;
|
||||
line-height: initial;
|
||||
margin-top: 5px;
|
||||
// button{
|
||||
// margin-right: 10px;
|
||||
// }
|
||||
}
|
||||
&.monaco-nofullscreen {
|
||||
position: relative !important;
|
||||
.monaco_fullscreen_icon {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
line-height: 1;
|
||||
z-index: 7;
|
||||
i:before {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.monaco-fullscreen {
|
||||
position: fixed !important;
|
||||
height: 100% !important;
|
||||
width: 100% !important;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
.monaco_fullscreen_icon {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
i:before {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.luna-monaco-button button {
|
||||
width: 100%;
|
||||
}
|
||||
.luna-monaco-button-dialog {
|
||||
.next-dialog-body {
|
||||
padding: 0;
|
||||
.next-form-item {
|
||||
height: 100%;
|
||||
margin-bottom: 0;
|
||||
.next-form-item-control,
|
||||
.next-form-item-control > div {
|
||||
height: 100% !important;
|
||||
}
|
||||
.next-form-item-help {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
// color-setter
|
||||
.lowcode-color-box {
|
||||
margin-right: -5px;
|
||||
padding: 3px 0 3px 3px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
display: inline-block;
|
||||
div {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 1px solid #ddd;
|
||||
.next-menu-item {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
.next-balloon-normal.lowcode-color-content {
|
||||
padding: 0;
|
||||
background: #ffffff;
|
||||
border-radius: 0;
|
||||
border: 1px solid #e5e5e5;
|
||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
.sketch-picker {
|
||||
border-radius: 0 !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
.flexbox-fix {
|
||||
input {
|
||||
width: 100% !important;
|
||||
min-width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.code-input-value {
|
||||
float: left;
|
||||
}
|
||||
.code-input-help {
|
||||
float: right;
|
||||
color: #6897f2;
|
||||
}
|
||||
|
||||
@ -1,24 +1,26 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Select, Balloon } from '@alife/next';
|
||||
import { Select, Balloon, Icon } from '@alife/next';
|
||||
import * as acorn from 'acorn';
|
||||
|
||||
import { isJSExpression, generateI18n } from './locale/utils';
|
||||
import zhCN from './locale/zh-CN';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const { Option, AutoComplete } = Select;
|
||||
const { Tooltip } = Balloon;
|
||||
const helpMap = {
|
||||
this: '容器上下文对象',
|
||||
'this.state': '容器的state',
|
||||
'this.props': '容器的props',
|
||||
'this.context': '容器的context',
|
||||
'this.page': '页面上下文对象',
|
||||
'this.component': '组件上下文对象',
|
||||
'this.constants': '应用常量对象',
|
||||
'this.utils': '应用工具对象',
|
||||
'this.dataSourceMap': '容器数据源Map',
|
||||
'this.field': '表单Field对象'
|
||||
'state': '容器的state',
|
||||
'props': '容器的props',
|
||||
'context': '容器的context',
|
||||
'schema': '页面上下文对象',
|
||||
'component': '组件上下文对象',
|
||||
'constants': '应用常量对象',
|
||||
'utils': '应用工具对象',
|
||||
'dataSourceMap': '容器数据源Map',
|
||||
'field': '表单Field对象'
|
||||
}
|
||||
|
||||
export default class ExpressionView extends PureComponent {
|
||||
@ -45,7 +47,7 @@ export default class ExpressionView extends PureComponent {
|
||||
i18n: any;
|
||||
t: void;
|
||||
$input: any;
|
||||
listenerFun: (event: any) => void;
|
||||
listenerFun: ((event: any) => void) | undefined;
|
||||
|
||||
static getInitValue(val: { value: any; match: (arg0: RegExp) => any; }) {
|
||||
if (isJSExpression(val)) {
|
||||
@ -81,51 +83,12 @@ export default class ExpressionView extends PureComponent {
|
||||
onChange(value: string, actionType: string) {
|
||||
let realInputValue = value;
|
||||
let realDataSource = null;
|
||||
const cursorIndex = this.getInputCursorPosition();
|
||||
let nextCursorIndex: number;
|
||||
//更新值
|
||||
if (actionType === 'itemClick' || actionType === 'enter') {
|
||||
let curValue = this.state.value;
|
||||
if (curValue) {
|
||||
//如果是非.结束,则替换当前这个变量;
|
||||
let preStr = curValue.substr(0, cursorIndex);
|
||||
let nextStr = curValue.substr(cursorIndex);
|
||||
let preArr = preStr.split('.');
|
||||
let preArrLen = preArr.length;
|
||||
let tarPreStr = '';
|
||||
if (!preArr[preArrLen - 1]) {
|
||||
//如果是.结束,则增加到.后面
|
||||
if (preArr[preArrLen - 2] === 'this') {
|
||||
preArr = preArr.slice(0, preArrLen - 2);
|
||||
preArr.push(value);
|
||||
tarPreStr = preArr.join('.');
|
||||
} else {
|
||||
tarPreStr = preStr + value;
|
||||
}
|
||||
} else {
|
||||
if (preArr[preArrLen - 2] === 'this') {
|
||||
preArr = preArr.slice(0, preArrLen - 2);
|
||||
} else {
|
||||
preArr = preArr.slice(0, preArrLen - 1);
|
||||
}
|
||||
preArr.push(value);
|
||||
tarPreStr = preArr.join('.');
|
||||
}
|
||||
realInputValue = tarPreStr + nextStr;
|
||||
realDataSource = this.getDataSource(tarPreStr + '.') || [];
|
||||
nextCursorIndex = tarPreStr.length;
|
||||
}
|
||||
} else {
|
||||
let tarPreStr = value.substr(0, cursorIndex);
|
||||
if (tarPreStr) {
|
||||
let lastChar = tarPreStr.charAt(tarPreStr.length - 1);
|
||||
if (lastChar === '.') {
|
||||
realDataSource = this.getDataSource(tarPreStr) || [];
|
||||
} else {
|
||||
realDataSource = this.getDataSource(tarPreStr + '.');
|
||||
}
|
||||
} else {
|
||||
realDataSource = this.getDataSource('this.');
|
||||
realInputValue = curValue + realInputValue;
|
||||
}
|
||||
}
|
||||
//更新数据源
|
||||
@ -154,21 +117,16 @@ export default class ExpressionView extends PureComponent {
|
||||
* @return {Array}
|
||||
*/
|
||||
getDataSource(tempStr: string): Array<any> {
|
||||
if (tempStr === '' || /[^\w\.]$/.test(tempStr)) {
|
||||
return this.getDataSource('this.') || [];
|
||||
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;
|
||||
//给默认情况增加this
|
||||
if (tempStr === 'this.') {
|
||||
tempKeys = tempKeys.map((item: string) => {
|
||||
return 'this.' + item;
|
||||
});
|
||||
tempKeys.unshift('this');
|
||||
}
|
||||
return tempKeys;
|
||||
} else if (/\.$/.test(tempStr)) {
|
||||
return [];
|
||||
@ -202,34 +160,31 @@ export default class ExpressionView extends PureComponent {
|
||||
* @param {Array}
|
||||
* @return {Array}
|
||||
*/
|
||||
getContextKeys(keys: any) {
|
||||
// let context = {};
|
||||
// const { appHelper } = this.context;
|
||||
// const activeKey = appHelper && appHelper.activeKey;
|
||||
// if (!activeKey) return;
|
||||
// const activeCtx = appHelper.schemaHelper.compCtxMap && appHelper.schemaHelper.compCtxMap[activeKey];
|
||||
// if (!activeCtx) return null;
|
||||
// let __self = activeCtx;
|
||||
// if (keys && keys.length > 1) {
|
||||
// keys.shift(0);
|
||||
// let path = '/' + keys.join('/');
|
||||
// path = path.replace(/[\[\]]/g, '/');
|
||||
// context = jsonuri.get(__self, path);
|
||||
// if (context && typeof context === 'object') {
|
||||
// return this.filterKey(context);
|
||||
// }
|
||||
// } else if (keys && keys[0] === 'this') {
|
||||
// return this.filterKey(__self);
|
||||
// }
|
||||
// return null;
|
||||
return [
|
||||
"page",
|
||||
"component"
|
||||
]
|
||||
getContextKeys(keys: []) {
|
||||
const editor = this.props.field.editor;
|
||||
console.log(editor);
|
||||
const limitKeys = ['schema', 'utils', 'constants'];
|
||||
if (keys.length === 0) return limitKeys;
|
||||
if (!limitKeys.includes(keys[0])) return [];
|
||||
let result = [];
|
||||
let keyValue = editor;
|
||||
let assert = false;
|
||||
keys.forEach(item => {
|
||||
if (!keyValue[item] || typeof keyValue[item] !== 'object') {
|
||||
assert = true;
|
||||
}
|
||||
if (keyValue[item]) {
|
||||
keyValue = keyValue[item];
|
||||
}
|
||||
})
|
||||
if (assert) return [];
|
||||
result = Object.keys(keyValue);
|
||||
return result;
|
||||
// return utilsKeys.concat(constantsKeys).concat(schemaKeys);
|
||||
}
|
||||
|
||||
/*过滤key */
|
||||
filterKey(obj: any) {
|
||||
filterKey(obj: any, name: string) {
|
||||
let filterKeys = [
|
||||
'reloadDataSource',
|
||||
'REACT_HOT_LOADER_RENDERED_GENERATION',
|
||||
@ -244,7 +199,7 @@ export default class ExpressionView extends PureComponent {
|
||||
let result = [];
|
||||
for (let key in obj) {
|
||||
if (key.indexOf('_') !== 0 && filterKeys.indexOf(key) === -1) {
|
||||
result.push(key);
|
||||
result.push(`${name}.${key}`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -259,12 +214,16 @@ 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 = preStr.split('.').slice(-1);
|
||||
let lastKey: string[] = preStr.split('.').slice(-1);
|
||||
if (!lastKey) return true;
|
||||
if (item.value.indexOf(lastKey) > -1) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// handleClick = () => {
|
||||
// this.props.field.editor.emit('variableBindDialog.open');
|
||||
// }
|
||||
|
||||
render() {
|
||||
const { value, dataSource } = this.state;
|
||||
const { placeholder } = this.props;
|
||||
@ -293,26 +252,30 @@ export default class ExpressionView extends PureComponent {
|
||||
isValObject ? (
|
||||
value
|
||||
) : (
|
||||
<AutoComplete
|
||||
{...this.props}
|
||||
style={{ width: '100%' }}
|
||||
dataSource={dataSource}
|
||||
placeholder={placeholder || this.i18n('jsExpression')}
|
||||
value={value}
|
||||
disabled={isValObject}
|
||||
innerBefore={<span style={{ color: '#999', marginLeft: 4 }}>{'{{'}</span>}
|
||||
innerAfter={<span style={{ color: '#999', marginRight: 4 }}>{'}}'}</span>}
|
||||
itemRender={({ value }) => {
|
||||
return (
|
||||
<Option key={value} text={value} value={value}>
|
||||
<div className="code-input-value">{value}</div>
|
||||
<div className="code-input-help">{helpMap[value]}</div>
|
||||
</Option>
|
||||
);
|
||||
}}
|
||||
onChange={this.onChange.bind(this)}
|
||||
filter={this.filterOption.bind(this)}
|
||||
/>
|
||||
<div>
|
||||
<AutoComplete
|
||||
{...this.props}
|
||||
style={{ width: '100%' }}
|
||||
dataSource={dataSource}
|
||||
placeholder={placeholder || this.i18n('jsExpression')}
|
||||
value={value}
|
||||
disabled={isValObject}
|
||||
innerBefore={<span style={{ color: '#999', marginLeft: 4 }}>{'{{'}</span>}
|
||||
innerAfter={<span style={{ color: '#999', marginRight: 4 }}>{'}}'}</span>}
|
||||
popupClassName="expression-setter-item-inner"
|
||||
itemRender={({ value }) => {
|
||||
console.log(value);
|
||||
return (
|
||||
<Option key={value} text={value} value={value}>
|
||||
<div className="code-input-value">{value}</div>
|
||||
<div className="code-input-help">{helpMap[value]}</div>
|
||||
</Option>
|
||||
);
|
||||
}}
|
||||
onChange={this.onChange.bind(this)}
|
||||
filter={this.filterOption.bind(this)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
>
|
||||
@ -363,7 +326,7 @@ export default class ExpressionView extends PureComponent {
|
||||
* 字符串取得对象keys
|
||||
*/
|
||||
getObjectKeys(str: string) {
|
||||
let keys = [];
|
||||
let keys: string | any[] = [];
|
||||
if (str) keys = str.split('.');
|
||||
return keys.slice(0, keys.length - 1);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user