年审
This commit is contained in:
@ -0,0 +1,495 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Card,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
Radio,
|
||||
Button,
|
||||
message,
|
||||
Row,
|
||||
Col,
|
||||
Divider,
|
||||
Space,
|
||||
Switch,
|
||||
Typography,
|
||||
Spin,
|
||||
Table,
|
||||
Popconfirm,
|
||||
Modal,
|
||||
} from 'antd';
|
||||
import { history, useLocation } from 'umi';
|
||||
import {
|
||||
ArrowLeftOutlined,
|
||||
SaveOutlined,
|
||||
PlusOutlined,
|
||||
DeleteOutlined,
|
||||
StarFilled,
|
||||
StarOutlined
|
||||
} from '@ant-design/icons';
|
||||
import CategorySelector from '@/components/CategorySelector';
|
||||
import {
|
||||
AnnualTemplateStatus,
|
||||
AnnualTemplateStatusText,
|
||||
} from '@/dicts/supplierAnnualDict';
|
||||
import {
|
||||
addAnnualTemplate,
|
||||
updateAnnualTemplate,
|
||||
getAnnualTemplateDetail,
|
||||
getAllAnnualTemplates
|
||||
} from '@/servers/api/supplierAnnual';
|
||||
import styles from './supplierAnnualTemplateManage.less';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
interface LocationState {
|
||||
isEdit?: boolean;
|
||||
editData?: supplierAnnualTemplateManage.TemplateRecord;
|
||||
}
|
||||
|
||||
// 模板记录类型 - 使用实际API接口类型
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
// 品类限制类型常量
|
||||
const CategoryLimitationType = {
|
||||
UNIVERSAL: '0', // 不限
|
||||
LIMITED: '1', // 限制
|
||||
};
|
||||
|
||||
// 品类限制类型文本
|
||||
const CategoryLimitationTypeText = {
|
||||
[CategoryLimitationType.UNIVERSAL]: '不限',
|
||||
[CategoryLimitationType.LIMITED]: '限制',
|
||||
};
|
||||
|
||||
// 是否星号项常量
|
||||
const StarOptions = {
|
||||
YES: '1',
|
||||
NO: '0',
|
||||
};
|
||||
|
||||
// 是否星号项文本
|
||||
const StarOptionsText = {
|
||||
[StarOptions.YES]: '是',
|
||||
[StarOptions.NO]: '否',
|
||||
};
|
||||
|
||||
const SupplierAnnualTemplateManageAdd: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [isEdit, setIsEdit] = useState<boolean>(false);
|
||||
const [templateDetail, setTemplateDetail] = useState<supplierAnnualTemplateManage.TemplateDetailData | null>(null);
|
||||
const [templateList, setTemplateList] = useState<supplierAnnualTemplateManage.TemplateRecord[]>([]);
|
||||
const [indicatorList, setIndicatorList] = useState<supplierAnnualTemplateManage.IndicatorItem[]>([]);
|
||||
|
||||
// 获取路由传递的数据
|
||||
const location = useLocation<LocationState>();
|
||||
|
||||
// 获取所有模板列表
|
||||
const fetchTemplateList = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await getAllAnnualTemplates();
|
||||
if (res.success && res.data) {
|
||||
setTemplateList(res.data);
|
||||
} else {
|
||||
message.error(res.message || '获取模板列表失败');
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error('获取模板列表失败:', error);
|
||||
message.error('获取模板列表失败');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取模板详情
|
||||
const fetchTemplateDetail = async (templateId: string) => {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await getAnnualTemplateDetail(templateId);
|
||||
if (res.success && res.data) {
|
||||
setTemplateDetail(res.data);
|
||||
|
||||
// 设置表单数据
|
||||
form.setFieldsValue({
|
||||
templateName: res.data.templateName,
|
||||
categoryLimitation: res.data.categoryLimitation,
|
||||
categoryId: res.data.categoryId,
|
||||
status: res.data.status,
|
||||
copyTemplateId: res.data.templateType,
|
||||
});
|
||||
|
||||
// 设置指标数据
|
||||
if (res.data.indicatorList && res.data.indicatorList.length > 0) {
|
||||
setIndicatorList(res.data.indicatorList);
|
||||
}
|
||||
} else {
|
||||
message.error(res.message || '获取模板详情失败');
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error('获取模板详情失败:', error);
|
||||
message.error('获取模板详情失败');
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 初始化编辑数据
|
||||
useEffect(() => {
|
||||
// 获取所有模板列表
|
||||
fetchTemplateList();
|
||||
|
||||
// 如果是编辑模式,加载编辑数据
|
||||
if (location.state?.isEdit && location.state?.editData) {
|
||||
setIsEdit(true);
|
||||
|
||||
// 获取模板详情
|
||||
if (location.state.editData.id) {
|
||||
fetchTemplateDetail(location.state.editData.id);
|
||||
}
|
||||
} else {
|
||||
// 非编辑模式,默认添加一条空指标
|
||||
const newIndicator: supplierAnnualTemplateManage.IndicatorItem = {
|
||||
orderBy: '1',
|
||||
itemName: '',
|
||||
isStar: StarOptions.NO,
|
||||
};
|
||||
setIndicatorList([newIndicator]);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// 处理返回
|
||||
const handleBack = () => {
|
||||
history.goBack();
|
||||
};
|
||||
|
||||
// 实际提交数据的函数
|
||||
const submitFormData = async (submitData: supplierAnnualTemplateManage.AddTemplateRequest) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
// 调用API接口
|
||||
let res;
|
||||
if (isEdit) {
|
||||
res = await updateAnnualTemplate(submitData);
|
||||
} else {
|
||||
res = await addAnnualTemplate(submitData);
|
||||
}
|
||||
|
||||
if (res && res.success) {
|
||||
message.success(isEdit ? '模板更新成功' : '模板保存成功');
|
||||
history.goBack();
|
||||
} else {
|
||||
message.error(res?.message || (isEdit ? '模板更新失败' : '模板保存失败'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('提交失败:', error);
|
||||
message.error('提交失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
// 处理表单提交前的验证
|
||||
const handleSubmit = async (values: any) => {
|
||||
// 检查指标列表
|
||||
if (!indicatorList || indicatorList.length === 0) {
|
||||
message.error('至少需要添加一项指标');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查指标名称不能为空
|
||||
const emptyNameIndex = indicatorList.findIndex(item => !item.itemName);
|
||||
if (emptyNameIndex !== -1) {
|
||||
message.error(`第 ${emptyNameIndex + 1} 项指标名称不能为空`);
|
||||
return;
|
||||
}
|
||||
|
||||
// 准备提交数据
|
||||
const submitData: supplierAnnualTemplateManage.AddTemplateRequest = {
|
||||
...values,
|
||||
indicatorList,
|
||||
templateType: values.copyTemplateId || '1', // 默认类型
|
||||
};
|
||||
|
||||
// 如果是编辑模式,添加ID
|
||||
if (isEdit && templateDetail) {
|
||||
submitData.id = templateDetail.id;
|
||||
}
|
||||
|
||||
// 显示确认弹框
|
||||
Modal.confirm({
|
||||
title: '确认提交',
|
||||
content: isEdit ? '确定要更新此模板吗?' : '确定要保存此模板吗?',
|
||||
okText: '确定',
|
||||
cancelText: '取消',
|
||||
onOk: async () => {
|
||||
await submitFormData(submitData);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理模板选择
|
||||
const handleTemplateSelect = async (templateId: string) => {
|
||||
// 如果是新建模式,并且选择了模板,获取模板详情作为基础数据
|
||||
if (!isEdit && templateId) {
|
||||
try {
|
||||
setLoading(true);
|
||||
const res = await getAnnualTemplateDetail(templateId);
|
||||
if (res.success && res.data) {
|
||||
// 设置品类限制和品类信息
|
||||
form.setFieldsValue({
|
||||
categoryLimitation: res.data.categoryLimitation,
|
||||
categoryId: res.data.categoryId,
|
||||
});
|
||||
|
||||
// 复制指标列表
|
||||
if (res.data.indicatorList && res.data.indicatorList.length > 0) {
|
||||
const copiedList = JSON.parse(JSON.stringify(res.data.indicatorList)).map((item: any) => {
|
||||
// 删除id,防止ID冲突
|
||||
delete item.id;
|
||||
return item;
|
||||
});
|
||||
setIndicatorList(copiedList);
|
||||
}
|
||||
} else {
|
||||
message.error(res.message || '获取模板详情失败');
|
||||
}
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error('获取模板详情失败:', error);
|
||||
message.error('获取模板详情失败');
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 处理添加指标
|
||||
const handleAddIndicator = () => {
|
||||
const newIndicator: supplierAnnualTemplateManage.IndicatorItem = {
|
||||
orderBy: String(indicatorList.length + 1),
|
||||
itemName: '',
|
||||
isStar: StarOptions.NO,
|
||||
};
|
||||
setIndicatorList([...indicatorList, newIndicator]);
|
||||
};
|
||||
|
||||
// 处理删除指标
|
||||
const handleDeleteIndicator = (index: number) => {
|
||||
const newList = [...indicatorList];
|
||||
newList.splice(index, 1);
|
||||
// 更新序号
|
||||
const updatedList = newList.map((item, idx) => ({
|
||||
...item,
|
||||
orderBy: String(idx + 1),
|
||||
}));
|
||||
setIndicatorList(updatedList);
|
||||
};
|
||||
|
||||
// 处理指标项修改
|
||||
const handleIndicatorChange = (index: number, key: string, value: string) => {
|
||||
const newList = [...indicatorList];
|
||||
newList[index][key] = value;
|
||||
setIndicatorList(newList);
|
||||
};
|
||||
|
||||
// 指标表格列定义
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'orderBy',
|
||||
key: 'orderBy',
|
||||
width: 80,
|
||||
render: (_: string, __: any, index: number) => index + 1,
|
||||
},
|
||||
{
|
||||
title: '检查项目',
|
||||
dataIndex: 'itemName',
|
||||
key: 'itemName',
|
||||
render: (text: string, record: supplierAnnualTemplateManage.IndicatorItem, index: number) => (
|
||||
<Input
|
||||
value={text}
|
||||
onChange={(e) => handleIndicatorChange(index, 'itemName', e.target.value)}
|
||||
placeholder="请输入检查项目名称"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '星号项',
|
||||
dataIndex: 'isStar',
|
||||
key: 'isStar',
|
||||
width: 120,
|
||||
render: (text: string, record: supplierAnnualTemplateManage.IndicatorItem, index: number) => (
|
||||
<Select
|
||||
value={text}
|
||||
onChange={(value) => handleIndicatorChange(index, 'isStar', value)}
|
||||
className={styles.starSelector}
|
||||
>
|
||||
<Option value={StarOptions.YES}>{StarOptionsText[StarOptions.YES]}</Option>
|
||||
<Option value={StarOptions.NO}>{StarOptionsText[StarOptions.NO]}</Option>
|
||||
</Select>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 120,
|
||||
render: (_: any, __: supplierAnnualTemplateManage.IndicatorItem, index: number) => (
|
||||
<Space>
|
||||
{index === indicatorList.length - 1 && (
|
||||
<Button
|
||||
type="link"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={handleAddIndicator}
|
||||
title="添加指标"
|
||||
/>
|
||||
)}
|
||||
<Popconfirm
|
||||
title="确定要删除此指标吗?"
|
||||
onConfirm={() => handleDeleteIndicator(index)}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
<Button type="link" danger icon={<DeleteOutlined />} title="删除指标" />
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="common-container">
|
||||
<div className={styles.pageHeader}>
|
||||
<Title level={4} style={{ margin: 0 }}>
|
||||
{isEdit ? '编辑年度模板' : '新增年度模板'}
|
||||
</Title>
|
||||
<Button type="link" icon={<ArrowLeftOutlined />} onClick={handleBack}>
|
||||
返回
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={handleSubmit}
|
||||
initialValues={{
|
||||
categoryLimitation: CategoryLimitationType.UNIVERSAL,
|
||||
status: AnnualTemplateStatus.DRAFT,
|
||||
}}
|
||||
labelCol={{ span: 7 }}
|
||||
wrapperCol={{ span: 17 }}
|
||||
>
|
||||
<Spin spinning={loading}>
|
||||
<Card title="基础信息" bordered={false} className={styles.innerCard}>
|
||||
<Row gutter={24}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label="模板名称"
|
||||
name="templateName"
|
||||
rules={[{ required: true, message: '请输入模板名称' }]}
|
||||
>
|
||||
<Input placeholder="请输入模板名称" maxLength={50} />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label="是否限品类"
|
||||
name="categoryLimitation"
|
||||
rules={[{ required: true, message: '请选择是否限品类' }]}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value={CategoryLimitationType.UNIVERSAL}>{CategoryLimitationTypeText[CategoryLimitationType.UNIVERSAL]}</Radio>
|
||||
<Radio value={CategoryLimitationType.LIMITED}>{CategoryLimitationTypeText[CategoryLimitationType.LIMITED]}</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prevValues, currentValues) =>
|
||||
prevValues.categoryLimitation !== currentValues.categoryLimitation
|
||||
}
|
||||
>
|
||||
{({ getFieldValue }) => {
|
||||
const categoryLimitation = getFieldValue('categoryLimitation');
|
||||
return categoryLimitation === CategoryLimitationType.LIMITED ? (
|
||||
<Form.Item
|
||||
label="选择品类"
|
||||
name="categoryId"
|
||||
rules={[{ required: true, message: '请选择品类' }]}
|
||||
>
|
||||
<CategorySelector multiple={false} />
|
||||
</Form.Item>
|
||||
) : null;
|
||||
}}
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row gutter={24}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label="选择模版"
|
||||
name="copyTemplateId"
|
||||
>
|
||||
<Select
|
||||
placeholder="选择模版"
|
||||
loading={templateList.length === 0}
|
||||
onSelect={handleTemplateSelect}
|
||||
>
|
||||
{templateList.map(template => (
|
||||
template.id ? (
|
||||
<Option key={template.id} value={template.id}>
|
||||
{template.templateName}
|
||||
</Option>
|
||||
) : null
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
label="模板状态"
|
||||
name="status"
|
||||
rules={[{ required: true, message: '请选择模板状态' }]}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value={AnnualTemplateStatus.DRAFT}>{AnnualTemplateStatusText[AnnualTemplateStatus.DRAFT]}</Radio>
|
||||
<Radio value={AnnualTemplateStatus.ENABLED}>{AnnualTemplateStatusText[AnnualTemplateStatus.ENABLED]}</Radio>
|
||||
<Radio value={AnnualTemplateStatus.DISABLED}>{AnnualTemplateStatusText[AnnualTemplateStatus.DISABLED]}</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
<Divider />
|
||||
|
||||
<Card title="指标信息" bordered={false} className={styles.innerCard}>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={indicatorList}
|
||||
bordered
|
||||
rowKey="orderBy"
|
||||
size="middle"
|
||||
pagination={false}
|
||||
locale={{ emptyText: '暂无指标数据' }}
|
||||
className={styles.indicatorTable}
|
||||
/>
|
||||
</Card>
|
||||
</Spin>
|
||||
|
||||
<div className={styles.formActions}>
|
||||
<Space>
|
||||
<Button onClick={handleBack}>取消</Button>
|
||||
<Button type="primary" htmlType="submit" loading={loading} icon={<SaveOutlined />}>
|
||||
{isEdit ? '更新' : '保存'}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SupplierAnnualTemplateManageAdd;
|
||||
Reference in New Issue
Block a user