feat: 公式编辑器 ResultBox支持展示变量 (#3684)

This commit is contained in:
Allen 2022-03-03 15:24:49 +08:00 committed by GitHub
parent a840b910e7
commit 26985ca476
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 180 additions and 22 deletions

View File

@ -75,6 +75,9 @@ exports[`Renderer:input-formula 1`] = `
class="cxd-ResultBox cxd-FormulaPicker-input cxd-ResultBox--borderFull"
tabindex="-1"
>
<span
class="cxd-ResultBox-singleValue"
/>
<input
placeholder="暂无数据"
theme="cxd"

View File

@ -288,23 +288,95 @@ Tab 结构:
}
```
## 高亮文本
通过配置`allowInput`为`false`可以高亮文本内容,但是只能在编辑器中编辑
```schema: scope="body"
{
"type": "form",
"debug": true,
"body": [
{
"type": "input-formula",
"name": "formula",
"allowInput": false,
"label": "公式",
"evalMode": false,
"value": "SUM(1 + 2)",
"variables": [
{
"label": "表单字段",
"children": [
{
"label": "文章名",
"value": "name",
"tag": "文本"
},
{
"label": "作者",
"value": "author",
"tag": "文本"
},
{
"label": "售价",
"value": "price",
"tag": "数字"
},
{
"label": "出版时间",
"value": "time",
"tag": "时间"
},
{
"label": "版本号",
"value": "version",
"tag": "数字"
},
{
"label": "出版社",
"value": "publisher",
"tag": "文本"
}
]
},
{
"label": "流程字段",
"children": [
{
"label": "联系电话",
"value": "telphone"
},
{
"label": "地址",
"value": "addr"
}
]
}
],
}
]
}
```
## 属性表
| 属性名 | 类型 | 默认值 | 说明 |
| ----------------- | ------------------------------------------------------------------------------------------ | -------------- | ------------------------------------------------------------------------------ |
| title | `string` | `'公式编辑器'` | 弹框标题 |
| header | `string` | - | 编辑器 header 标题,如果不设置,默认使用表单项`label`字段 |
| evalMode | `boolean` | `true` | 表达式模式 或者 模板模式,模板模式则需要将表达式写在 `${``}` 中间。 |
| variables | `{label: string; value: string; children?: any[]; tag?: string}[]` | `[]` | 可用变量 |
| variableMode | `string` | `list` | 可配置成 `tabs` 或者 `tree` 默认为列表,支持分组。 |
| functions | `Object[]` | - | 可以不设置,默认就是 amis-formula 里面定义的函数,如果扩充了新的函数则需要指定 |
| inputMode | `'button' \| 'input-button'` | - | 控件的展示模式 |
| icon | `string` | - | 按钮图标,例如`fa fa-list` |
| btnLabel | `string` | `'公示编辑'` | 按钮文本,`inputMode`为`button`时生效 |
| level | `'info' \| 'success' \| 'warning' \| 'danger' \| 'link' \| 'primary' \| 'dark' \| 'light'` | `default` | 按钮样式 |
| btnSize | `'xs' \| 'sm' \| 'md' \| 'lg'` | - | 按钮大小 |
| borderMode | `'full' \| 'half' \| 'none'` | - | 输入框边框模式 |
| placeholder | `string` | `'暂无数据'` | 输入框占位符 |
| className | `string` | - | 控件外层 CSS 样式类名 |
| variableClassName | `string` | - | 变量面板 CSS 样式类名 |
| functionClassName | `string` | - | 函数面板 CSS 样式类名 |
| 属性名 | 类型 | 默认值 | 说明 |
| ----------------- | ------------------------------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------ |
| title | `string` | `'公式编辑器'` | 弹框标题 |
| header | `string` | - | 编辑器 header 标题,如果不设置,默认使用表单项`label`字段 |
| evalMode | `boolean` | `true` | 表达式模式 或者 模板模式,模板模式则需要将表达式写在 `${``}` 中间。 |
| variables | `{label: string; value: string; children?: any[]; tag?: string}[]` | `[]` | 可用变量 |
| variableMode | `string` | `list` | 可配置成 `tabs` 或者 `tree` 默认为列表,支持分组。 |
| functions | `Object[]` | - | 可以不设置,默认就是 amis-formula 里面定义的函数,如果扩充了新的函数则需要指定 |
| inputMode | `'button' \| 'input-button'` | - | 控件的展示模式 |
| icon | `string` | - | 按钮图标,例如`fa fa-list` |
| btnLabel | `string` | `'公示编辑'` | 按钮文本,`inputMode`为`button`时生效 |
| level | `'info' \| 'success' \| 'warning' \| 'danger' \| 'link' \| 'primary' \| 'dark' \| 'light'` | `default` | 按钮样式 |
| allowInput | `boolean` | 输入框是否可输入 |
| btnSize | `'xs' \| 'sm' \| 'md' \| 'lg'` | - | 按钮大小 |
| borderMode | `'full' \| 'half' \| 'none'` | - | 输入框边框模式 |
| placeholder | `string` | `'暂无数据'` | 输入框占位符 |
| className | `string` | - | 控件外层 CSS 样式类名 |
| variableClassName | `string` | - | 变量面板 CSS 样式类名 |
| functionClassName | `string` | - | 函数面板 CSS 样式类名 |

View File

@ -316,4 +316,22 @@
color: var(--InputFormula-icon-color-onActive);
}
}
&-ResultBox {
padding-right: 10px;
span.c-field {
background: #007bff;
padding: 3px 5px;
margin: 0 1px;
color: #fff;
font-size: 12px;
border-radius: 4px;
}
span.c-func {
color: #ae4597;
font-weight: bold;
line-height: 14px;
padding: 0 2px;
}
}
}

View File

@ -10,7 +10,7 @@ import {FormulaPlugin, editorFactory} from './plugin';
import FuncList from './FuncList';
import {VariableList} from './VariableList';
import CodeMirrorEditor from '../CodeMirror';
import {autobind} from '../../utils/helper';
import {autobind, eachTree} from '../../utils/helper';
import {themeable, ThemeProps} from '../../theme';
import {localeable, LocaleProps} from '../../locale';
@ -133,8 +133,39 @@ export class FormulaEditor extends React.Component<
variables: Array<VariableItem>,
functions: Array<FuncGroup>
) {
// todo 高亮原始文本
return value;
if (!Array.isArray(variables) || !variables.length || !value) {
return;
}
const varMap: {
[propname: string]: string;
} = {};
eachTree(
variables,
item => item.value && (varMap[item.value] = item.label)
);
const vars = Object.keys(varMap).sort((a, b) => b.length - a.length);
let content = value || '';
// 标记方法调用
content = content.replace(/([A-Z]+)\s*\(/g, (_, func, pos) => {
return _?.replace(func, `<span class="c-func">${func}</span>`);
});
vars.forEach(v => {
let from = 0;
let idx = -1;
while (~(idx = content.indexOf(v, from))) {
content = content.replace(
v,
`<span class="c-field">${varMap[v]}</span>`
);
from = idx + v.length;
}
});
return {html: content};
}
componentWillUnmount() {

View File

@ -69,6 +69,11 @@ export interface FormulaPickerProps extends FormulaEditorProps {
*/
disabled?: boolean;
/**
* fx在弹窗中输入
*/
allowInput?: boolean;
/**
*
*/
@ -96,12 +101,28 @@ export class FormulaPicker extends React.Component<FormulaPickerProps> {
this.props.onChange?.(value);
}
@autobind
renderFormulaValue(item: any) {
const {allowInput, classnames: cx} = this.props;
const html = {__html: item.html};
if (allowInput) {
return '';
}
return (
<div
className={cx('FormulaPicker-ResultBox')}
dangerouslySetInnerHTML={html}
></div>
);
}
render() {
let {
classnames: cx,
value,
translate: __,
disabled,
allowInput,
className,
onChange,
size,
@ -186,9 +207,15 @@ export class FormulaPicker extends React.Component<FormulaPickerProps> {
'FormulaPicker-input',
isOpened ? 'is-active' : ''
)}
allowInput
allowInput={allowInput}
clearable={clearable}
value={value}
result={FormulaEditor.highlightValue(
value,
variables,
functions
)}
itemRender={this.renderFormulaValue}
onResultChange={noop}
onChange={this.handleConfirm}
disabled={disabled}

View File

@ -55,6 +55,11 @@ export interface InputFormulaControlSchema extends FormBaseControl {
*/
inputMode?: 'button' | 'input-button';
/**
* input是否允许输入fx在弹窗中输入
*/
allowInput?: boolean;
/**
*
*/
@ -139,6 +144,7 @@ export class InputFormulaRenderer extends React.Component<InputFormulaProps> {
className,
classPrefix: ns,
classnames: cx,
allowInput = true,
borderMode,
placeholder,
inputMode,
@ -156,6 +162,7 @@ export class InputFormulaRenderer extends React.Component<InputFormulaProps> {
className={className}
value={value}
disabled={disabled}
allowInput={allowInput}
onChange={onChange}
evalMode={evalMode}
variables={variables}