对接评价结果接口
This commit is contained in:
@ -75,6 +75,15 @@ export default [
|
||||
},
|
||||
component: '@/pages/supplierEvaluateManage/supplierTemplateManage/supplierTemplateManageDetail',
|
||||
},
|
||||
{
|
||||
name: 'supplierEvaluateRuleManage',
|
||||
path: 'supplierEvaluateRuleManage',
|
||||
meta: {
|
||||
title: '评价规则管理',
|
||||
icon: 'icon-liebiaomoshi',
|
||||
},
|
||||
component: '@/pages/supplierEvaluateManage/supplierEvaluateRuleManage/supplierEvaluateRuleManage',
|
||||
},
|
||||
{
|
||||
name: 'supplierTaskManage',
|
||||
path: 'supplierTaskManage',
|
||||
@ -225,7 +234,7 @@ export default [
|
||||
path: '/backend',
|
||||
name: 'backend',
|
||||
icon: 'smile',
|
||||
component: '@/layouts/MainLayout',
|
||||
component: '@/layouts/MainLayout',
|
||||
routes: [
|
||||
{
|
||||
path: '/backend/workbenches',
|
||||
@ -257,7 +266,7 @@ export default [
|
||||
path: '/informationRetrieval',
|
||||
name: 'informationRetrieval',
|
||||
icon: 'smile',
|
||||
component: '@/layouts/MainLayout',
|
||||
component: '@/layouts/MainLayout',
|
||||
routes: [
|
||||
{
|
||||
path: '/informationRetrieval/registrationQuery',
|
||||
@ -283,7 +292,7 @@ export default [
|
||||
path: '/informationManagement',
|
||||
name: 'informationManagement',
|
||||
icon: 'smile',
|
||||
component: '@/layouts/MainLayout',
|
||||
component: '@/layouts/MainLayout',
|
||||
routes: [
|
||||
{
|
||||
path: '/informationManagement/SupplierRegisterAgent',
|
||||
@ -309,7 +318,7 @@ export default [
|
||||
path: '/admission',
|
||||
name: 'admission',
|
||||
icon: 'smile',
|
||||
component: '@/layouts/MainLayout',
|
||||
component: '@/layouts/MainLayout',
|
||||
routes: [
|
||||
{
|
||||
path: '/admission/admissionManagement',
|
||||
@ -347,7 +356,7 @@ export default [
|
||||
path: '/category',
|
||||
name: 'category',
|
||||
icon: 'smile',
|
||||
component: '@/layouts/MainLayout',
|
||||
component: '@/layouts/MainLayout',
|
||||
routes: [
|
||||
{
|
||||
path: '/category/category-manage',
|
||||
@ -385,7 +394,7 @@ export default [
|
||||
path: '/supplierBlacklist',
|
||||
name: 'supplierBlacklist',
|
||||
icon: 'smile',
|
||||
component: '@/layouts/MainLayout',
|
||||
component: '@/layouts/MainLayout',
|
||||
routes: [
|
||||
{
|
||||
path: '/supplierBlacklist/manage',
|
||||
|
@ -454,7 +454,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
|
||||
key: 'index',
|
||||
width: 50,
|
||||
render: (_: any, record: TableRowItem, index: number) => {
|
||||
return renderWithRowSpan(index + 1, record, (cellContent) => cellContent);
|
||||
return <>{index + 1}</>;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
90
src/components/ScoreEvaluationTable/README.md
Normal file
90
src/components/ScoreEvaluationTable/README.md
Normal file
@ -0,0 +1,90 @@
|
||||
# ScoreEvaluationTable 评分表格组件
|
||||
|
||||
## 组件介绍
|
||||
|
||||
ScoreEvaluationTable 是一个用于展示和填写供应商评价得分的表格组件。该组件基于 EvaluateTemplateTable 组件扩展,在二级指标中添加了评分列和说明列,可用于评价结果的展示和评分录入。
|
||||
|
||||
## 功能特点
|
||||
|
||||
- 支持一级指标和二级指标的层级展示
|
||||
- 支持评分和评分说明的录入和展示
|
||||
- 支持详情模式(只读)和编辑模式
|
||||
- 支持数据格式的自动转换
|
||||
- 自动合并一级指标单元格
|
||||
|
||||
## 使用方法
|
||||
|
||||
```tsx
|
||||
import ScoreEvaluationTable from '@/components/ScoreEvaluationTable';
|
||||
|
||||
// 示例数据
|
||||
const evaluationData = [
|
||||
{
|
||||
id: '1',
|
||||
baseIndicator: '质量管理',
|
||||
descIndicator: '质量管理体系完善程度',
|
||||
score: '30',
|
||||
indicatorNdList: [
|
||||
{
|
||||
id: '1-1',
|
||||
subIndicator: '质量管理体系认证',
|
||||
score: '10',
|
||||
isStar: '0',
|
||||
actualScore: '8',
|
||||
remark: '已获得ISO9001认证'
|
||||
},
|
||||
{
|
||||
id: '1-2',
|
||||
subIndicator: '质量控制流程',
|
||||
score: '10',
|
||||
isStar: '1',
|
||||
actualScore: '9',
|
||||
remark: '质量控制流程完善'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// 详情模式(只读)
|
||||
<ScoreEvaluationTable
|
||||
value={evaluationData}
|
||||
isDetail={true}
|
||||
/>
|
||||
|
||||
// 编辑模式
|
||||
<ScoreEvaluationTable
|
||||
value={evaluationData}
|
||||
onChange={(newData) => console.log(newData)}
|
||||
isDetail={false}
|
||||
/>
|
||||
```
|
||||
|
||||
## 属性说明
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| value | array | [] | 表格数据,应符合API返回的评价指标数据结构 |
|
||||
| onChange | function | - | 数据变更回调函数 |
|
||||
| isDetail | boolean | false | 是否为详情模式(只读) |
|
||||
| loading | boolean | false | 表格加载状态 |
|
||||
|
||||
## 数据格式
|
||||
|
||||
组件接受的数据格式应为一个数组,每个元素代表一个一级指标,包含以下字段:
|
||||
|
||||
```typescript
|
||||
interface IndicatorItem {
|
||||
id?: string; // 一级指标ID
|
||||
baseIndicator: string; // 一级指标名称
|
||||
descIndicator?: string; // 一级指标说明
|
||||
score: string; // 一级指标分值
|
||||
indicatorNdList: { // 二级指标列表
|
||||
id?: string; // 二级指标ID
|
||||
subIndicator: string; // 二级指标名称
|
||||
score: string; // 二级指标分值
|
||||
isStar?: string; // 是否为星号项
|
||||
actualScore?: string; // 实际评分
|
||||
remark?: string; // 评分说明
|
||||
}[];
|
||||
}
|
||||
```
|
@ -0,0 +1,35 @@
|
||||
// 评分表格样式
|
||||
.score-evaluation-table {
|
||||
margin-bottom: 16px;
|
||||
|
||||
.ant-table-thead > tr > th {
|
||||
background-color: #f5f5f5;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ant-table-tbody > tr > td {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.ellipsis-text {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// 评分列样式
|
||||
.low-score {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.high-score {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
// 星号项样式
|
||||
.star-item {
|
||||
color: #faad14;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
370
src/components/ScoreEvaluationTable/ScoreEvaluationTable.tsx
Normal file
370
src/components/ScoreEvaluationTable/ScoreEvaluationTable.tsx
Normal file
@ -0,0 +1,370 @@
|
||||
// 供应商评价得分表格组件
|
||||
// 用于展示和填写供应商评价得分,基于EvaluateTemplateTable组件扩展
|
||||
// 在二级指标中添加了评分列和说明列
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Table,
|
||||
Input,
|
||||
InputNumber,
|
||||
Typography,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import './ScoreEvaluationTable.less';
|
||||
|
||||
const { Text } = Typography;
|
||||
const { TextArea } = Input;
|
||||
|
||||
/**
|
||||
* 评分表格组件属性
|
||||
*/
|
||||
interface ScoreEvaluationTableProps {
|
||||
/**
|
||||
* 表格数据,应符合API返回的评价指标数据结构
|
||||
*/
|
||||
value?: any[];
|
||||
/**
|
||||
* 数据变更回调函数
|
||||
*/
|
||||
onChange?: (value: any[]) => void;
|
||||
/**
|
||||
* 是否为详情模式(只读)
|
||||
*/
|
||||
isDetail?: boolean;
|
||||
/**
|
||||
* 表格加载状态
|
||||
*/
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部使用的表格行数据结构
|
||||
*/
|
||||
interface TableRowItem {
|
||||
key: string;
|
||||
stId?: string; // 一级指标ID
|
||||
ndId?: string; // 二级指标ID
|
||||
baseIndicator: string; // 一级指标名称
|
||||
descIndicator?: string; // 一级指标说明
|
||||
stScore: string; // 一级指标分值
|
||||
subIndicator: string; // 二级指标名称
|
||||
ndScore: string; // 二级指标分值
|
||||
isStar?: string; // 是否为星号项
|
||||
score?: string | number; // 实际评分
|
||||
remark?: string; // 评分说明
|
||||
}
|
||||
|
||||
/**
|
||||
* 供应商评价得分表格组件
|
||||
* 用于展示和填写供应商评价得分,支持详情模式和编辑模式
|
||||
*/
|
||||
const ScoreEvaluationTable: React.FC<ScoreEvaluationTableProps> = ({
|
||||
value = [],
|
||||
onChange,
|
||||
isDetail = false,
|
||||
loading = false,
|
||||
}) => {
|
||||
// 表格数据源
|
||||
const [dataSource, setDataSource] = useState<TableRowItem[]>([]);
|
||||
|
||||
// 将API数据转换为表格数据
|
||||
const convertApiDataToTableData = (apiData: any[]): TableRowItem[] => {
|
||||
// 检查数据是否已经是扁平化的表格数据格式
|
||||
if (apiData.length > 0 && 'subIndicator' in apiData[0]) {
|
||||
return apiData as TableRowItem[];
|
||||
}
|
||||
|
||||
// 如果是嵌套结构,需要扁平化处理
|
||||
if (apiData.length > 0 && 'indicatorNdList' in apiData[0]) {
|
||||
const flattenedData: TableRowItem[] = [];
|
||||
|
||||
apiData.forEach((stItem: any, stIndex: number) => {
|
||||
if (!stItem.indicatorNdList || stItem.indicatorNdList.length === 0) {
|
||||
// 如果没有二级指标,添加一个空的二级指标行
|
||||
flattenedData.push({
|
||||
key: `${stItem.id || stIndex}-0`,
|
||||
stId: stItem.id,
|
||||
baseIndicator: stItem.baseIndicator || '',
|
||||
descIndicator: stItem.descIndicator || '',
|
||||
stScore: stItem.score || '0',
|
||||
subIndicator: '',
|
||||
ndScore: '0',
|
||||
score: stItem.actualScore || '',
|
||||
remark: stItem.remark || '',
|
||||
});
|
||||
} else {
|
||||
// 处理二级指标
|
||||
stItem.indicatorNdList.forEach((ndItem: any, ndIndex: number) => {
|
||||
flattenedData.push({
|
||||
key: `${stItem.id || stIndex}-${ndItem.id || ndIndex}`,
|
||||
stId: stItem.id,
|
||||
ndId: ndItem.id,
|
||||
baseIndicator: stItem.baseIndicator || '',
|
||||
descIndicator: stItem.descIndicator || '',
|
||||
stScore: stItem.score || '0',
|
||||
subIndicator: ndItem.subIndicator || '',
|
||||
ndScore: ndItem.score || '0',
|
||||
isStar: ndItem.isStar || '',
|
||||
score: ndItem.actualScore || '',
|
||||
remark: ndItem.remark || '',
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return flattenedData;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// 将表格数据转换回API格式
|
||||
const convertTableDataToApiData = (tableData: TableRowItem[]): any[] => {
|
||||
// 按一级指标分组
|
||||
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;
|
||||
}, {});
|
||||
|
||||
// 转换为API需要的格式
|
||||
return Object.keys(groupedByLevel1).map((groupKey, stIndex) => {
|
||||
const level1Items = groupedByLevel1[groupKey];
|
||||
const firstItem = level1Items[0];
|
||||
|
||||
return {
|
||||
id: firstItem.stId || `temp-st-${stIndex}`,
|
||||
baseIndicator: firstItem.baseIndicator || '',
|
||||
descIndicator: firstItem.descIndicator || '',
|
||||
score: firstItem.stScore || '0',
|
||||
indicatorNdList: level1Items.map((item, ndIndex) => {
|
||||
return {
|
||||
id: item.ndId || `temp-nd-${stIndex}-${ndIndex}`,
|
||||
subIndicator: item.subIndicator || '',
|
||||
score: item.ndScore || '0',
|
||||
isStar: item.isStar || '',
|
||||
actualScore: item.score || '',
|
||||
remark: item.remark || ''
|
||||
};
|
||||
})
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 单独处理value变化
|
||||
useEffect(() => {
|
||||
if (value && value.length > 0) {
|
||||
const tableData = convertApiDataToTableData(value);
|
||||
setDataSource(tableData);
|
||||
} else {
|
||||
setDataSource([]);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
// 更新数据源
|
||||
const updateDataSource = (newData: TableRowItem[]) => {
|
||||
setDataSource(newData);
|
||||
if (onChange) {
|
||||
// 转换回API格式再传递给父组件
|
||||
const apiData = convertTableDataToApiData(newData);
|
||||
onChange(apiData);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理输入变化
|
||||
const handleInputChange = (val: any, record: TableRowItem, field: string) => {
|
||||
const newData = [...dataSource];
|
||||
const index = newData.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index > -1) {
|
||||
newData[index] = { ...newData[index], [field]: val };
|
||||
updateDataSource(newData);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取一级指标的行数
|
||||
const getLevel1RowSpan = (baseIndicator: string) => {
|
||||
if (!baseIndicator) return 1;
|
||||
return dataSource.filter((item) => item.baseIndicator === baseIndicator).length;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '一级指标',
|
||||
children: [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
align: 'center' as const,
|
||||
key: 'index',
|
||||
width: 50,
|
||||
render: (_: any, record: TableRowItem, index: number) => {
|
||||
return <>{index + 1}</>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '基本指标',
|
||||
align: 'center' as const,
|
||||
dataIndex: 'baseIndicator',
|
||||
key: 'baseIndicator',
|
||||
width: 150,
|
||||
render: (text: string, record: TableRowItem) => {
|
||||
if (!record.baseIndicator) return text || '-';
|
||||
|
||||
// 查找相同baseIndicator的所有项
|
||||
const level1Items = dataSource.filter((item) => item.baseIndicator === record.baseIndicator);
|
||||
const index = level1Items.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index === 0) {
|
||||
return {
|
||||
children: text || '-',
|
||||
props: { rowSpan: level1Items.length },
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: { rowSpan: 0 },
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '指标说明',
|
||||
align: 'center' as const,
|
||||
dataIndex: 'descIndicator',
|
||||
key: 'descIndicator',
|
||||
width: 200,
|
||||
render: (text: string, record: TableRowItem) => {
|
||||
if (!record.baseIndicator) return text || '-';
|
||||
|
||||
// 查找相同baseIndicator的所有项
|
||||
const level1Items = dataSource.filter((item) => item.baseIndicator === record.baseIndicator);
|
||||
const index = level1Items.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index === 0) {
|
||||
return {
|
||||
children: text || '-',
|
||||
props: { rowSpan: level1Items.length },
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: { rowSpan: 0 },
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
align: 'center' as const,
|
||||
dataIndex: 'stScore',
|
||||
key: 'stScore',
|
||||
width: 80,
|
||||
render: (text: string, record: TableRowItem) => {
|
||||
if (!record.baseIndicator) return text || '0';
|
||||
|
||||
// 查找相同baseIndicator的所有项
|
||||
const level1Items = dataSource.filter((item) => item.baseIndicator === record.baseIndicator);
|
||||
const index = level1Items.findIndex((item) => item.key === record.key);
|
||||
|
||||
if (index === 0) {
|
||||
return {
|
||||
children: text || '0',
|
||||
props: { rowSpan: level1Items.length },
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: { rowSpan: 0 },
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '二级指标',
|
||||
children: [
|
||||
{
|
||||
title: '细分指标',
|
||||
dataIndex: 'subIndicator',
|
||||
key: 'subIndicator',
|
||||
align: 'center' as const,
|
||||
width: 200,
|
||||
render: (text: string) => text || '-',
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
dataIndex: 'ndScore',
|
||||
key: 'ndScore',
|
||||
width: 80,
|
||||
align: 'center' as const,
|
||||
render: (text: string) => text || '0',
|
||||
},
|
||||
{
|
||||
title: '评分',
|
||||
dataIndex: 'score',
|
||||
key: 'score',
|
||||
width: 100,
|
||||
align: 'center' as const,
|
||||
render: (text: string | number, record: TableRowItem) => {
|
||||
if (isDetail) {
|
||||
return text || '-';
|
||||
}
|
||||
return (
|
||||
<InputNumber
|
||||
min={0}
|
||||
max={parseFloat(record.ndScore) || 100}
|
||||
value={text ? parseFloat(String(text)) : undefined}
|
||||
onChange={(val) => handleInputChange(val, record, 'score')}
|
||||
style={{ width: '100%' }}
|
||||
placeholder="请输入评分"
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '评分说明',
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
width: 200,
|
||||
render: (text: string, record: TableRowItem) => {
|
||||
if (isDetail) {
|
||||
return (
|
||||
<Tooltip title={text}>
|
||||
<div className="ellipsis-text">{text || '-'}</div>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<TextArea
|
||||
value={text}
|
||||
onChange={(e) => handleInputChange(e.target.value, record, 'remark')}
|
||||
placeholder="请输入评分说明"
|
||||
autoSize={{ minRows: 1, maxRows: 3 }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="score-evaluation-table">
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={dataSource}
|
||||
pagination={false}
|
||||
bordered
|
||||
rowKey="key"
|
||||
size="middle"
|
||||
loading={loading}
|
||||
scroll={{ x: 'max-content' }}
|
||||
locale={{ emptyText: '无数据' }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScoreEvaluationTable;
|
3
src/components/ScoreEvaluationTable/index.ts
Normal file
3
src/components/ScoreEvaluationTable/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import ScoreEvaluationTable from './ScoreEvaluationTable';
|
||||
|
||||
export default ScoreEvaluationTable;
|
@ -35,22 +35,3 @@ export const ApprovalResultColor = {
|
||||
[ApprovalResult.APPROVED]: 'green',
|
||||
[ApprovalResult.REJECTED]: 'red',
|
||||
};
|
||||
|
||||
// 导入评价等级
|
||||
import { EvaluateLevel, EvaluateLevelText, EvaluateLevelColor } from './supplierTemplateDict';
|
||||
|
||||
// 重新导出评价等级
|
||||
export { EvaluateLevel, EvaluateLevelText, EvaluateLevelColor };
|
||||
|
||||
// 评价分数对应等级
|
||||
export const getEvaluateLevel = (score: number): string => {
|
||||
if (score >= 90) {
|
||||
return EvaluateLevel.EXCELLENT;
|
||||
} else if (score >= 80) {
|
||||
return EvaluateLevel.GOOD;
|
||||
} else if (score >= 70) {
|
||||
return EvaluateLevel.AVERAGE;
|
||||
} else {
|
||||
return EvaluateLevel.POOR;
|
||||
}
|
||||
};
|
||||
|
@ -31,14 +31,6 @@ export const TemplateStatusColor = {
|
||||
[TemplateStatus.DISABLED]: 'red',
|
||||
};
|
||||
|
||||
// 评价等级
|
||||
export const EvaluateLevel = {
|
||||
EXCELLENT: 'excellent', // 优秀
|
||||
GOOD: 'good', // 良好
|
||||
AVERAGE: 'average', // 一般
|
||||
POOR: 'poor', // 较差
|
||||
};
|
||||
|
||||
// 是否设置星号项
|
||||
export const StarLevel = {
|
||||
NO: '0', // 否
|
||||
@ -50,20 +42,6 @@ export const StarLevelText = {
|
||||
[StarLevel.YES]: '是',
|
||||
};
|
||||
|
||||
export const EvaluateLevelText = {
|
||||
[EvaluateLevel.EXCELLENT]: 'A',
|
||||
[EvaluateLevel.GOOD]: 'B',
|
||||
[EvaluateLevel.AVERAGE]: 'C',
|
||||
[EvaluateLevel.POOR]: 'D',
|
||||
};
|
||||
|
||||
export const EvaluateLevelColor = {
|
||||
[EvaluateLevel.EXCELLENT]: 'green',
|
||||
[EvaluateLevel.GOOD]: 'blue',
|
||||
[EvaluateLevel.AVERAGE]: 'orange',
|
||||
[EvaluateLevel.POOR]: 'red',
|
||||
};
|
||||
|
||||
// 指标添加选项
|
||||
export enum IndicatorAddOption {
|
||||
CAN_ADD = '0',
|
||||
|
@ -1,13 +1,24 @@
|
||||
import login from './en-US/login';
|
||||
import register from './en-US/register';
|
||||
import menu from './en-US/menu';
|
||||
import workbench from './en-US/workbench';
|
||||
import globalModal from './en-US/globalModal';
|
||||
import login from './en-US/login';
|
||||
import menu from './en-US/menu';
|
||||
import register from './en-US/register';
|
||||
import workbench from './en-US/workbench';
|
||||
import supplierEvaluateRuleManage from './en-US/supplierEvaluateRuleManage';
|
||||
|
||||
export default {
|
||||
...login,
|
||||
...register,
|
||||
...menu,
|
||||
...workbench,
|
||||
'navBar.lang': 'Languages',
|
||||
'layout.user.link.help': 'Help',
|
||||
'layout.user.link.privacy': 'Privacy',
|
||||
'layout.user.link.terms': 'Terms',
|
||||
'app.home.introduce': 'introduce',
|
||||
'app.forms.basic.title': 'Basic form',
|
||||
'app.forms.basic.description':
|
||||
'Form pages are used to collect or verify information to users, and basic forms are common in scenarios where there are fewer data items.',
|
||||
'登录/注册': 'Login/Register',
|
||||
...globalModal,
|
||||
...login,
|
||||
...menu,
|
||||
...register,
|
||||
...workbench,
|
||||
...supplierEvaluateRuleManage,
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ export default {
|
||||
'menu.模板管理': 'Template Management',
|
||||
'menu.模板管理新增': 'Add Template',
|
||||
'menu.模板管理详情': 'Template Detail',
|
||||
'menu.评价规则管理': 'Evaluation Rule Management',
|
||||
'menu.任务管理': 'Task Management',
|
||||
'menu.任务管理新增': 'Add Task',
|
||||
'menu.评价打分': 'Evaluation Scoring',
|
||||
@ -22,7 +23,7 @@ export default {
|
||||
'menu.年审任务管理': 'Annual Review Task Management',
|
||||
'menu.年度查询': 'Annual Query',
|
||||
'menu.年审结果': 'Annual Review Results',
|
||||
|
||||
|
||||
//供应商
|
||||
'menu.admit': 'admit',
|
||||
'menu.dict': 'dict',
|
||||
|
52
src/locales/en-US/supplierEvaluateRuleManage.ts
Normal file
52
src/locales/en-US/supplierEvaluateRuleManage.ts
Normal file
@ -0,0 +1,52 @@
|
||||
export default {
|
||||
'supplierEvaluateRuleManage.title': 'Evaluation Rule Management',
|
||||
'supplierEvaluateRuleManage.add': 'Add',
|
||||
'supplierEvaluateRuleManage.edit': 'Edit',
|
||||
'supplierEvaluateRuleManage.delete': 'Delete',
|
||||
'supplierEvaluateRuleManage.confirm': 'Confirm',
|
||||
'supplierEvaluateRuleManage.cancel': 'Cancel',
|
||||
'supplierEvaluateRuleManage.submit': 'Submit',
|
||||
|
||||
// 表格列名
|
||||
'supplierEvaluateRuleManage.column.index': 'No.',
|
||||
'supplierEvaluateRuleManage.column.levelName': 'Level Name',
|
||||
'supplierEvaluateRuleManage.column.ratingName': 'Rating Name',
|
||||
'supplierEvaluateRuleManage.column.scoreRange': 'Score Range',
|
||||
'supplierEvaluateRuleManage.column.remark': 'Remark',
|
||||
'supplierEvaluateRuleManage.column.action': 'Action',
|
||||
|
||||
// 表单字段
|
||||
'supplierEvaluateRuleManage.form.levelName': 'Level Name',
|
||||
'supplierEvaluateRuleManage.form.levelName.placeholder': 'Please enter level name, such as A, B, C, etc.',
|
||||
'supplierEvaluateRuleManage.form.levelName.required': 'Please enter level name',
|
||||
'supplierEvaluateRuleManage.form.ratingName': 'Rating Name',
|
||||
'supplierEvaluateRuleManage.form.ratingName.placeholder': 'Please enter rating name, such as Excellent Supplier, Good Supplier, etc.',
|
||||
'supplierEvaluateRuleManage.form.ratingName.required': 'Please enter rating name',
|
||||
'supplierEvaluateRuleManage.form.beginValue': 'Start Value',
|
||||
'supplierEvaluateRuleManage.form.beginValue.placeholder': 'Please enter start value',
|
||||
'supplierEvaluateRuleManage.form.beginValue.required': 'Please enter start value',
|
||||
'supplierEvaluateRuleManage.form.beginValue.integer': 'Please enter a positive integer',
|
||||
'supplierEvaluateRuleManage.form.endValue': 'End Value',
|
||||
'supplierEvaluateRuleManage.form.endValue.placeholder': 'Please enter end value',
|
||||
'supplierEvaluateRuleManage.form.endValue.required': 'Please enter end value',
|
||||
'supplierEvaluateRuleManage.form.endValue.integer': 'Please enter a positive integer',
|
||||
'supplierEvaluateRuleManage.form.endValue.greater': 'End value must be greater than start value',
|
||||
'supplierEvaluateRuleManage.form.remark': 'Remark',
|
||||
'supplierEvaluateRuleManage.form.remark.placeholder': 'Please enter remarks',
|
||||
|
||||
// 模态框标题
|
||||
'supplierEvaluateRuleManage.modal.add': 'Add Evaluation Rule',
|
||||
'supplierEvaluateRuleManage.modal.edit': 'Edit Evaluation Rule',
|
||||
'supplierEvaluateRuleManage.modal.delete': 'Confirm Delete',
|
||||
'supplierEvaluateRuleManage.modal.delete.content': 'Are you sure to delete rule "{levelName}"?',
|
||||
|
||||
// 消息提示
|
||||
'supplierEvaluateRuleManage.message.getList.error': 'Failed to get evaluation rule list',
|
||||
'supplierEvaluateRuleManage.message.getDetail.error': 'Failed to get evaluation rule detail',
|
||||
'supplierEvaluateRuleManage.message.add.success': 'Successfully added evaluation rule',
|
||||
'supplierEvaluateRuleManage.message.add.error': 'Failed to add evaluation rule',
|
||||
'supplierEvaluateRuleManage.message.update.success': 'Successfully updated evaluation rule',
|
||||
'supplierEvaluateRuleManage.message.update.error': 'Failed to update evaluation rule',
|
||||
'supplierEvaluateRuleManage.message.delete.success': 'Successfully deleted rule: {levelName}',
|
||||
'supplierEvaluateRuleManage.message.delete.error': 'Failed to delete evaluation rule',
|
||||
};
|
@ -1,12 +1,24 @@
|
||||
import login from './zh-CN/login';
|
||||
import register from './zh-CN/register';
|
||||
import menu from './zh-CN/menu';
|
||||
import workbench from './zh-CN/workbench';
|
||||
import globalModal from './zh-CN/globalModal';
|
||||
import login from './zh-CN/login';
|
||||
import menu from './zh-CN/menu';
|
||||
import register from './zh-CN/register';
|
||||
import workbench from './zh-CN/workbench';
|
||||
import supplierEvaluateRuleManage from './zh-CN/supplierEvaluateRuleManage';
|
||||
|
||||
export default {
|
||||
...login,
|
||||
...register,
|
||||
...menu,
|
||||
...workbench,
|
||||
'navBar.lang': '语言',
|
||||
'layout.user.link.help': '帮助',
|
||||
'layout.user.link.privacy': '隐私',
|
||||
'layout.user.link.terms': '条款',
|
||||
'app.home.introduce': '介绍',
|
||||
'app.forms.basic.title': '基础表单',
|
||||
'app.forms.basic.description':
|
||||
'表单页用于向用户收集或验证信息,基础表单常见于数据项较少的表单场景。',
|
||||
'登录/注册': '登录/注册',
|
||||
...globalModal,
|
||||
...login,
|
||||
...menu,
|
||||
...register,
|
||||
...workbench,
|
||||
...supplierEvaluateRuleManage,
|
||||
};
|
||||
|
@ -6,6 +6,7 @@ export default {
|
||||
'menu.模板管理': '模板管理',
|
||||
'menu.模板管理新增': '模板管理新增',
|
||||
'menu.模板管理详情': '模板管理详情',
|
||||
'menu.评价规则管理': '评价规则管理',
|
||||
'menu.任务管理': '任务管理',
|
||||
'menu.任务管理新增': '任务管理新增',
|
||||
'menu.评价打分': '评价打分',
|
||||
@ -23,7 +24,7 @@ export default {
|
||||
'menu.年度查询': '年度查询',
|
||||
'menu.年审结果': '年审结果',
|
||||
|
||||
|
||||
|
||||
//供应商
|
||||
'menu.admit': '供应商准入审批',
|
||||
'menu.dict': '字典',
|
||||
|
52
src/locales/zh-CN/supplierEvaluateRuleManage.ts
Normal file
52
src/locales/zh-CN/supplierEvaluateRuleManage.ts
Normal file
@ -0,0 +1,52 @@
|
||||
export default {
|
||||
'supplierEvaluateRuleManage.title': '评价规则管理',
|
||||
'supplierEvaluateRuleManage.add': '新增',
|
||||
'supplierEvaluateRuleManage.edit': '编辑',
|
||||
'supplierEvaluateRuleManage.delete': '删除',
|
||||
'supplierEvaluateRuleManage.confirm': '确认',
|
||||
'supplierEvaluateRuleManage.cancel': '取消',
|
||||
'supplierEvaluateRuleManage.submit': '提交',
|
||||
|
||||
// 表格列名
|
||||
'supplierEvaluateRuleManage.column.index': '序号',
|
||||
'supplierEvaluateRuleManage.column.levelName': '等级名称',
|
||||
'supplierEvaluateRuleManage.column.ratingName': '评级名称',
|
||||
'supplierEvaluateRuleManage.column.scoreRange': '分数区间',
|
||||
'supplierEvaluateRuleManage.column.remark': '备注',
|
||||
'supplierEvaluateRuleManage.column.action': '操作',
|
||||
|
||||
// 表单字段
|
||||
'supplierEvaluateRuleManage.form.levelName': '等级名称',
|
||||
'supplierEvaluateRuleManage.form.levelName.placeholder': '请输入等级名称,如A、B、C等',
|
||||
'supplierEvaluateRuleManage.form.levelName.required': '请输入等级名称',
|
||||
'supplierEvaluateRuleManage.form.ratingName': '评级名称',
|
||||
'supplierEvaluateRuleManage.form.ratingName.placeholder': '请输入评级名称,如优秀供应商、良好供应商等',
|
||||
'supplierEvaluateRuleManage.form.ratingName.required': '请输入评级名称',
|
||||
'supplierEvaluateRuleManage.form.beginValue': '起始分值',
|
||||
'supplierEvaluateRuleManage.form.beginValue.placeholder': '请输入起始分值',
|
||||
'supplierEvaluateRuleManage.form.beginValue.required': '请输入起始分值',
|
||||
'supplierEvaluateRuleManage.form.beginValue.integer': '请输入正整数',
|
||||
'supplierEvaluateRuleManage.form.endValue': '结束分值',
|
||||
'supplierEvaluateRuleManage.form.endValue.placeholder': '请输入结束分值',
|
||||
'supplierEvaluateRuleManage.form.endValue.required': '请输入结束分值',
|
||||
'supplierEvaluateRuleManage.form.endValue.integer': '请输入正整数',
|
||||
'supplierEvaluateRuleManage.form.endValue.greater': '结束分值必须大于起始分值',
|
||||
'supplierEvaluateRuleManage.form.remark': '备注',
|
||||
'supplierEvaluateRuleManage.form.remark.placeholder': '请输入备注信息',
|
||||
|
||||
// 模态框标题
|
||||
'supplierEvaluateRuleManage.modal.add': '新增评价规则',
|
||||
'supplierEvaluateRuleManage.modal.edit': '编辑评价规则',
|
||||
'supplierEvaluateRuleManage.modal.delete': '确认删除',
|
||||
'supplierEvaluateRuleManage.modal.delete.content': '确定要删除规则"{levelName}"吗?',
|
||||
|
||||
// 消息提示
|
||||
'supplierEvaluateRuleManage.message.getList.error': '获取评价规则列表失败',
|
||||
'supplierEvaluateRuleManage.message.getDetail.error': '获取评价规则详情失败',
|
||||
'supplierEvaluateRuleManage.message.add.success': '新增评价规则成功',
|
||||
'supplierEvaluateRuleManage.message.add.error': '新增评价规则失败',
|
||||
'supplierEvaluateRuleManage.message.update.success': '更新评价规则成功',
|
||||
'supplierEvaluateRuleManage.message.update.error': '更新评价规则失败',
|
||||
'supplierEvaluateRuleManage.message.delete.success': '成功删除规则: {levelName}',
|
||||
'supplierEvaluateRuleManage.message.delete.error': '删除评价规则失败',
|
||||
};
|
@ -1,17 +0,0 @@
|
||||
import React from 'react';
|
||||
const LinkComponent: React.FC = () => {
|
||||
return (
|
||||
<div className="link">
|
||||
<div>友情链接</div>
|
||||
<div className="flex">
|
||||
<a href="https://www.baidu.com">百度</a>
|
||||
<a href="https://www.baidu.com">百度</a>
|
||||
<a href="https://www.baidu.com">百度</a>
|
||||
<a href="https://www.baidu.com">百度</a>
|
||||
<a href="https://www.baidu.com">百度</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LinkComponent;
|
@ -1,244 +1,7 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Card, Row, Col, Tabs, Table } from 'antd';
|
||||
import { useIntl, Link } from 'umi';
|
||||
import './index.less';
|
||||
import IconFont from '@/components/IconFont/IconFont';
|
||||
import LinkComponent from './Link';
|
||||
const IndexPage: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const [noticeLoading, setNoticeLoading] = useState(false);
|
||||
const [noticeList, setNoticeList] = useState([
|
||||
{
|
||||
title: 'CA使用通知',
|
||||
id: '1',
|
||||
content: '系统将于2022年5月27日期开始对全流程使用CA服务,届时全部投标供应商需办理CA。',
|
||||
},
|
||||
{
|
||||
title: '5月27日系统优化升级通知',
|
||||
id: '2',
|
||||
content:
|
||||
'系统将于2022年5月27日(周五)22:00--2022年5月28日(周六)6:00进行系统优化升级,届时系统将暂停服务。',
|
||||
},
|
||||
{
|
||||
title: '测试标题123123',
|
||||
id: '3',
|
||||
content: '测试内容124145',
|
||||
},
|
||||
{
|
||||
title: '测试标题45435',
|
||||
id: '4',
|
||||
content: '测试内容6666',
|
||||
},
|
||||
]);
|
||||
const tabList = [
|
||||
{
|
||||
key: '1',
|
||||
label: intl.formatMessage({ id: '采购需求公示' }),
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
label: intl.formatMessage({ id: '招标采购公告' }),
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
label: intl.formatMessage({ id: '非招标采购公告' }),
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
label: intl.formatMessage({ id: '资格预审公告' }),
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
label: intl.formatMessage({ id: '招募公告' }),
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
label: intl.formatMessage({ id: '变更公告' }),
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
label: intl.formatMessage({ id: '中标(中选)候选人公示' }),
|
||||
},
|
||||
{
|
||||
key: '8',
|
||||
label: intl.formatMessage({ id: '中标(中选)结果公示' }),
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
label: intl.formatMessage({ id: '采购失败(流标)公告' }),
|
||||
},
|
||||
];
|
||||
//tab 切换事件
|
||||
const tabChange = (key: string) => {
|
||||
console.log(key);
|
||||
};
|
||||
const [tableLoading, setTableLoading] = useState(false);
|
||||
const dataSource = [
|
||||
{
|
||||
key: '1',
|
||||
title: '中远海运空运北方物流基地标识制作及安装服务',
|
||||
address: '西湖区湖底公园1号',
|
||||
date: '2025年01月23日',
|
||||
lastDate: '剩余3天4小时',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
title: '中远海运空运北方物流基地标识制作及安装服务',
|
||||
address: '西湖区湖底公园1号',
|
||||
date: '2025年01月23日',
|
||||
lastDate: '剩余3天4小时',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
title: '中远海运空运北方物流基地标识制作及安装服务',
|
||||
address: '西湖区湖底公园1号',
|
||||
date: '2025年01月23日',
|
||||
lastDate: '剩余3天4小时',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
title: '中远海运空运北方物流基地标识制作及安装服务',
|
||||
address: '西湖区湖底公园1号',
|
||||
date: '2025年01月23日',
|
||||
lastDate: '剩余3天4小时',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
title: '中远海运空运北方物流基地标识制作及安装服务',
|
||||
address: '西湖区湖底公园1号',
|
||||
date: '2025年01月23日',
|
||||
lastDate: '剩余3天4小时',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
title: '中远海运空运北方物流基地标识制作及安装服务',
|
||||
address: '西湖区湖底公园1号',
|
||||
date: '2025年01月23日',
|
||||
lastDate: '剩余3天4小时',
|
||||
},
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '项目所在地',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
},
|
||||
{
|
||||
title: '公告标题',
|
||||
dataIndex: 'title',
|
||||
key: 'title',
|
||||
render: (text: string, record) => (
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/announce/announceInfo',
|
||||
search: '?id=' + record.id,
|
||||
}}
|
||||
>
|
||||
{text}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '发布时间',
|
||||
dataIndex: 'date',
|
||||
key: 'date',
|
||||
},
|
||||
{
|
||||
title: '文件购买截止时间',
|
||||
dataIndex: 'lastDate',
|
||||
key: 'lastDate',
|
||||
render: (text: string) => <span className="lastDate">{text}</span>,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* 通知列表 */}
|
||||
<Row gutter={20}>
|
||||
{noticeList.map((item) => (
|
||||
<Col span={6} key={item.id}>
|
||||
<Card
|
||||
title={item.title}
|
||||
loading={noticeLoading}
|
||||
hoverable
|
||||
className="card"
|
||||
bodyStyle={{ padding: 10 }}
|
||||
extra={
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/notice/noticeInfo',
|
||||
search: '?id=' + item.id,
|
||||
}}
|
||||
>
|
||||
{intl.formatMessage({ id: '查看' })}
|
||||
</Link>
|
||||
}
|
||||
>
|
||||
<p className="cardContent">{item.content}</p>
|
||||
</Card>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
<Tabs onChange={tabChange}>
|
||||
{tabList.map((item) => (
|
||||
<Tabs.TabPane tab={item.label} key={item.key} />
|
||||
))}
|
||||
</Tabs>
|
||||
|
||||
<Table loading={tableLoading} dataSource={dataSource} columns={columns} pagination={false} />
|
||||
|
||||
<div className="tableLoadMore">
|
||||
<Link
|
||||
to={{
|
||||
pathname: '/announce',
|
||||
}}
|
||||
>
|
||||
{intl.formatMessage({ id: '加载更多' })}
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<Row style={{ marginTop: '20px', backgroundColor: '#fff' }}>
|
||||
<Col span={12}>
|
||||
<div className="blockTitle">紧急问题咨询</div>
|
||||
<img src="" alt="" />
|
||||
<div className="questionItem">
|
||||
<IconFont type="icon-dizhi" className="icon" />
|
||||
北京市前门大街173号
|
||||
</div>
|
||||
<div className="questionItem">
|
||||
<IconFont type="icon-dianhua" className="icon" />
|
||||
17676373746
|
||||
</div>
|
||||
<div className="questionItem">
|
||||
<IconFont type="icon-youxiang" className="icon" />
|
||||
i723648723@383.com
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<div className="blockTitle">CA服务</div>
|
||||
<Row>
|
||||
<Col span={6} offset={6}>
|
||||
<span>CA办理</span>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<span>CA客服</span>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div className="blockTitle">联系方式</div>
|
||||
<p style={{ marginTop: 20 }}>客服1: 400-300-9989</p>
|
||||
<p>客服1: 400-300-9989</p>
|
||||
<p>客服1: 400-300-9989</p>
|
||||
<p>客服1: 400-300-9989</p>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div>
|
||||
<LinkComponent />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return <div>首页</div>;
|
||||
};
|
||||
|
||||
export default IndexPage;
|
||||
|
@ -1,221 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Table, Progress, Typography, Card, Tag } from 'antd';
|
||||
import styles from './components.less';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
interface GeneralEvaluationProps {
|
||||
supplierName?: string;
|
||||
}
|
||||
|
||||
const GeneralEvaluation: React.FC<GeneralEvaluationProps> = ({ supplierName }) => {
|
||||
// 评价数据
|
||||
const evaluationData = [
|
||||
{
|
||||
key: '1',
|
||||
firstIndex: '基本情况(base case)',
|
||||
firstDescription: '企业基本资质与存续状态证明',
|
||||
firstScore: 4,
|
||||
secondIndex: '资质文件',
|
||||
secondScore: 1,
|
||||
averageScore: 3,
|
||||
rowSpan: 2,
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
firstIndex: '基本情况(base case)',
|
||||
firstDescription: '企业基本资质与存续状态证明',
|
||||
firstScore: 4,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 3,
|
||||
averageScore: 1,
|
||||
rowSpan: 0, // 设为0表示不显示
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
firstIndex: '成本(cost)',
|
||||
firstDescription: '商品与服务的总拥有成本',
|
||||
firstScore: 7,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 7,
|
||||
averageScore: 6.5,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
firstIndex: '创新(innovate)',
|
||||
firstDescription: '为公司提供竞争优势,提高商业价值而持续提供创新性建议及解决方案',
|
||||
firstScore: 20,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 20,
|
||||
averageScore: 18.5,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
firstIndex: '服务 (service)',
|
||||
firstDescription: '为满足公司商业需求而提供的服务与支持',
|
||||
firstScore: 10,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 10,
|
||||
averageScore: 10,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
firstIndex: '质量(quality)',
|
||||
firstDescription: '提供满足需求(规格)的产品与服务',
|
||||
firstScore: 25,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 25,
|
||||
averageScore: 24,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
firstIndex: '绿色(environment protection)',
|
||||
firstDescription: '优秀的交付能力及与之相关的灵活性',
|
||||
firstScore: 25,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 25,
|
||||
averageScore: 24,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '8',
|
||||
firstIndex: '安全(safety)',
|
||||
firstDescription: '产品质量安全、环境保护、风险防控及商业道德约束',
|
||||
firstScore: 6,
|
||||
secondIndex: 'XXX',
|
||||
secondScore: 6,
|
||||
averageScore: 5,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
firstIndex: '廉洁(integrity)',
|
||||
firstDescription: '商业道德约束',
|
||||
firstScore: 3,
|
||||
secondIndex: '商业贿赂与道德风险',
|
||||
secondScore: 3,
|
||||
averageScore: 3,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '10',
|
||||
firstIndex: '合计',
|
||||
firstDescription: '',
|
||||
firstScore: 100,
|
||||
secondIndex: '',
|
||||
secondScore: 100,
|
||||
averageScore: 95,
|
||||
rowSpan: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
width: 50,
|
||||
render: (text: string, record: any, index: number) => index + 1,
|
||||
},
|
||||
{
|
||||
title: '一级指标',
|
||||
children: [
|
||||
{
|
||||
title: '*基本指标',
|
||||
dataIndex: 'firstIndex',
|
||||
key: 'firstIndex',
|
||||
width: 150,
|
||||
render: (text: string, record: any, index: number) => {
|
||||
return {
|
||||
children: text,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '*指标说明',
|
||||
dataIndex: 'firstDescription',
|
||||
key: 'firstDescription',
|
||||
width: 220,
|
||||
render: (text: string, record: any) => {
|
||||
return {
|
||||
children: text,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
dataIndex: 'firstScore',
|
||||
key: 'firstScore',
|
||||
width: 80,
|
||||
render: (text: number, record: any) => {
|
||||
return {
|
||||
children: text,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '二级指标',
|
||||
children: [
|
||||
{
|
||||
title: '*细分指标',
|
||||
dataIndex: 'secondIndex',
|
||||
key: 'secondIndex',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
dataIndex: 'secondScore',
|
||||
key: 'secondScore',
|
||||
width: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '平均分',
|
||||
dataIndex: 'averageScore',
|
||||
key: 'averageScore',
|
||||
width: 80,
|
||||
render: (score: number) => (
|
||||
<span className={score < 60 ? styles.lowScore : ''}>
|
||||
{score}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 计算总分
|
||||
const totalScore = evaluationData[evaluationData.length - 1].averageScore;
|
||||
const totalPossibleScore = evaluationData[evaluationData.length - 1].firstScore;
|
||||
const scorePercentage = (totalScore / totalPossibleScore) * 100;
|
||||
|
||||
return (
|
||||
<div className={styles.evaluationContainer}>
|
||||
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={evaluationData}
|
||||
pagination={false}
|
||||
className={styles.scoreTable}
|
||||
bordered
|
||||
size="middle"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default GeneralEvaluation;
|
@ -1,265 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Table, Progress, Typography, Card, Tag } from 'antd';
|
||||
import styles from './components.less';
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
interface TechnicalEvaluationProps {
|
||||
supplierName?: string;
|
||||
}
|
||||
|
||||
const TechnicalEvaluation: React.FC<TechnicalEvaluationProps> = ({ supplierName }) => {
|
||||
// 评价数据
|
||||
const evaluationData = [
|
||||
{
|
||||
key: '1',
|
||||
firstIndex: '技术实力',
|
||||
firstDescription: '技术团队规模与研发能力',
|
||||
firstScore: 20,
|
||||
secondIndex: '研发团队规模',
|
||||
secondScore: 10,
|
||||
averageScore: 9,
|
||||
rowSpan: 2,
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
firstIndex: '技术实力',
|
||||
firstDescription: '技术团队规模与研发能力',
|
||||
firstScore: 20,
|
||||
secondIndex: '技术创新能力',
|
||||
secondScore: 10,
|
||||
averageScore: 8,
|
||||
rowSpan: 0, // 设为0表示不显示
|
||||
},
|
||||
{
|
||||
key: '3',
|
||||
firstIndex: '产品性能',
|
||||
firstDescription: '产品的技术指标与性能表现',
|
||||
firstScore: 25,
|
||||
secondIndex: '核心性能指标',
|
||||
secondScore: 15,
|
||||
averageScore: 14,
|
||||
rowSpan: 2,
|
||||
},
|
||||
{
|
||||
key: '4',
|
||||
firstIndex: '产品性能',
|
||||
firstDescription: '产品的技术指标与性能表现',
|
||||
firstScore: 25,
|
||||
secondIndex: '稳定性与可靠性',
|
||||
secondScore: 10,
|
||||
averageScore: 9.5,
|
||||
rowSpan: 0,
|
||||
},
|
||||
{
|
||||
key: '5',
|
||||
firstIndex: '技术支持',
|
||||
firstDescription: '提供的技术服务与支持能力',
|
||||
firstScore: 15,
|
||||
secondIndex: '响应速度',
|
||||
secondScore: 8,
|
||||
averageScore: 7.5,
|
||||
rowSpan: 2,
|
||||
},
|
||||
{
|
||||
key: '6',
|
||||
firstIndex: '技术支持',
|
||||
firstDescription: '提供的技术服务与支持能力',
|
||||
firstScore: 15,
|
||||
secondIndex: '问题解决能力',
|
||||
secondScore: 7,
|
||||
averageScore: 6.5,
|
||||
rowSpan: 0,
|
||||
},
|
||||
{
|
||||
key: '7',
|
||||
firstIndex: '技术文档',
|
||||
firstDescription: '技术文档的完整性与准确性',
|
||||
firstScore: 10,
|
||||
secondIndex: '文档完整性',
|
||||
secondScore: 5,
|
||||
averageScore: 4.5,
|
||||
rowSpan: 2,
|
||||
},
|
||||
{
|
||||
key: '8',
|
||||
firstIndex: '技术文档',
|
||||
firstDescription: '技术文档的完整性与准确性',
|
||||
firstScore: 10,
|
||||
secondIndex: '文档准确性',
|
||||
secondScore: 5,
|
||||
averageScore: 4,
|
||||
rowSpan: 0,
|
||||
},
|
||||
{
|
||||
key: '9',
|
||||
firstIndex: '技术培训',
|
||||
firstDescription: '提供的技术培训与知识转移',
|
||||
firstScore: 15,
|
||||
secondIndex: '培训质量',
|
||||
secondScore: 8,
|
||||
averageScore: 7,
|
||||
rowSpan: 2,
|
||||
},
|
||||
{
|
||||
key: '10',
|
||||
firstIndex: '技术培训',
|
||||
firstDescription: '提供的技术培训与知识转移',
|
||||
firstScore: 15,
|
||||
secondIndex: '培训频率',
|
||||
secondScore: 7,
|
||||
averageScore: 6,
|
||||
rowSpan: 0,
|
||||
},
|
||||
{
|
||||
key: '11',
|
||||
firstIndex: '兼容性',
|
||||
firstDescription: '与现有系统的兼容性',
|
||||
firstScore: 15,
|
||||
secondIndex: '系统兼容性评估',
|
||||
secondScore: 15,
|
||||
averageScore: 13.5,
|
||||
rowSpan: 1,
|
||||
},
|
||||
{
|
||||
key: '12',
|
||||
firstIndex: '合计',
|
||||
firstDescription: '',
|
||||
firstScore: 100,
|
||||
secondIndex: '',
|
||||
secondScore: 100,
|
||||
averageScore: 89.5,
|
||||
rowSpan: 1,
|
||||
},
|
||||
];
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '',
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
width: 50,
|
||||
render: (text: string, record: any, index: number) => index + 1,
|
||||
},
|
||||
{
|
||||
title: '一级指标',
|
||||
children: [
|
||||
{
|
||||
title: '*基本指标',
|
||||
dataIndex: 'firstIndex',
|
||||
key: 'firstIndex',
|
||||
width: 150,
|
||||
className: styles.requiredColumn,
|
||||
render: (text: string, record: any, index: number) => {
|
||||
return {
|
||||
children: text,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '*指标说明',
|
||||
dataIndex: 'firstDescription',
|
||||
key: 'firstDescription',
|
||||
width: 220,
|
||||
className: styles.requiredColumn,
|
||||
render: (text: string, record: any) => {
|
||||
return {
|
||||
children: text,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
dataIndex: 'firstScore',
|
||||
key: 'firstScore',
|
||||
width: 80,
|
||||
render: (text: number, record: any) => {
|
||||
return {
|
||||
children: text,
|
||||
props: {
|
||||
rowSpan: record.rowSpan,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '二级指标',
|
||||
children: [
|
||||
{
|
||||
title: '*细分指标',
|
||||
dataIndex: 'secondIndex',
|
||||
key: 'secondIndex',
|
||||
width: 180,
|
||||
className: styles.requiredColumn,
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
dataIndex: 'secondScore',
|
||||
key: 'secondScore',
|
||||
width: 80,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: '平均分',
|
||||
dataIndex: 'averageScore',
|
||||
key: 'averageScore',
|
||||
width: 80,
|
||||
render: (score: number) => (
|
||||
<span className={score < 60 ? styles.lowScore : ''}>
|
||||
{score}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 计算总分
|
||||
const totalScore = evaluationData[evaluationData.length - 1].averageScore;
|
||||
const totalPossibleScore = evaluationData[evaluationData.length - 1].firstScore;
|
||||
const scorePercentage = (totalScore / totalPossibleScore) * 100;
|
||||
|
||||
return (
|
||||
<div className={styles.evaluationContainer}>
|
||||
<Card className={styles.summaryCard}>
|
||||
<div className={styles.scoreSummary}>
|
||||
<div className={styles.scoreCircle}>
|
||||
<Progress
|
||||
type="circle"
|
||||
percent={scorePercentage}
|
||||
format={() => `${totalScore}`}
|
||||
width={80}
|
||||
strokeColor={{
|
||||
'0%': '#108ee9',
|
||||
'100%': '#87d068',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.scoreInfo}>
|
||||
<Title level={4}>技术评价总分</Title>
|
||||
<Text type="secondary">满分: {totalPossibleScore}分</Text>
|
||||
{supplierName && <Text type="secondary">供应商: {supplierName}</Text>}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={evaluationData}
|
||||
pagination={false}
|
||||
className={styles.scoreTable}
|
||||
bordered
|
||||
size="middle"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TechnicalEvaluation;
|
@ -1,80 +0,0 @@
|
||||
.evaluationContainer {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.summaryCard {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.scoreSummary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.scoreCircle {
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.scoreInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
h4 {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.scoreCell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
span {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.scoreTable {
|
||||
margin-top: 16px;
|
||||
|
||||
:global {
|
||||
.ant-table-thead > tr > th {
|
||||
background-color: #f5f5f5;
|
||||
text-align: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.ant-table-tbody > tr > td {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 必填列样式 */
|
||||
.requiredColumn {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '*';
|
||||
color: #ff4d4f;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
/* 低分警示 */
|
||||
.lowScore {
|
||||
color: #ff4d4f;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* 表格嵌套表头样式 */
|
||||
:global {
|
||||
.ant-table-thead > tr > th.ant-table-cell-fix-left,
|
||||
.ant-table-thead > tr > th.ant-table-cell-fix-right {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
}
|
@ -188,11 +188,25 @@ const SupplierEvaluateResult: React.FC = () => {
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '评价品类',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
width: 120,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text: string) => (
|
||||
<Tooltip placement="topLeft" title={text || '未指定'}>
|
||||
{text || '未指定'}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '发起单位',
|
||||
dataIndex: 'tenantName',
|
||||
key: 'tenantName',
|
||||
width: 200,
|
||||
dataIndex: 'deptName',
|
||||
key: 'deptName',
|
||||
width: 180,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
|
@ -1,202 +1,145 @@
|
||||
// 评价结果详情
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, Form, Button, Descriptions, Divider, Row, Col, Tabs, message } from 'antd';
|
||||
import { Card, Button, message, Typography } from 'antd';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { history, useLocation } from 'umi';
|
||||
import { EvaluateLevel, EvaluateLevelText } from '@/dicts/supplierTemplateDict';
|
||||
import GeneralEvaluation from './components/GeneralEvaluation';
|
||||
import TechnicalEvaluation from './components/TechnicalEvaluation';
|
||||
import ScoreEvaluationTable from '@/components/ScoreEvaluationTable';
|
||||
import styles from './supplierEvaluateResult.less';
|
||||
import { getIndicator } from '@/servers/api/supplierEvaluate';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
const { Title } = Typography;
|
||||
|
||||
// 组件使用默认的接口定义
|
||||
// 评价打分详情数据接口
|
||||
interface IndicatorDetailData {
|
||||
category: string;
|
||||
name: string;
|
||||
taskIndicatorVo: {
|
||||
baseIndicator: string;
|
||||
indicatorDesc: string;
|
||||
score: string;
|
||||
subIndicator: {
|
||||
id: string;
|
||||
remark: string | null;
|
||||
scoreNum: string | null;
|
||||
starIndicator: string;
|
||||
stId: string;
|
||||
subIndicator: string;
|
||||
subScore: string;
|
||||
}[];
|
||||
}[];
|
||||
}
|
||||
|
||||
const SupplierEvaluateResultByZb: React.FC = () => {
|
||||
const location = useLocation<{ record: any }>();
|
||||
const location = useLocation<{
|
||||
record: API.EvaluateScoreIndicator;
|
||||
parentRecord: API.EvaluateTaskRecord;
|
||||
supplierRecord: API.EvaluateSupplierRecord;
|
||||
scoreDetail: API.EvaluateScoreData;
|
||||
}>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [scoreRecord, setScoreRecord] = useState<any>(null);
|
||||
const [evaluationData, setEvaluationData] = useState<{
|
||||
general: any[];
|
||||
technical: any[];
|
||||
}>({
|
||||
general: [],
|
||||
technical: [],
|
||||
});
|
||||
|
||||
// 模拟获取评价详情数据
|
||||
const fetchEvaluationData = (record: any) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// 模拟API请求
|
||||
setTimeout(() => {
|
||||
// 模拟通用评价数据
|
||||
const generalData = [
|
||||
{
|
||||
id: '1',
|
||||
firstIndex: '质量管理',
|
||||
firstDescription: '供应商质量管理体系评价',
|
||||
secondIndex: '质量管理体系认证',
|
||||
secondDescription: '是否通过ISO9001认证',
|
||||
score: 9,
|
||||
weight: 0.1,
|
||||
weightedScore: 0.9,
|
||||
comment: '已通过ISO9001认证,证书有效',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
firstIndex: '质量管理',
|
||||
firstDescription: '供应商质量管理体系评价',
|
||||
secondIndex: '质量控制流程',
|
||||
secondDescription: '是否建立完善的质量控制流程',
|
||||
score: 8,
|
||||
weight: 0.1,
|
||||
weightedScore: 0.8,
|
||||
comment: '质量控制流程完善,但执行记录不够完整',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
firstIndex: '交付能力',
|
||||
firstDescription: '供应商交付能力评价',
|
||||
secondIndex: '准时交付率',
|
||||
secondDescription: '过去一年准时交付率评价',
|
||||
score: 9.5,
|
||||
weight: 0.15,
|
||||
weightedScore: 1.425,
|
||||
comment: '准时交付率98%,表现优秀',
|
||||
},
|
||||
];
|
||||
|
||||
// 模拟技术评价数据
|
||||
const technicalData = [
|
||||
{
|
||||
id: '1',
|
||||
firstIndex: '技术能力',
|
||||
firstDescription: '供应商技术研发能力评价',
|
||||
secondIndex: '研发投入',
|
||||
secondDescription: '研发投入占营业额比例',
|
||||
score: 8.5,
|
||||
weight: 0.1,
|
||||
weightedScore: 0.85,
|
||||
comment: '研发投入占营业额5%,符合行业平均水平',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
firstIndex: '技术能力',
|
||||
firstDescription: '供应商技术研发能力评价',
|
||||
secondIndex: '专利数量',
|
||||
secondDescription: '拥有专利数量评价',
|
||||
score: 9,
|
||||
weight: 0.05,
|
||||
weightedScore: 0.45,
|
||||
comment: '拥有15项有效专利,其中发明专利5项',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
firstIndex: '设备设施',
|
||||
firstDescription: '供应商设备设施评价',
|
||||
secondIndex: '设备先进性',
|
||||
secondDescription: '生产设备先进程度评价',
|
||||
score: 8,
|
||||
weight: 0.1,
|
||||
weightedScore: 0.8,
|
||||
comment: '主要生产设备较为先进,但部分设备需要更新',
|
||||
},
|
||||
];
|
||||
|
||||
setEvaluationData({
|
||||
general: generalData,
|
||||
technical: technicalData,
|
||||
});
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
console.error('获取评价详情数据失败:', error);
|
||||
message.error('获取评价详情数据失败');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const [scoreRecord, setScoreRecord] = useState<API.EvaluateScoreIndicator | null>(null);
|
||||
const [parentRecord, setParentRecord] = useState<API.EvaluateTaskRecord | null>(null);
|
||||
const [supplierRecord, setSupplierRecord] = useState<API.EvaluateSupplierRecord | null>(null);
|
||||
const [indicatorDetail, setIndicatorDetail] = useState<IndicatorDetailData | null>(null);
|
||||
|
||||
// 获取上级页面传递的数据
|
||||
useEffect(() => {
|
||||
if (location.state?.record) {
|
||||
setScoreRecord(location.state.record);
|
||||
// 模拟获取评价详情数据
|
||||
fetchEvaluationData(location.state.record);
|
||||
}
|
||||
if (location.state?.parentRecord) {
|
||||
setParentRecord(location.state.parentRecord);
|
||||
}
|
||||
if (location.state?.supplierRecord) {
|
||||
setSupplierRecord(location.state.supplierRecord);
|
||||
}
|
||||
if (location.state?.scoreDetail) {
|
||||
// 如果有上级页面传递的评分明细数据,暂存下来
|
||||
// 稍后我们仍然会通过API获取最新数据
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
// 获取评价打分详情数据
|
||||
const fetchIndicatorDetail = async () => {
|
||||
if (!scoreRecord?.id) {
|
||||
message.error('缺少评价记录ID,无法获取数据');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await getIndicator(scoreRecord.id);
|
||||
if (response.data && response.success) {
|
||||
setIndicatorDetail(response.data);
|
||||
} else {
|
||||
message.error(response.message || '获取评价打分详情失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价打分详情失败:', error);
|
||||
message.error('获取评价打分详情失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听scoreRecord变化,获取评价详情数据
|
||||
useEffect(() => {
|
||||
if (scoreRecord?.id) {
|
||||
fetchIndicatorDetail();
|
||||
}
|
||||
}, [scoreRecord]);
|
||||
|
||||
// 返回上一页
|
||||
const handleBack = () => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
// 计算总得分
|
||||
const calculateTotalScore = () => {
|
||||
let totalScore = 0;
|
||||
let totalWeight = 0;
|
||||
// 将API数据转换为ScoreEvaluationTable组件所需的格式
|
||||
const formatDataForScoreTable = () => {
|
||||
if (!indicatorDetail?.taskIndicatorVo) return [];
|
||||
|
||||
// 计算通用评价得分
|
||||
evaluationData.general.forEach((item: any) => {
|
||||
totalScore += item.weightedScore;
|
||||
totalWeight += item.weight;
|
||||
return indicatorDetail.taskIndicatorVo.map(indicator => {
|
||||
return {
|
||||
baseIndicator: indicator.baseIndicator,
|
||||
descIndicator: indicator.indicatorDesc,
|
||||
score: indicator.score,
|
||||
indicatorNdList: indicator.subIndicator?.map(subItem => {
|
||||
return {
|
||||
subIndicator: subItem.subIndicator,
|
||||
score: subItem.subScore,
|
||||
isStar: subItem.starIndicator,
|
||||
id: subItem.id,
|
||||
actualScore: subItem.scoreNum || '',
|
||||
remark: subItem.remark || ''
|
||||
};
|
||||
}) || []
|
||||
};
|
||||
});
|
||||
|
||||
// 计算技术评价得分
|
||||
evaluationData.technical.forEach((item: any) => {
|
||||
totalScore += item.weightedScore;
|
||||
totalWeight += item.weight;
|
||||
});
|
||||
|
||||
// 如果权重总和不为0,则计算加权平均分
|
||||
if (totalWeight > 0) {
|
||||
return (totalScore / totalWeight).toFixed(2);
|
||||
}
|
||||
|
||||
return '0.00';
|
||||
};
|
||||
|
||||
// 获取评价等级
|
||||
const getEvaluateLevel = (score: number) => {
|
||||
if (score >= 90) {
|
||||
return EvaluateLevelText[EvaluateLevel.EXCELLENT];
|
||||
} else if (score >= 80) {
|
||||
return EvaluateLevelText[EvaluateLevel.GOOD];
|
||||
} else if (score >= 70) {
|
||||
return EvaluateLevelText[EvaluateLevel.AVERAGE];
|
||||
} else {
|
||||
return EvaluateLevelText[EvaluateLevel.POOR];
|
||||
}
|
||||
};
|
||||
|
||||
if (!scoreRecord) {
|
||||
if (loading && !indicatorDetail) {
|
||||
return <div className="common-container">加载中...</div>;
|
||||
}
|
||||
|
||||
const supplierName = supplierRecord?.supplierName || indicatorDetail?.name || '供应商';
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<div className="action-row">
|
||||
<div className="filter-action-row">
|
||||
<Title level={4} className={styles.pageTitle}>
|
||||
{supplierName} - 评价详情
|
||||
</Title>
|
||||
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Card title="评价基本信息" bordered={false} className={styles.infoCard}>
|
||||
<Descriptions column={3}>
|
||||
<Descriptions.Item label="供应商名称">{scoreRecord.supplierName}</Descriptions.Item>
|
||||
<Descriptions.Item label="品类">{scoreRecord.category}</Descriptions.Item>
|
||||
<Descriptions.Item label="评价单位">{scoreRecord.evaluateUnit}</Descriptions.Item>
|
||||
<Descriptions.Item label="评价人员">{scoreRecord.evaluator}</Descriptions.Item>
|
||||
<Descriptions.Item label="评价时间">{scoreRecord.evaluateTime}</Descriptions.Item>
|
||||
<Descriptions.Item label="评价得分">{scoreRecord.score}</Descriptions.Item>
|
||||
<Descriptions.Item label="评价等级">
|
||||
{getEvaluateLevel(scoreRecord.score)}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
|
||||
<Card title="评价详情" bordered={false} className={styles.detailCard}>
|
||||
<GeneralEvaluation supplierName={scoreRecord.supplierName} />
|
||||
<Card title="评价指标详情" bordered={false} className={styles.detailCard}>
|
||||
<ScoreEvaluationTable
|
||||
value={formatDataForScoreTable()}
|
||||
isDetail={true}
|
||||
loading={loading}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
@ -8,33 +8,27 @@ import {
|
||||
Button,
|
||||
Table,
|
||||
Space,
|
||||
Tag,
|
||||
TablePaginationConfig,
|
||||
Modal,
|
||||
Row,
|
||||
Col,
|
||||
Tooltip,
|
||||
message,
|
||||
} from 'antd';
|
||||
import type { TablePaginationConfig } from 'antd';
|
||||
import {
|
||||
SearchOutlined,
|
||||
DeleteOutlined,
|
||||
ArrowLeftOutlined,
|
||||
FileTextOutlined,
|
||||
BarChartOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { history, useLocation } from 'umi';
|
||||
import moment from 'moment';
|
||||
import { EvaluateLevel, EvaluateLevelText, EvaluateLevelColor } from '@/dicts/supplierTemplateDict';
|
||||
import styles from './supplierEvaluateResult.less';
|
||||
import { getEvaluateSupplierList, getAllEvaluateRules } from '@/servers/api/supplierEvaluate';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
const location = useLocation<{ record: SupplierEvaluate.EvaluateResultRecord }>();
|
||||
const location = useLocation<{ record: API.EvaluateTaskRecord }>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
const [resultData, setResultData] = useState<SupplierEvaluate.EvaluateResultDetailRecord[]>([]);
|
||||
const [resultData, setResultData] = useState<API.EvaluateSupplierRecord[]>([]);
|
||||
const [pagination, setPagination] = useState<TablePaginationConfig>({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
@ -44,10 +38,11 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
showTotal: (total) => `共 ${total} 条记录`,
|
||||
});
|
||||
const [searchParams, setSearchParams] =
|
||||
useState<SupplierEvaluate.EvaluateResultDetailSearchParams>({});
|
||||
const [parentRecord, setParentRecord] = useState<SupplierEvaluate.EvaluateResultRecord | null>(
|
||||
useState<API.EvaluateSupplierSearchParams>({});
|
||||
const [parentRecord, setParentRecord] = useState<API.EvaluateTaskRecord | null>(
|
||||
null,
|
||||
);
|
||||
const [evaluateRules, setEvaluateRules] = useState<API.EvaluateRuleItem[]>([]);
|
||||
|
||||
// 品类数据
|
||||
const categoryOptions = [
|
||||
@ -58,12 +53,6 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
{ label: '医药', value: '医药' },
|
||||
];
|
||||
|
||||
// 评价等级选项
|
||||
const levelOptions = Object.entries(EvaluateLevelText).map(([value, label]) => ({
|
||||
label,
|
||||
value,
|
||||
}));
|
||||
|
||||
// 获取上级页面传递的数据
|
||||
useEffect(() => {
|
||||
if (location.state?.record) {
|
||||
@ -71,12 +60,38 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
// 模拟获取评价结果详情列表
|
||||
// 获取评价规则列表
|
||||
const fetchEvaluateRules = async () => {
|
||||
try {
|
||||
const response = await getAllEvaluateRules();
|
||||
if (response.success && response.data) {
|
||||
setEvaluateRules(response.data);
|
||||
} else {
|
||||
message.error(response.message || '获取评价规则列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价规则列表失败:', error);
|
||||
message.error('获取评价规则列表失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取评价规则列表
|
||||
useEffect(() => {
|
||||
fetchEvaluateRules();
|
||||
}, []);
|
||||
|
||||
// 获取评价结果详情列表
|
||||
const fetchResultDetailList = async (
|
||||
current = 1,
|
||||
pageSize = 10,
|
||||
params: SupplierEvaluate.EvaluateResultDetailSearchParams = searchParams,
|
||||
params: API.EvaluateSupplierSearchParams = searchParams,
|
||||
) => {
|
||||
// 确保有评价任务ID
|
||||
if (!parentRecord?.id) {
|
||||
message.error('缺少评价任务ID,无法获取数据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新搜索参数状态
|
||||
if (params !== searchParams) {
|
||||
setSearchParams(params);
|
||||
@ -84,77 +99,58 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
// 模拟API请求
|
||||
setTimeout(() => {
|
||||
// 模拟数据
|
||||
const mockData: SupplierEvaluate.EvaluateResultDetailRecord[] = Array.from({
|
||||
length: 35,
|
||||
}).map((_, index) => {
|
||||
const id = `${index + 1}`;
|
||||
// 构建请求参数
|
||||
const requestParams: API.EvaluateSupplierRequest = {
|
||||
basePageRequest: {
|
||||
pageNo: current,
|
||||
pageSize: pageSize,
|
||||
},
|
||||
evaluateTaskId: parentRecord.id,
|
||||
};
|
||||
|
||||
// 随机选择品类
|
||||
const categoryIndex = Math.floor(Math.random() * categoryOptions.length);
|
||||
// 添加搜索条件
|
||||
if (params.supplierName) {
|
||||
requestParams.supplierName = params.supplierName;
|
||||
}
|
||||
if (params.level) {
|
||||
requestParams.level = params.level;
|
||||
}
|
||||
|
||||
// 随机生成得分和等级
|
||||
const score = Math.floor(Math.random() * 40) + 60; // 60-100分
|
||||
let level;
|
||||
if (score >= 90) {
|
||||
level = EvaluateLevel.EXCELLENT;
|
||||
} else if (score >= 80) {
|
||||
level = EvaluateLevel.GOOD;
|
||||
} else if (score >= 70) {
|
||||
level = EvaluateLevel.AVERAGE;
|
||||
} else {
|
||||
level = EvaluateLevel.POOR;
|
||||
}
|
||||
// 调用接口获取数据
|
||||
const response = await getEvaluateSupplierList(requestParams);
|
||||
if (response.data && response.success) {
|
||||
const { records, total, current: currentPage, size } = response.data;
|
||||
|
||||
return {
|
||||
id,
|
||||
key: id,
|
||||
supplierName: `供应商${index + 1}`,
|
||||
category: categoryOptions[categoryIndex].value,
|
||||
score,
|
||||
level,
|
||||
};
|
||||
});
|
||||
// 处理数据,增加表格需要的key属性
|
||||
const formattedData = records.map(record => ({
|
||||
...record,
|
||||
key: record.id,
|
||||
}));
|
||||
|
||||
// 根据搜索条件过滤
|
||||
let filteredData = [...mockData];
|
||||
if (params.supplierName) {
|
||||
filteredData = filteredData.filter((item) =>
|
||||
item.supplierName.includes(params.supplierName || ''),
|
||||
);
|
||||
}
|
||||
if (params.level) {
|
||||
filteredData = filteredData.filter((item) => item.level === params.level);
|
||||
}
|
||||
|
||||
// 分页
|
||||
const startIndex = (current - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const paginatedData = filteredData.slice(startIndex, endIndex);
|
||||
|
||||
setResultData(paginatedData);
|
||||
setResultData(formattedData);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current,
|
||||
pageSize,
|
||||
total: filteredData.length,
|
||||
current: currentPage,
|
||||
pageSize: size,
|
||||
total,
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
} else {
|
||||
message.error(response.message || '获取评价结果详情列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价结果详情列表失败:', error);
|
||||
message.error('获取评价结果详情列表失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
useEffect(() => {
|
||||
fetchResultDetailList(pagination.current, pagination.pageSize, {});
|
||||
}, []);
|
||||
if (parentRecord?.id) {
|
||||
fetchResultDetailList(pagination.current, pagination.pageSize, {});
|
||||
}
|
||||
}, [parentRecord]);
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleTableChange = (newPagination: TablePaginationConfig) => {
|
||||
@ -178,31 +174,25 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
};
|
||||
|
||||
// 查看得分明细
|
||||
const handleViewScoreDetail = (record: SupplierEvaluate.EvaluateResultDetailRecord) => {
|
||||
const handleViewScoreDetail = (record: API.EvaluateSupplierRecord) => {
|
||||
history.push({
|
||||
pathname: 'supplierEvaluateResultScoreDetail',
|
||||
state: { record }
|
||||
state: { record, parentRecord }
|
||||
});
|
||||
};
|
||||
|
||||
// 查看打分情况
|
||||
const handleViewScoring = (record: SupplierEvaluate.EvaluateResultDetailRecord) => {
|
||||
const handleViewScoring = (record: API.EvaluateSupplierRecord) => {
|
||||
history.push({
|
||||
pathname: 'supplierEvaluateResultScoreByList',
|
||||
state: { record }
|
||||
state: { record, parentRecord }
|
||||
});
|
||||
};
|
||||
|
||||
// 获取等级标签
|
||||
const getLevelTag = (level: string) => {
|
||||
const text = EvaluateLevelText[level as keyof typeof EvaluateLevelText] || '未知等级';
|
||||
return text;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
render: (_: any, __: SupplierEvaluate.EvaluateResultDetailRecord, index: number) =>
|
||||
render: (_: any, __: API.EvaluateSupplierRecord, index: number) =>
|
||||
(pagination.current! - 1) * pagination.pageSize! + index + 1,
|
||||
width: 80,
|
||||
},
|
||||
@ -228,24 +218,23 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
},
|
||||
{
|
||||
title: '评价得分',
|
||||
dataIndex: 'score',
|
||||
key: 'score',
|
||||
dataIndex: 'reviewScore',
|
||||
key: 'reviewScore',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '评价等级',
|
||||
dataIndex: 'level',
|
||||
key: 'level',
|
||||
dataIndex: 'levelName',
|
||||
key: 'levelName',
|
||||
width: 100,
|
||||
align: 'center' as const,
|
||||
render: (level: string) => getLevelTag(level),
|
||||
align: 'center' as const
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 180,
|
||||
align: 'center' as const,
|
||||
render: (_: unknown, record: SupplierEvaluate.EvaluateResultDetailRecord) => (
|
||||
render: (_: unknown, record: API.EvaluateSupplierRecord) => (
|
||||
<Space size="middle">
|
||||
<Button
|
||||
type="link"
|
||||
@ -270,9 +259,9 @@ const SupplierEvaluateResultInfo: React.FC = () => {
|
||||
</Form.Item>
|
||||
<Form.Item name="level" label="评价等级">
|
||||
<Select placeholder="请选择评价等级" allowClear style={{ width: 150 }}>
|
||||
{levelOptions.map((option) => (
|
||||
<Option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
{evaluateRules.map((rule) => (
|
||||
<Option key={rule.id} value={rule.levelName}>
|
||||
{rule.levelName}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
|
@ -1,34 +1,58 @@
|
||||
// 供应商评价结果打分情况
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
Button,
|
||||
Table,
|
||||
Space,
|
||||
TablePaginationConfig,
|
||||
Tooltip,
|
||||
message,
|
||||
} from 'antd';
|
||||
import {
|
||||
SearchOutlined,
|
||||
DeleteOutlined,
|
||||
ArrowLeftOutlined,
|
||||
EyeOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import type { TablePaginationConfig } from 'antd';
|
||||
import { SearchOutlined, DeleteOutlined, ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { history, useLocation } from 'umi';
|
||||
import { EvaluateLevel, EvaluateLevelText } from '@/dicts/supplierTemplateDict';
|
||||
import styles from './supplierEvaluateResult.less';
|
||||
import { getEvaluateScoreList, getAllEvaluateRules } from '@/servers/api/supplierEvaluate';
|
||||
|
||||
// 为修复类型问题,定义新的评分数据结构
|
||||
interface ScoreDataItem {
|
||||
id: string;
|
||||
key: string;
|
||||
name?: string;
|
||||
supplierName: string;
|
||||
evaluateTheme: string;
|
||||
startTime?: string;
|
||||
endTime?: string;
|
||||
evaluateTime: string;
|
||||
status?: string;
|
||||
statusName?: string;
|
||||
score: string | number;
|
||||
suscore?: string | number;
|
||||
createBy?: string;
|
||||
createTime?: string;
|
||||
updateBy?: string;
|
||||
updateTime?: string;
|
||||
categoryName?: string; // 品类名称
|
||||
deptName?: string; // 评价单位
|
||||
evaluatorName?: string; // 评价人员
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// 自定义类型用于传递给详情页的数据
|
||||
interface DetailPageState {
|
||||
record: ScoreDataItem;
|
||||
parentRecord: API.EvaluateSupplierRecord | null;
|
||||
}
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
const location = useLocation<{ record: SupplierEvaluate.EvaluateResultDetailRecord }>();
|
||||
const location = useLocation<{
|
||||
record: API.EvaluateSupplierRecord;
|
||||
}>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
const [scoreData, setScoreData] = useState<any[]>([]);
|
||||
const [scoreData, setScoreData] = useState<ScoreDataItem[]>([]);
|
||||
const [pagination, setPagination] = useState<TablePaginationConfig>({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
@ -37,28 +61,50 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
showQuickJumper: true,
|
||||
showTotal: (total) => `共 ${total} 条记录`,
|
||||
});
|
||||
const [searchParams, setSearchParams] = useState<any>({});
|
||||
const [supplierRecord, setSupplierRecord] = useState<SupplierEvaluate.EvaluateResultDetailRecord | null>(null);
|
||||
const [searchParams, setSearchParams] = useState<API.EvaluateScoreSearchParams>({});
|
||||
const [record, setRecord] = useState<API.EvaluateSupplierRecord | null>(null);
|
||||
const [evaluateRules, setEvaluateRules] = useState<API.EvaluateRuleItem[]>([]);
|
||||
|
||||
// 评价等级选项
|
||||
const levelOptions = Object.entries(EvaluateLevelText).map(([value, label]) => ({
|
||||
label,
|
||||
value,
|
||||
}));
|
||||
// 获取评价规则列表
|
||||
const fetchEvaluateRules = async () => {
|
||||
try {
|
||||
const response = await getAllEvaluateRules();
|
||||
if (response.success && response.data) {
|
||||
setEvaluateRules(response.data);
|
||||
} else {
|
||||
message.error(response.message || '获取评价规则列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价规则列表失败:', error);
|
||||
message.error('获取评价规则列表失败');
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取评价规则列表
|
||||
useEffect(() => {
|
||||
fetchEvaluateRules();
|
||||
}, []);
|
||||
|
||||
// 获取上级页面传递的数据
|
||||
useEffect(() => {
|
||||
console.log(location.state);
|
||||
if (location.state?.record) {
|
||||
setSupplierRecord(location.state.record);
|
||||
setRecord(location.state.record);
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
// 模拟获取评价打分情况列表
|
||||
// 获取评价打分情况列表
|
||||
const fetchScoreList = async (
|
||||
current = 1,
|
||||
pageSize = 10,
|
||||
params: any = searchParams,
|
||||
params: API.EvaluateScoreSearchParams = searchParams,
|
||||
) => {
|
||||
// 确保有必要的参数
|
||||
if (!record?.supplierId || !record?.evaluateTaskId) {
|
||||
message.error('缺少必要参数,无法获取数据');
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新搜索参数状态
|
||||
if (params !== searchParams) {
|
||||
setSearchParams(params);
|
||||
@ -66,88 +112,76 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
// 模拟API请求
|
||||
setTimeout(() => {
|
||||
// 模拟数据
|
||||
const mockData = Array.from({ length: 35 }).map((_, index) => {
|
||||
const id = `${index + 1}`;
|
||||
// 构建请求参数
|
||||
const requestParams: API.EvaluateScoreRequest = {
|
||||
basePageRequest: {
|
||||
pageNo: current,
|
||||
pageSize: pageSize,
|
||||
},
|
||||
taskId: record.evaluateTaskId,
|
||||
supplierId: record.supplierId,
|
||||
...params,
|
||||
};
|
||||
|
||||
// 随机生成得分
|
||||
const score = Math.floor(Math.random() * 40) + 60; // 60-100分
|
||||
// 调用接口获取数据
|
||||
const response = await getEvaluateScoreList(requestParams);
|
||||
|
||||
// 评价单位
|
||||
const units = ['中山市合创展包装材料有限公司', '广州市科技发展有限公司', '深圳市创新科技有限公司', '东莞市制造业有限公司'];
|
||||
const unitIndex = Math.floor(Math.random() * units.length);
|
||||
// 新的接口返回格式,结构是: { success, data: { records, total, ... } }
|
||||
if (response.success && response.data) {
|
||||
const { records = [], total = 0, size = 10, current: currentPage = 1 } = response.data;
|
||||
|
||||
return {
|
||||
id,
|
||||
key: id,
|
||||
supplierName: supplierRecord?.supplierName || `供应商${index + 1}`,
|
||||
category: supplierRecord?.category || '电子',
|
||||
evaluateUnit: units[unitIndex],
|
||||
evaluator: `评价人${index + 1}`,
|
||||
evaluateTime: `2023-${Math.floor(Math.random() * 12) + 1}-${Math.floor(Math.random() * 28) + 1}`,
|
||||
score,
|
||||
};
|
||||
});
|
||||
if (records && records.length > 0) {
|
||||
// 格式化数据用于表格显示 - 使用新的字段名称
|
||||
const formattedData = records.map((item: any, index: number) => ({
|
||||
...item,
|
||||
key: index.toString(),
|
||||
supplierName: item.name || '-',
|
||||
evaluateTheme: item.evaluateTheme || '-',
|
||||
evaluateTime: item.endTime || item.startTime || '-',
|
||||
score: item.suscore || '0',
|
||||
status: item.statusName || '-',
|
||||
categoryName: item.categoryName || '-', // 品类
|
||||
deptName: item.deptName || '-', // 评价单位
|
||||
evaluatorName: item.evaluatorName || item.createBy || '-', // 评价人员
|
||||
}));
|
||||
|
||||
// 根据搜索条件过滤
|
||||
let filteredData = [...mockData];
|
||||
if (params.supplierName) {
|
||||
filteredData = filteredData.filter((item) =>
|
||||
item.supplierName.includes(params.supplierName || ''),
|
||||
);
|
||||
}
|
||||
if (params.level) {
|
||||
filteredData = filteredData.filter((item) => {
|
||||
let level;
|
||||
if (item.score >= 90) {
|
||||
level = EvaluateLevel.EXCELLENT;
|
||||
} else if (item.score >= 80) {
|
||||
level = EvaluateLevel.GOOD;
|
||||
} else if (item.score >= 70) {
|
||||
level = EvaluateLevel.AVERAGE;
|
||||
} else {
|
||||
level = EvaluateLevel.POOR;
|
||||
}
|
||||
return level === params.level;
|
||||
setScoreData(formattedData);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current: currentPage,
|
||||
pageSize: size,
|
||||
total,
|
||||
});
|
||||
} else {
|
||||
setScoreData([]);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current,
|
||||
pageSize,
|
||||
total: 0,
|
||||
});
|
||||
message.info('暂无评价打分数据');
|
||||
}
|
||||
|
||||
// 分页
|
||||
const startIndex = (current - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const paginatedData = filteredData.slice(startIndex, endIndex);
|
||||
|
||||
setScoreData(paginatedData);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current,
|
||||
pageSize,
|
||||
total: filteredData.length,
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
} else {
|
||||
message.error(response.message || '获取评价打分情况列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价打分情况列表失败:', error);
|
||||
message.error('获取评价打分情况列表失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
useEffect(() => {
|
||||
fetchScoreList(pagination.current, pagination.pageSize, {});
|
||||
}, []);
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleTableChange = (newPagination: TablePaginationConfig) => {
|
||||
fetchScoreList(newPagination.current, newPagination.pageSize, searchParams);
|
||||
};
|
||||
if (record?.supplierId && record?.evaluateTaskId) {
|
||||
fetchScoreList(pagination.current, pagination.pageSize);
|
||||
}
|
||||
}, [record]);
|
||||
|
||||
// 处理搜索
|
||||
const handleSearch = (values: any) => {
|
||||
const handleSearch = (values: API.EvaluateScoreSearchParams) => {
|
||||
fetchScoreList(1, pagination.pageSize, values);
|
||||
};
|
||||
|
||||
@ -163,25 +197,34 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
};
|
||||
|
||||
// 查看评价详情
|
||||
const handleViewDetail = (record: any) => {
|
||||
const handleViewDetail = (scoreItem: ScoreDataItem) => {
|
||||
const detailState: DetailPageState = {
|
||||
record: scoreItem,
|
||||
parentRecord: record
|
||||
};
|
||||
history.push({
|
||||
pathname: 'supplierEvaluateResultByZb',
|
||||
state: { record }
|
||||
state: detailState,
|
||||
});
|
||||
};
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleTableChange = (newPagination: TablePaginationConfig) => {
|
||||
fetchScoreList(newPagination.current, newPagination.pageSize, searchParams);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
render: (_: any, __: any, index: number) =>
|
||||
(pagination.current! - 1) * pagination.pageSize! + index + 1,
|
||||
width: 80,
|
||||
width: 60,
|
||||
},
|
||||
{
|
||||
title: '供应商名称',
|
||||
dataIndex: 'supplierName',
|
||||
key: 'supplierName',
|
||||
width: 200,
|
||||
width: 180,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
@ -193,15 +236,23 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
},
|
||||
{
|
||||
title: '品类',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
dataIndex: 'categoryName',
|
||||
key: 'categoryName',
|
||||
width: 120,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text: string) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '评价单位',
|
||||
dataIndex: 'evaluateUnit',
|
||||
key: 'evaluateUnit',
|
||||
width: 180,
|
||||
dataIndex: 'deptName',
|
||||
key: 'deptName',
|
||||
width: 150,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
@ -213,9 +264,17 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
},
|
||||
{
|
||||
title: '评价人员',
|
||||
dataIndex: 'evaluator',
|
||||
key: 'evaluator',
|
||||
dataIndex: 'evaluatorName',
|
||||
key: 'evaluatorName',
|
||||
width: 120,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (text: string) => (
|
||||
<Tooltip placement="topLeft" title={text}>
|
||||
{text}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '评价时间',
|
||||
@ -233,13 +292,10 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 100,
|
||||
width: 80,
|
||||
align: 'center' as const,
|
||||
render: (_: unknown, record: any) => (
|
||||
<Button
|
||||
type="link"
|
||||
onClick={() => handleViewDetail(record)}
|
||||
>
|
||||
render: (_: unknown, scoreItem: ScoreDataItem) => (
|
||||
<Button type="link" onClick={() => handleViewDetail(scoreItem)}>
|
||||
查看
|
||||
</Button>
|
||||
),
|
||||
@ -255,9 +311,9 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
</Form.Item>
|
||||
<Form.Item name="level" label="评价等级">
|
||||
<Select placeholder="请选择评价等级" allowClear style={{ width: 150 }}>
|
||||
{levelOptions.map((option) => (
|
||||
<Option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
{evaluateRules.map((rule) => (
|
||||
<Option key={rule.id} value={rule.levelName}>
|
||||
{rule.levelName}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
@ -285,7 +341,7 @@ const SupplierEvaluateResultScoreByList: React.FC = () => {
|
||||
pagination={pagination}
|
||||
loading={loading}
|
||||
onChange={handleTableChange}
|
||||
scroll={{ x: 1100 }}
|
||||
scroll={{ x: 1200 }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,37 +1,93 @@
|
||||
// 供应商评价结果得分明细
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Tabs, Button, Typography, Row, Col } from 'antd';
|
||||
import { Button, Typography, Card, Spin, message } from 'antd';
|
||||
import { ArrowLeftOutlined } from '@ant-design/icons';
|
||||
import { history, useLocation } from 'umi';
|
||||
import GeneralEvaluation from './components/GeneralEvaluation';
|
||||
import TechnicalEvaluation from './components/TechnicalEvaluation';
|
||||
import ScoreEvaluationTable from '@/components/ScoreEvaluationTable';
|
||||
import styles from './supplierEvaluateResult.less';
|
||||
import { getSupplierScoreDetail } from '@/servers/api/supplierEvaluate';
|
||||
|
||||
const { Title } = Typography;
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
const SupplierEvaluateResultScoreDetail: React.FC = () => {
|
||||
const location = useLocation<{ record: SupplierEvaluate.EvaluateResultDetailRecord }>();
|
||||
const [supplierRecord, setSupplierRecord] = useState<SupplierEvaluate.EvaluateResultDetailRecord | null>(null);
|
||||
const [activeTab, setActiveTab] = useState<string>('1');
|
||||
const location = useLocation<{
|
||||
record: API.EvaluateSupplierRecord;
|
||||
parentRecord: API.EvaluateTaskRecord;
|
||||
}>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [supplierRecord, setSupplierRecord] = useState<API.EvaluateSupplierRecord | null>(null);
|
||||
const [parentRecord, setParentRecord] = useState<API.EvaluateTaskRecord | null>(null);
|
||||
const [scoreDetail, setScoreDetail] = useState<API.EvaluateScoreDetailData | null>(null);
|
||||
|
||||
// 获取上级页面传递的数据
|
||||
useEffect(() => {
|
||||
if (location.state?.record) {
|
||||
setSupplierRecord(location.state.record);
|
||||
}
|
||||
if (location.state?.parentRecord) {
|
||||
setParentRecord(location.state.parentRecord);
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
// 处理Tab切换
|
||||
const handleTabChange = (key: string) => {
|
||||
setActiveTab(key);
|
||||
// 获取得分明细数据
|
||||
const fetchScoreDetail = async () => {
|
||||
if (!supplierRecord?.id) {
|
||||
message.error('缺少必要参数,无法获取数据');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await getSupplierScoreDetail(supplierRecord.id);
|
||||
|
||||
if (response.success && response.data) {
|
||||
setScoreDetail(response.data);
|
||||
} else {
|
||||
message.error(response.message || '获取评价得分明细失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价得分明细失败:', error);
|
||||
message.error('获取评价得分明细失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 当供应商记录加载完成后,获取得分明细
|
||||
useEffect(() => {
|
||||
if (supplierRecord?.id) {
|
||||
fetchScoreDetail();
|
||||
}
|
||||
}, [supplierRecord]);
|
||||
|
||||
// 返回上一页
|
||||
const handleBack = () => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
// 将API数据转换为ScoreEvaluationTable组件所需的格式
|
||||
const formatDataForScoreTable = () => {
|
||||
if (!scoreDetail?.taskIndicatorVo) return [];
|
||||
|
||||
return scoreDetail.taskIndicatorVo.map(indicator => {
|
||||
return {
|
||||
baseIndicator: indicator.baseIndicator,
|
||||
descIndicator: indicator.indicatorDesc,
|
||||
score: indicator.score,
|
||||
indicatorNdList: indicator.subIndicator?.map(subItem => {
|
||||
return {
|
||||
subIndicator: subItem.subIndicator,
|
||||
score: subItem.subScore,
|
||||
isStar: subItem.starIndicator,
|
||||
id: subItem.id,
|
||||
actualScore: subItem.scoreNum || subItem.subScore,
|
||||
remark: subItem.remark || ''
|
||||
};
|
||||
}) || []
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<div className={styles.headerRow}>
|
||||
@ -48,14 +104,19 @@ const SupplierEvaluateResultScoreDetail: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="content-area">
|
||||
<Tabs activeKey={activeTab} onChange={handleTabChange} type="card">
|
||||
<TabPane tab="通用评价" key="1">
|
||||
<GeneralEvaluation supplierName={supplierRecord?.supplierName} />
|
||||
</TabPane>
|
||||
<TabPane tab="技术评价" key="2">
|
||||
<TechnicalEvaluation supplierName={supplierRecord?.supplierName} />
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
<Card bordered={false}>
|
||||
{loading ? (
|
||||
<div className="loading-container" style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<Spin tip="加载中..." />
|
||||
</div>
|
||||
) : (
|
||||
<ScoreEvaluationTable
|
||||
value={formatDataForScoreTable()}
|
||||
isDetail={true}
|
||||
loading={loading}
|
||||
/>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -0,0 +1,347 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Button, Table, Space, message, Tooltip, Modal, Tag, Form, Input, InputNumber } from 'antd';
|
||||
import { PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons';
|
||||
import type { TablePaginationConfig } from 'antd';
|
||||
import { useIntl, FormattedMessage } from 'umi';
|
||||
import {
|
||||
getAllEvaluateRules,
|
||||
getEvaluateRuleDetail,
|
||||
addEvaluateRule,
|
||||
updateEvaluateRule,
|
||||
deleteEvaluateRule
|
||||
} from '@/servers/api/supplierEvaluate';
|
||||
|
||||
// 定义规则表单数据类型
|
||||
interface RuleFormData {
|
||||
id?: string;
|
||||
beginValue: string;
|
||||
endValue: string;
|
||||
levelName: string;
|
||||
ratingName?: string;
|
||||
remark?: string;
|
||||
}
|
||||
|
||||
const SupplierEvaluateRuleManage: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [ruleData, setRuleData] = useState<API.EvaluateRuleItem[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
const [modalVisible, setModalVisible] = useState<boolean>(false);
|
||||
const [modalTitle, setModalTitle] = useState<string>(intl.formatMessage({ id: 'supplierEvaluateRuleManage.modal.add' }));
|
||||
const [editingRule, setEditingRule] = useState<API.EvaluateRuleItem | null>(null);
|
||||
const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
|
||||
|
||||
// 获取规则列表
|
||||
const fetchRuleList = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await getAllEvaluateRules();
|
||||
if (response.success && response.data) {
|
||||
setRuleData(response.data);
|
||||
} else {
|
||||
message.error(response.message || intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.getList.error' }));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价规则列表失败:', error);
|
||||
message.error(intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.getList.error' }));
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
useEffect(() => {
|
||||
fetchRuleList();
|
||||
}, []);
|
||||
|
||||
// 处理添加规则
|
||||
const handleAdd = () => {
|
||||
setModalTitle(intl.formatMessage({ id: 'supplierEvaluateRuleManage.modal.add' }));
|
||||
setEditingRule(null);
|
||||
form.resetFields();
|
||||
setModalVisible(true);
|
||||
};
|
||||
|
||||
// 处理编辑规则
|
||||
const handleEdit = async (record: API.EvaluateRuleItem) => {
|
||||
setModalTitle(intl.formatMessage({ id: 'supplierEvaluateRuleManage.modal.edit' }));
|
||||
setEditingRule(record);
|
||||
|
||||
try {
|
||||
// 获取规则详情
|
||||
const response = await getEvaluateRuleDetail(record.id);
|
||||
if (response.success && response.data) {
|
||||
const ruleDetail = response.data;
|
||||
form.setFieldsValue({
|
||||
id: ruleDetail.id,
|
||||
beginValue: ruleDetail.beginValue,
|
||||
endValue: ruleDetail.endValue,
|
||||
levelName: ruleDetail.levelName,
|
||||
ratingName: ruleDetail.ratingName || '',
|
||||
remark: ruleDetail.remark || '',
|
||||
});
|
||||
setModalVisible(true);
|
||||
} else {
|
||||
message.error(response.message || intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.getDetail.error' }));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取评价规则详情失败:', error);
|
||||
message.error(intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.getDetail.error' }));
|
||||
}
|
||||
};
|
||||
|
||||
// 处理删除规则
|
||||
const handleDelete = (record: API.EvaluateRuleItem) => {
|
||||
Modal.confirm({
|
||||
title: intl.formatMessage({ id: 'supplierEvaluateRuleManage.modal.delete' }),
|
||||
icon: <ExclamationCircleOutlined />,
|
||||
content: intl.formatMessage(
|
||||
{ id: 'supplierEvaluateRuleManage.modal.delete.content' },
|
||||
{ levelName: record.levelName }
|
||||
),
|
||||
okText: intl.formatMessage({ id: 'supplierEvaluateRuleManage.confirm' }),
|
||||
cancelText: intl.formatMessage({ id: 'supplierEvaluateRuleManage.cancel' }),
|
||||
onOk: async () => {
|
||||
try {
|
||||
const response = await deleteEvaluateRule(record.id);
|
||||
if (response.success) {
|
||||
message.success(
|
||||
intl.formatMessage(
|
||||
{ id: 'supplierEvaluateRuleManage.message.delete.success' },
|
||||
{ levelName: record.levelName }
|
||||
)
|
||||
);
|
||||
fetchRuleList(); // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.delete.error' }));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('删除评价规则失败:', error);
|
||||
message.error(intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.delete.error' }));
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 处理表单提交
|
||||
const handleFormSubmit = async () => {
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
setConfirmLoading(true);
|
||||
|
||||
if (editingRule) {
|
||||
// 更新规则
|
||||
const updateParams: API.EvaluateRuleUpdateRequest = {
|
||||
id: editingRule.id,
|
||||
beginValue: String(values.beginValue),
|
||||
endValue: String(values.endValue),
|
||||
levelName: values.levelName,
|
||||
remark: values.remark,
|
||||
};
|
||||
|
||||
const response = await updateEvaluateRule(updateParams);
|
||||
if (response.success) {
|
||||
message.success(intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.update.success' }));
|
||||
setModalVisible(false);
|
||||
fetchRuleList(); // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.update.error' }));
|
||||
}
|
||||
} else {
|
||||
// 新增规则
|
||||
const addParams: API.EvaluateRuleAddRequest = {
|
||||
beginValue: String(values.beginValue),
|
||||
endValue: String(values.endValue),
|
||||
levelName: values.levelName,
|
||||
ratingName: values.ratingName || '',
|
||||
remark: values.remark,
|
||||
};
|
||||
|
||||
const response = await addEvaluateRule(addParams);
|
||||
if (response.success) {
|
||||
message.success(intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.add.success' }));
|
||||
setModalVisible(false);
|
||||
fetchRuleList(); // 刷新列表
|
||||
} else {
|
||||
message.error(response.message || intl.formatMessage({ id: 'supplierEvaluateRuleManage.message.add.error' }));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('表单验证或提交失败:', error);
|
||||
} finally {
|
||||
setConfirmLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 取消表单
|
||||
const handleCancel = () => {
|
||||
setModalVisible(false);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: <FormattedMessage id="supplierEvaluateRuleManage.column.index" />,
|
||||
render: (_: any, __: any, index: number) => index + 1,
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="supplierEvaluateRuleManage.column.levelName" />,
|
||||
dataIndex: 'levelName',
|
||||
key: 'levelName',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="supplierEvaluateRuleManage.column.ratingName" />,
|
||||
dataIndex: 'ratingName',
|
||||
key: 'ratingName',
|
||||
width: 150,
|
||||
render: (ratingName: string) => ratingName || '-',
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="supplierEvaluateRuleManage.column.scoreRange" />,
|
||||
key: 'scoreRange',
|
||||
width: 150,
|
||||
render: (_: any, record: API.EvaluateRuleItem) => `${record.beginValue} - ${record.endValue}`,
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="supplierEvaluateRuleManage.column.remark" />,
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
width: 200,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (remark: string) => (
|
||||
<Tooltip placement="topLeft" title={remark}>
|
||||
{remark || '-'}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: <FormattedMessage id="supplierEvaluateRuleManage.column.action" />,
|
||||
key: 'action',
|
||||
width: 150,
|
||||
align: 'center' as const,
|
||||
render: (_: unknown, record: API.EvaluateRuleItem) => (
|
||||
<Space size="middle">
|
||||
<Button type="link" onClick={() => handleEdit(record)}>
|
||||
<FormattedMessage id="supplierEvaluateRuleManage.edit" />
|
||||
</Button>
|
||||
<Button type="link" onClick={() => handleDelete(record)}>
|
||||
<FormattedMessage id="supplierEvaluateRuleManage.delete" />
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<div className="action-row" style={{ marginBottom: '16px', display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button type="primary" ghost icon={<PlusOutlined />} onClick={handleAdd}>
|
||||
<FormattedMessage id="supplierEvaluateRuleManage.add" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="content-area">
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={ruleData}
|
||||
loading={loading}
|
||||
rowKey="id"
|
||||
scroll={{ x: 1500 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 新增/编辑规则模态框 */}
|
||||
<Modal
|
||||
title={modalTitle}
|
||||
visible={modalVisible}
|
||||
onCancel={handleCancel}
|
||||
maskClosable={false}
|
||||
width={600}
|
||||
confirmLoading={confirmLoading}
|
||||
onOk={handleFormSubmit}
|
||||
okText={intl.formatMessage({ id: 'supplierEvaluateRuleManage.submit' })}
|
||||
cancelText={intl.formatMessage({ id: 'supplierEvaluateRuleManage.cancel' })}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
initialValues={{
|
||||
beginValue: '',
|
||||
endValue: '',
|
||||
levelName: '',
|
||||
ratingName: '',
|
||||
remark: '',
|
||||
}}
|
||||
>
|
||||
{editingRule && (
|
||||
<Form.Item name="id" hidden>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item
|
||||
name="levelName"
|
||||
label={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.levelName' })}
|
||||
rules={[{ required: true, message: intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.levelName.required' }) }]}
|
||||
>
|
||||
<Input placeholder={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.levelName.placeholder' })} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="ratingName"
|
||||
label={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.ratingName' })}
|
||||
rules={[{ required: !editingRule, message: intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.ratingName.required' }) }]}
|
||||
>
|
||||
<Input placeholder={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.ratingName.placeholder' })} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="beginValue"
|
||||
label={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.beginValue' })}
|
||||
rules={[
|
||||
{ required: true, message: intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.beginValue.required' }) },
|
||||
{
|
||||
pattern: /^[1-9]\d*$/,
|
||||
message: intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.beginValue.integer' })
|
||||
}
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={0} style={{ width: '100%' }} placeholder={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.beginValue.placeholder' })} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="endValue"
|
||||
label={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.endValue' })}
|
||||
rules={[
|
||||
{ required: true, message: intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.endValue.required' }) },
|
||||
{
|
||||
pattern: /^[1-9]\d*$/,
|
||||
message: intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.endValue.integer' })
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(_, value) {
|
||||
if (!value || !getFieldValue('beginValue')) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
if (parseInt(value) <= parseInt(getFieldValue('beginValue'))) {
|
||||
return Promise.reject(new Error(intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.endValue.greater' })));
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<InputNumber min={0} precision={0} style={{ width: '100%' }} placeholder={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.endValue.placeholder' })} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="remark"
|
||||
label={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.remark' })}
|
||||
>
|
||||
<Input.TextArea rows={4} placeholder={intl.formatMessage({ id: 'supplierEvaluateRuleManage.form.remark.placeholder' })} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierEvaluateRuleManage;
|
@ -0,0 +1,21 @@
|
||||
// 供应商评价打分页面样式
|
||||
.headerRow {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.titleSection {
|
||||
flex: 1;
|
||||
|
||||
.pageTitle {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.actionSection {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
@ -1,346 +1,203 @@
|
||||
// 供应商评价打分
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
Button,
|
||||
Table,
|
||||
Space,
|
||||
Tag,
|
||||
DatePicker,
|
||||
TablePaginationConfig,
|
||||
Tooltip,
|
||||
message,
|
||||
} from 'antd';
|
||||
import {
|
||||
SearchOutlined,
|
||||
DeleteOutlined,
|
||||
PlusOutlined,
|
||||
EditOutlined,
|
||||
EyeOutlined,
|
||||
FormOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { TaskStatus, TaskStatusText, TaskStatusColor } from '@/dicts/supplierTaskDict';
|
||||
import moment from 'moment';
|
||||
import { Button, Card, Form, message, Typography, Spin, Space } from 'antd';
|
||||
import { ArrowLeftOutlined, SaveOutlined } from '@ant-design/icons';
|
||||
import { history, useLocation } from 'umi';
|
||||
import ScoreEvaluationTable from '@/components/ScoreEvaluationTable';
|
||||
import styles from './supplierEvaluateScore.less';
|
||||
import { getSupplierScoreDetail, submitEvaluateScore } from '@/servers/api/supplierEvaluate';
|
||||
|
||||
const { Option } = Select;
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
// 定义搜索参数接口
|
||||
interface ScoreSearchParams {
|
||||
evaluateTitle?: string;
|
||||
supplierName?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
// 定义打分记录接口
|
||||
interface ScoreRecord {
|
||||
id: string;
|
||||
evaluateTitle: string;
|
||||
supplierName: string;
|
||||
category: string;
|
||||
status: string;
|
||||
scoreStatus: string; // 打分状态:未打分、已打分、已提交
|
||||
createTime: string;
|
||||
key: string;
|
||||
}
|
||||
|
||||
// 打分状态
|
||||
const ScoreStatus = {
|
||||
NOT_SCORED: 'not_scored',
|
||||
SCORED: 'scored',
|
||||
SUBMITTED: 'submitted',
|
||||
};
|
||||
|
||||
const ScoreStatusText = {
|
||||
[ScoreStatus.NOT_SCORED]: '未打分',
|
||||
[ScoreStatus.SCORED]: '已打分',
|
||||
[ScoreStatus.SUBMITTED]: '已提交',
|
||||
};
|
||||
|
||||
const ScoreStatusColor = {
|
||||
[ScoreStatus.NOT_SCORED]: 'orange',
|
||||
[ScoreStatus.SCORED]: 'blue',
|
||||
[ScoreStatus.SUBMITTED]: 'green',
|
||||
};
|
||||
const { Title } = Typography;
|
||||
|
||||
const SupplierEvaluateScore: React.FC = () => {
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [form] = Form.useForm();
|
||||
const [scoreData, setScoreData] = useState<ScoreRecord[]>([]);
|
||||
const [pagination, setPagination] = useState<TablePaginationConfig>({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: (total) => `共 ${total} 条记录`,
|
||||
});
|
||||
const [searchParams, setSearchParams] = useState<ScoreSearchParams>({});
|
||||
const location = useLocation<{
|
||||
record: API.EvaluateSupplierRecord;
|
||||
parentRecord: API.EvaluateTaskRecord;
|
||||
}>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [submitting, setSubmitting] = useState<boolean>(false);
|
||||
const [supplierRecord, setSupplierRecord] = useState<API.EvaluateSupplierRecord | null>(null);
|
||||
const [parentRecord, setParentRecord] = useState<API.EvaluateTaskRecord | null>(null);
|
||||
const [scoreDetail, setScoreDetail] = useState<API.EvaluateScoreDetailData | null>(null);
|
||||
const [scoreData, setScoreData] = useState<any[]>([]);
|
||||
|
||||
// 品类数据
|
||||
const categoryOptions = [
|
||||
{ label: '食品', value: '食品' },
|
||||
{ label: '电子', value: '电子' },
|
||||
{ label: '机械', value: '机械' },
|
||||
{ label: '化工', value: '化工' },
|
||||
{ label: '医药', value: '医药' },
|
||||
];
|
||||
// 获取上级页面传递的数据
|
||||
useEffect(() => {
|
||||
if (location.state?.record) {
|
||||
setSupplierRecord(location.state.record);
|
||||
}
|
||||
if (location.state?.parentRecord) {
|
||||
setParentRecord(location.state.parentRecord);
|
||||
}
|
||||
}, [location]);
|
||||
|
||||
// 模拟获取打分列表
|
||||
const fetchScoreList = async (
|
||||
current = 1,
|
||||
pageSize = 10,
|
||||
params: ScoreSearchParams = searchParams,
|
||||
) => {
|
||||
// 更新搜索参数状态
|
||||
if (params !== searchParams) {
|
||||
setSearchParams(params);
|
||||
// 将API数据转换为ScoreEvaluationTable组件所需的格式
|
||||
const formatDataForScoreTable = (data: API.EvaluateScoreDetailData | null) => {
|
||||
if (!data?.taskIndicatorVo) return [];
|
||||
|
||||
return data.taskIndicatorVo.map(indicator => {
|
||||
return {
|
||||
baseIndicator: indicator.baseIndicator,
|
||||
descIndicator: indicator.indicatorDesc,
|
||||
score: indicator.score,
|
||||
indicatorNdList: indicator.subIndicator?.map(subItem => {
|
||||
return {
|
||||
subIndicator: subItem.subIndicator,
|
||||
score: subItem.subScore,
|
||||
isStar: subItem.starIndicator,
|
||||
id: subItem.id,
|
||||
actualScore: subItem.scoreNum || '',
|
||||
remark: subItem.remark || ''
|
||||
};
|
||||
}) || []
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 获取得分明细数据
|
||||
const fetchScoreDetail = async () => {
|
||||
if (!supplierRecord?.id) {
|
||||
message.error('缺少必要参数,无法获取数据');
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
// 模拟API请求
|
||||
setTimeout(() => {
|
||||
// 模拟数据
|
||||
const mockData: ScoreRecord[] = Array.from({ length: 35 }).map((_, index) => {
|
||||
const id = `${index + 1}`;
|
||||
const status = Object.values(TaskStatus)[Math.floor(Math.random() * 3)];
|
||||
const scoreStatus = Object.values(ScoreStatus)[Math.floor(Math.random() * 3)];
|
||||
const response = await getSupplierScoreDetail(supplierRecord.id);
|
||||
|
||||
// 随机选择品类
|
||||
const categoryIndex = Math.floor(Math.random() * categoryOptions.length);
|
||||
if (response.success && response.data) {
|
||||
setScoreDetail(response.data);
|
||||
|
||||
return {
|
||||
id,
|
||||
key: id,
|
||||
evaluateTitle: `供应商评价任务${index + 1}`,
|
||||
supplierName: `供应商${index + 1}`,
|
||||
category: categoryOptions[categoryIndex].value,
|
||||
status,
|
||||
scoreStatus,
|
||||
createTime: moment().subtract(Math.floor(Math.random() * 90), 'days').format('YYYY-MM-DD HH:mm:ss'),
|
||||
};
|
||||
});
|
||||
|
||||
// 根据搜索条件过滤
|
||||
let filteredData = [...mockData];
|
||||
if (params.evaluateTitle) {
|
||||
filteredData = filteredData.filter(item =>
|
||||
item.evaluateTitle.includes(params.evaluateTitle || '')
|
||||
);
|
||||
}
|
||||
if (params.supplierName) {
|
||||
filteredData = filteredData.filter(item =>
|
||||
item.supplierName.includes(params.supplierName || '')
|
||||
);
|
||||
}
|
||||
if (params.status) {
|
||||
filteredData = filteredData.filter(item =>
|
||||
item.scoreStatus === params.status
|
||||
);
|
||||
}
|
||||
|
||||
// 分页
|
||||
const startIndex = (current - 1) * pageSize;
|
||||
const endIndex = startIndex + pageSize;
|
||||
const paginatedData = filteredData.slice(startIndex, endIndex);
|
||||
|
||||
setScoreData(paginatedData);
|
||||
setPagination({
|
||||
...pagination,
|
||||
current,
|
||||
pageSize,
|
||||
total: filteredData.length,
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
}, 500);
|
||||
// 转换数据格式
|
||||
const formattedData = formatDataForScoreTable(response.data);
|
||||
setScoreData(formattedData);
|
||||
} else {
|
||||
message.error(response.message || '获取评价得分明细失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取打分列表失败:', error);
|
||||
message.error('获取打分列表失败');
|
||||
console.error('获取评价得分明细失败:', error);
|
||||
message.error('获取评价得分明细失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 首次加载获取数据
|
||||
// 当供应商记录加载完成后,获取得分明细
|
||||
useEffect(() => {
|
||||
fetchScoreList(pagination.current, pagination.pageSize, {});
|
||||
}, []);
|
||||
if (supplierRecord?.id) {
|
||||
fetchScoreDetail();
|
||||
}
|
||||
}, [supplierRecord]);
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleTableChange = (newPagination: TablePaginationConfig) => {
|
||||
fetchScoreList(newPagination.current, newPagination.pageSize, searchParams);
|
||||
// 返回上一页
|
||||
const handleBack = () => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
// 处理搜索
|
||||
const handleSearch = (values: any) => {
|
||||
fetchScoreList(1, pagination.pageSize, values);
|
||||
// 处理评分数据变更
|
||||
const handleScoreDataChange = (newData: any[]) => {
|
||||
setScoreData(newData);
|
||||
};
|
||||
|
||||
// 处理重置
|
||||
const handleReset = () => {
|
||||
form.resetFields();
|
||||
fetchScoreList(1, pagination.pageSize, {});
|
||||
};
|
||||
// 提交评分
|
||||
const handleSubmit = async () => {
|
||||
if (!supplierRecord?.id) {
|
||||
message.error('缺少必要参数,无法提交');
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理打分
|
||||
const handleScore = (record: ScoreRecord) => {
|
||||
message.info(`开始为 ${record.supplierName} 打分`);
|
||||
};
|
||||
// 验证所有二级指标是否都已评分
|
||||
const hasEmptyScore = scoreData.some(item =>
|
||||
item.indicatorNdList.some((subItem: any) =>
|
||||
!subItem.actualScore && subItem.actualScore !== 0
|
||||
)
|
||||
);
|
||||
|
||||
// 处理查看
|
||||
const handleView = (record: ScoreRecord) => {
|
||||
message.info(`查看 ${record.supplierName} 的打分情况`);
|
||||
};
|
||||
if (hasEmptyScore) {
|
||||
message.warning('请为所有指标填写评分');
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理提交
|
||||
const handleSubmit = (record: ScoreRecord) => {
|
||||
message.success(`已提交 ${record.supplierName} 的评分`);
|
||||
fetchScoreList(pagination.current, pagination.pageSize, searchParams);
|
||||
};
|
||||
setSubmitting(true);
|
||||
try {
|
||||
// 构建提交数据
|
||||
const submitData = {
|
||||
id: supplierRecord.id,
|
||||
taskIndicatorVo: scoreData.map(item => ({
|
||||
baseIndicator: item.baseIndicator,
|
||||
indicatorDesc: item.descIndicator,
|
||||
score: item.score,
|
||||
subIndicator: item.indicatorNdList.map((subItem: any) => ({
|
||||
id: subItem.id,
|
||||
subIndicator: subItem.subIndicator,
|
||||
subScore: subItem.score,
|
||||
starIndicator: subItem.isStar,
|
||||
scoreNum: subItem.actualScore,
|
||||
remark: subItem.remark
|
||||
}))
|
||||
}))
|
||||
};
|
||||
|
||||
// 获取状态标签
|
||||
const getScoreStatusTag = (status: string) => {
|
||||
const color = ScoreStatusColor[status as keyof typeof ScoreStatusColor] || 'default';
|
||||
const text = ScoreStatusText[status as keyof typeof ScoreStatusText] || '未知状态';
|
||||
return <Tag color={color}>{text}</Tag>;
|
||||
};
|
||||
const response = await submitEvaluateScore(submitData);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
render: (_: any, __: ScoreRecord, index: number) =>
|
||||
(pagination.current! - 1) * pagination.pageSize! + index + 1,
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '评价主题',
|
||||
dataIndex: 'evaluateTitle',
|
||||
key: 'evaluateTitle',
|
||||
width: 200,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (evaluateTitle: string) => (
|
||||
<Tooltip placement="topLeft" title={evaluateTitle}>
|
||||
{evaluateTitle}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '供应商名称',
|
||||
dataIndex: 'supplierName',
|
||||
key: 'supplierName',
|
||||
width: 150,
|
||||
ellipsis: {
|
||||
showTitle: false,
|
||||
},
|
||||
render: (supplierName: string) => (
|
||||
<Tooltip placement="topLeft" title={supplierName}>
|
||||
{supplierName}
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '品类',
|
||||
dataIndex: 'category',
|
||||
key: 'category',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '打分状态',
|
||||
dataIndex: 'scoreStatus',
|
||||
key: 'scoreStatus',
|
||||
width: 100,
|
||||
render: (status: string) => getScoreStatusTag(status),
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 200,
|
||||
align: 'center' as const,
|
||||
render: (_: unknown, record: ScoreRecord) => (
|
||||
<Space size="middle">
|
||||
{record.scoreStatus === ScoreStatus.NOT_SCORED && (
|
||||
<Button
|
||||
type="link"
|
||||
icon={<FormOutlined />}
|
||||
onClick={() => handleScore(record)}
|
||||
>
|
||||
打分
|
||||
</Button>
|
||||
)}
|
||||
{record.scoreStatus === ScoreStatus.SCORED && (
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => handleSubmit(record)}
|
||||
>
|
||||
提交
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type="link"
|
||||
icon={<EyeOutlined />}
|
||||
onClick={() => handleView(record)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
if (response.success) {
|
||||
message.success('评分提交成功');
|
||||
// 提交成功后返回列表页
|
||||
history.goBack();
|
||||
} else {
|
||||
message.error(response.message || '评分提交失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('评分提交失败:', error);
|
||||
message.error('评分提交失败');
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<div className="filter-action-row">
|
||||
<Form form={form} layout="inline" onFinish={handleSearch} className="filter-form">
|
||||
<Form.Item name="evaluateTitle" label="评价主题">
|
||||
<Input placeholder="请输入评价主题" allowClear />
|
||||
</Form.Item>
|
||||
<Form.Item name="supplierName" label="供应商名称">
|
||||
<Input placeholder="请输入供应商名称" allowClear />
|
||||
</Form.Item>
|
||||
<Form.Item name="status" label="打分状态">
|
||||
<Select placeholder="请选择状态" allowClear style={{ width: 150 }}>
|
||||
<Option value={ScoreStatus.NOT_SCORED}>{ScoreStatusText[ScoreStatus.NOT_SCORED]}</Option>
|
||||
<Option value={ScoreStatus.SCORED}>{ScoreStatusText[ScoreStatus.SCORED]}</Option>
|
||||
<Option value={ScoreStatus.SUBMITTED}>{ScoreStatusText[ScoreStatus.SUBMITTED]}</Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item className="filter-btns">
|
||||
<Button type="primary" icon={<SearchOutlined />} onClick={() => form.submit()}>
|
||||
搜索
|
||||
<div className={styles.headerRow}>
|
||||
<div className={styles.titleSection}>
|
||||
<Title level={4} className={styles.pageTitle}>
|
||||
{supplierRecord?.supplierName || '供应商'} - 评价打分
|
||||
</Title>
|
||||
</div>
|
||||
<div className={styles.actionSection}>
|
||||
<Space>
|
||||
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
||||
返回
|
||||
</Button>
|
||||
<Button type="primary" danger icon={<DeleteOutlined />} onClick={handleReset}>
|
||||
重置
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<SaveOutlined />}
|
||||
onClick={handleSubmit}
|
||||
loading={submitting}
|
||||
>
|
||||
提交
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="right-buttons">
|
||||
<Button type="primary" ghost icon={<PlusOutlined />} onClick={() => message.info('新增打分任务')}>
|
||||
新增
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="content-area">
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={scoreData}
|
||||
pagination={pagination}
|
||||
loading={loading}
|
||||
onChange={handleTableChange}
|
||||
scroll={{ x: 1100 }}
|
||||
/>
|
||||
<Card bordered={false}>
|
||||
{loading ? (
|
||||
<div className="loading-container" style={{ textAlign: 'center', padding: '50px' }}>
|
||||
<Spin tip="加载中..." />
|
||||
</div>
|
||||
) : (
|
||||
<Form form={form} layout="vertical">
|
||||
<ScoreEvaluationTable
|
||||
value={scoreData}
|
||||
onChange={handleScoreDataChange}
|
||||
isDetail={false}
|
||||
loading={loading}
|
||||
/>
|
||||
</Form>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -32,7 +32,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
.template-indicator-card {
|
||||
margin-bottom: 24px;
|
||||
|
||||
.indicator-area {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.ant-card-head {
|
||||
padding: 0 0 16px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.ant-card-head-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
margin-top: 24px;
|
||||
|
@ -322,6 +322,7 @@ const SupplierTemplateManage: React.FC = () => {
|
||||
<div className="content-area">
|
||||
<Table
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={templateData}
|
||||
pagination={pagination}
|
||||
loading={loading}
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
CategoryLimitationTypeText,
|
||||
StarLevel,
|
||||
} from '@/dicts/supplierTemplateDict';
|
||||
import EvaluateTemplateTable from '@/components/EvaluateTemplateTable';
|
||||
import ScoreEvaluationTable from '@/components/ScoreEvaluationTable';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
@ -114,7 +114,7 @@ const SupplierTemplateManageDetail: React.FC = () => {
|
||||
|
||||
<Card title="评价指标" bordered={false}>
|
||||
{templateData.length > 0 ? (
|
||||
<EvaluateTemplateTable
|
||||
<ScoreEvaluationTable
|
||||
value={templateData}
|
||||
isDetail={true}
|
||||
/>
|
||||
|
@ -206,3 +206,130 @@ export async function getEvaluateResultList(params: API.EvaluateTaskRequest) {
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评价结果详情列表(供应商列表)
|
||||
* @param params 查询参数
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function getEvaluateSupplierList(params: API.EvaluateSupplierRequest) {
|
||||
return request<API.APIResponse<API.EvaluateSupplierData>>('/coscoEvaluate/supplier/getPage', {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取供应商评价打分情况
|
||||
* @param params 查询参数
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function getEvaluateScoreList(params: API.EvaluateScoreRequest) {
|
||||
return request<API.APIResponse<API.PageResponse<any>>>('/coscoEvaluate/supplier/getSupplierDimension', {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评价打分详情
|
||||
* @param id 评价记录ID
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function getEvaluateScoreDetail(id: string) {
|
||||
return request<API.APIResponse<API.EvaluateScoreDetailData>>(`/coscoEvaluate/user/getIndicator?id=${id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有评价规则列表
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function getAllEvaluateRules() {
|
||||
return request<API.EvaluateRuleResponse>('/coscoEvaluate/level/getAllList', {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评价规则详情
|
||||
* @param id 规则ID
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function getEvaluateRuleDetail(id: string) {
|
||||
return request<API.EvaluateRuleDetailResponse>(`/coscoEvaluate/level/${id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增评价规则
|
||||
* @param params 规则数据
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function addEvaluateRule(params: API.EvaluateRuleAddRequest) {
|
||||
return request<API.APIResponse<any>>('/coscoEvaluate/level', {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新评价规则
|
||||
* @param params 规则数据
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function updateEvaluateRule(params: API.EvaluateRuleUpdateRequest) {
|
||||
return request<API.APIResponse<any>>('/coscoEvaluate/level', {
|
||||
method: 'PUT',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除评价规则
|
||||
* @param id 规则ID
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function deleteEvaluateRule(id: string) {
|
||||
return request<API.APIResponse<any>>(`/coscoEvaluate/level/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取供应商评价得分明细
|
||||
* @param id 评价记录ID
|
||||
* @returns Promise
|
||||
*/
|
||||
export async function getSupplierScoreDetail(id: string) {
|
||||
return request<API.APIResponse<API.EvaluateScoreDetailData>>(`/coscoEvaluate/supplier/getScoreResult`, {
|
||||
method: 'GET',
|
||||
params: { id }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交供应商评价得分
|
||||
* @param params 评价得分数据
|
||||
* @returns
|
||||
*/
|
||||
export async function submitEvaluateScore(params: any) {
|
||||
return request('/api/supplier/evaluate/score/submit', {
|
||||
method: 'POST',
|
||||
data: params,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取评价打分详情
|
||||
* @param id 评价记录ID
|
||||
* @returns
|
||||
*/
|
||||
export async function getIndicator(id: string) {
|
||||
return request('/coscoEvaluate/user/getIndicator', {
|
||||
method: 'GET',
|
||||
params: { id },
|
||||
});
|
||||
}
|
||||
|
634
src/servers/api/typings.d.ts
vendored
634
src/servers/api/typings.d.ts
vendored
@ -6,33 +6,6 @@ declare namespace API {
|
||||
data: T;
|
||||
}
|
||||
|
||||
export type PolicyRequest = {
|
||||
/**
|
||||
* 内容
|
||||
*/
|
||||
content: string;
|
||||
/**
|
||||
* 内容_英文版
|
||||
*/
|
||||
contentEn: string;
|
||||
/**
|
||||
* 是否置顶(0.否、1.是)
|
||||
*/
|
||||
isTop: string;
|
||||
/**
|
||||
* 是否设置英文内容(0.否、1.是)
|
||||
*/
|
||||
settingEn: number;
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
title: string;
|
||||
/**
|
||||
* 标题英文
|
||||
*/
|
||||
titleEn: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type RegisterRequest = {
|
||||
coscoSupplierBank: CoscoSupplierBank[];
|
||||
@ -171,73 +144,6 @@ declare namespace API {
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 政策法规数据项
|
||||
export interface PolicyRecord {
|
||||
basePageRequest: null;
|
||||
content: string;
|
||||
contentEn: string;
|
||||
createBy: string;
|
||||
createDate: null;
|
||||
createTime: string;
|
||||
deleteFlag: null;
|
||||
delFlag: string;
|
||||
id: string;
|
||||
isTop: string;
|
||||
lastUpdateTime: null;
|
||||
publishBy: string | null;
|
||||
publishTime: string | null;
|
||||
settingEn: string;
|
||||
status: string;
|
||||
tenantId: string | null;
|
||||
tenantName: string | null;
|
||||
title: string;
|
||||
titleEn: string | null;
|
||||
updateBy: string | null;
|
||||
updateDate: string | null;
|
||||
updateTime: string;
|
||||
}
|
||||
|
||||
// 政策法规请求参数
|
||||
export interface PolicyRequest {
|
||||
id?: string;
|
||||
title: string;
|
||||
titleEn: string;
|
||||
content: string;
|
||||
contentEn: string;
|
||||
isTop: string;
|
||||
settingEn: number;
|
||||
}
|
||||
|
||||
// 下载中心数据项
|
||||
export interface DownloadRecord {
|
||||
id: string;
|
||||
name: string;
|
||||
category: string;
|
||||
keyword: string;
|
||||
createTime: string;
|
||||
createBy: string;
|
||||
status: string; // 状态:0-草稿,1-已发布
|
||||
thumbnail?: string; // 缩略图URL
|
||||
fileUrl?: string; // 文件URL
|
||||
}
|
||||
|
||||
// 下载中心请求参数
|
||||
export interface DownloadRequest {
|
||||
id?: string;
|
||||
name: string;
|
||||
category: string;
|
||||
keyword: string;
|
||||
fileId?: string;
|
||||
thumbnailId?: string;
|
||||
}
|
||||
|
||||
// 下载中心查询参数
|
||||
export interface DownloadSearchParams {
|
||||
name?: string;
|
||||
category?: string;
|
||||
status?: string;
|
||||
}
|
||||
|
||||
// 文件上传响应
|
||||
export interface UploadResponse {
|
||||
id: string;
|
||||
@ -247,266 +153,7 @@ declare namespace API {
|
||||
fileUrl: string;
|
||||
}
|
||||
|
||||
// 通知中心数据项
|
||||
export interface NoticeRecord {
|
||||
id: string;
|
||||
title: string;
|
||||
titleEn?: string;
|
||||
content: string;
|
||||
contentEn?: string;
|
||||
createTime: string;
|
||||
createBy: string;
|
||||
status: string; // 状态:0-草稿,1-已发布,2-已下架
|
||||
isTop: string; // 是否置顶:0-否,1-是
|
||||
settingEn?: number; // 是否设置英文:0-否,1-是
|
||||
}
|
||||
|
||||
// 通知中心请求参数
|
||||
export interface NoticeRequest {
|
||||
id?: string;
|
||||
title: string;
|
||||
titleEn?: string;
|
||||
content: string;
|
||||
contentEn?: string;
|
||||
isTop: string;
|
||||
settingEn?: number;
|
||||
}
|
||||
|
||||
// 通知中心查询参数
|
||||
export interface NoticeSearchParams {
|
||||
title?: string;
|
||||
status?: string;
|
||||
pageNo?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// 帮助中心数据项
|
||||
export interface HelpRecord {
|
||||
id: string;
|
||||
title: string;
|
||||
titleEn?: string;
|
||||
type: string; // 类型,对应页面中的category
|
||||
content: string;
|
||||
contentEn?: string;
|
||||
createTime: string;
|
||||
createBy: string;
|
||||
updateTime?: string;
|
||||
updateBy?: string;
|
||||
status: string; // 状态:0-草稿,1-已发布,2-已下架
|
||||
isTop: string; // 是否置顶:0-否,1-是
|
||||
settingEn: number; // 是否设置英文:0-否,1-是
|
||||
answerContent?: string;
|
||||
answerContentNe?: string;
|
||||
publishBy?: string | null;
|
||||
publishTime?: string | null;
|
||||
deleteFlag?: null;
|
||||
delFlag?: string;
|
||||
tenantId?: string | null;
|
||||
tenantName?: string | null;
|
||||
lastUpdateTime?: null;
|
||||
createDate?: null;
|
||||
updateDate?: null;
|
||||
basePageRequest?: null;
|
||||
}
|
||||
|
||||
// 帮助中心请求参数
|
||||
export interface HelpRequest {
|
||||
id?: string;
|
||||
title: string;
|
||||
titleEn?: string;
|
||||
type: string; // 类型,对应页面中的category
|
||||
content: string;
|
||||
contentEn?: string;
|
||||
isTop: string;
|
||||
settingEn: number;
|
||||
answerContent?: string;
|
||||
answerContentNe?: number;
|
||||
}
|
||||
|
||||
// 帮助中心查询参数
|
||||
export interface HelpSearchParams {
|
||||
title?: string;
|
||||
type?: string; // 类型,对应页面中的category
|
||||
status?: string;
|
||||
pageNo?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// 用户提问数据项
|
||||
export interface UserQuestionRecord {
|
||||
id: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
email?: string;
|
||||
question: string;
|
||||
answer?: string;
|
||||
createTime: string;
|
||||
answerTime?: string;
|
||||
status: string; // 状态:0-未回答,1-已回答
|
||||
}
|
||||
|
||||
// 用户提问查询参数
|
||||
export interface UserQuestionSearchParams {
|
||||
question?: string;
|
||||
status?: string;
|
||||
pageNo?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
// 用户问题记录类型
|
||||
interface QuestionRecord {
|
||||
id: string;
|
||||
title: string;
|
||||
type: string;
|
||||
content: string;
|
||||
answerContent?: string;
|
||||
userName: string;
|
||||
companyName: string;
|
||||
fullName: string;
|
||||
contactDetails: string;
|
||||
email: string;
|
||||
askTime: string;
|
||||
answerTime?: string;
|
||||
answerBy?: string;
|
||||
isAnswer: string; // 0-未回答,1-已回答
|
||||
isPublished?: number; // 0-未发布,1-已发布
|
||||
isTop?: number; // 0-未置顶,1-已置顶
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
}
|
||||
|
||||
// 问题列表请求参数
|
||||
interface QuestionListRequest {
|
||||
isAnswer?: number; // 0-未回答,1-已回答
|
||||
title?: string;
|
||||
type?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 问题添加请求参数
|
||||
interface QuestionAddRequest {
|
||||
title: string;
|
||||
content: string;
|
||||
type: string;
|
||||
fullName: string;
|
||||
companyName: string;
|
||||
userName: string;
|
||||
contactDetails: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
// 问题回答请求参数
|
||||
interface QuestionAnswerRequest {
|
||||
id: string;
|
||||
answerContent: string;
|
||||
isPublished?: number; // 0-未发布,1-已发布
|
||||
isTop?: number; // 0-未置顶,1-已置顶
|
||||
}
|
||||
|
||||
// 问题状态更新请求参数
|
||||
interface QuestionStatusRequest {
|
||||
id: string;
|
||||
isPublished?: number; // 0-未发布,1-已发布
|
||||
isTop?: number; // 0-未置顶,1-已置顶
|
||||
}
|
||||
// 友情链接分类类型定义
|
||||
interface CategoryType {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
parentId: string;
|
||||
orderBy: string;
|
||||
remark: string;
|
||||
delFlag?: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
createBy?: string;
|
||||
updateBy?: string;
|
||||
key?: string;
|
||||
children?: CategoryType[];
|
||||
}
|
||||
|
||||
// 友情链接类型定义
|
||||
interface LinkType {
|
||||
id: string;
|
||||
classificationId: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
thumbnail: string;
|
||||
url: string;
|
||||
status: string;
|
||||
orderBy: string;
|
||||
createTime?: string;
|
||||
updateTime?: string;
|
||||
categoryName?: string; // 用于显示
|
||||
// 以下是详情接口返回的额外字段
|
||||
createBy?: string;
|
||||
createDate?: string | null;
|
||||
updateBy?: string | null;
|
||||
updateDate?: string | null;
|
||||
tenantId?: string | null;
|
||||
tenantName?: string | null;
|
||||
deleteFlag?: string | null;
|
||||
lastUpdateTime?: string | null;
|
||||
delFlag?: string;
|
||||
remark?: string | null;
|
||||
basePageRequest?: null;
|
||||
}
|
||||
// 友情链接分类请求参数
|
||||
export interface CategoryRequest {
|
||||
id?: string;
|
||||
name: string;
|
||||
type: string;
|
||||
parentId: string;
|
||||
orderBy: string;
|
||||
remark: string;
|
||||
}
|
||||
|
||||
// 友情链接分类响应数据
|
||||
export interface CategoryItem {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
parentId: string;
|
||||
orderBy: string;
|
||||
remark: string;
|
||||
delFlag: string;
|
||||
createTime: string;
|
||||
updateTime: string;
|
||||
createBy: string;
|
||||
updateBy?: string;
|
||||
}
|
||||
|
||||
// 友情链接请求参数
|
||||
export interface LinkRequest {
|
||||
id?: string | number;
|
||||
classificationId: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
thumbnail: string;
|
||||
url: string;
|
||||
orderBy: number | string;
|
||||
}
|
||||
|
||||
// 友情链接响应数据
|
||||
export interface LinkItem {
|
||||
id: string;
|
||||
classificationId: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
thumbnail: string;
|
||||
url: string;
|
||||
status: string;
|
||||
orderBy: string;
|
||||
delFlag: string;
|
||||
createTime: string;
|
||||
updateTime: string;
|
||||
createBy: string;
|
||||
updateBy?: string;
|
||||
remark?: string;
|
||||
basePageRequest?: null;
|
||||
}
|
||||
|
||||
//
|
||||
// 供应商评价任务状态枚举
|
||||
export enum TaskStatus {
|
||||
DRAFT = '0', // 草稿
|
||||
@ -612,6 +259,285 @@ declare namespace API {
|
||||
timeRange?: [string, string];
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价结果详情查询请求
|
||||
export interface EvaluateSupplierRequest {
|
||||
basePageRequest: BasePageRequest;
|
||||
evaluateTaskId: string;
|
||||
isAnswer?: number;
|
||||
supplierName?: string;
|
||||
level?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价结果详情响应数据
|
||||
export interface EvaluateSupplierData {
|
||||
countId: null;
|
||||
current: number;
|
||||
hitCount: boolean;
|
||||
maxLimit: null;
|
||||
optimizeCountSql: boolean;
|
||||
orders: any[];
|
||||
pages: number;
|
||||
records: EvaluateSupplierRecord[];
|
||||
searchCount: boolean;
|
||||
size: number;
|
||||
total: number;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价结果详情记录
|
||||
export interface EvaluateSupplierRecord {
|
||||
basePageRequest: null;
|
||||
createBy: string;
|
||||
createDate: null;
|
||||
createTime: string;
|
||||
deleteFlag: null;
|
||||
delFlag: string;
|
||||
evaluateTaskId: string;
|
||||
id: string;
|
||||
lastUpdateTime: null;
|
||||
reviewResult: null | string;
|
||||
reviewScore: null | number;
|
||||
supplierId: string;
|
||||
tenantId: null;
|
||||
tenantName: null;
|
||||
updateBy: string;
|
||||
updateDate: null;
|
||||
updateTime: string;
|
||||
supplierName?: string; // 供应商名称
|
||||
category?: string; // 品类
|
||||
level?: string; // 评价等级
|
||||
score?: number; // 评价得分
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价结果详情查询参数
|
||||
export interface EvaluateSupplierSearchParams {
|
||||
evaluateTaskId?: string;
|
||||
supplierName?: string;
|
||||
level?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价打分情况请求
|
||||
export interface EvaluateScoreRequest {
|
||||
basePageRequest: BasePageRequest;
|
||||
taskId: string;
|
||||
supplierId: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价打分情况响应数据
|
||||
export interface EvaluateScoreData {
|
||||
categoryId: null;
|
||||
categoryLimitation: string;
|
||||
createBy: null;
|
||||
createDate: null;
|
||||
createTime: null;
|
||||
deleteFlag: null;
|
||||
delFlag: string;
|
||||
deptId: null;
|
||||
endTime: string;
|
||||
evaluateTheme: string;
|
||||
evaluateYear: string;
|
||||
id: string;
|
||||
indicatorList: EvaluateScoreIndicator[];
|
||||
lastUpdateTime: null;
|
||||
startTime: string;
|
||||
status: string;
|
||||
supplierIds: EvaluateSupplierId[];
|
||||
templateId: string;
|
||||
tenantId: null;
|
||||
tenantName: null;
|
||||
updateBy: null;
|
||||
updateDate: null;
|
||||
updateTime: null;
|
||||
weightDept: null;
|
||||
weightStatus: string;
|
||||
weightValue: null;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 评价指标列表
|
||||
export interface EvaluateScoreIndicator {
|
||||
indicatorIds: null[];
|
||||
type: string;
|
||||
userId: string;
|
||||
userName?: string;
|
||||
evaluateUnit?: string;
|
||||
evaluateTime?: string;
|
||||
score?: string | number;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商ID列表
|
||||
export interface EvaluateSupplierId {
|
||||
id: string;
|
||||
userIds: any[];
|
||||
supplierName?: string;
|
||||
category?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价打分情况查询参数
|
||||
export interface EvaluateScoreSearchParams {
|
||||
supplierName?: string;
|
||||
evaluateUnit?: string;
|
||||
level?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价打分详情查询请求
|
||||
export interface EvaluateScoreDetailRequest {
|
||||
id: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 供应商评价打分详情响应数据
|
||||
export interface EvaluateScoreDetailData {
|
||||
taskIndicatorVo?: {
|
||||
baseIndicator: string; // 一级指标名称
|
||||
indicatorDesc?: string; // 指标说明
|
||||
score: string; // 一级指标分值
|
||||
subIndicator?: {
|
||||
id: string; // 二级指标ID
|
||||
subIndicator: string; // 二级指标名称
|
||||
subScore: string; // 二级指标分值
|
||||
starIndicator?: string; // 是否星号项
|
||||
scoreNum?: string; // 实际得分
|
||||
remark?: string; // 评分说明
|
||||
}[];
|
||||
}[];
|
||||
// 其他字段...
|
||||
}
|
||||
|
||||
// 评价指标数据
|
||||
export interface TaskIndicatorVo {
|
||||
baseIndicator: string;
|
||||
indicatorDesc: string;
|
||||
score: string;
|
||||
subIndicator: SubIndicator[];
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 二级指标数据
|
||||
export interface SubIndicator {
|
||||
id: string;
|
||||
remark: null;
|
||||
scoreNum: null;
|
||||
starIndicator: string;
|
||||
stId: string;
|
||||
subIndicator: string;
|
||||
subScore: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 评价规则相关类型定义
|
||||
export interface EvaluateRuleResponse {
|
||||
code: number;
|
||||
data: EvaluateRuleItem[];
|
||||
message: string;
|
||||
success: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface EvaluateRuleDetailResponse {
|
||||
code: number;
|
||||
data: EvaluateRuleItem;
|
||||
message: string;
|
||||
success: boolean;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface EvaluateRuleItem {
|
||||
beginValue: string;
|
||||
createBy: string;
|
||||
createDate: null;
|
||||
createTime: string;
|
||||
deleteFlag: null;
|
||||
delFlag: string;
|
||||
endValue: string;
|
||||
id: string;
|
||||
lastUpdateTime: null;
|
||||
levelName: string;
|
||||
remark: string;
|
||||
ratingName?: string;
|
||||
tenantId: null;
|
||||
tenantName: null;
|
||||
updateBy: string;
|
||||
updateDate: null;
|
||||
updateTime: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface EvaluateRuleAddRequest {
|
||||
/**
|
||||
* 阈值起始区间值
|
||||
*/
|
||||
beginValue: string;
|
||||
/**
|
||||
* 阈值截至区间值
|
||||
*/
|
||||
endValue: string;
|
||||
/**
|
||||
* 等级名称(A、B、C...)
|
||||
*/
|
||||
levelName: string;
|
||||
/**
|
||||
* 评级名称(优秀供应商、良好供应商、应辅导供应商、应淘汰供应商)
|
||||
*/
|
||||
ratingName: string;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export interface EvaluateRuleUpdateRequest {
|
||||
/**
|
||||
* 规则ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* 阈值起始区间值
|
||||
*/
|
||||
beginValue: string | number;
|
||||
/**
|
||||
* 阈值截至区间值
|
||||
*/
|
||||
endValue: string | number;
|
||||
/**
|
||||
* 等级名称(A、B、C...)
|
||||
*/
|
||||
levelName: string;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
remark?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
// 评价打分详情数据
|
||||
interface IndicatorDetailData {
|
||||
category: string;
|
||||
name: string;
|
||||
taskIndicatorVo: {
|
||||
baseIndicator: string;
|
||||
indicatorDesc: string;
|
||||
score: string;
|
||||
subIndicator: {
|
||||
id: string;
|
||||
remark: string | null;
|
||||
scoreNum: string | null;
|
||||
starIndicator: string;
|
||||
stId: string;
|
||||
subIndicator: string;
|
||||
subScore: string;
|
||||
}[];
|
||||
}[];
|
||||
}
|
||||
}
|
||||
|
||||
// 供应商评价模块类型定义
|
||||
|
Reference in New Issue
Block a user