feat(delivery): 优化发货单据生成与预览功能
- 新增图片预览与保存功能,支持点击放大查看 - 调整PDF下载逻辑,支持下载后查看或保存至本地 - 更新发货单据结构,区分pdfUrl与picUrl字段 - 移除旧版采购底单单据页面及相关配置 - 优化UI布局,增强底部按钮区域的操作体验 - 引入新的图标资源,支持下载和PDF相关操作 - 修复跳转路径问题,统一指向新的发货单据页面 - 增强日期格式化处理,确保预计到仓时间准确显示
This commit is contained in:
parent
b4df78d549
commit
91d9d4bf89
@ -85,7 +85,7 @@ config = {
|
||||
// 发货单
|
||||
{
|
||||
root: "pages/delivery",
|
||||
pages: ["all", "document/delivery", "document/purchase"],
|
||||
pages: ["all", "document"],
|
||||
},
|
||||
// 瓜农
|
||||
{
|
||||
|
||||
@ -1,121 +1,197 @@
|
||||
import { useState } from "react";
|
||||
import { Text, View } from "@tarojs/components";
|
||||
import { Image, Text, View } from "@tarojs/components";
|
||||
import { Button } from "@nutui/nutui-react-taro";
|
||||
import Taro from "@tarojs/taro";
|
||||
import { Icon } from "@/components";
|
||||
|
||||
interface Step3SuccessProps {
|
||||
document: string;
|
||||
pdfUrl: string;
|
||||
picUrl?: string;
|
||||
}
|
||||
|
||||
export default function Step3Success(props: Step3SuccessProps) {
|
||||
const { document } = props;
|
||||
const { pdfUrl, picUrl } = props;
|
||||
const [tempFilePath, setTempFilePath] = useState<string>();
|
||||
|
||||
// 查看文档
|
||||
const handleView = async () => {
|
||||
if (!tempFilePath) {
|
||||
// 保存图片
|
||||
const handleSaveImage = async () => {
|
||||
if (!picUrl) {
|
||||
Taro.showToast({
|
||||
title: "请先下载发货单据",
|
||||
title: "没有可保存的预览图片",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 下载文件
|
||||
const downloadRes = await Taro.downloadFile({
|
||||
url: picUrl!,
|
||||
});
|
||||
// 保存图片到相册
|
||||
await Taro.saveImageToPhotosAlbum({
|
||||
filePath: downloadRes.tempFilePath,
|
||||
});
|
||||
|
||||
Taro.showToast({
|
||||
title: "图片已保存到相册",
|
||||
icon: "success",
|
||||
duration: 2000,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("保存图片失败:", error);
|
||||
Taro.showToast({
|
||||
title: "保存图片失败,请检查相册权限",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 下载PDF
|
||||
const handleDownloadPDF = async () => {
|
||||
Taro.showToast({
|
||||
title: "正在下载PDF文件",
|
||||
icon: "loading",
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
try {
|
||||
// 下载文件
|
||||
const downloadRes = await Taro.downloadFile({
|
||||
url: pdfUrl!,
|
||||
});
|
||||
|
||||
if (downloadRes.tempFilePath) {
|
||||
setTempFilePath(downloadRes.tempFilePath);
|
||||
|
||||
// 保存PDF到手机
|
||||
if (Taro.saveFile) {
|
||||
await Taro.saveFile({
|
||||
tempFilePath: downloadRes.tempFilePath,
|
||||
});
|
||||
|
||||
Taro.showToast({
|
||||
title: "PDF下载成功",
|
||||
icon: "success",
|
||||
duration: 2000,
|
||||
});
|
||||
} else {
|
||||
// 如果不支持saveFile,直接提示下载完成
|
||||
Taro.openDocument({
|
||||
filePath: downloadRes.tempFilePath,
|
||||
showMenu: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("下载PDF失败:", error);
|
||||
Taro.showToast({
|
||||
title: "下载PDF失败",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 查看PDF文档
|
||||
const handleViewPDF = async () => {
|
||||
if (!tempFilePath) {
|
||||
await handleDownloadPDF();
|
||||
}
|
||||
|
||||
if (tempFilePath) {
|
||||
Taro.openDocument({
|
||||
filePath: tempFilePath,
|
||||
showMenu: true,
|
||||
});
|
||||
};
|
||||
|
||||
// 处理下载功能
|
||||
const handleDownload = async () => {
|
||||
Taro.showToast({
|
||||
title: "正在生成并下载发货单据",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
// 下载文件
|
||||
Taro.downloadFile({
|
||||
url: document!,
|
||||
}).then((downloadRes) => {
|
||||
if (downloadRes.tempFilePath) {
|
||||
setTempFilePath(downloadRes.tempFilePath);
|
||||
Taro.showToast({
|
||||
title: "发货单据已下载成功,您可以将生成的PDF发送给好友",
|
||||
icon: "none",
|
||||
duration: 3000,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理分享功能
|
||||
const handleShare = async () => {
|
||||
if (!tempFilePath) {
|
||||
Taro.showToast({
|
||||
title: "请先下载发货单据",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
Taro.showToast({
|
||||
title: "正在分享到微信",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
// 下载完成后转发
|
||||
Taro.shareFileMessage({
|
||||
filePath: tempFilePath,
|
||||
fileName: `发货单据.pdf`,
|
||||
complete: (res) => {
|
||||
console.log("complete", res);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="flex flex-1 flex-col items-center justify-center rounded-lg bg-white p-4 shadow-md">
|
||||
<View className="mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-green-100">
|
||||
<Text className="text-2xl text-green-600">✓</Text>
|
||||
<View className="flex flex-1 flex-col overflow-hidden rounded-md bg-gray-100 shadow-md">
|
||||
{/* 预览区域 */}
|
||||
<View className="flex-1 p-2.5">
|
||||
<View className="rounded-lg bg-white shadow-sm">
|
||||
{picUrl ? (
|
||||
<View
|
||||
className="overflow-hidden rounded-lg border border-gray-200"
|
||||
style={{ maxHeight: Taro.pxTransform(400) }}
|
||||
>
|
||||
<Image
|
||||
src={picUrl}
|
||||
mode="widthFix"
|
||||
className="w-full"
|
||||
onClick={() => {
|
||||
Taro.previewImage({
|
||||
urls: [picUrl],
|
||||
current: picUrl,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<View className="mb-2 text-xl font-bold text-gray-800">
|
||||
发货单据生成成功
|
||||
) : (
|
||||
<View className="flex h-48 items-center justify-center rounded-lg border-2 border-dashed border-gray-300 bg-gray-50">
|
||||
<Text className="text-gray-500">暂无预览图片</Text>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<View className="mb-8 text-gray-600">
|
||||
您的发货单据已生成,可以下载或转发给好友
|
||||
</View>
|
||||
|
||||
<View className="mb-6 flex w-full flex-row justify-center gap-4">
|
||||
{document && !tempFilePath && (
|
||||
<View className={"flex-1"}>
|
||||
<Button type="default" size="large" block onClick={handleDownload}>
|
||||
下载文档
|
||||
{/* 底部按钮区域 */}
|
||||
<View className="border-t border-gray-100 bg-white p-2.5">
|
||||
<View className="flex flex-col gap-2.5">
|
||||
{/* 保存图片按钮 */}
|
||||
{picUrl && (
|
||||
<Button
|
||||
icon={<Icon name="download" size={16} color={"white"} />}
|
||||
type="primary"
|
||||
size="large"
|
||||
block
|
||||
onClick={handleSaveImage}
|
||||
className="flex items-center justify-center"
|
||||
>
|
||||
<Text className="font-medium">保存图片</Text>
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{/* PDF操作按钮 */}
|
||||
<View className="flex gap-3">
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
icon={<Icon name="file-pdf" size={16} color={"white"} />}
|
||||
type="primary"
|
||||
size="large"
|
||||
color="orange"
|
||||
block
|
||||
onClick={handleDownloadPDF}
|
||||
>
|
||||
<Text className="font-medium">下载PDF</Text>
|
||||
</Button>
|
||||
</View>
|
||||
{tempFilePath && (
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
icon={<Icon name="eye" size={16} color={"white"} />}
|
||||
type="default"
|
||||
size="large"
|
||||
block
|
||||
onClick={handleViewPDF}
|
||||
>
|
||||
<Text className="font-medium">查看PDF</Text>
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
{document && tempFilePath && (
|
||||
<>
|
||||
<View className={"flex-1"}>
|
||||
<Button type="default" size="large" block onClick={handleView}>
|
||||
查看文档
|
||||
</Button>
|
||||
</View>
|
||||
<View className={"flex-1"}>
|
||||
<Button type="primary" size="large" block onClick={handleShare}>
|
||||
转发好友
|
||||
</Button>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
|
||||
<View className="text-sm text-gray-500">
|
||||
提示:您可以随时在发货单据列表中重新下载
|
||||
{/* 提示信息 */}
|
||||
<View className="text-center">
|
||||
<Text className="text-xs text-gray-500">
|
||||
点击预览图片可放大查看
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
|
||||
@ -3,6 +3,8 @@ import classNames from "classnames";
|
||||
import React from "react";
|
||||
|
||||
export type IconNames =
|
||||
| "download"
|
||||
| "file-pdf"
|
||||
| "check-circle"
|
||||
| "exclamation"
|
||||
| "arrow-up"
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 5042354 */
|
||||
src: url('//at.alicdn.com/t/c/font_5042354_6imvn9bni2l.woff2?t=1766198766212') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_5042354_6imvn9bni2l.woff?t=1766198766212') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_5042354_6imvn9bni2l.ttf?t=1766198766212') format('truetype');
|
||||
src: url('//at.alicdn.com/t/c/font_5042354_mzxt7rknws.woff2?t=1766213275700') format('woff2'),
|
||||
url('//at.alicdn.com/t/c/font_5042354_mzxt7rknws.woff?t=1766213275700') format('woff'),
|
||||
url('//at.alicdn.com/t/c/font_5042354_mzxt7rknws.ttf?t=1766213275700') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,14 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-download:before {
|
||||
content: "\e636";
|
||||
}
|
||||
|
||||
.icon-file-pdf:before {
|
||||
content: "\e634";
|
||||
}
|
||||
|
||||
.icon-exclamation:before {
|
||||
content: "\e635";
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
onClick={async () => {
|
||||
// 跳转到发货单据生成页面
|
||||
await Taro.navigateTo({
|
||||
url: buildUrl("/pages/delivery/document/delivery", {
|
||||
url: buildUrl("/pages/delivery/document", {
|
||||
orderShipId: orderShip.orderShipId,
|
||||
orderId: orderShip.orderId,
|
||||
}),
|
||||
|
||||
@ -184,7 +184,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
onClick={async (e) => {
|
||||
// 跳转到发货单据生成页面
|
||||
await Taro.navigateTo({
|
||||
url: buildUrl("/pages/delivery/document/delivery", {
|
||||
url: buildUrl("/pages/delivery/document", {
|
||||
orderShipId: shipOrderVO.orderShipId,
|
||||
orderId: shipOrderVO.orderId,
|
||||
}),
|
||||
|
||||
@ -18,6 +18,7 @@ import {
|
||||
DeliveryStep2Preview,
|
||||
DeliveryStep3Success,
|
||||
} from "@/components";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
// 特殊处理:其他费用要实时获取费用项目
|
||||
const updateOtherFeesModule = async (
|
||||
@ -76,13 +77,13 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
|
||||
const [step, setStep] = useState(1);
|
||||
const [moduleList, setModuleList] = useState<any[]>([]);
|
||||
const [height, setHeight] = useState<number>();
|
||||
const [purchaseOrderVO, setPurchaseOrderVO] =
|
||||
useState<BusinessAPI.PurchaseOrderVO>();
|
||||
|
||||
const [orderShipVO, setOrderShipVO] = useState<BusinessAPI.OrderShip>();
|
||||
const [deliveryTemplate, setDeliveryTemplate] = useState<string>();
|
||||
const [document, setDocument] = useState<string>();
|
||||
const [pdfUrl, setPdfUrl] = useState<string>();
|
||||
const [picUrl, setPicUrl] = useState<string>();
|
||||
|
||||
const step1FormRef = useRef<DeliveryStep1FormRef>(null);
|
||||
|
||||
@ -102,9 +103,10 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
setPurchaseOrderVO(purchaseOrderVO);
|
||||
const shipOrderVO = purchaseOrderVO.orderShipList[0];
|
||||
setOrderShipVO(shipOrderVO);
|
||||
if (shipOrderVO.document) {
|
||||
if (shipOrderVO.pdfUrl || shipOrderVO.picUrl) {
|
||||
setStep(3);
|
||||
setDocument(shipOrderVO.document);
|
||||
setPdfUrl(shipOrderVO.pdfUrl);
|
||||
setPicUrl(shipOrderVO.picUrl);
|
||||
}
|
||||
|
||||
const { data } = await business.dealer.showDealer({
|
||||
@ -188,7 +190,6 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
},
|
||||
onCancel: () => {
|
||||
Dialog.close("dialog");
|
||||
console.log("12123");
|
||||
},
|
||||
});
|
||||
return;
|
||||
@ -231,16 +232,29 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
// 截图预览内容
|
||||
const capturePreview = async () => {
|
||||
const template = new PdfTemplate(moduleList);
|
||||
const { data } = await poster.pdf.postApiV1Pdf({
|
||||
const {
|
||||
data: { data: pdfData },
|
||||
} = await poster.pdf.postApiV1Pdf({
|
||||
html: template.generateHtmlString(),
|
||||
});
|
||||
|
||||
const {
|
||||
data: { data: picData },
|
||||
} = await poster.poster.postApiV1Poster({
|
||||
html: template.generateHtmlString(),
|
||||
format: "a4",
|
||||
});
|
||||
|
||||
setPdfUrl(pdfData?.path);
|
||||
setPicUrl(picData?.path);
|
||||
|
||||
const orderShip = purchaseOrderVO?.orderShipList[0];
|
||||
// 存储 至 shipOrder previewUrl
|
||||
if (orderShip) {
|
||||
let formData: BusinessAPI.OrderShipGenerateDocumentCmd = {
|
||||
orderShipId: orderShip?.orderShipId,
|
||||
document: data?.data?.path,
|
||||
pdfUrl: pdfData?.path as string,
|
||||
picUrl: picData?.path as string,
|
||||
};
|
||||
// 检查各模块中的必填字段是否已填写
|
||||
for (const module of moduleList) {
|
||||
@ -267,7 +281,9 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
}
|
||||
// 检查预计到仓时间字段是否开启且已填写
|
||||
else if (column.dataIndex === "requiredEstimatedArrivalTime") {
|
||||
formData.estimatedArrivalDate = orderShip?.estimatedArrivalDate;
|
||||
formData.estimatedArrivalDate = dayjs(
|
||||
orderShip?.estimatedArrivalDate,
|
||||
).format("YYYY-MM-DD");
|
||||
}
|
||||
// 检查备注字段是否开启且已填写
|
||||
else if (column.dataIndex === "requiredRemarks") {
|
||||
@ -281,10 +297,6 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
}
|
||||
business.orderShip.generateDocumentOrderShip(formData).then();
|
||||
}
|
||||
|
||||
if (data && data?.data?.path) {
|
||||
setDocument(data?.data?.path);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回上一步
|
||||
@ -308,47 +320,13 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
setStep(1);
|
||||
};
|
||||
|
||||
const [topBarHeight, setTopBarHeight] = useState<number>(0);
|
||||
const [bottomBarHeight, setBottomBarHeight] = useState<number>(0);
|
||||
const topBarRef = useRef<any>(null);
|
||||
const bottomBarRef = useRef<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// 获取 topBar 和 bottomBar 的实际高度
|
||||
const queryTopBar = Taro.createSelectorQuery();
|
||||
queryTopBar
|
||||
.select("#topBar")
|
||||
.boundingClientRect((rect: any) => {
|
||||
if (rect) {
|
||||
setTopBarHeight(rect.height);
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
|
||||
const queryBottomBar = Taro.createSelectorQuery();
|
||||
queryBottomBar
|
||||
.select("#bottomBar")
|
||||
.boundingClientRect((rect: any) => {
|
||||
if (rect) {
|
||||
setBottomBarHeight(rect.height);
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
}, [step]);
|
||||
|
||||
useEffect(() => {
|
||||
// 计算滚动区域高度:窗口高度 - topBar高度 - bottomBar高度
|
||||
const windowHeight = Taro.getSystemInfoSync().windowHeight;
|
||||
setHeight(windowHeight - topBarHeight - bottomBarHeight);
|
||||
}, [topBarHeight, bottomBarHeight]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<View
|
||||
className={
|
||||
"flex flex-1 flex-col overflow-x-hidden overflow-y-auto bg-[#D1D5DB]"
|
||||
}
|
||||
>
|
||||
<View id={"topBar"} ref={topBarRef}>
|
||||
<View className={"p-2.5"}>
|
||||
<View className={"rounded-lg bg-white p-4 shadow-md"}>
|
||||
<Steps value={step} status="dynamic" layout="single">
|
||||
@ -358,15 +336,11 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
</Steps>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
className={classNames("px-2.5", {
|
||||
"overflow-hidden": step === 2,
|
||||
})}
|
||||
style={{
|
||||
height: height,
|
||||
}}
|
||||
>
|
||||
{step === 1 && (
|
||||
<View className="flex flex-col rounded-lg bg-white p-2.5 shadow-md">
|
||||
@ -381,14 +355,13 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
|
||||
{step === 2 && <DeliveryStep2Preview moduleList={moduleList} />}
|
||||
|
||||
{step === 3 && document && <DeliveryStep3Success document={document} />}
|
||||
{step === 3 && pdfUrl && (
|
||||
<DeliveryStep3Success pdfUrl={pdfUrl} picUrl={picUrl} />
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
ref={bottomBarRef}
|
||||
className={"fixed bottom-0 left-0 z-10 w-full bg-white"}
|
||||
id={"bottomBar"}
|
||||
>
|
||||
<View className={"sticky bottom-0 left-0 z-10 w-full bg-white"}>
|
||||
<View className={"flex flex-row gap-2.5 p-2.5"}>
|
||||
{step == 1 && (
|
||||
<View className={"flex-1"}>
|
||||
@ -464,6 +437,6 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
</View>
|
||||
<SafeArea position={"bottom"} />
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
});
|
||||
@ -1,4 +0,0 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: "采购底单单据生成",
|
||||
navigationBarBackgroundColor: "#fff",
|
||||
});
|
||||
@ -1,390 +0,0 @@
|
||||
import hocAuth from "@/hocs/auth";
|
||||
import { CommonComponent } from "@/types/typings";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { View } from "@tarojs/components";
|
||||
import { Button, Dialog, SafeArea, Step, Steps } from "@nutui/nutui-react-taro";
|
||||
import shipOrder from "@/constant/orderShip";
|
||||
import Taro from "@tarojs/taro";
|
||||
import classNames from "classnames";
|
||||
import { business, poster } from "@/services";
|
||||
import { buildUrl, PdfTemplate } from "@/utils";
|
||||
import {
|
||||
Icon,
|
||||
PurchaseStep1Form,
|
||||
PurchaseStep1FormRef,
|
||||
PurchaseStep2Preview,
|
||||
PurchaseStep3Success,
|
||||
} from "@/components";
|
||||
|
||||
export default hocAuth(function Page(props: CommonComponent) {
|
||||
const { router, setLoading } = props;
|
||||
const orderId = router.params
|
||||
.orderId as BusinessAPI.PurchaseOrderVO["orderId"];
|
||||
|
||||
const [step, setStep] = useState(1);
|
||||
const [moduleList, setModuleList] = useState<any[]>([]);
|
||||
const [document, setDocument] =
|
||||
useState<BusinessAPI.OrderShipVO["document"]>();
|
||||
const [height, setHeight] = useState<number>();
|
||||
const [purchaseOrderVO, setPurchaseOrderVO] =
|
||||
useState<BusinessAPI.PurchaseOrderVO>();
|
||||
const [shipOrderVO, setShipOrderVO] = useState<BusinessAPI.OrderShipVO>();
|
||||
|
||||
const step1FormRef = useRef<PurchaseStep1FormRef>(null);
|
||||
|
||||
const init = async (orderId: BusinessAPI.PurchaseOrderVO["orderId"]) => {
|
||||
setLoading(true);
|
||||
const {
|
||||
data: { data: purchaseOrderVO },
|
||||
} = await business.purchaseOrder.showPurchaseOrder({
|
||||
purchaseOrderShowQry: {
|
||||
orderId,
|
||||
},
|
||||
});
|
||||
setPurchaseOrderVO(purchaseOrderVO);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (orderId) {
|
||||
init(orderId).then();
|
||||
}
|
||||
}, [orderId]);
|
||||
|
||||
// 预览确认
|
||||
const previewAndConfirm = () => {
|
||||
if (step === 2) {
|
||||
// 显示确认对话框
|
||||
Dialog.open("dialog", {
|
||||
title: "生成发货单据",
|
||||
content: "即将生成发货单据,请确认发货单据是否正确。",
|
||||
confirmText: "确认生成",
|
||||
cancelText: "取消",
|
||||
onConfirm: async () => {
|
||||
// 截图预览内容
|
||||
await capturePreview();
|
||||
Dialog.close("dialog");
|
||||
// 进入第三步
|
||||
setStep(3);
|
||||
},
|
||||
onCancel: () => {
|
||||
Dialog.close("dialog");
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (step === 1) {
|
||||
// 调用 Step1Form 的表单校验方法
|
||||
if (step1FormRef.current && step1FormRef.current.validateForm()) {
|
||||
setStep(2);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (step < 3) {
|
||||
setStep(step + 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 生成发货单据
|
||||
const generateShippingDocument = async () => {
|
||||
// 显示确认对话框
|
||||
Dialog.open("dialog", {
|
||||
title: "生成发货单据",
|
||||
content: "即将生成发货单据,请确认发货单据是否正确。",
|
||||
confirmText: "确认生成",
|
||||
cancelText: "取消",
|
||||
onConfirm: async () => {
|
||||
// 截图预览内容
|
||||
await capturePreview();
|
||||
Dialog.close("dialog");
|
||||
// 进入第三步
|
||||
setStep(3);
|
||||
},
|
||||
onCancel: () => {
|
||||
Dialog.close("dialog");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 截图预览内容
|
||||
const capturePreview = async () => {
|
||||
const template = new PdfTemplate(moduleList);
|
||||
console.log("generateHtmlString", template.generateHtmlString());
|
||||
const { data } = await poster.pdf.postApiV1Pdf({
|
||||
html: template.generateHtmlString(),
|
||||
});
|
||||
|
||||
// 存储 至 shipOrder previewUrl
|
||||
if (shipOrderVO) {
|
||||
let formData: BusinessAPI.OrderShipGenerateDocumentCmd = {
|
||||
orderShipId: shipOrderVO?.orderShipId,
|
||||
document: data?.data?.path,
|
||||
};
|
||||
// 检查各模块中的必填字段是否已填写
|
||||
for (const module of moduleList) {
|
||||
const contentSchema = module.schemas.find(
|
||||
(schema) => schema.title === "内容配置",
|
||||
);
|
||||
|
||||
if (
|
||||
!contentSchema ||
|
||||
!contentSchema.columns ||
|
||||
contentSchema.columns.length === 0
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const column of contentSchema.columns) {
|
||||
// 检查西瓜品级字段是否开启且已填写
|
||||
if (column.dataIndex === "requiredWatermelonGrade") {
|
||||
formData.watermelonGrade = shipOrderVO?.watermelonGrade;
|
||||
}
|
||||
// 检查发货地字段是否开启且已填写
|
||||
else if (column.dataIndex === "requiredShippingFrom") {
|
||||
formData.shippingAddress = shipOrderVO?.shippingAddress;
|
||||
}
|
||||
// 检查预计到仓时间字段是否开启且已填写
|
||||
else if (column.dataIndex === "requiredEstimatedArrivalTime") {
|
||||
formData.estimatedArrivalDate = shipOrderVO?.estimatedArrivalDate;
|
||||
}
|
||||
// 检查备注字段是否开启且已填写
|
||||
else if (column.dataIndex === "requiredRemarks") {
|
||||
formData.remark = shipOrderVO?.remark;
|
||||
}
|
||||
// 检查品级字段是否开启且已填写
|
||||
else if (column.dataIndex === "requiredGrade") {
|
||||
formData.orderShipItemList = shipOrderVO?.orderShipItemList;
|
||||
}
|
||||
}
|
||||
}
|
||||
business.orderShip.generateDocumentOrderShip(formData).then();
|
||||
}
|
||||
|
||||
if (data && data?.data?.path) {
|
||||
setDocument(data?.data?.path);
|
||||
}
|
||||
};
|
||||
|
||||
// 返回上一步
|
||||
const goToPrevStep = () => {
|
||||
if (step > 0) {
|
||||
setStep(step - 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
setStep(1);
|
||||
// 重新加载初始数据
|
||||
if (orderId) {
|
||||
init(orderId).then();
|
||||
}
|
||||
};
|
||||
|
||||
// 重新生成单据
|
||||
const regenerateDocument = () => {
|
||||
setStep(1);
|
||||
};
|
||||
|
||||
const [topBarHeight, setTopBarHeight] = useState<number>(0);
|
||||
const [bottomBarHeight, setBottomBarHeight] = useState<number>(0);
|
||||
const topBarRef = useRef<any>(null);
|
||||
const bottomBarRef = useRef<any>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// 获取 topBar 和 bottomBar 的实际高度
|
||||
const queryTopBar = Taro.createSelectorQuery();
|
||||
queryTopBar
|
||||
.select("#topBar")
|
||||
.boundingClientRect((rect: any) => {
|
||||
if (rect) {
|
||||
setTopBarHeight(rect.height);
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
|
||||
const queryBottomBar = Taro.createSelectorQuery();
|
||||
queryBottomBar
|
||||
.select("#bottomBar")
|
||||
.boundingClientRect((rect: any) => {
|
||||
if (rect) {
|
||||
setBottomBarHeight(rect.height);
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
}, [step]);
|
||||
|
||||
useEffect(() => {
|
||||
// 计算滚动区域高度:窗口高度 - topBar高度 - bottomBar高度
|
||||
const windowHeight = Taro.getSystemInfoSync().windowHeight;
|
||||
setHeight(windowHeight - topBarHeight - bottomBarHeight);
|
||||
}, [topBarHeight, bottomBarHeight]);
|
||||
|
||||
if (!purchaseOrderVO) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
className={
|
||||
"flex flex-1 flex-col overflow-x-hidden overflow-y-auto bg-[#D1D5DB]"
|
||||
}
|
||||
>
|
||||
<View id={"topBar"} ref={topBarRef}>
|
||||
<View className={"p-2.5"}>
|
||||
<View className={"rounded-lg bg-white p-4 shadow-md"}>
|
||||
<Steps value={step} status="dynamic" layout="single">
|
||||
{shipOrder.steps.map((item, index) => (
|
||||
<Step key={index} {...item} />
|
||||
))}
|
||||
</Steps>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View
|
||||
className={classNames("px-2.5", {
|
||||
"overflow-hidden": step === 2,
|
||||
})}
|
||||
style={{
|
||||
height: height,
|
||||
}}
|
||||
>
|
||||
{step === 1 && (
|
||||
<View className={"flex flex-col gap-2.5"}>
|
||||
<View className="overflow-hidden rounded-lg bg-white shadow-sm">
|
||||
<View className="flex overflow-x-auto border-b border-gray-200 px-2">
|
||||
<View className="flex-none">
|
||||
<View className="text-primary flex items-center gap-1 px-4 py-3 text-sm font-medium">
|
||||
<Icon name="plus" size={14} />
|
||||
<View>添加分单</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="flex-none">
|
||||
<View className="tab-active flex items-center px-4 py-3 text-sm font-medium">
|
||||
<View>黄花仓</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="flex-none">
|
||||
<View className="flex items-center px-4 py-3 text-sm font-medium">
|
||||
<View>晋州仓</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="flex-none">
|
||||
<View className="flex items-center px-4 py-3 text-sm font-medium">
|
||||
<View>石家庄仓</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="flex-none">
|
||||
<View className="flex items-center px-4 py-3 text-sm font-medium">
|
||||
<View>保定仓</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="flex-none">
|
||||
<View className="flex items-center px-4 py-3 text-sm font-medium">
|
||||
<View>唐山仓</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View className="p-2.5">
|
||||
<PurchaseStep1Form
|
||||
ref={step1FormRef}
|
||||
moduleList={moduleList}
|
||||
shipOrderVO={shipOrderVO}
|
||||
setShipOrderVO={setShipOrderVO}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{step === 2 && <PurchaseStep2Preview moduleList={moduleList} />}
|
||||
|
||||
{step === 3 && document && <PurchaseStep3Success document={document} />}
|
||||
</View>
|
||||
|
||||
<View
|
||||
ref={bottomBarRef}
|
||||
className={"fixed bottom-0 left-0 z-10 w-full bg-white"}
|
||||
id={"bottomBar"}
|
||||
>
|
||||
<View className={"flex flex-row gap-2.5 p-2.5"}>
|
||||
{step == 1 && (
|
||||
<View className={"flex-1"}>
|
||||
<Button type="default" block size={"large"} onClick={resetForm}>
|
||||
重置
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
{step == 1 && (
|
||||
<View className={"flex-1"}>
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
size={"large"}
|
||||
onClick={previewAndConfirm}
|
||||
>
|
||||
下一步
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
{step == 2 && (
|
||||
<View className={"flex-1"}>
|
||||
<Button
|
||||
type="default"
|
||||
block
|
||||
size={"large"}
|
||||
onClick={goToPrevStep}
|
||||
>
|
||||
返回修改
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
{step == 2 && (
|
||||
<View className={"flex-1"}>
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
size={"large"}
|
||||
onClick={generateShippingDocument}
|
||||
>
|
||||
生成发货单据
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
{step == 3 && (
|
||||
<View className={"flex-1"}>
|
||||
<Button
|
||||
type="default"
|
||||
block
|
||||
size={"large"}
|
||||
onClick={() =>
|
||||
Taro.switchTab({
|
||||
url: buildUrl("/pages/main/index/index"),
|
||||
})
|
||||
}
|
||||
>
|
||||
返回首页
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
{step == 3 && (
|
||||
<View className={"flex-1"}>
|
||||
<Button
|
||||
type="primary"
|
||||
block
|
||||
size={"large"}
|
||||
onClick={regenerateDocument}
|
||||
>
|
||||
重新生成
|
||||
</Button>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
<SafeArea position={"bottom"} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
});
|
||||
@ -3131,7 +3131,9 @@ declare namespace BusinessAPI {
|
||||
/** 瓜农姓名逗号隔开 */
|
||||
farmerInfo?: string;
|
||||
/** 发货单据 */
|
||||
document: string;
|
||||
pdfUrl: string;
|
||||
picUrl: string;
|
||||
|
||||
/** 发货单状态:0_草稿;1_待发货;2_待回款;3_待改签;4_部分回款;5_已回款;6_拒收完结;7_已完结; */
|
||||
state:
|
||||
| "DRAFT"
|
||||
@ -3200,7 +3202,9 @@ declare namespace BusinessAPI {
|
||||
/** 发货单明细 */
|
||||
orderShipItemList?: OrderShipItem[];
|
||||
/** 发货单据 */
|
||||
document?: string;
|
||||
picUrl?: string;
|
||||
/** 发货单据 */
|
||||
pdfUrl?: string;
|
||||
};
|
||||
|
||||
type OrderShipItem = {
|
||||
|
||||
@ -19,6 +19,7 @@ export async function postApiV1Poster(
|
||||
type?: string;
|
||||
/** 编码类型 */
|
||||
encoding?: string;
|
||||
format?: 'custom' | 'a4';
|
||||
},
|
||||
options?: { [key: string]: any },
|
||||
) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user