mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-01 19:47:56 +08:00
feat:表达式编辑器支持变量为函数和表达式&editor导出上下文变量获取方法
This commit is contained in:
parent
4beeaca727
commit
259f1cc93c
@ -11,6 +11,8 @@ import type {Schema} from 'amis';
|
|||||||
import type {SchemaObject} from 'amis';
|
import type {SchemaObject} from 'amis';
|
||||||
import {assign, cloneDeep} from 'lodash';
|
import {assign, cloneDeep} from 'lodash';
|
||||||
import {getGlobalData} from 'amis-theme-editor-helper';
|
import {getGlobalData} from 'amis-theme-editor-helper';
|
||||||
|
import {isExpression, resolveVariableAndFilter} from 'amis-core';
|
||||||
|
import type {VariableItem} from 'amis-ui';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
guid,
|
guid,
|
||||||
@ -1132,3 +1134,90 @@ export function deleteThemeConfigData(data: any) {
|
|||||||
|
|
||||||
return schemaData;
|
return schemaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从amis数据域中取变量数据
|
||||||
|
* @param node
|
||||||
|
* @param manager
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export async function resolveVariablesFromScope(node: any, manager: any) {
|
||||||
|
await manager?.getContextSchemas(node);
|
||||||
|
// 获取当前组件内相关变量,如表单、增删改查
|
||||||
|
const dataPropsAsOptions: VariableItem[] = updateComponentContext(
|
||||||
|
(await manager?.dataSchema?.getDataPropsAsOptions()) ?? []
|
||||||
|
);
|
||||||
|
|
||||||
|
const variables: VariableItem[] =
|
||||||
|
manager?.variableManager?.getVariableFormulaOptions() || [];
|
||||||
|
|
||||||
|
return [...dataPropsAsOptions, ...variables].filter(
|
||||||
|
(item: any) => item.children?.length
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整合 props & amis数据域 中的 variables
|
||||||
|
* @param that 为组件的实例 this
|
||||||
|
**/
|
||||||
|
export async function getVariables(that: any) {
|
||||||
|
let variablesArr: any[] = [];
|
||||||
|
|
||||||
|
const {variables, requiredDataPropsVariables} = that.props;
|
||||||
|
if (!variables || requiredDataPropsVariables) {
|
||||||
|
// 从amis数据域中取变量数据
|
||||||
|
const {node, manager} = that.props.formProps || that.props;
|
||||||
|
let vars = await resolveVariablesFromScope(node, manager);
|
||||||
|
if (Array.isArray(vars)) {
|
||||||
|
if (!that.isUnmount) {
|
||||||
|
variablesArr = vars;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (variables) {
|
||||||
|
if (Array.isArray(variables)) {
|
||||||
|
variablesArr = [...variables, ...variablesArr];
|
||||||
|
} else if (typeof variables === 'function') {
|
||||||
|
variablesArr = [...variables(that), ...variablesArr];
|
||||||
|
} else if (isExpression(variables)) {
|
||||||
|
variablesArr = [
|
||||||
|
...resolveVariableAndFilter(
|
||||||
|
that.props.variables as any,
|
||||||
|
that.props.data,
|
||||||
|
'| raw'
|
||||||
|
),
|
||||||
|
...variablesArr
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果存在应用语言类型,则进行翻译
|
||||||
|
if (that.appLocale && that.appCorpusData) {
|
||||||
|
return translateSchema(variablesArr, that.appCorpusData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return variablesArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新组件上下文中label为带层级说明
|
||||||
|
* @param variables 变量列表
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const updateComponentContext = (variables: any[]) => {
|
||||||
|
const items = [...variables];
|
||||||
|
const idx = items.findIndex(item => item.label === '组件上下文');
|
||||||
|
if (~idx) {
|
||||||
|
items.splice(idx, 1, {
|
||||||
|
...items[idx],
|
||||||
|
children: items[idx].children.map((child: any, index: number) => ({
|
||||||
|
...child,
|
||||||
|
label:
|
||||||
|
index === 0
|
||||||
|
? `当前数据域${child.label ? '(' + child.label + ')' : ''}`
|
||||||
|
: `上${index}层${child.label ? '(' + child.label + ')' : ''}`
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
};
|
||||||
|
@ -8,9 +8,9 @@ import cx from 'classnames';
|
|||||||
import {FormItem, Button, Icon, PickerContainer} from 'amis';
|
import {FormItem, Button, Icon, PickerContainer} from 'amis';
|
||||||
import {FormulaEditor} from 'amis-ui';
|
import {FormulaEditor} from 'amis-ui';
|
||||||
import type {VariableItem} from 'amis-ui';
|
import type {VariableItem} from 'amis-ui';
|
||||||
import {getVariables} from './textarea-formula/utils';
|
|
||||||
import {renderFormulaValue} from './FormulaControl';
|
import {renderFormulaValue} from './FormulaControl';
|
||||||
import {reaction} from 'mobx';
|
import {reaction} from 'mobx';
|
||||||
|
import {getVariables} from 'amis-editor-core';
|
||||||
|
|
||||||
interface ExpressionFormulaControlProps extends FormControlProps {
|
interface ExpressionFormulaControlProps extends FormControlProps {
|
||||||
/**
|
/**
|
||||||
|
@ -3,16 +3,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import debounce from 'lodash/debounce';
|
|
||||||
import uniqBy from 'lodash/uniqBy';
|
|
||||||
import isNumber from 'lodash/isNumber';
|
import isNumber from 'lodash/isNumber';
|
||||||
import isBoolean from 'lodash/isBoolean';
|
import isBoolean from 'lodash/isBoolean';
|
||||||
import isPlainObject from 'lodash/isPlainObject';
|
import isPlainObject from 'lodash/isPlainObject';
|
||||||
import isArray from 'lodash/isArray';
|
import isArray from 'lodash/isArray';
|
||||||
import isString from 'lodash/isString';
|
import isString from 'lodash/isString';
|
||||||
import isEqual from 'lodash/isEqual';
|
|
||||||
import omit from 'lodash/omit';
|
import omit from 'lodash/omit';
|
||||||
import last from 'lodash/last';
|
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import {
|
import {
|
||||||
FormItem,
|
FormItem,
|
||||||
@ -34,11 +30,11 @@ import type {
|
|||||||
VariableItem,
|
VariableItem,
|
||||||
FuncGroup
|
FuncGroup
|
||||||
} from 'amis-ui/lib/components/formula/Editor';
|
} from 'amis-ui/lib/components/formula/Editor';
|
||||||
import {dataMapping, FormControlProps} from 'amis-core';
|
import {FormControlProps} from 'amis-core';
|
||||||
import type {BaseEventContext} from 'amis-editor-core';
|
import type {BaseEventContext} from 'amis-editor-core';
|
||||||
import {EditorManager} from 'amis-editor-core';
|
import {EditorManager} from 'amis-editor-core';
|
||||||
import {reaction} from 'mobx';
|
import {reaction} from 'mobx';
|
||||||
import {getVariables} from './textarea-formula/utils';
|
import {getVariables} from 'amis-editor-core';
|
||||||
|
|
||||||
export enum FormulaDateType {
|
export enum FormulaDateType {
|
||||||
NotDate, // 不是时间类
|
NotDate, // 不是时间类
|
||||||
|
@ -10,11 +10,11 @@ import type {VariableItem, CodeMirror} from 'amis-ui';
|
|||||||
import {Icon, Button, FormItem, TooltipWrapper} from 'amis';
|
import {Icon, Button, FormItem, TooltipWrapper} from 'amis';
|
||||||
import {autobind, FormControlProps} from 'amis-core';
|
import {autobind, FormControlProps} from 'amis-core';
|
||||||
import {FormulaPlugin, editorFactory} from './textarea-formula/plugin';
|
import {FormulaPlugin, editorFactory} from './textarea-formula/plugin';
|
||||||
import {getVariables} from './textarea-formula/utils';
|
|
||||||
import {renderFormulaValue} from './FormulaControl';
|
import {renderFormulaValue} from './FormulaControl';
|
||||||
import FormulaPicker, {
|
import FormulaPicker, {
|
||||||
CustomFormulaPickerProps
|
CustomFormulaPickerProps
|
||||||
} from './textarea-formula/FormulaPicker';
|
} from './textarea-formula/FormulaPicker';
|
||||||
|
import {getVariables} from 'amis-editor-core';
|
||||||
|
|
||||||
export interface TplFormulaControlProps extends FormControlProps {
|
export interface TplFormulaControlProps extends FormControlProps {
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,7 @@ export * from './helper';
|
|||||||
import {i18n as _i18n} from 'i18n-runtime';
|
import {i18n as _i18n} from 'i18n-runtime';
|
||||||
import type {VariableItem} from 'amis-ui/lib/components/formula/Editor';
|
import type {VariableItem} from 'amis-ui/lib/components/formula/Editor';
|
||||||
import {reaction} from 'mobx';
|
import {reaction} from 'mobx';
|
||||||
import {updateComponentContext} from '../../util';
|
import {updateComponentContext} from 'amis-editor-core';
|
||||||
|
|
||||||
interface EventControlProps extends FormControlProps {
|
interface EventControlProps extends FormControlProps {
|
||||||
actions: PluginActions; // 组件的动作列表
|
actions: PluginActions; // 组件的动作列表
|
||||||
@ -504,7 +504,12 @@ export class EventControl extends React.Component<
|
|||||||
|
|
||||||
// 编辑的时候只能拿到当前动作前面动作的事件变量以及当前动作事件
|
// 编辑的时候只能拿到当前动作前面动作的事件变量以及当前动作事件
|
||||||
if (data.type === 'update') {
|
if (data.type === 'update') {
|
||||||
actions = actions.slice(0, data.actionData!.actionIndex !== undefined ? data.actionData!.actionIndex + 1 : 0);
|
actions = actions.slice(
|
||||||
|
0,
|
||||||
|
data.actionData!.actionIndex !== undefined
|
||||||
|
? data.actionData!.actionIndex + 1
|
||||||
|
: 0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let jsonSchema = {...(eventConfig?.dataSchema?.[0] ?? {})};
|
let jsonSchema = {...(eventConfig?.dataSchema?.[0] ?? {})};
|
||||||
|
@ -11,9 +11,9 @@ import type {VariableItem, CodeMirror} from 'amis-ui';
|
|||||||
import {FormulaPlugin, editorFactory} from './plugin';
|
import {FormulaPlugin, editorFactory} from './plugin';
|
||||||
|
|
||||||
import FormulaPicker, {CustomFormulaPickerProps} from './FormulaPicker';
|
import FormulaPicker, {CustomFormulaPickerProps} from './FormulaPicker';
|
||||||
import {getVariables} from './utils';
|
|
||||||
import {reaction} from 'mobx';
|
import {reaction} from 'mobx';
|
||||||
import {renderFormulaValue} from '../FormulaControl';
|
import {renderFormulaValue} from '../FormulaControl';
|
||||||
|
import {getVariables} from 'amis-editor-core';
|
||||||
|
|
||||||
export interface AdditionalMenuClickOpts {
|
export interface AdditionalMenuClickOpts {
|
||||||
/**
|
/**
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
import {isExpression, resolveVariableAndFilter} from 'amis-core';
|
|
||||||
import {translateSchema} from 'amis-editor-core';
|
|
||||||
import type {VariableItem} from 'amis-ui/lib/components/formula/Editor';
|
|
||||||
import {updateComponentContext} from '../../util';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从amis数据域中取变量数据
|
|
||||||
* @param node
|
|
||||||
* @param manager
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export async function resolveVariablesFromScope(node: any, manager: any) {
|
|
||||||
await manager?.getContextSchemas(node);
|
|
||||||
// 获取当前组件内相关变量,如表单、增删改查
|
|
||||||
const dataPropsAsOptions: VariableItem[] = updateComponentContext(
|
|
||||||
(await manager?.dataSchema?.getDataPropsAsOptions()) ?? []
|
|
||||||
);
|
|
||||||
|
|
||||||
const variables: VariableItem[] =
|
|
||||||
manager?.variableManager?.getVariableFormulaOptions() || [];
|
|
||||||
|
|
||||||
return [...dataPropsAsOptions, ...variables].filter(
|
|
||||||
(item: any) => item.children?.length
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 整合 props & amis数据域 中的 variables
|
|
||||||
* @param that 为组件的实例 this
|
|
||||||
**/
|
|
||||||
export async function getVariables(that: any) {
|
|
||||||
let variablesArr: any[] = [];
|
|
||||||
const {variables, requiredDataPropsVariables} = that.props;
|
|
||||||
if (!variables || requiredDataPropsVariables) {
|
|
||||||
// 从amis数据域中取变量数据
|
|
||||||
const {node, manager} = that.props.formProps || that.props;
|
|
||||||
let vars = await resolveVariablesFromScope(node, manager);
|
|
||||||
if (Array.isArray(vars)) {
|
|
||||||
if (!that.isUnmount) {
|
|
||||||
variablesArr = vars;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (variables) {
|
|
||||||
if (Array.isArray(variables)) {
|
|
||||||
variablesArr = [...variables, ...variablesArr];
|
|
||||||
} else if (typeof variables === 'function') {
|
|
||||||
variablesArr = [...variables(that), ...variablesArr];
|
|
||||||
} else if (isExpression(variables)) {
|
|
||||||
variablesArr = [
|
|
||||||
...resolveVariableAndFilter(
|
|
||||||
that.props.variables as any,
|
|
||||||
that.props.data,
|
|
||||||
'| raw'
|
|
||||||
),
|
|
||||||
...variablesArr
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果存在应用语言类型,则进行翻译
|
|
||||||
if (that.appLocale && that.appCorpusData) {
|
|
||||||
return translateSchema(variablesArr, that.appCorpusData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return variablesArr;
|
|
||||||
}
|
|
@ -42,26 +42,3 @@ export const schemaToArray = (value: any) => {
|
|||||||
export const schemaArrayFormat = (value: any) => {
|
export const schemaArrayFormat = (value: any) => {
|
||||||
return value && Array.isArray(value) && value.length === 1 ? value[0] : value;
|
return value && Array.isArray(value) && value.length === 1 ? value[0] : value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 更新组件上下文中label为带层级说明
|
|
||||||
* @param variables 变量列表
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const updateComponentContext = (variables: any[]) => {
|
|
||||||
const items = [...variables];
|
|
||||||
const idx = items.findIndex(item => item.label === '组件上下文');
|
|
||||||
if (~idx) {
|
|
||||||
items.splice(idx, 1, {
|
|
||||||
...items[idx],
|
|
||||||
children: items[idx].children.map((child: any, index: number) => ({
|
|
||||||
...child,
|
|
||||||
label:
|
|
||||||
index === 0
|
|
||||||
? `当前数据域${child.label ? '(' + child.label + ')' : ''}`
|
|
||||||
: `上${index}层${child.label ? '(' + child.label + ')' : ''}`
|
|
||||||
}))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
};
|
|
||||||
|
@ -243,7 +243,7 @@ export class FormulaEditor extends React.Component<
|
|||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
const {variables} = this.props;
|
const {variables} = this.props;
|
||||||
this.normalizeVariables(variables);
|
this.normalizeVariables(variables as VariableItem[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(
|
componentDidUpdate(
|
||||||
@ -252,7 +252,7 @@ export class FormulaEditor extends React.Component<
|
|||||||
snapshot?: any
|
snapshot?: any
|
||||||
): void {
|
): void {
|
||||||
if (prevProps.variables !== this.props.variables) {
|
if (prevProps.variables !== this.props.variables) {
|
||||||
this.normalizeVariables(this.props.variables);
|
this.normalizeVariables(this.props.variables as VariableItem[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import {uncontrollable} from 'amis-core';
|
import {
|
||||||
|
isExpression,
|
||||||
|
resolveVariableAndFilterForAsync,
|
||||||
|
uncontrollable
|
||||||
|
} from 'amis-core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {
|
import {
|
||||||
FormulaEditor,
|
FormulaEditor,
|
||||||
@ -23,7 +27,8 @@ import Modal from '../Modal';
|
|||||||
import PopUp from '../PopUp';
|
import PopUp from '../PopUp';
|
||||||
import {isMobile} from 'amis-core';
|
import {isMobile} from 'amis-core';
|
||||||
|
|
||||||
export interface FormulaPickerProps extends FormulaEditorProps {
|
export interface FormulaPickerProps
|
||||||
|
extends Omit<FormulaEditorProps, 'variables'> {
|
||||||
// 新的属性?
|
// 新的属性?
|
||||||
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
||||||
|
|
||||||
@ -124,7 +129,13 @@ export interface FormulaPickerProps extends FormulaEditorProps {
|
|||||||
onRef?: (node: any) => void;
|
onRef?: (node: any) => void;
|
||||||
|
|
||||||
popOverContainer?: any;
|
popOverContainer?: any;
|
||||||
|
|
||||||
useMobileUI?: boolean;
|
useMobileUI?: boolean;
|
||||||
|
|
||||||
|
variables?:
|
||||||
|
| Array<VariableItem>
|
||||||
|
| string
|
||||||
|
| ((props: any) => Array<VariableItem>);
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormulaPickerState {
|
export interface FormulaPickerState {
|
||||||
@ -155,7 +166,8 @@ export class FormulaPicker extends React.Component<
|
|||||||
isOpened: false,
|
isOpened: false,
|
||||||
value: this.props.value!,
|
value: this.props.value!,
|
||||||
editorValue: this.value2EditorValue(this.props),
|
editorValue: this.value2EditorValue(this.props),
|
||||||
isError: false
|
isError: false,
|
||||||
|
variables: Array.isArray(props.variables) ? props.variables : []
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +266,19 @@ export class FormulaPicker extends React.Component<
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
async handleClick() {
|
async handleClick() {
|
||||||
|
const {variables, data} = this.props;
|
||||||
|
if (typeof variables === 'function') {
|
||||||
|
const list = await variables(this.props);
|
||||||
|
this.setState({variables: list});
|
||||||
|
} else if (typeof variables === 'string' && isExpression(variables)) {
|
||||||
|
const result = await resolveVariableAndFilterForAsync(
|
||||||
|
variables,
|
||||||
|
data,
|
||||||
|
'|raw'
|
||||||
|
);
|
||||||
|
this.setState({variables: result});
|
||||||
|
}
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
...(await this.props.onPickerOpen?.(this.props)),
|
...(await this.props.onPickerOpen?.(this.props)),
|
||||||
editorValue: this.value2EditorValue(this.props),
|
editorValue: this.value2EditorValue(this.props),
|
||||||
@ -328,7 +353,6 @@ export class FormulaPicker extends React.Component<
|
|||||||
icon,
|
icon,
|
||||||
title,
|
title,
|
||||||
clearable,
|
clearable,
|
||||||
variables,
|
|
||||||
functions,
|
functions,
|
||||||
children,
|
children,
|
||||||
variableMode,
|
variableMode,
|
||||||
@ -405,7 +429,7 @@ export class FormulaPicker extends React.Component<
|
|||||||
? void 0
|
? void 0
|
||||||
: FormulaEditor.highlightValue(
|
: FormulaEditor.highlightValue(
|
||||||
value,
|
value,
|
||||||
variables!,
|
this.state.variables!,
|
||||||
this.props.evalMode
|
this.props.evalMode
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -448,7 +472,7 @@ export class FormulaPicker extends React.Component<
|
|||||||
? void 0
|
? void 0
|
||||||
: FormulaEditor.highlightValue(
|
: FormulaEditor.highlightValue(
|
||||||
value,
|
value,
|
||||||
variables!,
|
this.state.variables!,
|
||||||
this.props.evalMode
|
this.props.evalMode
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -485,7 +509,7 @@ export class FormulaPicker extends React.Component<
|
|||||||
<Editor
|
<Editor
|
||||||
{...rest}
|
{...rest}
|
||||||
evalMode={mixedMode ? true : evalMode}
|
evalMode={mixedMode ? true : evalMode}
|
||||||
variables={this.state.variables ?? variables}
|
variables={this.state.variables}
|
||||||
functions={this.state.functions ?? functions}
|
functions={this.state.functions ?? functions}
|
||||||
variableMode={this.state.variableMode ?? variableMode}
|
variableMode={this.state.variableMode ?? variableMode}
|
||||||
value={editorValue}
|
value={editorValue}
|
||||||
@ -516,7 +540,7 @@ export class FormulaPicker extends React.Component<
|
|||||||
<Editor
|
<Editor
|
||||||
{...rest}
|
{...rest}
|
||||||
evalMode={mixedMode ? true : evalMode}
|
evalMode={mixedMode ? true : evalMode}
|
||||||
variables={this.state.variables ?? variables}
|
variables={this.state.variables}
|
||||||
functions={this.state.functions ?? functions}
|
functions={this.state.functions ?? functions}
|
||||||
variableMode={this.state.variableMode ?? variableMode}
|
variableMode={this.state.variableMode ?? variableMode}
|
||||||
value={editorValue}
|
value={editorValue}
|
||||||
|
Loading…
Reference in New Issue
Block a user