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

refactor: 重构功能选择器组件

parent c92c4e87
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { debounce } from 'lodash';
import { Checkbox } from 'antd'; import { Checkbox } from 'antd';
import classnames from 'classnames'; import classnames from 'classnames';
import useMergeValue from 'use-merge-value';
import styles from './itemCard.less'; import styles from './itemCard.less';
import { checkChildrenByCondition, checkIsGroup, getId } from '.';
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));
};
const ListCardItem = props => { const ListCardItem = props => {
const { const { searchWord, item, valueList, updateValueList, ouid } = props;
getValueCallback,
itemid,
searchWord,
allChecked,
groupIndeterminate,
children,
text,
type,
isChecked,
...rest
} = props;
// id // id
const id = getId(rest); const id = getId(item);
// 当前checkbox为分组时有用,是否部分选中
const [indeterminate, setIndeterminate] = useState(true);
// 用来收集子节点的值
const [childValues, setChildValues] = useState({});
// 是否是地图组件 // 是否是地图组件
const isMapWedgt = type === 'widgetUIPage'; const isMapWedgt = item.type === 'widgetUIPage';
// 当前组件是否是分组id // 当前组件是否是分组id
const isGroup = checkIsGroup(type); const isGroup = checkIsGroup(item);
const [groupChecked, setGroupChecked] = useState(false); const [indeterminate, setIndeterminate] = useState(!isGroup);
const [childrenKeys, setChildrenKeys] = useState([]);
// 当前组件是否勾选
const [checked, setChecked] = useState(isChecked);
useEffect(() => { useEffect(() => {
// const all = children.every(u => checkAllChildrenChecked(u));
if (isGroup) { if (isGroup) {
// setIndeterminate(!all && children.some(u => checkSomeChildrenChecked(u))); const keys = checkChildrenByCondition(item, c => getId(c), 'map').flat();
setChildrenKeys(keys);
} else { } else {
setIndeterminate(false); //
// 初始进来报告自己的值
getValueCallback(isChecked ? [id] : [], itemid);
} }
}, []); }, [item]);
// 监听父级是否勾选,如果父级勾选 则需要吧自己设置勾选状态并回传值
useEffect(() => {
if (allChecked !== checked && !groupIndeterminate) {
if (!isGroup) {
setChecked(allChecked);
setIndeterminate(false);
getValueCallback(allChecked ? [id] : [], itemid);
}
}
}, [allChecked, groupIndeterminate]);
// 勾选事件处理 // 勾选事件处理
const handleChecked = e => { const handleChecked = e => {
const { checked: v } = e.target; const { checked: v } = e.target;
if (isGroup) { if (isGroup) {
if (indeterminate) { const result = [...childrenKeys, id];
setGroupChecked(true); updateValueList(v ? result : [], result);
} else {
setGroupChecked(v);
}
setIndeterminate(false);
} else { } else {
setChecked(v); updateValueList(v ? [id] : [], [id]);
}
if (!isGroup) {
getValueCallback(v ? [id] : [], itemid);
} }
}; };
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 = () => const renderChild = () =>
children && item.children &&
children.map((c, i) => ( item.children.map((c, i) => (
<ListCardItem <ListCardItem
{...c} item={c}
itemid={i} itemid={i}
allChecked={groupChecked}
groupIndeterminate={indeterminate}
key={`item${i}key`} key={`item${i}key`}
getValueCallback={handleChildValueCallback} updateValueList={updateValueList}
valueList={valueList}
ouid={ouid}
searchWord={searchWord} searchWord={searchWord}
/> />
)); ));
...@@ -139,24 +61,25 @@ const ListCardItem = props => { ...@@ -139,24 +61,25 @@ const ListCardItem = props => {
<div className={styles.topCheckbox}> <div className={styles.topCheckbox}>
<Checkbox <Checkbox
indeterminate={isGroup ? indeterminate : false} indeterminate={isGroup ? indeterminate : false}
checked={isGroup ? groupChecked : checked} checked={valueList.includes(id)}
onChange={handleChecked} onChange={handleChecked}
> >
{isMapWedgt ? ( {isMapWedgt ? (
<div <div
style={{ display: 'inline-block' }} style={{ display: 'inline-block' }}
ref={r => { ref={r => {
if (r) r.innerHTML = text; if (r) r.innerHTML = item.text;
}} }}
/> />
) : ( ) : (
<span <span
className={classnames({ className={classnames({
[styles.boldLabel]: isGroup, [styles.boldLabel]: isGroup,
[styles.isSearch]: searchWord && text.includes(searchWord), [styles.isSearch]:
searchWord && item.text.includes(searchWord),
})} })}
> >
{text} {item.text}
</span> </span>
)} )}
</Checkbox> </Checkbox>
......
import React, { useState, useEffect, useCallback, useRef } from 'react'; 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 ListCardItem from './ItemCard';
import { get, post } from '@/services'; import { get, post } from '@/services';
import styles from './ItemCard.less'; import styles from './ItemCard.less';
const tip = 'loading...'; 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 ListCard = props => {
const { const { ouid, searchWord, onCommit = () => {}, itemObj } = props;
ouid, const [valueList, setValueList] = useState([]);
searchWord,
valueCallback,
onCommit = () => {},
itemObj,
} = props;
const [valueList, setValueList] = useState({});
const [dataList, setdataList] = useState([]); const [dataList, setdataList] = useState([]);
const [loading, setLoading] = useState(true); 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(() => { useEffect(() => {
setLoading(true); setLoading(true);
const defaultConfig = { const defaultConfig = {
...@@ -50,6 +61,18 @@ const ListCard = props => { ...@@ -50,6 +61,18 @@ const ListCard = props => {
list.push({ ...defaultConfig, ...item }); list.push({ ...defaultConfig, ...item });
}); });
setdataList(list); setdataList(list);
setValueList(
list
.map(l =>
checkChildrenByCondition(
l,
it => (it.isChecked ? [getId(it)] : []),
'map',
).flat(Infinity),
)
.flat(Infinity)
.filter(Boolean),
);
setLoading(false); setLoading(false);
}) })
.catch(err => { .catch(err => {
...@@ -76,14 +99,16 @@ const ListCard = props => { ...@@ -76,14 +99,16 @@ const ListCard = props => {
<> <>
{dataList.some(d => d.type === 'widgetUIPage') && ( {dataList.some(d => d.type === 'widgetUIPage') && (
<ListCardItem <ListCardItem
{...{ item={{
type: 'widgetGroup', type: 'widgetGroup',
searchWord, searchWord,
children: dataList.filter(d => d.type === 'widgetUIPage'), children: dataList.filter(d => d.type === 'widgetUIPage'),
text: '地图组件', text: '地图组件',
itemid: '9999', itemid: '9999',
}} }}
getValueCallback={getValueCallback} ouid={ouid}
updateValueList={updateValueList}
valueList={valueList}
searchWord={searchWord} searchWord={searchWord}
/> />
)} )}
...@@ -93,10 +118,11 @@ const ListCard = props => { ...@@ -93,10 +118,11 @@ const ListCard = props => {
.filter(d => d.type === 'widgetGroup') .filter(d => d.type === 'widgetGroup')
.map((item, index) => ( .map((item, index) => (
<ListCardItem <ListCardItem
{...item} item={item}
itemid={index} ouid={ouid}
updateValueList={updateValueList}
valueList={valueList}
key={`item${index}key`} key={`item${index}key`}
getValueCallback={getValueCallback}
searchWord={searchWord} searchWord={searchWord}
{...props} {...props}
/> />
......
...@@ -160,13 +160,12 @@ const SiteManage = () => { ...@@ -160,13 +160,12 @@ const SiteManage = () => {
const valueCallback = valueObj => { const valueCallback = valueObj => {
setSubList(valueObj); setSubList(valueObj);
}; };
const handleCommit = value => { const handleCommit = rusults => {
console.log(value); console.log(rusults);
let arr = Object.values(subList);
setMenuToRole( setMenuToRole(
qs.stringify({ qs.stringify({
roleID, roleID,
menuNameList: String(arr.flat()), menuNameList: String(rusults.flat()),
}), }),
{ {
headers: { headers: {
...@@ -306,7 +305,6 @@ const SiteManage = () => { ...@@ -306,7 +305,6 @@ const SiteManage = () => {
ouid={roleID} ouid={roleID}
itemObj={itemObj} itemObj={itemObj}
searchWord={searchWord} searchWord={searchWord}
valueCallback={valueCallback}
onCommit={handleCommit} 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