评价打分和年审审核时候需要根据模板的星号项来验证
This commit is contained in:
@ -307,7 +307,7 @@ export default [
|
||||
},
|
||||
{
|
||||
name: '年审打分',
|
||||
path: 'supplierAnnual/supplierAnnualScore',
|
||||
path: '/supplierAnnual/supplierAnnualScore',
|
||||
hideInMenu: true,
|
||||
icon: 'icon-dafen',
|
||||
component: '@/pages/supplierAnnualManage/supplierAnnualReview/supplierAnnualScore',
|
||||
|
@ -32,4 +32,9 @@
|
||||
color: #faad14;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.required {
|
||||
color: red;
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
@ -2,13 +2,7 @@
|
||||
// 用于展示和填写供应商评价得分,基于EvaluateTemplateTable组件扩展
|
||||
// 在二级指标中添加了评分列和说明列
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Table,
|
||||
Input,
|
||||
InputNumber,
|
||||
Typography,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { Table, Input, InputNumber, Typography, Tooltip } from 'antd';
|
||||
import { useIntl } from 'umi';
|
||||
import './ScoreEvaluationTable.less';
|
||||
|
||||
@ -92,6 +86,7 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
ndScore: stItem.score || '0',
|
||||
score: stItem.actualScore || '',
|
||||
remark: stItem.remark || '',
|
||||
isStar: stItem.isStar || '',
|
||||
});
|
||||
} else {
|
||||
// 处理二级指标
|
||||
@ -107,7 +102,7 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
stScore: stItem.score || '0',
|
||||
subIndicator: ndItem.subIndicator || '',
|
||||
ndScore: ndItem.subScore || '0',
|
||||
isStar: ndItem.starIndicator || '',
|
||||
isStar: ndItem.isStar || '',
|
||||
score: ndItem.scoreNum || '',
|
||||
remark: ndItem.remark || '',
|
||||
});
|
||||
@ -125,15 +120,18 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
// 将表格数据转换回API格式
|
||||
const convertTableDataToApiData = (tableData: TableRowItem[]): any[] => {
|
||||
// 按一级指标分组
|
||||
const groupedByLevel1 = tableData.reduce((acc: Record<string, TableRowItem[]>, item: TableRowItem) => {
|
||||
const groupKey = item.baseIndicator || `empty-${item.key}`;
|
||||
const groupedByLevel1 = tableData.reduce(
|
||||
(acc: Record<string, TableRowItem[]>, item: TableRowItem) => {
|
||||
const groupKey = item.baseIndicator || `empty-${item.key}`;
|
||||
|
||||
if (!acc[groupKey]) {
|
||||
acc[groupKey] = [];
|
||||
}
|
||||
acc[groupKey].push(item);
|
||||
return acc;
|
||||
}, {});
|
||||
if (!acc[groupKey]) {
|
||||
acc[groupKey] = [];
|
||||
}
|
||||
acc[groupKey].push(item);
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
// 转换为API需要的格式
|
||||
return Object.keys(groupedByLevel1).map((groupKey, stIndex) => {
|
||||
@ -152,9 +150,10 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
subScore: item.ndScore || '0',
|
||||
starIndicator: item.isStar || '0',
|
||||
scoreNum: item.score || '',
|
||||
remark: item.remark || ''
|
||||
remark: item.remark || '',
|
||||
isStar: item.isStar,
|
||||
};
|
||||
})
|
||||
}),
|
||||
};
|
||||
});
|
||||
};
|
||||
@ -220,7 +219,9 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
if (!record.baseIndicator) return text || '-';
|
||||
|
||||
// 查找相同baseIndicator的所有项
|
||||
const level1Items = dataSource.filter((item) => item.baseIndicator === record.baseIndicator);
|
||||
const level1Items = dataSource.filter(
|
||||
(item) => item.baseIndicator === record.baseIndicator,
|
||||
);
|
||||
const index = level1Items.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index === 0) {
|
||||
@ -245,7 +246,9 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
if (!record.baseIndicator) return text || '-';
|
||||
|
||||
// 查找相同baseIndicator的所有项
|
||||
const level1Items = dataSource.filter((item) => item.baseIndicator === record.baseIndicator);
|
||||
const level1Items = dataSource.filter(
|
||||
(item) => item.baseIndicator === record.baseIndicator,
|
||||
);
|
||||
const index = level1Items.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index === 0) {
|
||||
@ -270,7 +273,9 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
if (!record.baseIndicator) return text || '0';
|
||||
|
||||
// 查找相同baseIndicator的所有项
|
||||
const level1Items = dataSource.filter((item) => item.baseIndicator === record.baseIndicator);
|
||||
const level1Items = dataSource.filter(
|
||||
(item) => item.baseIndicator === record.baseIndicator,
|
||||
);
|
||||
const index = level1Items.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index === 0) {
|
||||
@ -296,7 +301,15 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
key: 'subIndicator',
|
||||
align: 'center' as const,
|
||||
width: 200,
|
||||
render: (text: string) => text || '-',
|
||||
render: (text: string, record: TableRowItem) => (
|
||||
<>
|
||||
{/* 是否必填 1是 0否 */}
|
||||
{record.isStar && record.isStar === '1' && (
|
||||
<span className="required">*</span>
|
||||
)}
|
||||
{text || '-'}
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'supplierEvaluateScore.scoreTable.subScore' }),
|
||||
@ -317,14 +330,18 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
return text || '-';
|
||||
}
|
||||
return (
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={parseFloat(record.ndScore) || 0}
|
||||
value={text ? parseFloat(String(text)) : undefined}
|
||||
onChange={(val) => handleInputChange(val, record, 'score')}
|
||||
style={{ width: '100%' }}
|
||||
placeholder={intl.formatMessage({ id: 'supplierEvaluateScore.scoreTable.placeholder.score' })}
|
||||
/>
|
||||
<>
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={parseFloat(record.ndScore) || 0}
|
||||
value={text ? parseFloat(String(text)) : undefined}
|
||||
onChange={(val) => handleInputChange(val, record, 'score')}
|
||||
style={{ width: '100%' }}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'supplierEvaluateScore.scoreTable.placeholder.score',
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
},
|
||||
},
|
||||
@ -345,7 +362,9 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
<TextArea
|
||||
value={text}
|
||||
onChange={(e) => handleInputChange(e.target.value, record, 'remark')}
|
||||
placeholder={intl.formatMessage({ id: 'supplierEvaluateScore.scoreTable.placeholder.remark' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'supplierEvaluateScore.scoreTable.placeholder.remark',
|
||||
})}
|
||||
autoSize={{ minRows: 1, maxRows: 3 }}
|
||||
/>
|
||||
);
|
||||
@ -366,7 +385,9 @@ const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
size="middle"
|
||||
loading={loading}
|
||||
scroll={{ x: 'max-content' }}
|
||||
locale={{ emptyText: intl.formatMessage({ id: 'supplierEvaluateScore.scoreTable.emptyText' }) }}
|
||||
locale={{
|
||||
emptyText: intl.formatMessage({ id: 'supplierEvaluateScore.scoreTable.emptyText' }),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -14,7 +14,11 @@
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.require{
|
||||
color: red;
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.content-area {
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ interface ScoreFormItem {
|
||||
description: string;
|
||||
examineResult: string;
|
||||
remark: string;
|
||||
isStar: string; // 是否为星号项
|
||||
}
|
||||
|
||||
const SupplierAnnualReviewScore: React.FC = () => {
|
||||
@ -76,7 +77,9 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
message.warning(intl.formatMessage({ id: 'supplierAnnualReview.score.noScoreItemData' }));
|
||||
}
|
||||
} else {
|
||||
message.error(res.message || intl.formatMessage({ id: 'supplierAnnualReview.detail.getDetailFailed' }));
|
||||
message.error(
|
||||
res.message || intl.formatMessage({ id: 'supplierAnnualReview.detail.getDetailFailed' }),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取审查详情失败:', error);
|
||||
@ -128,7 +131,9 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
message.success(intl.formatMessage({ id: 'supplierAnnualReview.score.submitSuccess' }));
|
||||
history.goBack();
|
||||
} else {
|
||||
message.error(res.message || intl.formatMessage({ id: 'supplierAnnualReview.score.submitFailed' }));
|
||||
message.error(
|
||||
res.message || intl.formatMessage({ id: 'supplierAnnualReview.score.submitFailed' }),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('评审提交失败:', error);
|
||||
@ -142,6 +147,21 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
try {
|
||||
// 表单验证
|
||||
await form.validateFields();
|
||||
const formValues = form.getFieldsValue();
|
||||
const scoreVoList = scoreItems.map((item) => ({
|
||||
id: item.id,
|
||||
name: item.itemName,
|
||||
description: item.description,
|
||||
examineResult: formValues[`examineResult_${item.id}`],
|
||||
remark: formValues[`remark_${item.id}`] || '',
|
||||
isStar: item.isStar, // 是否为星号项
|
||||
}));
|
||||
// 检查所有星号项是否必填
|
||||
const validateIsStar = scoreVoList.some((item) => item.isStar == '1' && !item.examineResult);
|
||||
if (validateIsStar) {
|
||||
message.warning('请填写所有星号项的评审结果!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 确认提交
|
||||
Modal.confirm({
|
||||
@ -159,7 +179,8 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
|
||||
// 获取状态标签
|
||||
const getStatusTag = (status: string | undefined, statusName: string | undefined) => {
|
||||
if (!status) return <Tag>{intl.formatMessage({ id: 'supplierAnnualReview.common.unknownStatus' })}</Tag>;
|
||||
if (!status)
|
||||
return <Tag>{intl.formatMessage({ id: 'supplierAnnualReview.common.unknownStatus' })}</Tag>;
|
||||
const color =
|
||||
AnnualReviewStatusColor[status as keyof typeof AnnualReviewStatusColor] || 'default';
|
||||
const text =
|
||||
@ -183,23 +204,47 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
<Spin spinning={loading}>
|
||||
{reviewDetail ? (
|
||||
<>
|
||||
<Card title={intl.formatMessage({ id: 'supplierAnnualReview.score.basicInfo' })} bordered={false} className={styles['detail-card']}>
|
||||
<Card
|
||||
title={intl.formatMessage({ id: 'supplierAnnualReview.score.basicInfo' })}
|
||||
bordered={false}
|
||||
className={styles['detail-card']}
|
||||
>
|
||||
<Descriptions column={2} bordered>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.reviewTheme' })}>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.reviewTheme' })}
|
||||
>
|
||||
{reviewDetail.annualreviewTheme}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.supplierName' })}>
|
||||
<a onClick={() => supplierDetailModal?.(reviewDetail.supplierId)}>{reviewDetail.name}</a>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.supplierName' })}
|
||||
>
|
||||
<a onClick={() => supplierDetailModal?.(reviewDetail.supplierId)}>
|
||||
{reviewDetail.name}
|
||||
</a>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.department' })}>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.department' })}
|
||||
>
|
||||
{reviewDetail.deptName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.reviewer' })}>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.reviewer' })}
|
||||
>
|
||||
{reviewDetail.reviewerName || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.startTime' })}>{reviewDetail.startTime}</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.endTime' })}>{reviewDetail.endTime}</Descriptions.Item>
|
||||
<Descriptions.Item label={intl.formatMessage({ id: 'supplierAnnualReview.list.status' })}>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.startTime' })}
|
||||
>
|
||||
{reviewDetail.startTime}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.endTime' })}
|
||||
>
|
||||
{reviewDetail.endTime}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={intl.formatMessage({ id: 'supplierAnnualReview.list.status' })}
|
||||
>
|
||||
{reviewDetail.reviewStatusName || '-'}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
@ -207,7 +252,11 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card title={intl.formatMessage({ id: 'supplierAnnualReview.score.examineResult' })} bordered={false} className={styles['detail-card']}>
|
||||
<Card
|
||||
title={intl.formatMessage({ id: 'supplierAnnualReview.score.examineResult' })}
|
||||
bordered={false}
|
||||
className={styles['detail-card']}
|
||||
>
|
||||
<Form form={form} layout="vertical" className={styles['score-form']}>
|
||||
{scoreItems.length > 0 ? (
|
||||
<Table
|
||||
@ -221,20 +270,22 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
title: intl.formatMessage({ id: 'supplierAnnualReview.score.scoreItem' }),
|
||||
dataIndex: 'itemName',
|
||||
width: '15%',
|
||||
render: (text, record) => (
|
||||
<div>
|
||||
{record.isStar == '1' && <span className={styles['require']}>*</span>}
|
||||
{text}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
// {
|
||||
// title: intl.formatMessage({ id: 'supplierAnnualReview.score.scoreItemDesc' }),
|
||||
// dataIndex: 'description',
|
||||
// width: '25%',
|
||||
// },
|
||||
{
|
||||
title: intl.formatMessage({ id: 'supplierAnnualReview.detail.examineResult' }),
|
||||
title: intl.formatMessage({
|
||||
id: 'supplierAnnualReview.detail.examineResult',
|
||||
}),
|
||||
dataIndex: 'examineResult',
|
||||
width: '25%',
|
||||
render: (_, record) => (
|
||||
<Form.Item
|
||||
name={`examineResult_${record.id}`}
|
||||
rules={[{ required: true, message: intl.formatMessage({ id: 'supplierAnnualReview.score.pleaseSelectResult' }) }]}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Radio.Group>
|
||||
@ -249,17 +300,18 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: intl.formatMessage({ id: 'supplierAnnualReview.score.examineRemark' }),
|
||||
title: intl.formatMessage({
|
||||
id: 'supplierAnnualReview.score.examineRemark',
|
||||
}),
|
||||
dataIndex: 'remark',
|
||||
width: '35%',
|
||||
render: (_, record) => (
|
||||
<Form.Item
|
||||
name={`remark_${record.id}`}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
<Form.Item name={`remark_${record.id}`} style={{ marginBottom: 0 }}>
|
||||
<TextArea
|
||||
rows={2}
|
||||
placeholder={intl.formatMessage({ id: 'supplierAnnualReview.score.pleaseInputRemark' })}
|
||||
placeholder={intl.formatMessage({
|
||||
id: 'supplierAnnualReview.score.pleaseInputRemark',
|
||||
})}
|
||||
maxLength={200}
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -268,7 +320,11 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<Empty description={intl.formatMessage({ id: 'supplierAnnualReview.score.noScoreItemData' })} />
|
||||
<Empty
|
||||
description={intl.formatMessage({
|
||||
id: 'supplierAnnualReview.score.noScoreItemData',
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className={styles['score-actions']}>
|
||||
@ -285,7 +341,11 @@ const SupplierAnnualReviewScore: React.FC = () => {
|
||||
</Card>
|
||||
</>
|
||||
) : (
|
||||
!loading && <Empty description={intl.formatMessage({ id: 'supplierAnnualReview.detail.noDetailData' })} />
|
||||
!loading && (
|
||||
<Empty
|
||||
description={intl.formatMessage({ id: 'supplierAnnualReview.detail.noDetailData' })}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</Spin>
|
||||
</Card>
|
||||
|
@ -84,10 +84,10 @@ const SupplierEvaluateScoreDetail: React.FC = () => {
|
||||
id: subItem.id,
|
||||
subIndicator: subItem.subIndicator,
|
||||
subScore: subItem.subScore, // 二级指标标准分值
|
||||
isStar: subItem.starIndicator,
|
||||
scoreNum: subItem.score || '', // 实际评分值:使用API返回的score字段
|
||||
score: subItem.score || '', // 组件内部显示用
|
||||
remark: subItem.remark || '',
|
||||
isStar: subItem.isStar, // 是否必填
|
||||
};
|
||||
})
|
||||
.filter(Boolean) || [],
|
||||
@ -151,12 +151,12 @@ const SupplierEvaluateScoreDetail: React.FC = () => {
|
||||
const hasEmptyScore = scoreData.some((item) =>
|
||||
item.indicatorNdList.some((subItem: any) => {
|
||||
// 使用scoreNum字段检查是否已评分
|
||||
return !subItem.scoreNum && subItem.scoreNum !== 0;
|
||||
return !subItem.scoreNum && subItem.scoreNum !== 0 && subItem.isStar === '1'; // 只检查必填项
|
||||
}),
|
||||
);
|
||||
|
||||
if (hasEmptyScore) {
|
||||
message.warning(intl.formatMessage({ id: 'supplierEvaluateScore.message.emptyScore' }));
|
||||
message.warning("请填写所有必填项的评分!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,7 @@ const handleDisableTemplate = (id: string) => {
|
||||
name="tenantName"
|
||||
label={intl.formatMessage({ id: 'supplierTemplateManage.column.tenantName' })}
|
||||
>
|
||||
<AccessDepartmentSelect placeholder={'请选择准入单位'} />
|
||||
<AccessDepartmentSelect placeholder={'请选择创建单位'} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="categoryId"
|
||||
|
Reference in New Issue
Block a user