Files
fe_supplier_frontend/src/components/EvaluateTaskPersonnelSelector/EvaluateTaskPersonnelSelector.tsx
2025-06-24 18:58:43 +08:00

186 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { Table, Input, Button, Space, message } from 'antd';
import { SearchOutlined } from '@ant-design/icons';
import { getUserList } from '@/servers/api/user';
import './EvaluateTaskPersonnelSelector.less';
const { Search } = Input;
/**
* 评价任务人员选择组件属性接口
* @interface EvaluateTaskPersonnelSelectorProps
* @property {Function} onSelect - 选择确认后的回调函数,返回所选人员数组
* @property {API.PersonnelItem[]} selectedPersonnel - 已选择的人员列表
*/
interface EvaluateTaskPersonnelSelectorProps {
onSelect: (personnel: API.PersonnelItem[]) => void; // 选择确认后的回调函数
selectedPersonnel?: API.PersonnelItem[]; // 已选择的人员列表(用于回显)
}
/**
* 评价任务人员选择组件
* 用于在评价任务管理中选择评价人员,显示为简单表格
*
* @component
* @example
* ```jsx
* <EvaluateTaskPersonnelSelector
* onSelect={(selected) => console.log('已选择人员:', selected)}
* selectedPersonnel={[]}
* />
* ```
*/
const EvaluateTaskPersonnelSelector: React.FC<EvaluateTaskPersonnelSelectorProps> = ({
onSelect,
selectedPersonnel = []
}) => {
// 搜索关键词
const [keyword, setKeyword] = useState<string>('');
// 所有可选人员列表
const [personnel, setPersonnel] = useState<API.PersonnelItem[]>([]);
// 已选择人员ID列表
const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
// 加载状态
const [loading, setLoading] = useState<boolean>(false);
// 初始化时根据传入的selectedPersonnel设置选中状态
useEffect(() => {
// 直接使用传入的selectedPersonnel更新选中状态
// 如果为空数组,则清空选择
const newSelectedIds = selectedPersonnel?.map(item => item.id) || [];
setSelectedKeys(newSelectedIds);
}, [selectedPersonnel]); // 依赖selectedPersonnel而不是selectedPersonnelIds
/**
* 从API获取用户列表数据
*/
const fetchPersonnelData = useCallback(async () => {
setLoading(true);
try {
const params: API.UserListRequest = {
basePageRequest: {
pageNo: 1,
pageSize: 100, // 获取足够多的数据
},
keyword: keyword || undefined,
};
const response = await getUserList(params);
if (response && response.code === 200 && response.data) {
const users = response.data as API.UserItem[];
// 转换API返回的用户数据为组件所需格式
const personnelData: API.PersonnelItem[] = users.map((user) => ({
id: user.userId, // 用户ID
name: user.userName, // 用户名称
department: user.userDept, // 用户部门
position: '', // API中没有提供职位信息
}));
setPersonnel(personnelData);
} else {
message.error(response?.message || '获取用户列表失败');
}
} catch (error) {
console.error('获取人员数据失败:', error);
message.error('获取人员数据失败,请稍后重试');
} finally {
setLoading(false);
}
}, [keyword]); // 移除selectedPersonnelIds依赖
/**
* 初始化人员数据
*/
useEffect(() => {
// 加载人员数据API请求
fetchPersonnelData();
}, [fetchPersonnelData]);
/**
* 处理搜索
* @param {string} value - 搜索关键词
*/
const handleSearch = (value: string) => {
setKeyword(value);
};
/**
* 处理行选择变化
* @param {string[]} selectedRowKeys - 选中的行keys
* @param {API.PersonnelItem[]} selectedRows - 选中的行数据
*/
const handleSelectChange = (selectedRowKeys: React.Key[], selectedRows: API.PersonnelItem[]) => {
setSelectedKeys(selectedRowKeys as string[]);
};
/**
* 处理确认选择
*/
const handleConfirm = () => {
// 根据选中的ID筛选出完整的人员数据
const selectedData = personnel.filter(item => selectedKeys.includes(item.id));
// 回调传递给父组件
onSelect(selectedData);
};
// 表格列定义
const columns = [
{
title: '姓名', // 列标题
dataIndex: 'name', // 数据字段名
key: 'name', // 列唯一标识
},
{
title: '部门',
dataIndex: 'department',
key: 'department',
},
];
return (
<div className="evaluate-task-personnel-selector">
<div className="selector-header">
<div className="search-bar">
<Search
placeholder="请输入姓名搜索"
onSearch={handleSearch}
enterButton={<Button icon={<SearchOutlined />}></Button>}
/>
</div>
<div className="selected-count">
: <span className="count">{selectedKeys.length}</span>
</div>
</div>
<Table
rowSelection={{
selectedRowKeys: selectedKeys,
onChange: handleSelectChange,
}}
columns={columns}
dataSource={personnel}
rowKey="id"
size="small"
loading={loading}
pagination={{ pageSize: 10 }}
/>
<div className="selector-footer">
<Space>
<Button onClick={() => setSelectedKeys([])}></Button>
<Button type="primary" onClick={handleConfirm}>
</Button>
</Space>
</div>
</div>
);
};
export default EvaluateTaskPersonnelSelector;