在业务实现的过程中,时常会出现且或关系逻辑的拼接。逻辑运算的组合使用,是实现复杂业务规则和决议支持系统的关键技能。
目前袋鼠云的指标管理平台、客户数据洞察平台、数据资产平台都有在使用。并且,且或组件已经在 RC 5.0中添加到组件库,企业现在可以更加机动地构建和实施复杂的业务规则。
本文将从前期分析、组件封装、具体实现三个维度深入探究如何实现业务中的且或组件。
前期分析
01 确定好数据结构
因为是嵌套结构,可以通过 ➕➖ 来增长层级大概数据,因此采用树形结构来存储数据。- export interface IFilterValue<T> {
- key: string;
- level?: number; // 当前节点的层级,用于判断一些按钮的展示
- type?: number; // 当前节点的条件关系,1 | 2
- rowValues?: T; // Form 节点的相关的信息(子节点无条件节点时才有)
- children?: IFilterValue<T>[]; // 子节点的信息(子节点存在条件节点时才有)
- }
复制代码 上述的图片的数据为:- {
- "key": "qTipLrlUt",
- "level": 1,
- "children": [
- {
- "key": "B6Jrbqcfof",
- "type": 2,
- "level": 2,
- "children": [
- {
- "rowValues": {
- "condition": 1,
- "rowPermission": ""
- },
- "key": "deg8x8UgZ",
- "level": 2
- },
- {
- "key": "_sczw_1h8H",
- "type": 1,
- "level": 3,
- "children": [
- {
- "key": "Z5UkUPJoA",
- "rowValues": {
- "condition": 1,
- "rowPermission": ""
- },
- "level": 3
- },
- {
- "key": "MbpJILqHGx",
- "rowValues": {
- "condition": 1,
- "rowPermission": ""
- },
- "level": 3
- }
- ]
- }
- ]
- },
- {
- "rowValues": {
- "condition": 1,
- "rowPermission": ""
- },
- "key": "qx6bG0o5H",
- "level": 1
- }
- ],
- "type": 1
- }
复制代码 02 明确每个使用按钮的实现
03 明确组件的封装
· 组件只希望实现条件节点/线条/使用按钮的展示,因今后面的组件需要作为参数 component 传入
· 组件对层级有一个控制,支持 maxLevel 来控制
· 每一次新增数据的时候,默认值需要传入 initValues
· 支持两种模式:「编辑状态」和「查看状态」
· 支持受控和非受控两种模式
组件封装
01 FilterRules
提供给用户使用的组件,实现数据的增删改查使用,可以采用受控和非受控两种模式。它担当的参数如下:- interface IProps<T> {
- value?: IFilterValue<T>;
- disabled?: boolean;
- maxLevel?: number;
- initValues: T;
- notEmpty?: { data: boolean; message?: string };
- component: (props: IComponentProps<T>) => React.ReactNode;
- onChange?: (value: IFilterValue<T> | undefined) => void;
- }
复制代码- export const FilterRules = <T>(props: IProps<T>) => {
- const {
- component,
- maxLevel = 5,
- disabled = false,
- notEmpty = { data: true, message: '必须有一条数据' },
- value,
- initValues,
- onChange,
- } = props;
- // 查找当前操作的节点
- const finRelationNode = (
- parentData: IFilterValue<T>,
- targetKey: string,
- needCurrent?: boolean,
- ): IFilterValue<T> | null | undefined => {};
- const handleAddCondition = (keyObj: { key: string; isOut?: boolean }) => {};
- // 增加新的数据,判断是在当前节点下新增或者新生成一个条件节点
- const addCondition = (
- treeNode: any,
- keyObj: { key: string; isOut?: boolean },
- initRowValue: T,
- ) => {};
- const handleDeleteCondition = (key: string) => {};
- // 删除节点,删除当前节点下的一条数据或者是删除一个条件节点
- const deleteCondition = (parentData: IFilterValue<T>, key: string) => {};
- // 删除一个条件节点时,更新当前数据的层级
- const updateLevel = (node: IFilterValue<T>) => {};
- // 更改条件节点的条件
- const handleChangeCondition = (
- key: string,
- type: ROW_PERMISSION_RELATION,
- ) => {};
- // 改变节点的的数据
- const handleChangeRowValues = (key: string, values: T) => {};
- return (
- <RulesController<T>
- maxLevel={maxLevel}
- disabled={disabled}
- value={value}
- component={component}
- onAddCondition={handleAddCondition}
- onDeleteCondition={handleDeleteCondition}
- onChangeCondition={handleChangeCondition}
- onChangeRowValues={handleChangeRowValues}
- />
- );
- };
复制代码 ● 编辑情况
· 非受控组件使用- <Form form={form}>
- <Form.Item name={'condition'}>
- <FilterRules<IRowValue>
- component={(props) => (
- <RowColumnConfig columns={record?.columns ?? []} {...props} />
- )}
- maxLevel={MAX_LEVEL}
- initValues={INIT_ROW_VALUES}
- />
- </Form.Item>
- </Form>;
- // RowColumnConfig 实现,name 可能是 children[0].formValues
- <Form.Item
- name={['condition', ...name, 'column']}
- rules={[{ message: '请选择字段', required: true }]}
- initialValue={column}
- >
- <Select placeholder="请选择字段">
- {columns.map((item) => (
- <Option key={item} value={item}>
- {item}
- </Option>
- ))}
- </Select>
- </Form.Item>;
- // 最后通过 form.validateFields() 拿到的和上述的数据结构一致
复制代码 · 受控组件使用- const [ruleData, setRuleData] = useState({
- key: shortid(),
- level: 0,
- rowValues: {
- column: first.column,
- condition: first.condition,
- rowPermission: first?.value,
- },
- });
- <FilterRules<IRowValue>
- value={ruleData}
- component={(props) => (
- <RowColumnConfig columns={record?.columns ?? []} {...props} />
- )}
- maxLevel={MAX_LEVEL}
- initValues={INIT_ROW_VALUES}
- onChange={setRuleData}
- />;
- // 通过 ruleData 就能够拿到最后的结果
复制代码 ● 查看使用- <FilterRules
- component={(props) => <RowColumnConfig columns={[]} {...props} />}
- disabled
- value={value}
- />
复制代码 ● 编辑查看使用(后续新增)
上图为最后实现的结果,适用于部门数据禁用且可以编辑其他数据。常见业务情景:上一次生存的数据不可修改,但需要在当前底子上继承新增数据。
在这种使用模式下,FilterRules 组件上的 props 依旧为 false,通过设置 value 中每一个节点的 disabled 属性来实现上述功能。
[code]// 修改 IFilterValue 的类型//
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |