import { ScrollView, View } from "@tarojs/components"; import { Icon } from "@/components"; import { Button, Dialog, Image, Input, Popup, SafeArea, Toast, } from "@nutui/nutui-react-taro"; import classNames from "classnames"; import { forwardRef, useEffect, useImperativeHandle, useState } from "react"; import { business } from "@/services"; import { BoxBrand, BoxProduct, BoxSpec, SupplierVO } from "@/types/typings"; import { generateShortId } from "@/utils/generateShortId"; import { convertBoxBrandToOrderPackages, convertOrderPackagesToBoxBrands, } from "@/utils/orderPackage"; // 定义ref暴露的方法接口 export interface OrderPackageRef { validate: () => boolean; } interface IOrderPackageProps { value: SupplierVO; onChange: (supplierVO: SupplierVO) => void; } export default forwardRef( function OrderPackage(props, ref) { const { value, onChange } = props; const [supplierVO, setSupplierVO] = useState(value); // 初始化数据 useEffect(() => { setSupplierVO(value); const orderPackageList = value.orderPackageList || []; setOrderPackageList(orderPackageList); if (orderPackageList.length > 0) { // 根据当前供应商确定需要检查的纸箱类型 let requiredTypes: string[] = []; // 确定当前供应商需要检查哪些纸箱类型 if (value.isPaper && value.isLast) { requiredTypes = ["OWN", "USED", "EXTRA_USED", "REMAIN"]; } else if (value.isPaper && !value.isLast) { requiredTypes = ["USED", "OWN", "EXTRA"]; } else if (!value.isPaper) { requiredTypes = ["OWN", "EXTRA_USED"]; } requiredTypes.map((type) => { setPackageTypeEnabled((prev) => { return { ...prev, [type]: orderPackageList.some((item) => item.boxType === type) ? 1 : 2, }; }); }); } }, []); const [orderPackageList, setOrderPackageList] = useState< BusinessAPI.OrderPackage[] >([]); // 将校验方法暴露给父组件 useImperativeHandle(ref, () => ({ validate, })); // 校验函数 const validate = () => { // 根据当前供应商确定需要检查的纸箱类型 let requiredTypes: string[] = []; // 确定当前供应商需要检查哪些纸箱类型 if (supplierVO.isPaper && supplierVO.isLast) { // 空磅包含纸箱 + 最后一个瓜农 if (packageTypeEnabled.OWN === 1) { requiredTypes = ["OWN", "USED"]; if (packageTypeEnabled.REMAIN === 1) { requiredTypes.push("REMAIN"); } } else if (packageTypeEnabled.OWN === 2) { requiredTypes = ["USED", "OWN", "EXTRA_USED"]; if (packageTypeEnabled.REMAIN === 1) { requiredTypes.push("REMAIN"); } } } else if (supplierVO.isPaper && !supplierVO.isLast) { // 空磅包含纸箱 + 非最后一个瓜农 if (packageTypeEnabled.OWN === 1) { requiredTypes = ["OWN", "USED"]; } else if (packageTypeEnabled.OWN === 2) { requiredTypes = ["USED", "OWN", "EXTRA"]; } } else if (!supplierVO.isPaper) { // 空磅不包含纸箱 if (packageTypeEnabled.OWN === 1) { requiredTypes = ["OWN"]; } else if (packageTypeEnabled.OWN === 2) { requiredTypes = ["EXTRA_USED"]; } } // 检查所需选项是否都已做出选择(不是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; } // 检查所有启用的纸箱类型是否都填写了信息 const enabledTypes = Object.entries(packageTypeEnabled) .filter( ([type, enabled]) => requiredTypes.includes(type) && enabled === 1, ) .map(([type, _]) => type); // 检查每个启用的类型是否有对应的纸箱数据 for (const type of enabledTypes) { const hasPackagesOfType = orderPackageList.some( (item) => item.boxType === type, ); if (!hasPackagesOfType) { const typeLabels = { USED: "记录装车用的纸箱", EXTRA_USED: "记录额外运输来的所有纸箱", EXTRA: "记录额外运输来的所有纸箱", REMAIN: "记录车上没用完的纸箱", OWN: "记录装车用的瓜农的纸箱", }; Toast.show("toast", { icon: "fail", title: "提示", content: `已选择使用${typeLabels[type]},请添加对应的纸箱信息`, }); return false; } } return true; }; // 纸箱品牌数据 const [boxBrandList, setBoxBrandList] = useState(); const initBoxBrandList = async () => { const { data } = await business.boxBrand.listBoxBrand({ boxBrandListQry: { status: true, withProduct: true, }, }); const boxBrandList = data.data ?.filter( (boxBrand) => boxBrand.status && boxBrand.boxProductVOList && boxBrand.boxProductVOList.length > 0, ) .map((boxBrand) => { // 将产品按规格分类 const boxSpecList: BoxSpec[] = boxBrand.boxSpecVOList?.map((item) => { return { id: generateShortId(), boxSpecId: item.specId, boxSpecName: item.name, boxProductList: [], }; }) || []; const boxProductList = boxBrand.boxProductVOList?.map( (boxProductVO) => { const boxProduct: BoxProduct = { id: generateShortId(), boxProductId: boxProductVO.productId, boxProductName: boxProductVO.name, boxProductWeight: boxProductVO.weight, boxSpecId: boxProductVO.specId, boxSpecName: boxProductVO.specName, boxCostPrice: boxProductVO.costPrice, boxSalePrice: boxProductVO.salePrice, boxBrandId: boxBrand.brandId, boxBrandName: boxBrand.name, boxCount: 0, }; return boxProduct; }, ); return { id: generateShortId(), boxBrandId: boxBrand.brandId, boxBrandName: boxBrand.name, boxBrandImage: boxBrand.image, boxBrandType: boxBrand.type, boxSpecList: boxSpecList .map((boxSpec) => { return { id: generateShortId(), boxSpecId: boxSpec.boxSpecId, boxSpecName: boxSpec.boxSpecName, boxProductList: boxProductList?.filter( (boxProduct) => boxProduct.boxSpecId === boxSpec.boxSpecId, ) || [], }; }) .filter( (boxSpec) => boxSpec.boxProductList && boxSpec.boxProductList.length > 0, ) || [], }; }) || []; setBoxBrandList(boxBrandList as any); }; useEffect(() => { initBoxBrandList().then(); }, []); // 添加状态来跟踪当前选择的纸箱类型 const [boxType, setBoxType] = useState("USED"); // 新增状态:跟踪每种纸箱类型的启用状态 // 0: 未选, 1: 选择是, 2: 选择否 const [packageTypeEnabled, setPackageTypeEnabled] = useState({ USED: 0, EXTRA_USED: 0, EXTRA: 0, REMAIN: 0, OWN: 0, }); // 监听供应商信息变化 useEffect(() => { if (orderPackageList) { onChange({ ...supplierVO, orderPackageList, }); } }, [orderPackageList]); // 批量添加纸箱相关状态 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 [editingItemIndex, setEditingItemIndex] = useState( null, ); // 处理批量添加时的品牌选择 const handleBatchBrandSelect = (brand: BoxBrand) => { // 检查当前boxType下是否已存在该品牌 const isBrandAlreadySelected = orderPackageList.some( (pkg) => pkg.boxType === boxType && 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 addBatchPackageInfo = () => { if (!selectedBrand) { return; } // 使用convertBoxBrandToOrderPackages转换数据 const newOrderPackages = convertBoxBrandToOrderPackages( selectedBrand, boxType, ); // 过滤掉数量为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, }; }); // 添加到orderPackageList中 setOrderPackageList((prev) => [...prev, ...updatedOrderPackages]); // 重置选择并关闭弹窗 setSelectedBrand(null); setProductCounts(new Map()); setShowBatchModal(false); }; // 删除包装信息 const removePackageInfo = (boxBrandId: string) => { Dialog.open("dialog", { title: "提示", content: "确定要移除此纸箱品牌吗?", confirmText: "确定", cancelText: "取消", onConfirm: () => { const newList = [ ...orderPackageList.filter( (item) => item.boxBrandId !== boxBrandId, ), ]; setOrderPackageList(newList); Dialog.close("dialog"); }, onCancel: () => { Dialog.close("dialog"); }, }); }; // 处理纸箱类型启用状态切换 const togglePackageType = ( type: BusinessAPI.OrderPackage["boxType"], value: number, // 0: 未选, 1: 选择是, 2: 选择否 ) => { setPackageTypeEnabled((prev) => ({ ...prev, [type]: value, })); }; // 处理编辑按钮点击 const handleEditItem = (item: BoxBrand, index: number) => { console.log( "handleEditItem", item, index, orderPackageList, orderPackageList.filter( (pkg) => pkg.boxBrandId === item.boxBrandId && pkg.boxType === item.boxType, ), ); // 从packages中找到完整的品牌信息用于编辑 const brandToEdit = convertOrderPackagesToBoxBrands( orderPackageList.filter( (pkg) => pkg.boxBrandId === item.boxBrandId && pkg.boxType === item.boxType, ), )[0]; // 获取完整品牌信息(包括所有规格) const fullBrandInfo = boxBrandList?.find( (brand) => brand.boxBrandId === item.boxBrandId, ); // 合并已有的数据和完整品牌信息 const mergedBrandInfo = fullBrandInfo ? { ...fullBrandInfo, boxType: item.boxType, // 保持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, }; }), }; }), } : brandToEdit; if (mergedBrandInfo) { setEditingItem(mergedBrandInfo); setEditingItemIndex(index); 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 && editingItemIndex !== null) { // 检查是否尝试更改为已存在的品牌(排除自身) const isBrandAlreadySelected = orderPackageList.some( (pkg) => pkg.boxType === editingItem.boxType && pkg.boxBrandId === editingItem.boxBrandId && !( pkg.boxBrandId === editingItem.boxBrandId && pkg.boxType === editingItem.boxType ), ); if (isBrandAlreadySelected) { Toast.show("toast", { icon: "fail", title: "提示", content: "该纸箱品牌在此类型下已存在,请选择其他品牌", }); return; } // 使用convertBoxBrandToOrderPackages转换编辑后的数据 const updatedOrderPackages = convertBoxBrandToOrderPackages( editingItem, editingItem.boxType, ).filter((pkg) => pkg.boxCount > 0); // 更新orderPackageList const newList = [...orderPackageList]; // 找到对应品牌和类型的现有项目并替换 const startIndex = newList.findIndex( (pkg) => pkg.boxBrandId === editingItem.boxBrandId && pkg.boxType === editingItem.boxType, ); if (startIndex !== -1) { // 移除旧的项目 const filteredList = newList.filter( (pkg) => !( pkg.boxBrandId === editingItem.boxBrandId && pkg.boxType === editingItem.boxType ), ); // 添加更新后的项目 setOrderPackageList([...filteredList, ...updatedOrderPackages]); } else { // 如果没有找到,直接添加 setOrderPackageList((prev) => [...prev, ...updatedOrderPackages]); } } setShowEditModal(false); setEditingItem(null); setEditingItemIndex(null); }; // 渲染单个包装信息模块 const renderOrderPackageItem = (item: BoxBrand, index: number) => { // 获取品牌信息用于展示品牌图片 const brandInfo = boxBrandList?.find( (brand) => brand.boxBrandId === item.boxBrandId, ); return ( {/* 品牌背景水印 */} {brandInfo?.boxBrandImage && ( )} {/* 品牌信息和操作按钮放在同一行 */} {brandInfo?.boxBrandImage && ( )} {item.boxBrandName || "未选择品牌"} {/* 操作按钮与品牌信息放在同一行 */} handleEditItem(item, index)} > 编辑 removePackageInfo(item.boxBrandId)} > 移除 {/* 详细信息展示,按分类显示 */} {item.boxSpecList && item.boxSpecList.map((boxSpec, boxIndex) => ( {boxSpec.boxSpecName} {boxSpec.boxProductList .map( (detail) => `${detail.boxProductName} 共 ${detail.boxCount} 个`, ) .join(",")} ))} ); }; // 根据启用的纸箱类型渲染对应的内容 const renderPackageByType = (type: keyof typeof packageTypeEnabled) => { // 获取该类型下所有的纸箱 const packagesOfType = convertOrderPackagesToBoxBrands( orderPackageList.filter((pkg) => pkg.boxType === type), ); // 根据类型设置显示标题 const typeLabels = { USED: "装车用的纸箱", EXTRA_USED: "用的额外运输纸箱", EXTRA: "额外运输来的所有纸箱", REMAIN: "车上没用完的纸箱", OWN: "装车用的瓜农的纸箱", }; return ( 记录{typeLabels[type]} {packagesOfType.length > 0 ? ( packagesOfType.map((item, index) => renderOrderPackageItem(item, index), ) ) : ( 还没有添加纸箱 )} ); }; // 渲染批量添加纸箱弹窗 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) => { if (boxType === "OWN") { return item.boxBrandType === "FARMER_BOX"; } else { return ( item.boxBrandType === "THIRD_PARTY_BOX" || item.boxBrandType === "OUR_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, ); }} > ); })} ))} {/* 底部按钮 */} ); }; return ( {/* 替换原来的Tab导航为问答式选择 */} {supplierVO.name}的纸箱使用情况 {/* 是否使用瓜农自己的纸箱 */} 瓜农包纸箱吗? {/* 根据供应商属性显示不同的问题 */} {supplierVO.isPaper && supplierVO.isLast && ( /* 当前为最后一个瓜农 */ <> {packageTypeEnabled.OWN === 1 && ( /* 当选择了使用自己的纸箱时 */ <> {renderPackageByType("OWN")} {/* 分隔线 */} {/* 空车带来的纸箱用完了吗? */} 空车带来的纸箱用完了吗? {packageTypeEnabled.REMAIN === 1 && renderPackageByType("REMAIN")} )} {packageTypeEnabled.OWN === 2 && ( /* 当没有选择使用自己的纸箱时 */ <> {renderPackageByType("USED")} {/* 分隔线 */} {/* 空车带来的纸箱用完了吗? */} 空车带来的纸箱用完了吗? {packageTypeEnabled.REMAIN === 1 && renderPackageByType("REMAIN")} {/* 分隔线 */} {/* 用额外运输纸箱的了吗? */} 用额外运输纸箱的了吗? {packageTypeEnabled.EXTRA_USED === 1 && renderPackageByType("EXTRA_USED")} )} )} {supplierVO.isPaper && !supplierVO.isLast && ( /* 非最后一个瓜农 */ <> {packageTypeEnabled.OWN === 1 && ( /* 当选择了使用自己的纸箱时 */ <> {renderPackageByType("OWN")} {/* 分隔线 */} )} {packageTypeEnabled.OWN === 2 && ( /* 当没有选择使用自己的纸箱时 */ <> {renderPackageByType("USED")} {/* 分隔线 */} {/* 有额外运输纸箱过来吗? */} 有额外运输纸箱过来吗? {packageTypeEnabled.EXTRA === 1 && renderPackageByType("EXTRA")} )} )} {!supplierVO.isPaper && ( /* 空磅不包含纸箱 */ <> {packageTypeEnabled.OWN === 1 && ( /* 当选择了使用自己的纸箱时 */ <> {renderPackageByType("OWN")} {/* 分隔线 */} )} {packageTypeEnabled.OWN === 2 && ( /* 当没有选择使用自己的纸箱时 */ <> {renderPackageByType("EXTRA_USED")} {/* 分隔线 */} )} )} {/* 批量添加弹窗 */} {renderBatchAddModal()} {/* 编辑弹窗 */} {renderEditModal()} ); }, );