264 lines
7.5 KiB
JavaScript
264 lines
7.5 KiB
JavaScript
import React, { useEffect, useState } from 'react';
|
||
import { Card, Typography, Descriptions, Table, Button, Space, Spin } from 'antd';
|
||
import { ArrowLeftOutlined, PrinterOutlined, EditOutlined } from '@ant-design/icons';
|
||
import { useNavigate, useParams } from 'react-router-dom';
|
||
import { supabase } from '@/config/supabase';
|
||
import ReactDOMServer from 'react-dom/server';
|
||
import PrintView from '@/components/PrintView';
|
||
|
||
const { Title, Text } = Typography;
|
||
|
||
const printStyles = `
|
||
@media print {
|
||
/* 隐藏所有按钮和不需要的元素 */
|
||
button, .no-print {
|
||
display: none !important;
|
||
}
|
||
|
||
/* 只打印卡片内容 */
|
||
.ant-card {
|
||
box-shadow: none !important;
|
||
margin: 0 !important;
|
||
padding: 0 !important;
|
||
}
|
||
|
||
/* 移除背景色 */
|
||
body, .bg-gray-50 {
|
||
background: white !important;
|
||
min-height: auto !important;
|
||
padding: 0 !important;
|
||
}
|
||
|
||
/* 确保内容完整打印 */
|
||
.ant-card-body {
|
||
padding: 24px !important;
|
||
page-break-inside: avoid;
|
||
}
|
||
|
||
/* 优化表格打印样式 */
|
||
.ant-table {
|
||
page-break-inside: auto !important;
|
||
}
|
||
|
||
.ant-table-row {
|
||
page-break-inside: avoid !important;
|
||
}
|
||
}
|
||
`;
|
||
|
||
const QuotationView = () => {
|
||
const navigate = useNavigate();
|
||
const { id } = useParams();
|
||
const [data, setData] = useState(null);
|
||
const [loading, setLoading] = useState(true);
|
||
|
||
const fetchQuotationDetail = async () => {
|
||
try {
|
||
const { data: quotation, error } = await supabase
|
||
.from('resources')
|
||
.select('*')
|
||
.eq('id', id)
|
||
.single();
|
||
|
||
if (error) throw error;
|
||
setData(quotation);
|
||
} catch (error) {
|
||
console.error('获取报价单<E4BBB7><E58D95>情失败:', error);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
if (id) {
|
||
fetchQuotationDetail();
|
||
}
|
||
}, [id]);
|
||
|
||
const columns = [
|
||
{
|
||
title: '序号',
|
||
dataIndex: 'index',
|
||
width: 100,
|
||
render: (_, __, index) => index + 1,
|
||
},
|
||
{
|
||
title: '名称',
|
||
dataIndex: 'productName',
|
||
width: '40%',
|
||
},
|
||
{
|
||
title: '数量',
|
||
dataIndex: 'quantity',
|
||
width: '20%',
|
||
align: 'right',
|
||
render: (value) => value?.toLocaleString('zh-CN', { minimumFractionDigits: 2 }),
|
||
},
|
||
{
|
||
title: '单价',
|
||
dataIndex: 'price',
|
||
width: '20%',
|
||
align: 'right',
|
||
render: (value) => value?.toLocaleString('zh-CN', { minimumFractionDigits: 2 }),
|
||
},
|
||
{
|
||
title: '小计',
|
||
width: '20%',
|
||
align: 'right',
|
||
render: (_, record) => (
|
||
(record.quantity * record.price)?.toLocaleString('zh-CN', { minimumFractionDigits: 2 })
|
||
),
|
||
},
|
||
];
|
||
|
||
const handlePrint = () => {
|
||
const printWindow = window.open('', '_blank');
|
||
const printContent = ReactDOMServer.renderToString(<PrintView data={data} />);
|
||
printWindow.document.write(`
|
||
<!DOCTYPE html>
|
||
<html>
|
||
<head>
|
||
<title>打印报价单</title>
|
||
<link rel="stylesheet" href="${window.location.origin}/antd.min.css">
|
||
<style>
|
||
@media print {
|
||
body {
|
||
padding: 0;
|
||
margin: 0;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
${printContent}
|
||
<script>
|
||
window.onload = function() {
|
||
window.print();
|
||
window.onafterprint = function() {
|
||
window.close();
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|
||
`);
|
||
printWindow.document.close();
|
||
};
|
||
|
||
if (loading) {
|
||
return (
|
||
<div className="flex justify-center items-center min-h-screen">
|
||
<Spin size="large" />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (!data) {
|
||
return null;
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<style>{printStyles}</style>
|
||
|
||
<div className="bg-gray-50 min-h-screen ">
|
||
<Card className="max-w-5xl mx-auto shadow-lg">
|
||
<div className="flex justify-between items-center mb-6 no-print">
|
||
<Space>
|
||
<Button
|
||
icon={<ArrowLeftOutlined />}
|
||
onClick={() => navigate('/company/quotation')}
|
||
>
|
||
返回列表
|
||
</Button>
|
||
</Space>
|
||
<Space>
|
||
<Button
|
||
icon={<EditOutlined />}
|
||
type="primary"
|
||
onClick={() => navigate(`/company/quotaInfo/${data.id}?edit=true`)}
|
||
>
|
||
编辑报价单
|
||
</Button>
|
||
<Button
|
||
icon={<PrinterOutlined />}
|
||
onClick={handlePrint}
|
||
>
|
||
打印报价单
|
||
</Button>
|
||
</Space>
|
||
</div>
|
||
|
||
<div className="text-center mb-8">
|
||
<Title level={2} className="!mb-2">{data.attributes.quataName}</Title>
|
||
<Text type="secondary">报价单号:{data.id}</Text>
|
||
</div>
|
||
|
||
<div className="bg-gray-50 p-6 rounded-lg mb-8">
|
||
<Descriptions column={2} bordered>
|
||
<Descriptions.Item label="客户公司" span={1}>
|
||
{data.attributes.companyName}
|
||
</Descriptions.Item>
|
||
<Descriptions.Item label="供应商" span={1}>
|
||
{data.attributes.supplierName}
|
||
</Descriptions.Item>
|
||
<Descriptions.Item label="报价日期" span={1}>
|
||
{new Date(data.created_at).toLocaleDateString('zh-CN')}
|
||
</Descriptions.Item>
|
||
<Descriptions.Item label="报价有效期" span={1}>
|
||
{new Date(Date.now() + 30*24*60*60*1000).toLocaleDateString('zh-CN')}
|
||
</Descriptions.Item>
|
||
</Descriptions>
|
||
</div>
|
||
|
||
<div className="mb-8">
|
||
<Title level={4} className="mb-4">报价明细</Title>
|
||
<Table
|
||
columns={columns}
|
||
dataSource={data.attributes.items}
|
||
pagination={false}
|
||
rowKey={(record, index) => index}
|
||
className="border rounded-lg"
|
||
summary={() => (
|
||
<Table.Summary fixed>
|
||
<Table.Summary.Row className="bg-gray-50 font-bold">
|
||
<Table.Summary.Cell index={0} colSpan={4} align="right">
|
||
总计({data.attributes.currency}):
|
||
</Table.Summary.Cell>
|
||
<Table.Summary.Cell index={1} align="right">
|
||
{data.attributes.totalAmount?.toLocaleString('zh-CN', {
|
||
minimumFractionDigits: 2,
|
||
style: 'currency',
|
||
currency: data.attributes.currency
|
||
})}
|
||
</Table.Summary.Cell>
|
||
</Table.Summary.Row>
|
||
</Table.Summary>
|
||
)}
|
||
/>
|
||
</div>
|
||
|
||
{data.attributes.description && (
|
||
<div className="bg-gray-50 p-6 rounded-lg">
|
||
<Title level={4} className="mb-4">补充说明</Title>
|
||
<Text>{data.attributes.description}</Text>
|
||
</div>
|
||
)}
|
||
|
||
<div className="mt-8 pt-8 border-t border-gray-200">
|
||
<Text type="secondary" className="block mb-2">
|
||
注意事项:
|
||
</Text>
|
||
<ul className="text-gray-500 text-sm">
|
||
<li>1. 本报价单有效期为30天</li>
|
||
<li>2. 最终解释权归本公司所有</li>
|
||
<li>3. 如有疑问请及时联系我们</li>
|
||
</ul>
|
||
</div>
|
||
</Card>
|
||
</div>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default QuotationView; |