Commit 064d5298 authored by 张烨's avatar 张烨

refactor: 重构功能选择器组件

parent c92c4e87
import React, { useState, useEffect } from 'react';
import { debounce } from 'lodash';
import { Checkbox } from 'antd';
import classnames from 'classnames';
import useMergeValue from 'use-merge-value';
import styles from './itemCard.less';
const CheckGroup = Checkbox.Group;
const getId = item => item.userID || item.roleID || item.stationID || item.id;
const checkIsGroup = node => ['widgetGroup'].includes(node?.type || node);
const checkChildrenByCondition = (item, fn, tag = 'every') => {
if (!checkIsGroup(item)) {
return fn(item);
}
return item.children[tag](t => checkChildrenByCondition(t, fn, tag));
};
import { checkChildrenByCondition, checkIsGroup, getId } from '.';
const ListCardItem = props => {
const {
getValueCallback,
itemid,
searchWord,
allChecked,
groupIndeterminate,
children,
text,
type,
isChecked,
...rest
} = props;
const { searchWord, item, valueList, updateValueList, ouid } = props;
// id
const id = getId(rest);
// 当前checkbox为分组时有用,是否部分选中
const [indeterminate, setIndeterminate] = useState(true);
// 用来收集子节点的值
const [childValues, setChildValues] = useState({});
const id = getId(item);
// 是否是地图组件
const isMapWedgt = type === 'widgetUIPage';
const isMapWedgt = item.type === 'widgetUIPage';
// 当前组件是否是分组id
const isGroup = checkIsGroup(type);
const [groupChecked, setGroupChecked] = useState(false);
// 当前组件是否勾选
const [checked, setChecked] = useState(isChecked);
const isGroup = checkIsGroup(item);
const [indeterminate, setIndeterminate] = useState(!isGroup);
const [childrenKeys, setChildrenKeys] = useState([]);
useEffect(() => {
// const all = children.every(u => checkAllChildrenChecked(u));
if (isGroup) {
// setIndeterminate(!all && children.some(u => checkSomeChildrenChecked(u)));
const keys = checkChildrenByCondition(item, c => getId(c), 'map').flat();
setChildrenKeys(keys);
} else {
setIndeterminate(false);
// 初始进来报告自己的值
getValueCallback(isChecked ? [id] : [], itemid);
//
}
}, []);
// 监听父级是否勾选,如果父级勾选 则需要吧自己设置勾选状态并回传值
useEffect(() => {
if (allChecked !== checked && !groupIndeterminate) {
if (!isGroup) {
setChecked(allChecked);
setIndeterminate(false);
getValueCallback(allChecked ? [id] : [], itemid);
}
}
}, [allChecked, groupIndeterminate]);
}, [item]);
// 勾选事件处理
const handleChecked = e => {
const { checked: v } = e.target;
if (isGroup) {
if (indeterminate) {
setGroupChecked(true);
} else {
setGroupChecked(v);
}
setIndeterminate(false);
const result = [...childrenKeys, id];
updateValueList(v ? result : [], result);
} else {
setChecked(v);
}
if (!isGroup) {
getValueCallback(v ? [id] : [], itemid);
updateValueList(v ? [id] : [], [id]);
}
};
const handleChildValueCallback = (arr, childIndex) => {
// 进这里的都是分组,组长统计并处理自己的状态: 全选,部分选,零选
// 拿到所有勾选的子节点
childValues[childIndex] = arr.flat();
const childValArr = Object.values(childValues).flat();
// 保存组员状态
setChildValues({ ...childValues });
// 递归执行的条件函数
const condition = c => childValArr.includes(getId(c));
const isAllchecked = checkChildrenByCondition(
{ children, type },
condition,
);
const isSomeChecked = checkChildrenByCondition(
{ children, type },
condition,
'some',
);
setIndeterminate(!isAllchecked && isSomeChecked);
setGroupChecked(isSomeChecked);
// eslint-disable-next-line no-unused-expressions
getValueCallback && getValueCallback([...childValArr, id], itemid);
};
const renderChild = () =>
children &&
children.map((c, i) => (
item.children &&
item.children.map((c, i) => (
<ListCardItem
{...c}
item={c}
itemid={i}
allChecked={groupChecked}
groupIndeterminate={indeterminate}
key={`item${i}key`}
getValueCallback={handleChildValueCallback}
updateValueList={updateValueList}
valueList={valueList}
ouid={ouid}
searchWord={searchWord}
/>
));
......@@ -139,24 +61,25 @@ const ListCardItem = props => {
<div className={styles.topCheckbox}>
<Checkbox
indeterminate={isGroup ? indeterminate : false}
checked={isGroup ? groupChecked : checked}
checked={valueList.includes(id)}
onChange={handleChecked}
>
{isMapWedgt ? (
<div
style={{ display: 'inline-block' }}
ref={r => {
if (r) r.innerHTML = text;
if (r) r.innerHTML = item.text;
}}
/>
) : (
<span
className={classnames({
[styles.boldLabel]: isGroup,
[styles.isSearch]: searchWord && text.includes(searchWord),
[styles.isSearch]:
searchWord && item.text.includes(searchWord),
})}
>
{text}
{item.text}
</span>
)}
</Checkbox>
......
import React, { useState, useEffect, useCallback, useRef } from 'react';
import { Spin, Button } from 'antd';
import { Spin, Button, Empty } from 'antd';
import _ from 'lodash';
import ListCardItem from './ItemCard';
import { get, post } from '@/services';
import styles from './ItemCard.less';
const tip = 'loading...';
export const getId = item =>
item.userID || item.roleID || item.stationID || item.id;
export const checkIsGroup = node =>
['widgetGroup'].includes(node?.type || node);
export const checkChildrenByCondition = (item, fn, tag = 'every') => {
if (!checkIsGroup(item)) {
return fn(item);
}
return item.children[tag](t => checkChildrenByCondition(t, fn, tag));
};
const ListCard = props => {
const {
ouid,
searchWord,
valueCallback,
onCommit = () => {},
itemObj,
} = props;
const [valueList, setValueList] = useState({});
const { ouid, searchWord, onCommit = () => {}, itemObj } = props;
const [valueList, setValueList] = useState([]);
const [dataList, setdataList] = useState([]);
const [loading, setLoading] = useState(true);
const [mapObj, setMapObj] = useState({});
const updateValueList = (checkedKeys, childrenKeys) => {
console.time('updateValueList:');
const removekeys = _.difference(childrenKeys, checkedKeys);
let result = _.uniq(_.union(checkedKeys, valueList));
_.remove(result, v => removekeys.includes(v));
setValueList(result);
console.timeEnd('updateValueList:');
};
const getValueCallback = useCallback((value, index) => {
valueList[index] = value;
setValueList({ ...valueList });
valueCallback({ ...valueList });
}, []);
console.log(itemObj, 'itemObj');
useEffect(() => {
setLoading(true);
const defaultConfig = {
......@@ -50,6 +61,18 @@ const ListCard = props => {
list.push({ ...defaultConfig, ...item });
});
setdataList(list);
setValueList(
list
.map(l =>
checkChildrenByCondition(
l,
it => (it.isChecked ? [getId(it)] : []),
'map',
).flat(Infinity),
)
.flat(Infinity)
.filter(Boolean),
);
setLoading(false);
})
.catch(err => {
......@@ -76,14 +99,16 @@ const ListCard = props => {
<>
{dataList.some(d => d.type === 'widgetUIPage') && (
<ListCardItem
{...{
item={{
type: 'widgetGroup',
searchWord,
children: dataList.filter(d => d.type === 'widgetUIPage'),
text: '地图组件',
itemid: '9999',
}}
getValueCallback={getValueCallback}
ouid={ouid}
updateValueList={updateValueList}
valueList={valueList}
searchWord={searchWord}
/>
)}
......@@ -93,10 +118,11 @@ const ListCard = props => {
.filter(d => d.type === 'widgetGroup')
.map((item, index) => (
<ListCardItem
{...item}
itemid={index}
item={item}
ouid={ouid}
updateValueList={updateValueList}
valueList={valueList}
key={`item${index}key`}
getValueCallback={getValueCallback}
searchWord={searchWord}
{...props}
/>
......
......@@ -160,13 +160,12 @@ const SiteManage = () => {
const valueCallback = valueObj => {
setSubList(valueObj);
};
const handleCommit = value => {
console.log(value);
let arr = Object.values(subList);
const handleCommit = rusults => {
console.log(rusults);
setMenuToRole(
qs.stringify({
roleID,
menuNameList: String(arr.flat()),
menuNameList: String(rusults.flat()),
}),
{
headers: {
......@@ -306,7 +305,6 @@ const SiteManage = () => {
ouid={roleID}
itemObj={itemObj}
searchWord={searchWord}
valueCallback={valueCallback}
onCommit={handleCommit}
/>
)}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment