/*
|
* @Author: dminyi 1301963064@qq.com
|
* @Date: 2024-08-29 17:41:09
|
* @LastEditors: lwh
|
* @LastEditTime: 2024-11-14 19:31:45
|
* @FilePath: \gzDyh\gz-customerSystem\src\components\SelectObjModal\selectPerson.jsx
|
* @Description: 选择经办人
|
*/
|
import React, { useState, useEffect, useMemo } from 'react';
|
import PropTypes from 'prop-types';
|
import { Button, Space, Input, Tree } from 'antd';
|
import { CloseOutlined } from '@ant-design/icons';
|
import './index.less';
|
import * as $$ from '../../utils/utility';
|
import { Modal, Spin } from '@arco-design/web-react';
|
|
const { Search } = Input;
|
|
const txtMap = {
|
supUnit: '组织',
|
dept: '部门',
|
dept_union: '部门',
|
person: '人',
|
unit: '组织'
|
}
|
|
// 获取人员,组织,部门数据
|
function getDataApi(type, searchData, caseId) {
|
let url
|
switch (type) {
|
case 'dept':
|
url = `ctUnit/unitChoose`
|
break;
|
case 'dept_union':
|
url = `ctUnit/unitChoose4Union`
|
break;
|
case 'person':
|
url = 'ctUser/userChoose'
|
break
|
case 'unit':
|
url = 'ctUser/unitList'
|
break
|
case 'supUnit':
|
url = `caseInfoUnfold/superviceUnitChoose?caseId=${caseId}`
|
break
|
default:
|
break;
|
}
|
return $$.ax.request({ url, type: 'get', data: searchData, service: type === 'supUnit' ? 'mediate' : 'cust' });
|
}
|
|
/**
|
* visible, // 传入参数控制modal显示
|
* checkKeys, // 选中,数据格式 [{value:'',label:''}]
|
* type, // 'person': 选择人员 'unit': 选择组织 'dept': 选择部门 'supUnit': 督办组织
|
* isCheckbox, // 是否多选
|
* searchData, // 搜索条件
|
* onClose, // 关闭
|
* onOk, // 点击确定的回调
|
*/
|
const SelectObjModal = ({ visible = false, checkKeys = [], type = 'dept', isCheckbox = false, searchData = {}, onClose, onOk, caseId }) => {
|
const nameStr = txtMap[type];
|
// 默认调解员查询'22_00024-4'
|
const searchRole = type === 'person' ? { roleCode: '22_00024-4' } : {};
|
const [data, setData] = useState([]);
|
const [checkedKeys, setCheckedKeys] = useState({ keys: [], items: [] });
|
const [expandedKeys, setExpandedKeys] = useState([]);
|
const [searchValue, setSearchValue] = useState('');
|
const [autoExpandParent, setAutoExpandParent] = useState(true);
|
const [dataList, setDataList] = useState([]);
|
const [loading, setLoading] = useState(false);
|
|
|
|
// tree复选框选择
|
function handleCheck(checkedKeys, e) {
|
if (!isCheckbox && checkedKeys.checked.length > 1) {
|
$$.info({ type: 'warning', content: '当前选择只可单选' });
|
return;
|
}
|
let checkedNodes = e.checkedNodes;
|
checkedNodes.forEach((x) => delete x.children);
|
setCheckedKeys({ keys: checkedKeys.checked, items: checkedNodes });
|
}
|
|
// 删除选项
|
function handleDelete(t) {
|
checkedKeys.keys.splice(t, 1);
|
checkedKeys.items.splice(t, 1);
|
setCheckedKeys({ ...checkedKeys });
|
}
|
|
const getParentKey = (key, tree) => {
|
let parentKey;
|
for (let i = 0; i < tree.length; i++) {
|
const node = tree[i];
|
if (node.children) {
|
if (node.children.some((item) => item.value === key)) {
|
parentKey = node.value;
|
} else if (getParentKey(key, node.children)) {
|
parentKey = getParentKey(key, node.children);
|
}
|
}
|
}
|
return parentKey;
|
};
|
|
function handleSearch(value, dataList) {
|
const newExpandedKeys = dataList
|
.map((item) => {
|
if (item.label.indexOf(value) > -1) {
|
return getParentKey(item.value, data);
|
}
|
return null;
|
}).filter((item, i, self) => item && self.indexOf(item) === i);
|
setExpandedKeys(newExpandedKeys);
|
setSearchValue(value);
|
setAutoExpandParent(true);
|
}
|
|
useEffect(() => {
|
if (!visible) return;
|
// 获取数据
|
async function getData() {
|
setLoading(true)
|
const res = await getDataApi(type, { ...searchRole, ...searchData }, caseId);
|
setLoading(false)
|
if (res.type) {
|
setData(res.data || []);
|
}
|
}
|
if (checkKeys.length !== 0) {
|
let keys = [];
|
checkKeys.forEach((x) => keys.push(x.value));
|
setCheckedKeys({ keys, items: checkKeys });
|
} else {
|
setCheckedKeys({ keys: [], items: [] });
|
}
|
getData();
|
}, [type, visible]);
|
|
// 搜索
|
useEffect(() => {
|
if (!visible) return;
|
const arr = [];
|
const generateList = (data) => {
|
for (let i = 0; i < data.length; i++) {
|
const node = data[i];
|
const { value, label } = node;
|
arr.push({ value, label });
|
if (node.children) {
|
generateList(node.children);
|
}
|
}
|
};
|
generateList(data);
|
setDataList(arr);
|
handleSearch('', arr);
|
}, [data]);
|
|
const treeData = useMemo(() => {
|
const loop = (data) => {
|
const copiedData = JSON.parse(JSON.stringify(data));
|
return copiedData.map((item, idx) => {
|
const strTitle = item.label;
|
const index = strTitle.indexOf(searchValue);
|
|
// 只保留包含 searchValue 的项
|
if (index <= -1 && !item.children) {
|
return null; // 返回 null 表示不包含在最终结果中
|
}
|
|
const beforeStr = strTitle.substring(0, index);
|
const afterStr = strTitle.slice(index + searchValue.length);
|
const label =
|
index > -1 ? (
|
<span>
|
{beforeStr}
|
<span className="selectObjModal-searchValue">{searchValue}</span>
|
{afterStr}
|
</span>
|
) : (
|
<span>{strTitle}</span>
|
);
|
|
if (item.children) {
|
const filteredChildren = loop(item.children).filter(Boolean); // 递归处理子项并过滤掉 null
|
return {
|
label,
|
name: strTitle,
|
value: item.value,
|
checkable: item.checkable,
|
children: filteredChildren.length > 0 ? filteredChildren : undefined,
|
};
|
}
|
|
return {
|
label,
|
name: strTitle,
|
checkable: item.checkable,
|
value: item.value,
|
};
|
}).filter(Boolean); // 过滤掉 null
|
};
|
|
return loop(data);
|
}, [searchValue, data]);
|
return (
|
<Modal
|
visible={!!visible}
|
title={`选择${nameStr}`}
|
footer={null}
|
onCancel={onClose}
|
unmountOnExit={true}
|
maskClosable={false}
|
style={{ width: '560px' }}
|
>
|
<div className="selectObjModal-main">
|
<div className="selectObjModal-left">
|
<div className="selectObjModal-left-search">
|
<Search placeholder={`查询${nameStr}名称`} onSearch={(e) => {
|
// handleSearch('', dataList)
|
if (!e) {
|
handleSearch('', dataList)
|
|
} else {
|
handleSearch(e, dataList)
|
}
|
}} />
|
</div>
|
<div className="selectObjModal-left-main">
|
<Spin loading={loading} style={{ width: '100%', height: '100%' }}>
|
{data.length > 0 ? (
|
<Tree
|
checkable
|
checkStrictly
|
defaultExpandAll
|
onExpand={(newExpandedKeys) => {
|
setExpandedKeys(newExpandedKeys);
|
setAutoExpandParent(false);
|
}}
|
expandedKeys={expandedKeys}
|
autoExpandParent={autoExpandParent}
|
selectable={false}
|
onCheck={(checkedKeys, e) => handleCheck(checkedKeys, e)}
|
checkedKeys={checkedKeys.keys}
|
treeData={treeData}
|
fieldNames={{ title: 'label', key: 'value' }}
|
height={400}
|
/>
|
) : (
|
$$.MyEmpty()
|
)}
|
</Spin>
|
</div>
|
</div>
|
<div className="selectObjModal-right">
|
{checkedKeys.items.map((x, t) => (
|
<div className="selectObjModal-right-item" key={x.value}>
|
<span className="selectObjModal-right-item-name">{x.label}</span>
|
<CloseOutlined onClick={() => handleDelete(t)} className="selectObjModal-right-item-icon" />
|
</div>
|
))}
|
{checkedKeys.items.length === 0 && <div className="selectObjModal-none">{$$.MyEmpty({ description: '尚未选择' + nameStr })}</div>}
|
</div>
|
</div>
|
<div className="selectObjModal-footer">
|
<div>已选中:{checkedKeys.keys.length}{txtMap[type]}</div>
|
<Space size="middle">
|
<Button onClick={onClose}>取消</Button>
|
<Button type="primary" onClick={() => onOk && onOk(checkedKeys)}>
|
确定
|
</Button>
|
</Space>
|
</div>
|
</Modal>
|
);
|
};
|
|
SelectObjModal.propTypes = {
|
visible: PropTypes.any,
|
checkKeys: PropTypes.array,
|
type: PropTypes.string,
|
isCheckbox: PropTypes.bool,
|
searchData: PropTypes.object,
|
onClose: PropTypes.func,
|
onOk: PropTypes.func,
|
};
|
|
export default SelectObjModal;
|