mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:58:07 +08:00
feat: 公式支持快捷变量支持
This commit is contained in:
parent
09e564e9e7
commit
0a436fb137
@ -4,7 +4,7 @@
|
|||||||
import {hasIcon, mapObject, utils} from 'amis';
|
import {hasIcon, mapObject, utils} from 'amis';
|
||||||
import type {PlainObject, Schema, SchemaNode} from 'amis';
|
import type {PlainObject, Schema, SchemaNode} from 'amis';
|
||||||
import {getGlobalData} from 'amis-theme-editor-helper';
|
import {getGlobalData} from 'amis-theme-editor-helper';
|
||||||
import {isExpression, resolveVariableAndFilter} from 'amis-core';
|
import {filterTree, isExpression, resolveVariableAndFilter} from 'amis-core';
|
||||||
import type {VariableItem} from 'amis-ui';
|
import type {VariableItem} from 'amis-ui';
|
||||||
import {isObservable, reaction} from 'mobx';
|
import {isObservable, reaction} from 'mobx';
|
||||||
import DeepDiff, {Diff} from 'deep-diff';
|
import DeepDiff, {Diff} from 'deep-diff';
|
||||||
@ -1362,65 +1362,78 @@ export async function getVariables(that: any) {
|
|||||||
return variablesArr;
|
return variablesArr;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getQuickVariables(
|
export async function getQuickVariables(that: any) {
|
||||||
that: any,
|
|
||||||
resolver?: (vars: any[]) => any[]
|
|
||||||
) {
|
|
||||||
const {node, manager} = that.props.formProps || that.props;
|
const {node, manager} = that.props.formProps || that.props;
|
||||||
const selfName = that.props?.data?.name;
|
const {quickVars, data} = that.props;
|
||||||
|
const selfName = data?.name;
|
||||||
await manager?.getContextSchemas(node);
|
await manager?.getContextSchemas(node);
|
||||||
const options = await manager?.dataSchema?.getDataPropsAsOptions();
|
const options = await manager?.dataSchema?.getDataPropsAsOptions();
|
||||||
if (Array.isArray(options)) {
|
if (Array.isArray(options)) {
|
||||||
const vars = options.find(item => item.label === '组件上下文');
|
const curOptions = options.find(item => item.label === '组件上下文');
|
||||||
if (vars?.children?.length) {
|
return resolveQuickVariables(curOptions, quickVars, selfName);
|
||||||
// 获取当前层的变量
|
|
||||||
const current: any[] = vars.children[0].children || [];
|
|
||||||
const filterVars = current
|
|
||||||
.filter(item => item.value !== selfName && item.schemaType)
|
|
||||||
.map(item => {
|
|
||||||
// 子表过滤成员那层
|
|
||||||
if (item.type === 'array' && Array.isArray(item.children)) {
|
|
||||||
if (item.children.length === 1) {
|
|
||||||
const child = item.children[0];
|
|
||||||
if (child.type === 'object' && child.disabled) {
|
|
||||||
return {
|
|
||||||
...item,
|
|
||||||
children: child.children
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
|
|
||||||
return resolver ? resolver(filterVars) : filterVars;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveQuickVariablesByType(
|
export function resolveQuickVariables(
|
||||||
variables: VariableItem[],
|
option: any,
|
||||||
quickVars?: VariableItem[]
|
quickVars?: VariableItem[],
|
||||||
|
selfName?: string
|
||||||
) {
|
) {
|
||||||
|
if (!option?.children?.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const finalVars = [];
|
||||||
|
const curOption = option.children[0];
|
||||||
|
const superOption = option.children[1];
|
||||||
|
const variables = (curOption.children || [])
|
||||||
|
.filter((item: any) => item.value !== selfName && item.schemaType)
|
||||||
|
.map((item: any) => {
|
||||||
|
// 子表过滤成员那层
|
||||||
|
if (item.type === 'array' && Array.isArray(item.children)) {
|
||||||
|
if (item.children.length === 1) {
|
||||||
|
const child = item.children[0];
|
||||||
|
if (child.type === 'object' && child.disabled) {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
children: child.children
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
if (superOption?.children?.length) {
|
||||||
|
const superVars = superOption?.children.filter(
|
||||||
|
(item: any) => item.schemaType && item.type !== 'array'
|
||||||
|
);
|
||||||
|
finalVars.push(...superVars);
|
||||||
|
finalVars.push({
|
||||||
|
label: curOption.label,
|
||||||
|
children: variables
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
finalVars.push(...variables);
|
||||||
|
}
|
||||||
|
|
||||||
if (quickVars?.length) {
|
if (quickVars?.length) {
|
||||||
const vars: VariableItem[] = [];
|
const vars: VariableItem[] = [];
|
||||||
vars.push({
|
vars.push({
|
||||||
label: '快捷变量',
|
label: '快捷变量',
|
||||||
children: quickVars
|
children: quickVars
|
||||||
});
|
});
|
||||||
if (variables.length) {
|
if (finalVars.length) {
|
||||||
vars.push({
|
vars.push({
|
||||||
label: '表单变量',
|
label: '表单变量',
|
||||||
children: variables
|
children: finalVars
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return vars;
|
return vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
return variables;
|
return finalVars;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -20,11 +20,7 @@ import FormulaPicker, {
|
|||||||
import {JSONPipeOut, autobind, translateSchema} from 'amis-editor-core';
|
import {JSONPipeOut, autobind, translateSchema} 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 {
|
import {getVariables, getQuickVariables} from 'amis-editor-core';
|
||||||
getVariables,
|
|
||||||
getQuickVariables,
|
|
||||||
resolveQuickVariablesByType
|
|
||||||
} from 'amis-editor-core';
|
|
||||||
|
|
||||||
import type {BaseEventContext} from 'amis-editor-core';
|
import type {BaseEventContext} from 'amis-editor-core';
|
||||||
import type {VariableItem, FuncGroup} from 'amis-ui';
|
import type {VariableItem, FuncGroup} from 'amis-ui';
|
||||||
@ -215,14 +211,11 @@ export default class FormulaControl extends React.Component<
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const {valueType, quickVars} = this.props;
|
|
||||||
const variables = await getVariables(this);
|
const variables = await getVariables(this);
|
||||||
const quickVariables = await getQuickVariables(this, items =>
|
const quickVariables = await getQuickVariables(this);
|
||||||
items.filter(item => item.schemaType === valueType)
|
|
||||||
);
|
|
||||||
this.setState({
|
this.setState({
|
||||||
variables,
|
variables,
|
||||||
quickVariables: resolveQuickVariablesByType(quickVariables, quickVars)
|
quickVariables: this.filterQuickVariablesByType(quickVariables)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +229,26 @@ export default class FormulaControl extends React.Component<
|
|||||||
this.buttonTarget = ref;
|
this.buttonTarget = ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
filterQuickVariablesByType(variables: any[]) {
|
||||||
|
const rendererSchema = this.getRendererSchemaFromProps();
|
||||||
|
const filterVars = variables
|
||||||
|
.map(item => {
|
||||||
|
if (item.children) {
|
||||||
|
item.children = item.children.filter(
|
||||||
|
(i: any) => i.schemaType === rendererSchema.type
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
.filter(
|
||||||
|
item =>
|
||||||
|
item.schemaType === rendererSchema.type ||
|
||||||
|
(item.children && item.children?.length)
|
||||||
|
);
|
||||||
|
return filterVars;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 ${xx}(非 \${xx})替换成 \${xx}
|
* 将 ${xx}(非 \${xx})替换成 \${xx}
|
||||||
* 备注: 手动编辑时,自动处理掉 ${xx},避免识别成 公式表达式
|
* 备注: 手动编辑时,自动处理掉 ${xx},避免识别成 公式表达式
|
||||||
@ -664,6 +677,7 @@ export default class FormulaControl extends React.Component<
|
|||||||
data={quickVariables}
|
data={quickVariables}
|
||||||
onSelect={this.handleQuickVariableSelect}
|
onSelect={this.handleQuickVariableSelect}
|
||||||
popOverContainer={popOverContainer}
|
popOverContainer={popOverContainer}
|
||||||
|
simplifyMemberOprs
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
@ -55,6 +55,11 @@ export interface TplFormulaControlProps extends FormControlProps {
|
|||||||
* 支付支持快捷变量
|
* 支付支持快捷变量
|
||||||
*/
|
*/
|
||||||
quickVariables?: boolean;
|
quickVariables?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 额外的快捷变量
|
||||||
|
*/
|
||||||
|
quickVars?: Array<VariableItem>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TplFormulaControlState {
|
interface TplFormulaControlState {
|
||||||
@ -148,7 +153,10 @@ export class TplFormulaControl extends React.Component<
|
|||||||
|
|
||||||
const variables = await getVariables(this);
|
const variables = await getVariables(this);
|
||||||
const quickVariables = await getQuickVariables(this);
|
const quickVariables = await getQuickVariables(this);
|
||||||
this.setState({variables, quickVariables});
|
this.setState({
|
||||||
|
variables,
|
||||||
|
quickVariables
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
@ -474,6 +482,7 @@ export class TplFormulaControl extends React.Component<
|
|||||||
data={quickVariables}
|
data={quickVariables}
|
||||||
onSelect={this.handleQuickVariableSelect}
|
onSelect={this.handleQuickVariableSelect}
|
||||||
popOverContainer={popOverContainer}
|
popOverContainer={popOverContainer}
|
||||||
|
simplifyMemberOprs
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
@ -484,6 +484,7 @@ export class TextareaFormulaControl extends React.Component<
|
|||||||
data={quickVariables}
|
data={quickVariables}
|
||||||
onSelect={this.handleQuickVariableSelect}
|
onSelect={this.handleQuickVariableSelect}
|
||||||
popOverContainer={popOverContainer}
|
popOverContainer={popOverContainer}
|
||||||
|
simplifyMemberOprs
|
||||||
/>
|
/>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
|
@ -302,6 +302,7 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
& > label {
|
& > label {
|
||||||
|
cursor: pointer;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@ -311,6 +312,10 @@
|
|||||||
min-width: #{px2rem(50px)};
|
min-width: #{px2rem(50px)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& > .icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.fa-ellipsis-h {
|
.fa-ellipsis-h {
|
||||||
margin-right: #{px2rem(5px)};
|
margin-right: #{px2rem(5px)};
|
||||||
&:hover {
|
&:hover {
|
||||||
@ -319,6 +324,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-tag {
|
&-tag {
|
||||||
|
cursor: auto;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0 #{px2rem(8px)};
|
padding: 0 #{px2rem(8px)};
|
||||||
|
@ -5,6 +5,7 @@ import GroupedSelection from '../GroupedSelection';
|
|||||||
import Tabs, {Tab} from '../Tabs';
|
import Tabs, {Tab} from '../Tabs';
|
||||||
import TreeSelection from '../TreeSelection';
|
import TreeSelection from '../TreeSelection';
|
||||||
import SearchBox from '../SearchBox';
|
import SearchBox from '../SearchBox';
|
||||||
|
import {Icon} from '../icons';
|
||||||
|
|
||||||
import type {VariableItem} from './CodeEditor';
|
import type {VariableItem} from './CodeEditor';
|
||||||
import type {ItemRenderStates} from '../Selection';
|
import type {ItemRenderStates} from '../Selection';
|
||||||
@ -42,29 +43,34 @@ const memberOpers = [
|
|||||||
'即当前列表中所有符合该成员条件的记录总数,需补充成员条件,例如:item.xxx === 1'
|
'即当前列表中所有符合该成员条件的记录总数,需补充成员条件,例如:item.xxx === 1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '取该成员去重之后的总数',
|
label: '去重计数:取该成员去重之后的总数',
|
||||||
value: 'COUNT(UNIQ(${arr}, item.${member}))',
|
value: 'COUNT(UNIQ(${arr}, item.${member}))',
|
||||||
description: '即对该成员记录进行去重,并统计总数'
|
description: '即对该成员记录进行去重,并统计总数',
|
||||||
|
simple: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '取该成员的总和',
|
label: '求和:求当前列的所有值之和',
|
||||||
value: 'SUM(ARRAYMAP(${arr}, item => item.${member}))',
|
value: 'SUM(ARRAYMAP(${arr}, item => item.${member}))',
|
||||||
description: '即计算该成员记录的总和,需确认该成员记录均为数字类型'
|
description: '即计算该成员记录的总和,需确认该成员记录均为数字类型',
|
||||||
|
simple: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '取该成员的平均值',
|
label: '平均值:求当前列的平均值',
|
||||||
value: 'AVG(ARRAYMAP(${arr}, item => item.${member}))',
|
value: 'AVG(ARRAYMAP(${arr}, item => item.${member}))',
|
||||||
description: '即计算该成员记录的平均值,需确认该成员记录均为数字类型'
|
description: '即计算该成员记录的平均值,需确认该成员记录均为数字类型',
|
||||||
|
simple: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '取该成员的最大值',
|
label: '最大值:取当前列的最大值',
|
||||||
value: 'MAX(ARRAYMAP(${arr}, item => item.${member}))',
|
value: 'MAX(ARRAYMAP(${arr}, item => item.${member}))',
|
||||||
description: '即计算该成员记录中最大值,需确认该成员记录均为数字类型'
|
description: '即计算该成员记录中最大值,需确认该成员记录均为数字类型',
|
||||||
|
simple: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '取该成员的最小值',
|
label: '最小值:取当前列的最小值',
|
||||||
value: 'MIN(ARRAYMAP(${arr}, item => item.${member}))',
|
value: 'MIN(ARRAYMAP(${arr}, item => item.${member}))',
|
||||||
description: '即计算该成员记录中最小值,需确认该成员记录均为数字类型'
|
description: '即计算该成员记录中最小值,需确认该成员记录均为数字类型',
|
||||||
|
simple: true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -80,6 +86,7 @@ export interface VariableListProps extends ThemeProps, SpinnerExtraProps {
|
|||||||
onSelect?: (item: VariableItem) => void;
|
onSelect?: (item: VariableItem) => void;
|
||||||
selfVariableName?: string;
|
selfVariableName?: string;
|
||||||
expandTree?: boolean;
|
expandTree?: boolean;
|
||||||
|
simplifyMemberOprs?: boolean;
|
||||||
popOverContainer?: () => HTMLElement;
|
popOverContainer?: () => HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +103,7 @@ function VariableList(props: VariableListProps) {
|
|||||||
placeholderRender,
|
placeholderRender,
|
||||||
selfVariableName,
|
selfVariableName,
|
||||||
expandTree,
|
expandTree,
|
||||||
|
simplifyMemberOprs,
|
||||||
popOverContainer
|
popOverContainer
|
||||||
} = props;
|
} = props;
|
||||||
const [variables, setVariables] = React.useState<Array<VariableItem>>([]);
|
const [variables, setVariables] = React.useState<Array<VariableItem>>([]);
|
||||||
@ -177,28 +185,30 @@ function VariableList(props: VariableListProps) {
|
|||||||
}
|
}
|
||||||
popOverRender={({onClose}) => (
|
popOverRender={({onClose}) => (
|
||||||
<ul className={cx(`${classPrefix}-item-oper`)}>
|
<ul className={cx(`${classPrefix}-item-oper`)}>
|
||||||
{memberOpers.map((item, i) => {
|
{memberOpers
|
||||||
return (
|
.filter(item => !simplifyMemberOprs || item.simple)
|
||||||
<TooltipWrapper
|
.map((item, i) => {
|
||||||
key={i}
|
return (
|
||||||
tooltip={item.description}
|
<TooltipWrapper
|
||||||
tooltipTheme="dark"
|
|
||||||
>
|
|
||||||
<li
|
|
||||||
key={i}
|
key={i}
|
||||||
onClick={() =>
|
tooltip={item.description}
|
||||||
handleMemberClick(
|
tooltipTheme="dark"
|
||||||
{...item, isMember: true},
|
|
||||||
option,
|
|
||||||
onClose
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<span>{item.label}</span>
|
<li
|
||||||
</li>
|
key={i}
|
||||||
</TooltipWrapper>
|
onClick={() =>
|
||||||
);
|
handleMemberClick(
|
||||||
})}
|
{...item, isMember: true},
|
||||||
|
option,
|
||||||
|
onClose
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span>{item.label}</span>
|
||||||
|
</li>
|
||||||
|
</TooltipWrapper>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@ -207,7 +217,14 @@ function VariableList(props: VariableListProps) {
|
|||||||
tooltip={option.description ?? option.label}
|
tooltip={option.description ?? option.label}
|
||||||
tooltipTheme="dark"
|
tooltipTheme="dark"
|
||||||
>
|
>
|
||||||
<label onClick={onClick}>{option.label}</label>
|
<>
|
||||||
|
<label onClick={onClick}>{option.label}</label>
|
||||||
|
<Icon
|
||||||
|
onClick={onClick}
|
||||||
|
icon="ellipsis-v"
|
||||||
|
className="icon"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
</TooltipWrapper>
|
</TooltipWrapper>
|
||||||
)}
|
)}
|
||||||
</PopOverContainer>
|
</PopOverContainer>
|
||||||
|
Loading…
Reference in New Issue
Block a user