应答文件、补充应答文件

This commit is contained in:
sunyu
2025-07-25 14:06:22 +08:00
parent 8014c81948
commit 9bfb67e9dd
6 changed files with 999 additions and 0 deletions

View File

@ -0,0 +1,407 @@
import React, { useEffect, useRef, useState } from 'react';
import '@/utils/lq.style.less';
import { Button, Input, Form, Modal, Select, DatePicker, message } from 'antd';
import ProTable from '@ant-design/pro-table';
import { getProId } from '@/utils/session';
import ExtendUpload from '@/utils/ExtendUpload';
import moment from 'moment';
import { getPageList, insertDocument, supplierUpdateDocument } from '../service';
import { saveDateTimeFormatter } from "@/utils/DateUtils";
const { Option } = Select;
const { TextArea } = Input;
const layoutForm = {
labelCol: { span: 6 },
wrapperCol: { span: 18 },
};
interface Supplier {
id: string;
name: string;
}
interface State {
visible: boolean;
whetherReadonly: boolean;
supplierFileId: string;
supplierSupplementaryFileId: string;
suppliers: Supplier[];
selectedSupplier: string;
replyDeadline: string;
subject: string;
content: string;
attachment: string;
}
const PurchaserResponseDocumentList: React.FC = () => {
const [form] = Form.useForm();
const actionRef = useRef<any>();
const [state, setState] = useState<State>({
visible: false,
whetherReadonly: false,
supplierFileId: '',
supplierSupplementaryFileId: '',
suppliers: [
{ id: '1', name: '杭州安恒信息技术股份有限公司' },
{ id: '2', name: '浪潮天元通信信息系统有限公司' },
{ id: '3', name: '河南软信科技有限公司' },
{ id: '4', name: '浙江省邮电工程建设有限公司' },
{ id: '5', name: '无锡市德科立光电子技术股份有限公司' },
],
selectedSupplier: '',
replyDeadline: '',
subject: '',
content: '',
attachment: '',
});
const [isReplyMode, setIsReplyMode] = useState(false); // 新增:控制回复模式
useEffect(() => {
// 可以在这里添加初始化逻辑
}, []);
const columns = [
{
title: '序号',
valueType: 'index',
},
{
title: '主题',
dataIndex: 'subject',
},
{
title: '指定供应商',
dataIndex: 'supplierName',
},
{
title: '指定供应商id',
dataIndex: 'supplierId',
hideInTable: true // 隐藏该列
},
{
title: '内容',
dataIndex: 'content',
hideInTable: true // 隐藏该列
},
{
title: '应答截止时间',
dataIndex: 'replyDeadline',
},
{
title: '状态',
dataIndex: 'status',
render: (_, record) => {
const statusMap = {
'1': '未回复',
'2': '未回复',
'3': '已回复',
};
return statusMap[record.status] || '-'; // 默认显示未知状态,防止映射失败
},
},
{
title: '操作',
width: 240, // 增加列宽以容纳三个按钮
valueType: 'option',
render: (_, record) => (
<div className="flex items-center space-x-2"> {/* 使用Tailwind CSS类优化布局 */}
{record.status === '3' ? (
<Button type="link" danger onClick={() => view(record)}>
</Button>
) : (
<>
<Button type="link" danger onClick={() => edit(record)}>
</Button>
</>
)}
</div>
),
}
];
const view = (data: any) => {
const selectedSupplierObj = state.suppliers.find(
(supplier) => supplier.id === data.supplierId
);
setState({
...state,
visible: true,
whetherReadonly: true,
selectedSupplier: data.supplierId,
replyDeadline: data.replyDeadline,
subject: data.subject,
content: data.content,
attachment: data.attachment,
});
form.setFieldsValue({
...data,
replyDeadline: moment(data.replyDeadline),
selectedSupplier: selectedSupplierObj
? { value: selectedSupplierObj.id, label: selectedSupplierObj.name }
: undefined,
});
setIsReplyMode(false); // 查看模式下不启用回复模式
};
const edit = (data: any) => {
const selectedSupplierObj = state.suppliers.find(
(supplier) => supplier.id === data.supplierId
);
setState({
...state,
visible: true,
whetherReadonly: false,
selectedSupplier: data.supplierId,
replyDeadline: data.replyDeadline,
subject: data.subject,
content: data.content,
attachment: data.attachment,
});
form.setFieldsValue({
...data,
replyDeadline: moment(data.replyDeadline),
selectedSupplier: selectedSupplierObj
? { value: selectedSupplierObj.id, label: selectedSupplierObj.name }
: undefined,
});
setIsReplyMode(true); // 回复模式下启用
};
const handleCancel = () => {
setState({
...state,
visible: false,
whetherReadonly: false,
});
form.resetFields();
setIsReplyMode(false); // 重置回复模式
};
const handleSubmit = async () => {
try {
const values = await form.validateFields();
values.replyDeadline = saveDateTimeFormatter(moment(values.replyDeadline));
if (values.selectedSupplier) {
values.supplierId = values.selectedSupplier.value;
values.supplierName = values.selectedSupplier.label;
delete values.selectedSupplier;
}
console.log(values);
if (values.id) {
await supplierUpdateDocument(values).then((r: any) => {
if (r?.code == 200) {
message.success('修改成功');
} else {
message.error('修改失败');
}
});
} else {
await insertDocument(values).then((r: any) => {
if (r?.code == 200) {
message.success('新增成功');
} else {
message.error('新增失败');
}
});
}
handleCancel();
actionRef.current?.reload();
} catch (error) {
console.log("错误失败!");
console.error(error);
}
};
const onFinish = (values: any) => {
message.success('保存成功');
setState({
...state,
visible: false,
});
actionRef.current.reload();
};
const handleAdd = () => {
setState({
...state,
visible: true,
whetherReadonly: false,
selectedSupplier: '',
replyDeadline: '',
subject: '',
content: '',
attachment: '',
});
form.resetFields();
setIsReplyMode(false); // 新增模式下不启用回复模式
};
const createForm = () => {
const modalHeight = innerHeight * 96 / 100;
return (
<Modal
visible={state.visible}
width="60%"
title="补充文件说明"
onCancel={handleCancel}
destroyOnClose={true}
centered
style={{ maxHeight: modalHeight }}
bodyStyle={{ maxHeight: modalHeight - 107, overflowY: 'auto' }}
footer={state.whetherReadonly ? [
<Button key="back" onClick={handleCancel}>
</Button>
] : [
<Button key="back" onClick={handleCancel}>
</Button>,
<Button key="submit" type="primary" onClick={handleSubmit}>
</Button>
]}
>
<Form
{...layoutForm}
form={form}
onFinish={onFinish}
>
<Form.Item label="主键id" name="id" hidden>
<Input />
</Form.Item>
<Form.Item label="状态" name="status" hidden>
<Input />
</Form.Item>
<Form.Item
label="指定供应商"
name="selectedSupplier"
rules={[{ required: true, message: '请选择供应商' }]}
>
<Select
disabled={isReplyMode || state.whetherReadonly} // 新增:根据回复模式或只读模式禁用
placeholder="请选择供应商"
labelInValue
>
{state.suppliers.map(supplier => (
<Option key={supplier.id} value={supplier.id}>
{supplier.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item
label="应答截止时间"
name="replyDeadline"
rules={[{ required: true, message: '请选择应答截止时间' }]}
>
<DatePicker
disabled={isReplyMode || state.whetherReadonly} // 新增:根据回复模式或只读模式禁用
showTime
format="YYYY-MM-DD HH:mm:ss"
/>
</Form.Item>
<Form.Item
label="主题"
name="subject"
rules={[{ required: true, message: '请输入主题' }]}
>
<Input
disabled={isReplyMode || state.whetherReadonly} // 新增:根据回复模式或只读模式禁用
placeholder="请输入主题"
/>
</Form.Item>
<Form.Item
label="内容"
name="content"
rules={[{ required: true, message: '请输入内容' }]}
>
<TextArea
disabled={isReplyMode || state.whetherReadonly} // 新增:根据回复模式或只读模式禁用
placeholder="请输入内容"
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</Form.Item>
<Form.Item
label="附件"
name="attachment"
>
<ExtendUpload
bid={state.supplierFileId}
btnName="上传附件"
maxCount={5}
uploadProps={{
name: 'attachment',
disabled: isReplyMode || state.whetherReadonly, // 新增:根据回复模式或只读模式禁用
}}
/>
</Form.Item>
<Form.Item
label="补充文件"
name="supplementaryAttachment"
>
<ExtendUpload
bid={state.supplierSupplementaryFileId}
btnName="上传附件"
maxCount={5}
uploadProps={{
name: 'supplementaryAttachment',
disabled: state.whetherReadonly, // 仅在只读模式下禁用,回复模式下可编辑
}}
/>
</Form.Item>
</Form>
</Modal>
);
};
return (
<>
<Button type="primary" onClick={handleAdd} style={{ marginBottom: 16 }}>
</Button>
<ProTable
rowKey="id"
size="small"
actionRef={actionRef}
params={{ projectId: getProId() }}
request={(params) =>
getPageList({
...params,
basePageRequest: { pageNo: 1, pageSize: 10 },
}).then((res) => {
const result = {
data: res.data.records,
total: res.data.total,
success: res.success,
pageSize: res.data.size,
current: res.data.current
}
return result;
})
}
columns={columns}
search={false}
options={false}
pagination={{ defaultPageSize: 10 }}
/>
{createForm()}
</>
);
};
export default PurchaserResponseDocumentList;

View File

@ -0,0 +1,11 @@
import React from 'react';
import PurchaserResponseDocumentList from './components/PurchaserResponseDocumentList';
// 补充应答文件
const Index: React.FC<{}> = () => {
return (
<PurchaserResponseDocumentList />
)
}
export default Index;

View File

@ -0,0 +1,76 @@
import request from "@/utils/request";
/**
* 采购人查询数据并分页
* @param params
*/
export async function getPage(params: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/getPage', {
method: 'post',
data: params,
});
}
/**
* 供应商查询数据并分页
* @param params
*/
export async function getPageList(params: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/getPageList', {
method: 'post',
data: params,
});
}
/**
* 删除应答
* @param id
*/
export function deleteById(id: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/delete/' + id);
}
/**
* 保存
* @param data
*/
export function insertDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument', {
method: 'post',
data: data
});
}
/**
* 采购人修改补充应答文件数据
* @param data
*/
export function updateDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/update', {
method: 'post',
data: data
});
}
/**
* 采购人修改补充应答文件数据
* @param data
*/
export function supplierUpdateDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/supplierUpdateDocument', {
method: 'post',
data: data
});
}
/**
* 发送
* @param data
*/
export function sendDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/sendDocument', {
method: 'post',
data: data
});
}

View File

@ -0,0 +1,442 @@
import React, { useEffect, useRef, useState } from 'react';
import '@/utils/lq.style.less';
import { Button, Input, Form, Modal, Select, DatePicker, message } from 'antd';
import ProTable from '@ant-design/pro-table';
import { followUpAProjectManager, getProId } from '@/utils/session';
import ExtendUpload from '@/utils/ExtendUpload';
import moment from 'moment';
import { getPage, deleteById, insertDocument, updateDocument, sendDocument } from '../service';
import { saveDateTimeFormatter } from "@/utils/DateUtils";
const { Option } = Select;
const { TextArea } = Input;
const layoutForm = {
labelCol: { span: 6 },
wrapperCol: { span: 18 },
};
interface Supplier {
id: string;
name: string;
}
interface State {
visible: boolean;
whetherReadonly: boolean;
supplierFileId: string;
supplierSupplementaryFileId: string;
suppliers: Supplier[];
selectedSupplier: string;
replyDeadline: string;
subject: string;
content: string;
attachment: string;
status: string; // 新增:存储当前记录的状态
}
const ResponseDocumentList: React.FC = () => {
const [form] = Form.useForm();
const actionRef = useRef<any>();
const [state, setState] = useState<State>({
visible: false,
whetherReadonly: false,
supplierFileId: '',
supplierSupplementaryFileId: '',
suppliers: [
{ id: '1', name: '杭州安恒信息技术股份有限公司' },
{ id: '2', name: '浪潮天元通信信息系统有限公司' },
{ id: '3', name: '河南软信科技有限公司' },
{ id: '4', name: '浙江省邮电工程建设有限公司' },
{ id: '5', name: '无锡市德科立光电子技术股份有限公司' },
],
selectedSupplier: '',
replyDeadline: '',
subject: '',
content: '',
attachment: '',
status: '', // 初始化状态
});
useEffect(() => {
// 可以在这里添加初始化逻辑
}, []);
const columns = [
{
title: '序号',
valueType: 'index',
},
{
title: '主题',
dataIndex: 'subject',
},
{
title: '指定供应商',
dataIndex: 'supplierName',
},
{
title: '指定供应商id',
dataIndex: 'supplierId',
hideInTable: true // 隐藏该列
},
{
title: '内容',
dataIndex: 'content',
hideInTable: true // 隐藏该列
},
{
title: '应答截止时间',
dataIndex: 'replyDeadline',
},
{
title: '状态',
dataIndex: 'status',
render: (_, record) => {
const statusMap = {
'1': '已保存',
'2': '已发送',
'3': '已回复',
};
return statusMap[record.status] || '-'; // 默认显示未知状态,防止映射失败
},
},
{
title: '操作',
width: 240, // 增加列宽以容纳三个按钮
valueType: 'option',
render: (_, record) => (
<div className="flex items-center space-x-2"> {/* 使用Tailwind CSS类优化布局 */}
{record.status !== '1' ? (
<Button type="link" danger onClick={() => view(record)}>
</Button>
) : (
<>
<Button type="link" danger onClick={() => edit(record)}>
</Button>
<Button type="link" danger onClick={() => remove(record.id)}>
</Button>
<Button type="link" danger onClick={() => send(record)}>
</Button>
</>
)}
</div>
),
}
];
const view = (data: any) => {
const selectedSupplierObj = state.suppliers.find(
(supplier) => supplier.id === data.supplierId
);
setState({
...state,
visible: true,
whetherReadonly: true,
selectedSupplier: data.supplierId,
replyDeadline: data.replyDeadline,
subject: data.subject,
content: data.content,
attachment: data.attachment,
status: data.status, // 新增:存储当前记录的状态
});
form.setFieldsValue({
...data,
replyDeadline: moment(data.replyDeadline),
selectedSupplier: selectedSupplierObj
? { value: selectedSupplierObj.id, label: selectedSupplierObj.name }
: undefined,
});
};
const edit = (data: any) => {
const selectedSupplierObj = state.suppliers.find(
(supplier) => supplier.id === data.supplierId
);
setState({
...state,
visible: true,
whetherReadonly: false,
selectedSupplier: data.supplierId,
replyDeadline: data.replyDeadline,
subject: data.subject,
content: data.content,
attachment: data.attachment,
status: data.status, // 新增:存储当前记录的状态
});
form.setFieldsValue({
...data,
replyDeadline: moment(data.replyDeadline),
selectedSupplier: selectedSupplierObj
? { value: selectedSupplierObj.id, label: selectedSupplierObj.name }
: undefined,
});
};
const remove = (id: any) => {
Modal.confirm({
title: '确认删除?',
onOk: async () => {
await deleteById(id).then((r: any) => {
if (r?.code == 200) {
message.success('删除成功');
} else {
message.error('删除失败');
}
})
.finally(() => actionRef.current?.reload());
},
});
};
const send = (data: any) => {
sendDocument(data).then((r: any) => {
if (r?.code == 200) {
message.success('发送成功');
} else {
message.error('发送失败');
}
})
.finally(() => actionRef.current?.reload());
};
const handleCancel = () => {
setState({
...state,
visible: false,
whetherReadonly: false,
status: '', // 重置状态
});
form.resetFields();
};
const handleSubmit = async () => {
try {
const values = await form.validateFields();
values.replyDeadline = saveDateTimeFormatter(moment(values.replyDeadline));
if (values.selectedSupplier) {
values.supplierId = values.selectedSupplier.value;
values.supplierName = values.selectedSupplier.label;
delete values.selectedSupplier;
}
console.log(values);
if (values.id) {
await updateDocument(values).then((r: any) => {
if (r?.code == 200) {
message.success('修改成功');
} else {
message.error('修改失败');
}
});
} else {
await insertDocument(values).then((r: any) => {
if (r?.code == 200) {
message.success('新增成功');
} else {
message.error('新增失败');
}
});
}
handleCancel();
actionRef.current?.reload();
} catch (error) {
console.log("错误失败!");
console.error(error);
}
};
const onFinish = (values: any) => {
message.success('保存成功');
setState({
...state,
visible: false,
});
actionRef.current.reload();
};
const createForm = () => {
const modalHeight = innerHeight * 96 / 100;
return (
<Modal
visible={state.visible}
width="60%"
title="补充文件说明"
onCancel={handleCancel}
destroyOnClose={true}
centered
style={{ maxHeight: modalHeight }}
bodyStyle={{ maxHeight: modalHeight - 107, overflowY: 'auto' }}
footer={state.whetherReadonly ? [
<Button key="back" onClick={handleCancel}>
</Button>
] : [
<Button key="back" onClick={handleCancel}>
</Button>,
<Button key="submit" type="primary" onClick={handleSubmit}>
</Button>
]}
>
<Form
{...layoutForm}
form={form}
onFinish={onFinish}
>
<Form.Item label="主键id" name="id" hidden>
<Input />
</Form.Item>
<Form.Item label="状态" name="status" hidden>
<Input />
</Form.Item>
<Form.Item
label="指定供应商"
name="selectedSupplier"
rules={[{ required: true, message: '请选择供应商' }]}
>
<Select
disabled={state.whetherReadonly}
placeholder="请选择供应商"
labelInValue
>
{state.suppliers.map(supplier => (
<Option key={supplier.id} value={supplier.id}>
{supplier.name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item
label="应答截止时间"
name="replyDeadline"
rules={[{ required: true, message: '请选择应答截止时间' }]}
>
<DatePicker
disabled={state.whetherReadonly}
showTime
format="YYYY-MM-DD HH:mm:ss"
/>
</Form.Item>
<Form.Item
label="主题"
name="subject"
rules={[{ required: true, message: '请输入主题' }]}
>
<Input
disabled={state.whetherReadonly}
placeholder="请输入主题"
/>
</Form.Item>
<Form.Item
label="内容"
name="content"
rules={[{ required: true, message: '请输入内容' }]}
>
<TextArea
disabled={state.whetherReadonly}
placeholder="请输入内容"
autoSize={{ minRows: 4, maxRows: 6 }}
/>
</Form.Item>
<Form.Item
label="附件"
name="attachment"
>
<ExtendUpload
bid={state.supplierFileId}
btnName="上传附件"
maxCount={5}
uploadProps={{
name: 'attachment',
disabled: state.whetherReadonly,
}}
/>
</Form.Item>
{/* 新增:根据状态显示/隐藏补充文件字段 */}
{state.status === '3' && (
<Form.Item
label="补充文件"
name="supplementaryAttachment"
>
<ExtendUpload
bid={state.supplierSupplementaryFileId}
btnName="上传附件"
maxCount={5}
uploadProps={{
name: 'supplementaryAttachment',
disabled: state.whetherReadonly,
}}
/>
</Form.Item>
)}
</Form>
</Modal>
);
};
const handleAdd = () => {
setState({
...state,
visible: true,
whetherReadonly: false,
selectedSupplier: '',
replyDeadline: '',
subject: '',
content: '',
attachment: '',
status: '', // 初始化状态
});
form.resetFields();
};
return (
<>
<Button type="primary" onClick={handleAdd} style={{ marginBottom: 16 }}>
</Button>
<ProTable
rowKey="id"
size="small"
actionRef={actionRef}
params={{ projectId: getProId() }}
request={(params) =>
getPage({
...params,
basePageRequest: { pageNo: 1, pageSize: 10 },
}).then((res) => {
const result = {
data: res.data.records,
total: res.data.total,
success: res.success,
pageSize: res.data.size,
current: res.data.current
}
return result;
})
}
columns={columns}
search={false}
options={false}
pagination={{ defaultPageSize: 10 }}
/>
{createForm()}
</>
);
};
export default ResponseDocumentList;

View File

@ -0,0 +1,11 @@
import React from 'react';
import ResponseDocumentList from './components/ResponseDocumentList';
// 补充应答文件
const Index: React.FC<{}> = () => {
return (
<ResponseDocumentList />
)
}
export default Index;

View File

@ -0,0 +1,52 @@
import request from "@/utils/request";
/**
* 查询数据并分页
* @param params
*/
export async function getPage(params: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/getPage', {
method: 'post',
data: params,
});
}
/**
* 删除应答
* @param id
*/
export function deleteById(id: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/delete/' + id);
}
/**
* 保存
* @param data
*/
export function insertDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument', {
method: 'post',
data: data
});
}
/**
* 修改数据
* @param data
*/
export function updateDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/update', {
method: 'post',
data: data
});
}
/**
* 发送
* @param data
*/
export function sendDocument(data: any) {
return request('/api/biz-service-ebtp-project/v1/coscosupplementaryresponsedocument/sendDocument', {
method: 'post',
data: data
});
}