diff --git a/jsconfig.json b/jsconfig.json index df83de4..9eeca62 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -2,7 +2,12 @@ "compilerOptions": { "baseUrl": ".", "paths": { - "@/*": ["src/*"] + "@/*": ["src/*"], + "@components/*": ["src/components/*"], + "@pages/*": ["src/pages/*"], + "@utils/*": ["src/utils/*"], + "@assets/*": ["src/assets/*"], + "@config/*": ["src/config/*"] } } } \ No newline at end of file diff --git a/src/components/SectionList/index.jsx b/src/components/SectionList/index.jsx index 38168af..d0f1ffe 100644 --- a/src/components/SectionList/index.jsx +++ b/src/components/SectionList/index.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useMemo } from 'react'; import { Form, Input, InputNumber, Button, Card, Typography, Modal, message, Divider, Select } from 'antd'; import { PlusOutlined, DeleteOutlined, EditOutlined, CheckOutlined, CloseOutlined } from '@ant-design/icons'; import { v4 as uuidv4 } from 'uuid'; @@ -247,12 +247,53 @@ const SectionList = ({ onClick={() => handleCreateCustom(add, fieldsLength)} className="w-1/3 border-2" > - 自定义小节 + 自定义模块 ); + // 修改项目小计的计算,将其封装为 memo 组件 + const ItemSubtotal = React.memo(({ quantity, price, currentCurrency }) => { + const subtotal = useMemo(() => { + const safeQuantity = Number(quantity) || 0; + const safePrice = Number(price) || 0; + return safeQuantity * safePrice; + }, [quantity, price]); + + return ( +
+ + {formatCurrency(subtotal, currentCurrency)} + +
+ ); + }); + + // 修改小节总计的计算,将其封装为 memo 组件 + const SectionTotal = React.memo(({ items, currentCurrency }) => { + const total = useMemo(() => { + if (!Array.isArray(items)) return 0; + return items.reduce((sum, item) => { + if (!item) return sum; + const safeQuantity = Number(item.quantity) || 0; + const safePrice = Number(item.price) || 0; + return sum + (safeQuantity * safePrice); + }, 0); + }, [items]); + + return ( +
+ + 小计总额: + + {formatCurrency(total, currentCurrency)} + + +
+ ); + }); + return ( <> @@ -439,16 +480,11 @@ const SectionList = ({ > -
- - {formatCurrency( - calculateItemAmount( - formValues?.sections?.[sectionIndex]?.items?.[itemIndex]?.quantity, - formValues?.sections?.[sectionIndex]?.items?.[itemIndex]?.price - ) - )} - -
+ {!isView && itemFields.length > 1 && ( @@ -368,348 +534,69 @@ const ServicePage = () => { }, ]; - // 子表格列定义 - const itemColumns = [ - { - title: "项目名称", - dataIndex: "name", - key: "name", - render: (text, record) => { - const isEditing = record.key === editingKey; - return isEditing ? ( - ( +
+ + {Object.entries(TEMPLATE_TYPES).map(([key, value]) => ( + - - - ) : ( - - - handleDeleteItem(record)} - > - - - - ); - }, - }, - ]; - - // 修改 expandedRowRender 函数,确保 key 的唯一性 - const expandedRowRender = (record) => ( -
- {record.attributes.sections?.map((section, sectionIndex) => ( - - - {section.sectionName || `服务类型 ${sectionIndex + 1}`} - - - 总计: ¥ - {section.items - .reduce( - (total, item) => - total + - (Number(item.price) || 0) * (Number(item.quantity) || 0), - 0 - ) - .toLocaleString("zh-CN", { - minimumFractionDigits: 2, - maximumFractionDigits: 2, - })} - -
- } - headStyle={{ - background: "rgba(59, 130, 246, 0.05)", - borderBottom: "1px solid rgba(59, 130, 246, 0.1)", - }} - style={{ - background: "rgba(59, 130, 246, 0.02)", - }} + + ))} + {selectedType && ( + + )} + + +