年审
This commit is contained in:
@ -0,0 +1,325 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { history } from 'umi';
|
||||
import {
|
||||
Button,
|
||||
Table,
|
||||
Space,
|
||||
message,
|
||||
Input,
|
||||
Select,
|
||||
Form,
|
||||
Tooltip,
|
||||
Tag,
|
||||
DatePicker,
|
||||
Row,
|
||||
Col,
|
||||
Card,
|
||||
} from 'antd';
|
||||
import type { TablePaginationConfig } from 'antd';
|
||||
import {
|
||||
SearchOutlined,
|
||||
DeleteOutlined,
|
||||
EyeOutlined,
|
||||
EditOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { getAnnualReviewList } from '@/servers/api/supplierAnnual';
|
||||
import {
|
||||
AnnualReviewStatus,
|
||||
AnnualReviewStatusText,
|
||||
AnnualReviewStatusColor,
|
||||
} from '@/dicts/supplierAnnualReviewDict';
|
||||
import styles from './supplierAnnualReview.less';
|
||||
|
||||
const { Option } = Select;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
// 搜索参数类型
|
||||
interface AnnualReviewSearchParams {
|
||||
annualreviewTheme?: string;
|
||||
reviewStatus?: string;
|
||||
timeRange?: string[];
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
const SupplierAnnualReview: React.FC = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const [reviewData, setReviewData] = useState<supplierAnnualReview.ReviewRecord[]>([]);
|
||||
const [pagination, setPagination] = useState<TablePaginationConfig>({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: (total) => `共 ${total} 条记录`,
|
||||
});
|
||||
const [searchParams, setSearchParams] = useState<AnnualReviewSearchParams>({});
|
||||
|
||||
// 获取审查列表
|
||||
const fetchReviewList = async (
|
||||
current = 1,
|
||||
pageSize = 10,
|
||||
params: AnnualReviewSearchParams = searchParams,
|
||||
) => {
|
||||
// 更新搜索参数状态
|
||||
if (params !== searchParams) {
|
||||
setSearchParams(params);
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
// 构建请求参数
|
||||
const requestParams: supplierAnnualReview.ReviewListRequest = {
|
||||
basePageRequest: {
|
||||
pageNo: current,
|
||||
pageSize: pageSize,
|
||||
},
|
||||
};
|
||||
|
||||
// 添加搜索条件
|
||||
if (params.annualreviewTheme) {
|
||||
requestParams.annualreviewTheme = params.annualreviewTheme;
|
||||
}
|
||||
if (params.reviewStatus) {
|
||||
requestParams.reviewStatus = params.reviewStatus;
|
||||
}
|
||||
if (params.timeRange && params.timeRange.length === 2) {
|
||||
requestParams.startTime = params.timeRange[0];
|
||||
requestParams.endTime = params.timeRange[1];
|
||||
}
|
||||
|
||||
const response = await getAnnualReviewList(requestParams);
|
||||
|
||||
if (response.success && response.data) {
|
||||
const { records, total, current: currentPage, size } = response.data;
|
||||
setReviewData(records);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current: currentPage,
|
||||
pageSize: size,
|
||||
total,
|
||||
});
|
||||
} else {
|
||||
message.error(response.message || '获取审查列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取审查列表失败:', error);
|
||||
message.error('获取审查列表失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
useEffect(() => {
|
||||
fetchReviewList(pagination.current, pagination.pageSize, {});
|
||||
}, []);
|
||||
|
||||
// 处理查看
|
||||
const handleView = (record: supplierAnnualReview.ReviewRecord) => {
|
||||
history.push({
|
||||
pathname: 'supplierAnnualScoreDetail',
|
||||
state: {
|
||||
id: record.id,
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理打分
|
||||
const handleScore = (record: supplierAnnualReview.ReviewRecord) => {
|
||||
history.push({
|
||||
pathname: 'supplierAnnualScore',
|
||||
state: {
|
||||
id: record.id,
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 获取状态标签
|
||||
const getStatusTag = (status: string | undefined, statusName: string | undefined) => {
|
||||
if (!status) return <Tag>未知状态</Tag>;
|
||||
const color = AnnualReviewStatusColor[status as keyof typeof AnnualReviewStatusColor] || 'default';
|
||||
const text = statusName || AnnualReviewStatusText[status as keyof typeof AnnualReviewStatusText] || '未知状态';
|
||||
return <Tag color={color}>{text}</Tag>;
|
||||
};
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleTableChange = (newPagination: TablePaginationConfig) => {
|
||||
fetchReviewList(newPagination.current, newPagination.pageSize, searchParams);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
render: (_: any, __: supplierAnnualReview.ReviewRecord, index: number) =>
|
||||
(pagination.current! - 1) * pagination.pageSize! + index + 1,
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '审查主题',
|
||||
dataIndex: 'annualreviewTheme',
|
||||
key: 'annualreviewTheme',
|
||||
width: 200,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text: string) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '供应商名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 200,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text: string) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '所属部门',
|
||||
dataIndex: 'deptName',
|
||||
key: 'deptName',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '审查员',
|
||||
dataIndex: 'userName',
|
||||
key: 'userName',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'startTime',
|
||||
key: 'startTime',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
dataIndex: 'endTime',
|
||||
key: 'endTime',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'reviewStatus',
|
||||
key: 'reviewStatus',
|
||||
width: 100,
|
||||
render: (status: string, record: supplierAnnualReview.ReviewRecord) =>
|
||||
getStatusTag(status, record.reviewStatusName),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
align: 'center' as const,
|
||||
render: (_: unknown, record: supplierAnnualReview.ReviewRecord) => (
|
||||
<Space size="middle">
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleView(record)}
|
||||
size="small"
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
{/* 只有待审核状态的可以打分 */}
|
||||
{record.reviewStatus === AnnualReviewStatus.WAITING && (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleScore(record)}
|
||||
size="small"
|
||||
>
|
||||
打分
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 处理搜索
|
||||
const handleSearch = (values: any) => {
|
||||
const { timeRange, ...rest } = values;
|
||||
const params: AnnualReviewSearchParams = { ...rest };
|
||||
|
||||
if (timeRange && timeRange.length === 2) {
|
||||
params.timeRange = [
|
||||
timeRange[0].format('YYYY-MM-DD'),
|
||||
timeRange[1].format('YYYY-MM-DD')
|
||||
];
|
||||
}
|
||||
|
||||
fetchReviewList(1, pagination.pageSize, params);
|
||||
};
|
||||
|
||||
// 重置搜索表单
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
fetchReviewList(1, pagination.pageSize, {});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<Card>
|
||||
<div className="filter-action-row">
|
||||
<Form
|
||||
form={form}
|
||||
name="search"
|
||||
onFinish={handleSearch}
|
||||
layout="inline"
|
||||
className="filter-form"
|
||||
>
|
||||
<Form.Item name="annualreviewTheme" label="审查主题">
|
||||
<Input placeholder="请输入审查主题" allowClear />
|
||||
</Form.Item>
|
||||
<Form.Item name="reviewStatus" label="状态">
|
||||
<Select placeholder="请选择状态" allowClear style={{ width: 120 }}>
|
||||
{Object.entries(AnnualReviewStatusText).map(([key, value]) => (
|
||||
<Option key={key} value={key}>{value}</Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item name="timeRange" label="时间范围">
|
||||
<RangePicker style={{ width: 240 }} />
|
||||
</Form.Item>
|
||||
<Form.Item className="filter-btns">
|
||||
<Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
|
||||
搜索
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={handleReset}
|
||||
>
|
||||
重置
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div className="content-area">
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={reviewData}
|
||||
pagination={pagination}
|
||||
loading={loading}
|
||||
onChange={handleTableChange}
|
||||
scroll={{ x: 1200 }}
|
||||
/>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierAnnualReview;
|
@ -0,0 +1,60 @@
|
||||
// 供应商年度审查样式
|
||||
.filter-action-row {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.filter-form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
|
||||
.filter-btns {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.content-area {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.status-tag {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
// 详情页样式
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-card {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.score-form {
|
||||
|
||||
.score-form-item {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.score-table {
|
||||
margin-bottom: 16px;
|
||||
|
||||
:global {
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.score-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 24px;
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
@ -0,0 +1,305 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { history } from 'umi';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Descriptions,
|
||||
Divider,
|
||||
Spin,
|
||||
message,
|
||||
Typography,
|
||||
Empty,
|
||||
Space,
|
||||
Form,
|
||||
Radio,
|
||||
Input,
|
||||
Modal,
|
||||
Tag,
|
||||
Table,
|
||||
} from 'antd';
|
||||
import { ArrowLeftOutlined, SaveOutlined } from '@ant-design/icons';
|
||||
import { getAnnualReviewDetail, submitAnnualReviewScore } from '@/servers/api/supplierAnnual';
|
||||
import {
|
||||
AnnualReviewStatus,
|
||||
AnnualReviewStatusText,
|
||||
AnnualReviewStatusColor,
|
||||
ExamineResult,
|
||||
ExamineResultText,
|
||||
} from '@/dicts/supplierAnnualReviewDict';
|
||||
import styles from './supplierAnnualReview.less';
|
||||
|
||||
const { Title } = Typography;
|
||||
const { TextArea } = Input;
|
||||
|
||||
interface ScoreFormItem {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
examineResult: string;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
const SupplierAnnualReviewScore: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [submitting, setSubmitting] = useState<boolean>(false);
|
||||
const [reviewDetail, setReviewDetail] = useState<supplierAnnualReview.ReviewRecord | null>(null);
|
||||
const [scoreItems, setScoreItems] = useState<ScoreFormItem[]>([]);
|
||||
|
||||
// 从路由获取ID
|
||||
const { id } = history.location.state as { id: string };
|
||||
|
||||
// 获取审查详情
|
||||
const fetchReviewDetail = async (reviewId: string) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await getAnnualReviewDetail(reviewId);
|
||||
if (res.success && res.data) {
|
||||
setReviewDetail(res.data);
|
||||
|
||||
// 这里应该根据实际接口返回的数据设置打分项
|
||||
// 由于没有具体的数据结构,这里模拟一些打分项
|
||||
const mockScoreItems: ScoreFormItem[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: '质量评价',
|
||||
description: '供应商产品质量及质量管理体系评价',
|
||||
examineResult: '',
|
||||
remark: '',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: '交付评价',
|
||||
description: '供应商交付及时性、准确性评价',
|
||||
examineResult: '',
|
||||
remark: '',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: '服务评价',
|
||||
description: '供应商服务响应速度及服务质量评价',
|
||||
examineResult: '',
|
||||
remark: '',
|
||||
},
|
||||
];
|
||||
|
||||
setScoreItems(mockScoreItems);
|
||||
|
||||
// 初始化表单
|
||||
const initialValues: any = {};
|
||||
mockScoreItems.forEach((item) => {
|
||||
initialValues[`examineResult_${item.id}`] = '';
|
||||
initialValues[`remark_${item.id}`] = '';
|
||||
});
|
||||
|
||||
form.setFieldsValue(initialValues);
|
||||
} else {
|
||||
message.error(res.message || '获取审查详情失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取审查详情失败:', error);
|
||||
message.error('获取审查详情失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
fetchReviewDetail(id);
|
||||
} else {
|
||||
message.error('审查ID不存在,无法获取详情');
|
||||
history.goBack();
|
||||
}
|
||||
}, [id]);
|
||||
|
||||
// 返回列表页
|
||||
const handleBack = () => {
|
||||
history.goBack();
|
||||
};
|
||||
// 提交评分
|
||||
const submitScore = async () => {
|
||||
if (!reviewDetail) return;
|
||||
|
||||
try {
|
||||
setSubmitting(true);
|
||||
|
||||
// 准备提交数据
|
||||
const formValues = form.getFieldsValue();
|
||||
const scoreVoList = scoreItems.map((item) => ({
|
||||
id: item.id,
|
||||
examineResult: formValues[`examineResult_${item.id}`],
|
||||
remark: formValues[`remark_${item.id}`] || '',
|
||||
}));
|
||||
|
||||
const submitData: supplierAnnualReview.ScoreRequest = {
|
||||
id: reviewDetail.id,
|
||||
scoreVoList,
|
||||
};
|
||||
|
||||
const res = await submitAnnualReviewScore(submitData);
|
||||
|
||||
if (res.success) {
|
||||
message.success('评审提交成功');
|
||||
history.goBack();
|
||||
} else {
|
||||
message.error(res.message || '评审提交失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('评审提交失败:', error);
|
||||
message.error('评审提交失败');
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
try {
|
||||
// 表单验证
|
||||
await form.validateFields();
|
||||
|
||||
// 确认提交
|
||||
Modal.confirm({
|
||||
title: '确认提交',
|
||||
content: '确定要提交评审结果吗?提交后将无法修改。',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: submitScore,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('表单验证失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取状态标签
|
||||
const getStatusTag = (status: string | undefined, statusName: string | undefined) => {
|
||||
if (!status) return <Tag>未知状态</Tag>;
|
||||
const color =
|
||||
AnnualReviewStatusColor[status as keyof typeof AnnualReviewStatusColor] || 'default';
|
||||
const text =
|
||||
statusName ||
|
||||
AnnualReviewStatusText[status as keyof typeof AnnualReviewStatusText] ||
|
||||
'未知状态';
|
||||
return <Tag color={color}>{text}</Tag>;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<Card>
|
||||
<div className={styles['page-header']}>
|
||||
<Title level={4} style={{ margin: 0 }}>
|
||||
年度审查评分
|
||||
</Title>
|
||||
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
<Spin spinning={loading}>
|
||||
{reviewDetail ? (
|
||||
<>
|
||||
<Card title="基本信息" bordered={false} className={styles['detail-card']}>
|
||||
<Descriptions column={2} bordered>
|
||||
<Descriptions.Item label="审查主题">
|
||||
{reviewDetail.annualreviewTheme}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="供应商名称">{reviewDetail.name}</Descriptions.Item>
|
||||
<Descriptions.Item label="所属部门">
|
||||
{reviewDetail.deptName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="审查员">
|
||||
{reviewDetail.userName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="开始时间">{reviewDetail.startTime}</Descriptions.Item>
|
||||
<Descriptions.Item label="结束时间">{reviewDetail.endTime}</Descriptions.Item>
|
||||
<Descriptions.Item label="状态">
|
||||
{getStatusTag(reviewDetail.reviewStatus, reviewDetail.reviewStatusName)}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card title="审查结果" bordered={false} className={styles['detail-card']}>
|
||||
<Form form={form} layout="vertical" className={styles['score-form']}>
|
||||
<Table
|
||||
rowKey="id"
|
||||
dataSource={scoreItems}
|
||||
pagination={false}
|
||||
bordered
|
||||
className={styles['score-table']}
|
||||
columns={[
|
||||
{
|
||||
title: '评分项',
|
||||
dataIndex: 'name',
|
||||
width: '15%',
|
||||
},
|
||||
{
|
||||
title: '评分项说明',
|
||||
dataIndex: 'description',
|
||||
width: '25%',
|
||||
},
|
||||
{
|
||||
title: '评审结果',
|
||||
dataIndex: 'examineResult',
|
||||
width: '25%',
|
||||
render: (_, record) => (
|
||||
<Form.Item
|
||||
name={`examineResult_${record.id}`}
|
||||
rules={[{ required: true, message: '请选择评审结果' }]}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value={ExamineResult.QUALIFIED}>
|
||||
{ExamineResultText[ExamineResult.QUALIFIED]}
|
||||
</Radio>
|
||||
<Radio value={ExamineResult.UNQUALIFIED}>
|
||||
{ExamineResultText[ExamineResult.UNQUALIFIED]}
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '评审说明',
|
||||
dataIndex: 'remark',
|
||||
width: '35%',
|
||||
render: (_, record) => (
|
||||
<Form.Item
|
||||
name={`remark_${record.id}`}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<TextArea
|
||||
rows={2}
|
||||
placeholder="请输入评审说明"
|
||||
maxLength={200}
|
||||
/>
|
||||
</Form.Item>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className={styles['score-actions']}>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<SaveOutlined />}
|
||||
onClick={handleSubmit}
|
||||
loading={submitting}
|
||||
>
|
||||
提交评审
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
!loading && <Empty description="暂无审查详情数据" />
|
||||
)}
|
||||
</Spin>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierAnnualReviewScore;
|
@ -0,0 +1,211 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { history } from 'umi';
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Descriptions,
|
||||
Divider,
|
||||
Spin,
|
||||
message,
|
||||
Typography,
|
||||
Empty,
|
||||
Table,
|
||||
Tag,
|
||||
} from 'antd';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { getAnnualReviewDetail } from '@/servers/api/supplierAnnual';
|
||||
import {
|
||||
AnnualReviewStatus,
|
||||
AnnualReviewStatusText,
|
||||
AnnualReviewStatusColor,
|
||||
ExamineResult,
|
||||
ExamineResultText,
|
||||
ExamineResultColor,
|
||||
} from '@/dicts/supplierAnnualReviewDict';
|
||||
import styles from './supplierAnnualReview.less';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
// 模拟评分结果的数据结构
|
||||
interface ScoreResult {
|
||||
id: string;
|
||||
itemName: string;
|
||||
examineResult: string;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
const SupplierAnnualReviewDetail: React.FC = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [reviewDetail, setReviewDetail] = useState<supplierAnnualReview.ReviewRecord | null>(null);
|
||||
const [scoreResults, setScoreResults] = useState<ScoreResult[]>([]);
|
||||
|
||||
// 从路由获取ID
|
||||
const { id } = history.location.state as { id: string };
|
||||
|
||||
// 获取审查详情
|
||||
const fetchReviewDetail = async (reviewId: string) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await getAnnualReviewDetail(reviewId);
|
||||
if (res.success && res.data) {
|
||||
setReviewDetail(res.data);
|
||||
|
||||
// 这里应该根据实际接口返回的数据设置评分结果
|
||||
// 由于没有具体的数据结构,这里模拟一些评分结果
|
||||
const mockScoreResults: ScoreResult[] = [
|
||||
{
|
||||
id: '1',
|
||||
itemName: '产品质量',
|
||||
examineResult: ExamineResult.QUALIFIED,
|
||||
remark: '产品质量符合要求,无重大质量问题',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
itemName: '交货及时性',
|
||||
examineResult: ExamineResult.QUALIFIED,
|
||||
remark: '交货及时,满足生产需求',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
itemName: '服务态度',
|
||||
examineResult: ExamineResult.UNQUALIFIED,
|
||||
remark: '客户反馈服务态度有待提高,响应不及时',
|
||||
},
|
||||
];
|
||||
|
||||
setScoreResults(mockScoreResults);
|
||||
} else {
|
||||
message.error(res.message || '获取审查详情失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取审查详情失败:', error);
|
||||
message.error('获取审查详情失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
fetchReviewDetail(id);
|
||||
} else {
|
||||
message.error('审查ID不存在,无法获取详情');
|
||||
history.goBack();
|
||||
}
|
||||
}, [id]);
|
||||
|
||||
// 返回列表页
|
||||
const handleBack = () => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
// 获取状态标签
|
||||
const getStatusTag = (status: string | undefined, statusName: string | undefined) => {
|
||||
if (!status) return <Tag>未知状态</Tag>;
|
||||
const color = AnnualReviewStatusColor[status as keyof typeof AnnualReviewStatusColor] || 'default';
|
||||
const text = statusName || AnnualReviewStatusText[status as keyof typeof AnnualReviewStatusText] || '未知状态';
|
||||
return <Tag color={color}>{text}</Tag>;
|
||||
};
|
||||
|
||||
// 获取评审结果标签
|
||||
const getResultTag = (result: string) => {
|
||||
const color = ExamineResultColor[result as keyof typeof ExamineResultColor] || 'default';
|
||||
const text = ExamineResultText[result as keyof typeof ExamineResultText] || '未知';
|
||||
return <Tag color={color}>{text}</Tag>;
|
||||
};
|
||||
|
||||
// 评分结果表格列定义
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
width: 80,
|
||||
render: (_: any, __: any, index: number) => index + 1,
|
||||
},
|
||||
{
|
||||
title: '评分项',
|
||||
dataIndex: 'itemName',
|
||||
key: 'itemName',
|
||||
},
|
||||
{
|
||||
title: '评审结果',
|
||||
dataIndex: 'examineResult',
|
||||
key: 'examineResult',
|
||||
width: 120,
|
||||
render: (result: string) => getResultTag(result),
|
||||
},
|
||||
{
|
||||
title: '评审说明',
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<Card>
|
||||
<div className={styles['page-header']}>
|
||||
<Title level={4} style={{ margin: 0 }}>
|
||||
年度审查详情
|
||||
</Title>
|
||||
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
<Spin spinning={loading}>
|
||||
{reviewDetail ? (
|
||||
<>
|
||||
<Card title="基本信息" bordered={false} className={styles['detail-card']}>
|
||||
<Descriptions column={2} bordered>
|
||||
<Descriptions.Item label="审查主题">
|
||||
{reviewDetail.annualreviewTheme}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="供应商名称">
|
||||
{reviewDetail.name}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="所属部门">
|
||||
{reviewDetail.deptName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="审查员">
|
||||
{reviewDetail.userName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="开始时间">
|
||||
{reviewDetail.startTime}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="结束时间">
|
||||
{reviewDetail.endTime}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="状态">
|
||||
{getStatusTag(reviewDetail.reviewStatus, reviewDetail.reviewStatusName)}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card title="评分结果" bordered={false} className={styles['detail-card']}>
|
||||
{scoreResults.length > 0 ? (
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={scoreResults}
|
||||
rowKey="id"
|
||||
pagination={false}
|
||||
bordered
|
||||
/>
|
||||
) : (
|
||||
<Empty description="暂无评分数据" />
|
||||
)}
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
!loading && <Empty description="暂无审查详情数据" />
|
||||
)}
|
||||
</Spin>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierAnnualReviewDetail;
|
Reference in New Issue
Block a user