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(
|
2025-06-30 09:43:28 +08:00
|
|
|
|
(supplier: SupplierItem) => {
|
2025-06-27 19:55:19 +08:00
|
|
|
|
// 确保evaluators字段存在且为数组
|
|
|
|
|
const evaluators = supplier.evaluators || [];
|
|
|
|
|
return {
|
|
|
|
|
...supplier,
|
|
|
|
|
userDept: supplier.userDept || '采购部', // 设置默认部门
|
|
|
|
|
evaluatorCount: evaluators.length,
|
|
|
|
|
evaluators: evaluators,
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// 更新本地供应商状态
|
|
|
|
|
setSuppliers(suppliersWithEvaluators);
|
|
|
|
|
} else {
|
|
|
|
|
// 没有选择供应商,清空供应商列表
|
|
|
|
|
setSuppliers([]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}, [taskFormData]); // 依赖于 taskFormData,当 model 数据变化时重新计算
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 更新表单数据
|
|
|
|
|
* 将本地状态同步到 Dva model
|
|
|
|
|
* @param updatedData 要更新的部分数据
|
|
|
|
|
*/
|
|
|
|
|
const updateFormData = (updatedData: any) => {
|
|
|
|
|
// 结构 更新数据中的suppliersWithEvaluators
|
|
|
|
|
const { suppliersWithEvaluators }: { suppliersWithEvaluators: SupplierItem[] } = updatedData;
|
|
|
|
|
// 构建供应商ID列表
|
|
|
|
|
const supplierIds = suppliersWithEvaluators.map((supplier) => ({
|
2025-06-30 09:43:28 +08:00
|
|
|
|
suppliedId: supplier.id,
|
2025-06-27 19:55:19 +08:00
|
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
/**
|
|
|
|
|
* 处理选择评价人员按钮点击事件
|
|
|
|
|
* 打开评价人员选择模态框
|
|
|
|
|
* @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}>
|
2025-06-30 09:43:28 +08:00
|
|
|
|
<Card title="选择年审人员" bordered={false} className="inner-card">
|
2025-06-27 19:55:19 +08:00
|
|
|
|
{/* 工具栏区域 */}
|
|
|
|
|
{mode !== 'division' && (
|
|
|
|
|
<div className={styles.toolbar}>
|
|
|
|
|
<Space>
|
|
|
|
|
<Button
|
|
|
|
|
type="primary"
|
|
|
|
|
onClick={handleBatchSelect}
|
|
|
|
|
disabled={selectedRowKeys.length === 0}
|
|
|
|
|
>
|
2025-06-30 09:43:28 +08:00
|
|
|
|
批量选择年审人员
|
2025-06-27 19:55:19 +08:00
|
|
|
|
</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}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
|
2025-06-30 09:43:28 +08:00
|
|
|
|
{/* 批量选择年审人员弹窗 */}
|
2025-06-27 19:55:19 +08:00
|
|
|
|
<BatchEvaluatorModal
|
|
|
|
|
visible={batchSelectModalVisible}
|
|
|
|
|
onCancel={() => setBatchSelectModalVisible(false)}
|
|
|
|
|
filter={mode === 'division'}
|
|
|
|
|
filterUserIds={filterUserIds}
|
|
|
|
|
onSelect={handleBatchEvaluatorSelect}
|
|
|
|
|
/>
|
|
|
|
|
|
2025-06-30 09:43:28 +08:00
|
|
|
|
{/* 单个供应商年审人员弹窗 */}
|
2025-06-27 19:55:19 +08:00
|
|
|
|
<SupplierEvaluatorModal
|
|
|
|
|
visible={evaluatorModalVisible}
|
|
|
|
|
onCancel={() => setEvaluatorModalVisible(false)}
|
|
|
|
|
filter={mode === 'division'}
|
|
|
|
|
filterUserIds={filterUserIds}
|
|
|
|
|
onSelect={handleEvaluatorSelect}
|
|
|
|
|
currentSupplier={currentSupplier}
|
|
|
|
|
mode={modalMode}
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
</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;
|