371 lines
11 KiB
TypeScript
371 lines
11 KiB
TypeScript
![]() |
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
|
|||
|
import { Card, Table, Tag, Switch, Space, Button, message, Modal, Radio, Checkbox, Row, Col } from 'antd';
|
|||
|
import type { PersonnelItem } from '@/servers/types/evaluator';
|
|||
|
import type { ColumnsType } from 'antd/es/table';
|
|||
|
import type { CheckboxValueType } from 'antd/es/checkbox/Group';
|
|||
|
import styles from '../supplierTaskManageAdd.less';
|
|||
|
|
|||
|
// 评价指标类型定义
|
|||
|
interface IndicatorItem {
|
|||
|
id: string;
|
|||
|
name: string;
|
|||
|
description: string;
|
|||
|
}
|
|||
|
|
|||
|
// 组件接收的Props定义
|
|||
|
interface DivisionStepProps {
|
|||
|
formData: any;
|
|||
|
onFormDataChange?: (values: any) => void;
|
|||
|
}
|
|||
|
|
|||
|
// 评价方式枚举
|
|||
|
enum EvaluateType {
|
|||
|
ALL = 'ALL', // 按评价单评价(全部指标)
|
|||
|
INDICATOR = 'INDICATOR', // 按指标评价(部分指标)
|
|||
|
}
|
|||
|
|
|||
|
// 模拟的评价指标数据
|
|||
|
const mockIndicators: IndicatorItem[] = [
|
|||
|
{ id: 'I001', name: '产品质量', description: '评估供应商产品质量' },
|
|||
|
{ id: 'I002', name: '交货及时性', description: '评估供应商交货的及时性' },
|
|||
|
{ id: 'I003', name: '服务水平', description: '评估供应商提供的服务水平' },
|
|||
|
{ id: 'I004', name: '价格竞争力', description: '评估供应商产品价格的竞争力' },
|
|||
|
{ id: 'I005', name: '技术能力', description: '评估供应商的技术创新能力' },
|
|||
|
];
|
|||
|
|
|||
|
const DivisionStep = forwardRef<any, DivisionStepProps>(({ formData, onFormDataChange }, ref) => {
|
|||
|
// 从上一步获取的评价人员列表
|
|||
|
const [evaluators, setEvaluators] = useState<PersonnelItem[]>([]);
|
|||
|
|
|||
|
// 评价人员指标分配数据
|
|||
|
const [indicatorAssignments, setIndicatorAssignments] = useState<{
|
|||
|
[userId: string]: {
|
|||
|
type: EvaluateType;
|
|||
|
indicatorIds: string[];
|
|||
|
};
|
|||
|
}>({});
|
|||
|
|
|||
|
// 选中的行keys
|
|||
|
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
|||
|
|
|||
|
// 指标列表
|
|||
|
const [indicators] = useState<IndicatorItem[]>(mockIndicators);
|
|||
|
|
|||
|
// 指标分工弹窗可见性
|
|||
|
const [divisionModalVisible, setDivisionModalVisible] = useState(false);
|
|||
|
|
|||
|
// 评价方式类型
|
|||
|
const [batchEvaluateType, setBatchEvaluateType] = useState<EvaluateType>(EvaluateType.ALL);
|
|||
|
|
|||
|
// 批量选择的指标
|
|||
|
const [batchSelectedIndicators, setBatchSelectedIndicators] = useState<string[]>([]);
|
|||
|
|
|||
|
// 处理行选择变化
|
|||
|
const handleSelectChange = (newSelectedRowKeys: React.Key[]) => {
|
|||
|
setSelectedRowKeys(newSelectedRowKeys);
|
|||
|
};
|
|||
|
|
|||
|
// 打开指标分工弹窗
|
|||
|
const handleOpenDivisionModal = () => {
|
|||
|
if (selectedRowKeys.length === 0) {
|
|||
|
message.warning('请先选择评价人员');
|
|||
|
return;
|
|||
|
}
|
|||
|
setDivisionModalVisible(true);
|
|||
|
};
|
|||
|
|
|||
|
// 处理评价方式变更
|
|||
|
const handleEvaluateTypeChange = (e: any) => {
|
|||
|
setBatchEvaluateType(e.target.value);
|
|||
|
};
|
|||
|
|
|||
|
// 处理指标选择变更
|
|||
|
const handleIndicatorChange = (checkedValues: CheckboxValueType[]) => {
|
|||
|
setBatchSelectedIndicators(checkedValues.map(v => v.toString()));
|
|||
|
};
|
|||
|
|
|||
|
// 批量设置指标分工
|
|||
|
const handleBatchSetDivision = () => {
|
|||
|
// 获取选中的评价人员
|
|||
|
const selectedEvaluators = evaluators.filter(
|
|||
|
evaluator => selectedRowKeys.includes(evaluator.id)
|
|||
|
);
|
|||
|
|
|||
|
// 更新指标分配数据
|
|||
|
const newAssignments = { ...indicatorAssignments };
|
|||
|
|
|||
|
selectedEvaluators.forEach(evaluator => {
|
|||
|
newAssignments[evaluator.id] = {
|
|||
|
type: batchEvaluateType,
|
|||
|
indicatorIds: batchEvaluateType === EvaluateType.INDICATOR ? batchSelectedIndicators : [],
|
|||
|
};
|
|||
|
});
|
|||
|
|
|||
|
setIndicatorAssignments(newAssignments);
|
|||
|
setDivisionModalVisible(false);
|
|||
|
message.success(`已为${selectedRowKeys.length}名评价人员设置分工`);
|
|||
|
};
|
|||
|
|
|||
|
// 处理单个评价人员的指标分工
|
|||
|
const handleAssignIndicators = (userId: string) => {
|
|||
|
Modal.info({
|
|||
|
title: '评价指标分工',
|
|||
|
content: '此功能将在后续完善',
|
|||
|
okText: '确定',
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// 查看评价人员的指标分工
|
|||
|
const handleViewAssignment = (userId: string) => {
|
|||
|
const assignment = indicatorAssignments[userId];
|
|||
|
if (!assignment) {
|
|||
|
message.info('该评价人员尚未设置分工');
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
const assignedIndicators = indicators.filter(ind =>
|
|||
|
assignment.type === EvaluateType.ALL ||
|
|||
|
assignment.indicatorIds.includes(ind.id)
|
|||
|
);
|
|||
|
|
|||
|
Modal.info({
|
|||
|
title: '查看评价指标分工',
|
|||
|
content: (
|
|||
|
<div>
|
|||
|
<p>评价方式: {assignment.type === EvaluateType.ALL ? '按评价单评价' : '按指标评价'}</p>
|
|||
|
<p>评价指标: </p>
|
|||
|
<ul>
|
|||
|
{assignedIndicators.map(ind => (
|
|||
|
<li key={ind.id}>{ind.name}</li>
|
|||
|
))}
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
),
|
|||
|
okText: '确定',
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// 删除评价人员
|
|||
|
const handleRemoveEvaluator = (userId: string) => {
|
|||
|
Modal.confirm({
|
|||
|
title: '确认删除',
|
|||
|
content: '确定要删除该评价人员吗?',
|
|||
|
okText: '确定',
|
|||
|
cancelText: '取消',
|
|||
|
onOk: () => {
|
|||
|
// 更新评价人员列表
|
|||
|
setEvaluators(prev => prev.filter(e => e.id !== userId));
|
|||
|
|
|||
|
// 更新指标分配数据
|
|||
|
const newAssignments = { ...indicatorAssignments };
|
|||
|
delete newAssignments[userId];
|
|||
|
setIndicatorAssignments(newAssignments);
|
|||
|
|
|||
|
message.success('已删除评价人员');
|
|||
|
},
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
// 初始化:从formData中提取指标分配数据
|
|||
|
useEffect(() => {
|
|||
|
if (formData.indicatorList) {
|
|||
|
// 如果已有指标分配数据,直接使用
|
|||
|
const assignments: any = {};
|
|||
|
formData.indicatorList.forEach((item: any) => {
|
|||
|
assignments[item.userId] = {
|
|||
|
type: item.type,
|
|||
|
indicatorIds: item.indicatorIds || [],
|
|||
|
};
|
|||
|
});
|
|||
|
setIndicatorAssignments(assignments);
|
|||
|
}
|
|||
|
}, [formData.indicatorList]);
|
|||
|
|
|||
|
// 从上一步获取评价人员列表 - 避免频繁更新
|
|||
|
useEffect(() => {
|
|||
|
if (!formData.suppliersWithEvaluators) return;
|
|||
|
|
|||
|
// 从所有供应商中提取评价人员列表
|
|||
|
const allEvaluators: PersonnelItem[] = [];
|
|||
|
|
|||
|
formData.suppliersWithEvaluators.forEach((supplier: any) => {
|
|||
|
if (supplier.evaluators && supplier.evaluators.length > 0) {
|
|||
|
supplier.evaluators.forEach((evaluator: PersonnelItem) => {
|
|||
|
// 检查是否已存在(避免重复)
|
|||
|
if (!allEvaluators.some(e => e.id === evaluator.id)) {
|
|||
|
allEvaluators.push({
|
|||
|
...evaluator,
|
|||
|
// 添加单位和员工编号,假设这些字段可能不存在
|
|||
|
company: evaluator.company || supplier.supplierName || '未知单位',
|
|||
|
employeeNumber: evaluator.employeeNumber || `EMP${evaluator.id.slice(-4)}`,
|
|||
|
department: evaluator.department || '未知部门',
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
setEvaluators(allEvaluators);
|
|||
|
}, [formData.suppliersWithEvaluators]);
|
|||
|
|
|||
|
// 为评价人员初始化指标分配数据 - 作为单独的效果处理
|
|||
|
useEffect(() => {
|
|||
|
// 检查是否有新的评价人员需要初始化
|
|||
|
const newAssignments = { ...indicatorAssignments };
|
|||
|
let hasNewAssignments = false;
|
|||
|
|
|||
|
evaluators.forEach(evaluator => {
|
|||
|
if (!indicatorAssignments[evaluator.id]) {
|
|||
|
newAssignments[evaluator.id] = {
|
|||
|
type: EvaluateType.ALL,
|
|||
|
indicatorIds: [],
|
|||
|
};
|
|||
|
hasNewAssignments = true;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (hasNewAssignments) {
|
|||
|
setIndicatorAssignments(newAssignments);
|
|||
|
}
|
|||
|
}, [evaluators, indicatorAssignments]);
|
|||
|
|
|||
|
// 同步数据回表单 - 使用防抖确保不会频繁触发
|
|||
|
const previousValueRef = React.useRef<string>("");
|
|||
|
|
|||
|
useEffect(() => {
|
|||
|
// 将评价人员列表和指标分配数据同步回表单
|
|||
|
const indicatorList = evaluators.map(evaluator => ({
|
|||
|
userId: evaluator.id,
|
|||
|
userName: evaluator.name,
|
|||
|
type: indicatorAssignments[evaluator.id]?.type || EvaluateType.ALL,
|
|||
|
indicatorIds: indicatorAssignments[evaluator.id]?.indicatorIds || [],
|
|||
|
}));
|
|||
|
|
|||
|
// 使用JSON字符串比较确保只有在真正变化时才更新
|
|||
|
const currentValue = JSON.stringify(indicatorList);
|
|||
|
if (currentValue !== previousValueRef.current) {
|
|||
|
previousValueRef.current = currentValue;
|
|||
|
onFormDataChange?.({
|
|||
|
...formData,
|
|||
|
indicatorList,
|
|||
|
});
|
|||
|
}
|
|||
|
}, [evaluators, indicatorAssignments, formData, onFormDataChange]);
|
|||
|
|
|||
|
// 暴露给父组件的方法
|
|||
|
useImperativeHandle(ref, () => ({
|
|||
|
validate: () => {
|
|||
|
if (evaluators.length === 0) {
|
|||
|
return {
|
|||
|
valid: false,
|
|||
|
message: '请先分配评价人员',
|
|||
|
};
|
|||
|
}
|
|||
|
return { valid: true };
|
|||
|
},
|
|||
|
}));
|
|||
|
|
|||
|
// 表格列定义
|
|||
|
const columns: ColumnsType<PersonnelItem> = [
|
|||
|
{
|
|||
|
title: '姓名',
|
|||
|
dataIndex: 'name',
|
|||
|
key: 'name',
|
|||
|
},
|
|||
|
{
|
|||
|
title: '所属单位',
|
|||
|
dataIndex: 'company',
|
|||
|
key: 'company',
|
|||
|
},
|
|||
|
{
|
|||
|
title: '所属部门',
|
|||
|
dataIndex: 'department',
|
|||
|
key: 'department',
|
|||
|
},
|
|||
|
{
|
|||
|
title: '员工编号',
|
|||
|
dataIndex: 'employeeNumber',
|
|||
|
key: 'employeeNumber',
|
|||
|
},
|
|||
|
{
|
|||
|
title: '是否设置分工',
|
|||
|
key: 'hasDivision',
|
|||
|
render: (_: any, record: PersonnelItem) => {
|
|||
|
const assignment = indicatorAssignments[record.id];
|
|||
|
if (!assignment) return <Tag color="red">未设置</Tag>;
|
|||
|
return <Tag color="green">已设置</Tag>;
|
|||
|
},
|
|||
|
},
|
|||
|
{
|
|||
|
title: '操作',
|
|||
|
key: 'action',
|
|||
|
render: (_: any, record: PersonnelItem) => (
|
|||
|
<Space size="middle">
|
|||
|
<Button type="link" onClick={() => handleAssignIndicators(record.id)}>评价指标分工</Button>
|
|||
|
<Button type="link" onClick={() => handleViewAssignment(record.id)}>查看</Button>
|
|||
|
<Button type="link" onClick={() => handleRemoveEvaluator(record.id)}>删除</Button>
|
|||
|
</Space>
|
|||
|
),
|
|||
|
},
|
|||
|
];
|
|||
|
|
|||
|
return (
|
|||
|
<div>
|
|||
|
<div style={{ marginBottom: 16 }}>
|
|||
|
<Button
|
|||
|
type="primary"
|
|||
|
onClick={handleOpenDivisionModal}
|
|||
|
disabled={selectedRowKeys.length === 0}
|
|||
|
>
|
|||
|
设置评价指标分工
|
|||
|
</Button>
|
|||
|
</div>
|
|||
|
|
|||
|
<Table
|
|||
|
rowKey="id"
|
|||
|
rowSelection={{
|
|||
|
selectedRowKeys,
|
|||
|
onChange: handleSelectChange,
|
|||
|
}}
|
|||
|
columns={columns}
|
|||
|
dataSource={evaluators}
|
|||
|
pagination={false}
|
|||
|
/>
|
|||
|
|
|||
|
{/* 批量设置指标分工弹窗 */}
|
|||
|
<Modal
|
|||
|
title="批量设置评价指标分工"
|
|||
|
visible={divisionModalVisible}
|
|||
|
onOk={handleBatchSetDivision}
|
|||
|
onCancel={() => setDivisionModalVisible(false)}
|
|||
|
okText="确定"
|
|||
|
cancelText="取消"
|
|||
|
width={700}
|
|||
|
>
|
|||
|
<div>
|
|||
|
<p>您已选择 {selectedRowKeys.length} 名评价人员进行指标分工设置</p>
|
|||
|
<Radio.Group defaultValue={EvaluateType.ALL} onChange={handleEvaluateTypeChange}>
|
|||
|
<Radio value={EvaluateType.ALL}>按评价单评价</Radio>
|
|||
|
<Radio value={EvaluateType.INDICATOR}>按指标评价</Radio>
|
|||
|
</Radio.Group>
|
|||
|
|
|||
|
<div style={{ marginTop: 16 }}>
|
|||
|
<p>指标列表:</p>
|
|||
|
<Checkbox.Group style={{ width: '100%' }} onChange={handleIndicatorChange}>
|
|||
|
<Row>
|
|||
|
{indicators.map(indicator => (
|
|||
|
<Col span={8} key={indicator.id}>
|
|||
|
<Checkbox value={indicator.id}>{indicator.name}</Checkbox>
|
|||
|
</Col>
|
|||
|
))}
|
|||
|
</Row>
|
|||
|
</Checkbox.Group>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</Modal>
|
|||
|
</div>
|
|||
|
);
|
|||
|
});
|
|||
|
|
|||
|
export default DivisionStep;
|