暂存评价任务新增

This commit is contained in:
linxd
2025-06-24 18:58:43 +08:00
parent 9a45e65db1
commit d7df286214
22 changed files with 1502 additions and 908 deletions

View File

@ -0,0 +1,370 @@
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;