我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 本文作者:霜序 本文首發於:https://juejin.cn/post/7299384698882539574 在大數據業務中,時常會出現且或關係邏輯的拼接,有需要做 ...
我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。
本文作者:霜序
本文首發於:https://juejin.cn/post/7299384698882539574
在大數據業務中,時常會出現且或關係邏輯的拼接,有需要做成可視化配置,如下圖
目前該組件已經開源到了我們組件庫 dt-react-component,詳細查看
前期分析
需要確定好數據結構
因為是嵌套結構,可以通過 ➕➖ 來增加層級或者數據,因此採用樹形結構來存儲數據。
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
}
明確每個操作按鈕的實現
明確組件的封裝
- 組件只希望實現條件節點/線條/操作按鈕的展示,因此後面的組件需要作為參數 component 傳入
- 組件對層級有一個控制,支持 maxLevel 來控制
- 每一次新增數據的時候,預設值需要傳入 initValues
- 支持兩種模式 編輯狀態 和 查看狀態
- 支持受控和非受控兩種模式
組件封裝
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 屬性來實現上述功能
// 修改 IFilterValue 的類型
//