- 在MelonFarmer组件中新增supplierCount属性用于判断是否显示拼车选项 - 修改"是否为最后一个瓜农"为"是否要拼车"的逻辑与文案 - 更新多个图标引用,包括新增address-book图标 - 调整输入框样式,增加图标前缀提升用户体验 - 优化称重信息页面的提示文字,使其更清晰易懂 - 增加OrderPackage相关类型定义及转换工具函数 - 更新页面审核和创建流程中的样式与交互逻辑 - 升级iconfont字体文件版本,支持新图标 - 修复部分组件样式问题,如SupplierList底部间距等
545 lines
17 KiB
TypeScript
545 lines
17 KiB
TypeScript
import hocAuth from "@/hocs/auth";
|
|
import { CommonComponent } from "@/types/typings";
|
|
import Taro, { useDidShow } from "@tarojs/taro";
|
|
import { business } from "@/services";
|
|
import { useEffect, useState } from "react";
|
|
import { View } from "@tarojs/components";
|
|
import dayjs from "dayjs";
|
|
import purchaseOrder from "@/constant/purchaseOrder";
|
|
import {
|
|
Button,
|
|
Dialog,
|
|
SafeArea,
|
|
Toast,
|
|
Input,
|
|
} from "@nutui/nutui-react-taro";
|
|
import { formatCurrency } from "@/utils/format";
|
|
import {
|
|
BasicInfoSection,
|
|
CompanyInfoSection,
|
|
CostSummarySection,
|
|
DealerInfoSection,
|
|
EmptyBoxInfoSection,
|
|
LaborInfoSection,
|
|
MarketPriceSection,
|
|
PackageInfoSection,
|
|
PackagingCostSection,
|
|
ProfitCalcSection,
|
|
PurchaseCostInfoSection,
|
|
PurchaseOrderRejectApprove,
|
|
PurchaseOrderRejectFinal,
|
|
PurchaseOrderFinalApprove,
|
|
SupplierInfoSection,
|
|
RebateCalcSection,
|
|
} from "@/components";
|
|
import {
|
|
getMelonCost1,
|
|
getTotalGrossWeight,
|
|
getTotalNetWeight,
|
|
} from "@/utils/calcutePurchaseOrder";
|
|
|
|
const sectionList = {
|
|
// 销售方信息卡片
|
|
supplierInfo: CompanyInfoSection,
|
|
// 下游经销商信息
|
|
dealerInfo: DealerInfoSection,
|
|
// 基础信息
|
|
basicInfo: BasicInfoSection,
|
|
// 瓜农信息
|
|
farmerInfo: SupplierInfoSection,
|
|
// 采购成本
|
|
purchaseCostInfo: PurchaseCostInfoSection,
|
|
// 包装纸箱费
|
|
packageInfo: PackageInfoSection,
|
|
// 空箱费用
|
|
emptyBoxInfo: EmptyBoxInfoSection,
|
|
// 用工信息
|
|
laborInfo: LaborInfoSection,
|
|
// 包装费
|
|
packagingCost: PackagingCostSection,
|
|
// 成本合计
|
|
costSummary: CostSummarySection,
|
|
// 市场报价
|
|
marketPrice: MarketPriceSection,
|
|
// 返点计算
|
|
rebateCalc: RebateCalcSection,
|
|
// 利润计算
|
|
profitCalc: ProfitCalcSection,
|
|
};
|
|
|
|
const sectionConfig = {
|
|
supplierInfo: {
|
|
title: "销售方信息",
|
|
containerClass: "border-l-8 border-l-blue-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
dealerInfo: {
|
|
title: "下游经销商信息",
|
|
containerClass: "border-l-8 border-l-green-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
basicInfo: {
|
|
title: "基础信息",
|
|
containerClass: "border-l-8 border-l-yellow-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
farmerInfo: {
|
|
title: "瓜农信息",
|
|
containerClass: "border-l-8 border-l-purple-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
purchaseCostInfo: {
|
|
title: "采购成本",
|
|
containerClass: "border-l-8 border-l-red-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
packageInfo: {
|
|
title: "包装纸箱费",
|
|
containerClass: "border-l-8 border-l-indigo-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
emptyBoxInfo: {
|
|
title: "空箱费用",
|
|
containerClass: "border-l-8 border-l-pink-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
laborInfo: {
|
|
title: "用工信息",
|
|
containerClass: "border-l-8 border-l-teal-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
packagingCost: {
|
|
title: "包装费",
|
|
containerClass: "border-l-8 border-l-orange-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
costSummary: {
|
|
title: "成本合计",
|
|
containerClass: "border-l-8 border-l-cyan-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
marketPrice: {
|
|
title: "市场报价",
|
|
containerClass: "border-l-8 border-l-lime-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
rebateCalc: {
|
|
title: "返点计算",
|
|
containerClass: "border-l-8 border-l-amber-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
profitCalc: {
|
|
title: "利润计算",
|
|
containerClass: "border-l-8 border-l-emerald-500",
|
|
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
|
},
|
|
};
|
|
|
|
export default hocAuth(function Page(props: CommonComponent) {
|
|
const { router, isInitialized, setIsInitialized, role } = props;
|
|
|
|
const orderId = router.params
|
|
.orderId as BusinessAPI.PurchaseOrderVO["orderId"];
|
|
|
|
const [purchaseOrderVO, setPurchaseOrderVO] =
|
|
useState<BusinessAPI.PurchaseOrderVO>();
|
|
|
|
const [originPrincipal, setOriginPrincipal] = useState("");
|
|
|
|
console.log("purchaseOrderVO-----", purchaseOrderVO);
|
|
|
|
const [collapsedSections, setCollapsedSections] = useState<
|
|
Record<string, boolean>
|
|
>({
|
|
supplierInfo: false,
|
|
dealerInfo: false,
|
|
basicInfo: false,
|
|
farmerInfo: false,
|
|
purchaseCostInfo: false,
|
|
packageInfo: false,
|
|
emptyBoxInfo: false,
|
|
laborInfo: false,
|
|
packagingCost: false,
|
|
costSummary: false,
|
|
marketPrice: false,
|
|
rebateCalc: false,
|
|
profitCalc: false,
|
|
});
|
|
|
|
// 暂存和提交审核的Dialog状态
|
|
const [saveDialogVisible, setSaveDialogVisible] = useState(false);
|
|
const [submitDialogVisible, setSubmitDialogVisible] = useState(false);
|
|
|
|
const toggleSection = (section: string) => {
|
|
setCollapsedSections((prev) => ({
|
|
...prev,
|
|
[section]: !prev[section],
|
|
}));
|
|
};
|
|
|
|
// 暂存操作
|
|
const handleSave = () => {
|
|
setSaveDialogVisible(true);
|
|
};
|
|
|
|
// 确认暂存
|
|
const confirmSave = async () => {
|
|
// 关闭对话框
|
|
setSaveDialogVisible(false);
|
|
|
|
// 这里应该调用暂存API
|
|
console.log("暂存数据:", purchaseOrderVO);
|
|
|
|
const { data } = await business.purchaseOrder.approvePurchaseOrder({
|
|
...purchaseOrderVO!,
|
|
draft: true,
|
|
});
|
|
|
|
if (data.success) {
|
|
Toast.show("toast", {
|
|
icon: "success",
|
|
title: "提示",
|
|
content: "暂存成功",
|
|
});
|
|
// 返回采购单页面
|
|
Taro.switchTab({ url: "/pages/main/purchase/index" });
|
|
}
|
|
};
|
|
|
|
// 提交老板审核操作
|
|
const handleSubmit = () => {
|
|
setSubmitDialogVisible(true);
|
|
};
|
|
|
|
// 确认提交老板审核
|
|
const confirmSubmit = async () => {
|
|
// 关闭对话框
|
|
setSubmitDialogVisible(false);
|
|
|
|
// 表单校验
|
|
const errorMsg = validateForm();
|
|
if (errorMsg) {
|
|
Toast.show("toast", {
|
|
icon: "fail",
|
|
title: "校验失败",
|
|
content: errorMsg,
|
|
});
|
|
return;
|
|
}
|
|
|
|
// 这里应该调用提交审核API
|
|
console.log("提交老板审核:", purchaseOrderVO);
|
|
|
|
const { data } = await business.purchaseOrder.approvePurchaseOrder({
|
|
...purchaseOrderVO!,
|
|
draft: false,
|
|
});
|
|
|
|
if (data.success) {
|
|
Toast.show("toast", {
|
|
icon: "success",
|
|
title: "提示",
|
|
content: "暂存成功",
|
|
});
|
|
// 返回采购单页面
|
|
Taro.switchTab({ url: "/pages/main/purchase/index" });
|
|
}
|
|
};
|
|
|
|
// 表单校验
|
|
const validateForm = () => {
|
|
// 校验销售方
|
|
if (!purchaseOrderVO?.orderCompany?.companyId) {
|
|
return "请选择销售方";
|
|
}
|
|
|
|
// 校验经销商和仓库
|
|
if (
|
|
!purchaseOrderVO?.orderDealer?.dealerId ||
|
|
!purchaseOrderVO?.orderDealer?.warehouseId
|
|
) {
|
|
return "请选择经销商和仓库";
|
|
}
|
|
|
|
// 校验本车次号
|
|
if (!purchaseOrderVO?.orderVehicle?.vehicleNo) {
|
|
return "请输入本车次号";
|
|
}
|
|
|
|
// 校验运费类型
|
|
if (!purchaseOrderVO?.orderVehicle?.priceType) {
|
|
return "请选择运费类型";
|
|
}
|
|
|
|
// 校验市场报价的报价方式
|
|
if (!purchaseOrderVO?.pricingMethod) {
|
|
return "请选择市场报价的报价方式";
|
|
}
|
|
|
|
// 校验市场报价的销售单价
|
|
purchaseOrderVO.orderSupplierList.forEach(
|
|
(supplier: BusinessAPI.OrderSupplier) => {
|
|
if (!supplier.salePrice || supplier.salePrice <= 0) {
|
|
return "请填写市场报价的销售单价";
|
|
}
|
|
},
|
|
);
|
|
|
|
return null;
|
|
};
|
|
|
|
const init = async (orderId: BusinessAPI.PurchaseOrderVO["orderId"]) => {
|
|
const { data } = await business.purchaseOrder.showPurchaseOrder({
|
|
purchaseOrderShowQry: {
|
|
orderId,
|
|
},
|
|
});
|
|
|
|
if (data.success) {
|
|
setPurchaseOrderVO(data.data);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (orderId && !isInitialized) {
|
|
init(orderId).then(() => {
|
|
setIsInitialized(true);
|
|
});
|
|
}
|
|
}, []);
|
|
|
|
useDidShow(() => {
|
|
if (orderId && isInitialized) {
|
|
init(orderId).then();
|
|
}
|
|
});
|
|
|
|
if (!purchaseOrderVO) {
|
|
return;
|
|
}
|
|
|
|
return (
|
|
<View className={"flex flex-col gap-2.5"} id={"purchase-order-audit"}>
|
|
{/* 顶部导航 */}
|
|
<View className="bg-white p-4">
|
|
{/* 展示产地负责人*/}
|
|
<View className="mb-3 flex flex-row items-center gap-3">
|
|
<View className="flex-shrink-0 text-base font-bold text-gray-900">
|
|
产地负责人
|
|
</View>
|
|
|
|
<View
|
|
className={`flex h-12 w-full items-center rounded-lg border-2 border-gray-300 bg-gray-50 px-3`}
|
|
>
|
|
<Input
|
|
type="text"
|
|
disabled={
|
|
role === "boss" ||
|
|
(role === "reviewer" &&
|
|
purchaseOrderVO.state !== "WAITING_AUDIT")
|
|
}
|
|
placeholder="请输入产地负责人姓名"
|
|
value={originPrincipal || purchaseOrderVO.createdByName}
|
|
onChange={(value) => setOriginPrincipal(value)}
|
|
onBlur={() => {
|
|
// 更新采购订单中的产地负责人
|
|
setPurchaseOrderVO((prev) => ({
|
|
...prev!,
|
|
originPrincipal: originPrincipal,
|
|
}));
|
|
}}
|
|
className="w-full bg-transparent"
|
|
/>
|
|
</View>
|
|
</View>
|
|
|
|
<View className="mb-2 rounded-lg bg-blue-50 p-3 text-lg font-bold text-gray-800">
|
|
{`第${purchaseOrderVO?.orderVehicle?.vehicleNo || "-"}车 - ${purchaseOrderVO?.orderVehicle.origin} 至 ${purchaseOrderVO?.orderVehicle.destination}`}
|
|
</View>
|
|
{purchaseOrderVO?.orderDealer && (
|
|
<>
|
|
<View className="text-neutral-darker mb-1 text-sm font-medium">
|
|
经销商名称: {purchaseOrderVO?.orderDealer?.shortName}
|
|
</View>
|
|
<View className="text-neutral-darker text-sm font-medium">
|
|
经销商公司: {purchaseOrderVO?.orderDealer?.companyName}
|
|
</View>
|
|
</>
|
|
)}
|
|
</View>
|
|
|
|
{/* 状态栏 */}
|
|
<View className="flex flex-row items-center justify-between rounded-lg bg-white p-4 shadow-sm">
|
|
<View className="inline-block rounded-md border-1 bg-gradient-to-r from-amber-500 to-orange-500 px-4 py-2 text-sm font-bold text-white shadow">
|
|
{
|
|
purchaseOrder.stateList.find(
|
|
(item) => item.value === purchaseOrderVO?.state,
|
|
)?.title
|
|
}
|
|
</View>
|
|
<View className="text-neutral-darker text-right text-sm">
|
|
<View>
|
|
创建时间:{" "}
|
|
{dayjs(purchaseOrderVO?.createdAt).format("YYYY-MM-DD HH:mm")}
|
|
</View>
|
|
<View className="font-medium">
|
|
车牌号: {purchaseOrderVO?.orderVehicle.plate}
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
{/* 关键指标 */}
|
|
<View className="grid grid-cols-2 gap-3 rounded-lg bg-white p-4 shadow-sm">
|
|
<View className="rounded-lg border border-blue-200 bg-gradient-to-br from-blue-50 to-blue-100 p-3 text-center">
|
|
<View className="mb-1 text-lg font-bold text-blue-800">
|
|
{purchaseOrderVO?.orderSupplierList.length}
|
|
</View>
|
|
<View className="text-sm font-medium text-blue-600">关联瓜农</View>
|
|
</View>
|
|
<View className="rounded-lg border border-green-200 bg-gradient-to-br from-green-50 to-green-100 p-3 text-center">
|
|
<View className="mb-1 text-lg font-bold text-green-800">
|
|
{formatCurrency(getTotalGrossWeight(purchaseOrderVO))} 斤
|
|
</View>
|
|
<View className="text-sm font-medium text-green-600">总毛重</View>
|
|
</View>
|
|
<View className="rounded-lg border border-purple-200 bg-gradient-to-br from-purple-50 to-purple-100 p-3 text-center">
|
|
<View className="mb-1 text-lg font-bold text-purple-800">
|
|
{formatCurrency(getTotalNetWeight(purchaseOrderVO))} 斤
|
|
</View>
|
|
<View className="text-sm font-medium text-purple-600">总净重</View>
|
|
</View>
|
|
<View className="rounded-lg border border-amber-200 bg-gradient-to-br from-amber-50 to-amber-100 p-3 text-center">
|
|
<View className="mb-1 text-lg font-bold text-amber-800">
|
|
{formatCurrency(getMelonCost1(purchaseOrderVO))}
|
|
</View>
|
|
<View className="text-sm font-medium text-amber-600">
|
|
西瓜采购总金额
|
|
</View>
|
|
</View>
|
|
</View>
|
|
|
|
{/* 循环渲染各部分内容 */}
|
|
{Object.keys(sectionList).map((sectionKey) => {
|
|
const SectionComponent = sectionList[sectionKey];
|
|
const config = sectionConfig[sectionKey];
|
|
const isCollapsed = collapsedSections[sectionKey];
|
|
|
|
return (
|
|
<View className="overflow-hidden bg-white" key={sectionKey}>
|
|
<View
|
|
className={`z-10 flex items-center justify-between p-4 shadow-sm ${config.containerClass}`}
|
|
onClick={() => toggleSection(sectionKey)}
|
|
>
|
|
<View className="text-base font-bold text-gray-800">
|
|
{config.title}
|
|
</View>
|
|
<View className="text-neutral-darker text-lg">
|
|
{isCollapsed ? "▲" : "▼"}
|
|
</View>
|
|
</View>
|
|
{!isCollapsed && (
|
|
<View className={config.contentClass}>
|
|
<SectionComponent
|
|
purchaseOrderVO={purchaseOrderVO}
|
|
onChange={setPurchaseOrderVO}
|
|
readOnly={
|
|
role === "boss" ||
|
|
(role === "reviewer" &&
|
|
purchaseOrderVO.state !== "WAITING_AUDIT")
|
|
}
|
|
/>
|
|
</View>
|
|
)}
|
|
</View>
|
|
);
|
|
})}
|
|
|
|
{/* 按钮操作 */}
|
|
<View className={"sticky bottom-0 z-10 bg-white"} id={"bottomBar"}>
|
|
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
|
|
{role === "reviewer" && purchaseOrderVO.state === "WAITING_AUDIT" && (
|
|
<>
|
|
<View className={"flex-1"}>
|
|
<PurchaseOrderRejectApprove
|
|
purchaseOrderVO={purchaseOrderVO}
|
|
size={"xlarge"}
|
|
onFinish={() => {
|
|
// 返回首页
|
|
Taro.switchTab({ url: "/pages/main/purchase/index" });
|
|
}}
|
|
/>
|
|
</View>
|
|
<View className={"flex-1"}>
|
|
<Button
|
|
block
|
|
type={"default"}
|
|
size={"xlarge"}
|
|
className="bg-gray-200 text-gray-700"
|
|
onClick={handleSave}
|
|
>
|
|
暂存
|
|
</Button>
|
|
</View>
|
|
<View className={"flex-1"}>
|
|
<Button
|
|
block
|
|
type={"primary"}
|
|
size={"xlarge"}
|
|
className="bg-primary text-white"
|
|
onClick={handleSubmit}
|
|
>
|
|
提交老板审核
|
|
</Button>
|
|
</View>
|
|
</>
|
|
)}
|
|
{role === "boss" &&
|
|
purchaseOrderVO.state === "WAITING_BOSS_APPROVE" && (
|
|
<>
|
|
<View className={"flex-1"}>
|
|
<PurchaseOrderRejectFinal
|
|
purchaseOrderVO={purchaseOrderVO}
|
|
size={"xlarge"}
|
|
onFinish={() => {
|
|
// 返回首页
|
|
Taro.switchTab({ url: "/pages/main/purchase/index" });
|
|
}}
|
|
/>
|
|
</View>
|
|
<View className={"flex-1"}>
|
|
<PurchaseOrderFinalApprove
|
|
purchaseOrderVO={purchaseOrderVO}
|
|
size={"xlarge"}
|
|
onFinish={() => {
|
|
// 返回首页
|
|
Taro.switchTab({ url: "/pages/main/purchase/index" });
|
|
}}
|
|
/>
|
|
</View>
|
|
</>
|
|
)}
|
|
</View>
|
|
<SafeArea position={"bottom"} />
|
|
</View>
|
|
|
|
{/* 暂存确认对话框 */}
|
|
<Dialog
|
|
visible={saveDialogVisible}
|
|
title="确认暂存"
|
|
content="确定要暂存当前采购订单吗?"
|
|
onCancel={() => setSaveDialogVisible(false)}
|
|
onConfirm={confirmSave}
|
|
/>
|
|
|
|
{/* 提交审核确认对话框 */}
|
|
<Dialog
|
|
visible={submitDialogVisible}
|
|
title="提交审核"
|
|
content="确定要提交给老板审核吗?"
|
|
onCancel={() => setSubmitDialogVisible(false)}
|
|
onConfirm={confirmSubmit}
|
|
/>
|
|
</View>
|
|
);
|
|
});
|