This commit is contained in:
‘Liammcl’
2024-12-29 01:11:01 +08:00
parent ffb8fdfe83
commit 22b0ec8d5a
18 changed files with 2434 additions and 1158 deletions

View File

@@ -1,119 +0,0 @@
import React from 'react';
import { Table } from 'antd';
const PrintView = ({ data }) => {
const columns = [
{
title: '序号',
dataIndex: 'index',
width: 60,
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 })
),
},
];
return (
<div className="print-wrapper">
<div className="print-header">
<h1>{data.attributes.quataName}</h1>
<div className="quotation-id">报价单号{data.id}</div>
</div>
<div className="info-grid">
<div className="info-item">
<span className="info-label">客户公司</span>
<span className="info-value">{data.attributes.companyName}</span>
</div>
<div className="info-item">
<span className="info-label">供应商</span>
<span className="info-value">{data.attributes.supplierName}</span>
</div>
<div className="info-item">
<span className="info-label">报价日期</span>
<span className="info-value">
{new Date(data.created_at).toLocaleDateString('zh-CN')}
</span>
</div>
<div className="info-item">
<span className="info-label">报价有效期</span>
<span className="info-value">
{new Date(Date.now() + 30*24*60*60*1000).toLocaleDateString('zh-CN')}
</span>
</div>
</div>
<div>
<div className="section-title">报价明细</div>
<Table
columns={columns}
dataSource={data.attributes.items}
pagination={false}
rowKey={(record, index) => index}
bordered
summary={() => (
<Table.Summary fixed>
<Table.Summary.Row>
<Table.Summary.Cell index={0} colSpan={4} align="right">
总计{data.attributes.currency}
</Table.Summary.Cell>
<Table.Summary.Cell index={1} align="right">
<span style={{ color: '#1890ff', fontSize: '16px' }}>
{data.attributes.totalAmount?.toLocaleString('zh-CN', {
minimumFractionDigits: 2,
style: 'currency',
currency: data.attributes.currency
})}
</span>
</Table.Summary.Cell>
</Table.Summary.Row>
</Table.Summary>
)}
/>
</div>
{data.attributes.description && (
<div className="description-section">
<div className="section-title">补充说明</div>
<div>{data.attributes.description}</div>
</div>
)}
<div className="notes-section">
<div className="notes-title">注意事项</div>
<ul className="notes-list">
<li>本报价单有效期为30天</li>
<li>最终解释权归本公司所有</li>
<li>如有疑问请及时联系我们</li>
</ul>
</div>
</div>
);
};
export default PrintView;

View File

@@ -328,6 +328,49 @@ const SectionList = ({
</div>
);
});
const addSectionFn = async (field) => {
try {
await form.validateFields(['sections', field.name]);
const allValues = form.getFieldsValue(true);
const currentSection = allValues.sections[field.name];
if (!currentSection) {
throw new Error('未找到section数据');
}
const templateData = {
type: 'sections',
attributes: {
name: currentSection.sectionName,
template_type: type,
items: currentSection.items.map(item => ({
name: item.name,
description: item.description,
quantity: item.quantity,
price: item.price,
unit: item.unit
}))
},
schema_version: 1
};
console.log('准备保存的数据:', templateData);
const { error } = await supabase
.from('resources')
.insert([templateData]);
if (error) throw error;
message.success('保存模板成功');
fetchAvailableSections();
} catch (error) {
message.error('保存模板失败');
console.error(error);
}
};
return (
<>
<Form.List name="sections">
@@ -400,12 +443,21 @@ const SectionList = ({
)}
</div>
{!isView && (
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => remove(field.name)}
/>
<div className="flex gap-3">
<Button
type="text"
icon={<PlusOutlined />}
onClick={() => addSectionFn(field)}
>
添加到模版
</Button>
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => remove(field.name)}
/>
</div>
)}
</div>
}

View File

@@ -289,7 +289,48 @@ const SectionList = ({ form, isView, formValues, type }) => {
)}
</div>
);
const addSectionFn = async (field) => {
try {
await form.validateFields(['sections', field.name]);
const allValues = form.getFieldsValue(true);
const currentSection = allValues.sections[field.name];
if (!currentSection) {
throw new Error('未找到section数据');
}
const templateData = {
type: 'sections',
attributes: {
name: currentSection.sectionName,
template_type: type,
items: currentSection.items.map(item => ({
name: item.name,
description: item.description,
quantity: item.quantity,
price: item.price,
unit: item.unit
}))
},
schema_version: 1
};
const { error } = await supabase
.from('resources')
.insert([templateData]);
if (error) throw error;
message.success('保存模板成功');
fetchAvailableSections();
} catch (error) {
message.error('保存模板失败');
console.error(error);
}
};
return (
<>
<Form.List name="sections">
@@ -362,12 +403,23 @@ const SectionList = ({ form, isView, formValues, type }) => {
)}
</div>
{!isView && (
<Button
<div className="flex gap-3">
<Button
type="text"
icon={<PlusOutlined />}
onClick={() => addSectionFn(field)}
className="ml-2"
>
添加到模版
</Button>
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => remove(field.name)}
/>
</div>
)}
</div>
}
@@ -516,13 +568,15 @@ const SectionList = ({ form, isView, formValues, type }) => {
</Form.Item>
{!isView && itemFields.length > 1 && (
<Button
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => removeItem(itemField.name)}
className="flex items-center justify-center"
/>
/>
)}
</div>
);

View File

@@ -9,12 +9,12 @@ const TEMPLATE_TYPES = [
icon: <FileTextOutlined className="text-2xl text-blue-500" />,
description: '创建标准化的报价单模板,包含服务项目、价格等信息'
},
{
key: 'project',
title: '专案模板',
icon: <ProjectOutlined className="text-2xl text-green-500" />,
description: '创建专案流程模板,包含项目阶段、时间线等信息'
},
// {
// key: 'project',
// title: '专案模板',
// icon: <ProjectOutlined className="text-2xl text-green-500" />,
// description: '创建专案流程模板,包含项目阶段、时间线等信息'
// },
{
key: 'task',
title: '任务模板',