修复ts警告,增加供应商评价模板管理一级指标二级指标的禁用逻辑
This commit is contained in:
@ -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[]);
|
||||
};
|
||||
|
||||
|
@ -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">
|
||||
|
@ -49,8 +49,8 @@ export enum IndicatorAddOption {
|
||||
}
|
||||
|
||||
export const IndicatorAddOptionText = {
|
||||
[IndicatorAddOption.CAN_ADD]: '可增加',
|
||||
[IndicatorAddOption.CANNOT_ADD]: '不可增加',
|
||||
[IndicatorAddOption.CAN_ADD]: '可修改',
|
||||
[IndicatorAddOption.CANNOT_ADD]: '不可修改',
|
||||
};
|
||||
|
||||
// 重新导出任务类型
|
||||
|
@ -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',
|
||||
|
@ -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': '请选择是否限品类',
|
||||
|
@ -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';
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -57,11 +57,6 @@ const BasicInfoStepComponent = (props: BasicInfoStepProps) => {
|
||||
// 获取评价模板和初始化表单数据
|
||||
useEffect(() => {
|
||||
fetchTemplates();
|
||||
|
||||
// 初始化表单数据
|
||||
if (taskFormData) {
|
||||
form.setFieldsValue(taskFormData);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 当taskFormData变化时更新表单值
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}, []);
|
||||
|
||||
// 表格变化处理
|
||||
|
@ -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>
|
||||
|
@ -54,6 +54,8 @@ declare namespace SupplierTemplateManage {
|
||||
templateName: string;
|
||||
status: string;
|
||||
dimensions: TemplateDimension[];
|
||||
indicatorStMore: string;
|
||||
indicatorNdMore: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
message: string;
|
||||
|
Reference in New Issue
Block a user