refactor(purchase): 重构纸箱规格相关逻辑
- 将 BoxCategory 相关类型和逻辑替换为 BoxSpec - 更新 OrderPackage 组件中的分类展示和数量统计逻辑 - 修改采购预览页面的规格字段展示方式 - 调整配送单据中的纸箱规格数据结构 - 新增 BoxSpec 相关服务接口和类型定义 - 移除旧的 calculateSupplierWeights 工具函数 - 更新组件内部变量命名以匹配新规范 - 修正空箱信息区域组件的属性传递问题
This commit is contained in:
parent
323fe4c83d
commit
5eb4e0f4bb
@ -12,7 +12,7 @@ import {
|
||||
import classNames from "classnames";
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
|
||||
import { business } from "@/services";
|
||||
import { BoxBrand, BoxCategory, BoxProduct, SupplierVO } from "@/types/typings";
|
||||
import { BoxBrand, BoxProduct, BoxSpec, SupplierVO } from "@/types/typings";
|
||||
import { generateShortId } from "@/utils/generateShortId";
|
||||
import {
|
||||
convertBoxBrandToOrderPackages,
|
||||
@ -183,20 +183,15 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
)
|
||||
.map((boxBrand) => {
|
||||
// 将产品按规格分类
|
||||
const boxCategoryList: BoxCategory[] = [
|
||||
{
|
||||
const boxSpecList: BoxSpec[] =
|
||||
boxBrand.boxSpecVOList?.map((item) => {
|
||||
return {
|
||||
id: generateShortId(),
|
||||
boxCategoryId: "FOUR_GRAIN",
|
||||
boxCategoryName: "4粒装",
|
||||
boxSpecId: item.specId,
|
||||
boxSpecName: item.name,
|
||||
boxProductList: [],
|
||||
},
|
||||
{
|
||||
id: generateShortId(),
|
||||
boxCategoryId: "TWO_GRAIN",
|
||||
boxCategoryName: "2粒装",
|
||||
boxProductList: [],
|
||||
},
|
||||
];
|
||||
};
|
||||
}) || [];
|
||||
const boxProductList = boxBrand.boxProductVOList?.map(
|
||||
(boxProductVO) => {
|
||||
const boxProduct: BoxProduct = {
|
||||
@ -204,7 +199,8 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
boxProductId: boxProductVO.productId,
|
||||
boxProductName: boxProductVO.name,
|
||||
boxProductWeight: boxProductVO.weight,
|
||||
boxCategoryId: boxProductVO.specType,
|
||||
boxSpecId: boxProductVO.specId,
|
||||
boxSpecName: boxProductVO.specName,
|
||||
boxCostPrice: boxProductVO.costPrice,
|
||||
boxSalePrice: boxProductVO.salePrice,
|
||||
boxBrandId: boxBrand.brandId,
|
||||
@ -222,25 +218,24 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
boxBrandName: boxBrand.name,
|
||||
boxBrandImage: boxBrand.image,
|
||||
boxBrandType: boxBrand.type,
|
||||
boxCategoryList:
|
||||
boxCategoryList
|
||||
.map((boxCategory) => {
|
||||
boxSpecList:
|
||||
boxSpecList
|
||||
.map((boxSpec) => {
|
||||
return {
|
||||
id: generateShortId(),
|
||||
boxCategoryId: boxCategory.boxCategoryId,
|
||||
boxCategoryName: boxCategory.boxCategoryName,
|
||||
boxSpecId: boxSpec.boxSpecId,
|
||||
boxSpecName: boxSpec.boxSpecName,
|
||||
boxProductList:
|
||||
boxProductList?.filter(
|
||||
(boxProduct) =>
|
||||
boxProduct.boxCategoryId ===
|
||||
boxCategory.boxCategoryId,
|
||||
boxProduct.boxSpecId === boxSpec.boxSpecId,
|
||||
) || [],
|
||||
};
|
||||
})
|
||||
.filter(
|
||||
(boxCategory) =>
|
||||
boxCategory.boxProductList &&
|
||||
boxCategory.boxProductList.length > 0,
|
||||
(boxSpec) =>
|
||||
boxSpec.boxProductList &&
|
||||
boxSpec.boxProductList.length > 0,
|
||||
) || [],
|
||||
};
|
||||
}) || [];
|
||||
@ -311,8 +306,8 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
setSelectedBrand(brand);
|
||||
// 初始化所有产品的数量为0
|
||||
const initialCounts = new Map<string, number>();
|
||||
brand.boxCategoryList?.forEach((category) => {
|
||||
category.boxProductList.forEach((product) => {
|
||||
brand.boxSpecList?.forEach((boxSpec) => {
|
||||
boxSpec.boxProductList.forEach((product) => {
|
||||
initialCounts.set(product.id, 0);
|
||||
});
|
||||
});
|
||||
@ -331,17 +326,15 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
if (selectedBrand) {
|
||||
const updatedBrand = { ...selectedBrand };
|
||||
|
||||
updatedBrand.boxCategoryList = updatedBrand.boxCategoryList?.map(
|
||||
(category) => {
|
||||
const updatedProducts = category.boxProductList.map((product) => {
|
||||
updatedBrand.boxSpecList = updatedBrand.boxSpecList?.map((boxSpec) => {
|
||||
const updatedProducts = boxSpec.boxProductList.map((product) => {
|
||||
if (product.id === productId) {
|
||||
return { ...product, boxCount: count };
|
||||
}
|
||||
return product;
|
||||
});
|
||||
return { ...category, boxProductList: updatedProducts };
|
||||
},
|
||||
);
|
||||
return { ...boxSpec, boxProductList: updatedProducts };
|
||||
});
|
||||
setSelectedBrand(updatedBrand);
|
||||
}
|
||||
};
|
||||
@ -361,7 +354,7 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
// 过滤掉数量为0的项目
|
||||
const filteredOrderPackages = newOrderPackages.filter((pkg) => {
|
||||
// 从productCounts中获取对应产品的数量
|
||||
const product = selectedBrand.boxCategoryList
|
||||
const product = selectedBrand.boxSpecList
|
||||
?.flatMap((c) => c.boxProductList)
|
||||
.find((p) => p.id === pkg.orderPackageId);
|
||||
const count = product ? productCounts.get(product.id) || 0 : 0;
|
||||
@ -371,7 +364,7 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
// 更新数量信息
|
||||
const updatedOrderPackages = filteredOrderPackages.map((pkg) => {
|
||||
// 从productCounts中获取对应产品的数量
|
||||
const product = selectedBrand.boxCategoryList
|
||||
const product = selectedBrand.boxSpecList
|
||||
?.flatMap((c) => c.boxProductList)
|
||||
.find((p) => p.id === pkg.orderPackageId);
|
||||
const count = product ? productCounts.get(product.id) || 0 : 0;
|
||||
@ -453,17 +446,17 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
? {
|
||||
...fullBrandInfo,
|
||||
boxType: item.boxType, // 保持boxType
|
||||
boxCategoryList: fullBrandInfo.boxCategoryList?.map((category) => {
|
||||
boxSpecList: fullBrandInfo.boxSpecList?.map((boxSpec) => {
|
||||
// 找到对应的已存在分类数据
|
||||
const existingCategory = brandToEdit?.boxCategoryList?.find(
|
||||
(cat) => cat.boxCategoryId === category.boxCategoryId,
|
||||
const existingSpec = brandToEdit?.boxSpecList?.find(
|
||||
(spec) => spec.boxSpecId === boxSpec.boxSpecId,
|
||||
);
|
||||
|
||||
return {
|
||||
...category,
|
||||
boxProductList: category.boxProductList.map((product) => {
|
||||
...boxSpec,
|
||||
boxProductList: boxSpec.boxProductList.map((product) => {
|
||||
// 找到对应的产品数据
|
||||
const existingProduct = existingCategory?.boxProductList.find(
|
||||
const existingProduct = existingSpec?.boxProductList.find(
|
||||
(prod) => prod.boxProductId === product.boxProductId,
|
||||
);
|
||||
|
||||
@ -486,7 +479,7 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
|
||||
// 更新编辑项中的数量
|
||||
const updateEditingItemCount = (
|
||||
categoryIndex: number,
|
||||
specIndex: number,
|
||||
detailIndex: number,
|
||||
count: number,
|
||||
) => {
|
||||
@ -501,25 +494,23 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
|
||||
const updatedItem = { ...editingItem };
|
||||
|
||||
// 确保boxCategoryList存在
|
||||
if (!updatedItem.boxCategoryList) {
|
||||
updatedItem.boxCategoryList = fullBrandInfo.boxCategoryList.map(
|
||||
(category) => ({
|
||||
...category,
|
||||
boxProductList: category.boxProductList.map((product) => ({
|
||||
// 确保boxSpecList存在
|
||||
if (!updatedItem.boxSpecList) {
|
||||
updatedItem.boxSpecList = fullBrandInfo.boxSpecList.map((boxSpec) => ({
|
||||
...boxSpec,
|
||||
boxProductList: boxSpec.boxProductList.map((product) => ({
|
||||
...product,
|
||||
boxCount: 0,
|
||||
})),
|
||||
}),
|
||||
);
|
||||
}));
|
||||
}
|
||||
|
||||
// 确保category存在
|
||||
if (!updatedItem.boxCategoryList[categoryIndex]) {
|
||||
updatedItem.boxCategoryList[categoryIndex] = {
|
||||
...fullBrandInfo.boxCategoryList[categoryIndex],
|
||||
boxProductList: fullBrandInfo.boxCategoryList[
|
||||
categoryIndex
|
||||
// 确保spec存在
|
||||
if (!updatedItem.boxSpecList[specIndex]) {
|
||||
updatedItem.boxSpecList[specIndex] = {
|
||||
...fullBrandInfo.boxSpecList[specIndex],
|
||||
boxProductList: fullBrandInfo.boxSpecList[
|
||||
specIndex
|
||||
].boxProductList.map((product) => ({
|
||||
...product,
|
||||
boxCount: 0,
|
||||
@ -528,26 +519,24 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
}
|
||||
|
||||
// 更新对应的产品数量
|
||||
const category = { ...updatedItem.boxCategoryList[categoryIndex] };
|
||||
const boxSpec = { ...updatedItem.boxSpecList[specIndex] };
|
||||
|
||||
// 确保boxProductList存在
|
||||
if (!category.boxProductList) {
|
||||
category.boxProductList = fullBrandInfo.boxCategoryList[
|
||||
categoryIndex
|
||||
if (!boxSpec.boxProductList) {
|
||||
boxSpec.boxProductList = fullBrandInfo.boxSpecList[
|
||||
specIndex
|
||||
].boxProductList.map((product) => ({
|
||||
...product,
|
||||
boxCount: 0,
|
||||
}));
|
||||
}
|
||||
|
||||
const boxProductList = [...category.boxProductList];
|
||||
const boxProductList = [...boxSpec.boxProductList];
|
||||
|
||||
// 确保产品存在
|
||||
if (!boxProductList[detailIndex]) {
|
||||
boxProductList[detailIndex] = {
|
||||
...fullBrandInfo.boxCategoryList[categoryIndex].boxProductList[
|
||||
detailIndex
|
||||
],
|
||||
...fullBrandInfo.boxSpecList[specIndex].boxProductList[detailIndex],
|
||||
boxCount: 0,
|
||||
};
|
||||
}
|
||||
@ -557,10 +546,10 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
boxCount: count,
|
||||
};
|
||||
|
||||
category.boxProductList = boxProductList;
|
||||
const updatedCategories = [...updatedItem.boxCategoryList];
|
||||
updatedCategories[categoryIndex] = category;
|
||||
updatedItem.boxCategoryList = updatedCategories;
|
||||
boxSpec.boxProductList = boxProductList;
|
||||
const updatedSpecList = [...updatedItem.boxSpecList];
|
||||
updatedSpecList[specIndex] = boxSpec;
|
||||
updatedItem.boxSpecList = updatedSpecList;
|
||||
|
||||
setEditingItem(updatedItem);
|
||||
};
|
||||
@ -686,17 +675,17 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
|
||||
{/* 详细信息展示,按分类显示 */}
|
||||
<View className="space-y-2">
|
||||
{item.boxCategoryList &&
|
||||
item.boxCategoryList.map((categoryData, categoryIndex) => (
|
||||
{item.boxSpecList &&
|
||||
item.boxSpecList.map((boxSpec, boxIndex) => (
|
||||
<View
|
||||
key={categoryIndex}
|
||||
key={boxIndex}
|
||||
className="rounded-lg bg-gray-50 p-3 text-sm text-gray-600"
|
||||
>
|
||||
<View className="mb-1 font-medium text-gray-700">
|
||||
{categoryData.boxCategoryName}
|
||||
{boxSpec.boxSpecName}
|
||||
</View>
|
||||
<View>
|
||||
{categoryData.boxProductList
|
||||
{boxSpec.boxProductList
|
||||
.map(
|
||||
(detail) =>
|
||||
`${detail.boxProductName} 共 ${detail.boxCount} 个`,
|
||||
@ -854,13 +843,13 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
<View className="mb-2 text-sm text-gray-600">
|
||||
纸箱规格(点击 +/- 修改数量,0表示不使用)
|
||||
</View>
|
||||
{selectedBrand.boxCategoryList?.map((category) => (
|
||||
<View key={category.id} className="mb-4">
|
||||
{selectedBrand.boxSpecList?.map((boxSpec) => (
|
||||
<View key={boxSpec.id} className="mb-4">
|
||||
<View className="mb-2 text-base font-medium">
|
||||
{category.boxCategoryName}
|
||||
{boxSpec.boxSpecName}
|
||||
</View>
|
||||
<View className="space-y-3">
|
||||
{category.boxProductList.map((boxProduct) => {
|
||||
{boxSpec.boxProductList.map((boxProduct) => {
|
||||
const currentCount =
|
||||
productCounts.get(boxProduct.id) || 0;
|
||||
return (
|
||||
@ -1005,19 +994,14 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
<View className="mb-4">
|
||||
<View className="mb-2 text-sm text-gray-600">纸箱详情</View>
|
||||
<View className="space-y-3">
|
||||
{editingItem?.boxCategoryList &&
|
||||
editingItem.boxCategoryList.map(
|
||||
(categoryData, categoryIndex) => (
|
||||
<View
|
||||
key={categoryIndex}
|
||||
className="rounded-lg bg-gray-50 p-3"
|
||||
>
|
||||
{editingItem?.boxSpecList &&
|
||||
editingItem.boxSpecList.map((boxSpec, specId) => (
|
||||
<View key={specId} className="rounded-lg bg-gray-50 p-3">
|
||||
<View className="mb-2 text-base font-medium text-gray-800">
|
||||
{categoryData.boxCategoryName}
|
||||
{boxSpec.boxSpecName}
|
||||
</View>
|
||||
<View className="space-y-2">
|
||||
{categoryData.boxProductList.map(
|
||||
(detail, detailIndex) => {
|
||||
{boxSpec.boxProductList.map((detail, detailIndex) => {
|
||||
const currentCount = detail?.boxCount || 0;
|
||||
|
||||
return (
|
||||
@ -1037,7 +1021,7 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
currentCount - 1,
|
||||
);
|
||||
updateEditingItemCount(
|
||||
categoryIndex,
|
||||
specId,
|
||||
detailIndex,
|
||||
newCount,
|
||||
);
|
||||
@ -1053,12 +1037,9 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
className="!h-8 !w-12 !p-0 !text-center"
|
||||
onChange={(value) => {
|
||||
const num = Number(value);
|
||||
if (
|
||||
!Number.isNaN(num) &&
|
||||
num >= 0
|
||||
) {
|
||||
if (!Number.isNaN(num) && num >= 0) {
|
||||
updateEditingItemCount(
|
||||
categoryIndex,
|
||||
specId,
|
||||
detailIndex,
|
||||
num,
|
||||
);
|
||||
@ -1070,7 +1051,7 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
className="flex h-8 w-8 items-center justify-center rounded-r bg-gray-200"
|
||||
onClick={() => {
|
||||
updateEditingItemCount(
|
||||
categoryIndex,
|
||||
specId,
|
||||
detailIndex,
|
||||
currentCount + 1,
|
||||
);
|
||||
@ -1084,12 +1065,10 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
)}
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
),
|
||||
)}
|
||||
))}
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
@ -68,18 +68,7 @@ export default function PurchasePreview(props: IPurchasePreviewProps) {
|
||||
const [columns] = useState<Array<TableColumnProps>>([
|
||||
{
|
||||
title: "规格",
|
||||
key: "boxCategoryId",
|
||||
render: (record: any) => {
|
||||
return (
|
||||
<View>
|
||||
{record.boxCategoryId === "FOUR_GRAIN"
|
||||
? "4粒"
|
||||
: record.boxCategoryId === "TWO_GRAIN"
|
||||
? "2粒"
|
||||
: "其他"}
|
||||
</View>
|
||||
);
|
||||
},
|
||||
key: "boxSpecName",
|
||||
fixed: "left",
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import { Table } from "@nutui/nutui-react-taro";
|
||||
import { formatCurrency } from "@/utils/format";
|
||||
|
||||
export default function EmptyBoxInfoSection(props: {
|
||||
export default function EmptyBoxInfoSection(_props: {
|
||||
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
|
||||
readOnly?: boolean;
|
||||
}) {
|
||||
const { purchaseOrderVO } = props;
|
||||
|
||||
// 将所有空箱信息合并并按品牌、型号、规格分组
|
||||
// const groupedEmptyBoxData = purchaseOrderVO.orderSupplierList?.reduce(
|
||||
// (acc, supplier) => {
|
||||
|
||||
@ -4,7 +4,6 @@ import { Button, Input, Popup, SafeArea, Table } from "@nutui/nutui-react-taro";
|
||||
import { Icon } from "@/components";
|
||||
import { View } from "@tarojs/components";
|
||||
|
||||
|
||||
export default function PackageInfoSection(props: {
|
||||
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
|
||||
onChange?: (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => void;
|
||||
@ -20,7 +19,7 @@ export default function PackageInfoSection(props: {
|
||||
},
|
||||
{
|
||||
title: "规格",
|
||||
key: "boxCategoryName",
|
||||
key: "boxSpecName",
|
||||
},
|
||||
{
|
||||
title: "纸箱型号",
|
||||
@ -33,7 +32,12 @@ export default function PackageInfoSection(props: {
|
||||
{
|
||||
title: "销售单价(元/斤)",
|
||||
key: "boxSalePrice",
|
||||
render: (value: BusinessAPI.OrderPackage & { orderPackageId?: string, isTotalRow?: boolean }) => {
|
||||
render: (
|
||||
value: BusinessAPI.OrderPackage & {
|
||||
orderPackageId?: string;
|
||||
isTotalRow?: boolean;
|
||||
},
|
||||
) => {
|
||||
// 合计行不显示编辑按钮
|
||||
if (value.isTotalRow) {
|
||||
return formatCurrency(value.boxSalePrice as number);
|
||||
@ -41,14 +45,15 @@ export default function PackageInfoSection(props: {
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex items-center justify-between w-full"
|
||||
className="flex w-full items-center justify-between"
|
||||
onClick={(e) => {
|
||||
if (!readOnly) {
|
||||
e.stopPropagation();
|
||||
// 设置临时编辑值为当前值
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[value.orderPackageId || ""]: editValues[value.orderPackageId || ""],
|
||||
[value.orderPackageId || ""]:
|
||||
editValues[value.orderPackageId || ""],
|
||||
}));
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
@ -57,9 +62,11 @@ export default function PackageInfoSection(props: {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<View className={!readOnly ? "underline cursor-pointer" : ""}>{formatCurrency(value.boxSalePrice as number)}</View>
|
||||
<View className={!readOnly ? "cursor-pointer underline" : ""}>
|
||||
{formatCurrency(value.boxSalePrice as number)}
|
||||
</View>
|
||||
{!readOnly && (
|
||||
<View className="flex items-center justify-center ml-2 p-2 -m-2">
|
||||
<View className="-m-2 ml-2 flex items-center justify-center p-2">
|
||||
<Icon name={"pen-to-square"} size={16} color={"#1a73e8"} />
|
||||
</View>
|
||||
)}
|
||||
@ -70,7 +77,12 @@ export default function PackageInfoSection(props: {
|
||||
{
|
||||
title: "销售金额(元)",
|
||||
key: "boxSalePayment",
|
||||
render: (value: BusinessAPI.OrderPackage & { boxProductCount: number, isTotalRow?: boolean }) =>
|
||||
render: (
|
||||
value: BusinessAPI.OrderPackage & {
|
||||
boxProductCount: number;
|
||||
isTotalRow?: boolean;
|
||||
},
|
||||
) =>
|
||||
formatCurrency(
|
||||
Number((value?.boxSalePrice || 0) * value.boxProductCount) as number,
|
||||
),
|
||||
@ -78,7 +90,12 @@ export default function PackageInfoSection(props: {
|
||||
{
|
||||
title: "箱重(斤)",
|
||||
key: "boxProductWeight",
|
||||
render: (value: BusinessAPI.OrderPackage & { orderPackageId?: string, isTotalRow?: boolean }) => {
|
||||
render: (
|
||||
value: BusinessAPI.OrderPackage & {
|
||||
orderPackageId?: string;
|
||||
isTotalRow?: boolean;
|
||||
},
|
||||
) => {
|
||||
// 合计行不显示编辑按钮
|
||||
if (value.isTotalRow) {
|
||||
return formatCurrency(value.boxProductWeight);
|
||||
@ -86,14 +103,15 @@ export default function PackageInfoSection(props: {
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex items-center justify-between w-full"
|
||||
className="flex w-full items-center justify-between"
|
||||
onClick={(e) => {
|
||||
if (!readOnly) {
|
||||
e.stopPropagation();
|
||||
// 设置临时编辑值为当前值
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[value.orderPackageId || ""]: editValues[value.orderPackageId || ""],
|
||||
[value.orderPackageId || ""]:
|
||||
editValues[value.orderPackageId || ""],
|
||||
}));
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
@ -102,9 +120,11 @@ export default function PackageInfoSection(props: {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<View className={!readOnly ? "underline cursor-pointer" : ""}>{formatCurrency(value.boxProductWeight)}</View>
|
||||
<View className={!readOnly ? "cursor-pointer underline" : ""}>
|
||||
{formatCurrency(value.boxProductWeight)}
|
||||
</View>
|
||||
{!readOnly && (
|
||||
<View className="flex items-center justify-center ml-2 p-2 -m-2">
|
||||
<View className="-m-2 ml-2 flex items-center justify-center p-2">
|
||||
<Icon name={"pen-to-square"} size={16} color={"#1a73e8"} />
|
||||
</View>
|
||||
)}
|
||||
@ -115,7 +135,12 @@ export default function PackageInfoSection(props: {
|
||||
{
|
||||
title: "成本单价(元)",
|
||||
key: "boxCostPrice",
|
||||
render: (value: BusinessAPI.OrderPackage & { orderPackageId?: string, isTotalRow?: boolean }) => {
|
||||
render: (
|
||||
value: BusinessAPI.OrderPackage & {
|
||||
orderPackageId?: string;
|
||||
isTotalRow?: boolean;
|
||||
},
|
||||
) => {
|
||||
// 合计行不显示编辑按钮
|
||||
if (value.isTotalRow) {
|
||||
return formatCurrency(value.boxCostPrice as number);
|
||||
@ -123,14 +148,15 @@ export default function PackageInfoSection(props: {
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex items-center justify-between w-full"
|
||||
className="flex w-full items-center justify-between"
|
||||
onClick={(e) => {
|
||||
if (!readOnly) {
|
||||
e.stopPropagation();
|
||||
// 设置临时编辑值为当前值
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[value.orderPackageId || ""]: editValues[value.orderPackageId || ""],
|
||||
[value.orderPackageId || ""]:
|
||||
editValues[value.orderPackageId || ""],
|
||||
}));
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
@ -139,9 +165,11 @@ export default function PackageInfoSection(props: {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<View className={!readOnly ? "underline cursor-pointer" : ""}>{formatCurrency(value.boxCostPrice as number)}</View>
|
||||
<View className={!readOnly ? "cursor-pointer underline" : ""}>
|
||||
{formatCurrency(value.boxCostPrice as number)}
|
||||
</View>
|
||||
{!readOnly && (
|
||||
<View className="flex items-center justify-center ml-2 p-2 -m-2">
|
||||
<View className="-m-2 ml-2 flex items-center justify-center p-2">
|
||||
<Icon name={"pen-to-square"} size={16} color={"#1a73e8"} />
|
||||
</View>
|
||||
)}
|
||||
@ -226,20 +254,17 @@ export default function PackageInfoSection(props: {
|
||||
(acc, supplier) => {
|
||||
supplier.orderPackageList?.forEach((pkg) => {
|
||||
// 生成分组键
|
||||
const key = `${pkg.boxBrandName}-${pkg.boxProductName}-${pkg.boxCategoryId}`;
|
||||
const key = `${pkg.boxBrandName}-${pkg.boxProductName}-${pkg.boxSpecId}`;
|
||||
|
||||
// 转换规格字段
|
||||
const boxCategoryName =
|
||||
pkg.boxCategoryId === "FOUR_GRAIN"
|
||||
? "4粒"
|
||||
: pkg.boxCategoryId === "TWO_GRAIN"
|
||||
? "2粒"
|
||||
: "其他";
|
||||
const boxSpecId = pkg.boxSpecId;
|
||||
const boxSpecName = pkg.boxSpecName;
|
||||
|
||||
if (!acc[key]) {
|
||||
acc[key] = {
|
||||
...pkg,
|
||||
boxCategoryName,
|
||||
boxSpecId,
|
||||
boxSpecName,
|
||||
boxProductCount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -213,7 +213,8 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
packingSpec: {
|
||||
data:
|
||||
shipOrderVO.shipOrderPackageList?.map((item) => ({
|
||||
boxCategory: item.boxCategory || "",
|
||||
boxSpecId: item.boxSpecId || "",
|
||||
boxSpecName: item.boxSpecName || "",
|
||||
boxType: item.boxProduct || "",
|
||||
quantity: item.quantity?.toString() || "",
|
||||
unitPrice: item.unitPrice?.toString() || "",
|
||||
@ -1078,13 +1079,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
htmlString += `
|
||||
<div class="${gridClass} ${index > 0 ? "border-t-0" : ""}">
|
||||
<div class="flex items-end justify-center">
|
||||
${
|
||||
item.boxCategory === "FOUR_GRAIN"
|
||||
? "4粒装"
|
||||
: item.boxCategory === "TWO_GRAIN"
|
||||
? "2粒装"
|
||||
: "未知"
|
||||
}
|
||||
${item.boxSpecName}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -2126,11 +2121,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
)}
|
||||
>
|
||||
<View className={"flex items-end justify-center"}>
|
||||
{item.boxCategory === "FOUR_GRAIN"
|
||||
? "4粒装"
|
||||
: item.boxCategory === "TWO_GRAIN"
|
||||
? "2粒装"
|
||||
: "未知"}
|
||||
{item.boxSpecName}
|
||||
</View>
|
||||
|
||||
<View className={"flex items-end justify-center"}>
|
||||
|
||||
@ -151,7 +151,8 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
packingSpec: {
|
||||
data:
|
||||
shipOrderVO.shipOrderPackageList?.map((item) => ({
|
||||
boxCategory: item.boxCategory || "",
|
||||
boxSpecId: item.boxSpecId || "",
|
||||
boxSpecName: item.boxSpecName || "",
|
||||
boxType: item.boxProduct || "",
|
||||
quantity: item.quantity?.toString() || "",
|
||||
unitPrice: item.unitPrice?.toString() || "",
|
||||
@ -1006,13 +1007,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
htmlString += `
|
||||
<div class="${gridClass} ${index > 0 ? "border-t-0" : ""}">
|
||||
<div class="flex items-end justify-center">
|
||||
${
|
||||
item.boxCategory === "FOUR_GRAIN"
|
||||
? "4粒装"
|
||||
: item.boxCategory === "TWO_GRAIN"
|
||||
? "2粒装"
|
||||
: "未知"
|
||||
}
|
||||
${item.boxSpecName}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -1948,11 +1943,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
)}
|
||||
>
|
||||
<View className={"flex items-end justify-center"}>
|
||||
{item.boxCategory === "FOUR_GRAIN"
|
||||
? "4粒装"
|
||||
: item.boxCategory === "TWO_GRAIN"
|
||||
? "2粒装"
|
||||
: "未知"}
|
||||
{item.boxSpecName}
|
||||
</View>
|
||||
|
||||
<View className={"flex items-end justify-center"}>
|
||||
|
||||
@ -25,11 +25,11 @@ import {
|
||||
Weigh,
|
||||
WeighRef,
|
||||
} from "@/components";
|
||||
import { calculateSupplierWeights } from "@/utils/calculateSupplierWeights";
|
||||
import { business } from "@/services";
|
||||
import { generateShortId } from "@/utils/generateShortId";
|
||||
import Taro from "@tarojs/taro";
|
||||
import buildUrl from "@/utils/buildUrl";
|
||||
import { SupplierWeightCalculator } from "@/utils/SupplierWeightCalculator";
|
||||
|
||||
const defaultSupplierList: SupplierVO[] = [
|
||||
{
|
||||
@ -191,10 +191,15 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
}, [active]);
|
||||
|
||||
useEffect(() => {
|
||||
if (orderSupplierList) {
|
||||
const supplierWeightCalculator = new SupplierWeightCalculator(
|
||||
orderSupplierList as any,
|
||||
);
|
||||
setPurchaseOrder((prev) => ({
|
||||
...prev!,
|
||||
orderSupplierList: calculateSupplierWeights(orderSupplierList),
|
||||
orderSupplierList: supplierWeightCalculator.calculate(),
|
||||
}));
|
||||
}
|
||||
}, [orderSupplierList]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
126
packages/app-client/src/services/business/boxSpec.ts
Normal file
126
packages/app-client/src/services/business/boxSpec.ts
Normal file
@ -0,0 +1,126 @@
|
||||
// @ts-ignore
|
||||
/* eslint-disable */
|
||||
import request from "../request";
|
||||
|
||||
/** 创建纸箱规格 POST /operation/createBoxSpec */
|
||||
export async function createBoxSpec(
|
||||
body: BusinessAPI.BoxSpecCreateCmd,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.SingleResponseBoxSpecVO>(
|
||||
"/operation/createBoxSpec",
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 纸箱规格删除 DELETE /operation/destroyBoxSpec */
|
||||
export async function destroyBoxSpec(
|
||||
body: BusinessAPI.BoxSpecDestroyCmd,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.Response>("/operation/destroyBoxSpec", {
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
});
|
||||
}
|
||||
|
||||
/** 纸箱规格列表 GET /operation/listBoxSpec */
|
||||
export async function listBoxSpec(
|
||||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||
params: BusinessAPI.listBoxSpecParams,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.MultiResponseBoxSpecVO>("/operation/listBoxSpec", {
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
boxSpecListQry: undefined,
|
||||
...params["boxSpecListQry"],
|
||||
},
|
||||
...(options || {}),
|
||||
});
|
||||
}
|
||||
|
||||
/** 纸箱规格列表 GET /operation/pageBoxSpec */
|
||||
export async function pageBoxSpec(
|
||||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||
params: BusinessAPI.pageBoxSpecParams,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.PageResponseBoxSpecVO>("/operation/pageBoxSpec", {
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
boxSpecPageQry: undefined,
|
||||
...params["boxSpecPageQry"],
|
||||
},
|
||||
...(options || {}),
|
||||
});
|
||||
}
|
||||
|
||||
/** 纸箱规格详情 GET /operation/showBoxSpec */
|
||||
export async function showBoxSpec(
|
||||
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
|
||||
params: BusinessAPI.showBoxSpecParams,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.SingleResponseBoxSpecVO>(
|
||||
"/operation/showBoxSpec",
|
||||
{
|
||||
method: "GET",
|
||||
params: {
|
||||
...params,
|
||||
boxSpecShowQry: undefined,
|
||||
...params["boxSpecShowQry"],
|
||||
},
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 纸箱规格更新 PUT /operation/updateBoxSpec */
|
||||
export async function updateBoxSpec(
|
||||
body: BusinessAPI.BoxSpecUpdateCmd,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.SingleResponseBoxSpecVO>(
|
||||
"/operation/updateBoxSpec",
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/** 纸箱规格更新 PATCH /operation/updateBoxSpec */
|
||||
export async function updateBoxSpec1(
|
||||
body: BusinessAPI.BoxSpecUpdateCmd,
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
return request<BusinessAPI.SingleResponseBoxSpecVO>(
|
||||
"/operation/updateBoxSpec",
|
||||
{
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
data: body,
|
||||
...(options || {}),
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -23,12 +23,14 @@ import * as costItem from "./costItem";
|
||||
import * as company from "./company";
|
||||
import * as companyPaymentAccount from "./companyPaymentAccount";
|
||||
import * as channel from "./channel";
|
||||
import * as boxSpec from "./boxSpec";
|
||||
import * as boxProduct from "./boxProduct";
|
||||
import * as boxBrand from "./boxBrand";
|
||||
import * as agreement from "./agreement";
|
||||
import * as role from "./role";
|
||||
import * as permission from "./permission";
|
||||
import * as extraction from "./extraction";
|
||||
|
||||
export default {
|
||||
user,
|
||||
supplier,
|
||||
@ -51,6 +53,7 @@ export default {
|
||||
company,
|
||||
companyPaymentAccount,
|
||||
channel,
|
||||
boxSpec,
|
||||
boxProduct,
|
||||
boxBrand,
|
||||
agreement,
|
||||
|
||||
@ -103,12 +103,14 @@ declare namespace BusinessAPI {
|
||||
name: string;
|
||||
/** 品牌图片URL */
|
||||
image?: string;
|
||||
/** 纸箱规格ID */
|
||||
specIds?: number[];
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
};
|
||||
|
||||
type BoxBrandDestroyCmd = {
|
||||
@ -132,8 +134,8 @@ declare namespace BusinessAPI {
|
||||
brandId?: string;
|
||||
/** 是否包含纸箱产品 */
|
||||
withProduct?: boolean;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
};
|
||||
|
||||
type BoxBrandPageQry = {
|
||||
@ -153,8 +155,8 @@ declare namespace BusinessAPI {
|
||||
status?: boolean;
|
||||
/** 纸箱品牌ID */
|
||||
brandId?: string;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
offset?: number;
|
||||
};
|
||||
|
||||
@ -172,12 +174,14 @@ declare namespace BusinessAPI {
|
||||
name: string;
|
||||
/** 品牌图片URL */
|
||||
image?: string;
|
||||
/** 纸箱规格ID */
|
||||
specIds?: number[];
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
};
|
||||
|
||||
type BoxBrandVO = {
|
||||
@ -187,14 +191,18 @@ declare namespace BusinessAPI {
|
||||
name: string;
|
||||
/** 品牌图片URL */
|
||||
image?: string;
|
||||
/** 纸箱规格ID */
|
||||
specIds?: number[];
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
/** 纸箱产品列表 */
|
||||
boxProductVOList?: BoxProductVO[];
|
||||
/** 纸箱规格列表 */
|
||||
boxSpecVOList?: BoxSpecVO[];
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
};
|
||||
@ -210,16 +218,18 @@ declare namespace BusinessAPI {
|
||||
costPrice?: number;
|
||||
/** 销售价 */
|
||||
salePrice?: number;
|
||||
/** 规格:1_2粒装;2_4粒装 */
|
||||
specType: "TWO_GRAIN" | "FOUR_GRAIN";
|
||||
/** 规格ID */
|
||||
specId?: string;
|
||||
/** 规格名称 */
|
||||
specName?: string;
|
||||
/** 品牌ID */
|
||||
brandId: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
};
|
||||
|
||||
type BoxProductDestroyCmd = {
|
||||
@ -245,10 +255,10 @@ declare namespace BusinessAPI {
|
||||
name?: string;
|
||||
/** 纸箱品牌ID */
|
||||
brandId?: string;
|
||||
/** 规格:1_2粒装;2_4粒装 */
|
||||
specType?: "TWO_GRAIN" | "FOUR_GRAIN";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 规格ID */
|
||||
specId?: string;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
};
|
||||
|
||||
type BoxProductPageQry = {
|
||||
@ -272,10 +282,10 @@ declare namespace BusinessAPI {
|
||||
name?: string;
|
||||
/** 纸箱品牌ID */
|
||||
brandId?: string;
|
||||
/** 规格:1_2粒装;2_4粒装 */
|
||||
specType?: "TWO_GRAIN" | "FOUR_GRAIN";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 规格ID */
|
||||
specId?: string;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type?: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
offset?: number;
|
||||
};
|
||||
|
||||
@ -297,16 +307,18 @@ declare namespace BusinessAPI {
|
||||
costPrice?: number;
|
||||
/** 销售价 */
|
||||
salePrice?: number;
|
||||
/** 规格:1_2粒装;2_4粒装 */
|
||||
specType: "TWO_GRAIN" | "FOUR_GRAIN";
|
||||
/** 规格ID */
|
||||
specId?: string;
|
||||
/** 规格名称 */
|
||||
specName?: string;
|
||||
/** 品牌ID */
|
||||
brandId: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
};
|
||||
|
||||
type BoxProductVO = {
|
||||
@ -320,12 +332,94 @@ declare namespace BusinessAPI {
|
||||
costPrice: number;
|
||||
/** 销售价 */
|
||||
salePrice: number;
|
||||
/** 规格:1_2粒装;2_4粒装 */
|
||||
specType: "TWO_GRAIN" | "FOUR_GRAIN";
|
||||
/** 规格ID */
|
||||
specId: string;
|
||||
/** 规格名称 */
|
||||
specName: string;
|
||||
/** 品牌ID */
|
||||
brandId: string;
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱 */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
/** 品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
type: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
/** 创建时间 */
|
||||
createdAt?: string;
|
||||
};
|
||||
|
||||
type BoxSpecCreateCmd = {
|
||||
/** 规格ID */
|
||||
specId: string;
|
||||
/** 规格名称 */
|
||||
name: string;
|
||||
/** 排序号 */
|
||||
sort: number;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
};
|
||||
|
||||
type BoxSpecDestroyCmd = {
|
||||
/** 纸箱规格ID */
|
||||
specId: string;
|
||||
};
|
||||
|
||||
type BoxSpecListQry = {
|
||||
/** 状态:1_启用;0_禁用; */
|
||||
status?: boolean;
|
||||
/** 纸箱规格ID */
|
||||
specId?: string;
|
||||
};
|
||||
|
||||
type BoxSpecPageQry = {
|
||||
pageSize?: number;
|
||||
pageIndex?: number;
|
||||
orderBy?: string;
|
||||
orderDirection?: string;
|
||||
groupBy?: string;
|
||||
needTotalCount?: boolean;
|
||||
/** 自定义字段key */
|
||||
customFieldKey?: string;
|
||||
/** 自定义字段value */
|
||||
customFieldValue?: string;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用; */
|
||||
status?: boolean;
|
||||
/** 纸箱规格ID */
|
||||
specId?: string;
|
||||
offset?: number;
|
||||
};
|
||||
|
||||
type BoxSpecShowQry = {
|
||||
/** 状态:1_启用;0_禁用; */
|
||||
status?: boolean;
|
||||
/** 纸箱规格ID */
|
||||
specId?: string;
|
||||
};
|
||||
|
||||
type BoxSpecUpdateCmd = {
|
||||
/** 纸箱规格ID */
|
||||
specId: string;
|
||||
/** 规格名称 */
|
||||
name: string;
|
||||
/** 排序号 */
|
||||
sort: number;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
status: boolean;
|
||||
};
|
||||
|
||||
type BoxSpecVO = {
|
||||
/** 规格ID */
|
||||
specId: string;
|
||||
/** 规格名称 */
|
||||
name: string;
|
||||
/** 排序号 */
|
||||
sort: number;
|
||||
/** 备注 */
|
||||
remark?: string;
|
||||
/** 状态:1_启用;0_禁用 */
|
||||
@ -878,6 +972,8 @@ declare namespace BusinessAPI {
|
||||
| "FIXED_COST"
|
||||
| "WORKER_ADVANCE"
|
||||
| "PRODUCTION_ADVANCE";
|
||||
/** 是否在录入时显示 */
|
||||
showInEntry?: boolean;
|
||||
/** 项目名称 */
|
||||
name?: string;
|
||||
offset?: number;
|
||||
@ -1823,6 +1919,10 @@ declare namespace BusinessAPI {
|
||||
boxProductListQry: BoxProductListQry;
|
||||
};
|
||||
|
||||
type listBoxSpecParams = {
|
||||
boxSpecListQry: BoxSpecListQry;
|
||||
};
|
||||
|
||||
type listCompanyParams = {
|
||||
companyListQry: CompanyListQry;
|
||||
};
|
||||
@ -2145,6 +2245,15 @@ declare namespace BusinessAPI {
|
||||
notEmpty?: boolean;
|
||||
};
|
||||
|
||||
type MultiResponseBoxSpecVO = {
|
||||
success?: boolean;
|
||||
errCode?: string;
|
||||
errMessage?: string;
|
||||
data?: BoxSpecVO[];
|
||||
empty?: boolean;
|
||||
notEmpty?: boolean;
|
||||
};
|
||||
|
||||
type MultiResponseCompanyPaymentAccountVO = {
|
||||
success?: boolean;
|
||||
errCode?: string;
|
||||
@ -2384,6 +2493,8 @@ declare namespace BusinessAPI {
|
||||
payerType?: "US" | "OTHER";
|
||||
/** 负责人 */
|
||||
principal?: string;
|
||||
/** 是否需要数量和价格 */
|
||||
requireQuantityAndPrice?: boolean;
|
||||
/** 费用类型:1_包装材料;2_人工费用;3_其他费用;4_固定费用;5_工头垫付;6_产地垫付 */
|
||||
costType:
|
||||
| "PACKAGING_MATERIALS"
|
||||
@ -2392,8 +2503,6 @@ declare namespace BusinessAPI {
|
||||
| "FIXED_COST"
|
||||
| "WORKER_ADVANCE"
|
||||
| "PRODUCTION_ADVANCE";
|
||||
/** 是否需要填写数量和单价 */
|
||||
requireQuantityAndPrice: boolean;
|
||||
};
|
||||
|
||||
type OrderDealer = {
|
||||
@ -2448,8 +2557,12 @@ declare namespace BusinessAPI {
|
||||
boxBrandName: string;
|
||||
/** 箱子品牌图片 */
|
||||
boxBrandImage?: string;
|
||||
/** 箱子分类ID */
|
||||
boxCategoryId: string;
|
||||
/** 箱子品牌类型:1_我方纸箱;2_瓜农纸箱;3_第三方纸箱;4_礼盒; */
|
||||
boxBrandType: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
/** 箱子规格ID */
|
||||
boxSpecId: string;
|
||||
/** 箱子规格名称 */
|
||||
boxSpecName: string;
|
||||
/** 箱子产品ID */
|
||||
boxProductId: string;
|
||||
/** 箱子产品名称 */
|
||||
@ -2596,6 +2709,10 @@ declare namespace BusinessAPI {
|
||||
boxProductPageQry: BoxProductPageQry;
|
||||
};
|
||||
|
||||
type pageBoxSpecParams = {
|
||||
boxSpecPageQry: BoxSpecPageQry;
|
||||
};
|
||||
|
||||
type pageChannelParams = {
|
||||
channelPageQry: ChannelPageQry;
|
||||
};
|
||||
@ -2699,6 +2816,19 @@ declare namespace BusinessAPI {
|
||||
totalPages?: number;
|
||||
};
|
||||
|
||||
type PageResponseBoxSpecVO = {
|
||||
success?: boolean;
|
||||
errCode?: string;
|
||||
errMessage?: string;
|
||||
totalCount?: number;
|
||||
pageSize?: number;
|
||||
pageIndex?: number;
|
||||
data?: BoxSpecVO[];
|
||||
empty?: boolean;
|
||||
notEmpty?: boolean;
|
||||
totalPages?: number;
|
||||
};
|
||||
|
||||
type PageResponseChannelVO = {
|
||||
success?: boolean;
|
||||
errCode?: string;
|
||||
@ -3752,8 +3882,10 @@ declare namespace BusinessAPI {
|
||||
orderPackageId: string;
|
||||
/** 发货单ID */
|
||||
shipOrderId: string;
|
||||
/** 箱型ID */
|
||||
boxSpecId?: number;
|
||||
/** 箱型 */
|
||||
boxCategory?: string;
|
||||
boxSpecName?: string;
|
||||
/** 箱号 */
|
||||
boxProduct?: string;
|
||||
/** 数量 */
|
||||
@ -3921,7 +4053,7 @@ declare namespace BusinessAPI {
|
||||
shipOrderItemList?: ShipOrderItem[];
|
||||
/** 发货单子项表 */
|
||||
shipOrderPackageList?: ShipOrderPackage[];
|
||||
/** 发货单费用项 */
|
||||
/** 发货单成本项目信息 */
|
||||
orderCostList?: OrderCost[];
|
||||
};
|
||||
|
||||
@ -3937,6 +4069,10 @@ declare namespace BusinessAPI {
|
||||
boxProductShowQry: BoxProductShowQry;
|
||||
};
|
||||
|
||||
type showBoxSpecParams = {
|
||||
boxSpecShowQry: BoxSpecShowQry;
|
||||
};
|
||||
|
||||
type showChannelParams = {
|
||||
channelShowQry: ChannelShowQry;
|
||||
};
|
||||
@ -4050,6 +4186,13 @@ declare namespace BusinessAPI {
|
||||
data?: BoxProductVO;
|
||||
};
|
||||
|
||||
type SingleResponseBoxSpecVO = {
|
||||
success?: boolean;
|
||||
errCode?: string;
|
||||
errMessage?: string;
|
||||
data?: BoxSpecVO;
|
||||
};
|
||||
|
||||
type SingleResponseCategoryVO = {
|
||||
success?: boolean;
|
||||
errCode?: string;
|
||||
|
||||
@ -13,7 +13,9 @@ export interface CommonComponent {
|
||||
user: AuthAPI.UserVO;
|
||||
shareOptions: any;
|
||||
role: "origin-entry" | "market-buyer" | "reviewer" | "boss";
|
||||
setRole: (role: "origin-entry" | "market-buyer" | "reviewer" | "boss") => void;
|
||||
setRole: (
|
||||
role: "origin-entry" | "market-buyer" | "reviewer" | "boss",
|
||||
) => void;
|
||||
router: Router;
|
||||
options: Taro.getLaunchOptionsSync.LaunchOptions;
|
||||
isInitialized: boolean;
|
||||
@ -33,9 +35,9 @@ export interface BoxBrand {
|
||||
boxBrandId: string;
|
||||
boxBrandName: string;
|
||||
boxBrandImage: string;
|
||||
boxBrandType: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
|
||||
boxBrandType: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX" | "GIFT_BOX";
|
||||
boxType: "USED" | "EXTRA" | "EXTRA_USED" | "REMAIN" | "OWN" | "DEFAULT";
|
||||
boxCategoryList: BoxCategory[];
|
||||
boxSpecList: BoxSpec[];
|
||||
}
|
||||
|
||||
export interface BoxProduct {
|
||||
@ -46,15 +48,16 @@ export interface BoxProduct {
|
||||
boxProductName: string;
|
||||
boxCount: number;
|
||||
boxProductWeight: number;
|
||||
boxCategoryId: "FOUR_GRAIN" | "TWO_GRAIN";
|
||||
boxSpecId: string;
|
||||
boxSpecName: string;
|
||||
boxCostPrice: number;
|
||||
boxSalePrice: number;
|
||||
}
|
||||
|
||||
export interface BoxCategory {
|
||||
export interface BoxSpec {
|
||||
id: string;
|
||||
boxCategoryId: "FOUR_GRAIN" | "TWO_GRAIN";
|
||||
boxCategoryName: string;
|
||||
boxSpecId: string;
|
||||
boxSpecName: string;
|
||||
boxProductList: BoxProduct[];
|
||||
}
|
||||
|
||||
|
||||
189
packages/app-client/src/utils/SupplierWeightCalculator.ts
Normal file
189
packages/app-client/src/utils/SupplierWeightCalculator.ts
Normal file
@ -0,0 +1,189 @@
|
||||
import { Decimal } from "decimal.js";
|
||||
|
||||
/**
|
||||
* 农户重量计算器类
|
||||
* 用于计算每个农户的净重和毛重,并赋值到原数据中
|
||||
*/
|
||||
export class SupplierWeightCalculator {
|
||||
private suppliers: BusinessAPI.OrderSupplier[];
|
||||
|
||||
constructor(suppliers: BusinessAPI.OrderSupplier[]) {
|
||||
this.suppliers = suppliers;
|
||||
this.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化计算规则
|
||||
*/
|
||||
private init() {
|
||||
Decimal.set({
|
||||
precision: 20,
|
||||
rounding: 0, // 向下舍入(更保守的计算方式)
|
||||
toExpNeg: -7,
|
||||
toExpPos: 21,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算所有农户的重量信息
|
||||
* @returns {Array} 包含净重、毛重和空磅的农户数据
|
||||
*/
|
||||
calculate(): BusinessAPI.OrderSupplier[] {
|
||||
if (!this.suppliers || this.suppliers.length === 0) {
|
||||
return this.suppliers;
|
||||
}
|
||||
|
||||
// 使用第一个瓜农的空磅重量作为初始空磅重量
|
||||
const initialEmptyWeight = this.suppliers[0].emptyWeight;
|
||||
let previousTotalWeight = initialEmptyWeight; // 上一个农户的总磅重量(kg)
|
||||
|
||||
for (let i = 0; i < this.suppliers.length; i++) {
|
||||
const supplier = this.suppliers[i];
|
||||
const isFirstSupplier = i === 0;
|
||||
const isLastSupplier = supplier.isLast;
|
||||
|
||||
// 设置空磅重量(第一个农户使用自己的空磅重量,其他使用前一个农户的总磅重量)
|
||||
if (isFirstSupplier) {
|
||||
// 第一个农户的空磅重量已经是正确的
|
||||
} else {
|
||||
supplier.emptyWeight = this.suppliers[i - 1].totalWeight;
|
||||
}
|
||||
|
||||
// 计算本次使用纸箱的总重量(斤)
|
||||
const usedBoxesWeight = new Decimal(
|
||||
this.calculateBoxesTotalWeight(supplier.orderPackageList || [], "USED"),
|
||||
)
|
||||
.add(
|
||||
this.calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList || [],
|
||||
"OWN",
|
||||
),
|
||||
)
|
||||
.toNumber();
|
||||
|
||||
// 计算额外配送的已使用纸箱总重量(斤)
|
||||
const extraUsedBoxesWeight = this.calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList || [],
|
||||
"EXTRA_USED",
|
||||
);
|
||||
|
||||
if (!supplier.isPaper) {
|
||||
// 如果不是纸箱包装,直接使用原始重量(kg转斤)
|
||||
supplier.grossWeight = new Decimal(supplier.totalWeight)
|
||||
.sub(supplier.emptyWeight)
|
||||
.mul(2)
|
||||
.toNumber();
|
||||
|
||||
supplier.netWeight = new Decimal(supplier.grossWeight)
|
||||
.sub(usedBoxesWeight)
|
||||
.sub(extraUsedBoxesWeight)
|
||||
.toNumber();
|
||||
|
||||
previousTotalWeight = supplier.totalWeight;
|
||||
supplier.invoiceAmount = new Decimal(supplier.netWeight)
|
||||
.mul(supplier.purchasePrice)
|
||||
.toNumber();
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算额外配送的纸箱总重量(斤)
|
||||
const extraBoxesWeight = this.calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList || [],
|
||||
"EXTRA",
|
||||
);
|
||||
|
||||
// 计算车上剩余纸箱(斤)
|
||||
const remainingBoxesWeight = this.calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList || [],
|
||||
"REMAIN",
|
||||
);
|
||||
|
||||
if (isFirstSupplier && isLastSupplier) {
|
||||
// 既是第一个也是最后一个瓜农(单个瓜农情况)- 优先使用最后一个瓜农算法
|
||||
// 净重 = (总磅 - 空磅) * 2 + 剩余空箱子重量 - 已使用额外纸箱重量
|
||||
supplier.netWeight = new Decimal(supplier.totalWeight)
|
||||
.sub(initialEmptyWeight)
|
||||
.mul(2)
|
||||
.add(remainingBoxesWeight)
|
||||
.sub(extraUsedBoxesWeight)
|
||||
.toNumber();
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = new Decimal(supplier.netWeight)
|
||||
.add(usedBoxesWeight)
|
||||
.toNumber();
|
||||
} else if (isLastSupplier) {
|
||||
// 最后一个农户(根据isLast标识判断)
|
||||
// 净重 = (总磅 - 前一个总磅) * 2 + 剩余空箱子重量 - 额外纸箱重量
|
||||
supplier.netWeight = new Decimal(supplier.totalWeight)
|
||||
.sub(previousTotalWeight)
|
||||
.mul(2)
|
||||
.add(remainingBoxesWeight)
|
||||
.sub(extraBoxesWeight)
|
||||
.toNumber();
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = new Decimal(supplier.netWeight)
|
||||
.add(usedBoxesWeight)
|
||||
.toNumber();
|
||||
} else if (isFirstSupplier) {
|
||||
// 第一个农户(但不是最后一个)
|
||||
// 净重 = (总磅 - 空磅) * 2 - 额外纸箱重量
|
||||
supplier.netWeight = new Decimal(supplier.totalWeight)
|
||||
.sub(initialEmptyWeight)
|
||||
.mul(2)
|
||||
.sub(extraBoxesWeight)
|
||||
.toNumber();
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = new Decimal(supplier.netWeight)
|
||||
.add(usedBoxesWeight)
|
||||
.toNumber();
|
||||
} else {
|
||||
// 中间农户
|
||||
// 净重 = (总磅 - 前一个总磅) * 2 - 额外纸箱重量
|
||||
supplier.netWeight = new Decimal(supplier.totalWeight)
|
||||
.sub(previousTotalWeight)
|
||||
.mul(2)
|
||||
.sub(extraBoxesWeight)
|
||||
.toNumber();
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = new Decimal(supplier.netWeight)
|
||||
.add(usedBoxesWeight)
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
previousTotalWeight = supplier.totalWeight;
|
||||
supplier.invoiceAmount = new Decimal(supplier.netWeight)
|
||||
.mul(supplier.purchasePrice)
|
||||
.toNumber();
|
||||
}
|
||||
|
||||
return this.suppliers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算纸箱的总重量(斤)
|
||||
* @param {Array} orderPackageList - 包装信息列表
|
||||
* @param {string} boxType - 箱子类型 ('USED' 或 'EXTRA',不传则计算所有)
|
||||
* @returns {number} 总重量(斤)
|
||||
*/
|
||||
private calculateBoxesTotalWeight(
|
||||
orderPackageList: BusinessAPI.OrderPackage[],
|
||||
boxType?: any,
|
||||
): number {
|
||||
if (!orderPackageList) return 0;
|
||||
|
||||
let filteredPackages = orderPackageList;
|
||||
if (boxType) {
|
||||
filteredPackages = orderPackageList.filter(
|
||||
(pkg) => pkg.boxType === boxType,
|
||||
);
|
||||
}
|
||||
|
||||
return filteredPackages.reduce((sum, pkg) => {
|
||||
// 纸箱重量单位是斤,直接使用
|
||||
const boxWeight = pkg.boxProductWeight || 0;
|
||||
return new Decimal(sum)
|
||||
.add(new Decimal(pkg.boxCount || 0).mul(boxWeight))
|
||||
.toNumber();
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
@ -1,293 +0,0 @@
|
||||
/**
|
||||
* 计算每个农户的净重和毛重,并赋值到原数据中
|
||||
* @param {Array} suppliers - 农户数据数组
|
||||
* @returns {Array} 包含净重、毛重和空磅的农户数据
|
||||
*/
|
||||
export function calculateSupplierWeights(suppliers) {
|
||||
if (!suppliers || suppliers.length === 0) {
|
||||
return suppliers;
|
||||
}
|
||||
|
||||
// 使用第一个瓜农的空磅重量作为初始空磅重量
|
||||
const initialEmptyWeight = suppliers[0].emptyWeight;
|
||||
let previousTotalWeight = initialEmptyWeight; // 上一个农户的总磅重量(kg)
|
||||
|
||||
for (let i = 0; i < suppliers.length; i++) {
|
||||
const supplier = suppliers[i];
|
||||
const isFirstSupplier = i === 0;
|
||||
const isLastSupplier = supplier.isLast === true;
|
||||
|
||||
// 设置空磅重量(第一个农户使用自己的空磅重量,其他使用前一个农户的总磅重量)
|
||||
if (isFirstSupplier) {
|
||||
// 第一个农户的空磅重量已经是正确的
|
||||
} else {
|
||||
supplier.emptyWeight = suppliers[i - 1].totalWeight;
|
||||
}
|
||||
|
||||
// 计算本次使用纸箱的总重量(斤)
|
||||
const usedBoxesWeight = calculateBoxesTotalWeight(supplier.orderPackageList, 'USED') + calculateBoxesTotalWeight(supplier.orderPackageList, 'OWN');
|
||||
|
||||
if (!supplier.isPaper) {
|
||||
// 如果不是纸箱包装,直接使用原始重量(kg转斤)
|
||||
supplier.grossWeight = (supplier.totalWeight - supplier.emptyWeight) * 2;
|
||||
supplier.netWeight = supplier.grossWeight - usedBoxesWeight;
|
||||
previousTotalWeight = supplier.totalWeight;
|
||||
supplier.invoiceAmount = supplier.netWeight * supplier.purchasePrice;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算额外配送的纸箱总重量(斤)
|
||||
const extraBoxesWeight = calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList,
|
||||
'EXTRA'
|
||||
);
|
||||
|
||||
// 计算额外配送的已使用纸箱总重量(斤)
|
||||
const extraUsedBoxesWeight = calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList,
|
||||
'EXTRA_USED'
|
||||
);
|
||||
|
||||
// 计算车上剩余纸箱(斤)
|
||||
const remainingBoxesWeight = calculateBoxesTotalWeight(
|
||||
supplier.orderPackageList,
|
||||
'REMAIN'
|
||||
);
|
||||
|
||||
if (isFirstSupplier && isLastSupplier) {
|
||||
// 既是第一个也是最后一个瓜农(单个瓜农情况)- 优先使用最后一个瓜农算法
|
||||
// 净重 = (总磅 - 空磅) * 2 + 剩余空箱子重量 - 已使用额外纸箱重量
|
||||
supplier.netWeight = (supplier.totalWeight - initialEmptyWeight) * 2 + remainingBoxesWeight - extraUsedBoxesWeight;
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = supplier.netWeight + usedBoxesWeight;
|
||||
|
||||
} else if (isLastSupplier) {
|
||||
// 最后一个农户(根据isLast标识判断)
|
||||
// 净重 = (总磅 - 前一个总磅) * 2 + 剩余空箱子重量 - 额外纸箱重量
|
||||
supplier.netWeight = (supplier.totalWeight - previousTotalWeight) * 2 + remainingBoxesWeight - extraBoxesWeight;
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = supplier.netWeight + usedBoxesWeight;
|
||||
|
||||
} else if (isFirstSupplier) {
|
||||
// 第一个农户(但不是最后一个)
|
||||
// 净重 = (总磅 - 空磅) * 2 - 额外纸箱重量
|
||||
supplier.netWeight = (supplier.totalWeight - initialEmptyWeight) * 2 - extraBoxesWeight;
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = supplier.netWeight + usedBoxesWeight;
|
||||
|
||||
} else {
|
||||
// 中间农户
|
||||
// 净重 = (总磅 - 前一个总磅) * 2 - 额外纸箱重量
|
||||
supplier.netWeight = (supplier.totalWeight - previousTotalWeight) * 2 - extraBoxesWeight;
|
||||
// 毛重 = 净重 + 本次使用纸箱重量
|
||||
supplier.grossWeight = supplier.netWeight + usedBoxesWeight;
|
||||
}
|
||||
|
||||
previousTotalWeight = supplier.totalWeight;
|
||||
supplier.invoiceAmount = supplier.netWeight * supplier.purchasePrice;
|
||||
}
|
||||
|
||||
return suppliers;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算纸箱的总重量(斤)
|
||||
* @param {Array} orderPackageList - 包装信息列表
|
||||
* @param {string} boxType - 箱子类型 ('used' 或 'extra',不传则计算所有)
|
||||
* @returns {number} 总重量(斤)
|
||||
*/
|
||||
function calculateBoxesTotalWeight(orderPackageList, boxType?: any) {
|
||||
if (!orderPackageList) return 0;
|
||||
|
||||
let filteredPackages = orderPackageList;
|
||||
if (boxType) {
|
||||
filteredPackages = orderPackageList.filter((pkg) => pkg.boxType === boxType);
|
||||
}
|
||||
|
||||
return filteredPackages.reduce((sum, pkg) => {
|
||||
// 纸箱重量单位是斤,直接使用
|
||||
const boxWeight = pkg.boxProductWeight || 0;
|
||||
return sum + pkg.boxCount * boxWeight;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// // 使用示例 - 单个瓜农(既是第一个也是最后一个)
|
||||
// const singleSupplier = [
|
||||
// {
|
||||
// id: "1",
|
||||
// name: "瓜农1",
|
||||
// isPaper: true,
|
||||
// isLast: true, // 单个瓜农也是最后一个
|
||||
// emptyWeight: 25, // kg
|
||||
// totalWeight: 50, // kg
|
||||
// orderPackageList: [
|
||||
// {
|
||||
// boxBrandId: "brand1",
|
||||
// boxCategoryId: "TWO_GRAIN",
|
||||
// boxProductId: "product1",
|
||||
// boxProductWeight: 0.6, // 斤
|
||||
// boxCount: 2,
|
||||
// boxType: "used"
|
||||
// },
|
||||
// {
|
||||
// boxBrandId: "brand1",
|
||||
// boxCategoryId: "TWO_GRAIN",
|
||||
// boxProductId: "product1",
|
||||
// boxProductWeight: 0.6, // 斤
|
||||
// boxCount: 1,
|
||||
// boxType: "extra-used"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ];
|
||||
//
|
||||
// // 使用示例 - 多个瓜农
|
||||
// const multipleSuppliers = [
|
||||
// {
|
||||
// id: "1",
|
||||
// name: "瓜农1",
|
||||
// isPaper: true,
|
||||
// emptyWeight: 25, // kg
|
||||
// totalWeight: 50, // kg
|
||||
// orderPackageList: [
|
||||
// {
|
||||
// boxBrandId: "brand1",
|
||||
// boxCategoryId: "TWO_GRAIN",
|
||||
// boxProductId: "product1",
|
||||
// boxProductWeight: 0.6, // 斤
|
||||
// boxCount: 2,
|
||||
// boxType: "used"
|
||||
// },
|
||||
// {
|
||||
// boxBrandId: "brand1",
|
||||
// boxCategoryId: "TWO_GRAIN",
|
||||
// boxProductId: "product1",
|
||||
// boxProductWeight: 0.6, // 斤
|
||||
// boxCount: 1,
|
||||
// boxType: "extra"
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// id: "2",
|
||||
// name: "瓜农2",
|
||||
// isPaper: true,
|
||||
// isLast: true, // 标记为最后一个瓜农
|
||||
// totalWeight: 80, // kg
|
||||
// orderPackageList: [
|
||||
// {
|
||||
// boxBrandId: "brand2",
|
||||
// boxCategoryId: "THREE_GRAIN",
|
||||
// boxProductId: "product2",
|
||||
// boxProductWeight: 1.0, // 斤
|
||||
// boxCount: 2,
|
||||
// boxType: "used"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ];
|
||||
//
|
||||
// // 使用示例 - 第一个但不是最后一个
|
||||
// const firstNotLastSuppliers = [
|
||||
// {
|
||||
// id: "1",
|
||||
// name: "瓜农1",
|
||||
// isPaper: true,
|
||||
// emptyWeight: 25, // kg
|
||||
// totalWeight: 50, // kg
|
||||
// orderPackageList: [
|
||||
// {
|
||||
// boxBrandId: "brand1",
|
||||
// boxCategoryId: "TWO_GRAIN",
|
||||
// boxProductId: "product1",
|
||||
// boxProductWeight: 0.6, // 斤
|
||||
// boxCount: 2,
|
||||
// boxType: "used"
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// id: "2",
|
||||
// name: "瓜农2",
|
||||
// isPaper: true,
|
||||
// // 没有isLast标记,当作中间农户
|
||||
// totalWeight: 80, // kg
|
||||
// orderPackageList: [
|
||||
// {
|
||||
// boxBrandId: "brand2",
|
||||
// boxCategoryId: "THREE_GRAIN",
|
||||
// boxProductId: "product2",
|
||||
// boxProductWeight: 1.0, // 斤
|
||||
// boxCount: 2,
|
||||
// boxType: "used"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ];
|
||||
//
|
||||
// console.log("=== 单个瓜农测试(既是第一个也是最后一个)===");
|
||||
// const result1 = calculateSupplierWeights(singleSupplier);
|
||||
// console.log(JSON.stringify(result1, null, 2));
|
||||
//
|
||||
// console.log("\n=== 多个瓜农测试 ===");
|
||||
// const result2 = calculateSupplierWeights(multipleSuppliers);
|
||||
// console.log(JSON.stringify(result2, null, 2));
|
||||
//
|
||||
// console.log("\n=== 第一个但不是最后一个测试 ===");
|
||||
// const result3 = calculateSupplierWeights(firstNotLastSuppliers);
|
||||
// console.log(JSON.stringify(result3, null, 2));
|
||||
//
|
||||
// // 详细显示结果
|
||||
// function displayResults(suppliers, title) {
|
||||
// console.log(`\n${title}:`);
|
||||
// suppliers.forEach((supplier, index) => {
|
||||
//
|
||||
// const isFirstSupplier = index === 0;
|
||||
// const isLastSupplier = supplier.isLast === true;
|
||||
//
|
||||
// console.log(`\n农户${index + 1} ${supplier.name}:`);
|
||||
// console.log(` 是否第一个: ${index === 0 ? '是' : '否'}`);
|
||||
// console.log(` 是否最后一个: ${supplier.isLast ? '是' : '否'}`);
|
||||
// console.log(` 空磅重量: ${supplier.emptyWeight} kg`);
|
||||
// console.log(` 总磅重量: ${supplier.totalWeight} kg`);
|
||||
// console.log(` 净重: ${supplier.netWeight?.toFixed(2) || 'N/A'} 斤`);
|
||||
// console.log(` 毛重: ${supplier.grossWeight?.toFixed(2) || 'N/A'} 斤`);
|
||||
//
|
||||
// if (supplier.isPaper) {
|
||||
// const usedBoxesWeight = calculateBoxesTotalWeight(supplier.orderPackageList, 'used');
|
||||
// const extraUsedBoxesWeight = calculateBoxesTotalWeight(supplier.orderPackageList, 'extra-used');
|
||||
// const extraBoxesWeight = calculateBoxesTotalWeight(supplier.orderPackageList, 'extra');
|
||||
// const remainingEmptyBoxesWeight = calculateBoxesTotalWeight(supplier.orderPackageList, 'remaining');
|
||||
//
|
||||
// if (isFirstSupplier && isLastSupplier) {
|
||||
// console.log(` 本次使用纸箱重量: ${usedBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 已用额外运输纸箱重量: ${extraUsedBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 车上剩余纸箱重量: ${remainingEmptyBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 净重 = (总磅${supplier.totalWeight} - 空磅${supplier.emptyWeight}) × 2 + 车上剩余纸箱重量${remainingEmptyBoxesWeight.toFixed(2)} - 已用额外运输纸箱重量${extraUsedBoxesWeight.toFixed(2)} = ${supplier.netWeight?.toFixed(2)}斤`);
|
||||
// console.log(` 毛重 = 净重${supplier.netWeight?.toFixed(2)} + 本次使用纸箱重量${usedBoxesWeight.toFixed(2)} = ${supplier.grossWeight?.toFixed(2)}斤`);
|
||||
// } else if (isFirstSupplier) {
|
||||
// // 第一个瓜农
|
||||
// console.log(` 本次使用纸箱重量: ${usedBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 额外运输纸箱重量: ${extraBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 净重 = (总磅${supplier.totalWeight} - 空磅${supplier.emptyWeight}) × 2 - 额外运输纸箱重量${extraBoxesWeight.toFixed(2)} = ${supplier.netWeight?.toFixed(2)}斤`);
|
||||
// console.log(` 毛重 = 净重${supplier.netWeight?.toFixed(2)} + 本次使用纸箱重量${usedBoxesWeight.toFixed(2)} = ${supplier.grossWeight?.toFixed(2)}斤`);
|
||||
// } else if (isLastSupplier) {
|
||||
// // 最后一个瓜农
|
||||
// console.log(` 本次使用纸箱重量: ${usedBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 已用额外运输纸箱重量: ${extraUsedBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 车上剩余纸箱重量: ${remainingEmptyBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 净重 = (总磅${supplier.totalWeight} - 空磅${suppliers[index-1]?.totalWeight}) × 2 + 车上剩余纸箱重量${remainingEmptyBoxesWeight.toFixed(2)} - 已用额外运输纸箱重量${extraUsedBoxesWeight.toFixed(2)} = ${supplier.netWeight?.toFixed(2)}斤`);
|
||||
// console.log(` 毛重 = 净重${supplier.netWeight?.toFixed(2)} + 本次使用纸箱重量${usedBoxesWeight.toFixed(2)} = ${supplier.grossWeight?.toFixed(2)}斤`);
|
||||
// } else {
|
||||
// console.log(` 本次使用纸箱重量: ${usedBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 额外运输纸箱重量: ${extraBoxesWeight.toFixed(2)} 斤`);
|
||||
// console.log(` 净重 = (总磅${supplier.totalWeight} - 空磅${suppliers[index-1]?.totalWeight}) × 2 - 额外运输纸箱重量${extraBoxesWeight.toFixed(2)} = ${supplier.netWeight?.toFixed(2)}斤`);
|
||||
// console.log(` 毛重 = 净重${supplier.netWeight?.toFixed(2)} + 本次使用纸箱重量${usedBoxesWeight.toFixed(2)} = ${supplier.grossWeight?.toFixed(2)}斤`);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// displayResults(result1, "单个瓜农结果");
|
||||
// displayResults(result2, "多个瓜农结果");
|
||||
// displayResults(result3, "第一个但不是最后一个结果");
|
||||
@ -1,9 +1,9 @@
|
||||
// 将BoxBrand转换为OrderPackage数组
|
||||
import { BoxBrand, BoxCategory, BoxProduct } from "@/types/typings";
|
||||
import { BoxBrand, BoxProduct, BoxSpec } from "@/types/typings";
|
||||
import { generateShortId } from "@/utils/generateShortId";
|
||||
|
||||
// 添加一个辅助函数用于分组
|
||||
const groupBy = <T,>(
|
||||
const groupBy = <T>(
|
||||
array: T[],
|
||||
keyFn: (item: T) => string,
|
||||
): Record<string, T[]> => {
|
||||
@ -22,19 +22,21 @@ const groupBy = <T,>(
|
||||
|
||||
export const convertBoxBrandToOrderPackages = (
|
||||
boxBrand: BoxBrand,
|
||||
boxType: BusinessAPI.OrderPackage["boxType"] = "USED"
|
||||
boxType: BusinessAPI.OrderPackage["boxType"] = "USED",
|
||||
): BusinessAPI.OrderPackage[] => {
|
||||
const orderPackages: BusinessAPI.OrderPackage[] = [];
|
||||
|
||||
boxBrand.boxCategoryList?.forEach((category) => {
|
||||
boxBrand.boxSpecList?.forEach((category) => {
|
||||
category.boxProductList.forEach((product) => {
|
||||
orderPackages.push({
|
||||
orderPackageId: product.id,
|
||||
boxBrandId: product.boxBrandId,
|
||||
boxBrandName: product.boxBrandName,
|
||||
boxBrandImage: boxBrand.boxBrandImage,
|
||||
boxCategoryId: product.boxCategoryId,
|
||||
boxSpecId: product.boxSpecId,
|
||||
boxSpecName: product.boxSpecName,
|
||||
boxProductId: product.boxProductId,
|
||||
boxBrandType: boxBrand.boxBrandType,
|
||||
boxProductName: product.boxProductName,
|
||||
boxProductWeight: product.boxProductWeight,
|
||||
boxCount: product.boxCount || 0,
|
||||
@ -50,54 +52,48 @@ export const convertBoxBrandToOrderPackages = (
|
||||
|
||||
// 将OrderPackage数组转换为BoxBrand数组
|
||||
export const convertOrderPackagesToBoxBrands = (
|
||||
orderPackages: BusinessAPI.OrderPackage[]
|
||||
orderPackages: BusinessAPI.OrderPackage[],
|
||||
): BoxBrand[] => {
|
||||
// 按品牌ID分组
|
||||
const packagesByBrand = groupBy(
|
||||
orderPackages,
|
||||
(pkg) => pkg.boxBrandId
|
||||
);
|
||||
const packagesByBrand = groupBy(orderPackages, (pkg) => pkg.boxBrandId);
|
||||
|
||||
// 转换为BoxBrand数组
|
||||
return Object.entries(packagesByBrand).map(([brandId, packages]) => {
|
||||
const firstPackage = packages[0];
|
||||
|
||||
// 按分类ID分组
|
||||
const packagesByCategory = groupBy(
|
||||
packages,
|
||||
(pkg) => pkg.boxCategoryId
|
||||
);
|
||||
const packagesBySpec = groupBy(packages, (pkg) => pkg.boxSpecId);
|
||||
|
||||
// 创建BoxCategory数组
|
||||
const boxCategories: BoxCategory[] = Object.entries(packagesByCategory).map(
|
||||
([categoryId, categoryPackages]) => {
|
||||
const firstCategoryPackage = categoryPackages[0];
|
||||
const boxSpecList: BoxSpec[] = Object.entries(packagesBySpec).map(
|
||||
([specId, specList]) => {
|
||||
const firstCategoryPackage = specList[0];
|
||||
|
||||
// 创建BoxProduct数组
|
||||
const boxProducts: BoxProduct[] = categoryPackages.map((pkg) => ({
|
||||
const boxProducts: BoxProduct[] = specList.map(
|
||||
(pkg) =>
|
||||
({
|
||||
id: pkg.orderPackageId || generateShortId(),
|
||||
boxBrandId: pkg.boxBrandId,
|
||||
boxBrandName: pkg.boxBrandName,
|
||||
boxProductId: pkg.boxProductId,
|
||||
boxProductName: pkg.boxProductName,
|
||||
boxProductWeight: pkg.boxProductWeight,
|
||||
boxCategoryId: pkg.boxCategoryId,
|
||||
boxSpecId: pkg.boxSpecId,
|
||||
boxSpecName: pkg.boxSpecName,
|
||||
boxCostPrice: pkg.boxCostPrice,
|
||||
boxSalePrice: pkg.boxSalePrice,
|
||||
boxCount: pkg.boxCount,
|
||||
} as BoxProduct));
|
||||
}) as BoxProduct,
|
||||
);
|
||||
|
||||
return {
|
||||
id: generateShortId(),
|
||||
boxCategoryId: categoryId as "FOUR_GRAIN" | "TWO_GRAIN",
|
||||
boxCategoryName: firstCategoryPackage.boxCategoryId === "FOUR_GRAIN"
|
||||
? "4粒装"
|
||||
: firstCategoryPackage.boxCategoryId === "TWO_GRAIN"
|
||||
? "2粒装"
|
||||
: "未知",
|
||||
boxSpecId: specId,
|
||||
boxSpecName: firstCategoryPackage.boxSpecName,
|
||||
boxProductList: boxProducts,
|
||||
};
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
@ -105,8 +101,9 @@ export const convertOrderPackagesToBoxBrands = (
|
||||
boxBrandId: brandId,
|
||||
boxType: firstPackage.boxType,
|
||||
boxBrandName: firstPackage.boxBrandName,
|
||||
boxBrandImage: firstPackage.boxBrandImage,
|
||||
boxCategoryList: boxCategories,
|
||||
boxBrandImage: firstPackage.boxBrandImage!,
|
||||
boxBrandType: firstPackage.boxBrandType,
|
||||
boxSpecList: boxSpecList,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user