import React, { useState, useEffect, useMemo } from "react"; import { Form, Input, InputNumber, Select, Button, Space, Card, Typography, message, Popconfirm, Modal, Divider, } from "antd"; import { PlusOutlined, ArrowLeftOutlined, SaveOutlined, DeleteOutlined, } from "@ant-design/icons"; import { supabase } from "@/config/supabase"; import { useNavigate, useParams, useSearchParams } from "react-router-dom"; import { v4 as uuidv4 } from "uuid"; import SectionList from '@/components/SectionList' import ChatAIDrawer from '@/components/ChatAi'; const { Title } = Typography; // 添加货币符号映射 const CURRENCY_SYMBOLS = { CNY: "¥", TWD: "NT$", USD: "$", }; const QuotationForm = () => { const { id } = useParams(); const [searchParams] = useSearchParams(); const isEdit = searchParams.get("edit") === "true"; const templateId = searchParams.get("templateId"); const isView = id && !isEdit; const [form] = Form.useForm(); const navigate = useNavigate(); const [dataSource, setDataSource] = useState([{ id: Date.now() }]); const [totalAmount, setTotalAmount] = useState(0); const [loading, setLoading] = useState(false); const [currentCurrency, setCurrentCurrency] = useState("TWD"); const [customers, setCustomers] = useState([]); const [selectedCustomers, setSelectedCustomers] = useState([]); const [formValues, setFormValues] = useState({}); const [templateModalVisible, setTemplateModalVisible] = useState(false); const [availableSections, setAvailableSections] = useState([]); const [editingSectionIndex, setEditingSectionIndex] = useState(null); const [editingSectionName, setEditingSectionName] = useState(""); const [taxRate, setTaxRate] = useState(0); const [discount, setDiscount] = useState(0); // 计算单项金额 const calculateItemAmount = useMemo( () => (quantity, price) => { const safeQuantity = Number(quantity) || 0; const safePrice = Number(price) || 0; return safeQuantity * safePrice; }, [] ); // 计算小节总额 const calculateSectionTotal = useMemo( () => (items = []) => { if (!Array.isArray(items)) return 0; return items.reduce((sum, item) => { if (!item) return sum; return sum + calculateItemAmount(item.quantity, item.price); }, 0); }, [calculateItemAmount] ); // 计算总金额 const calculateTotalAmount = useMemo( () => (sections = []) => { if (!Array.isArray(sections)) return 0; return sections.reduce((sum, section) => { if (!section) return sum; return sum + calculateSectionTotal(section.items); }, 0); }, [calculateSectionTotal] ); // 格式化货币 const formatCurrency = useMemo( () => (amount, currency = currentCurrency) => { const safeAmount = Number(amount) || 0; return `${CURRENCY_SYMBOLS[currency] || ""}${safeAmount.toLocaleString( "zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2, } )}`; }, [currentCurrency] ); useEffect(() => { console.log(currentCurrency, 'currency'); }, [currentCurrency]) // 处理表单值变化 const handleValuesChange = (changedValues, allValues) => { setFormValues(allValues); if (changedValues.currency) { setCurrentCurrency(changedValues.currency); } }; // 修改初始值,确保每个项目都有唯一ID const initialValues = { currency: "TWD", sections: [ { key: uuidv4(), sectionName: "服务类型 1", items: [ { key: uuidv4(), name: "", quantity: 1, price: 0, description: "", unit: "", }, ], }, ], }; const fetchQuotationDetail = async () => { try { setLoading(true); const { data, error } = await supabase .from("resources") .select("*") .eq("id", id) .single(); if (error) throw error; if (data?.attributes) { const formData = { quataName: data.attributes.quataName, customers: data.attributes.customers.map((customer) => customer.id) || [], description: data.attributes.description, currency: data.attributes.currency || "TWD", sections: data.attributes.sections.map((section) => ({ key: uuidv4(), sectionName: section.sectionName, items: section.items.map((item) => ({ key: uuidv4(), name: item.name, quantity: Number(item.quantity) || 0, price: Number(item.price) || 0, description: item.description || "", unit: item.unit || "", })), })), taxRate: data.attributes.taxRate || 0, discount: data.attributes.discount || 0, }; form.setFieldsValue(formData); setFormValues(formData); setCurrentCurrency(data.attributes.currency || "TWD"); setTaxRate(data.attributes.taxRate || 0); setDiscount(data.attributes.discount || 0); if (data.attributes.customers) { setSelectedCustomers(data.attributes.customers); } } } catch (error) { console.error("获取报价单详情失败:", error); message.error("获取报价单详情失败"); } finally { setLoading(false); } }; const fetchTemplateData = async () => { try { setLoading(true); const { data: template, error } = await supabase .from("resources") .select("*") .eq("type", "serviceTemplate") .eq("id", templateId) .single(); if (error) throw error; if (template?.attributes) { const quotationData = { quataName: template.attributes.templateName, description: template.attributes.description, currency: template.attributes.currency || "TWD", category: template.attributes.category, sections: template.attributes.sections.map((section) => ({ key: uuidv4(), sectionName: section.sectionName, items: section.items.map((item) => ({ key: uuidv4(), name: item.name, quantity: item.quantity, price: item.price, description: item.description, unit: item.unit, })), })), }; setCurrentCurrency(template.attributes.currency || "TWD"); form.setFieldsValue(quotationData); setFormValues(quotationData); } } catch (error) { console.error("获取模板数据失败:", error); message.error("获取模板数据失败"); } finally { setLoading(false); } }; // 使用 useMemo 计算税后金额 const afterTaxAmount = useMemo(() => { const beforeTaxAmount = calculateTotalAmount(formValues?.sections) || 0; const taxAmount = beforeTaxAmount * (taxRate / 100); return beforeTaxAmount + taxAmount; }, [formValues?.sections, taxRate, calculateTotalAmount]); // 修改保存函数 const onFinish = async (values) => { try { setLoading(true); const beforeTaxAmount = calculateTotalAmount(values.sections); const quotationData = { type: "quota", attributes: { quataName: values.quataName, customers: customers .filter(customer => values.customers.includes(customer.id)) .map(customer => ({ id: customer.id, name: customer.attributes.name })), description: values.description, currency: currentCurrency, sections: values.sections.map((section) => ({ sectionName: section.sectionName, items: section.items.map((item) => ({ name: item.name, unit: item.unit, price: item.price, quantity: item.quantity, description: item.description, })), })), beforeTaxAmount, taxRate, afterTaxAmount, discount, finalAmount: discount || afterTaxAmount, }, }; let result; if (id) { result = await supabase .from("resources") .update(quotationData) .eq("id", id) .select(); } else { result = await supabase .from("resources") .insert([quotationData]) .select(); } if (result.error) throw result.error; message.success("保存成功"); navigate("/company/quotation"); } catch (error) { console.error("保存失败:", error); message.error("保存失败"); } finally { setLoading(false); } }; const fetchCustomers = async () => { try { const { data, error } = await supabase .from("resources") .select("*") .eq("type", "customer"); if (error) throw error; setCustomers(data || []); } catch (error) { console.error("获取客户列表失败:", error); } }; useEffect(() => { fetchCustomers(); }, []); // 确保在组件加载时正确获取数据 useEffect(() => { if (id) { fetchQuotationDetail(); } else if (templateId) { fetchTemplateData(); } else { // 如果既不是编辑也不是从模板创建,则设置初始值 form.setFieldsValue(initialValues); setFormValues(initialValues); } }, [id, templateId]); const [open, setOpen] = useState(false); const handleExport = (data) => { if(data?.activityName&&data?.currency){ const quotationData = { quataName: data.activityName, description: data.description, currency: data.currency || "TWD", sections: data.sections.map((section) => ({ key: uuidv4(), sectionName: section.sectionName, items: section.items.map((item) => ({ key: uuidv4(), name: item.name, quantity: item.quantity, price: item.price, description: item.description, unit: item.unit, })), })), }; setCurrentCurrency(data.currency || "TWD"); form.setFieldsValue(quotationData); setFormValues(quotationData); setTaxRate(data.taxRate || 0); message.success('已添加报价单'); }else{ const _data={ ...data, key: uuidv4(), } const newSections = [...formValues.sections, _data]; form.setFieldValue('sections', newSections); const currentFormValues = form.getFieldsValue(); setFormValues({ ...currentFormValues, sections: newSections }); message.success('已添加新的服务项目'); } setOpen(false); }; return (
{id ? (isEdit ? "编辑报价单" : "查看报价单") : "新建报价单"} {id ? isEdit ? "请修改报价单信息" : "报价单详情" : "请填写报价单信息"}
{!isView && ( <> )}
} >
{/* 基本信息卡片 */} 基本信息 } bordered={false} >
活动名称 } rules={[{ required: true, message: "活动名称" }]} > 货币类型} rules={[{ required: true, message: "请选择货币类型" }]} > 客户名称} rules={[{ required: true, message: "请选择至少一个客户" }]} >