feat: 公式支持快捷变量支持

This commit is contained in:
yupeng12 2024-06-06 17:31:34 +08:00
parent 09e564e9e7
commit 0a436fb137
6 changed files with 138 additions and 78 deletions

View File

@ -4,7 +4,7 @@
import {hasIcon, mapObject, utils} from 'amis';
import type {PlainObject, Schema, SchemaNode} from 'amis';
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 {isObservable, reaction} from 'mobx';
import DeepDiff, {Diff} from 'deep-diff';
@ -1362,65 +1362,78 @@ export async function getVariables(that: any) {
return variablesArr;
}
export async function getQuickVariables(
that: any,
resolver?: (vars: any[]) => any[]
) {
export async function getQuickVariables(that: any) {
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);
const options = await manager?.dataSchema?.getDataPropsAsOptions();
if (Array.isArray(options)) {
const vars = options.find(item => item.label === '组件上下文');
if (vars?.children?.length) {
// 获取当前层的变量
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;
}
const curOptions = options.find(item => item.label === '组件上下文');
return resolveQuickVariables(curOptions, quickVars, selfName);
}
return [];
}
export function resolveQuickVariablesByType(
variables: VariableItem[],
quickVars?: VariableItem[]
export function resolveQuickVariables(
option: any,
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) {
const vars: VariableItem[] = [];
vars.push({
label: '快捷变量',
children: quickVars
});
if (variables.length) {
if (finalVars.length) {
vars.push({
label: '表单变量',
children: variables
children: finalVars
});
}
return vars;
}
return variables;
return finalVars;
}
/**

View File

@ -20,11 +20,7 @@ import FormulaPicker, {
import {JSONPipeOut, autobind, translateSchema} from 'amis-editor-core';
import {EditorManager} from 'amis-editor-core';
import {reaction} from 'mobx';
import {
getVariables,
getQuickVariables,
resolveQuickVariablesByType
} from 'amis-editor-core';
import {getVariables, getQuickVariables} from 'amis-editor-core';
import type {BaseEventContext} from 'amis-editor-core';
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 quickVariables = await getQuickVariables(this, items =>
items.filter(item => item.schemaType === valueType)
);
const quickVariables = await getQuickVariables(this);
this.setState({
variables,
quickVariables: resolveQuickVariablesByType(quickVariables, quickVars)
quickVariables: this.filterQuickVariablesByType(quickVariables)
});
}
@ -236,6 +229,26 @@ export default class FormulaControl extends React.Component<
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}
@ -664,6 +677,7 @@ export default class FormulaControl extends React.Component<
data={quickVariables}
onSelect={this.handleQuickVariableSelect}
popOverContainer={popOverContainer}
simplifyMemberOprs
/>
</ul>
);

View File

@ -55,6 +55,11 @@ export interface TplFormulaControlProps extends FormControlProps {
*
*/
quickVariables?: boolean;
/**
*
*/
quickVars?: Array<VariableItem>;
}
interface TplFormulaControlState {
@ -148,7 +153,10 @@ export class TplFormulaControl extends React.Component<
const variables = await getVariables(this);
const quickVariables = await getQuickVariables(this);
this.setState({variables, quickVariables});
this.setState({
variables,
quickVariables
});
}
componentWillUnmount() {
@ -474,6 +482,7 @@ export class TplFormulaControl extends React.Component<
data={quickVariables}
onSelect={this.handleQuickVariableSelect}
popOverContainer={popOverContainer}
simplifyMemberOprs
/>
</ul>
);

View File

@ -484,6 +484,7 @@ export class TextareaFormulaControl extends React.Component<
data={quickVariables}
onSelect={this.handleQuickVariableSelect}
popOverContainer={popOverContainer}
simplifyMemberOprs
/>
</ul>
);

View File

@ -302,6 +302,7 @@
white-space: nowrap;
& > label {
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@ -311,6 +312,10 @@
min-width: #{px2rem(50px)};
}
& > .icon {
cursor: pointer;
}
.fa-ellipsis-h {
margin-right: #{px2rem(5px)};
&:hover {
@ -319,6 +324,7 @@
}
&-tag {
cursor: auto;
vertical-align: middle;
text-align: center;
padding: 0 #{px2rem(8px)};

View File

@ -5,6 +5,7 @@ import GroupedSelection from '../GroupedSelection';
import Tabs, {Tab} from '../Tabs';
import TreeSelection from '../TreeSelection';
import SearchBox from '../SearchBox';
import {Icon} from '../icons';
import type {VariableItem} from './CodeEditor';
import type {ItemRenderStates} from '../Selection';
@ -42,29 +43,34 @@ const memberOpers = [
'即当前列表中所有符合该成员条件的记录总数需补充成员条件例如item.xxx === 1'
},
{
label: '取该成员去重之后的总数',
label: '去重计数:取该成员去重之后的总数',
value: 'COUNT(UNIQ(${arr}, item.${member}))',
description: '即对该成员记录进行去重,并统计总数'
description: '即对该成员记录进行去重,并统计总数',
simple: true
},
{
label: '取该成员的总和',
label: '求和:求当前列的所有值之和',
value: 'SUM(ARRAYMAP(${arr}, item => item.${member}))',
description: '即计算该成员记录的总和,需确认该成员记录均为数字类型'
description: '即计算该成员记录的总和,需确认该成员记录均为数字类型',
simple: true
},
{
label: '取该成员的平均值',
label: '平均值:求当前列的平均值',
value: 'AVG(ARRAYMAP(${arr}, item => item.${member}))',
description: '即计算该成员记录的平均值,需确认该成员记录均为数字类型'
description: '即计算该成员记录的平均值,需确认该成员记录均为数字类型',
simple: true
},
{
label: '取该成员的最大值',
label: '最大值:取当前列的最大值',
value: 'MAX(ARRAYMAP(${arr}, item => item.${member}))',
description: '即计算该成员记录中最大值,需确认该成员记录均为数字类型'
description: '即计算该成员记录中最大值,需确认该成员记录均为数字类型',
simple: true
},
{
label: '取该成员的最小值',
label: '最小值:取当前列的最小值',
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;
selfVariableName?: string;
expandTree?: boolean;
simplifyMemberOprs?: boolean;
popOverContainer?: () => HTMLElement;
}
@ -96,6 +103,7 @@ function VariableList(props: VariableListProps) {
placeholderRender,
selfVariableName,
expandTree,
simplifyMemberOprs,
popOverContainer
} = props;
const [variables, setVariables] = React.useState<Array<VariableItem>>([]);
@ -177,28 +185,30 @@ function VariableList(props: VariableListProps) {
}
popOverRender={({onClose}) => (
<ul className={cx(`${classPrefix}-item-oper`)}>
{memberOpers.map((item, i) => {
return (
<TooltipWrapper
key={i}
tooltip={item.description}
tooltipTheme="dark"
>
<li
{memberOpers
.filter(item => !simplifyMemberOprs || item.simple)
.map((item, i) => {
return (
<TooltipWrapper
key={i}
onClick={() =>
handleMemberClick(
{...item, isMember: true},
option,
onClose
)
}
tooltip={item.description}
tooltipTheme="dark"
>
<span>{item.label}</span>
</li>
</TooltipWrapper>
);
})}
<li
key={i}
onClick={() =>
handleMemberClick(
{...item, isMember: true},
option,
onClose
)
}
>
<span>{item.label}</span>
</li>
</TooltipWrapper>
);
})}
</ul>
)}
>
@ -207,7 +217,14 @@ function VariableList(props: VariableListProps) {
tooltip={option.description ?? option.label}
tooltipTheme="dark"
>
<label onClick={onClick}>{option.label}</label>
<>
<label onClick={onClick}>{option.label}</label>
<Icon
onClick={onClick}
icon="ellipsis-v"
className="icon"
/>
</>
</TooltipWrapper>
)}
</PopOverContainer>