Files
fe_supplier_frontend/src/pages/supplierAnnualManage/supplierAnnualTaskManage/components/EvaluatorSelectStep.tsx

466 lines
15 KiB
TypeScript
Raw Normal View History

2025-06-27 19:55:19 +08:00
import React, { useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react';
import { Card, Button, Space, Form } from 'antd';
import styles from '../supplierAnnualTaskManageAdd.less';
import {
SupplierTable,
BatchEvaluatorModal,
SupplierEvaluatorModal,
WeightSettingModal,
} from './EvaluatorComponents';
import { ModalMode } from '@/servers/types/evaluator';
import type { PersonnelItem, SupplierItem } from '@/servers/types/evaluator';
import type { DeptWeightItem } from '@/servers/dao/supplierEvaluateTask';
import type { Dispatch } from 'umi';
import { connect } from 'umi';
import type { SupplierTaskModelState } from '@/models/supplierAnnualTaskManage';
/**
* Props接口
* supplierAnnualTaskManage: Dva model
* dispatch: Dva dispatch action
* innerRef: 内部 ref
*/
interface EvaluatorSelectStepProps {
supplierAnnualTaskManage: SupplierTaskModelState;
dispatch: Dispatch;
innerRef?: any; // 使用 innerRef 作为属性名
}
/**
*
*
*
* 1. model.taskFormData
* 2.
* 3. dispatch model
*/
const EvaluatorSelectStepComponent = (props: EvaluatorSelectStepProps) => {
const { supplierAnnualTaskManage, dispatch, innerRef } = props;
// 从 model 获取表单数据,避免通过 props 层层传递
const { taskFormData, mode } = supplierAnnualTaskManage;
// 选中的供应商行的key列表用于批量操作
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
// 供应商列表数据包含评价人员信息从Dva model获取初始数据维护在本地状态
const [suppliers, setSuppliers] = useState<SupplierItem[]>([]);
// 批量选择模态框的可见性控制
const [batchSelectModalVisible, setBatchSelectModalVisible] = useState(false);
// 权重设置模态框的可见性控制
const [weightSettingModalVisible, setWeightSettingModalVisible] = useState(false);
// 评价人员选择/查看模态框的可见性控制
const [evaluatorModalVisible, setEvaluatorModalVisible] = useState(false);
// 当前操作的供应商对象,用于评价人员的选择和查看
const [currentSupplier, setCurrentSupplier] = useState<SupplierItem | null>(null);
// 模态框模式SELECT(选择模式) 或 VIEW(查看模式)
const [modalMode, setModalMode] = useState<ModalMode>(ModalMode.SELECT);
// 权重单位列表,根据评价人员部门动态生成
const [taskDeptWeightList, setTaskDeptWeightList] = useState<DeptWeightItem[]>([]);
// 表单实例,用于权重设置
const [form] = Form.useForm();
const [filterUserIds, setFilterUserIds] = useState<string[]>([]);
useEffect(() => {
if (mode === 'division' && taskFormData.userList && taskFormData.userList.length > 0) {
const filterUserIdsaa = taskFormData.userList
.map((user: PersonnelItem) => (user.isSelected === true ? user.id : null))
.filter((id: string | null) => id !== null);
setFilterUserIds(filterUserIdsaa);
}
}, [mode, taskFormData.userList]);
/**
*
*
*/
useImperativeHandle(innerRef, () => ({
validateFields: () => {
// 自定义验证逻辑
if (suppliers.length === 0) {
return Promise.reject('请至少添加一个供应商');
}
// 检查是否每个供应商都有评价人员
const hasNoEvaluator = suppliers.some(
(supplier) => !supplier.evaluators || supplier.evaluators.length === 0,
);
if (hasNoEvaluator) {
return Promise.reject('存在未分配评价人员的供应商');
}
return Promise.resolve();
}
}));
/**
*
* 使 useEffect taskFormData model
*/
useEffect(() => {
// 从Dva model中获取上一步选择的供应商数据
if (taskFormData.selectedSuppliers && taskFormData.selectedSuppliers.length > 0) {
// 转换上一步的供应商数据,添加评价人员数量字段
const suppliersWithEvaluators = taskFormData.selectedSuppliers.map(
(supplier) => {
// 确保evaluators字段存在且为数组
const evaluators = supplier.evaluators || [];
return {
...supplier,
userDept: supplier.userDept || '采购部', // 设置默认部门
evaluatorCount: evaluators.length,
evaluators: evaluators,
};
},
);
// 更新本地供应商状态
setSuppliers(suppliersWithEvaluators);
} else {
// 没有选择供应商,清空供应商列表
setSuppliers([]);
}
}, [taskFormData]); // 依赖于 taskFormData当 model 数据变化时重新计算
/**
*
*
*/
useEffect(() => {
// 从所有供应商的评价人员中提取部门信息
const allDepartments: PersonnelItem[] = [];
suppliers.forEach((supplier) => {
if (supplier.evaluators && supplier.evaluators.length > 0) {
supplier.evaluators.forEach((evaluator) => {
if (evaluator.userDept) {
allDepartments.push(evaluator);
}
});
}
});
// 去重部门列表 - 根据部门ID去重
const departmentMap = new Map<string, PersonnelItem>();
allDepartments.forEach((dept) => {
if (dept.userDeptId && !departmentMap.has(dept.userDeptId)) {
departmentMap.set(dept.userDeptId, dept);
}
});
const uniqueDepartments = Array.from(departmentMap.values());
// 如果有部门数据,生成权重单位列表
if (uniqueDepartments.length > 0) {
const newTaskDeptWeightList: DeptWeightItem[] = uniqueDepartments.map((dept) => ({
weightDept: dept.userDeptId || '',
weightValue: '0', // 默认权重为0
weightDeptName: dept.userDept || '',
}));
// 更新权重单位列表,保留原有权重值
setTaskDeptWeightList((prevList) => {
const prevValuesMap = new Map(prevList.map((item) => [item.weightDept, item.weightValue]));
return newTaskDeptWeightList.map((item) => ({
...item,
weightValue: prevValuesMap.get(item.weightDept) || '0', // 如果有原来的权重值则保留
}));
});
}
}, [suppliers]); // 依赖于suppliers当选择的供应商或其评价人员变化时重新计算
/**
*
* Dva model
* @param updatedData
*/
const updateFormData = (updatedData: any) => {
// 结构 更新数据中的suppliersWithEvaluators
const { suppliersWithEvaluators }: { suppliersWithEvaluators: SupplierItem[] } = updatedData;
// 构建供应商ID列表
const supplierIds = suppliersWithEvaluators.map((supplier) => ({
id: supplier.id,
userIds: supplier.evaluators?.map((e: PersonnelItem) => e.id) || [],
}));
// 构建userList 并去重,确保保留 isSelected 为 true 的对象
const userMap = new Map();
suppliersWithEvaluators
.flatMap((s) => s.evaluators || [])
.forEach((user) => {
// 如果已存在此ID的用户且当前用户isSelected为true或者Map中不存在此用户则更新/添加
if (!userMap.has(user.id) || user.isSelected) {
userMap.set(user.id, user);
}
});
// 通过dispatch更新model中的数据
// 这是组件与Dva model交互的关键
dispatch({
type: 'supplierAnnualTaskManage/updateFormData', // action类型
payload: {
// action数据
...updatedData,
supplierIds,
selectedSuppliers: suppliersWithEvaluators,
},
});
};
/**
*
*
*/
const handleBatchSelect = () => {
if (selectedRowKeys.length === 0) return;
setBatchSelectModalVisible(true);
};
/**
*
*
*/
const handleWeightSetting = () => {
// 将权重数据转换为表单初始值
form.setFieldsValue({
taskDeptWeightList: taskDeptWeightList.reduce((acc, item) => {
acc[item.weightDept] = parseInt(item.weightValue, 10) || 0;
return acc;
}, {} as Record<string, number>),
});
setWeightSettingModalVisible(true);
};
/**
*
* Dva model
*/
const handleSaveWeights = () => {
form.validateFields().then((values) => {
// 将表单值转换回权重列表格式
const updatedTaskDeptWeightList = taskDeptWeightList.map((item) => ({
...item,
weightValue: values.taskDeptWeightList[item.weightDept].toString(),
}));
// 更新本地状态
setTaskDeptWeightList(updatedTaskDeptWeightList);
// 同步到Dva model
updateFormData({
suppliersWithEvaluators: suppliers,
taskDeptWeightList: updatedTaskDeptWeightList,
});
setWeightSettingModalVisible(false);
});
};
/**
*
*
* @param supplier
*/
const handleSelectEvaluators = (supplier: SupplierItem) => {
setCurrentSupplier(supplier);
setModalMode(ModalMode.SELECT);
setEvaluatorModalVisible(true);
};
/**
*
*
* @param supplier
*/
const handleViewEvaluators = (supplier: SupplierItem) => {
// 查找完整的供应商数据包括evaluators
const fullSupplier = suppliers.find((s) => s.id === supplier.id);
if (fullSupplier) {
setCurrentSupplier(fullSupplier);
} else {
setCurrentSupplier(supplier);
}
setModalMode(ModalMode.VIEW);
setEvaluatorModalVisible(true);
};
/**
*
* Dva model
* @param selectedEvaluators
*/
const handleEvaluatorSelect = (selectedEvaluators: PersonnelItem[]) => {
if (!currentSupplier) return;
// 更新当前供应商的评价人员列表
const updatedSuppliers = suppliers.map((supplier) => {
if (supplier.id === currentSupplier.id) {
const updated = {
...supplier,
evaluators: selectedEvaluators,
evaluatorCount: selectedEvaluators.length,
};
return updated;
}
return supplier;
});
// 更新本地状态
setSuppliers(updatedSuppliers);
// 同步到Dva model
updateFormData({ suppliersWithEvaluators: updatedSuppliers });
// 关闭模态框
setEvaluatorModalVisible(false);
};
/**
*
* Dva model
* @param selectedEvaluators
*/
const handleBatchEvaluatorSelect = (selectedEvaluators: PersonnelItem[]) => {
if (selectedRowKeys.length === 0) return;
// 更新所有选中供应商的评价人员列表
const updatedSuppliers = suppliers.map((supplier) => {
if (selectedRowKeys.includes(supplier.id)) {
return {
...supplier,
evaluators: selectedEvaluators,
evaluatorCount: selectedEvaluators.length,
};
}
return supplier;
});
// 更新本地状态
setSuppliers(updatedSuppliers);
// 同步到Dva model
updateFormData({ suppliersWithEvaluators: updatedSuppliers });
// 关闭模态框
setBatchSelectModalVisible(false);
};
/**
*
* Dva model
* @param key ID
*/
const handleDeleteSupplier = (key: string) => {
// 过滤掉要删除的供应商
const updatedSuppliers = suppliers.filter((item) => item.id !== key);
// 更新本地状态
setSuppliers(updatedSuppliers);
// 同步到Dva model
updateFormData({ suppliersWithEvaluators: updatedSuppliers });
// 更新选中行,移除已删除的供应商
setSelectedRowKeys((prevKeys) => prevKeys.filter((k) => k !== key));
};
// 渲染组件
return (
<div className={styles.evaluatorSelectStep}>
<Card title="选择评价人员" bordered={false} className="inner-card">
{/* 工具栏区域 */}
{mode !== 'division' && (
<div className={styles.toolbar}>
<Space>
<Button
type="primary"
onClick={handleBatchSelect}
disabled={selectedRowKeys.length === 0}
>
</Button>
<Button onClick={handleWeightSetting} disabled={taskDeptWeightList.length === 0}>
</Button>
</Space>
</div>
)}
{/* 供应商表格区域 */}
{suppliers.length === 0 ? (
<div style={{ textAlign: 'center', padding: '30px 0', color: '#999' }}>
</div>
) : (
<SupplierTable
suppliers={suppliers}
mode={mode}
selectedRowKeys={selectedRowKeys}
onSelectChange={setSelectedRowKeys}
onViewEvaluators={handleViewEvaluators}
onSelectEvaluators={handleSelectEvaluators}
onDeleteSupplier={handleDeleteSupplier}
/>
)}
{/* 批量选择评价人员弹窗 */}
<BatchEvaluatorModal
visible={batchSelectModalVisible}
onCancel={() => setBatchSelectModalVisible(false)}
filter={mode === 'division'}
filterUserIds={filterUserIds}
onSelect={handleBatchEvaluatorSelect}
/>
{/* 单个供应商评价人员弹窗 */}
<SupplierEvaluatorModal
visible={evaluatorModalVisible}
onCancel={() => setEvaluatorModalVisible(false)}
filter={mode === 'division'}
filterUserIds={filterUserIds}
onSelect={handleEvaluatorSelect}
currentSupplier={currentSupplier}
mode={modalMode}
/>
{/* 权重设置弹窗 */}
<WeightSettingModal
visible={weightSettingModalVisible}
onCancel={() => setWeightSettingModalVisible(false)}
onOk={handleSaveWeights}
taskDeptWeightList={taskDeptWeightList}
form={form}
/>
</Card>
</div>
);
};
/**
* Dva model
* model props
*/
const ConnectedComponent = connect(
({ supplierAnnualTaskManage }: { supplierAnnualTaskManage: SupplierTaskModelState }) => ({
supplierAnnualTaskManage,
}),
)(EvaluatorSelectStepComponent);
/**
* ref innerRef
*/
const EvaluatorSelectStep = forwardRef((props: any, ref) => (
<ConnectedComponent {...props} innerRef={ref} />
));
export default EvaluatorSelectStep;