feat(purchase): 新增草帘费用项功能并优化订单创建流程

- 在OrderVehicle模块中新增草帘费用项的添加与移除逻辑
- 根据选中状态动态更新orderCostList中的草帘费用项
- 优化PurchaseOrderWithdrawReview组件按钮点击事件处理
- 调整OrderPackage组件品牌选择过滤逻辑及数据结构
- 完善Weigh组件弹窗交互与样式布局
- 修复PackagingCostSection组件默认计提费用配置
- 升级delivery文档页面otherFees模块实时获取最新费用项目
- 优化delivery页面预览内容展示格式和数据填充逻辑
- 更新create页面传递orderCostList至子组件确保数据同步
- 引入generateShortId工具用于生成唯一订单费用ID
This commit is contained in:
shenyifei 2025-11-17 18:55:39 +08:00
parent cbde9caac1
commit 323fe4c83d
12 changed files with 582 additions and 236 deletions

View File

@ -14,6 +14,10 @@ export default {
process.env.TARO_ENV === "h5"
? '"/api"'
: '"https://api.erp.qilincloud168.com"',
"process.env.TARO_POSTER_DOMAIN":
process.env.TARO_ENV === "h5"
? '""'
: '"https://poster.qilincloud168.com"',
},
mini: {
miniCssExtractPluginOption: {
@ -23,6 +27,11 @@ export default {
h5: {
devServer: {
proxy: {
"/api/v1": {
target: JSON.parse('"https://poster.qilincloud168.com"'),
pathRewrite: { "^/api": "/api" },
changeOrigin: true,
},
"/api/": {
target: JSON.parse('"https://api.erp.qilincloud168.com"'),
pathRewrite: { "^/api": "/" },

View File

@ -7,7 +7,9 @@ interface IPurchaseOrderWithdrawReviewProps {
onFinish?: () => void;
}
export default function PurchaseOrderWithdrawReview(props: IPurchaseOrderWithdrawReviewProps) {
export default function PurchaseOrderWithdrawReview(
props: IPurchaseOrderWithdrawReviewProps,
) {
const { purchaseOrderVO, size = "normal", onFinish } = props;
const onWithdraw = async () => {
@ -24,7 +26,8 @@ export default function PurchaseOrderWithdrawReview(props: IPurchaseOrderWithdra
let errMessage = "";
try {
if (purchaseOrderVO.orderId) {
const { data } = await business.purchaseOrder.withdrawReviewPurchaseOrder({
const { data } =
await business.purchaseOrder.withdrawReviewPurchaseOrder({
orderId: purchaseOrderVO.orderId,
});
@ -65,7 +68,6 @@ export default function PurchaseOrderWithdrawReview(props: IPurchaseOrderWithdra
block
type={"danger"}
size={size}
className="btn-large bg-gray-200 ml-2 flex-1 text-gray-700"
onClick={async (e) => {
Dialog.open("dialog", {
title: "撤回提审提醒",

View File

@ -41,8 +41,6 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
const orderPackageList = value.orderPackageList || [];
setOrderPackageList(orderPackageList);
console.log("orderPackageList.length", orderPackageList.length, value)
if (orderPackageList.length > 0) {
// 根据当前供应商确定需要检查的纸箱类型
let requiredTypes: string[] = [];
@ -56,8 +54,6 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
requiredTypes = ["OWN", "EXTRA_USED"];
}
console.log("requiredTypes", requiredTypes)
requiredTypes.map((type) => {
setPackageTypeEnabled((prev) => {
return {
@ -225,6 +221,7 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
boxBrandId: boxBrand.brandId,
boxBrandName: boxBrand.name,
boxBrandImage: boxBrand.image,
boxBrandType: boxBrand.type,
boxCategoryList:
boxCategoryList
.map((boxCategory) => {
@ -797,10 +794,25 @@ export default forwardRef<OrderPackageRef, IOrderPackageProps>(
<View className="mb-2 text-sm text-gray-600"></View>
<ScrollView className="mb-2.5" scrollX>
<View className="flex w-fit flex-row gap-2.5">
{boxBrandList?.map((boxBrand) => (
{boxBrandList
?.filter((item) => {
console.log("item: ", item);
console.log("boxType: ", boxType);
if (boxType === "OWN") {
return item.boxBrandType === "FARMER_BOX";
} else {
return (
item.boxBrandType === "THIRD_PARTY_BOX" ||
item.boxBrandType === "OUR_BOX"
);
}
})
?.map((boxBrand) => (
<View
key={boxBrand.id}
className={"flex flex-col items-center justify-center"}
className={
"flex flex-col items-center justify-center"
}
onClick={() => handleBatchBrandSelect(boxBrand)}
>
<View

View File

@ -15,12 +15,16 @@ import dayjs from "dayjs";
import Taro from "@tarojs/taro";
import { business } from "@/services";
import { validatePrice as validatePrice1 } from "@/utils/format";
import { generateShortId } from "@/utils/generateShortId";
import { CostItem } from "@/types/typings";
interface IOrderVehicleProps {
orderVehicle: BusinessAPI.OrderVehicle;
setOrderVehicle: (orderVehicle: BusinessAPI.OrderVehicle) => void;
orderDealer: BusinessAPI.OrderDealer;
setOrderDealer: (orderDealer: BusinessAPI.OrderDealer) => void;
orderCostList: CostItem[];
setOrderCostList: (orderCostList: CostItem[]) => void;
}
export interface OrderVehicleRef {
@ -29,8 +33,14 @@ export interface OrderVehicleRef {
export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
function OrderVehicle(props, ref) {
const { orderVehicle, setOrderVehicle, setOrderDealer, orderDealer } =
props;
const {
orderVehicle,
setOrderVehicle,
setOrderDealer,
orderDealer,
orderCostList,
setOrderCostList,
} = props;
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
const [openStrawCurtain, setOpenStrawCurtain] = useState<boolean>(false);
@ -56,6 +66,28 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
const startDate = new Date(currentYear, 0, 1); // 当年第一天
const endDate = new Date(); // 今天
// 费用项目列表
const [costItems, setCostItems] = useState<BusinessAPI.CostItemVO[]>([]);
// 获取费用项目列表
useEffect(() => {
const fetchCostItems = async () => {
try {
const { data } = await business.costItem.listCostItem({
costItemListQry: {
status: true,
showInEntry: true,
},
});
setCostItems(data.data || []);
} catch (error) {
console.error("获取费用项目列表失败:", error);
}
};
fetchCostItems();
}, []);
// 当desc改变时更新车辆信息中的时间
useEffect(() => {
if (desc) {
@ -394,6 +426,17 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
}
};
const getCostItemByName = (name: string): BusinessAPI.CostItemVO => {
return costItems?.find(
(item) => item.name === name && item.costType === "PRODUCTION_ADVANCE",
)!;
};
const getOrderCostByName = (name: string): CostItem => {
return orderCostList?.find(
(item) => item.name === name && item.costType === "PRODUCTION_ADVANCE",
)!;
};
const handleStrawCurtainPriceChange = (value: string) => {
const numValue = validatePrice1(value);
if (numValue !== undefined) {
@ -402,6 +445,38 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
strawCurtainPrice: numValue as any,
});
const strawCurtainCostItem = getOrderCostByName("草帘");
if (!strawCurtainCostItem) {
Toast.show("toast", {
icon: "fail",
content: "请联系管理员,先添加草帘费用项",
});
return;
}
// 创建草帘费用项
setOrderCostList([
...(orderCostList.filter(
(item) =>
!(item.name === "草帘" && item.costType === "PRODUCTION_ADVANCE"),
) || []),
{
orderCostId: generateShortId(),
itemId: strawCurtainCostItem?.itemId,
name: strawCurtainCostItem?.name,
price: numValue as number,
unit: strawCurtainCostItem?.unit,
count: 1,
costType: "PRODUCTION_ADVANCE",
payerType: "US",
requireQuantityAndPrice:
strawCurtainCostItem?.requireQuantityAndPrice || false,
selected: true,
},
]);
// 校验草帘费用并更新错误状态
const isValid = validatePrice(value);
setStrawCurtainPriceError(!isValid && value !== "");
@ -744,8 +819,56 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
</View>
<Checkbox
className={"flex flex-row items-center"}
checked={openStrawCurtain}
onChange={(checked) => {
if (checked) {
// 从费用项目列表中查找草帘费用项
const strawCurtainCostItem = getCostItemByName("草帘");
if (!strawCurtainCostItem) {
Toast.show("toast", {
icon: "fail",
content: "请联系管理员,先添加草帘费用项",
duration: 3000,
});
return;
}
// 创建草帘费用项
setOrderCostList([
...(orderCostList || []),
{
orderCostId: generateShortId(),
itemId: strawCurtainCostItem?.itemId,
name: strawCurtainCostItem?.name,
price: 0,
unit: strawCurtainCostItem?.unit,
count: 1,
costType: "PRODUCTION_ADVANCE",
payerType: "US",
requireQuantityAndPrice:
strawCurtainCostItem?.requireQuantityAndPrice ||
false,
selected: true,
},
]);
} else {
// 如果关闭了草帘选项,则移除草帘费用项
setOrderCostList(
orderCostList?.filter(
(item) =>
item.costType === "PRODUCTION_ADVANCE" &&
item.name === "草帘",
),
);
}
setOpenStrawCurtain(checked);
setOrderVehicle({
...orderVehicle,
openStrawCurtain: checked,
});
}}
>
<View className={"text-sm font-normal text-[#000000]"}>

View File

@ -1,11 +1,13 @@
import { View } from "@tarojs/components";
import {
Button,
Input,
Popup,
Radio,
SafeArea,
Toast,
Uploader,
UploaderFileItem,
Popup,
} from "@nutui/nutui-react-taro";
import { Icon } from "@/components";
import { SupplierVO } from "@/types/typings";
@ -324,15 +326,13 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
visible={productPopupVisible}
position="bottom"
title="请选择具体品种"
description={"请选择具体品种,选择其他时请注明"}
onClose={() => setProductPopupVisible(false)}
round
closeable
>
<View className="p-4">
<View id="sub-options" className="slide-in mt-3">
<View className="mb-3 text-sm font-medium text-gray-500">
</View>
<View className={"flex flex-col gap-2.5 p-2.5"}>
<View className="flex flex-col gap-2.5">
<View className="grid grid-cols-2 gap-2">
{productList.map((product) => (
<View
@ -353,7 +353,6 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
))}
</View>
{selectedProduct === "其他(请注明)" && (
<View className="mt-4">
<View
className={`flex h-10 w-full items-center rounded-md ${selectedProduct === "其他(请注明)" && customProduct ? "border-primary border-4" : "border-4 border-gray-300"}`}
>
@ -366,21 +365,29 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
}}
/>
</View>
</View>
)}
<View className="mt-6 flex gap-3">
<View
className="border-primary text-primary flex-1 cursor-pointer rounded-md border py-3 text-center"
</View>
<View className={"flex w-full flex-row gap-2.5 bg-white"}>
<View className={"flex-1"}>
<Button
size="xlarge"
block
type="default"
onClick={() => {
setProductPopupVisible(false);
setSelectedProduct("");
setCustomProduct("");
}}
>
</Button>
</View>
<View
className="bg-primary flex-1 cursor-pointer rounded-md py-3 text-center text-white"
<View className={"flex-1"}>
<Button
size="xlarge"
block
type="primary"
onClick={() => {
let finalProduct = "";
if (selectedProduct === "其他(请注明)") {
@ -427,9 +434,10 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
}}
>
</Button>
</View>
</View>
</View>
<SafeArea position={"bottom"} />
</View>
</Popup>
{isFirst && (

View File

@ -135,6 +135,7 @@ export default function PackagingCostSection(props: {
count: 1,
unit: "项",
payerType: "US",
requireQuantityAndPrice: false,
};
// 更新purchaseOrderVO添加默认计提费

View File

@ -16,10 +16,59 @@ import {
import shipOrder from "@/constant/shipOrder";
import Taro from "@tarojs/taro";
import classNames from "classnames";
import { business } from "@/services";
import { business, poster } from "@/services";
import dayjs from "dayjs";
import buildUrl from "@/utils/buildUrl";
// 特殊处理:其他费用要实时获取费用项目
const updateOtherFeesModule = async (
module: any,
shipOrderVO: BusinessAPI.ShipOrderVO,
) => {
const {
data: { data },
} = await business.costItem.listCostItem({
costItemListQry: {
status: true,
},
});
const costItems =
data?.filter((item) => item.costType !== "HUMAN_COST") || [];
console.log("module", module);
return {
...module,
config: {
...module.config,
feeItems: shipOrderVO.orderCostList?.filter(
(item) => item.costType !== "HUMAN_COST",
),
feeLabels: costItems.reduce((acc: any, item: any) => {
acc[item.itemId] = item.name;
return acc;
}, {}),
},
schemas: [
{
title: "显示配置",
valueType: "group",
columns: [
{
dataIndex: "feeItems",
title: "显示费用项目",
valueType: "checkbox",
valueEnum: costItems.reduce((acc: any, item: any) => {
acc[item.itemId] = item.name;
return acc;
}, {}),
},
],
},
],
};
};
export default hocAuth(function Page(props: CommonComponent) {
const { router, setLoading } = props;
const shipOrderId = router.params
@ -93,7 +142,8 @@ export default hocAuth(function Page(props: CommonComponent) {
},
});
setDeliveryTemplate(data.data?.deliveryTemplate!);
const deliveryTemplate = data.data?.deliveryTemplate!;
setDeliveryTemplate(deliveryTemplate);
}
setLoading(false);
};
@ -104,13 +154,25 @@ export default hocAuth(function Page(props: CommonComponent) {
}
}, [shipOrderId]);
useEffect(() => {
if (deliveryTemplate && shipOrderVO) {
const refresh = async (
deliveryTemplate: string,
shipOrderVO: BusinessAPI.ShipOrderVO,
) => {
const template = JSON.parse(deliveryTemplate);
// 将 shipOrderVO 转换为 examples 的数据格式,然后再替换 moduleList 里面的 config 数据
const convertedData = convertShipOrderVOToExamplesFormat(shipOrderVO);
const updatedTemplate = updateTemplateConfig(template, convertedData);
const updatedTemplate = await updateTemplateConfig(
template,
convertedData,
shipOrderVO,
);
console.log("updatedTemplate", updatedTemplate);
setModuleList(updatedTemplate);
};
useEffect(() => {
if (deliveryTemplate && shipOrderVO) {
refresh(deliveryTemplate, shipOrderVO).then();
}
}, [shipOrderVO, deliveryTemplate]);
@ -170,36 +232,46 @@ export default hocAuth(function Page(props: CommonComponent) {
strawMatDebt: shipOrderVO.strawMatDebt?.toString() || "",
remarks: shipOrderVO.remark || "",
},
otherFees: {
trademark: shipOrderVO.trademarkFee?.toString() || "",
labor: shipOrderVO.laborFee?.toString() || "",
paperBox: shipOrderVO.cartonFee?.toString() || "",
fee: shipOrderVO.provisionFee?.toString() || "",
codingFee: shipOrderVO.codingFee?.toString() || "",
},
otherFees: {},
totalAmount: {
amount: shipOrderVO.totalAmount?.toString() || "",
farmer: shipOrderVO.farmerInfo || "",
},
otherInfo: {
origin: "",
supplier: "",
departureTime: "",
arrivalTime: "",
productName: "",
data: shipOrderVO.shipOrderItemList,
driverPhone: shipOrderVO?.driverPhone || "",
licensePlate: shipOrderVO.licensePlate || "",
accountCompany: shipOrderVO.companyName || "",
vehicleNumber: `${shipOrderVO.vehicleNo || ""}`,
destination: shipOrderVO.receivingAddress || "",
shippingFrom: shipOrderVO.shippingAddress || "",
estimatedArrivalTime: shipOrderVO.estimatedArrivalDate
? dayjs(shipOrderVO?.estimatedArrivalDate).format("YYYY年MM月DD日")
: "1",
},
};
};
// 更新模板配置
const updateTemplateConfig = (template: any[], data: any) => {
return template.map((module: any) => {
const newModule = { ...module };
const updateTemplateConfig = async (
template: any[],
data: any,
shipOrderVO: BusinessAPI.ShipOrderVO,
) => {
let templateList: any[] = [];
template.map(async (module: any) => {
let newModule = { ...module };
if (data[module.type]) {
newModule.config = { ...module.config, ...data[module.type] };
}
return newModule;
// 特殊处理: otherFees 要更新为最新的数据
if (module.type === "otherFees") {
newModule = await updateOtherFeesModule(module, shipOrderVO);
}
templateList.push(newModule);
});
return templateList;
};
// 渲染内容配置表单字段
@ -759,7 +831,7 @@ export default hocAuth(function Page(props: CommonComponent) {
// 将预览内容转换为HTML字符串的函数
const generateHtmlString = () => {
let htmlString = `
<style> @page {size: 210mm 297mm;margin: 0;padding: 0;}* {outline: none;box-sizing: border-box;margin: 0;padding: 0;border: 0 solid;}body {background-color: #fff;color: #4d4d4d;font-size: 14px;font-style: normal;box-sizing: border-box;}.page-wrap {width: 210mm;min-height: 297mm;margin: 0 auto;}.page-content {position: relative;box-sizing: border-box;width: 100%;height: 100%;padding: 20mm 10mm 0;display: flex;flex-direction: column;gap: 2mm;}@media print {.print-controls {display: none !important;}body {padding: 0;margin: 0;}}.print-module {margin-bottom: 15px;text-align: center;}.print-controls {position: fixed;top: 10px;right: 10px;z-index: 9999;}.print-button,.close-button {padding: 8px 16px;margin-left: 10px;cursor: pointer;border: 1px solid #d9d9d9;border-radius: 4px;}.print-button {background-color: #1890ff;color: white;}.close-button {background-color: #fff;color: #000;}.preview {width: 19cm;div {height: 0.7cm;}}.table-border {border: 2px solid #000;}.table-border>div {border-bottom: 1px solid #000;}.table-border>div>div {border-right: 1px solid #000;}.table-border>div>div:last-child {border-right: none;}.table-border>div:last-child {border-bottom: none;}.col-span-1 {grid-column: span 1 / span 1;}.col-span-2 {grid-column: span 2 / span 2;}.col-span-3 {grid-column: span 3 / span 3;}.col-span-6 {grid-column: span 6 / span 6;}.col-span-8 {grid-column: span 8 / span 8;}.flex {display: flex;}.items-center {align-items: center;}.grid {display: grid;}.w-full {width: 100%;}.grid-cols-1 {grid-template-columns: repeat(1, minmax(0, 1fr));}.grid-cols-2 {grid-template-columns: repeat(2, minmax(0, 1fr));}.grid-cols-3 {grid-template-columns: repeat(3, minmax(0, 1fr));}.grid-cols-4 {grid-template-columns: repeat(4, minmax(0, 1fr));}.grid-cols-5 {grid-template-columns: repeat(5, minmax(0, 1fr));}.grid-cols-6 {grid-template-columns: repeat(6, minmax(0, 1fr));}.grid-cols-7 {grid-template-columns: repeat(7, minmax(0, 1fr));}.grid-cols-8 {grid-template-columns: repeat(8, minmax(0, 1fr));}.items-end {align-items: flex-end;}.justify-center {justify-content: center;}.border-t-0 {border-top-width: 0px;}.border-b {border-bottom-width: 1px;}.border-black {border-color: #000000;}.bg-white {background-color: #ffffff;}.text-2xl {font-size: 24px;line-height: 1;}.text-base {font-size: 16px;line-height: 1;}.text-lg {font-size: 18px;line-height: 1;}.font-bold {font-weight: bold;}.preview {width: 19cm;div {height: 0.69cm;}}.table-border {border: 2px solid #000;}.table-border>div {border-bottom: 1px solid #000;}.table-border>div>div {border-right: 1px solid #000;}.table-border>div>div:last-child {border-right: none;}.table-border>div:last-child {border-bottom: none;} </style>
<style> @page {size: 210mm 297mm;margin: 0;padding: 0;}* {outline: none;box-sizing: border-box;margin: 0;padding: 0;border: 0 solid;}body {background-color: #fff;color: #4d4d4d;font-size: 14px;font-style: normal;box-sizing: border-box;}.page-wrap {width: 210mm;min-height: 297mm;margin: 0 auto;}.page-content {position: relative;box-sizing: border-box;width: 100%;height: 100%;padding: 20mm 10mm 0;display: flex;flex-direction: column;gap: 2mm;}@media print {.print-controls {display: none !important;}body {padding: 0;margin: 0;}}.print-module {margin-bottom: 15px;text-align: center;}.print-controls {position: fixed;top: 10px;right: 10px;z-index: 9999;}.print-button,.close-button {padding: 8px 16px;margin-left: 10px;cursor: pointer;border: 1px solid #d9d9d9;border-radius: 4px;}.print-button {background-color: #1890ff;color: white;}.close-button {background-color: #fff;color: #000;}.preview {width: 19cm;div {height: 0.7cm;}}.table-border {border: 2px solid #000;}.table-border>div {border-bottom: 1px solid #000;}.table-border>div>div {border-right: 1px solid #000;}.table-border>div>div:last-child {border-right: none;}.table-border>div:last-child {border-bottom: none;}.col-span-1 {grid-column: span 1 / span 1;}.col-span-2 {grid-column: span 2 / span 2;}.col-span-3 {grid-column: span 3 / span 3;}.col-span-6 {grid-column: span 6 / span 6;}.col-span-8 {grid-column: span 8 / span 8;}.flex {display: flex;}.items-center {align-items: center;}.grid {display: grid;}.w-full {width: 100%;}.grid-cols-1 {grid-template-columns: repeat(1, minmax(0, 1fr));}.grid-cols-2 {grid-template-columns: repeat(2, minmax(0, 1fr));}.grid-cols-3 {grid-template-columns: repeat(3, minmax(0, 1fr));}.grid-cols-4 {grid-template-columns: repeat(4, minmax(0, 1fr));}.grid-cols-5 {grid-template-columns: repeat(5, minmax(0, 1fr));}.grid-cols-6 {grid-template-columns: repeat(6, minmax(0, 1fr));}.grid-cols-7 {grid-template-columns: repeat(7, minmax(0, 1fr));}.grid-cols-8 {grid-template-columns: repeat(8, minmax(0, 1fr));}.items-end {align-items: flex-end;}.justify-center {justify-content: center;}.border-t-0 {border-top-width: 0px;}.border-b {border-bottom-width: 1px;}.border-black {border-color: #000000;}.bg-white {background-color: #ffffff;}.text-2xl {font-size: 24px;line-height: 1;}.text-base {font-size: 16px;line-height: 1;}.text-lg {font-size: 18px;line-height: 1;}.font-bold {font-weight: bold;}.preview {width: 19cm;div {height: 0.69cm;}}.table-border {border: 2px solid #000;}.table-border>div {border-bottom: 1px solid #000;}.table-border>div>div {border-right: 1px solid #000;}.table-border>div>div:last-child {border-right: none;}.table-border>div:last-child {border-bottom: none;}.p-2 {padding:8px}</style>
<div class="page-wrap">
<div class="page-content">
`;
@ -1229,26 +1301,139 @@ export default hocAuth(function Page(props: CommonComponent) {
if (module.type === "otherInfo") {
htmlString += `
<div class="preview grid w-full grid-cols-8 gap-0 text-base">
<div class="col-span-1 flex items-end justify-center">:</div>
<div class="col-span-3 flex items-end justify-center border-b border-black">
${config.origin || ""}
<div class="table-border">
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">:</div>
<div class="col-span-2 p-2 text-left">
${config.vehicleNumber}
</div>
<div class="col-span-1 flex items-end justify-center">:</div>
<div class="col-span-3 flex items-end justify-center border-b border-black">
${config.supplier || ""}
</div>
<div class="col-span-1 flex items-end justify-center">:</div>
<div class="col-span-3 flex items-end justify-center border-b border-black">
${config.departureTime || ""}
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-1 flex items-end justify-center">:</div>
<div class="col-span-3 flex items-end justify-center border-b border-black">
${config.arrivalTime || ""}
<div class="col-span-2 p-2 text-left">
${config.destination}
</div>
</div>
`;
if (config.showShippingFrom) {
htmlString += `
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
</div>
<div class="col-span-2 p-2 text-left">
${config.shippingFrom}
</div>
</div>
`;
}
htmlString += `<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-2 p-2 text-left">
${config.accountCompany}
</div>
</div>
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-2 p-2 text-left">
${config.date}
</div>
</div>
`;
if (config.showEstimatedArrivalTime) {
htmlString += `<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-2 p-2 text-left">
${config.estimatedArrivalTime}
</div>
</div>
`;
}
if (config.data) {
config.data?.forEach((item: any) => {
if (config.showGrade) {
htmlString += `
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-2 p-2 text-left">
${item.watermelonGrade}
</div>
</div>
`;
}
htmlString += `
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-2 p-2 text-left">
</div>
</div>
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
</div>
<div class="col-span-2 p-2 text-left">
${item.unitPrice}
${config.unitPriceUnit === "1" ? "元/斤" : "元/公斤"}
</div>
</div>
`;
});
}
htmlString += `
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
</div>
<div class="p-2 text-left">
${config.data?.reduce(
(acc: any, cur: any) => acc + cur.grossWeight,
0,
)}
</div>
<div class="p-2 text-left"></div>
</div>
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold"></div>
<div class="p-2 text-left">
${config.data?.reduce(
(acc: any, cur: any) => acc + cur.boxCount,
0,
)}
</div>
<div class="p-2 text-left"></div>
</div>
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">:</div>
<div class="col-span-2 p-2 text-left">
${config.licensePlate}
</div>
</div>
<div class="grid w-full grid-cols-3 gap-0 text-base">
<div class="p-2 text-left font-bold">
:
</div>
<div class="col-span-2 p-2 text-left">
${config.driverPhone}
</div>
<div class="col-span-1 flex items-end justify-center">:</div>
<div class="col-span-7 flex items-end justify-center border-b border-black">
${config.productName || ""}
</div>
</div>
`;
@ -1262,23 +1447,16 @@ export default hocAuth(function Page(props: CommonComponent) {
// 截图预览内容
const capturePreview = async () => {
// 请求 poster.qilincloud168.com/api/v1/pdfs 接口 请求参数是 html 内容 的json 格式响应结果为
// 调用API生成PDF
const { data } = await Taro.request({
url: "https://poster.qilincloud168.com/api/v1/pdf",
method: "POST",
header: {
"content-type": "application/json",
},
data: {
console.log("generateHtmlString", generateHtmlString());
const { data } = await poster.pdf.postApiV1Pdf({
html: generateHtmlString(),
},
});
// 存储 至 shipOrder previewUrl
if (shipOrderVO) {
let formData: BusinessAPI.ShipOrderGenerateDocumentCmd = {
shipOrderId: shipOrderVO?.shipOrderId,
shipDocument: data.path,
shipDocument: data?.data?.path,
};
// 检查各模块中的必填字段是否已填写
for (const module of moduleList) {
@ -1320,8 +1498,8 @@ export default hocAuth(function Page(props: CommonComponent) {
business.shipOrder.generateDocumentShipOrder(formData).then();
}
if (data && data.path) {
setShipDocument(data.path);
if (data && data?.data?.path) {
setShipDocument(data?.data?.path);
}
};
@ -2153,10 +2331,10 @@ export default hocAuth(function Page(props: CommonComponent) {
{config.feeItems?.map((feeType: any) => (
<>
<View className="col-span-1 flex items-end justify-center">
{config.feeLabels[feeType]}
{config.feeLabels[feeType.itemId]}
</View>
<View className="col-span-1 flex items-end justify-center border-b border-black">
{config[feeType]}
{feeType.count * feeType.price}
</View>
</>
))}
@ -2201,41 +2379,128 @@ export default hocAuth(function Page(props: CommonComponent) {
if (module.type === "otherInfo") {
return (
<View
key={module.id}
className={
"preview grid w-full grid-cols-8 gap-0 text-base"
}
>
<View className="col-span-1 flex items-end justify-center">
:
<View key={module.id} className={"table-border"}>
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">:</View>
<View className="col-span-2 p-2 text-left">
{config.vehicleNumber}
</View>
<View className="col-span-3 flex items-end justify-center border-b border-black">
{config.origin}
</View>
<View className="col-span-1 flex items-end justify-center">
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-2 p-2 text-left">
{config.destination}
</View>
</View>
{config.showShippingFrom && (
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
</View>
<View className="col-span-2 p-2 text-left">
{config.shippingFrom}
</View>
</View>
)}
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-3 flex items-end justify-center border-b border-black">
{config.supplier}
<View className="col-span-2 p-2 text-left">
{config.accountCompany}
</View>
<View className="col-span-1 flex items-end justify-center">
</View>
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-3 flex items-end justify-center border-b border-black">
{config.departureTime}
<View className="col-span-2 p-2 text-left">
{config.date}
</View>
<View className="col-span-1 flex items-end justify-center">
</View>
{config.showEstimatedArrivalTime && (
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-3 flex items-end justify-center border-b border-black">
{config.arrivalTime}
<View className="col-span-2 p-2 text-left">
{config.estimatedArrivalTime}
</View>
<View className="col-span-1 flex items-end justify-center">
:
</View>
<View className="col-span-7 flex items-end justify-center border-b border-black">
{config.productName}
)}
{config.data?.map((item: any) => {
return (
<>
{config.showGrade && (
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-2 p-2 text-left">
{item.watermelonGrade}
</View>
</View>
)}
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-2 p-2 text-left">
</View>
</View>
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
</View>
<View className="col-span-2 p-2 text-left">
{item.unitPrice}
{config.unitPriceUnit === "1"
? "元/斤"
: "元/公斤"}
</View>
</View>
</>
);
})}
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
</View>
<View className="p-2 text-left">
{config.data?.reduce(
(acc: any, cur: any) => acc + cur.grossWeight,
0,
)}
</View>
<View className="p-2 text-left"></View>
</View>
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold"></View>
<View className="p-2 text-left">
{config.data?.reduce(
(acc: any, cur: any) => acc + cur.boxCount,
0,
)}
</View>
<View className="p-2 text-left"></View>
</View>
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">:</View>
<View className="col-span-2 p-2 text-left">
{config.licensePlate}
</View>
</View>
<View className="grid w-full grid-cols-3 gap-0 text-base">
<View className="p-2 text-left font-bold">
:
</View>
<View className="col-span-2 p-2 text-left">
{config.driverPhone}
</View>
</View>
</View>
);

View File

@ -278,6 +278,7 @@ export default hocAuth(function Page(props: CommonComponent) {
active: active,
orderVehicle: purchaseOrder.orderVehicle,
orderDealer: purchaseOrder.orderDealer,
orderCostList: purchaseOrder.orderCostList,
});
if (data.success) {
@ -295,6 +296,7 @@ export default hocAuth(function Page(props: CommonComponent) {
active: active,
orderVehicle: purchaseOrder.orderVehicle,
orderDealer: purchaseOrder.orderDealer,
orderCostList: purchaseOrder.orderCostList,
});
if (data.success) {
@ -547,6 +549,10 @@ export default hocAuth(function Page(props: CommonComponent) {
setOrderVehicle={setOrderVehicle}
orderDealer={orderDealer!}
setOrderDealer={setOrderDealer}
orderCostList={orderCostList}
setOrderCostList={(costItemList: CostItem[]) => {
setOrderCostList(costItemList);
}}
/>
)}

View File

@ -3315,6 +3315,8 @@ declare namespace BusinessAPI {
orderVehicle: OrderVehicle;
/** 经销商信息 */
orderDealer: OrderDealer;
/** 采购订单费用信息 */
orderCostList: OrderCost[];
};
type PurchaseOrderStep2Cmd = {
@ -3724,6 +3726,8 @@ declare namespace BusinessAPI {
grossWeight?: number;
/** 箱重(斤) */
boxWeight?: number;
/** 箱数 */
boxCount?: number;
/** 净重(斤) */
netWeight?: number;
/** 单价(元) */
@ -3917,6 +3921,8 @@ declare namespace BusinessAPI {
shipOrderItemList?: ShipOrderItem[];
/** 发货单子项表 */
shipOrderPackageList?: ShipOrderPackage[];
/** 发货单费用项 */
orderCostList?: OrderCost[];
};
type showAgreementParams = {

View File

@ -1,2 +1,3 @@
export { default as auth } from "./auth";
export { default as business } from "./business";
export { default as poster } from "./poster";

View File

@ -1,25 +1,13 @@
import axios from "axios";
import Taro from "@tarojs/taro";
import { Toast } from "@nutui/nutui-react-taro";
const request = axios.create({
baseURL: process.env.TARO_API_DOMAIN,
baseURL: process.env.TARO_POSTER_DOMAIN,
});
// 创建全局的axios实例并安装请求拦截器
request.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
const saToken = Taro.getStorageSync("saToken");
if (saToken) {
config.headers.saToken = saToken;
}
const slug = Taro.getStorageSync("userRoleVO")?.slug;
if (slug) {
config.headers["Xh-Role-Slug"] = slug;
}
config.headers["Authorization"] = "Bearer abc123";
return config;
},
(error) => {
@ -28,80 +16,4 @@ request.interceptors.request.use(
},
);
// 在获取到响应后,安装响应拦截器
request.interceptors.response.use(
async (response) => {
console.log("response", response);
const {
data: { success, data },
} = response;
// 处理响应成功的情况
if (success) {
const saToken = data?.meta?.accessToken;
if (saToken) {
Taro.setStorageSync("saToken", saToken);
Taro.setStorageSync("user", data.userVO);
Taro.setStorageSync("userRoleVO", data.userRoleVOList?.[0]);
}
} else {
// 异常处理
if (response.data.errCode === "403") {
Toast.show("toast", {
icon: "fail",
title: "暂无权限",
content: response.data.errMessage,
});
}
// 如果是401则重新登录然后重新发起请求
if (response.data.errCode === "401") {
// 移除缓存
Taro.removeStorageSync("saToken");
Taro.removeStorageSync("user");
Taro.removeStorageSync("userRoleVO");
// const { code } = await Taro.login();
// const data = await wxMaLogin(code);
// if (data) {
// response.config.headers.saToken = `${Taro.getStorageSync("saToken")}`;
// return request(response.config);
// }
// 跳转到登录页面
Taro.navigateTo({
url: "/pages/public/login/index",
});
return response;
}
console.log("response.data.errCode", response.data.errCode);
if (response.data.errCode === "400") {
Toast.show("toast", {
icon: "fail",
title: "请求失败",
content: response.data.errMessage,
});
}
if (response.data.errCode === "500") {
Toast.show("toast", {
icon: "fail",
title: "服务器错误",
content: response.data.errMessage,
});
} else {
Toast.show("toast", {
icon: "fail",
title: "请求失败",
content: response.data.errMessage,
});
}
}
return response;
},
(error) => {
// 处理响应错误的情况
return Promise.reject(error);
},
);
export default request;

View File

@ -33,6 +33,7 @@ export interface BoxBrand {
boxBrandId: string;
boxBrandName: string;
boxBrandImage: string;
boxBrandType: "OUR_BOX" | "FARMER_BOX" | "THIRD_PARTY_BOX";
boxType: "USED" | "EXTRA" | "EXTRA_USED" | "REMAIN" | "OWN" | "DEFAULT";
boxCategoryList: BoxCategory[];
}