/* eslint-disable no-shadow */ /* eslint-disable array-callback-return */ /* eslint-disable consistent-return */ /* eslint-disable react/no-multi-comp */ /* eslint-disable eqeqeq */ import React, { useEffect, useState } from 'react'; import { // Tree, message, Input, notification, Tooltip, Card, Button, Spin, Empty, Pagination, Checkbox, } from 'antd'; import classnames from 'classnames'; import { PlusSquareOutlined, FormOutlined, DeleteOutlined, DoubleLeftOutlined, DoubleRightOutlined, PlusOutlined, ApartmentOutlined, CaretUpOutlined, CaretDownOutlined, } from '@ant-design/icons'; import PageContainer from '@/components/BasePageContainer'; import Tree from '@/components/ExpendableTree'; import voca from 'voca'; import zhCN from 'antd/es/locale/zh_CN'; import qs from 'qs'; import lodash, { clone } from 'lodash'; import styles from './SiteManage.less'; import { chooseUserToStation, getStationUserList, getSiteTree, getStationUsers, DragGroup, getGroupUserTree, } from '@/services/siteManage/api'; import AddModal from './AddModal'; import DelModal from './DelModal'; import EditModal from './EditModal'; import AddChildModal from './AddChildModal'; const { Search } = Input; const placeholder = '请输入查询条件'; const SiteManageV2 = () => { const [showSearchStyle, setShowSearchStyle] = useState(false); // 是否显示模糊查询样式 const [treeVisible, setTreeVisible] = useState(true); // 树是否可见 const [treeData, setTreeData] = useState([]); // 用户站点树 const [treeDataCopy, setTreeDataCopy] = useState([]); // 机构树数据备份,用于更改机构 const [treeState, setTreeState] = useState(true); // 树第一次加载 const [treeLoading, setTreeLoading] = useState(false); const [checkLoading, setCheckLoading] = useState(false); const [currentStation, setCurrentStation] = useState(''); // 当前选中站点 const [currentStationMsg, setCurrentStationMsg] = useState({}); // 当前编辑节点信息 const [dataList, setdataList] = useState([]); // 当前站点对应的分页用户列表 const [selectedState, setSelectedState] = useState(false); // 已选列表展开状态true为展开false为收起 const [visibleParams, setvisibleParams] = useState({ modalVisible: false, // 新增弹窗 delVisible: false, // 删除弹窗 editVisible: false, // 修改弹窗 spinLoading: false, // 加载弹窗 btnLoading: false, loading: false, checkBoxLoading: false, }); const [total, setTotal] = useState(0); // 分页总数 const [page, setPage] = useState({ pageNum: 1, pageSize: 10 }); const [selectList, setSelectList] = useState([]); // 已勾选列表数据 const [updatePageUser, setUpdatePageUser] = useState(1); // const [updateCheck, setUpdateCheck] = useState(1); const [name, setName] = useState(''); const [des, setDes] = useState(''); const [data, setData] = useState(''); const [ch, setCh] = useState(''); const [keepTree, setKeepTree] = useState([]); // 保存所有一级id用于控制只展开一项一级菜单 let a = []; // 渲染机构树 const mapTree = org => { const haveChildren = Array.isArray(org.children) && org.children.length > 0; return { title: ( <div className={styles.title}> <div className={styles.titleText}>{org.text}</div> <div className={styles.tip}> <Tooltip title="添加下级站点" className={styles.fs}> <PlusSquareOutlined style={{ fontSize: '16px', color: '#1890FF' }} onClick={e => addSite(e, org)} /> </Tooltip> <Tooltip title="编辑当前站点" className={styles.fs}> <FormOutlined style={{ fontSize: '16px', color: '#1890FF' }} onClick={e => editorSite(e, org)} /> </Tooltip> <Tooltip title="删除当前站点" className={styles.fs}> <DeleteOutlined style={{ fontSize: '16px', color: '#1890FF' }} onClick={e => delSite(e, org)} /> </Tooltip> </div> </div> ), key: org.id, // icon: <UserOutlined style={{ display: 'inline' }} />, // 判断它是否存在子集,若果存在就进行再次进行遍历操作,知道不存在子集便对其他的元素进行操作 children: haveChildren ? org.children.map(i => mapTree(i)) : [], }; }; // 添加下级站点 const addSite = (e, recode) => { e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); setCurrentStation(recode.id); handleShowModal('addChildVisible', true); }; // 删除当前站点 const delSite = (e, recode) => { e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); setCurrentStation(recode.id); handleShowModal('delVisible', true); }; // 编辑当前站点 const editorSite = (e, recode) => { e.stopPropagation(); e.nativeEvent.stopImmediatePropagation(); // 保存编辑回显信息 setCurrentStationMsg(recode); // setCurrentStation(recode.id); handleShowModal('editVisible', true); }; // 重新渲染树 const updateTrees = () => { setTreeLoading(true); getSiteTree({ selectNode: -1 }).then(res => { if (res.data.length > 0) { setTreeLoading(false); setTreeData(res.data); let aa = []; res.data.forEach(i => { aa.push(i.id); }); setKeepTree(aa); setTreeDataCopy(res.data); // 第一次加载,默认选择第一个组织 if (treeState) { onSelect([res.data[0].id], false); // 待会儿要改 setTreeState(false); } } else { setTreeLoading(false); notification.error({ message: '提示', duration: 15, description: res.msg, }); } }); }; // 获取用户机构树 // useEffect(() => { // updateTrees(); // }, [flag]); useEffect(() => { getValue(); updateTrees(); }, []); // 切换站点,点击分页按钮,提交 useEffect(() => { if (!currentStation) return; getList(); setShowSearchStyle(false); }, [updatePageUser]); // 切换站点,提交时触发已勾选列表更新 useEffect(() => { if (!currentStation) return; // getAllcheckList(); getAllCheckListNew(); }, [currentStation, updateCheck]); const getList = () => { let params = { PageIndex: +page.pageNum, PageSize: +page.pageSize, }; if (name) params = { ...params, key: name }; setCheckLoading(true); getGroupUserTree(params).then(res => { if (res.code === 0 && res.data) { setCheckLoading(false); setShowSearchStyle(true); let list = res.data.data; // 还原选择的数据 if (selectList.length > 0) { selectList.forEach(item => { list.forEach((value, index) => { if (item.groupId == value.groupId) { list[index].users.forEach((user, userIndex) => { if (user.userId === item.userId) { list[index].users[userIndex].isChecked = true; } }); let checkedLen = list[index].users.filter(v => v.isChecked).length; if (checkedLen === list[index].users.length) { list[index].isChecked = true; } } }); }); } handleShowModal('loading', false); setdataList(lodash.cloneDeep(list)); setTotal(res.data.count); } else { setCheckLoading(false); handleShowModal('loading', false); setdataList(lodash.cloneDeep([])); } }); }; // 搜索状态时获取当前站点可编辑用户(已勾选和未勾选)分页展示 const getSearchList = value => { let params = { PageIndex: 1, PageSize: 10, }; if (value) params = { ...params, key: value }; getGroupUserTree(params).then(res => { if (res.code === 0 && res.data) { setShowSearchStyle(true); let list = res.data.data; // 还原选择的数据 if (selectList.length > 0) { selectList.forEach(item => { list.forEach((value, index) => { if (item.groupId == value.groupId) { list[index].users.forEach((user, userIndex) => { if (user.userId === item.userId) { list[index].users[userIndex].isChecked = true; } }); let checkedLen = list[index].users.filter(v => v.isChecked).length; if (checkedLen === list[index].users.length) { list[index].isChecked = true; } } }); }); } handleShowModal('loading', false); setdataList(lodash.cloneDeep(list)); setTotal(res.data.count); } else { handleShowModal('loading', false); setdataList(lodash.cloneDeep([])); } }); setPage({ pageNum: 1, pageSize: 10 }); }; // 重置 const restButton = () => { let params = { PageIndex: 1, PageSize: 10, }; params = { ...params }; getGroupUserTree(params).then(res => { if (res.code === 0 && res.data) { setShowSearchStyle(true); let list = res.data.data; // 还原选择的数据 if (selectList.length > 0) { selectList.forEach(item => { list.forEach((value, index) => { if (item.groupId == value.groupId) { list[index].users.forEach((user, userIndex) => { if (user.userId === item.userId) { list[index].users[userIndex].isChecked = true; } }); let checkedLen = list[index].users.filter(v => v.isChecked).length; if (checkedLen === list[index].users.length) { list[index].isChecked = true; } } }); }); } handleShowModal('loading', false); setdataList(lodash.cloneDeep(list)); setTotal(res.data.count); } else { handleShowModal('loading', false); setdataList(lodash.cloneDeep([])); } }); setName(''); setPage({ pageNum: 1, pageSize: 10 }); }; const handleChange = e => { setName(e.target.value); }; // 获取当前站点所有已经勾选的用户新接口 const getAllCheckListNew = () => { getStationUsers({ stationId: currentStation, }).then(res => { let list = []; if (res.data.length > 0) { res.data.map((item, index) => { list.push({ groupId: +item.OUID, groupName: item.OUName, userName: item.userName, userId: item.userID, }); }); } setSelectList(lodash.cloneDeep(list)); setUpdatePageUser(updatePageUser + 1); }); }; // 选中某个站点 const onSelect = (props, e) => { setCh(props[0]); console.log(props[0], 'props[0]'); if (!props[0]) { setCurrentStation(currentStation); } else { setCurrentStation(props[0]); } setPage({ pageNum: 1, pageSize: 10 }); if (data) { data.map((item, index) => { if (item.id == props[0]) { setDes(item.describe); } }); } }; const getValue = () => { getSiteTree({ selectNode: -1 }).then(res => { getData1(res.data); }); }; const getData1 = e => { e.map((i, j) => { a.push(i); if (i.children.length > 0) { getData1(i.children); } }); setData(a); }; // 弹出模态框 const handleShowModal = (key, value) => { setvisibleParams({ ...visibleParams, [key]: value }); }; // 获取搜索框的值 const handleSearch = value => { // setName(value); getSearchList(value); }; const confirmModal = e => { handleShowModal('modalVisible', false); updateTrees(); // setFlag(flag + 1); }; const delModal = () => { handleShowModal('delVisible', false); updateTrees(); // setFlag(flag + 1); }; const editModal = () => { handleShowModal('editVisible', false); updateTrees(); // setFlag(flag + 1); }; const addChildModal = () => { handleShowModal('addChildVisible', false); updateTrees(); // setFlag(flag + 1); }; const handleChangeCollpase = (groupId, isShow) => { let index = dataList.findIndex(item => item.groupId === groupId); if (dataList[index].children && dataList[index].children.length > 0) { setdataList(lodash.cloneDeep(dataList)); return; } handleShowModal('loading', true); getStationUserList({ stationID: currentStation, groupId }).then(res => { if (res.code === 0 && res.data) { handleShowModal('loading', false); dataList[index].children = res.data; setdataList(lodash.cloneDeep(dataList)); } }); }; // 每组全选全不选 const handleChangeAll = (e, index) => { dataList[index].isChecked = e.target.checked; dataList[index].users.forEach(item => { item.isChecked = e.target.checked; let delIndex = selectList.findIndex( v => v.groupId == dataList[index].groupId && v.userId == item.userId, ); if (e.target.checked) { if (delIndex === -1) { selectList.push({ groupId: dataList[index].groupId, groupName: dataList[index].groupName, userName: item.userName, userId: item.userId, }); } } if (!e.target.checked) { selectList.splice(delIndex, 1); } }); setSelectList(lodash.cloneDeep(selectList)); setdataList(lodash.cloneDeep(dataList)); }; // 单个选择checkbox const handleChangeSignel = (e, index, vIndex) => { dataList[index].users[vIndex].isChecked = e.target.checked; let checked = isAllChecked(index); let hasIndex = selectList.findIndex( item => item.userId == dataList[index].users[vIndex].userId && item.groupId == dataList[index].groupId, ); dataList[index].isChecked = checked; if (e.target.checked && hasIndex === -1) { selectList.push({ groupId: dataList[index].groupId, groupName: dataList[index].groupName, userName: dataList[index].users[vIndex].userName, userId: dataList[index].users[vIndex].userId, }); } else { selectList.splice(hasIndex, 1); } setSelectList(lodash.cloneDeep(selectList)); setdataList(lodash.cloneDeep(dataList)); }; const isAllChecked = index => dataList[index].users.filter(item => item.isChecked).length === dataList[index].users.length; // 删除已选列表 const handleDel = index => { let { groupId, userId } = selectList[index]; let outerIndex = dataList.findIndex(item => item.groupId == groupId); if (outerIndex > -1) { let innerIndex = dataList[outerIndex].users.findIndex(item => item.userId == userId); dataList[outerIndex].users[innerIndex].isChecked = false; dataList[outerIndex].isChecked = isAllChecked(outerIndex); } selectList.splice(index, 1); setSelectList(lodash.cloneDeep(selectList)); setdataList(lodash.cloneDeep(dataList)); }; // 提交 const handleCommitBtn = () => { handleShowModal('btnLoading', true); let result = []; let obj = {}; selectList.forEach(item => { if (obj[item.groupId]) { obj[item.groupId].push(item.userId); } else { obj[item.groupId] = [item.userId]; } }); // dataList.forEach(item => { // if (obj[item.GroupId] && item.Users.length === obj[item.GroupId].length) { // obj[item.GroupId].push(item.GroupId); // } // }); result = Object.values(obj); // 数据处理成后台需要的格式 if (result.length === 0) return notification.warning({ message: '提示', description: '请至少选择选择一个用户!', }); chooseUserToStation({ userList: String(result.flat()), stationID: currentStation, }) .then(res => { handleShowModal('btnLoading', false); if (res.code === 0) { setSelectList([]); setUpdateCheck(updateCheck + 1); notification.success({ message: '提示', duration: 3, description: '设置成功', }); } else { notification.error({ message: '提示', duration: 15, description: res.msg, }); } }) .catch(err => { handleShowModal('btnLoading', false); }); }; // 分页 const handleChangePage = (pageNum, pageSize) => { setPage({ pageNum, pageSize }); setUpdatePageUser(updatePageUser + 1); }; /** ***操作按钮**** */ // 机构操作 const addTopStation = () => { handleShowModal('modalVisible', true); }; // 模糊查询匹配的样式 const searchStyle = val => { let n; if (showSearchStyle) { n = val.replace(new RegExp(name, 'g'), `<span style='color:red'>${name}</span>`); } else { n = val; } return <div dangerouslySetInnerHTML={{ __html: n }} />; }; // 返回拖拽完毕后的信息 const loop = (datas, key, parentID, callback) => { for (let i = 0; i < datas.length; i++) { if (datas[i].id === key) { return callback(datas[i], i, datas, parentID); } if (datas[i].children) { loop(datas[i].children, key, datas[i].id, callback); } } }; // 树的拖拽 const handleDrop = infos => { const dropKey = infos.node.key; const dragKey = infos.dragNode.key; const dropPos = infos.node.pos.split('-'); const dropPosition = infos.dropPosition - Number(dropPos[dropPos.length - 1]); const datas = JSON.parse(JSON.stringify(treeData)); // 找到拖拽的元素 let dragObj; let dropObj; let parId; let dragList; // 保存拖拽到的节点信息 loop(datas, dropKey, -1, item => { dropObj = item; }); // 保存节点信息并删除节点 loop(datas, dragKey, -1, (item, index, arr) => { arr.splice(index, 1); dragObj = item; }); // 将节点插入到正确的位置 if (!infos.dropToGap) { dropObj.children = dropObj.children || []; // 在哪里插入,示例添加到头部,可以是随意位置 dropObj.children.unshift(dragObj); parId = dropObj.id; dragList = dropObj.children.map(val => val.id); } else { let ar; let i; loop(datas, dropKey, -1, (item, index, arr, parentID) => { ar = arr; i = index; parId = parentID; }); if (dropPosition === -1) { ar.splice(i, 0, dragObj); } else { ar.splice(i + 1, 0, dragObj); } dragList = ar.map(ele => ele.id); } DragGroup({ dragGroupType: 3, groupId: dragKey.toString(), groupList: dragList.map(item => item.toString()), parentId: parId.toString(), }).then(res => { if (res.code === 0) { updateTrees(); } else { message.error(res.msg); } }); }; const Panels = React.memo(props => { let { index, groupId, groupName, users, isChecked, isShow, color } = props; return ( <div className={styles.sitePanel} key={groupId} id={`siteId${groupId}`}> {/* onClick={() => props.handleChangeCollpase(GroupId, isShow)} */} <div className={styles.sitePanelHead}> {/* {isShow ? ( <UpOutlined className={styles.siteIcon} /> ) : ( <DownOutlined className={styles.siteIcon} /> )} */} {/* <UpOutlined className={styles.siteIcon} /> */} <ApartmentOutlined className={styles.siteIcon} /> {searchStyle(groupName)} <Checkbox key="0" className={styles.siteListTitle} checked={isChecked} onClick={e => props.handleChangeAll(e, index)} > 全选 </Checkbox> </div> <div className={styles.sitePanelCon}> {users.length > 0 && users.map((v, vIndex) => ( <CheckBoxRow {...v} index={index} vIndex={vIndex} key={v.userId} handleChangeSignel={props.handleChangeSignel} /> ))} </div> </div> ); }); return ( <PageContainer className={styles.siteManageContainer}> <div className={styles.contentContainer}> <Spin spinning={treeLoading} tip="loading..."> <Card className={classnames({ [styles.orgContainer]: true, [styles.orgContainerHide]: !treeVisible, })} > <span style={{ margin: '0 190px 0 10px' }}>站点列表</span> <Tooltip title="添加顶级站点"> <PlusOutlined onClick={() => addTopStation()} style={{ color: '#1890FF', fontSize: '18px', verticalAlign: '0.04em', }} /> </Tooltip> {treeData.length > 0 && ( <div style={{ height: '100%', overflowY: 'scroll' }}> <Tree showIcon="true" showLine={{ showLeafIcon: false }} blockNode autoExpandParent selectedKeys={[currentStation]} onSelect={onSelect} treeData={treeData.map(t => mapTree(t))} expandedKeys={treeData[0].id} draggable onDrop={handleDrop} keepTree={keepTree} /> </div> )} <div className={styles.switcher}> {treeVisible && ( <Tooltip title="隐藏站点列表"> <DoubleLeftOutlined onClick={() => setTreeVisible(false)} /> </Tooltip> )} {!treeVisible && ( <Tooltip title="显示站点列表"> <DoubleRightOutlined onClick={() => setTreeVisible(true)} /> </Tooltip> )} </div> </Card> </Spin> {/* 右侧用户表 */} <div className={classnames({ [styles.userContainer]: true, [styles.userContainerHide]: !treeVisible, })} > <AddModal visible={visibleParams.modalVisible} onCancel={() => handleShowModal('modalVisible', false)} confirmModal={confirmModal} /> <AddChildModal visible={visibleParams.addChildVisible} pid={currentStation} onCancel={() => handleShowModal('addChildVisible', false)} confirmModal={addChildModal} /> <DelModal visible={visibleParams.delVisible} stationId={currentStation} onCancel={() => handleShowModal('delVisible', false)} confirmModal={delModal} /> <EditModal visible={visibleParams.editVisible} stationObj={currentStationMsg} des={des} onCancel={() => handleShowModal('editVisible', false)} confirmModal={editModal} /> <div className={classnames({ [styles.boxR]: true, [styles.boxH]: treeVisible, })} > <Card className={classnames({ [styles.cardBoxTop]: true, [styles.boxH]: treeVisible, })} > <Search style={{ width: 260 }} allowClear placeholder={placeholder} onSearch={handleSearch} value={name} onChange={e => handleChange(e)} enterButton /> <Button onClick={restButton}>重置</Button> </Card> <div style={{ background: '#fff', height: 'calc(100% - 64px)', paddingBottom: '10px' }}> <Spin spinning={checkLoading} tip="loading..."> <Card className={classnames({ [styles.boxH]: treeVisible, [styles.cardBoxR]: true, })} > <div style={{ display: 'flex', flexDirection: 'column ', height: '100%', }} > {/* <Checkbox className={styles.siteAll}>全选/反选</Checkbox> */} {dataList.length > 0 && !visibleParams.loading ? ( <> <p className={styles.siteline}>已选择列表:</p> <div className={styles.siteSelectList} style={{ height: selectedState ? '1200px' : '220px', transition: 'height 0.5s', }} > <ul className={styles.siteSelectUl}> {selectList.map((item, index) => ( <li key={`${item.userName}${item.groupId}${index}`} onClick={() => handleDel(index)} > {`${item.userName}(${item.groupName})`} </li> ))} </ul> </div> <div style={{ textAlign: 'center', margin: '10px 0' }}> <Tooltip title="收起"> <CaretUpOutlined style={{ fontSize: '20px', color: '#178BF6', display: selectedState ? 'block' : 'none', }} onClick={() => setSelectedState(false)} /> </Tooltip> <Tooltip title="展开"> <CaretDownOutlined style={{ fontSize: '20px', color: '#178BF6', display: selectedState ? 'none' : 'block', }} onClick={() => setSelectedState(true)} /> </Tooltip> </div> <div className={styles.siteBtn}> <Button type="primary" className={styles.siteCommit} onClick={handleCommitBtn} > 提交 </Button> </div> </> ) : ( <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} /> )} <div style={{ overflowY: 'scroll', flexGrow: '1', }} > {dataList.map((item, index) => ( <Panels {...item} index={index} key={item.groupId} handleChangeCollpase={handleChangeCollpase} handleChangeAll={handleChangeAll} handleChangeSignel={handleChangeSignel} /> ))} </div> </div> </Card> </Spin> {dataList.length > 0 && !visibleParams.loading ? ( <div style={{ textAlign: 'right', marginTop: '25px' }}> <Pagination size="small" total={total} current={page.pageNum} defaultPageSize="10" onChange={handleChangePage} pageSizeOptions={['10']} /> </div> ) : ( '' )} </div> </div> </div> </div> </PageContainer> ); }; const CheckBoxRow = React.memo(props => { let { vIndex, index, isChecked, userName } = props; return ( <Checkbox className={styles.siteList} checked={isChecked} onClick={e => props.handleChangeSignel(e, index, vIndex)} > {userName} </Checkbox> ); }); export default SiteManageV2;