From dfe9a89213b8fb80ba037df83a8313f0f76656cf Mon Sep 17 00:00:00 2001 From: shenyifei Date: Thu, 11 Dec 2025 12:42:01 +0800 Subject: [PATCH] =?UTF-8?q?refactor(components):=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=87=87=E8=B4=AD=E6=A8=A1=E5=9D=97=E7=A9=BA=E7=AE=B1=E5=92=8C?= =?UTF-8?q?=E8=B4=B9=E7=94=A8=E7=BB=84=E4=BB=B6=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 PageList 组件中对全局 loading 状态的依赖 - 简化 EmptyBoxModule 组件逻辑,使用 PackageList 组件替代原有复杂实现 - 移除冗余的状态管理和弹窗渲染逻辑 - 优化 OrderCost 组件样式和费用项匹配逻辑 - 修复成本项 ID 匹配问题,确保数据正确关联 - 添加边框样式增强视觉效果 - 移除调试日志和无用代码 - 简化组件间数据传递方式 --- .../src/components/biz/PageList.tsx | 11 +- .../purchase/PurchaseOrderApprovalList.tsx | 9 +- .../purchase/PurchaseOrderAuditList.tsx | 9 +- .../src/components/purchase/cost/CostCard.tsx | 7 + .../purchase/module/EmptyBoxModule.tsx | 888 +----------------- .../purchase/module/MelonFarmer.tsx | 6 +- .../components/purchase/module/OrderCost.tsx | 169 ++-- .../purchase/module/OrderCostItem.tsx | 404 ++++---- .../purchase/module/OrderOption.tsx | 4 +- .../purchase/module/OrderPackage.tsx | 413 ++++---- .../purchase/module/OrderVehicle.tsx | 600 ++++++------ .../purchase/package/PackageCard.tsx | 2 +- .../purchase/package/PackageList.tsx | 11 +- .../app-client/src/pages/main/menu/index.tsx | 1 - .../src/pages/purchase/approval/result.tsx | 9 +- .../src/pages/purchase/audit/audit.tsx | 131 ++- .../src/pages/purchase/audit/result.tsx | 9 +- .../src/pages/purchase/enter/create.tsx | 4 +- .../src/pages/purchase/enter/result.tsx | 9 +- .../app-client/src/pages/supplier/create.tsx | 10 +- .../src/services/business/typings.d.ts | 8 +- 21 files changed, 1033 insertions(+), 1681 deletions(-) diff --git a/packages/app-client/src/components/biz/PageList.tsx b/packages/app-client/src/components/biz/PageList.tsx index 5e21821..43cae9e 100644 --- a/packages/app-client/src/components/biz/PageList.tsx +++ b/packages/app-client/src/components/biz/PageList.tsx @@ -18,7 +18,6 @@ import { } from "@nutui/nutui-react-taro"; import { Icon } from "@/components"; import classNames from "classnames"; -import { globalStore } from "@/store/global-store"; import { ActionType, IRecordListProps, Query, Record } from "./typing"; export default ( @@ -48,7 +47,6 @@ export default ( toolbar?.search?.defaultActiveKey || "", ); - const { loading, setLoading } = globalStore((state: any) => state); const [lightTheme, setLightTheme] = useState(false); const [data, setData] = useState[]>(); const [query, setQuery] = useState(); @@ -109,11 +107,10 @@ export default ( } }) .exec(); - }, [loading, toolbar]); + }, [toolbar]); useEffect(() => { if (query) { - setLoading(true); request(query as any).then((res: Record) => { const list = res.data; if (res.success) { @@ -132,7 +129,6 @@ export default ( if (res.hasMore !== undefined) { setHasMore(res.hasMore); } - setLoading(false); } }); } @@ -141,8 +137,7 @@ export default ( const [hasMore, setHasMore] = useState(); const loadMore = async () => { - if (hasMore && !loading && query?.pageIndex) { - setLoading(true); + if (hasMore && query?.pageIndex) { setQuery({ ...query, pageIndex: query.pageIndex + 1, @@ -166,7 +161,7 @@ export default ( ); }; - if (loading || !data) { + if (!data) { if (skeleton) { return renderSkeleton(); } diff --git a/packages/app-client/src/components/purchase/PurchaseOrderApprovalList.tsx b/packages/app-client/src/components/purchase/PurchaseOrderApprovalList.tsx index 1258afd..4ca9c6d 100644 --- a/packages/app-client/src/components/purchase/PurchaseOrderApprovalList.tsx +++ b/packages/app-client/src/components/purchase/PurchaseOrderApprovalList.tsx @@ -1,5 +1,6 @@ import { ActionType, + CopyText, DealerPicker, Icon, PageList, @@ -167,9 +168,11 @@ export default function PurchaseOrderApprovalList( - - {purchaseOrderVO.orderSn} - + + + {purchaseOrderVO.orderSn} + + 采购单号 - - {purchaseOrderVO.orderSn} - + + + {purchaseOrderVO.orderSn} + + diff --git a/packages/app-client/src/components/purchase/module/EmptyBoxModule.tsx b/packages/app-client/src/components/purchase/module/EmptyBoxModule.tsx index 23fd631..740a91e 100644 --- a/packages/app-client/src/components/purchase/module/EmptyBoxModule.tsx +++ b/packages/app-client/src/components/purchase/module/EmptyBoxModule.tsx @@ -1,24 +1,10 @@ -import { ScrollView, View } from "@tarojs/components"; -import { Icon } from "@/components"; +import { View } from "@tarojs/components"; +import { PackageList } from "@/components"; import { useEffect, useState } from "react"; import { business } from "@/services"; -import { - Button, - Checkbox, - Dialog, - Image, - Input, - Popup, - SafeArea, - Toast, -} from "@nutui/nutui-react-taro"; +import { Checkbox } from "@nutui/nutui-react-taro"; import { BoxBrand, BoxProduct, BoxSpec } from "@/types/typings"; -import { - convertBoxBrandToOrderPackages, - convertOrderPackagesToBoxBrands, - generateShortId, -} from "@/utils"; -import classNames from "classnames"; +import { generateShortId } from "@/utils"; export interface IEmptyBoxModuleProps { orderPackageList: BusinessAPI.OrderPackage[]; @@ -28,23 +14,9 @@ export interface IEmptyBoxModuleProps { export default function EmptyBoxModule(props: IEmptyBoxModuleProps) { const { orderPackageList, onChange } = props; - // 空箱相关状态 - const [emptyBoxList, setEmptyBoxList] = useState( - [], - ); + const [hasEmptyBox, setHasEmptyBox] = useState(false); const [boxBrandList, setBoxBrandList] = useState(); - // 批量添加空箱相关状态 - const [selectedBrand, setSelectedBrand] = useState(null); - const [productCounts, setProductCounts] = useState>( - new Map(), - ); - const [showBatchModal, setShowBatchModal] = useState(false); - - // 编辑空箱弹窗状态 - const [showEditModal, setShowEditModal] = useState(false); - const [editingItem, setEditingItem] = useState(null); - // 初始化空箱品牌数据 const initBoxBrandList = async () => { const { data } = await business.boxBrand.listBoxBrand({ @@ -126,833 +98,51 @@ export default function EmptyBoxModule(props: IEmptyBoxModuleProps) { // 当传入的value发生变化时,重新初始化列表 useEffect(() => { initBoxBrandList().then(); - setEmptyBoxList(orderPackageList); if (orderPackageList?.length > 0) { - // 根据当前供应商确定需要检查的纸箱类型 - let requiredTypes: string[] = ["EMPTY"]; - - requiredTypes.map((type) => { - setPackageTypeEnabled((prev) => ({ - ...prev, - [type]: orderPackageList.some((item) => item.boxType === type) - ? 1 - : 0, - })); - }); + setHasEmptyBox(true); } }, []); - // 当空箱列表变化时,通知父组件更新 - useEffect(() => { - onChange( - emptyBoxList?.map((item) => { - return { - ...item, - id: generateShortId(), - }; - }), - ); - }, [emptyBoxList]); - - // 处理批量添加时的品牌选择 - const handleBatchBrandSelect = (brand: BoxBrand) => { - // 检查是否已存在该品牌 - const isBrandAlreadySelected = emptyBoxList.some( - (pkg) => pkg.boxBrandId === brand.boxBrandId, - ); - - if (isBrandAlreadySelected) { - Toast.show("toast", { - icon: "fail", - title: "提示", - content: "该空箱品牌已存在,请选择其他品牌或编辑现有信息", - }); - return; - } - - setSelectedBrand(brand); - // 初始化所有产品的数量为0 - const initialCounts = new Map(); - brand.boxSpecList?.forEach((boxSpec) => { - boxSpec.boxProductList.forEach((product) => { - initialCounts.set(product.id, 0); - }); - }); - setProductCounts(initialCounts); - }; - - // 处理产品数量变化 - const handleProductCountChange = (productId: string, count: number) => { - setProductCounts((prev) => { - const newCounts = new Map(prev); - newCounts.set(productId, Math.max(0, count)); // 允许为0,表示不使用 - return newCounts; - }); - - // 同时更新selectedBrand中的产品数量 - if (selectedBrand) { - const updatedBrand = { ...selectedBrand }; - - updatedBrand.boxSpecList = updatedBrand.boxSpecList?.map((boxSpec) => { - const updatedProducts = boxSpec.boxProductList.map((product) => { - if (product.id === productId) { - return { ...product, boxCount: count }; - } - return product; - }); - return { ...boxSpec, boxProductList: updatedProducts }; - }); - setSelectedBrand(updatedBrand); - } - }; - - // 批量添加空箱信息 - const addBatchEmptyBoxInfo = () => { - if (!selectedBrand) { - return; - } - - // 使用convertBoxBrandToOrderPackages转换数据 - const newOrderPackages = convertBoxBrandToOrderPackages( - selectedBrand, - "EMPTY", - ); - - // 过滤掉数量为0的项目 - const filteredOrderPackages = newOrderPackages.filter((pkg) => { - // 从productCounts中获取对应产品的数量 - const product = selectedBrand.boxSpecList - ?.flatMap((c) => c.boxProductList) - .find((p) => p.id === pkg.orderPackageId); - const count = product ? productCounts.get(product.id) || 0 : 0; - return count > 0; - }); - - // 更新数量信息 - const updatedOrderPackages = filteredOrderPackages.map((pkg) => { - // 从productCounts中获取对应产品的数量 - const product = selectedBrand.boxSpecList - ?.flatMap((c) => c.boxProductList) - .find((p) => p.id === pkg.orderPackageId); - const count = product ? productCounts.get(product.id) || 0 : 0; - return { - ...pkg, - boxCount: count, - }; - }); - - // 添加到emptyBoxList中 - setEmptyBoxList((prev) => [...prev, ...updatedOrderPackages]); - - // 重置选择并关闭弹窗 - setSelectedBrand(null); - setProductCounts(new Map()); - setShowBatchModal(false); - }; - - // 删除空箱信息 - const removeEmptyBoxInfo = (boxBrandId: string) => { - console.log("removeEmptyBoxInfo", boxBrandId); - Dialog.open("dialog", { - title: "提示", - content: "确定要移除此空箱品牌吗?", - confirmText: "确定", - cancelText: "取消", - onConfirm: () => { - const newList = [ - ...emptyBoxList.filter((item) => item.boxBrandId !== boxBrandId), - ]; - setEmptyBoxList(newList); - Dialog.close("dialog"); - }, - onCancel: () => { - Dialog.close("dialog"); - }, - }); - }; - - // 处理编辑按钮点击 - const handleEditItem = (item: BoxBrand) => { - // 从emptyBoxList中找到完整的品牌信息用于编辑 - const brandToEdit = convertOrderPackagesToBoxBrands( - emptyBoxList.filter((pkg) => pkg.boxBrandId === item.boxBrandId), - )[0]; - - // 获取完整品牌信息(包括所有规格) - const fullBrandInfo = boxBrandList?.find( - (brand) => brand.boxBrandId === item.boxBrandId, - ); - - // 合并已有的数据和完整品牌信息 - const mergedBrandInfo = fullBrandInfo - ? ({ - ...fullBrandInfo, - boxType: "EMPTY", // 保持boxType - boxSpecList: fullBrandInfo.boxSpecList?.map((boxSpec) => { - // 找到对应的已存在分类数据 - const existingSpec = brandToEdit?.boxSpecList?.find( - (spec) => spec.boxSpecId === boxSpec.boxSpecId, - ); - - return { - ...boxSpec, - boxProductList: boxSpec.boxProductList.map((product) => { - // 找到对应的产品数据 - const existingProduct = existingSpec?.boxProductList.find( - (prod) => prod.boxProductId === product.boxProductId, - ); - - return { - ...product, - boxCount: existingProduct?.boxCount || 0, - }; - }), - }; - }), - } as BoxBrand) - : brandToEdit; - - if (mergedBrandInfo) { - setEditingItem(mergedBrandInfo); - setShowEditModal(true); - } - }; - - // 更新编辑项中的数量 - const updateEditingItemCount = ( - specIndex: number, - detailIndex: number, - count: number, - ) => { - if (!editingItem) return; - - // 获取完整品牌信息 - const fullBrandInfo = boxBrandList?.find( - (brand) => brand.boxBrandId === editingItem.boxBrandId, - ); - - if (!fullBrandInfo) return; - - const updatedItem = { ...editingItem }; - - // 确保boxSpecList存在 - if (!updatedItem.boxSpecList) { - updatedItem.boxSpecList = fullBrandInfo.boxSpecList.map((boxSpec) => ({ - ...boxSpec, - boxProductList: boxSpec.boxProductList.map((product) => ({ - ...product, - boxCount: 0, - })), - })); - } - - // 确保spec存在 - if (!updatedItem.boxSpecList[specIndex]) { - updatedItem.boxSpecList[specIndex] = { - ...fullBrandInfo.boxSpecList[specIndex], - boxProductList: fullBrandInfo.boxSpecList[specIndex].boxProductList.map( - (product) => ({ - ...product, - boxCount: 0, - }), - ), - }; - } - - // 更新对应的产品数量 - const boxSpec = { ...updatedItem.boxSpecList[specIndex] }; - - // 确保boxProductList存在 - if (!boxSpec.boxProductList) { - boxSpec.boxProductList = fullBrandInfo.boxSpecList[ - specIndex - ].boxProductList.map((product) => ({ - ...product, - boxCount: 0, - })); - } - - const boxProductList = [...boxSpec.boxProductList]; - - // 确保产品存在 - if (!boxProductList[detailIndex]) { - boxProductList[detailIndex] = { - ...fullBrandInfo.boxSpecList[specIndex].boxProductList[detailIndex], - boxCount: 0, - }; - } - - boxProductList[detailIndex] = { - ...boxProductList[detailIndex], - boxCount: count, - }; - - boxSpec.boxProductList = boxProductList; - const updatedSpecList = [...updatedItem.boxSpecList]; - updatedSpecList[specIndex] = boxSpec; - updatedItem.boxSpecList = updatedSpecList; - - setEditingItem(updatedItem); - }; - - // 保存编辑的空箱信息 - const saveEditedItem = () => { - if (editingItem) { - // 检查是否尝试更改为已存在的品牌(排除自身) - const isBrandAlreadySelected = emptyBoxList.some( - (pkg) => - pkg.boxBrandId === editingItem.boxBrandId && - !(pkg.boxBrandId === editingItem.boxBrandId), - ); - - if (isBrandAlreadySelected) { - Toast.show("toast", { - icon: "fail", - title: "提示", - content: "该空箱品牌已存在,请选择其他品牌", - }); - return; - } - - // 使用convertBoxBrandToOrderPackages转换编辑后的数据 - const updatedOrderPackages = convertBoxBrandToOrderPackages( - editingItem, - "EMPTY", - ).filter((pkg) => pkg.boxCount > 0); - - // 更新emptyBoxList - const newList = [...emptyBoxList]; - // 找到对应品牌和类型的现有项目并替换 - const startIndex = newList.findIndex( - (pkg) => pkg.boxBrandId === editingItem.boxBrandId, - ); - - if (startIndex !== -1) { - // 移除旧的项目 - const filteredList = newList.filter( - (pkg) => !(pkg.boxBrandId === editingItem.boxBrandId), - ); - - // 添加更新后的项目 - setEmptyBoxList([...filteredList, ...updatedOrderPackages]); - } else { - // 如果没有找到,直接添加 - setEmptyBoxList((prev) => [...prev, ...updatedOrderPackages]); - } - } - setShowEditModal(false); - setEditingItem(null); - }; - - // 渲染单个空箱信息模块 - const renderEmptyBoxItem = (item: BoxBrand) => { - // 获取品牌信息用于展示品牌图片 - const brandInfo = boxBrandList?.find( - (brand) => brand.boxBrandId === item.boxBrandId, - ); - - return ( - - {/* 品牌背景水印 */} - {brandInfo?.boxBrandImage && ( - - - - )} - - {/* 品牌信息和操作按钮放在同一行 */} - - - {brandInfo?.boxBrandImage && ( - - - - )} - - - {item.boxBrandName || "未选择品牌"} - - - - - {/* 操作按钮与品牌信息放在同一行 */} - - handleEditItem(item)} - > - 编辑 - - { - console.log("removeEmptyBoxInfo", item.boxBrandId); - removeEmptyBoxInfo(item.boxBrandId); - }} - > - 移除 - - - - - {/* 详细信息展示,按分类显示 */} - - {item.boxSpecList && - item.boxSpecList.map((boxSpec, boxIndex) => ( - - - {boxSpec.boxSpecName} - - - {boxSpec.boxProductList - .map( - (detail) => - `${detail.boxProductName} 共 ${detail.boxCount} 个`, - ) - .join(",")} - - - ))} - - - ); - }; - - // 渲染批量添加空箱弹窗 - const renderBatchAddModal = () => { - // 检查是否至少有一个产品的数量大于0 - const hasAnyProductWithCount = selectedBrand - ? Array.from(productCounts.values()).some((count) => count > 0) - : false; - - return ( - { - setShowBatchModal(false); - setSelectedBrand(null); - setProductCounts(new Map()); - }} - title={"批量添加空箱"} - round - > - - - {/* 品牌选择 */} - - 选择品牌 - - - {boxBrandList - ?.filter((item) => item.boxBrandType !== "FARMER_BOX") - ?.map((boxBrand) => ( - handleBatchBrandSelect(boxBrand)} - > - - {boxBrand.boxBrandImage} - - - {boxBrand.boxBrandName} - - - ))} - - - - - {/* 未选择品牌时的提示 */} - {!selectedBrand && ( - - 请先选择一个品牌 - - )} - - {/* 产品展示 */} - {selectedBrand && ( - - - 空箱规格(点击 +/- 修改数量,0表示不使用) - - {selectedBrand.boxSpecList?.map((boxSpec) => ( - - - {boxSpec.boxSpecName} - - - {boxSpec.boxProductList.map((boxProduct) => { - const currentCount = - productCounts.get(boxProduct.id) || 0; - return ( - - - {boxProduct.boxProductName} - - - { - handleProductCountChange( - boxProduct.id, - Math.max(0, currentCount - 1), - ); - }} - > - - - - { - const num = Number(value); - if (!Number.isNaN(num) && num >= 0) { - handleProductCountChange( - boxProduct.id, - num, - ); - } - }} - /> - - { - handleProductCountChange( - boxProduct.id, - currentCount + 1, - ); - }} - > - - - - - - ); - })} - - - ))} - - )} - - - {/* 底部按钮 */} - - - - - - - - - - - - ); - }; - - // 渲染编辑空箱弹窗 - const renderEditModal = () => { - if (!editingItem) return null; - - // 获取品牌信息 - const brandInfo = boxBrandList?.find( - (brand) => brand.boxBrandId === editingItem.boxBrandId, - ); - - return ( - setShowEditModal(false)} - title={"编辑空箱信息"} - round - > - - - {/* 品牌信息 */} - - 品牌信息 - - {brandInfo?.boxBrandImage && ( - - - - )} - - {editingItem.boxBrandName} - - - - - {/* 详细信息 */} - - 空箱详情 - - {editingItem?.boxSpecList && - editingItem.boxSpecList.map((boxSpec, specId) => ( - - - {boxSpec.boxSpecName} - - - {boxSpec.boxProductList.map((detail, detailIndex) => { - const currentCount = detail?.boxCount || 0; - - return ( - - - {detail.boxProductName} - - - { - const newCount = Math.max( - 0, - currentCount - 1, - ); - updateEditingItemCount( - specId, - detailIndex, - newCount, - ); - }} - > - - - - { - const num = Number(value); - if (!Number.isNaN(num) && num >= 0) { - updateEditingItemCount( - specId, - detailIndex, - num, - ); - } - }} - /> - - { - updateEditingItemCount( - specId, - detailIndex, - currentCount + 1, - ); - }} - > - - - - 个 - - - - ); - })} - - - ))} - - - - - {/* 底部按钮 */} - - - - - - - - - - - - ); - }; - - // 获取空箱列表 - const emptyBoxes = convertOrderPackagesToBoxBrands(emptyBoxList); - - // 新增状态:跟踪每种纸箱类型的启用状态 - // 0: 未选, 1: 选择是, 2: 选择否 - const [packageTypeEnabled, setPackageTypeEnabled] = useState({ - EMPTY: 0, - }); - - // 处理纸箱类型启用状态切换 - const togglePackageType = ( - type: BusinessAPI.OrderPackage["boxType"], - value: number, // 0: 未选, 1: 选择是, 2: 选择否 - ) => { - setPackageTypeEnabled((prev) => ({ - ...prev, - [type]: value, - })); - }; + console.log("orderPackageList", orderPackageList); return ( - - - 带空箱了吗? - - { - togglePackageType("EMPTY", checked ? 1 : 0); - if (!checked) { - setEmptyBoxList([]); - } - }} - > - 带了 - + + + + + 带空箱了吗? + + + { + setHasEmptyBox(checked); + if (!checked) { + onChange([]); + } + }} + > + + 带了 + + + + + {/* 空箱信息展示 */} + {hasEmptyBox && ( + + )} - - {/* 空箱信息展示 */} - {packageTypeEnabled.EMPTY === 1 && ( - - {emptyBoxes.length > 0 ? ( - emptyBoxes.map((item) => renderEmptyBoxItem(item)) - ) : ( - - 还没有添加空箱 - - )} - - - - )} - - {/* 批量添加弹窗 */} - {renderBatchAddModal()} - {/* 编辑弹窗 */} - {renderEditModal()} ); } diff --git a/packages/app-client/src/components/purchase/module/MelonFarmer.tsx b/packages/app-client/src/components/purchase/module/MelonFarmer.tsx index 1100e3c..04b890f 100644 --- a/packages/app-client/src/components/purchase/module/MelonFarmer.tsx +++ b/packages/app-client/src/components/purchase/module/MelonFarmer.tsx @@ -595,7 +595,7 @@ export default forwardRef( {/* 只有最后一个瓜农才显示是否为最后一个瓜农的选项和添加按钮 */} {isLast && ( - + {supplierCount > 1 ? ( 这车货还需继续拼车吗? @@ -711,7 +711,7 @@ export default forwardRef( {/* 瓜农信息 */} - + @@ -910,7 +910,7 @@ export default forwardRef( {/* 若瓜农无法开发票,则可打款到微信 */} - + ( const { value, onChange } = props; const { orderSupplierList, orderCostList } = value; + console.log("orderCostList", orderCostList); const supplierVO = orderSupplierList[orderSupplierList.length - 1]; const costTemplate = supplierVO?.costTemplate; const costIds = supplierVO?.costIds; + console.log("costIds", costIds); // 解析costTemplate为JSON对象 const parsedCostTemplate = JSON.parse(costTemplate || "[]"); + console.log("parsedCostTemplate", parsedCostTemplate); // 初始化函数 const init = async (costIds: string[]) => { @@ -43,7 +47,7 @@ export default forwardRef( // 遍历costList,将costList中的项目添加到orderCostList中 parsedCostTemplate.productionTypeList?.forEach((item) => { - const existingItem = orderCostMap.get(item.costItemId); + const existingItem = orderCostMap.get(item.costId); if (existingItem) { newOrderCostList.push({ @@ -62,6 +66,44 @@ export default forwardRef( price: item.price || 0, unit: item.unit || "元", }); + + orderCostMap.set(item.costId, { + orderCostId: generateShortId(), + costItemIds: item.costItemIds, + costId: item.costId, + name: item.name, + type: item.type, + selected: false, + count: 1, + price: item.price || 0, + unit: item.unit || "元", + }); + } + }); + + const { data } = await business.cost.listCost({ + costListQry: { + status: true, + }, + }); + + data.data?.forEach((item) => { + if ( + item.costId && + costIds?.includes(item.costId) && + !newOrderCostList.some((cost) => cost.costId === item.costId) + ) { + newOrderCostList.push({ + orderCostId: generateShortId(), + costItemIds: item.costItemIds, + costId: item.costId, + name: item.name, + type: item.type, + selected: false, + count: 1, + price: item.price || 0, + unit: item.unit || "元", + }); } }); @@ -163,77 +205,82 @@ export default forwardRef( const orderCostId = currentItem?.orderCostId || generateShortId(); return ( - - - - - {item.name} - - { - toggleItemSelected(item.costId, checked); - }} - > - - 用了 - - + + + + {item.name} - - {/* 只对生产费用类型显示金额输入框 */} - {selected && ( - - - 多少钱: - - - { - updatePrice(item.costId, Number(value)); - }} - onBlur={() => validateCount(orderCostId, price)} - /> - - - - - - {countError[orderCostId] && selected && ( - - 请填写正确的金额 - - )} + { + toggleItemSelected(item.costId, checked); + }} + > + + 用了 - )} + + + {/* 只对生产费用类型显示金额输入框 */} + {selected && ( + + + 多少钱: + + + { + updatePrice(item.costId, Number(value)); + }} + onBlur={() => validateCount(orderCostId, price)} + /> + + + + + + {countError[orderCostId] && selected && ( + + 请填写正确的金额 + + )} + + )} ); }); }; return ( - + {/* 生产费用模块 */} - - 费用 - - - 用了直接填写金额 + + + 费用 + + + 用了直接填写金额 + + {renderItemList(parsedCostTemplate.productionTypeList)} - {renderItemList(parsedCostTemplate.productionTypeList)} ); diff --git a/packages/app-client/src/components/purchase/module/OrderCostItem.tsx b/packages/app-client/src/components/purchase/module/OrderCostItem.tsx index caeff5d..6d56d85 100644 --- a/packages/app-client/src/components/purchase/module/OrderCostItem.tsx +++ b/packages/app-client/src/components/purchase/module/OrderCostItem.tsx @@ -302,6 +302,19 @@ export default forwardRef( onChange?.({ ...value, orderPackageList, + orderCostItemList: orderCostItemList?.map((item1) => + item1.costItemId === item.costItemId + ? { + ...item1, + selected, + price: orderPackageList.reduce( + (sum, item) => + sum + (item.boxSalePrice || 0) * item.boxCount, + 0, + ), + } + : item1, + ), }); }} /> @@ -309,167 +322,168 @@ export default forwardRef( } return ( - - - - - {item.name} - - { - toggleItemSelected(item.costItemId, checked); - }} - > - - 用了 - - + + + + {item.name} + { + toggleItemSelected(item.costItemId, checked); + }} + > + + 用了 + + + - {selected && type === "ARTIFICIAL_TYPE" && ( + {selected && type === "ARTIFICIAL_TYPE" && ( + + {/* 费用承担方改为按钮形式,参考OrderPackage中的样式 */} + + 谁出钱: + + + + + + + {payerTypeError[item.costItemId] && selected && ( + + 请选择谁出这笔钱 + + )} + + )} + + {/* 根据rule值判断是否显示数量输入 */} + {selected && + (type === "ARTIFICIAL_TYPE" || type === "MATERIAL_TYPE") && + (item.rule === "INPUT_QUANTITY" || + item.rule === "INPUT_QUANTITY_AND_AMOUNT") && ( - {/* 费用承担方改为按钮形式,参考OrderPackage中的样式 */} - - 谁出钱: - - - + + + + + {item.unit} + - {payerTypeError[item.costItemId] && selected && ( + {countError[orderCostItemId] && selected && ( - 请选择谁出这笔钱 + 请填写正确的数量 )} )} - {/* 根据rule值判断是否显示数量输入 */} - {selected && - (type === "ARTIFICIAL_TYPE" || type === "MATERIAL_TYPE") && - (item.rule === "INPUT_QUANTITY" || - item.rule === "INPUT_QUANTITY_AND_AMOUNT") && ( - - - 用多少: - - { - const currentCount = count || 1; - const newCount = Math.max(1, currentCount - 1); - updateItemCount(item.costItemId, newCount); - - // 校验数量 - if (selected) { - validateCount(orderCostItemId, newCount); - } + {/* 根据rule值判断是否显示金额输入 */} + {selected && + (type === "ARTIFICIAL_TYPE" || type === "MATERIAL_TYPE") && + item.rule === "INPUT_QUANTITY_AND_AMOUNT" && ( + + + 多少钱: + + + { + updatePrice(item.costItemId, Number(value)); }} - > - - - - { - updateItemCount(item.costItemId, Number(value)); - }} - formatter={(value) => - Math.max(1, Number(value)).toString() - } - onBlur={() => validateCount(orderCostItemId, count)} - /> - - { - const currentCount = count || 1; - const newCount = currentCount + 1; - updateItemCount(item.costItemId, newCount); - - // 校验数量 - if (selected) { - validateCount(orderCostItemId, newCount); - } - }} - > - - - - - {item.unit} - + onBlur={() => validateCount(orderCostItemId, price)} + /> + - - {countError[orderCostItemId] && selected && ( - - 请填写正确的数量 - - )} - )} - {/* 根据rule值判断是否显示金额输入 */} - {selected && - (type === "ARTIFICIAL_TYPE" || type === "MATERIAL_TYPE") && - item.rule === "INPUT_QUANTITY_AND_AMOUNT" && ( - - - 多少钱: - - - { - updatePrice(item.costItemId, Number(value)); - }} - onBlur={() => validateCount(orderCostItemId, price)} - /> - - - 元 - - + {countError[orderCostItemId] && selected && ( + + 请填写正确的金额 - - {countError[orderCostItemId] && selected && ( - - 请填写正确的金额 - - )} - - )} - + )} + + )} ); }); @@ -488,62 +502,72 @@ export default forwardRef( }; return ( - - - 人工费用 - - - 对方出钱可以不勾选 - - {renderItemList( - getItemsByCostType("ARTIFICIAL_TYPE"), - "ARTIFICIAL_TYPE", - )} - - {/* 总的工头姓名输入框 */} - {shouldShowPrincipalInput() && ( - - 工头叫什么名字 - - { - handleForemanChange(value); - }} - onBlur={() => handlePrincipalBlur(foreman!)} - /> + + + + 人工费用 + + + + 对方出钱可以不勾选 - {foremanError && ( - - 工头叫啥子填一下 - - )} - )} - - - 辅料费用 - - - 用了几包就填几包 + + {/* 总的工头姓名输入框 */} + {shouldShowPrincipalInput() && ( + + 工头叫什么名字 + + { + handleForemanChange(value); + }} + onBlur={() => handlePrincipalBlur(foreman!)} + /> + + {foremanError && ( + + 工头叫啥子填一下 + + )} + + )} + + {renderItemList( + getItemsByCostType("ARTIFICIAL_TYPE"), + "ARTIFICIAL_TYPE", + )} + + + + + 辅料费用 + + + 用了几包就填几包 + + {/* 渲染辅料费用项(不含纸箱) */} + {renderItemList( + getItemsByCostType("MATERIAL_TYPE"), + "MATERIAL_TYPE", + )} - {/* 渲染辅料费用项(不含纸箱) */} - {renderItemList(getItemsByCostType("MATERIAL_TYPE"), "MATERIAL_TYPE")} ); diff --git a/packages/app-client/src/components/purchase/module/OrderOption.tsx b/packages/app-client/src/components/purchase/module/OrderOption.tsx index 91de218..0526fc9 100644 --- a/packages/app-client/src/components/purchase/module/OrderOption.tsx +++ b/packages/app-client/src/components/purchase/module/OrderOption.tsx @@ -168,8 +168,10 @@ export default forwardRef( orderId: value.orderId, active: Number(active + 1), foreman: value.foreman, - orderCostList: value.orderCostList, + // 空箱 orderPackageList: value.orderPackageList, + // 费用 + orderCostList: value.orderCostList.filter((item) => item.selected), orderCostItemList: value.orderCostItemList.filter( (item) => item.selected, ), diff --git a/packages/app-client/src/components/purchase/module/OrderPackage.tsx b/packages/app-client/src/components/purchase/module/OrderPackage.tsx index ba95eeb..8e676d2 100644 --- a/packages/app-client/src/components/purchase/module/OrderPackage.tsx +++ b/packages/app-client/src/components/purchase/module/OrderPackage.tsx @@ -45,21 +45,18 @@ export default forwardRef( if (supplierVO.isPaper && supplierVO.isLast) { setPackageTypeEnabled({ - USED: usageMap["USED"] || 0, EXTRA: 0, EXTRA_USED: usageMap["EXTRA_USED"] || 0, REMAIN: usageMap["REMAIN"] || 0, }); } else if (supplierVO.isPaper && !supplierVO.isLast) { setPackageTypeEnabled({ - USED: usageMap["USED"] || 0, EXTRA: usageMap["EXTRA"] || 0, EXTRA_USED: 0, REMAIN: 0, }); } else if (!supplierVO.isPaper) { setPackageTypeEnabled({ - USED: usageMap["USED"] || 0, EXTRA: 0, EXTRA_USED: 0, REMAIN: 0, @@ -100,31 +97,31 @@ export default forwardRef( // 确定当前供应商需要检查哪些纸箱类型 if (supplierVO.isPaper && supplierVO.isLast) { // 空磅包含纸箱 + 最后一个瓜农 - requiredTypes = ["USED", "EXTRA_USED", "REMAIN"]; + requiredTypes = ["EXTRA_USED", "REMAIN"]; } else if (supplierVO.isPaper && !supplierVO.isLast) { - requiredTypes = ["USED", "EXTRA"]; - } else if (!supplierVO.isPaper) { - // 空磅不包含纸箱 - requiredTypes = ["USED"]; + requiredTypes = ["EXTRA"]; } console.log("requiredTypes", requiredTypes); + if (requiredTypes.length > 0) { + // 检查所需选项是否都已做出选择(不是1就是2,不能是0) + const allRequiredAnswered = requiredTypes.every( + (type) => + packageTypeEnabled[type] === 1 || packageTypeEnabled[type] === 2, + ); - // 检查所需选项是否都已做出选择(不是1就是2,不能是0) - const allRequiredAnswered = requiredTypes.every( - (type) => - packageTypeEnabled[type] === 1 || packageTypeEnabled[type] === 2, - ); - - if (!allRequiredAnswered || requiredTypes.length === 0) { - Toast.show("toast", { - icon: "fail", - title: "提示", - content: "请回答相关的纸箱使用情况问题", - }); - return false; + if (!allRequiredAnswered || requiredTypes.length === 0) { + Toast.show("toast", { + icon: "fail", + title: "提示", + content: "请回答相关的纸箱使用情况问题", + }); + return false; + } } + requiredTypes.push("USED"); + // 检查所有启用的纸箱类型是否都填写了信息 const enabledTypes = Object.entries(packageTypeEnabled) .filter( @@ -141,9 +138,7 @@ export default forwardRef( if (!hasPackagesOfType) { const typeLabels = { USED: "记录装车用的纸箱", - EXTRA_USED: supplierVO.isPaper - ? "记录用的额外运输纸箱" - : "记录装车用的纸箱", + EXTRA_USED: "记录用的额外运输纸箱", EXTRA: "记录额外运输来的所有纸箱", REMAIN: "记录车上没用完的纸箱", }; @@ -250,7 +245,6 @@ export default forwardRef( // 新增状态:跟踪每种纸箱类型的启用状态 // 0: 未选, 1: 选择是, 2: 选择否 const [packageTypeEnabled, setPackageTypeEnabled] = useState({ - USED: 0, EXTRA_USED: 0, EXTRA: 0, REMAIN: 0, @@ -269,7 +263,6 @@ export default forwardRef( packageUsage: [ ...(Object.entries( packageTypeEnabled || { - USED: 0, EXTRA_USED: 0, EXTRA: 0, REMAIN: 0, @@ -297,192 +290,12 @@ export default forwardRef( return ( {/* 替换原来的Tab导航为问答式选择 */} - - - {supplierVO.name}装车的纸箱使用情况 - - - - - - {/* 根据供应商属性显示不同的问题 */} - {supplierVO.isPaper && supplierVO.isLast && ( - <> - - {/* 空车带来的纸箱用完了吗? */} - - 空车带来的纸箱用完了吗? - - - - - - - {packageTypeEnabled.REMAIN === 1 && ( - - )} + + + + {supplierVO.name}装车的纸箱使用情况 - - {/* 用额外运输纸箱的了吗? */} - - 用额外运输纸箱的了吗? - - - - - - - {packageTypeEnabled.EXTRA_USED === 1 && ( - - )} - - - )} - - {supplierVO.isPaper && !supplierVO.isLast && ( - /* 非最后一个瓜农 */ - - {/* 有额外运输纸箱过来吗? */} - - 有额外运输纸箱过来吗? - - - - - - - {packageTypeEnabled.EXTRA === 1 && ( - - )} - - )} - - {!supplierVO.isPaper && ( - /* 空磅不包含纸箱 */ - ( boxBrandList={boxBrandList} /> + + + {/* 根据供应商属性显示不同的问题 */} + {supplierVO.isPaper && supplierVO.isLast && ( + <> + + + {/* 空车带来的纸箱用完了吗? */} + + 空车带来的纸箱用完了吗? + + + + + + + {packageTypeEnabled.REMAIN === 1 && ( + + )} + + + + + + {/* 用额外运输纸箱的了吗? */} + + 用额外运输纸箱的了吗? + + + + + + + {packageTypeEnabled.EXTRA_USED === 1 && ( + + )} + + + + )} + + {supplierVO.isPaper && !supplierVO.isLast && ( + /* 非最后一个瓜农 */ + + + {/* 有额外运输纸箱过来吗? */} + + 有额外运输纸箱过来吗? + + + + + + + {packageTypeEnabled.EXTRA === 1 && ( + + )} + + )} ); diff --git a/packages/app-client/src/components/purchase/module/OrderVehicle.tsx b/packages/app-client/src/components/purchase/module/OrderVehicle.tsx index 13246c1..3e4b43d 100644 --- a/packages/app-client/src/components/purchase/module/OrderVehicle.tsx +++ b/packages/app-client/src/components/purchase/module/OrderVehicle.tsx @@ -535,45 +535,62 @@ export default forwardRef( return ( - - - - 智能识别 + + + + + 智能识别 + + +