前端数据组装案例
多选/单选的二级树(数组实现)转数组
需求描述
流程节点退回原因为多级选择,可单选也可多选。
- 退回:一级原因多选,当选中其他时,可手动输入原因作为一级退回原因的补充;
- 拒绝:一级原因多选,二级原因多选。支持配置为只选一级不选二级,也支持配置为选中一级,全选二级并排除被选中一级。
其中,一级/二级原因的选项为字典值,字典为数组递归定义。
查询字典接口返回数据结构:
后端需要复杂的动态数据分析,所以数据存储要求扁平化,要求结构为:
onChange监听处理数组转换问题
问题关键:
- 一二级原因既可以多选也可以单选;
- 存在二级与一级共存和互斥两种情况;
借助Map递归转化
/**
* dictToAbReasons
* @param vals
*/
export const dictToAbReasons = (
vals: Dict.DictionaryItem[] | Dict.DictionaryItem[][],
) => {
if (!vals) {
return;
}
const levelMapV1 = new Map<string, Dict.DictionaryItem>();
const levelMapV2 = new Map<string, Dict.DictionaryItem>();
const abReasons: Todo.AbnormalReason[] = [];
for (var i = 0; i < vals.length; i++) {
if (vals[i][0]) levelMapV1.set(vals[i][0]?.itemId, vals[i][0]);
if (vals[i][1]) levelMapV2.set(vals[i][1]?.itemId, vals[i][1]);
}
if (levelMapV1.size < 1 && levelMapV2.size < 1) {
levelMapV1.set(vals[0]?.itemId, vals[0]);
levelMapV2.set(vals[1]?.itemId, vals[1]);
}
if (levelMapV2.size > 0) {
levelMapV2.forEach((x) => {
if (levelMapV1.get(x?.parentId)) {
abReasons.push({
oneLevel: levelMapV1.get(x?.parentId).itemKey,
oneLevelVal: levelMapV1.get(x?.parentId).itemName,
secondLevel: x.itemKey,
secondLevelVal: x.itemName,
});
}
});
}
if (abReasons.length < 1 && levelMapV1.size > 0) {
levelMapV1.forEach((x) => {
abReasons.push({
oneLevel: x?.itemKey,
oneLevelVal: x?.itemName,
});
});
}
levelMapV1.clear();
levelMapV2.clear();
return abReasons;
};
注入Remark
/**
* injectOneLevelRemark
* @param abReasons
* @param key
* @param oneLevelRemark
*/
export const injectOneLevelRemark = (
abReasons: Todo.AbnormalReason[] | undefined,
key: string,
oneLevelRemark: string | undefined,
) => {
if (abReasons && oneLevelRemark && key) {
for (var i = 0; i < abReasons?.length; i++) {
if (abReasons[i]?.oneLevel === key) {
abReasons[i].oneLevelRemark = oneLevelRemark;
break;
}
}
}
console.log('abReasons=====>', abReasons);
return abReasons;
};
监听触发函数
const changeReasons = (
values: Dict.DictionaryItem[] | Dict.DictionaryItem[][],
) => {
const abReasons: Todo.AbnormalReason[] = dictToAbReasons(values);
formRef.current?.setFieldValue(
['review', 'abnormalReasons'],
abReasons
);
let flag = containsKey(abReasons,'backOneLevelRemark');
setOneLevelRemarkSwitch(flag);
if (!flag){
initOneLevelRemark();
}
};
const handleSubmit = async (value: A.Xxx) => {
injectOneLevelRemark(value.review?.abnormalReasons, 'backOneLevelRemark', value?.review?.abReasonsOneLevelRemark);
// ...
}