Files
fe_supplier_frontend/src/pages/supplierAnnualManage/supplierAnnualTaskManage/components/EvaluatorSelectStep.tsx
2025-06-30 09:43:28 +08:00

367 lines
12 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, 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: SupplierItem) => {
// 确保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) => ({
suppliedId: 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);
};
/**
* 处理选择评价人员按钮点击事件
* 打开评价人员选择模态框
* @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>
</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}
/>
</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;