ERPTurbo_Client/packages/app-client/src/components/purchase/module/OrderOption.tsx
shenyifei dfe9a89213 refactor(components): 优化采购模块空箱和费用组件实现
- 移除 PageList 组件中对全局 loading 状态的依赖
- 简化 EmptyBoxModule 组件逻辑,使用 PackageList 组件替代原有复杂实现
- 移除冗余的状态管理和弹窗渲染逻辑
- 优化 OrderCost 组件样式和费用项匹配逻辑
- 修复成本项 ID 匹配问题,确保数据正确关联
- 添加边框样式增强视觉效果
- 移除调试日志和无用代码
- 简化组件间数据传递方式
2025-12-11 12:42:01 +08:00

474 lines
14 KiB
TypeScript

import { View } from "@tarojs/components";
import { purchase } from "@/constant";
import { Button, Dialog, SafeArea, Toast } from "@nutui/nutui-react-taro";
import React, { forwardRef, useImperativeHandle } from "react";
import { globalStore } from "@/store/global-store";
import Taro from "@tarojs/taro";
import { buildUrl, generateShortId } from "@/utils";
import { business } from "@/services";
// 定义ref暴露的方法接口
export interface OrderOptionRef {
onAdd: () => void;
}
interface IOrderOptionProps {
value: BusinessAPI.PurchaseOrderVO;
onChange: (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => void;
vehicleRef: React.MutableRefObject<any>;
melonFarmerRefs: React.MutableRefObject<any[]>;
weighRefs: React.MutableRefObject<any[]>;
orderPackageRefs: React.MutableRefObject<any[]>;
orderCostRef: React.MutableRefObject<any>;
orderCostItemRef: React.MutableRefObject<any>;
}
export default forwardRef<OrderOptionRef, IOrderOptionProps>(
function OrderOption(props: IOrderOptionProps, ref) {
const {
value,
onChange,
vehicleRef,
melonFarmerRefs,
weighRefs,
orderPackageRefs,
orderCostRef,
orderCostItemRef,
} = props;
const { setLoading } = globalStore((state: any) => state);
const { orderSupplierList } = value;
const active = Number(value.active);
const setActive = (active: number) => {
onChange({
...value,
active,
});
};
// 车辆信息和经销商信息的保存
const saveVehicleAndDealerInfo = async () => {
if (!value) {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: "保存失败",
});
return false;
}
try {
let tempOrderId = value.orderId;
if (tempOrderId) {
const { data } = await business.purchaseOrder.savePurchaseOrderStep1({
orderId: tempOrderId,
active: active,
orderVehicle: value.orderVehicle,
orderDealer: value.orderDealer,
});
if (data.success) {
return true;
} else {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: data?.errMessage || "保存失败",
});
return false;
}
} else {
const { data } = await business.purchaseOrder.savePurchaseOrderStep1({
active: active,
orderVehicle: value.orderVehicle,
orderDealer: value.orderDealer,
});
if (data.success) {
onChange({
...value,
orderId: data.data?.orderId!,
});
return true;
} else {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: data?.errMessage || "保存失败",
});
return false;
}
}
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "保存失败",
});
console.error("保存车辆和经销商信息失败:", error);
return false;
}
};
// 供应商信息的保存(基础信息,称重信息,包材信息)
const saveSupplierInfo = async () => {
if (!value || !value.orderId) {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: "保存失败",
});
return false;
}
try {
const { data } = await business.purchaseOrder.savePurchaseOrderStep2({
orderId: value.orderId,
active: active,
orderSupplierList: value.orderSupplierList,
});
if (data.success) {
return true;
} else {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: data?.errMessage || "保存失败",
});
return false;
}
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "保存失败",
});
console.error("保存供应商信息失败:", error);
return false;
}
};
// 人工和辅料等保存
const saveCostInfo = async () => {
if (!value || !value.orderId) {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: "保存失败",
});
return false;
}
const { data } = await business.purchaseOrder.savePurchaseOrderStep3({
orderId: value.orderId,
active: Number(active + 1),
foreman: value.foreman,
// 空箱
orderPackageList: value.orderPackageList,
// 费用
orderCostList: value.orderCostList.filter((item) => item.selected),
orderCostItemList: value.orderCostItemList.filter(
(item) => item.selected,
),
});
if (data.success) {
return true;
} else {
Toast.show("toast", {
icon: "warn",
title: "提示",
content: data?.errMessage || "保存失败",
});
return false;
}
};
const onFinish = async () => {
Dialog.open("dialog", {
title: "预览确认",
content: "即将保存并预览当前采购订单,确定要继续吗?",
confirmText: "确认预览",
cancelText: "取消",
onConfirm: async () => {
// 只保存第六步的人工和辅料信息
const costSuccess = await saveCostInfo();
if (!costSuccess) {
Dialog.close("dialog");
return;
}
Toast.show("toast", {
icon: "success",
title: "提示",
content: "保存成功,正在跳转预览...",
});
// 跳转到预览页面
Taro.redirectTo({
url: buildUrl("/pages/purchase/enter/preview", {
orderId: value.orderId,
}),
});
Dialog.close("dialog");
},
onCancel: () => {
Dialog.close("dialog");
},
});
};
const onAdd = () => {
saveSupplierInfo();
const orderSupplierList = value?.orderSupplierList;
// 获取当前选中的供应商
const selectedIndex = orderSupplierList?.findIndex(
(supplier) => supplier.selected,
);
if (active === 2 && !melonFarmerRefs.current[selectedIndex]?.validate()) {
return;
}
// 在第三步(称重信息)时进行校验
else if (active === 3 && !weighRefs.current[selectedIndex]?.validate()) {
return;
} // 在第四步(包装信息)时进行校验
else if (
active === 4 &&
!orderPackageRefs.current[selectedIndex]?.validate()
) {
return;
}
onChange({
...value,
active: 2,
orderSupplierList: [
...orderSupplierList.map((supplierVO: BusinessAPI.OrderSupplier) => {
supplierVO.selected = false;
return supplierVO;
}),
{
orderSupplierId: generateShortId(),
supplierId: "",
name: "瓜农" + (orderSupplierList.length + 1),
idCard: "",
bankCard: "",
phone: "",
selected: true,
isPaper: orderSupplierList[selectedIndex].isPaper,
orderPackageList: [],
productId: orderSupplierList[selectedIndex]?.productId,
productName: orderSupplierList[selectedIndex]?.productName,
costTemplate: orderSupplierList[selectedIndex]?.costTemplate,
} as any,
],
});
};
// 将校验方法暴露给父组件
useImperativeHandle(ref, () => ({
onAdd,
}));
async function saveDraft() {
Dialog.open("dialog", {
title: "暂存确认",
content: "确定要暂存当前采购订单吗?",
confirmText: "确认暂存",
cancelText: "取消",
onConfirm: async () => {
// 按步骤调用保存接口进行暂存
let success = true;
// 保存第一步车辆和经销商信息
if (active == 1) {
success = await saveVehicleAndDealerInfo();
}
// 保存第二到第五步的供应商信息
if (success && active >= 2 && active <= 5) {
success = await saveSupplierInfo();
}
// 保存第六步的人工和辅料信息
if (success && active >= 6 && active <= 7) {
success = await saveCostInfo();
}
Dialog.close("dialog");
if (success) {
Toast.show("toast", {
icon: "success",
title: "提示",
content: "当前采购订单已暂存成功",
});
Taro.redirectTo({
url: "/pages/purchase/enter/drafts",
});
}
},
onCancel: () => {
Dialog.close("dialog");
},
});
}
if (!active) {
return;
}
return (
<View className={"sticky bottom-0 z-10 bg-white"}>
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
{active > 1 && active <= purchase.steps.length - 1 && (
<View className={"flex-1"}>
<Button
block
type={"default"}
size={"xlarge"}
className="flex-1 bg-gray-200 text-gray-700"
onClick={() => {
if (active > 1) {
setActive(active - 1);
}
}}
>
</Button>
</View>
)}
{active >= 1 && active <= purchase.steps.length - 1 && (
<View className={"flex-1"}>
<Button
block
type={"default"}
size={"xlarge"}
className="flex-1 bg-gray-200 text-gray-700"
onClick={async () => {
await saveDraft();
}}
>
</Button>
</View>
)}
{active < purchase.steps.length - 1 && (
<View className={"flex-1"}>
<Button
block
type={"primary"}
size={"xlarge"}
className="bg-primary flex-1 text-white"
onClick={async () => {
setLoading(true);
// 在第一步(车辆信息)时进行校验
if (active === 1) {
if (vehicleRef.current?.validate()) {
const success = await saveVehicleAndDealerInfo();
if (success) {
setActive(active + 1);
}
}
}
// 在第二步(瓜农信息)时进行校验
else if (active === 2) {
// 获取当前选中的供应商
const selectedIndex = orderSupplierList.findIndex(
(supplier) => supplier.selected,
);
if (
selectedIndex !== -1 &&
melonFarmerRefs.current[selectedIndex]?.validate()
) {
const success = await saveSupplierInfo();
if (success) {
setActive(active + 1);
}
}
}
// 在第三步(称重信息)时进行校验
else if (active === 3) {
// 获取当前选中的供应商
const selectedIndex = orderSupplierList.findIndex(
(supplier) => supplier.selected,
);
if (
selectedIndex !== -1 &&
weighRefs.current[selectedIndex]?.validate()
) {
const success = await saveSupplierInfo();
if (success) {
setActive(active + 1);
}
}
} // 在第四步(包装信息)时进行校验
else if (active === 4) {
// 获取当前选中的供应商
const selectedIndex = orderSupplierList.findIndex(
(supplier) => supplier.selected,
);
if (
selectedIndex !== -1 &&
orderPackageRefs.current[selectedIndex]?.validate()
) {
const success = await saveSupplierInfo();
if (success) {
setActive(active + 1);
}
}
} // 在第五步(票证上传)时进行校验
else if (active === 5) {
const success = await saveSupplierInfo();
if (success) {
setActive(active + 1);
}
} else {
setActive(active + 1);
}
setLoading(false);
}}
>
</Button>
</View>
)}
{active == purchase.steps.length - 1 && (
<>
<View className={"flex-1"}>
<Button
block
type={"primary"}
size={"xlarge"}
className="btn-large bg-primary ml-2 flex-1 text-white"
onClick={async () => {
setLoading(true);
// 第六步(人工辅料费用)时进行校验
if (
orderCostRef.current?.validate() ||
orderCostItemRef.current?.validate()
) {
await onFinish();
}
setLoading(false);
}}
>
</Button>
</View>
</>
)}
</View>
<SafeArea position={"bottom"} />
</View>
);
},
);