import React, { useState, useEffect } from 'react'; import { Input, Select, Row, Col, Table, Button, Form, Tooltip, message } from 'antd'; import { RightOutlined, LeftOutlined } from '@ant-design/icons'; import { getSupplierPage } from '@/servers/api/supplier'; import './SupplierSelector.less'; const { Option } = Select; /** * SupplierSelector 组件的属性接口 * @interface SupplierSelectorProps * @property {Function} [onSelect] - 当选择供应商发生变化时的回调函数 * @property {any[]} [selectedSuppliers] - 初始已选择的供应商列表 * @property {string[]} [deptList] - 部门列表,用于筛选供应商 * @property {boolean} [showDeptFilter] - 是否显示部门筛选,默认显示 * @property {boolean} [showCompanyFilter] - 是否显示公司名称筛选,默认不显示 */ interface SupplierSelectorProps { onSelect?: (selected: any[]) => void; selectedSuppliers?: any[]; deptList?: string[]; showDeptFilter?: boolean; showCompanyFilter?: boolean; } /** * 供应商数据项接口,对应后端SupplierPageVo * @interface SupplierItem * @property {string} id - 供应商ID * @property {string} name - 供应商名称 * @property {string} [deptId] - 部门ID * @property {string} [deptName] - 部门名称 * @property {string} [companyName] - 公司名称 * @property {string} [categoryName] - 所属品类 * @property {string} [levelName] - 最新评价等级 * @property {Date} [admissionTime] - 准入时间 * @property {Date} [evaluationTime] - 最新评价时间 * @property {any} [key: string] - 其他属性 */ interface SupplierItem { id: string; name: string; deptId?: string; deptName?: string; companyName?: string; categoryName?: string; levelName?: string; admissionTime?: Date; evaluationTime?: Date; [key: string]: any; } /** * 供应商选择器组件 * 用于从系统中选择供应商数据,支持搜索过滤、分页加载、双列表展示 * * @param {SupplierSelectorProps} props - 组件属性 * @returns {React.ReactElement} 供应商选择器组件 */ const SupplierSelector: React.FC = ({ onSelect, selectedSuppliers: initialSelectedSuppliers = [], deptList = [], showDeptFilter = true, showCompanyFilter = false }) => { // 表单实例,用于管理查询条件 const [form] = Form.useForm(); // 待选供应商数据列表 const [tableListData, setTableListData] = useState([]); // 分页信息 const [pagination, setPagination] = useState({ current: 1, pageSize: 10, total: 0 }); // 加载状态 const [loading, setLoading] = useState(false); // 左侧待选列表中已选中的项的ID const [leftSelected, setLeftSelected] = useState([]); // 右侧已选列表中选中的项的ID const [rightSelected, setRightSelected] = useState([]); // 最终已选择的供应商列表 const [chosenSuppliers, setChosenSuppliers] = useState(initialSelectedSuppliers); /** * 监听初始已选供应商变化,更新内部状态 */ useEffect(() => { setChosenSuppliers(initialSelectedSuppliers); }, [initialSelectedSuppliers]); /** * 合并供应商列表并去重 * @param {SupplierItem[]} suppliers - 原有的供应商列表 * @param {SupplierItem[]} selected - 新选择的供应商列表 * @returns {SupplierItem[]} 合并后的供应商列表,去除重复项 */ const filteredData = (suppliers: SupplierItem[], selected: SupplierItem[]) => { // 创建已有供应商ID的集合,用于快速查找 const ids = new Set(suppliers.map((item: SupplierItem) => item.id)); // 过滤出未在原列表中出现的供应商 const newSelected = selected.filter((item: SupplierItem) => !ids.has(item.id)); // 合并列表 return [...suppliers, ...newSelected]; }; /** * 将左侧选中的供应商移动到右侧已选列表 */ const moveToRight = () => { // 获取左侧选中的供应商数据 const selected = tableListData.filter((item: SupplierItem) => leftSelected.includes(item.id)); // 合并到已选列表并去重 const chosenSuppliersNew = filteredData(chosenSuppliers, selected); // 更新已选列表 setChosenSuppliers(chosenSuppliersNew); // 清空左侧选择状态 setLeftSelected([]); // 触发外部回调 onSelect?.(chosenSuppliersNew); }; /** * 将右侧选中的供应商从已选列表中移除 */ const moveToLeft = () => { // 过滤掉右侧选中的供应商 const remaining = chosenSuppliers.filter((item: SupplierItem) => !rightSelected.includes(item.id)); // 更新已选列表 setChosenSuppliers(remaining); // 清空右侧选择状态 setRightSelected([]); // 触发外部回调 onSelect?.(remaining); }; /** * 获取供应商列表数据 * @param {any} values - 查询条件 * @param {number} pageNo - 页码 * @param {number} pageSize - 每页数量 */ const getTableList = async (values: any = {}, pageNo: number = 1, pageSize: number = 10) => { setLoading(true); try { // 整理查询参数 const params = { ...values, pageNo, pageSize, deptList: deptList.length > 0 ? deptList : undefined }; // 调用API获取供应商列表 const response = await getSupplierPage(params); if (response && response.code === 200) { // 请求成功,更新数据和分页信息 setTableListData(response.data.records || []); setPagination({ current: pageNo, pageSize, total: response.data.total || 0 }); } else { // 请求失败,显示错误信息 message.error(response?.message || '获取供应商列表失败'); // 使用mock数据作为备用 setTableListData([ { id: '1', name: '供应商A', deptName: '采购部', companyName: '公司A', categoryName: '润滑油' }, { id: '2', name: '供应商B', deptName: '技术部', companyName: '公司B', categoryName: '燃油' }, { id: '3', name: '供应商C', deptName: '质量部', companyName: '公司C', categoryName: '备件' }, { id: '4', name: '供应商D', deptName: '采购部', companyName: '公司D', categoryName: '计算机' }, { id: '5', name: '供应商E', deptName: '技术部', companyName: '公司E', categoryName: '通信设备' }, ]); setPagination({ current: 1, pageSize: 10, total: 5 }); } } catch (error) { // 处理异常情况 console.error('获取供应商列表出错:', error); message.error('获取供应商列表失败,请稍后重试'); // 使用mock数据作为备用 setTableListData([ { id: '1', name: '供应商A', deptName: '采购部', companyName: '公司A', categoryName: '润滑油' }, { id: '2', name: '供应商B', deptName: '技术部', companyName: '公司B', categoryName: '燃油' }, { id: '3', name: '供应商C', deptName: '质量部', companyName: '公司C', categoryName: '备件' }, { id: '4', name: '供应商D', deptName: '采购部', companyName: '公司D', categoryName: '计算机' }, { id: '5', name: '供应商E', deptName: '技术部', companyName: '公司E', categoryName: '通信设备' }, ]); setPagination({ current: 1, pageSize: 10, total: 5 }); } finally { setLoading(false); } }; /** * 组件初始化时加载数据 */ useEffect(() => { const values = form.getFieldsValue(); getTableList(values, 1, 10); }, [deptList]); /** * 处理查询表单提交 * @param {any} values - 表单值 */ const handleSearch = (values: any) => { getTableList(values, 1, pagination.pageSize); }; /** * 重置查询表单并重新加载数据 */ const handleReset = () => { form.resetFields(); const values = form.getFieldsValue(); getTableList(values, 1, pagination.pageSize); }; /** * 处理表格分页变化 * @param {any} paginationInfo - 分页信息 */ const handleTableChange = (paginationInfo: any) => { const values = form.getFieldsValue(); getTableList(values, paginationInfo.current, paginationInfo.pageSize); }; // 表格列定义 const columns = [ { title: '供应商名称', dataIndex: 'name', ellipsis: true, render: (name: string) => ( {name} ), }, { title: '所属品类', dataIndex: 'categoryName', ellipsis: true, render: (categoryName: string) => ( {categoryName || '-'} ), } ]; // 如果显示部门筛选,添加部门列 if (showDeptFilter) { columns.push({ title: '部门', dataIndex: 'deptName', ellipsis: true, render: (deptName: string) => ( {deptName || '-'} ) }); } // 如果显示公司名称筛选,添加公司名称列 if (showCompanyFilter) { columns.push({ title: '公司名称', dataIndex: 'companyName', ellipsis: true, render: (companyName: string) => ( {companyName || '-'} ), }); } return (
{/* 查询表单 */}
{showDeptFilter && ( )} {showCompanyFilter && ( )}
{/* 供应商选择区域 */} {/* 左侧待选列表 */}
待选供应商 {pagination.total}项
{/* 中间操作按钮 */}
已选供应商 {chosenSuppliers.length}项
); }; export default SupplierSelector;