This commit is contained in:
@@ -199,7 +199,7 @@ export const AuthProvider = ({ children }) => {
|
|||||||
.single();
|
.single();
|
||||||
if (error) throw error;
|
if (error) throw error;
|
||||||
if(data?.attributes?.menuKeys){
|
if(data?.attributes?.menuKeys){
|
||||||
return data.attributes.menuKeys;
|
return data.attributes.menuKeys;
|
||||||
}else{
|
}else{
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import html2canvas from 'html2canvas';
|
|||||||
import jsPDF from 'jspdf';
|
import jsPDF from 'jspdf';
|
||||||
|
|
||||||
const { Title, Text } = Typography;
|
const { Title, Text } = Typography;
|
||||||
import { EXCHANGE_RATE,defaultSymbol } from '@/utils/exchange_rate';
|
import { EXCHANGE_RATE, defaultSymbol } from '@/utils/exchange_rate';
|
||||||
|
|
||||||
const QuotationPreview = () => {
|
const QuotationPreview = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
@@ -114,17 +114,6 @@ const QuotationPreview = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 导出按钮组件
|
|
||||||
const ExportPDFButton = () => (
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
icon={<DownloadOutlined />}
|
|
||||||
onClick={exportPDF}
|
|
||||||
>
|
|
||||||
导出PDF
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-center h-full">
|
<div className="flex justify-center items-center h-full">
|
||||||
@@ -139,52 +128,69 @@ const QuotationPreview = () => {
|
|||||||
const currencySymbol = EXCHANGE_RATE[attributes.currency]?.symbol || defaultSymbol;
|
const currencySymbol = EXCHANGE_RATE[attributes.currency]?.symbol || defaultSymbol;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-4xl mx-auto p-6">
|
<div className="min-h-screen bg-gradient-to-b from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 p-6 transition-colors duration-200">
|
||||||
<Card
|
<Card
|
||||||
title={
|
className="max-w-4xl mx-auto shadow-lg rounded-2xl bg-white dark:bg-gray-800 transition-colors duration-200"
|
||||||
|
bodyStyle={{ padding: 0 }}
|
||||||
|
>
|
||||||
|
<div className="p-6 border-b border-gray-200 dark:border-gray-700">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<Space>
|
<Space>
|
||||||
<FileTextOutlined className="text-blue-500" />
|
<FileTextOutlined className="text-blue-500 dark:text-blue-400" />
|
||||||
<span>报价单预览</span>
|
<span className="text-gray-800 dark:text-gray-200 font-medium">报价单预览</span>
|
||||||
</Space>
|
</Space>
|
||||||
<ExportPDFButton />
|
<Button
|
||||||
|
type="primary"
|
||||||
|
icon={<DownloadOutlined />}
|
||||||
|
onClick={exportPDF}
|
||||||
|
className="bg-blue-500 hover:bg-blue-600 border-none rounded-full shadow-md hover:shadow-lg transition-all duration-200"
|
||||||
|
>
|
||||||
|
导出PDF
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
</div>
|
||||||
>
|
|
||||||
<div id="quotation-content" className="p-6">
|
<div id="quotation-content" className="p-8 bg-white" style={{ width: '210mm', margin: '0 auto' }}>
|
||||||
<div className="text-center mb-8">
|
<div className="text-center mb-8">
|
||||||
<Title level={2}>{attributes.quataName}</Title>
|
<Title level={2} className="dark:text-gray-200">{attributes.quataName}</Title>
|
||||||
<Text type="secondary">创建日期:{new Date(quotation.created_at).toLocaleDateString()}</Text>
|
<Text type="secondary" className="dark:text-gray-400">
|
||||||
|
创建日期:{new Date(quotation.created_at).toLocaleDateString()}
|
||||||
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-gray-50 p-4 rounded-lg mb-6">
|
<div className="bg-gray-50 dark:bg-gray-700 p-6 rounded-2xl mb-6">
|
||||||
<Title level={4}>基本信息</Title>
|
<Title level={4} className="dark:text-gray-200 mb-4">基本信息</Title>
|
||||||
<div className="grid grid-cols-2 gap-4">
|
<div className="grid grid-cols-2 gap-6">
|
||||||
<div>
|
<div>
|
||||||
<Text type="secondary">客户:</Text>
|
<Text type="secondary" className="dark:text-gray-400">客户:</Text>
|
||||||
<Space>
|
<Space className="mt-2">
|
||||||
{attributes.customers?.map(customer => (
|
{attributes.customers?.map(customer => (
|
||||||
<Tag key={customer.id} color="blue">{customer.name}</Tag>
|
<Tag
|
||||||
|
key={customer.id}
|
||||||
|
className="px-3 py-1 rounded-full bg-blue-100 text-blue-600 dark:bg-blue-900 dark:text-blue-200 border-none"
|
||||||
|
>
|
||||||
|
{customer.name}
|
||||||
|
</Tag>
|
||||||
))}
|
))}
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Text type="secondary">货币类型:</Text>
|
<Text type="secondary" className="dark:text-gray-400">货币类型:</Text>
|
||||||
<Text>{attributes.currency}</Text>
|
<Text className="dark:text-gray-200 ml-2">{attributes.currency}</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{attributes.sections?.map((section, sIndex) => (
|
{attributes.sections?.map((section, sIndex) => (
|
||||||
<div key={sIndex} className="mb-6">
|
<div key={sIndex} className="mb-8">
|
||||||
<div className="flex items-center gap-2 h-full">
|
<div className="flex items-center gap-3 mb-4">
|
||||||
<div className="h-4 w-1 bg-blue-500 rounded-full" />
|
<div className="h-4 w-1 bg-blue-500 rounded-full" />
|
||||||
<h2>{section.sectionName}</h2>
|
<h2 className="text-lg font-medium dark:text-gray-200">{section.sectionName}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto rounded-2xl border border-gray-200 dark:border-gray-700">
|
||||||
<table className="min-w-full divide-y divide-gray-200">
|
<table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
<thead className="bg-gray-50">
|
<thead className="bg-gray-50 dark:bg-gray-800">
|
||||||
<tr>
|
<tr>
|
||||||
<th className="px-4 py-3 text-left text-sm font-medium text-gray-500">项目明细</th>
|
<th className="px-4 py-3 text-left text-sm font-medium text-gray-500">项目明细</th>
|
||||||
<th className="px-4 py-3 text-left text-sm font-medium text-gray-500">描述/备注</th>
|
<th className="px-4 py-3 text-left text-sm font-medium text-gray-500">描述/备注</th>
|
||||||
@@ -194,9 +200,9 @@ const QuotationPreview = () => {
|
|||||||
<th className="px-4 py-3 text-right text-sm font-medium text-gray-500">小计</th>
|
<th className="px-4 py-3 text-right text-sm font-medium text-gray-500">小计</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className="bg-white divide-y divide-gray-200">
|
<tbody className="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
{section.items.map((item, iIndex) => (
|
{section.items.map((item, iIndex) => (
|
||||||
<tr key={iIndex}>
|
<tr key={iIndex} className="hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors duration-150">
|
||||||
<td className="px-4 py-3 text-sm text-gray-900">{item.name}</td>
|
<td className="px-4 py-3 text-sm text-gray-900">{item.name}</td>
|
||||||
<td className="px-4 py-3 text-sm text-gray-500">{item.description}</td>
|
<td className="px-4 py-3 text-sm text-gray-500">{item.description}</td>
|
||||||
<td className="px-4 py-3 text-sm text-gray-500">{item.unit}</td>
|
<td className="px-4 py-3 text-sm text-gray-500">{item.unit}</td>
|
||||||
@@ -216,9 +222,9 @@ const QuotationPreview = () => {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
{/* 金额汇总 */}
|
{/* 金额汇总 */}
|
||||||
<div className="mt-8 border-t pt-4">
|
<div className="mt-8 border-t border-gray-200 dark:border-gray-700 pt-6">
|
||||||
<div className="flex justify-end space-y-2">
|
<div className="flex justify-end">
|
||||||
<div className="w-64 space-y-2">
|
<div className="w-64 space-y-3">
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between">
|
||||||
<Text>税前总计:</Text>
|
<Text>税前总计:</Text>
|
||||||
<Text>{currencySymbol}{attributes.beforeTaxAmount?.toLocaleString()}</Text>
|
<Text>{currencySymbol}{attributes.beforeTaxAmount?.toLocaleString()}</Text>
|
||||||
@@ -238,9 +244,9 @@ const QuotationPreview = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Divider className="my-2" />
|
<Divider className="my-2" />
|
||||||
<div className="flex justify-between">
|
<div className="flex justify-between items-center">
|
||||||
<Text strong>最终金额:</Text>
|
<Text strong className="dark:text-gray-200">最终金额:</Text>
|
||||||
<Text strong className="text-blue-500 text-xl">
|
<Text strong className="text-xl text-blue-500 dark:text-blue-400">
|
||||||
{currencySymbol}{(attributes.discount || attributes.afterTaxAmount)?.toLocaleString()}
|
{currencySymbol}{(attributes.discount || attributes.afterTaxAmount)?.toLocaleString()}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
@@ -251,9 +257,9 @@ const QuotationPreview = () => {
|
|||||||
{/* 补充说明 */}
|
{/* 补充说明 */}
|
||||||
{attributes.description && (
|
{attributes.description && (
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<Title level={4}>补充说明</Title>
|
<Title level={4} className="dark:text-gray-200">补充说明</Title>
|
||||||
<div className="bg-gray-50 p-4 rounded-lg">
|
<div className="bg-gray-50 dark:bg-gray-700 p-6 rounded-2xl">
|
||||||
<Text>{attributes.description}</Text>
|
<Text className="dark:text-gray-300">{attributes.description}</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user