修复ts警告,增加供应商评价模板管理一级指标二级指标的禁用逻辑

This commit is contained in:
linxd
2025-07-02 15:33:36 +08:00
parent aa7f985a74
commit 1dc59c9587
14 changed files with 247 additions and 144 deletions

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { Table, Input, Button, Space, message } from 'antd';
import type { TablePaginationConfig } from 'antd/es/table';
import { SearchOutlined } from '@ant-design/icons';
@ -131,7 +131,7 @@ const EvaluateTaskPersonnelSelector: React.FC<EvaluateTaskPersonnelSelectorProps
* @param {string[]} selectedRowKeys - 选中的行keys
* @param {API.PersonnelItem[]} selectedRows - 选中的行数据
*/
const handleSelectChange = (selectedRowKeys: React.Key[], selectedRows: API.PersonnelItem[]) => {
const handleSelectChange = (selectedRowKeys: React.Key[]) => {
setSelectedKeys(selectedRowKeys as string[]);
};

View File

@ -1,23 +1,15 @@
// 供应商评价 模板管理新增中的table
import React, { useState, useEffect } from 'react';
import { useIntl } from 'umi';
import {
Table,
Input,
Button,
Select,
Form,
InputNumber,
message,
Popconfirm,
} from 'antd';
import { Table, Input, Button, Select, InputNumber, message, Popconfirm } from 'antd';
import {
PlusOutlined,
MinusCircleOutlined,
PlusCircleOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import { getDictList, DictItem } from '@/servers/api/dicts';
import { getDictList } from '@/servers/api/dicts';
import type { DictItem } from '@/servers/api/dicts';
import { StarLevel, StarLevelText } from '@/dicts/supplierTemplateDict';
import { generateUUID } from '@/utils/utils';
import './EvaluateTemplateTable.less';
@ -35,6 +27,12 @@ interface EvaluateTemplateTableProps {
}
// 内部使用的数据结构,扁平化后的行数据
/**
* 表格行数据结构
* 重要:区分了一级指标和二级指标的禁用状态
* - disabledSt一级指标禁用状态同一组内应该保持一致
* - disabledNd二级指标禁用状态独立控制每个二级指标
*/
interface TableRowItem {
key: string;
stId?: string; // 一级指标ID
@ -50,6 +48,8 @@ interface TableRowItem {
orderBy?: number;
ndOrderBy?: number;
selected?: boolean; // 是否选中
disabledSt?: boolean; // 是否禁用一级
disabledNd?: boolean; // 是否禁用二级
}
const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
@ -62,7 +62,6 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
}) => {
const intl = useIntl();
const [dataSource, setDataSource] = useState<TableRowItem[]>([]);
const [form] = Form.useForm();
const [indicatorTypes, setIndicatorTypes] = useState<DictItem[]>([]);
const [loadingTypes, setLoadingTypes] = useState<boolean>(false);
@ -74,17 +73,26 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
if (res.success && res.data) {
setIndicatorTypes(res.data);
} else {
message.error(intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.message.getTypeFailed' }));
message.error(
intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.message.getTypeFailed' }),
);
}
} catch (error) {
console.error('获取指标类型失败:', error);
message.error(intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.message.getTypeFailed' }));
message.error(
intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.message.getTypeFailed' }),
);
} finally {
setLoadingTypes(false);
}
};
// 将API数据转换为表格数据
/**
* 将API数据转换为表格数据
*
* 重要说明这里处理了禁用状态的转换将API数据中的disabled属性映射到表格数据的disabledSt和disabledNd属性
* 确保一级指标和二级指标的禁用状态能正确保留
*/
const convertApiDataToTableData = (apiData: any[]): TableRowItem[] => {
// 检查数据是否已经是扁平化的表格数据格式
if (apiData.length > 0 && 'subIndicator' in apiData[0]) {
@ -97,15 +105,16 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
isStar: item.isStar || StarLevel.NO,
orderBy: typeof item.stOrderBy === 'string' ? parseInt(item.stOrderBy) : item.stOrderBy,
ndOrderBy: typeof item.orderBy === 'string' ? parseInt(item.orderBy) : item.orderBy,
selected: defaultSelectedIds.includes(item.id) // 根据defaultSelectedIds设置选中状态
selected: defaultSelectedIds.includes(item.id), // 根据defaultSelectedIds设置选中状态
disabledSt: item.disabledSt ?? false,
disabledNd: item.disabledNd,
}));
}
// 如果是嵌套结构,需要扁平化处理
if (apiData.length > 0 && 'indicatorNdList' in apiData[0]) {
const flattenedData: TableRowItem[] = [];
apiData.forEach((stItem: any, stIndex: number) => {
apiData.forEach((stItem: any) => {
stItem.indicatorNdList.forEach((ndItem: any, ndIndex: number) => {
flattenedData.push({
key: ndItem.id || `${stItem.id}-${ndIndex}`,
@ -120,34 +129,41 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
isStar: ndItem.isStar || StarLevel.NO,
descScore: ndItem.descScore,
orderBy: typeof stItem.orderBy === 'string' ? parseInt(stItem.orderBy) : stItem.orderBy,
ndOrderBy: typeof ndItem.orderBy === 'string' ? parseInt(ndItem.orderBy) : ndItem.orderBy,
selected: defaultSelectedIds.includes(ndItem.id) // 根据defaultSelectedIds设置选中状态
ndOrderBy:
typeof ndItem.orderBy === 'string' ? parseInt(ndItem.orderBy) : ndItem.orderBy,
selected: defaultSelectedIds.includes(ndItem.id), // 根据defaultSelectedIds设置选中状态
// 关键点1将API数据中的disabled属性映射到表格数据的disabledSt和disabledNd
// 这确保了一级指标的禁用状态正确传递到所有相关行,二级指标保持自己的禁用状态
disabledSt: stItem.disabled, // 根据disabled设置一级禁用状态
disabledNd: ndItem.disabled, // 根据disabled设置二级禁用状态
});
});
});
return flattenedData;
}
return [];
};
// 将表格数据转换回API格式
const convertTableDataToApiData = (tableData: TableRowItem[]): any[] => {
// 按一级指标分组
const groupedByLevel1 = tableData.reduce((acc: Record<string, TableRowItem[]>, item: TableRowItem) => {
// 为空的baseIndicator也需要分组使用特殊键标识
const groupKey = item.baseIndicator || `empty-${item.key}`;
const groupedByLevel1 = tableData.reduce(
(acc: Record<string, TableRowItem[]>, item: TableRowItem) => {
// 为空的baseIndicator也需要分组使用特殊键标识
const groupKey = item.baseIndicator || `empty-${item.key}`;
if (!acc[groupKey]) {
acc[groupKey] = [];
}
acc[groupKey].push(item);
return acc;
}, {});
if (!acc[groupKey]) {
acc[groupKey] = [];
}
acc[groupKey].push(item);
return acc;
},
{},
);
// 转换为API需要的格式
return Object.keys(groupedByLevel1).map((groupKey, stIndex) => {
const result = Object.keys(groupedByLevel1).map((groupKey, stIndex) => {
const level1Items = groupedByLevel1[groupKey];
const firstItem = level1Items[0];
@ -161,6 +177,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
score: firstItem.stScore || '0',
orderBy: firstItem.orderBy || stIndex + 1,
indicatorType: firstItem.indicatorType || '',
disabled: firstItem.disabledSt, // 关键点2: 保留一级指标的禁用状态确保在回传API格式时不丢失
indicatorNdList: level1Items.map((item, ndIndex) => {
// 生成唯一的临时ID
const tempNdId = `temp-nd-${generateUUID(16)}-${stIndex}-${ndIndex}`;
@ -171,17 +188,21 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
score: item.ndScore || '0',
isStar: item.isStar || StarLevel.NO,
orderBy: item.ndOrderBy || ndIndex + 1,
descScore: item.descScore || ''
descScore: item.descScore || '',
disabled: item.disabledNd, // 关键点3: 保留二级指标的禁用状态确保在回传API格式时不丢失
};
})
}),
};
});
return result;
};
// 初始化数据和获取字典
useEffect(() => {
// 获取指标类型字典
fetchIndicatorTypes();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 确保数据中没有重复的key
@ -202,22 +223,24 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
// 单独处理value变化
useEffect(() => {
// 初始化表格数据或value变化时更新
if (value && value.length > 0) {
// 避免不必要的状态更新,比较新旧数据是否相同
const currentValueStr = JSON.stringify(value);
const currentDataSourceApiStr = dataSource.length > 0 ?
JSON.stringify(convertTableDataToApiData(dataSource)) : '';
const currentDataSourceApiStr =
dataSource.length > 0 ? JSON.stringify(convertTableDataToApiData(dataSource)) : '';
if (currentValueStr !== currentDataSourceApiStr) {
const tableData = convertApiDataToTableData(value);
// 保留现有项的key确保稳定性
if (dataSource && dataSource.length > 0) {
const updatedTableData = tableData.map((newItem) => {
// 尝试查找对应的现有项通过stId和ndId匹配
const existingItem = dataSource.find(existing =>
(existing.stId === newItem.stId && existing.ndId === newItem.ndId) ||
(existing.baseIndicator === newItem.baseIndicator && existing.subIndicator === newItem.subIndicator)
const existingItem = dataSource.find(
(existing) =>
(existing.stId === newItem.stId && existing.ndId === newItem.ndId) ||
(existing.baseIndicator === newItem.baseIndicator &&
existing.subIndicator === newItem.subIndicator),
);
// 如果找到现有项保留其key和selected状态
@ -225,7 +248,9 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return {
...newItem,
key: existingItem.key,
selected: defaultSelectedIds.includes(newItem.ndId || '') ? true : existingItem.selected
selected: defaultSelectedIds.includes(newItem.ndId || '')
? true
: existingItem.selected,
};
}
@ -248,17 +273,17 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
// 处理defaultSelectedIds变化
useEffect(() => {
if (defaultSelectedIds.length > 0 && dataSource.length > 0) {
const newData = dataSource.map(item => ({
const newData = dataSource.map((item) => ({
...item,
selected: defaultSelectedIds.includes(item.ndId || '')
selected: defaultSelectedIds.includes(item.ndId || ''),
}));
console.log("newData",newData)
setDataSource(newData);
// 如果有onSelect回调传递所有选中的项
if (onSelect) {
const selectedItems = newData.filter(item => item.selected);
const selectedItems = newData.filter((item) => item.selected);
// 转换为API格式再传递给父组件
const selectedApiData = convertTableDataToApiData(selectedItems);
onSelect(selectedApiData);
@ -268,6 +293,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
// 更新数据源
const updateDataSource = (newData: TableRowItem[]) => {
// 确保每行都有唯一稳定的key
const finalData = ensureUniqueKeys(newData);
@ -281,7 +307,6 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
// 处理勾选状态变化
const handleCheckChange = (record: TableRowItem, checked: boolean) => {
console.log("handleCheckChange")
const newData = [...dataSource];
const index = newData.findIndex((item) => item.key === record.key);
if (index > -1) {
@ -290,7 +315,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
// 如果有onSelect回调传递所有选中的项
if (onSelect) {
const selectedItems = newData.filter(item => item.selected);
const selectedItems = newData.filter((item) => item.selected);
// 转换为API格式再传递给父组件
const selectedApiData = convertTableDataToApiData(selectedItems);
onSelect(selectedApiData);
@ -312,7 +337,11 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
// 检查是否有重复的baseIndicator
const existingNames = newData.map((d) => d.baseIndicator).filter(Boolean);
if (existingNames.includes(val)) {
message.warning(intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.message.duplicateName' }));
message.warning(
intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.message.duplicateName',
}),
);
return;
}
}
@ -351,7 +380,10 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
}
};
// 添加一级指标
/**
* 添加一级指标
* 重要添加新行时需要正确设置disabledSt和disabledNd属性否则会导致禁用状态丢失
*/
const addLevel1Indicator = (currentRecord?: TableRowItem) => {
// 使用改进后的工具函数生成唯一key
const newKey = `level1-${generateUUID(32)}`;
@ -369,16 +401,20 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
orderBy: dataSource.length + 1, // 确保正确的排序
ndOrderBy: 1, // 设置二级指标初始排序
selected: false, // 默认未选中
// 关键点4确保新添加的行也有正确的禁用属性否则会导致现有禁用状态丢失
disabledSt: false, // 默认不禁用一级指标
disabledNd: false, // 默认不禁用二级指标
};
// 制作数据源的副本,避免直接修改状态
const newData = [...dataSource];
const newData = dataSource.map(item => ({ ...item }));
// 找到当前记录所在的一级指标组的最后一行
let insertIndex = -1;
if (currentRecord && currentRecord.baseIndicator) {
// 找到相同baseIndicator的最后一个元素
const sameGroup = newData.filter((item) => item.baseIndicator === currentRecord.baseIndicator);
const sameGroup = newData.filter(
(item) => item.baseIndicator === currentRecord.baseIndicator,
);
const lastOfGroup = sameGroup[sameGroup.length - 1];
insertIndex = newData.findIndex((item) => item.key === lastOfGroup.key);
} else if (currentRecord && currentRecord.key) {
@ -393,6 +429,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
newData.push(newItem);
}
updateDataSource(newData);
};
@ -410,7 +447,10 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
updateDataSource(newData);
};
// 添加二级指标
/**
* 添加二级指标
* 重要:添加二级指标时需要从父级继承一级指标的禁用状态,确保同组内禁用状态一致
*/
const addSubIndicator = (parentKey: string) => {
// 使用工具函数生成唯一key
const newKey = `level2-${generateUUID(16)}`;
@ -418,7 +458,11 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
const parent = dataSource.find((item) => item.key === parentKey);
if (!parent || !parent.baseIndicator) {
message.warning(intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.baseIndicator' }));
message.warning(
intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.baseIndicator',
}),
);
return;
}
@ -432,8 +476,12 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
ndScore: '0',
isStar: StarLevel.NO,
descScore: '',
ndOrderBy: dataSource.filter(item => item.baseIndicator === parent.baseIndicator).length + 1,
ndOrderBy:
dataSource.filter((item) => item.baseIndicator === parent.baseIndicator).length + 1,
selected: false, // 默认未选中
// 关键点7继承父级的一级指标禁用状态确保同组内禁用状态一致
disabledSt: parent.disabledSt, // 继承父级的一级指标禁用状态
disabledNd: false, // 默认不禁用二级指标
};
// 找到当前记录所在的位置
@ -447,6 +495,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
newData.push(newItem);
}
updateDataSource(newData);
};
@ -465,7 +514,12 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return dataSource.filter((item) => item.baseIndicator === baseIndicator).length;
};
// 处理合并单元格
/**
* 处理合并单元格
*
* 重要这是解决问题的关键方法通过检查同组内是否有任何行的disabledSt为true
* 来决定是否禁用整个一级指标组的控件
*/
const renderWithRowSpan = (
content: any,
record: TableRowItem,
@ -486,8 +540,19 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
const index = level1Items.findIndex((item) => item.key === record.key);
if (index === 0) {
// 关键点5检查同组内是否有任何行的disabledSt为true
// 这是解决问题的核心,通过这个判断来决定是否禁用整个一级指标组的控件
const anyDisabled = level1Items.some(item => !!item.disabledSt);
// 关键点6创建一个临时记录使用组内任何行的禁用状态
// 这样确保只要组内有一行禁用,整个组的一级指标控件都会显示为禁用状态
const tempRecord = {
...record,
disabledSt: anyDisabled
};
return {
children: render(content, record),
children: render(content, tempRecord),
props: {
rowSpan: level1Items.length,
},
@ -528,13 +593,17 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
const typeItem = indicatorTypes.find((item) => item.code === cellContent);
return typeItem ? typeItem.dicName : cellContent || '-';
}
return (
<Select
value={cellContent}
onChange={(val) => handleInputChange(val, record, 'indicatorType')}
placeholder={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.selectType' })}
placeholder={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.selectType',
})}
style={{ width: '100%' }}
loading={loadingTypes}
disabled={record.disabledSt}
>
{indicatorTypes.map((item) => (
<Option key={item.code} value={item.code}>
@ -560,15 +629,20 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return (
<Input
value={cellContent}
disabled={record.disabledSt}
onChange={(e) => handleInputChange(e.target.value, record, 'baseIndicator')}
placeholder={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.baseIndicator' })}
placeholder={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.baseIndicator',
})}
/>
);
});
},
},
{
title: intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.indicatorDescription' }),
title: intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.indicatorDescription',
}),
align: 'center',
dataIndex: 'descIndicator',
key: 'descIndicator',
@ -581,8 +655,11 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return (
<Input
value={cellContent}
disabled={record.disabledSt}
onChange={(e) => handleInputChange(e.target.value, record, 'descIndicator')}
placeholder={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.indicatorDescription' })}
placeholder={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.indicatorDescription',
})}
/>
);
});
@ -603,8 +680,9 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
<InputNumber
min={0}
max={100}
disabled={record.disabledSt}
value={parseFloat(cellContent) || 0}
onChange={val => handleInputChange(val?.toString() || '0', record, 'stScore')}
onChange={(val) => handleInputChange(val?.toString() || '0', record, 'stScore')}
style={{ width: '100%' }}
/>
);
@ -627,20 +705,31 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
onClick={() => {
addLevel1Indicator(record);
}}
title={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.button.addLevelOne' })}
title={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.button.addLevelOne',
})}
/>
<Popconfirm
title={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.confirm.delete' })}
title={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.confirm.delete',
})}
onConfirm={() => removeLevel1Indicator(record)}
okText={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.confirm.ok' })}
cancelText={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.confirm.cancel' })}
okText={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.confirm.ok',
})}
cancelText={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.confirm.cancel',
})}
>
<Button
type="text"
danger
icon={<DeleteOutlined />}
title={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.button.deleteLevelOne' })}
/>
<Button
type="text"
danger
disabled={record.disabledSt}
icon={<DeleteOutlined />}
title={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.button.deleteLevelOne',
})}
/>
</Popconfirm>
</div>
));
@ -664,8 +753,11 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return (
<Input
value={text}
disabled={record.disabledNd}
onChange={(e) => handleInputChange(e.target.value, record, 'subIndicator')}
placeholder={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.subIndicator' })}
placeholder={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.subIndicator',
})}
/>
);
},
@ -684,6 +776,7 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
<InputNumber
min={0}
max={100}
disabled={record.disabledNd}
value={parseFloat(text) || 0}
onChange={(val) => handleInputChange(val?.toString() || '0', record, 'ndScore')}
style={{ width: '100%' }}
@ -704,7 +797,8 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return (
<Select
value={text || StarLevel.NO}
onChange={val => handleInputChange(val, record, 'isStar')}
disabled={record.disabledNd}
onChange={(val) => handleInputChange(val, record, 'isStar')}
style={{ width: '100%' }}
>
<Option value={StarLevel.NO}>{StarLevelText[StarLevel.NO]}</Option>
@ -714,7 +808,9 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
},
},
{
title: intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.scoreDescription' }),
title: intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.scoreDescription',
}),
dataIndex: 'descScore',
align: 'center',
key: 'descScore',
@ -725,8 +821,11 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
return (
<TextArea
value={text}
disabled={record.disabledNd}
onChange={(e) => handleInputChange(e.target.value, record, 'descScore')}
placeholder={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.scoreDescription' })}
placeholder={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.scoreDescription',
})}
autoSize={{ minRows: 1, maxRows: 3 }}
/>
);
@ -746,22 +845,33 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
type="text"
icon={<PlusOutlined />}
onClick={() => addSubIndicator(record.key)}
title={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.button.addSubIndicator' })}
title={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.button.addSubIndicator',
})}
/>
{/* 如果该一级指标下有多个二级指标,才允许删除 */}
{getLevel1RowSpan(record.baseIndicator) > 1 && (
<Popconfirm
title={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.confirm.delete' })}
title={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.confirm.delete',
})}
onConfirm={() => removeSubIndicator(record.key)}
okText={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.confirm.ok' })}
cancelText={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.confirm.cancel' })}
okText={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.confirm.ok',
})}
cancelText={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.confirm.cancel',
})}
>
<Button
type="text"
danger
icon={<MinusCircleOutlined />}
title={intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.button.deleteSubIndicator' })}
/>
<Button
type="text"
danger
disabled={record.disabledNd}
icon={<MinusCircleOutlined />}
title={intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.button.deleteSubIndicator',
})}
/>
</Popconfirm>
)}
</div>
@ -769,19 +879,23 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
},
},
// 添加勾选列只在isCheck为true时显示
...(isCheck ? [{
title: intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.check' }),
key: 'check',
align: 'center',
width: 80,
render: (_: any, record: TableRowItem) => (
<input
type="checkbox"
checked={record.selected}
onChange={(e) => handleCheckChange(record, e.target.checked)}
/>
),
}] : []),
...(isCheck
? [
{
title: intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.check' }),
key: 'check',
align: 'center',
width: 80,
render: (_: any, record: TableRowItem) => (
<input
type="checkbox"
checked={record.selected}
onChange={(e) => handleCheckChange(record, e.target.checked)}
/>
),
},
]
: []),
].filter((col) => !(isDetail && col.key === 'level2Action')),
},
];
@ -796,7 +910,11 @@ const EvaluateTemplateTable: React.FC<EvaluateTemplateTableProps> = ({
rowKey="key"
size="middle"
scroll={{ x: 'max-content' }}
locale={{ emptyText: intl.formatMessage({ id: 'supplierTemplateManage.evaluateTable.placeholder.emptyData' }) }}
locale={{
emptyText: intl.formatMessage({
id: 'supplierTemplateManage.evaluateTable.placeholder.emptyData',
}),
}}
/>
{!isDetail && (
<div className="add-button-row">

View File

@ -49,8 +49,8 @@ export enum IndicatorAddOption {
}
export const IndicatorAddOptionText = {
[IndicatorAddOption.CAN_ADD]: '可增加',
[IndicatorAddOption.CANNOT_ADD]: '不可增加',
[IndicatorAddOption.CAN_ADD]: '可修改',
[IndicatorAddOption.CANNOT_ADD]: '不可修改',
};
// 重新导出任务类型

View File

@ -41,8 +41,8 @@ export default {
'supplierTemplateManage.form.selectCategory': 'Select Category',
'supplierTemplateManage.form.selectTemplate': 'Select Template',
'supplierTemplateManage.form.status': 'Status',
'supplierTemplateManage.form.indicatorStMore': 'Allow Adding Primary Indicators',
'supplierTemplateManage.form.indicatorNdMore': 'Allow Adding Secondary Indicators',
'supplierTemplateManage.form.indicatorStMore': 'Allow Modifying Primary Indicators',
'supplierTemplateManage.form.indicatorNdMore': 'Allow Modifying Secondary Indicators',
'supplierTemplateManage.rule.templateName': 'Please enter template name',
'supplierTemplateManage.rule.categoryLimitation': 'Please select category limitation',

View File

@ -40,8 +40,8 @@ export default {
'supplierTemplateManage.form.selectCategory': '选择品类',
'supplierTemplateManage.form.selectTemplate': '选择模版',
'supplierTemplateManage.form.status': '是否启用',
'supplierTemplateManage.form.indicatorStMore': '是否可添加一级指标',
'supplierTemplateManage.form.indicatorNdMore': '是否可添加二级指标',
'supplierTemplateManage.form.indicatorStMore': '是否可修改一级指标',
'supplierTemplateManage.form.indicatorNdMore': '是否可修改二级指标',
'supplierTemplateManage.rule.templateName': '请输入模板名称',
'supplierTemplateManage.rule.categoryLimitation': '请选择是否限品类',

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
import { Card, Table, Button, Input, Row, Col, message, Space, Form, DatePicker, Select, Tag } from 'antd';
import { Table, Button, Input, message, Space, Form, DatePicker, Select } from 'antd';
import { history } from 'umi';
import { SearchOutlined, DeleteOutlined } from '@ant-design/icons';
import { getAnnualResultTaskList } from '@/servers/api/supplierAnnual';

View File

@ -15,10 +15,6 @@ import {
import { ArrowLeftOutlined } from '@ant-design/icons';
import { getAnnualResultReviewDetail } from '@/servers/api/supplierAnnual';
import {
AnnualReviewStatus,
AnnualReviewStatusText,
AnnualReviewStatusColor,
ExamineResult,
ExamineResultText,
ExamineResultColor,
} from '@/dicts/supplierAnnualReviewDict';
@ -32,11 +28,9 @@ const SupplierAnnualResultDetail: React.FC = () => {
const [scoreResults, setScoreResults] = useState<supplierAnnualResult.TaskIndicatorVo[]>([]);
// 从路由获取ID和其他参数
const { id, supplierId, supplierName, taskId, annualTheme } = history.location.state as {
const { id, supplierName, annualTheme } = history.location.state as {
id: string;
supplierId: string;
supplierName: string;
taskId: string;
annualTheme: string;
};

View File

@ -5,14 +5,11 @@ import {
Card,
Table,
Input,
Row,
Col,
message,
Space,
Form,
Select,
Typography,
Tag,
DatePicker
} from 'antd';
import { ArrowLeftOutlined, SearchOutlined, DeleteOutlined } from '@ant-design/icons';

View File

@ -5,8 +5,6 @@ import {
Card,
Table,
Input,
Row,
Col,
message,
Space,
Form,
@ -19,7 +17,6 @@ import { ArrowLeftOutlined, SearchOutlined, DeleteOutlined } from '@ant-design/i
import { getAnnualResultReviewList } from '@/servers/api/supplierAnnual';
import styles from './supplierAnnualResult.less';
import {
AnnualReviewStatus,
AnnualReviewStatusText,
AnnualReviewStatusColor
} from '@/dicts/supplierAnnualReviewDict';

View File

@ -57,11 +57,6 @@ const BasicInfoStepComponent = (props: BasicInfoStepProps) => {
// 获取评价模板和初始化表单数据
useEffect(() => {
fetchTemplates();
// 初始化表单数据
if (taskFormData) {
form.setFieldsValue(taskFormData);
}
}, []);
// 当taskFormData变化时更新表单值

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react';
import { Card, Button, Space, Form } from 'antd';
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react';
import { Card, Button, Space } from 'antd';
import styles from '../supplierAnnualTaskManageAdd.less';
import {
SupplierTable,
@ -60,8 +60,6 @@ const EvaluatorSelectStepComponent = (props: EvaluatorSelectStepProps) => {
// 模态框模式SELECT(选择模式) 或 VIEW(查看模式)
const [modalMode, setModalMode] = useState<ModalMode>(ModalMode.SELECT);
// 表单实例,用于权重设置
const [form] = Form.useForm();
const [filterUserIds, setFilterUserIds] = useState<string[]>([]);
useEffect(() => {
if (mode === 'division' && taskFormData.userList && taskFormData.userList.length > 0) {

View File

@ -1,11 +1,8 @@
import React, { useState, useEffect } from 'react';
import {
Card,
Table,
Button,
Input,
Row,
Col,
message,
Space,
Form,
@ -13,15 +10,12 @@ import {
Select,
Tag,
Tooltip,
Modal,
} from 'antd';
import { history } from 'umi';
import {
SearchOutlined,
DeleteOutlined,
PlusOutlined,
EditOutlined,
EyeOutlined,
} from '@ant-design/icons';
import { getAnnualTaskList } from '@/servers/api/supplierAnnual';
import {
@ -30,8 +24,6 @@ import {
AnnualTaskStatusColor,
AnnualTaskStatusOptions,
} from '@/dicts/supplierAnnualTaskManageDict';
import moment from 'moment';
import styles from './supplierAnnualTaskManage.less';
const { RangePicker } = DatePicker;
const { Option } = Select;
@ -86,6 +78,7 @@ const SupplierAnnualTaskManage: React.FC = () => {
// 首次加载获取数据
useEffect(() => {
fetchList({ current: 1, pageSize: 10 });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
// 表格变化处理

View File

@ -25,7 +25,6 @@ import {
CategoryLimitationTypeText,
TemplateStatus,
TemplateStatusText,
StarLevel,
IndicatorAddOption
} from '@/dicts/supplierTemplateDict';
import {
@ -71,6 +70,7 @@ const SupplierTemplateManageAdd: React.FC = () => {
const [indicatorStMore, setIndicatorStMore] = useState<string>(IndicatorAddOption.CAN_ADD);
const [indicatorNdMore, setIndicatorNdMore] = useState<string>(IndicatorAddOption.CAN_ADD);
// 获取路由传递的数据
const location = useLocation<LocationState>();
@ -122,12 +122,10 @@ const SupplierTemplateManageAdd: React.FC = () => {
setLoading(false);
}
};
// 初始化编辑数据
useEffect(() => {
// 获取所有模板列表
fetchTemplateList();
// 如果是编辑模式,加载编辑数据
if (location.state?.isEdit && location.state?.editData) {
setIsEdit(true);
@ -242,19 +240,30 @@ const SupplierTemplateManageAdd: React.FC = () => {
// 处理模板选择
const handleTemplateSelect = async (templateId: string) => {
// 如果是新建模式,并且选择了模板,获取模板详情作为基础数据
// 要求,如果选择模板时,需读取模板中的 indicatorStMore(一级指标是否可编辑) 和 indicatorNdMore(二级指标是否可编辑) 的值
// 来动态设置 EvaluateTemplateTable 组件的value(templateData) 中的disable属性
// 注意 当一级指标禁用时,需要判断指标类型是通用类型的才禁用,其他类型的指标不进行禁用
if (!isEdit && templateId) {
try {
setLoading(true);
const res = await getTemplateDetail(templateId);
if (res.success && res.data) {
// 一级指标是否可编辑
const indicatorStMoreStatus = res.data.indicatorStMore === IndicatorAddOption.CANNOT_ADD;
// 二级指标是否可编辑
const indicatorNdMoreStatus = res.data.indicatorNdMore === IndicatorAddOption.CANNOT_ADD;
// 只复制指标数据,不复制基础信息
if (res.data.indicatorStList && res.data.indicatorStList.length > 0) {
// 复制模板数据但清除ID以创建新记录
const copiedIndicatorStList = JSON.parse(JSON.stringify(res.data.indicatorStList)).map((stItem: SupplierTemplateManage.IndicatorSt) => {
// 通用类型指标禁用,其他类型指标不禁用 (如果当前是true 表示已禁用, 需要同时满足当前指标类型是通用类型)
stItem.disabled = indicatorStMoreStatus && stItem.indicatorType === "generalType";
// 删除ID而不是设为undefined
delete stItem.id;
// delete stItem.id;
stItem.indicatorNdList = stItem.indicatorNdList.map((ndItem: SupplierTemplateManage.IndicatorNd) => {
delete ndItem.id;
ndItem.disabled = indicatorNdMoreStatus
// delete ndItem.id;
return ndItem;
});
return stItem;
@ -372,7 +381,7 @@ const SupplierTemplateManageAdd: React.FC = () => {
<Form.Item
label={intl.formatMessage({ id: 'supplierTemplateManage.form.status' })}
name="status"
rules={[{ required: true, message: intl.formatMessage({ id: 'supplierTemplateManage.rule.status' }, { defaultMessage: '请选择是否启用' }) }]}
rules={[{ required: true }]}
>
<Radio.Group>
<Radio value={TemplateStatus.DRAFT}>{TemplateStatusText[TemplateStatus.DRAFT]}</Radio>

View File

@ -54,6 +54,8 @@ declare namespace SupplierTemplateManage {
templateName: string;
status: string;
dimensions: TemplateDimension[];
indicatorStMore: string;
indicatorNdMore: string;
[key: string]: any;
};
message: string;