From ff39dc01d2e125c9a03e2d037a0a58d6e35aff37 Mon Sep 17 00:00:00 2001 From: shenyifei Date: Tue, 23 Dec 2025 17:24:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(components):=20=E6=B7=BB=E5=8A=A0=E5=8F=91?= =?UTF-8?q?=E7=A5=A8=E6=89=B9=E9=87=8F=E4=B8=8A=E4=BC=A0=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E5=88=97=E8=A1=A8=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 InvoiceBatchUpload 组件支持发票批量上传 - 修改 PageList 组件类型定义支持泛型 - 在 PageList 组件中添加 toolbar footer 支持 - 优化发票页面 UI 布局和交互体验 - 更新应用版本号到 v0.0.53 - 重构发票上传页面实现批量选择功能 --- .../src/components/biz/PageList.tsx | 5 +- .../app-client/src/components/biz/typing.ts | 5 +- packages/app-client/src/components/index.ts | 1 + .../components/invoce/InvoiceBatchUpload.tsx | 298 +++++++++ .../app-client/src/components/invoce/index.ts | 1 + packages/app-client/src/constant/app.ts | 2 +- packages/app-client/src/pages/invoice/all.tsx | 208 ++++-- .../app-client/src/pages/invoice/pending.tsx | 449 ++++--------- .../app-client/src/pages/invoice/upload.tsx | 620 ++++++++---------- .../app-client/src/pages/supplier/all.tsx | 224 ++++--- 10 files changed, 960 insertions(+), 853 deletions(-) create mode 100644 packages/app-client/src/components/invoce/InvoiceBatchUpload.tsx create mode 100644 packages/app-client/src/components/invoce/index.ts diff --git a/packages/app-client/src/components/biz/PageList.tsx b/packages/app-client/src/components/biz/PageList.tsx index 43cae9e..2a6043f 100644 --- a/packages/app-client/src/components/biz/PageList.tsx +++ b/packages/app-client/src/components/biz/PageList.tsx @@ -48,7 +48,7 @@ export default ( ); const [lightTheme, setLightTheme] = useState(false); - const [data, setData] = useState[]>(); + const [data, setData] = useState([]); const [query, setQuery] = useState(); const [selectRows, setSelectRows] = useState([]); @@ -345,7 +345,7 @@ export default ( > {toolbar?.actions && toolbar?.actions.map((item) => item)} - {toolbar?.selectRow?.onClick && ( + {toolbar?.selectRow?.onClick && !toolbar?.footer && ( @@ -393,6 +393,7 @@ export default ( )} + {toolbar?.footer && toolbar?.footer?.(data || [])} {tabbar ? tabbar : } = { selectRow?: { onClick: (selectRow: any[]) => void; }; @@ -38,6 +38,7 @@ export type ToolBar = { items: any[]; }; render?: () => React.ReactNode | undefined; + footer?: (record: T[]) => React.ReactNode | undefined; }; export type IRecordListProps = { @@ -47,7 +48,7 @@ export type IRecordListProps = { type: "virtual" | "infinite"; skeleton?: React.ReactNode; actionRef: React.MutableRefObject; - toolbar?: ToolBar; + toolbar?: ToolBar; render: (record: T, index: number) => React.ReactNode; request: (params: Q) => Promise>; pagination: { diff --git a/packages/app-client/src/components/index.ts b/packages/app-client/src/components/index.ts index e6ee709..0c99038 100644 --- a/packages/app-client/src/components/index.ts +++ b/packages/app-client/src/components/index.ts @@ -9,3 +9,4 @@ export * from "./delivery"; export * from "./cost"; export * from "./expenses"; export * from "./audit"; +export * from "./invoce"; diff --git a/packages/app-client/src/components/invoce/InvoiceBatchUpload.tsx b/packages/app-client/src/components/invoce/InvoiceBatchUpload.tsx new file mode 100644 index 0000000..f1ce050 --- /dev/null +++ b/packages/app-client/src/components/invoce/InvoiceBatchUpload.tsx @@ -0,0 +1,298 @@ +import { Image, Text, View } from "@tarojs/components"; +import { Button, Popup, SafeArea, Toast } from "@nutui/nutui-react-taro"; +import Taro from "@tarojs/taro"; +import { uploadFile } from "@/utils"; +import { Icon } from "@/components"; +import { useState } from "react"; +import { business } from "@/services"; +import { globalStore } from "@/store/global-store"; +import { DecimalUtils } from "@/utils/classes/calculators/core/DecimalUtils"; + +interface IInvoiceBatchUploadProps { + visible: boolean; + setVisible: (visible: boolean) => void; + onFinish: () => void; + selectedOrders: BusinessAPI.OrderSupplierVO[]; +} + +export default function InvoiceBatchUpload(props: IInvoiceBatchUploadProps) { + const { visible, setVisible, onFinish, selectedOrders } = props; + + const { setLoading } = globalStore((state: any) => state); + const [invoiceImg, setInvoiceImg] = useState< + BusinessAPI.OrderSupplier["invoiceImg"] + >([]); + // 提交申请 + const handleSubmit = async () => { + // 这里添加提交申请的逻辑 + const { + data: { success }, + } = await business.orderSupplier.batchUploadInvoice({ + orderSupplierIdList: selectedOrders.map((order) => order.orderSupplierId), + invoiceImg: invoiceImg, + invoiceUpload: true, + }); + + if (success) { + Toast.show("toast", { + icon: "success", + title: "提交成功", + content: "发票已批量上传", + }); + onFinish?.(); + setVisible(false); + setInvoiceImg([]); + } + }; + + // 计算选中车次的总重量和总金额 + const calculateTotals = () => { + return selectedOrders.reduce( + (totals, order) => { + totals.totalWeight = DecimalUtils.add( + totals.totalWeight, + order.netWeight || 0, + ); + totals.totalAmount = DecimalUtils.add( + totals.totalAmount, + order.invoiceAmount || 0, + ); + return totals; + }, + { totalWeight: 0, totalAmount: 0 }, + ); + }; + + const { totalWeight, totalAmount } = calculateTotals(); + + return ( + setVisible(false)} + onOverlayClick={() => setVisible(false)} + lockScroll + round + > + + {/* 统计信息 */} + + + 已选{" "} + {selectedOrders.length}{" "} + 车次 + + + 总重量: + {totalWeight} 斤 + + + 总金额:{" "} + + {totalAmount.toFixed(2)} + + + + + {/* 上传发票 */} + + + {invoiceImg && invoiceImg?.length > 0 ? ( + invoiceImg?.map((uploadFileItem, index) => ( + + + + + + + + {uploadFileItem.fileName} + + + {Number(uploadFileItem.fileSize! / 1024 / 1024).toFixed( + 2, + )}{" "} + MB + + + + + + + + + + + + + )) + ) : ( + + { + await Taro.chooseMessageFile({ + type: "file", + count: 1, + success: (res) => { + setLoading(true); + const file = res.tempFiles[0]; + uploadFile(file.path).then(({ url }) => { + setInvoiceImg([ + { + fileName: url.split("/").pop(), + filePath: url, + fileSize: file.size, + fileType: url.split(".").pop(), + }, + ]); + setLoading(false); + Toast.show("toast", { + title: "上传成功", + icon: "success", + content: "发票已添加", + }); + }); + }, + fail: (err) => { + Toast.show("toast", { + title: "上传失败", + icon: "fail", + content: err.errMsg, + }); + }, + }); + }} + > + + + PDF文档 + + + 点击上传PDF + + + + { + await Taro.chooseImage({ + count: 1, + success: (res) => { + setLoading(true); + const file = res.tempFiles[0]; + uploadFile(file.path).then(({ url }) => { + setInvoiceImg([ + { + fileName: url.split("/").pop(), + filePath: url, + fileSize: file.size, + fileType: url.split(".").pop(), + }, + ]); + setLoading(false); + Toast.show("toast", { + title: "上传成功", + icon: "success", + content: "发票已添加", + }); + }); + }, + fail: (err) => { + Toast.show("toast", { + title: "上传失败", + icon: "fail", + content: err.errMsg, + }); + }, + }); + }} + > + + + 拍照/相册 + + + 点击上传照片 + + + + )} + + + + {/* 操作按钮 */} + + + + + {/* 提交按钮 */} + + + + + + + + ); +} diff --git a/packages/app-client/src/components/invoce/index.ts b/packages/app-client/src/components/invoce/index.ts new file mode 100644 index 0000000..00f063a --- /dev/null +++ b/packages/app-client/src/components/invoce/index.ts @@ -0,0 +1 @@ +export { default as InvoiceBatchUpload } from "./InvoiceBatchUpload"; diff --git a/packages/app-client/src/constant/app.ts b/packages/app-client/src/constant/app.ts index cfe57f8..c51ade7 100644 --- a/packages/app-client/src/constant/app.ts +++ b/packages/app-client/src/constant/app.ts @@ -1,2 +1,2 @@ // App 相关常量 -export const APP_VERSION = "v0.0.52"; +export const APP_VERSION = "v0.0.53"; diff --git a/packages/app-client/src/pages/invoice/all.tsx b/packages/app-client/src/pages/invoice/all.tsx index 256fb97..b458ea7 100644 --- a/packages/app-client/src/pages/invoice/all.tsx +++ b/packages/app-client/src/pages/invoice/all.tsx @@ -11,10 +11,11 @@ import { useRef, useState } from "react"; import { business } from "@/services"; import hocAuth from "@/hocs/auth"; import { CommonComponent } from "@/types/typings"; -import { View } from "@tarojs/components"; +import { Label, Text, View } from "@tarojs/components"; import dayjs from "dayjs"; import order from "@/constant/order"; import { Button, Toast } from "@nutui/nutui-react-taro"; +import classNames from "classnames"; export default hocAuth(function Page(props: CommonComponent) { const { shareOptions } = props; @@ -94,81 +95,154 @@ export default hocAuth(function Page(props: CommonComponent) { type={"infinite"} actionRef={actionRef} render={(orderSupplierVO: BusinessAPI.OrderSupplierVO, index) => ( - + - - - - - {orderSupplierVO.name} ( - {orderSupplierVO.orderVO?.orderVehicle?.origin}- - {orderSupplierVO.orderVO?.orderVehicle?.destination}) - - - {orderSupplierVO.poState && ( - - )} - - - - - {orderSupplierVO.orderVO?.orderVehicle?.vehicleNo - ? "第" + - orderSupplierVO.orderVO?.orderVehicle?.vehicleNo + - "车" - : "暂未生成车次"} - - - {dayjs( - orderSupplierVO.orderVO?.orderVehicle?.deliveryTime, - ).format("MM-DD")} - - | - {orderSupplierVO.netWeight}斤 - | - ¥{orderSupplierVO.invoiceAmount} - - - {`品种:${orderSupplierVO.productName}`} - + {/* 头部区域:名称 + 状态 */} + { + const imageUrls = + orderSupplierVO.invoiceImg?.map((file) => file.filePath!) || + []; + // 使用 Taro.previewImage 预览图片 + if (imageUrls?.length > 0) { + Taro.previewImage({ + urls: imageUrls, + }); + } else { + Toast.show("toast", { + title: "暂无发票图片", + icon: "none", + content: "", + }); + } + }} + > + + + {orderSupplierVO.name} + + + {orderSupplierVO.orderVO?.orderVehicle?.origin} →{" "} + {orderSupplierVO.orderVO?.orderVehicle?.destination} + + + + {orderSupplierVO.poState && ( + + )} - - - + {orderSupplierVO.orderVO?.orderVehicle?.vehicleNo + ? `第${orderSupplierVO.orderVO?.orderVehicle?.vehicleNo}车` + : "暂未生成车次"} + + + + + {dayjs( + orderSupplierVO.orderVO?.orderVehicle?.deliveryTime, + ).format("YYYY-MM-DD")} + + + + + + {orderSupplierVO.netWeight} 斤 + + + + + + ¥{orderSupplierVO.invoiceAmount} + + + + + + {orderSupplierVO.productName} + + + + + {/* 操作按钮区域 */} + + diff --git a/packages/app-client/src/pages/invoice/pending.tsx b/packages/app-client/src/pages/invoice/pending.tsx index e08ae7a..0c0f009 100644 --- a/packages/app-client/src/pages/invoice/pending.tsx +++ b/packages/app-client/src/pages/invoice/pending.tsx @@ -1,37 +1,31 @@ import { ActionType, Icon, + InvoiceBatchUpload, PageList, State, SupplierPicker, ToolBar, } from "@/components"; -import Taro, { useShareAppMessage } from "@tarojs/taro"; -import { useRef, useState } from "react"; +import { useShareAppMessage } from "@tarojs/taro"; import { business } from "@/services"; import hocAuth from "@/hocs/auth"; import { CommonComponent } from "@/types/typings"; -import { Image, View } from "@tarojs/components"; +import { Label, Text, View } from "@tarojs/components"; import dayjs from "dayjs"; -import { Button, Popup, SafeArea, Toast } from "@nutui/nutui-react-taro"; -import { uploadFile } from "@/utils"; -import { globalStore } from "@/store/global-store"; -import { DecimalUtils } from "@/utils/classes/calculators/core/DecimalUtils"; +import { Button } from "@nutui/nutui-react-taro"; import order from "@/constant/order"; +import classNames from "classnames"; +import { useRef, useState } from "react"; export default hocAuth(function Page(props: CommonComponent) { const { shareOptions } = props; const [supplierVO, setSupplierVO] = useState(); - const [popupVisible, setPopupVisible] = useState(false); + const [visible, setVisible] = useState(false); const [selectedOrders, setSelectedOrders] = useState< BusinessAPI.OrderSupplierVO[] >([]); - const { setLoading } = globalStore((state: any) => state); - - const [invoiceImg, setInvoiceImg] = useState< - BusinessAPI.OrderSupplier["invoiceImg"] - >([]); const actionRef = useRef(); const toolbar: ToolBar = { @@ -53,220 +47,14 @@ export default hocAuth(function Page(props: CommonComponent) { }, render: () => ( <> - {/* Popup 弹窗 */} - { + actionRef.current?.reload(); }} - closeable - destroyOnClose - visible={popupVisible} - title={"上传发票"} - position="bottom" - onClose={() => setPopupVisible(false)} - onOverlayClick={() => setPopupVisible(false)} - lockScroll - round - > - - {/* 统计信息 */} - - - 已选{" "} - - {selectedOrders.length} - {" "} - 车次 - - - 总重量: - {totalWeight} 斤 - - - 总金额:{" "} - - {totalAmount.toFixed(2)} - - - - - {/* 上传发票 */} - - - {invoiceImg && invoiceImg?.length > 0 ? ( - invoiceImg?.map((uploadFileItem, index) => ( - - - - - - - - {uploadFileItem.fileName} - - - {Number( - uploadFileItem.fileSize! / 1024 / 1024, - ).toFixed(2)}{" "} - MB - - - - - - - - - - - - - )) - ) : ( - - { - await Taro.chooseMessageFile({ - type: "file", - count: 1, - success: (res) => { - setLoading(true); - const file = res.tempFiles[0]; - uploadFile(file.path).then(({ url }) => { - setInvoiceImg([ - { - fileName: url.split("/").pop(), - filePath: url, - fileSize: file.size, - fileType: url.split(".").pop(), - }, - ]); - setLoading(false); - }); - }, - fail: (err) => { - Toast.show("toast", { - title: "上传失败", - icon: "fail", - content: err.errMsg, - }); - }, - }); - }} - > - - 添加文档 - - 上传PDF文档 - - - - { - await Taro.chooseImage({ - count: 1, - success: (res) => { - setLoading(true); - const file = res.tempFiles[0]; - uploadFile(file.path).then(({ url }) => { - setInvoiceImg([ - { - fileName: url.split("/").pop(), - filePath: url, - fileSize: file.size, - fileType: url.split(".").pop(), - }, - ]); - - setLoading(false); - }); - }, - fail: (err) => { - Toast.show("toast", { - title: "上传失败", - icon: "fail", - content: err.errMsg, - }); - }, - }); - }} - > - - 添加照片 - - 上传单张照片 - - - - )} - - - - - - - - {/* 提交按钮 */} - - - - - - - + /> { - return selectedOrders.reduce( - (totals, order) => { - totals.totalWeight = DecimalUtils.add( - totals.totalWeight, - order.netWeight || 0, - ); - totals.totalAmount = DecimalUtils.add( - totals.totalAmount, - order.invoiceAmount || 0, - ); - return totals; - }, - { totalWeight: 0, totalAmount: 0 }, - ); - }; - - const { totalWeight, totalAmount } = calculateTotals(); - - // 提交申请 - const handleSubmit = async () => { - // 这里添加提交申请的逻辑 - const { - data: { success }, - } = await business.orderSupplier.batchUploadInvoice({ - orderSupplierIdList: selectedOrders.map((order) => order.orderSupplierId), - invoiceImg: invoiceImg, - invoiceUpload: true, - }); - - if (success) { - Toast.show("toast", { - icon: "success", - title: "提交成功", - content: "", - }); - } - - actionRef.current?.reload(); - setPopupVisible(false); - setInvoiceImg([]); - }; - return ( <> @@ -365,70 +109,123 @@ export default hocAuth(function Page(props: CommonComponent) { type={"infinite"} actionRef={actionRef} render={(orderSupplierVO: BusinessAPI.OrderSupplierVO, index) => ( - + - - - - - {orderSupplierVO.name} ( - {orderSupplierVO.orderVO?.orderVehicle?.origin}- - {orderSupplierVO.orderVO?.orderVehicle?.destination}) - - - {orderSupplierVO.poState && ( - - )} - - - - - {orderSupplierVO.orderVO?.orderVehicle?.vehicleNo - ? "第" + - orderSupplierVO.orderVO?.orderVehicle?.vehicleNo + - "车" - : "暂未生成车次"} - - - {dayjs( - orderSupplierVO.orderVO?.orderVehicle?.deliveryTime, - ).format("MM-DD")} - - | - {orderSupplierVO.netWeight}斤 - | - ¥{orderSupplierVO.invoiceAmount} - - - {`品种:${orderSupplierVO.productName}`} - + {/* 头部区域:名称 + 状态 */} + + + + {orderSupplierVO.name} + + + {orderSupplierVO.orderVO?.orderVehicle?.origin} →{" "} + {orderSupplierVO.orderVO?.orderVehicle?.destination} + + + + {orderSupplierVO.poState && ( + + )} - - - {!orderSupplierVO.invoiceUpload && - (orderSupplierVO.poState === "WAITING_AUDIT" || - orderSupplierVO.poState === "COMPLETED") && ( - + + {/* 详细信息区域 */} + + + + + {orderSupplierVO.orderVO?.orderVehicle?.vehicleNo + ? `第${orderSupplierVO.orderVO?.orderVehicle?.vehicleNo}车` + : "暂未生成车次"} + + + + + {dayjs( + orderSupplierVO.orderVO?.orderVehicle?.deliveryTime, + ).format("YYYY-MM-DD")} + + + + + + {orderSupplierVO.netWeight} 斤 + + + + + + ¥{orderSupplierVO.invoiceAmount} + + + + + + {orderSupplierVO.productName} + + + {/* 发票状态提示 */} + {orderSupplierVO.invoiceUpload ? ( + + + + 已上传发票 + + + ) : ( + + + + 待上传发票 + + + )} + + + {/* 操作按钮区域 */} + + {!orderSupplierVO.invoiceUpload && + (orderSupplierVO.poState === "WAITING_AUDIT" || + orderSupplierVO.poState === "COMPLETED") && ( + + )} diff --git a/packages/app-client/src/pages/invoice/upload.tsx b/packages/app-client/src/pages/invoice/upload.tsx index 9b6d25d..fdabc01 100644 --- a/packages/app-client/src/pages/invoice/upload.tsx +++ b/packages/app-client/src/pages/invoice/upload.tsx @@ -1,48 +1,87 @@ import { ActionType, Icon, + InvoiceBatchUpload, PageList, State, SupplierPicker, ToolBar, } from "@/components"; -import Taro, { useShareAppMessage } from "@tarojs/taro"; +import { useShareAppMessage } from "@tarojs/taro"; import { useRef, useState } from "react"; import { business } from "@/services"; import hocAuth from "@/hocs/auth"; import { CommonComponent } from "@/types/typings"; -import { Image, View } from "@tarojs/components"; +import { Text, View } from "@tarojs/components"; import dayjs from "dayjs"; -import { Button, Popup, SafeArea, Toast } from "@nutui/nutui-react-taro"; -import { uploadFile } from "@/utils"; -import { globalStore } from "@/store/global-store"; -import { DecimalUtils } from "@/utils/classes/calculators/core/DecimalUtils"; import order from "@/constant/order"; +import classNames from "classnames"; +import { Button, Checkbox, SafeArea } from "@nutui/nutui-react-taro"; +import { DecimalUtils } from "@/utils/classes/calculators/core/DecimalUtils"; export default hocAuth(function Page(props: CommonComponent) { const { shareOptions } = props; const [supplierVO, setSupplierVO] = useState(); - const [popupVisible, setPopupVisible] = useState(false); + const [visible, setVisible] = useState(false); const [selectedOrders, setSelectedOrders] = useState< BusinessAPI.OrderSupplierVO[] >([]); - const { setLoading } = globalStore((state: any) => state); - - const [invoiceImg, setInvoiceImg] = useState< - BusinessAPI.OrderSupplier["invoiceImg"] - >([]); + const [selectedIds, setSelectedIds] = useState>(new Set()); const actionRef = useRef(); - const toolbar: ToolBar = { - selectRow: { - onClick: async (orderSupplierVOList: BusinessAPI.OrderSupplierVO[]) => { - console.log("orderSupplierVOList", orderSupplierVOList); - // 点击弹出popup - setSelectedOrders(orderSupplierVOList); - setPopupVisible(true); + + // 切换选中状态 + const toggleSelect = (orderSupplierVO: BusinessAPI.OrderSupplierVO) => { + const newSelectedIds = new Set(selectedIds); + if (newSelectedIds.has(orderSupplierVO.orderSupplierId)) { + newSelectedIds.delete(orderSupplierVO.orderSupplierId); + setSelectedOrders( + selectedOrders.filter( + (orderSupplierVO) => + orderSupplierVO.orderSupplierId !== orderSupplierVO.orderSupplierId, + ), + ); + } else { + newSelectedIds.add(orderSupplierVO.orderSupplierId); + setSelectedOrders([...selectedOrders, orderSupplierVO]); + } + setSelectedIds(newSelectedIds); + }; + + // 全选/取消全选 + const toggleSelectAll = (allIds: string[]) => { + if (selectedIds.size === allIds.length) { + // 取消全选 + setSelectedIds(new Set()); + } else { + // 全选 + setSelectedIds(new Set(allIds)); + } + }; + + // 计算选中订单的总重量和总金额 + const calculateSelectedTotals = (data: BusinessAPI.OrderSupplierVO[]) => { + const selected = data.filter((item) => + selectedIds.has(item.orderSupplierId), + ); + return selected.reduce( + (totals, order) => { + totals.totalWeight = DecimalUtils.add( + totals.totalWeight, + order.netWeight || 0, + ); + totals.totalAmount = DecimalUtils.add( + totals.totalAmount, + order.invoiceAmount || 0, + ); + return totals; }, - }, + { totalWeight: 0, totalAmount: 0 }, + ); + }; + + const toolbar: ToolBar = { search: { activeKey: "vehicleNo", defaultActiveKey: "vehicleNo", @@ -59,256 +98,125 @@ export default hocAuth(function Page(props: CommonComponent) { }, ], }, - render: () => ( - <> - {/* Popup 弹窗 */} - setPopupVisible(false)} - onOverlayClick={() => setPopupVisible(false)} - lockScroll - round - > - - {/* 统计信息 */} - - - 已选{" "} - - {selectedOrders.length} - {" "} - 车次 - - - 总重量: - {totalWeight} 斤 - - - 总金额:{" "} - - {totalAmount.toFixed(2)} - - - - - {/* 上传发票 */} - - - {invoiceImg && invoiceImg?.length > 0 ? ( - invoiceImg?.map((uploadFileItem, index) => ( - - - - - - - - {uploadFileItem.fileName} - - - {Number( - uploadFileItem.fileSize! / 1024 / 1024, - ).toFixed(2)}{" "} - MB - - - - - - - - - - - - - )) - ) : ( - - { - await Taro.chooseMessageFile({ - type: "file", - count: 1, - success: (res) => { - setLoading(true); - const file = res.tempFiles[0]; - uploadFile(file.path).then(({ url }) => { - setInvoiceImg([ - { - fileName: url.split("/").pop(), - filePath: url, - fileSize: file.size, - fileType: url.split(".").pop(), - }, - ]); - setLoading(false); - }); - }, - fail: (err) => { - Toast.show("toast", { - title: "上传失败", - icon: "fail", - content: err.errMsg, - }); - }, - }); - }} - > - - 添加文档 - - 上传PDF文档 - - - - { - await Taro.chooseImage({ - count: 1, - success: (res) => { - setLoading(true); - const file = res.tempFiles[0]; - uploadFile(file.path).then(({ url }) => { - setInvoiceImg([ - { - fileName: url.split("/").pop(), - filePath: url, - fileSize: file.size, - fileType: url.split(".").pop(), - }, - ]); - - setLoading(false); - }); - }, - fail: (err) => { - Toast.show("toast", { - title: "上传失败", - icon: "fail", - content: err.errMsg, - }); - }, - }); - }} - > - - 添加照片 - - 上传单张照片 - - - - )} - - - - - - - - {/* 提交按钮 */} - - - - - - - - - - { - setSupplierVO(supplierVO); + render: () => { + return ( + <> + {/* Popup 弹窗 */} + { actionRef.current?.reload(); + setSelectedIds(new Set()); }} - trigger={ - - - {supplierVO?.name || "瓜农"} - - {supplierVO?.name ? ( - { - setSupplierVO(undefined); - actionRef.current?.reload(); - event.stopPropagation(); - }} - /> - ) : ( - - )} - - } /> + + + { + setSupplierVO(supplierVO); + actionRef.current?.reload(); + }} + trigger={ + + + {supplierVO?.name || "瓜农"} + + {supplierVO?.name ? ( + { + setSupplierVO(undefined); + actionRef.current?.reload(); + event.stopPropagation(); + }} + /> + ) : ( + + )} + + } + /> + + + ); + }, + footer: (data: BusinessAPI.OrderSupplierVO[]) => { + const allIds = data.map((item) => item.orderSupplierId); + const isSelectedAll = + selectedIds.size === allIds.length && allIds.length > 0; + const totals = calculateSelectedTotals(data); + return ( + + {/* 批量操作栏 */} + {selectedIds.size > 0 && ( + + + toggleSelectAll(allIds)} + /> + + + 已选 {selectedIds.size} 项 + + + 总重: {totals.totalWeight}斤 | 金额: ¥ + {totals.totalAmount.toFixed(2)} + + + + + + + + + )} + + {/* 全选按钮 */} + {selectedIds.size === 0 && data.length > 0 && ( + + toggleSelectAll(allIds)} + > + + 全选当前页 + + + )} + - - ), + ); + }, }; useShareAppMessage((res) => { @@ -321,70 +229,65 @@ export default hocAuth(function Page(props: CommonComponent) { return {}; }); - // 计算选中车次的总重量和总金额 - const calculateTotals = () => { - return selectedOrders.reduce( - (totals, order) => { - totals.totalWeight = DecimalUtils.add( - totals.totalWeight, - order.netWeight || 0, - ); - totals.totalAmount = DecimalUtils.add( - totals.totalAmount, - order.invoiceAmount || 0, - ); - return totals; - }, - { totalWeight: 0, totalAmount: 0 }, - ); - }; - - const { totalWeight, totalAmount } = calculateTotals(); - - // 提交申请 - const handleSubmit = async () => { - // 这里添加提交申请的逻辑 - const { - data: { success }, - } = await business.orderSupplier.batchUploadInvoice({ - orderSupplierIdList: selectedOrders.map((order) => order.orderSupplierId), - invoiceImg: invoiceImg, - invoiceUpload: true, - }); - - if (success) { - Toast.show("toast", { - icon: "success", - title: "提交成功", - content: "", - }); - } - - actionRef.current?.reload(); - setPopupVisible(false); - setInvoiceImg([]); - }; - return ( <> rowId={"orderSupplierId"} - itemHeight={182} + itemHeight={100} type={"infinite"} actionRef={actionRef} - render={(orderSupplierVO: BusinessAPI.OrderSupplierVO, index) => ( - + render={(orderSupplierVO: BusinessAPI.OrderSupplierVO, index) => { + const isSelected = selectedIds.has(orderSupplierVO.orderSupplierId); + return ( - - - - {orderSupplierVO.name} ( - {orderSupplierVO.orderVO?.orderVehicle.origin}- - {orderSupplierVO.orderVO?.orderVehicle.destination}) + + {/* 选中遮罩层 */} + {isSelected && ( + + )} + + {/* 复选框 + 头部区域 */} + { + // 点击卡片切换选中状态 + e.stopPropagation(); + toggleSelect(orderSupplierVO); + }} + > + + { + e.stopPropagation(); + toggleSelect(orderSupplierVO); + }} + /> + + + {orderSupplierVO.name} + + + + {orderSupplierVO.orderVO?.orderVehicle?.origin} →{" "} + {orderSupplierVO.orderVO?.orderVehicle?.destination} + + + - + {orderSupplierVO.poState && ( )} + {/* 发票状态提示 */} + {orderSupplierVO.invoiceUpload ? ( + + + 已上传 + + ) : ( + + + 待上传 + + )} - - - {orderSupplierVO.orderVO?.orderVehicle?.vehicleNo - ? "第" + - orderSupplierVO.orderVO?.orderVehicle?.vehicleNo + - "车" - : "暂未生成车次"} + + {/* 详细信息区域 - 紧凑一行显示 */} + { + // 点击详细信息区域也切换选中状态 + e.stopPropagation(); + toggleSelect(orderSupplierVO); + }} + > + + + {orderSupplierVO.orderVO?.orderVehicle?.vehicleNo + ? `第${orderSupplierVO.orderVO?.orderVehicle?.vehicleNo}车` + : "暂未生成车次"} + + | + + {dayjs( + orderSupplierVO.orderVO?.orderVehicle?.deliveryTime, + ).format("MM-DD")} + + | + {orderSupplierVO.netWeight}斤 + | + ¥{orderSupplierVO.invoiceAmount} - - {dayjs( - orderSupplierVO.orderVO?.orderVehicle?.deliveryTime, - ).format("MM-DD")} - - | - {orderSupplierVO.netWeight}斤 - | - ¥{orderSupplierVO.invoiceAmount} - - - {`品种:${orderSupplierVO.productName}`} + + {orderSupplierVO.productName} + - - )} + ); + }} toolbar={toolbar} request={async (params) => { const { diff --git a/packages/app-client/src/pages/supplier/all.tsx b/packages/app-client/src/pages/supplier/all.tsx index 76b104c..6c241d3 100644 --- a/packages/app-client/src/pages/supplier/all.tsx +++ b/packages/app-client/src/pages/supplier/all.tsx @@ -60,134 +60,132 @@ export default hocAuth(function Page(props: CommonComponent) { type={"infinite"} actionRef={actionRef} render={(supplierVO: BusinessAPI.SupplierVO, index) => ( - + - - - - - - {/* 复制 */} - - {supplierVO?.name} - - - - - )} - {/* 新建采购 */} + + {/* 操作按钮区域 */} + + {supplierVO.phone && ( - {/* 协助开票 */} - - + )} + +