feat(purchase): 新增采购订单相关列表组件及常量配置

- 新增 PurchaseOrderList、PurchaseOrderAuditList、PurchaseOrderApprovalList 三个列表组件
- 在 purchase/index.ts 中导出新增的三个组件
- 更新 purchaseOrder 常量配置,增加审核与审批相关的状态列表和映射
- 修改 PageList 组件从 globalStore 获取 loading 状态
- 调整部分页面路径配置
- 新增发票上传相关页面及功能实现
- 优化部分组件导入和状态管理逻辑
This commit is contained in:
shenyifei 2025-11-24 23:28:26 +08:00
parent d37626d5bf
commit 4276945320
62 changed files with 3065 additions and 1455 deletions

View File

@ -18,24 +18,40 @@ config = {
{ {
root: "pages/purchase", root: "pages/purchase",
pages: [ pages: [
"history", // 全部采购
"enter/all",
// 采购员(市场/产地) // 创建采购单
"purchaser/create", "enter/create",
"purchaser/preview", // 预览采购单
"purchaser/result", "enter/preview",
// 采购员(草稿) // 采购单提审结果页面
"purchaser/draft/list", "enter/result",
// 采购单草稿箱
// 审核员(报价) "enter/drafts",
"reviewer/audit/audit", // 采购单审核
"reviewer/audit/list", "audit/audit",
"reviewer/audit/result", // 采购单待审核
"audit/pending",
// 审批员(老板) // 采购单审核中
"approver/audit/audit", "audit/reviewing",
"approver/audit/list", // 采购单审核结果页面
"approver/audit/result", "audit/result",
// 采购单审核拒绝
"audit/rejected",
// 全部采购单审核
"audit/all",
// 采购单审批
"approval/audit",
// 采购单待审批
"approval/pending",
// 采购单审批中
"approval/reviewing",
// 采购单审批结果页面
"approval/result",
// 采购单审批拒绝
"approval/rejected",
// 全部采购单审批
"approval/all",
], ],
}, },
// 发货单 // 发货单
@ -46,7 +62,12 @@ config = {
// 瓜农 // 瓜农
{ {
root: "pages/supplier", root: "pages/supplier",
pages: ["list", "purchase/invoice"], pages: ["create", "all"],
},
// 发票
{
root: "pages/invoice",
pages: ["upload", "all", "pending"],
}, },
], ],
permission: { permission: {

View File

@ -18,6 +18,7 @@ import {
} from "@nutui/nutui-react-taro"; } from "@nutui/nutui-react-taro";
import { Icon } from "@/components"; import { Icon } from "@/components";
import classNames from "classnames"; import classNames from "classnames";
import { globalStore } from "@/store/global-store";
import { ActionType, IRecordListProps, Query, Record } from "./typing"; import { ActionType, IRecordListProps, Query, Record } from "./typing";
export default <T extends {}, Q extends Query = Query>( export default <T extends {}, Q extends Query = Query>(
@ -47,8 +48,7 @@ export default <T extends {}, Q extends Query = Query>(
toolbar?.search?.defaultActiveKey || "", toolbar?.search?.defaultActiveKey || "",
); );
const [loading, setLoading] = useState<boolean>(true); const { loading, setLoading } = globalStore((state: any) => state);
const [lightTheme, setLightTheme] = useState(false); const [lightTheme, setLightTheme] = useState(false);
const [data, setData] = useState<Record<any>[]>(); const [data, setData] = useState<Record<any>[]>();
const [query, setQuery] = useState<Query>(); const [query, setQuery] = useState<Query>();

View File

@ -0,0 +1,256 @@
import {
ActionType,
DealerPicker,
Icon,
PageList,
PurchaseOrderRejectFinal,
State,
SupplierPicker,
ToolBar,
} from "@/components";
import React, { useRef, useState } from "react";
import { business } from "@/services";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
import dayjs from "dayjs";
import purchaseOrder from "@/constant/purchaseOrder";
import Taro from "@tarojs/taro";
interface IPurchaseOrderApprovalListProps {
params: BusinessAPI.PurchaseOrderPageQry;
toolbar?: ToolBar;
actionRef?: React.MutableRefObject<ActionType | undefined>;
}
export default function PurchaseOrderApprovalList(
props: IPurchaseOrderApprovalListProps,
) {
const {
params: bizParams,
toolbar: defaultToolbar,
actionRef: externalActionRef,
} = props;
const internalActionRef = useRef<ActionType>();
const actionRef = externalActionRef || internalActionRef;
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierVO>();
const toolbar: ToolBar = {
...defaultToolbar,
search: {
activeKey: "plate",
defaultActiveKey: "plate",
items: [
{
key: "plate",
name: "车牌号",
placeholder: "请输入车牌号",
},
],
},
render: () => (
<View className={"item-start flex flex-row gap-2.5"}>
<View>
<DealerPicker
onFinish={(dealerVO) => {
setDealerVO(dealerVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{dealerVO?.shortName || "经销商"}
</View>
{dealerVO?.shortName ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setDealerVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
<View>
<SupplierPicker
onFinish={(supplierVO) => {
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{supplierVO?.name || "瓜农"}
</View>
{supplierVO?.name ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setSupplierVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
</View>
),
};
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
toolbar={toolbar}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View className={"flex flex-col divide-y-2 divide-neutral-100"}>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
{/* 复制 */}
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle.dealerName}{" "}
{purchaseOrderVO.orderVehicle?.vehicleNo
? "第" +
purchaseOrderVO.orderVehicle?.vehicleNo +
"车"
: "暂未生成车次"}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
{purchaseOrderVO.orderVehicle?.origin} {" 至 "}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<State
state={purchaseOrderVO.auditState}
stateMap={purchaseOrder.approvalStateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.createdByName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
</View>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{purchaseOrderVO.state === "WAITING_AUDIT" &&
purchaseOrderVO.auditState === "PENDING_BOSS_APPROVAL" && (
<View className={"flex flex-row justify-end gap-2"}>
<PurchaseOrderRejectFinal
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/approval/audit", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
</View>
</View>
</View>
</View>
);
}}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
...bizParams,
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
}

View File

@ -0,0 +1,256 @@
import {
ActionType,
DealerPicker,
Icon,
PageList,
PurchaseOrderRejectApprove,
State,
SupplierPicker,
ToolBar,
} from "@/components";
import React, { useRef, useState } from "react";
import { business } from "@/services";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
import dayjs from "dayjs";
import purchaseOrder from "@/constant/purchaseOrder";
import Taro from "@tarojs/taro";
interface IPurchaseOrderAuditListProps {
params: BusinessAPI.PurchaseOrderPageQry;
toolbar?: ToolBar;
actionRef?: React.MutableRefObject<ActionType | undefined>;
}
export default function PurchaseOrderAuditList(
props: IPurchaseOrderAuditListProps,
) {
const {
params: bizParams,
toolbar: defaultToolbar,
actionRef: externalActionRef,
} = props;
const internalActionRef = useRef<ActionType>();
const actionRef = externalActionRef || internalActionRef;
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierVO>();
const toolbar: ToolBar = {
...defaultToolbar,
search: {
activeKey: "plate",
defaultActiveKey: "plate",
items: [
{
key: "plate",
name: "车牌号",
placeholder: "请输入车牌号",
},
],
},
render: () => (
<View className={"item-start flex flex-row gap-2.5"}>
<View>
<DealerPicker
onFinish={(dealerVO) => {
setDealerVO(dealerVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{dealerVO?.shortName || "经销商"}
</View>
{dealerVO?.shortName ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setDealerVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
<View>
<SupplierPicker
onFinish={(supplierVO) => {
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{supplierVO?.name || "瓜农"}
</View>
{supplierVO?.name ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setSupplierVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
</View>
),
};
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
toolbar={toolbar}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View className={"flex flex-col divide-y-2 divide-neutral-100"}>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
{/* 复制 */}
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle.dealerName}{" "}
{purchaseOrderVO.orderVehicle?.vehicleNo
? "第" +
purchaseOrderVO.orderVehicle?.vehicleNo +
"车"
: "暂未生成车次"}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
{purchaseOrderVO.orderVehicle?.origin} {" 至 "}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<State
state={purchaseOrderVO.auditState}
stateMap={purchaseOrder.auditStateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.createdByName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
</View>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{purchaseOrderVO.state === "WAITING_AUDIT" &&
purchaseOrderVO.auditState === "PENDING_QUOTE_APPROVAL" && (
<View className={"flex flex-row justify-end gap-2"}>
<PurchaseOrderRejectApprove
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/audit/audit", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
</View>
</View>
</View>
</View>
);
}}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
...bizParams,
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
}

View File

@ -0,0 +1,400 @@
import {
ActionType,
CopyText,
DealerPicker,
Icon,
PageList,
PurchaseOrderWithdrawReview,
State,
SupplierPicker,
ToolBar,
} from "@/components";
import React, { useRef, useState } from "react";
import { business } from "@/services";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl } from "@/utils";
import { Button, Dialog, Toast } from "@nutui/nutui-react-taro";
import dayjs from "dayjs";
import purchaseOrder from "@/constant/purchaseOrder";
import Taro from "@tarojs/taro";
interface IPurchaseOrderListProps {
params: BusinessAPI.PurchaseOrderPageQry;
create?: boolean;
toolbar?: ToolBar;
actionRef?: React.MutableRefObject<ActionType | undefined>;
}
export default function PurchaseOrderList(props: IPurchaseOrderListProps) {
const {
params: bizParams,
create = false,
toolbar: defaultToolbar,
actionRef: externalActionRef,
} = props;
const internalActionRef = useRef<ActionType>();
const actionRef = externalActionRef || internalActionRef;
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierVO>();
const toolbar: ToolBar = {
...defaultToolbar,
search: {
activeKey: "plate",
defaultActiveKey: "plate",
items: [
{
key: "plate",
name: "车牌号",
placeholder: "请输入车牌号",
},
],
},
render: () => (
<View className={"item-start flex flex-row gap-2.5"}>
<View>
<DealerPicker
onFinish={(dealerVO) => {
setDealerVO(dealerVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{dealerVO?.shortName || "经销商"}
</View>
{dealerVO?.shortName ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setDealerVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
<View>
<SupplierPicker
onFinish={(supplierVO) => {
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{supplierVO?.name || "瓜农"}
</View>
{supplierVO?.name ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setSupplierVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
</View>
),
actions: [
create && (
<View className={"flex flex-row gap-2 p-3"} key={"create"}>
<View className={"flex-1"}>
<View
className="bg-primary flex w-full flex-col items-center justify-center space-y-2 rounded-xl py-2.5 text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/enter/create"),
});
}}
>
<View className="text-base font-bold"></View>
</View>
</View>
</View>
),
],
};
// 删除采购订单
const handleDelete = (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => {
Dialog.open("dialog", {
title: "删除采购单",
content: `确定要删除这个采购单吗?删除后就找不回来了!`,
confirmText: "确定",
cancelText: "取消",
onConfirm: async () => {
try {
const { data } = await business.purchaseOrder.destroyPurchaseOrder({
orderId: purchaseOrderVO.orderId,
});
if (data.success) {
Toast.show("toast", {
icon: "success",
title: "提示",
content: "采购单删除成功",
});
actionRef.current?.reload();
} else {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: data.errMessage || "删除失败",
});
}
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "删除失败",
});
} finally {
Dialog.close("dialog");
}
},
onCancel: () => {
Dialog.close("dialog");
},
});
};
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View
className={"flex flex-col divide-y-2 divide-neutral-100"}
onClick={(event) => {
if (purchaseOrderVO.active === 7) {
Taro.navigateTo({
url: buildUrl("/pages/purchase/enter/preview", {
orderId: purchaseOrderVO.orderId,
}),
});
event.stopPropagation();
}
}}
>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle?.origin} {" 至 "}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
<CopyText copyData={purchaseOrderVO.orderSn}>
{purchaseOrderVO.orderSn}
</CopyText>
</Text>
</View>
<State
state={purchaseOrderVO.state}
stateMap={purchaseOrder.stateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(
purchaseOrderVO.orderVehicle?.deliveryTime,
).format("YYYY年MM月DD日")}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle.dealerName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.driver}
{purchaseOrderVO.orderVehicle?.plate}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSupplierList
.map((item) => item.name)
.join(",")}
</Text>
</View>
</View>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{purchaseOrderVO.state === "DRAFT" && (
<>
<Button
type={"danger"}
size={"small"}
onClick={(e) => {
handleDelete(purchaseOrderVO);
e.stopPropagation();
}}
>
</Button>
{/* 联系司机 */}
{purchaseOrderVO.orderVehicle.phone && (
<Button
type={"default"}
size={"small"}
onClick={(e) => {
Taro.makePhoneCall({
phoneNumber: purchaseOrderVO.orderVehicle
.phone as string,
});
e.stopPropagation();
}}
>
</Button>
)}
<Button
type={"default"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/enter/create", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
{purchaseOrderVO.active === 7 && (
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/enter/preview", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
)}
</>
)}
{purchaseOrderVO.state === "WAITING_AUDIT" && (
<>
<PurchaseOrderWithdrawReview
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
</>
)}
</View>
</View>
</View>
</View>
);
}}
toolbar={toolbar}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
...bizParams,
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
}

View File

@ -88,7 +88,7 @@ export default function PurchaseOrderSubmitReview(
cancelText: "取消", cancelText: "取消",
onConfirm: async () => { onConfirm: async () => {
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/purchaser/create", { url: buildUrl("/pages/purchase/enter/create", {
orderId: purchaseOrderVO.orderId, orderId: purchaseOrderVO.orderId,
supplierId: lastSupplier.supplierId, supplierId: lastSupplier.supplierId,
step: "2", step: "2",
@ -120,7 +120,7 @@ export default function PurchaseOrderSubmitReview(
cancelText: "取消", cancelText: "取消",
onConfirm: async () => { onConfirm: async () => {
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/purchaser/create", { url: buildUrl("/pages/purchase/enter/create", {
orderId: purchaseOrderVO.orderId, orderId: purchaseOrderVO.orderId,
supplierId: hasNoUpdateContractSupplier.supplierId, supplierId: hasNoUpdateContractSupplier.supplierId,
step: "5", step: "5",

View File

@ -41,3 +41,7 @@ export { default as PurchaseStep1Form } from "./document/Step1Form";
export type { Step1FormRef as PurchaseStep1FormRef } from "./document/Step1Form"; export type { Step1FormRef as PurchaseStep1FormRef } from "./document/Step1Form";
export { default as PurchaseStep2Preview } from "./document/Step2Preview"; export { default as PurchaseStep2Preview } from "./document/Step2Preview";
export { default as PurchaseStep3Success } from "./document/Step3Success"; export { default as PurchaseStep3Success } from "./document/Step3Success";
export { default as PurchaseOrderList } from "./PurchaseOrderList";
export { default as PurchaseOrderAuditList } from "./PurchaseOrderAuditList";
export { default as PurchaseOrderApprovalList } from "./PurchaseOrderApprovalList";

View File

@ -1,41 +1,15 @@
/** /**
* 采购订单状态: 0_草稿1_审核中2_审批中3_待发货4_已发货5_已付款6_已完结7_已驳回8_已关闭 *
DRAFT(0, "草稿"),
WAITING_AUDIT(1, "审核中"),
WAITING_APPROVE(2, "审批中"),
WAITING_SHIPMENT(3, "待发货"),
SHIPPED(4, "已发货"),
PAID(5, "已付款"),
COMPLETED(6, "已完结"),
REJECTED(7, "已驳回"),
*/ */
const stateList = [ const stateList = [
{ {
title: "全部", title: "草稿",
value: "ALL", value: "DRAFT",
}, },
{ {
title: "审核中", title: "审核中",
value: "WAITING_AUDIT", value: "WAITING_AUDIT",
}, },
{
title: "审批中",
value: "WAITING_APPROVE",
},
{
title: "待发货",
value: "WAITING_SHIPMENT",
},
{
title: "已发货",
value: "SHIPPED",
},
{
title: "已付款",
value: "PAID",
},
{ {
title: "已完结", title: "已完结",
value: "COMPLETED", value: "COMPLETED",
@ -44,9 +18,11 @@ const stateList = [
title: "已驳回", title: "已驳回",
value: "REJECTED", value: "REJECTED",
}, },
{
title: "已关闭",
value: "CLOSED",
},
]; ];
// 定义需求状态映射 - 优化颜色方案
const stateMap = { const stateMap = {
DRAFT: { DRAFT: {
label: "草稿", label: "草稿",
@ -55,35 +31,11 @@ const stateMap = {
borderColor: "#EA580C", borderColor: "#EA580C",
}, },
WAITING_AUDIT: { WAITING_AUDIT: {
label: "审核", label: "审核",
color: "#1E40AF", color: "#1E40AF",
bgColor: "#DBEAFE", bgColor: "#DBEAFE",
borderColor: "#3B82F6", borderColor: "#3B82F6",
}, },
WAITING_APPROVE: {
label: "待老板审批",
color: "#7C2D12",
bgColor: "#FDE68A",
borderColor: "#F59E0B",
},
WAITING_SHIPMENT: {
label: "待发货",
color: "#7C2D12",
bgColor: "#FDE68A",
borderColor: "#F59E0B",
},
SHIPPED: {
label: "已发货(待付款)",
color: "#86198F",
bgColor: "#F3E8FF",
borderColor: "#A855F7",
},
PAID: {
label: "已付款",
color: "#065F46",
bgColor: "#A7F3D0",
borderColor: "#10B981",
},
COMPLETED: { COMPLETED: {
label: "已完结", label: "已完结",
color: "#374151", color: "#374151",
@ -95,10 +47,106 @@ const stateMap = {
color: "#991B1B", color: "#991B1B",
bgColor: "#FEE2E2", bgColor: "#FEE2E2",
borderColor: "#EF4444", borderColor: "#EF4444",
} },
CLOSED: {
label: "已关闭",
color: "#6B7280",
bgColor: "#F3F4F6",
borderColor: "#6B7280",
},
};
/**
*
*/
const auditStateList = [
{
title: "待我审核",
value: "PENDING_QUOTE_APPROVAL",
},
{
title: "审批中",
value: "PENDING_BOSS_APPROVAL",
},
{
title: "已通过",
value: "BOSS_APPROVED",
},
{
title: "已驳回",
value: "BOSS_REJECTED",
},
];
const auditStateMap = {
PENDING_QUOTE_APPROVAL: {
label: "待我审核",
color: "#7C2D12",
bgColor: "#FED7AA",
borderColor: "#EA580C",
},
PENDING_BOSS_APPROVAL: {
label: "审批中",
color: "#1E40AF",
bgColor: "#DBEAFE",
borderColor: "#3B82F6",
},
BOSS_APPROVED: {
label: "已通过",
color: "#374151",
bgColor: "#E5E7EB",
borderColor: "#6B7280",
},
BOSS_REJECTED: {
label: "已驳回",
color: "#6B7280",
bgColor: "#F3F4F6",
borderColor: "#6B7280",
},
};
/**
*
*/
const approvalStateList = [
{
title: "待我审批",
value: "PENDING_BOSS_APPROVAL",
},
{
title: "已通过",
value: "BOSS_APPROVED",
},
{
title: "已驳回",
value: "BOSS_REJECTED",
},
];
const approvalStateMap = {
PENDING_BOSS_APPROVAL: {
label: "待我审批",
color: "#7C2D12",
bgColor: "#FED7AA",
borderColor: "#EA580C",
},
BOSS_APPROVED: {
label: "已通过",
color: "#374151",
bgColor: "#E5E7EB",
borderColor: "#6B7280",
},
BOSS_REJECTED: {
label: "已驳回",
color: "#991B1B",
bgColor: "#FEE2E2",
borderColor: "#EF4444",
},
}; };
export default { export default {
stateList, stateList,
stateMap: stateMap, stateMap,
auditStateList,
auditStateMap,
approvalStateList,
approvalStateMap,
}; };

View File

@ -170,7 +170,7 @@ const quickActionMap = {
icon: "file-signature", icon: "file-signature",
iconColor: "var(--color-primary)", iconColor: "var(--color-primary)",
bgColorClass: "bg-primary/10", bgColorClass: "bg-primary/10",
path: "/pages/purchase/reviewer/audit/list", path: "/pages/purchase/audit/pending",
}, },
{ {
id: "history", id: "history",

View File

@ -16,11 +16,12 @@ const hocAuth = (
base((props: any) => { base((props: any) => {
const { options, router } = props; const { options, router } = props;
const user = userStore(useShallow((state) => state.user)); const user = userStore(useShallow((state) => state.user));
const { userRoleVO, setUserRoleVO } = globalStore((state: any) => state); const { userRoleVO, setUserRoleVO, loading, setLoading } = globalStore(
(state: any) => state,
);
const [longitude, setLongitude] = useState<number>(); const [longitude, setLongitude] = useState<number>();
const [latitude, setLatitude] = useState<number>(); const [latitude, setLatitude] = useState<number>();
const [loading, setLoading] = useState<boolean>(false);
// 控制是否已初始化 // 控制是否已初始化
const [isInitialized, setIsInitialized] = useState(false); const [isInitialized, setIsInitialized] = useState(false);

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "上传发票",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,362 @@
import {
ActionType,
Icon,
PageList,
SupplierPicker,
ToolBar,
} from "@/components";
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 { View } from "@tarojs/components";
import dayjs from "dayjs";
import {
Button,
Popup,
SafeArea,
Toast,
Uploader,
UploaderFileItem,
} from "@nutui/nutui-react-taro";
import { uploadFile } from "@/utils";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierVO>();
const [popupVisible, setPopupVisible] = useState(false);
const [selectedOrders, setSelectedOrders] = useState<
BusinessAPI.OrderSupplierVO[]
>([]);
const [contractFiles, setContractFiles] = useState<any[]>([]);
const [invoiceFiles, setInvoiceFiles] = useState<any[]>([]);
// 发票照片
const [invoiceImgList, setInvoiceImgList] = useState<UploaderFileItem[]>([]);
// 合同照片
const [contractImgList, setContractImgList] = useState<UploaderFileItem[]>(
[],
);
// 发票照片变更处理函数
const handleInvoiceImgChange = (files: UploaderFileItem[]) => {
setInvoiceImgList(files);
// 如果有文件且上传成功保存URL到supplierVO
if (files.length > 0 && files[0].url) {
setSupplierVO((prev) => ({
...prev!,
invoiceImg: [files[0].url!],
invoiceUpload: true,
}));
} else {
// 如果没有文件清空URL
setSupplierVO((prev) => ({
...prev!,
invoiceImg: undefined,
invoiceUpload: false,
}));
}
};
// 合同照片变更处理函数
const handleContractImgChange = (files: UploaderFileItem[]) => {
setContractImgList(files);
// 保存所有文件URL到supplierVO
const urls = files.map((file) => file.url).filter((url) => url) as string[];
setSupplierVO((prev) => ({
...prev!,
contractImg: urls,
contractUpload: urls.length > 0,
}));
};
const actionRef = useRef<ActionType>();
const toolbar: ToolBar = {
selectRow: {
onClick: async (orderSupplierVOList: BusinessAPI.OrderSupplierVO[]) => {
console.log("orderSupplierVOList", orderSupplierVOList);
// 点击弹出popup
setSelectedOrders(orderSupplierVOList);
setPopupVisible(true);
},
},
search: {
activeKey: "vehicleNo",
defaultActiveKey: "vehicleNo",
items: [
{
key: "vehicleNo",
name: "车次号",
placeholder: "请输入车次号",
},
{
key: "plate",
name: "车牌号",
placeholder: "请输入车牌号",
},
],
},
render: () => (
<>
{/* Popup 弹窗 */}
<Popup
duration={150}
style={{
minHeight: "auto",
}}
visible={popupVisible}
position="bottom"
onClose={() => setPopupVisible(false)}
onOverlayClick={() => setPopupVisible(false)}
lockScroll
round
>
<View className="border-t border-green-100 bg-green-50 p-3">
{/* 统计信息 */}
<View className="mb-2 flex items-center justify-between">
<View className="text-sm font-medium text-gray-800">
{" "}
<View className="text-primary inline">
{selectedOrders.length}
</View>{" "}
</View>
<View className="text-sm font-medium text-gray-800">
<View className="text-primary inline">{totalWeight}</View>
</View>
<View className="text-sm font-medium text-gray-800">
{" "}
<View className="text-primary inline">
{totalAmount.toFixed(2)}
</View>
</View>
</View>
{/* 上传发票 */}
<View className="mb-2 flex items-center justify-between">
<View className="flex-1">
<Uploader
className={"w-full"}
value={invoiceImgList}
onChange={handleInvoiceImgChange}
sourceType={["album", "camera"]}
uploadIcon={<Icon name={"camera"} size={36} />}
uploadLabel={
<View className={"flex flex-col items-center"}>
<View className="text-sm"></View>
<View className="mt-1 text-xs text-gray-400">
</View>
</View>
}
maxCount={1}
//@ts-ignore
upload={uploadFile}
multiple
/>
</View>
</View>
{/* 上传合同 */}
<View className="mb-2 flex items-center justify-between">
<View className="flex-1">
<Uploader
className={"w-full"}
value={contractImgList}
onChange={handleContractImgChange}
sourceType={["album", "camera"]}
uploadIcon={<Icon name={"camera"} size={36} />}
uploadLabel={
<View className={"flex flex-col items-center"}>
<View className="text-sm"></View>
<View className="mt-1 text-xs text-gray-400">
</View>
</View>
}
maxCount={9}
//@ts-ignore
upload={uploadFile}
multiple
/>
</View>
</View>
<View className={"flex flex-1 flex-row gap-2.5"}>
<View className={"flex-1"}>
<Button
size={"xlarge"}
block
type="default"
onClick={() => setPopupVisible(false)}
>
</Button>
</View>
{/* 提交按钮 */}
<View className={"flex-1"}>
<Button
size={"xlarge"}
block
type="primary"
disabled={
contractFiles.length === 0 || invoiceFiles.length === 0
}
onClick={handleSubmit}
>
</Button>
</View>
</View>
<SafeArea position={"bottom"} />
</View>
</Popup>
<View className={"flex flex-row gap-2.5"}>
<SupplierPicker
onFinish={(supplierVO) => {
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{supplierVO?.name || "瓜农"}
</View>
{supplierVO?.name ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setSupplierVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
</>
),
};
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
// 计算选中车次的总重量和总金额
const calculateTotals = () => {
return selectedOrders.reduce(
(totals, order) => {
totals.totalWeight += order.netWeight || 0;
totals.totalAmount += order.invoiceAmount || 0;
return totals;
},
{ totalWeight: 0, totalAmount: 0 },
);
};
const { totalWeight, totalAmount } = calculateTotals();
// 提交申请
const handleSubmit = async () => {
// 这里添加提交申请的逻辑
Toast.show("提交申请成功", { duration: 1500 });
setPopupVisible(false);
// 重置状态
setContractFiles([]);
setInvoiceFiles([]);
};
return (
<>
<PageList<BusinessAPI.OrderSupplierVO, BusinessAPI.OrderSupplierPageQry>
rowId={"orderSupplierId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(orderSupplierVO: BusinessAPI.OrderSupplierVO, index) => (
<View className={"flex-1"} key={index}>
<View
className={"relative flex flex-col divide-y-2 divide-neutral-100"}
>
<View className="flex-1">
<View className="flex items-start justify-between">
<View>
<View className="text-base font-medium text-gray-800">
{orderSupplierVO.name} (
{orderSupplierVO.orderVehicle?.origin}-
{orderSupplierVO.orderVehicle?.destination})
</View>
</View>
{/*<View className="rounded bg-gray-100 px-2 py-1 text-xs text-gray-800">*/}
{/* 草稿*/}
{/*</View>*/}
</View>
<View className="my-1 flex flex-row flex-wrap gap-1 text-sm text-gray-600">
<View className="text-primary">
{orderSupplierVO.orderVehicle?.vehicleNo
? "第" + orderSupplierVO.orderVehicle?.vehicleNo + "车"
: "暂未生成车次"}
</View>
<View>
{dayjs(orderSupplierVO.orderVehicle?.deliveryTime).format(
"MM-DD",
)}
</View>
<View>|</View>
<View>{orderSupplierVO.netWeight}</View>
<View>|</View>
<View>¥{orderSupplierVO.invoiceAmount}</View>
</View>
<View className="text-xs text-gray-500">
{`${orderSupplierVO.productName} | 品种:`}
</View>
</View>
</View>
</View>
)}
toolbar={toolbar}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.orderSupplier.pageOrderSupplier({
orderSupplierPageQry: {
...params,
...(supplierVO
? {
supplierId: supplierVO.supplierId,
}
: {}),
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
</>
);
});

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "上传发票",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,362 @@
import {
ActionType,
Icon,
PageList,
SupplierPicker,
ToolBar,
} from "@/components";
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 { View } from "@tarojs/components";
import dayjs from "dayjs";
import {
Button,
Popup,
SafeArea,
Toast,
Uploader,
UploaderFileItem,
} from "@nutui/nutui-react-taro";
import { uploadFile } from "@/utils";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierVO>();
const [popupVisible, setPopupVisible] = useState(false);
const [selectedOrders, setSelectedOrders] = useState<
BusinessAPI.OrderSupplierVO[]
>([]);
const [contractFiles, setContractFiles] = useState<any[]>([]);
const [invoiceFiles, setInvoiceFiles] = useState<any[]>([]);
// 发票照片
const [invoiceImgList, setInvoiceImgList] = useState<UploaderFileItem[]>([]);
// 合同照片
const [contractImgList, setContractImgList] = useState<UploaderFileItem[]>(
[],
);
// 发票照片变更处理函数
const handleInvoiceImgChange = (files: UploaderFileItem[]) => {
setInvoiceImgList(files);
// 如果有文件且上传成功保存URL到supplierVO
if (files.length > 0 && files[0].url) {
setSupplierVO((prev) => ({
...prev!,
invoiceImg: [files[0].url!],
invoiceUpload: true,
}));
} else {
// 如果没有文件清空URL
setSupplierVO((prev) => ({
...prev!,
invoiceImg: undefined,
invoiceUpload: false,
}));
}
};
// 合同照片变更处理函数
const handleContractImgChange = (files: UploaderFileItem[]) => {
setContractImgList(files);
// 保存所有文件URL到supplierVO
const urls = files.map((file) => file.url).filter((url) => url) as string[];
setSupplierVO((prev) => ({
...prev!,
contractImg: urls,
contractUpload: urls.length > 0,
}));
};
const actionRef = useRef<ActionType>();
const toolbar: ToolBar = {
selectRow: {
onClick: async (orderSupplierVOList: BusinessAPI.OrderSupplierVO[]) => {
console.log("orderSupplierVOList", orderSupplierVOList);
// 点击弹出popup
setSelectedOrders(orderSupplierVOList);
setPopupVisible(true);
},
},
search: {
activeKey: "vehicleNo",
defaultActiveKey: "vehicleNo",
items: [
{
key: "vehicleNo",
name: "车次号",
placeholder: "请输入车次号",
},
{
key: "plate",
name: "车牌号",
placeholder: "请输入车牌号",
},
],
},
render: () => (
<>
{/* Popup 弹窗 */}
<Popup
duration={150}
style={{
minHeight: "auto",
}}
visible={popupVisible}
position="bottom"
onClose={() => setPopupVisible(false)}
onOverlayClick={() => setPopupVisible(false)}
lockScroll
round
>
<View className="border-t border-green-100 bg-green-50 p-3">
{/* 统计信息 */}
<View className="mb-2 flex items-center justify-between">
<View className="text-sm font-medium text-gray-800">
{" "}
<View className="text-primary inline">
{selectedOrders.length}
</View>{" "}
</View>
<View className="text-sm font-medium text-gray-800">
<View className="text-primary inline">{totalWeight}</View>
</View>
<View className="text-sm font-medium text-gray-800">
{" "}
<View className="text-primary inline">
{totalAmount.toFixed(2)}
</View>
</View>
</View>
{/* 上传发票 */}
<View className="mb-2 flex items-center justify-between">
<View className="flex-1">
<Uploader
className={"w-full"}
value={invoiceImgList}
onChange={handleInvoiceImgChange}
sourceType={["album", "camera"]}
uploadIcon={<Icon name={"camera"} size={36} />}
uploadLabel={
<View className={"flex flex-col items-center"}>
<View className="text-sm"></View>
<View className="mt-1 text-xs text-gray-400">
</View>
</View>
}
maxCount={1}
//@ts-ignore
upload={uploadFile}
multiple
/>
</View>
</View>
{/* 上传合同 */}
<View className="mb-2 flex items-center justify-between">
<View className="flex-1">
<Uploader
className={"w-full"}
value={contractImgList}
onChange={handleContractImgChange}
sourceType={["album", "camera"]}
uploadIcon={<Icon name={"camera"} size={36} />}
uploadLabel={
<View className={"flex flex-col items-center"}>
<View className="text-sm"></View>
<View className="mt-1 text-xs text-gray-400">
</View>
</View>
}
maxCount={9}
//@ts-ignore
upload={uploadFile}
multiple
/>
</View>
</View>
<View className={"flex flex-1 flex-row gap-2.5"}>
<View className={"flex-1"}>
<Button
size={"xlarge"}
block
type="default"
onClick={() => setPopupVisible(false)}
>
</Button>
</View>
{/* 提交按钮 */}
<View className={"flex-1"}>
<Button
size={"xlarge"}
block
type="primary"
disabled={
contractFiles.length === 0 || invoiceFiles.length === 0
}
onClick={handleSubmit}
>
</Button>
</View>
</View>
<SafeArea position={"bottom"} />
</View>
</Popup>
<View className={"flex flex-row gap-2.5"}>
<SupplierPicker
onFinish={(supplierVO) => {
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{supplierVO?.name || "瓜农"}
</View>
{supplierVO?.name ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setSupplierVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
</>
),
};
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
// 计算选中车次的总重量和总金额
const calculateTotals = () => {
return selectedOrders.reduce(
(totals, order) => {
totals.totalWeight += order.netWeight || 0;
totals.totalAmount += order.invoiceAmount || 0;
return totals;
},
{ totalWeight: 0, totalAmount: 0 },
);
};
const { totalWeight, totalAmount } = calculateTotals();
// 提交申请
const handleSubmit = async () => {
// 这里添加提交申请的逻辑
Toast.show("提交申请成功", { duration: 1500 });
setPopupVisible(false);
// 重置状态
setContractFiles([]);
setInvoiceFiles([]);
};
return (
<>
<PageList<BusinessAPI.OrderSupplierVO, BusinessAPI.OrderSupplierPageQry>
rowId={"orderSupplierId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(orderSupplierVO: BusinessAPI.OrderSupplierVO, index) => (
<View className={"flex-1"} key={index}>
<View
className={"relative flex flex-col divide-y-2 divide-neutral-100"}
>
<View className="flex-1">
<View className="flex items-start justify-between">
<View>
<View className="text-base font-medium text-gray-800">
{orderSupplierVO.name} (
{orderSupplierVO.orderVehicle?.origin}-
{orderSupplierVO.orderVehicle?.destination})
</View>
</View>
{/*<View className="rounded bg-gray-100 px-2 py-1 text-xs text-gray-800">*/}
{/* 草稿*/}
{/*</View>*/}
</View>
<View className="my-1 flex flex-row flex-wrap gap-1 text-sm text-gray-600">
<View className="text-primary">
{orderSupplierVO.orderVehicle?.vehicleNo
? "第" + orderSupplierVO.orderVehicle?.vehicleNo + "车"
: "暂未生成车次"}
</View>
<View>
{dayjs(orderSupplierVO.orderVehicle?.deliveryTime).format(
"MM-DD",
)}
</View>
<View>|</View>
<View>{orderSupplierVO.netWeight}</View>
<View>|</View>
<View>¥{orderSupplierVO.invoiceAmount}</View>
</View>
<View className="text-xs text-gray-500">
{`${orderSupplierVO.productName} | 品种:`}
</View>
</View>
</View>
</View>
)}
toolbar={toolbar}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.orderSupplier.pageOrderSupplier({
orderSupplierPageQry: {
...params,
...(supplierVO
? {
supplierId: supplierVO.supplierId,
}
: {}),
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
</>
);
});

View File

@ -55,7 +55,7 @@ export default hocAuth(function Page(props: CommonComponent) {
className="bg-primary flex w-full flex-col items-center justify-center space-y-2 rounded-xl py-2.5 text-white" className="bg-primary flex w-full flex-col items-center justify-center space-y-2 rounded-xl py-2.5 text-white"
onClick={() => { onClick={() => {
Taro.navigateTo({ Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/create"), url: buildUrl("/pages/purchase/enter/create"),
}); });
}} }}
> >

View File

@ -0,0 +1,49 @@
import { ActionType, PurchaseOrderApprovalList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import { useRef, useState } from "react";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import purchaseOrder from "@/constant/purchaseOrder";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const [auditState, setAuditState] = useState<
BusinessAPI.PurchaseOrderPageQry["auditState"]
>("PENDING_BOSS_APPROVAL");
const actionRef = useRef<ActionType>();
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderApprovalList
actionRef={actionRef}
toolbar={{
tabs: {
activeKey: "state",
defaultActiveKey: auditState!,
items: purchaseOrder.approvalStateList,
onChange: (item) => {
setAuditState(
item as BusinessAPI.PurchaseOrderPageQry["auditState"],
);
actionRef.current?.reload();
},
},
}}
params={{
state: "WAITING_AUDIT",
auditState: auditState,
}}
/>
);
});

View File

@ -178,36 +178,37 @@ export default hocAuth(function Page(props: CommonComponent) {
{/* 按钮操作 */} {/* 按钮操作 */}
<View className={"sticky bottom-0 z-10 bg-white"} id={"bottomBar"}> <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"> <View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
{purchaseOrderVO.state === "WAITING_APPROVE" && ( {purchaseOrderVO.state === "WAITING_AUDIT" &&
<> purchaseOrderVO.auditState === "PENDING_BOSS_APPROVAL" && (
<View className={"flex-1"}> <>
<PurchaseOrderRejectFinal <View className={"flex-1"}>
purchaseOrderVO={purchaseOrderVO} <PurchaseOrderRejectFinal
size={"xlarge"} purchaseOrderVO={purchaseOrderVO}
onFinish={() => { size={"xlarge"}
// 返回首页 onFinish={() => {
Taro.redirectTo({ // 返回首页
url: "/pages/purchase/approver/audit/list", Taro.redirectTo({
}); url: "/pages/purchase/approver/audit/list",
}} });
/> }}
</View> />
<View className={"flex-1"}> </View>
<PurchaseOrderFinalApprove <View className={"flex-1"}>
purchaseOrderVO={purchaseOrderVO} <PurchaseOrderFinalApprove
size={"xlarge"} purchaseOrderVO={purchaseOrderVO}
onFinish={() => { size={"xlarge"}
// 关闭当前页面并跳转到采购单审核通过页面 onFinish={() => {
Taro.redirectTo({ // 关闭当前页面并跳转到采购单审核通过页面
url: buildUrl(`/pages/purchase/approver/audit/result`, { Taro.redirectTo({
orderId: purchaseOrderVO?.orderId, url: buildUrl(`/pages/purchase/approver/audit/result`, {
}), orderId: purchaseOrderVO?.orderId,
}); }),
}} });
/> }}
</View> />
</> </View>
)} </>
)}
</View> </View>
<SafeArea position={"bottom"} /> <SafeArea position={"bottom"} />
</View> </View>

View File

@ -0,0 +1,27 @@
import { PurchaseOrderApprovalList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderApprovalList
params={{
state: "WAITING_AUDIT",
auditState: "PENDING_BOSS_APPROVAL",
}}
/>
);
});

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "采购单驳回",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,27 @@
import { PurchaseOrderApprovalList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderApprovalList
params={{
state: "REJECTED",
auditState: "BOSS_REJECTED",
}}
/>
);
});

View File

@ -0,0 +1,27 @@
import { PurchaseOrderAuditList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderAuditList
params={{
state: "WAITING_AUDIT",
auditState: "PENDING_BOSS_APPROVAL",
}}
/>
);
});

View File

@ -1,224 +0,0 @@
import {
ActionType,
PageList,
PurchaseOrderRejectFinal,
State,
} from "@/components";
import Taro, { useShareAppMessage } from "@tarojs/taro";
import { useRef } from "react";
import { business } from "@/services";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl, formatCurrency, PurchaseOrderCalculator } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
import purchaseOrder from "@/constant/purchaseOrder";
import dayjs from "dayjs";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const actionRef = useRef<ActionType>();
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View className={"flex flex-col divide-y-2 divide-neutral-100"}>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
{/* 复制 */}
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle?.vehicleNo
? "第" +
purchaseOrderVO.orderVehicle?.vehicleNo +
"车"
: "暂未生成车次"}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</View>
<State
state={purchaseOrderVO.state}
stateMap={purchaseOrder.stateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.createdByName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
线
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.origin} {"->"}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle.dealerName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.plate}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSupplierList.length}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{formatCurrency(calculator.getTotalGrossWeight())}{" "}
/ {" "}
{formatCurrency(calculator.getTotalNetWeight())}
</Text>
</View>
</View>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{purchaseOrderVO.state === "WAITING_APPROVE" && (
<View className={"flex flex-row justify-end gap-2"}>
<PurchaseOrderRejectFinal
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/approver/audit/audit",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
</View>
</View>
</View>
</View>
);
}}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
state: "WAITING_APPROVE",
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
});

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "采购单",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,49 @@
import { ActionType, PurchaseOrderAuditList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import { useRef, useState } from "react";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import purchaseOrder from "@/constant/purchaseOrder";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const [auditState, setAuditState] = useState<
BusinessAPI.PurchaseOrderPageQry["auditState"]
>("PENDING_QUOTE_APPROVAL");
const actionRef = useRef<ActionType>();
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderAuditList
actionRef={actionRef}
toolbar={{
tabs: {
activeKey: "state",
defaultActiveKey: auditState!,
items: purchaseOrder.auditStateList,
onChange: (item) => {
setAuditState(
item as BusinessAPI.PurchaseOrderPageQry["auditState"],
);
actionRef.current?.reload();
},
},
}}
params={{
state: "WAITING_AUDIT",
auditState: auditState,
}}
/>
);
});

View File

@ -217,7 +217,7 @@ export default hocAuth(function Page(props: CommonComponent) {
setTimeout(() => { setTimeout(() => {
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/reviewer/audit/list"), url: buildUrl("/pages/purchase/audit/pending"),
}); });
}, 1000); }, 1000);
@ -281,7 +281,7 @@ export default hocAuth(function Page(props: CommonComponent) {
content: "暂存成功", content: "暂存成功",
}); });
// 返回采购单页面 // 返回采购单页面
Taro.redirectTo({ url: "/pages/purchase/reviewer/audit/list" }); Taro.redirectTo({ url: "/pages/purchase/audit/pending" });
} }
}; };
@ -322,7 +322,7 @@ export default hocAuth(function Page(props: CommonComponent) {
}); });
// 跳转到提交结果页面 // 跳转到提交结果页面
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/reviewer/audit/result", { url: buildUrl("/pages/purchase/audit/result", {
orderId: purchaseOrderVO!.orderId, orderId: purchaseOrderVO!.orderId,
}), }),
}); });
@ -544,48 +544,50 @@ export default hocAuth(function Page(props: CommonComponent) {
{/* 按钮操作 */} {/* 按钮操作 */}
<View className={"sticky bottom-0 z-10 bg-white"} id={"bottomBar"}> <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"> <View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
{purchaseOrderVO.state === "WAITING_AUDIT" && ( {purchaseOrderVO.state === "WAITING_AUDIT" &&
<> purchaseOrderVO.auditState === "PENDING_QUOTE_APPROVAL" && (
<View className={"flex-1"}> <>
<Button <View className={"flex-1"}>
block <Button
type={"default"} block
size={"xlarge"} type={"default"}
className="bg-gray-200 text-gray-700" size={"xlarge"}
onClick={() => setMoreActionVisible(true)} className="bg-gray-200 text-gray-700"
> onClick={() => setMoreActionVisible(true)}
>
</Button>
</View> </Button>
<View className={"flex-1"}> </View>
<Button <View className={"flex-1"}>
block <Button
type={"primary"} block
size={"xlarge"} type={"primary"}
className="bg-primary text-white" size={"xlarge"}
onClick={handleSubmit} className="bg-primary text-white"
> onClick={handleSubmit}
>
</Button>
</View> </Button>
</> </View>
)} </>
{purchaseOrderVO.state === "WAITING_APPROVE" && ( )}
<> {purchaseOrderVO.state === "WAITING_AUDIT" &&
<View className={"flex-1"}> purchaseOrderVO.auditState === "PENDING_BOSS_APPROVAL" && (
<Button <>
block <View className={"flex-1"}>
type={"default"} <Button
size={"xlarge"} block
onClick={() => { type={"default"}
Taro.redirectTo({ url: "/pages/main/index/index" }); size={"xlarge"}
}} onClick={() => {
> Taro.redirectTo({ url: "/pages/main/index/index" });
}}
</Button> >
</View>
</> </Button>
)} </View>
</>
)}
</View> </View>
<SafeArea position={"bottom"} /> <SafeArea position={"bottom"} />
</View> </View>

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "采购单审核",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,27 @@
import { PurchaseOrderAuditList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderAuditList
params={{
state: "WAITING_AUDIT",
auditState: "PENDING_QUOTE_APPROVAL",
}}
/>
);
});

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "采购单驳回",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,27 @@
import { PurchaseOrderList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderList
params={{
state: "REJECTED",
auditState: "QUOTE_REJECTED",
}}
/>
);
});

View File

@ -49,7 +49,7 @@ export default hocAuth(function Page(props: CommonComponent) {
const viewPurchaseOrderDetail = () => { const viewPurchaseOrderDetail = () => {
if (purchaseOrder?.orderId) { if (purchaseOrder?.orderId) {
Taro.navigateTo({ Taro.navigateTo({
url: buildUrl("/pages/purchase/reviewer/audit/audit", { url: buildUrl("/pages/purchase/audit/audit", {
orderId: purchaseOrder.orderId, orderId: purchaseOrder.orderId,
}), }),
}); });

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "采购单审核",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,26 @@
import { PurchaseOrderList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderList
params={{
state: "WAITING_AUDIT",
}}
/>
);
});

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "采购单",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,46 @@
import { ActionType, PurchaseOrderList } from "@/components";
import { useShareAppMessage } from "@tarojs/taro";
import { useRef, useState } from "react";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import purchaseOrder from "@/constant/purchaseOrder";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const [state, setState] =
useState<BusinessAPI.PurchaseOrderPageQry["state"]>("DRAFT");
const actionRef = useRef<ActionType>();
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderList
actionRef={actionRef}
toolbar={{
tabs: {
activeKey: "state",
defaultActiveKey: state!,
items: purchaseOrder.stateList,
onChange: (item) => {
setState(item as BusinessAPI.PurchaseOrderPageQry["state"]);
actionRef.current?.reload();
},
},
}}
create
params={{
state: state,
}}
/>
);
});

View File

@ -1,14 +1,7 @@
import hocAuth from "@/hocs/auth"; import hocAuth from "@/hocs/auth";
import { CommonComponent, CostItem, SupplierVO } from "@/types/typings"; import { CommonComponent, CostItem, SupplierVO } from "@/types/typings";
import { View } from "@tarojs/components"; import { View } from "@tarojs/components";
import { import { Button, Dialog, SafeArea, Toast } from "@nutui/nutui-react-taro";
Button,
Dialog,
SafeArea,
Toast,
Tour,
TourList,
} from "@nutui/nutui-react-taro";
import { purchase } from "@/constant"; import { purchase } from "@/constant";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { import {
@ -65,31 +58,34 @@ const defaultSupplierList: SupplierVO[] = [
export default hocAuth(function Page(props: CommonComponent) { export default hocAuth(function Page(props: CommonComponent) {
const { router, userRoleVO, setLoading } = props; const { router, userRoleVO, setLoading } = props;
const supplierId = router.params
.supplierId as BusinessAPI.SupplierVO["supplierId"];
const [orderId, setOrderId] = useState( const [orderId, setOrderId] = useState(
router.params.orderId as BusinessAPI.PurchaseOrderShowQry["orderId"], router.params.orderId as BusinessAPI.PurchaseOrderShowQry["orderId"],
); );
const defaultStep = router.params.step as number; const defaultStep = router.params.step as number;
const defaultSupplierId = router.params.supplierId as string; const defaultSupplierId = router.params.supplierId as string;
const [showTour, setShowTour] = useState(true); // const [showTour, setShowTour] = useState(true);
//
const closeTour = () => { // const closeTour = () => {
setShowTour(false); // setShowTour(false);
}; // };
//
const steps: TourList[] = [ // const steps: TourList[] = [
{ // {
content: "粘贴识别", // content: "粘贴识别",
target: "target1", // target: "target1",
popoverOffset: [0, 12], // popoverOffset: [0, 12],
arrowOffset: 0, // arrowOffset: 0,
}, // },
{ // {
content: "选择经销商", // content: "选择经销商",
target: "target2", // target: "target2",
location: "bottom-left", // location: "bottom-left",
}, // },
]; // ];
const vehicleRef = useRef<OrderVehicleRef>(null); const vehicleRef = useRef<OrderVehicleRef>(null);
// 创建MelonFarmer组件的ref数组 // 创建MelonFarmer组件的ref数组
@ -104,11 +100,9 @@ export default hocAuth(function Page(props: CommonComponent) {
const [purchaseOrder, setPurchaseOrder] = const [purchaseOrder, setPurchaseOrder] =
useState<BusinessAPI.PurchaseOrderCreateCmd>(); useState<BusinessAPI.PurchaseOrderCreateCmd>();
console.log("purchaseOrder", purchaseOrder);
const [step, setStep] = useState<any>(); const [step, setStep] = useState<any>();
const [active, setActive] = useState<number>(1); const [active, setActive] = useState<number>(defaultStep || 1);
const [orderVehicle, setOrderVehicle] = const [orderVehicle, setOrderVehicle] =
useState<BusinessAPI.PurchaseOrderCreateCmd["orderVehicle"]>(); useState<BusinessAPI.PurchaseOrderCreateCmd["orderVehicle"]>();
const [orderDealer, setOrderDealer] = const [orderDealer, setOrderDealer] =
@ -161,7 +155,7 @@ export default hocAuth(function Page(props: CommonComponent) {
userRoleVO.slug === "origin-entry" userRoleVO.slug === "origin-entry"
) { ) {
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/purchaser/preview", { url: buildUrl("/pages/purchase/enter/preview", {
orderId: purchaseOrder.orderId, orderId: purchaseOrder.orderId,
}), }),
}); });
@ -191,7 +185,6 @@ export default hocAuth(function Page(props: CommonComponent) {
setActive(active); setActive(active);
} }
} }
setActive(4);
const orderCostList1 = purchaseOrder.orderCostList.map( const orderCostList1 = purchaseOrder.orderCostList.map(
(item: CostItem) => ({ (item: CostItem) => ({
...item, ...item,
@ -214,11 +207,37 @@ export default hocAuth(function Page(props: CommonComponent) {
setLoading(false); setLoading(false);
}); });
} }
}, []); }, [orderId]);
useEffect(() => {
if (supplierId) {
setLoading(true);
business.supplier
.showSupplier({
supplierShowQry: {
supplierId: supplierId,
},
})
.then(({ data: { data: supplierVO } }) => {
if (supplierVO) {
setOrderSupplierList([
{
orderSupplierId: generateShortId(),
...supplierVO,
selected: true,
},
]);
}
})
.finally(() => {
setLoading(false);
});
}
}, [supplierId]);
useEffect(() => { useEffect(() => {
if (active) { if (active) {
setStep(purchase.steps.find((item) => item.value === active)); setStep(purchase.steps.find((item) => item.value == active));
// 同步更新purchaseOrder中的active值 // 同步更新purchaseOrder中的active值
setPurchaseOrder((prev) => ({ ...prev!, active })); setPurchaseOrder((prev) => ({ ...prev!, active }));
} }
@ -264,6 +283,7 @@ export default hocAuth(function Page(props: CommonComponent) {
})); }));
}, [orderPackageList]); }, [orderPackageList]);
console.log("step", step);
if (step === undefined) { if (step === undefined) {
return; return;
} }
@ -475,7 +495,7 @@ export default hocAuth(function Page(props: CommonComponent) {
// 跳转到预览页面 // 跳转到预览页面
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/purchaser/preview", { url: buildUrl("/pages/purchase/enter/preview", {
orderId: orderId, orderId: orderId,
}), }),
}); });
@ -1045,14 +1065,14 @@ export default hocAuth(function Page(props: CommonComponent) {
<SafeArea position={"bottom"} /> <SafeArea position={"bottom"} />
</View> </View>
<Tour {/*<Tour*/}
className="nut-custom-tour nut-customword-tour hidden" {/* className="nut-custom-tour nut-customword-tour hidden"*/}
visible={showTour} {/* visible={showTour}*/}
onClose={closeTour} {/* onClose={closeTour}*/}
list={steps} {/* list={steps}*/}
type="step" {/* type="step"*/}
location="bottom-right" {/* location="bottom-right"*/}
/> {/*/>*/}
</> </>
); );
}); });

View File

@ -0,0 +1,27 @@
import { PurchaseOrderList } from "@/components";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { useShareAppMessage } from "@tarojs/taro";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PurchaseOrderList
create
params={{
state: "DRAFT",
}}
/>
);
});

View File

@ -64,7 +64,7 @@ export default hocAuth(function Page(props: CommonComponent) {
className="flex-1 bg-gray-200 text-gray-700" className="flex-1 bg-gray-200 text-gray-700"
onClick={() => { onClick={() => {
Taro.redirectTo({ Taro.redirectTo({
url: buildUrl("/pages/purchase/purchaser/create", { url: buildUrl("/pages/purchase/enter/create", {
orderId: purchaseOrder.orderId, orderId: purchaseOrder.orderId,
active: 6, active: 6,
}), }),

View File

@ -49,7 +49,7 @@ export default hocAuth(function Page(props: CommonComponent) {
const viewPurchaseOrderDetail = () => { const viewPurchaseOrderDetail = () => {
if (purchaseOrder?.orderId) { if (purchaseOrder?.orderId) {
Taro.navigateTo({ Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/preview", { url: buildUrl("/pages/purchase/enter/preview", {
orderId: purchaseOrder.orderId, orderId: purchaseOrder.orderId,
}), }),
}); });

View File

@ -1,462 +0,0 @@
import {
ActionType,
DealerPicker,
Icon,
PageList,
PurchaseOrderRejectApprove,
PurchaseOrderRejectFinal,
PurchaseOrderWithdrawReview,
State,
ToolBar,
} from "@/components";
import Taro, { useShareAppMessage } from "@tarojs/taro";
import { useRef, useState } from "react";
import { business } from "@/services";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl, formatCurrency, PurchaseOrderCalculator } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
import purchaseOrder from "@/constant/purchaseOrder";
import dayjs from "dayjs";
export default hocAuth(function Page(props: CommonComponent) {
const { userRoleVO, shareOptions } = props;
const [state, setState] =
useState<BusinessAPI.PurchaseOrderPageQry["state"]>();
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
const actionRef = useRef<ActionType>();
const toolbar: ToolBar = {
search: {
activeKey: "vehicleNo",
defaultActiveKey: "vehicleNo",
items: [
{
key: "vehicleNo",
name: "车次号",
placeholder: "请输入车次号",
},
{
key: "plate",
name: "车牌号",
placeholder: "请输入车牌号",
},
{
key: "supplierName",
name: "瓜农姓名",
placeholder: "请输入瓜农姓名",
},
],
},
tabs: {
activeKey: "state",
defaultActiveKey: state || "ALL",
items: purchaseOrder.stateList.filter((item) => {
if (userRoleVO.slug === "reviewer") {
return item.value !== "DRAFT";
}
return item;
}),
onChange: (item) => {
setState(item as BusinessAPI.PurchaseOrderPageQry["state"]);
actionRef.current?.reload();
},
},
render: () => (
<View className={"flex flex-row gap-2.5"}>
<DealerPicker
onFinish={(dealerVO) => {
setDealerVO(dealerVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`"border-2 border-primary flex h-6 items-center rounded-md px-2.5`}
>
<View className={"text-primary text-xs"}>
{dealerVO?.shortName || "经销商"}
</View>
{dealerVO?.shortName ? (
<Icon
name={"circle-xmark"}
size={16}
onClick={(event) => {
setDealerVO(undefined);
actionRef.current?.reload();
event.stopPropagation();
}}
/>
) : (
<Icon name={"chevron-down"} size={16} />
)}
</View>
}
/>
</View>
),
actions: [
userRoleVO.slug === "origin-entry" && (
<View className={"flex flex-row gap-2 p-3"} key={"create"}>
<View className={"flex-1"}>
<View
className="bg-primary flex w-full flex-col items-center justify-center space-y-2 rounded-xl py-2.5 text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/create"),
});
}}
>
<View className="text-base font-bold"></View>
</View>
</View>
</View>
),
],
};
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View
className={"flex flex-col divide-y-2 divide-neutral-100"}
onClick={(event) => {
if (purchaseOrderVO.active === 7) {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/preview", {
orderId: purchaseOrderVO.orderId,
}),
});
event.stopPropagation();
}
}}
>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
{/* 复制 */}
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle?.vehicleNo
? "第" +
purchaseOrderVO.orderVehicle?.vehicleNo +
"车"
: "暂未生成车次"}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</View>
<State
state={purchaseOrderVO.state}
stateMap={purchaseOrder.stateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.createdByName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
线
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.origin} {"->"}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle.dealerName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.plate}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSupplierList.length}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{formatCurrency(calculator.getTotalGrossWeight())}{" "}
/ {" "}
{formatCurrency(calculator.getTotalNetWeight())}
</Text>
</View>
</View>
</View>
</View>
{userRoleVO.slug === "boss" && (
<View className={"py-2.5"}>
{purchaseOrderVO.state === "WAITING_APPROVE" && (
<View className={"flex flex-row justify-end gap-2"}>
<PurchaseOrderRejectFinal
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/approver/audit/audit",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
</View>
)}
{userRoleVO.slug === "reviewer" && (
<View className={"py-2.5"}>
{purchaseOrderVO.state === "WAITING_AUDIT" && (
<View className={"flex flex-row justify-end gap-2"}>
<PurchaseOrderRejectApprove
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/reviewer/audit/audit",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
{purchaseOrderVO.state === "WAITING_APPROVE" && (
<View className={"flex flex-row justify-end gap-2"}>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/reviewer/audit/result",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
</View>
)}
{userRoleVO.slug === "origin-entry" && (
<View className={"py-2.5"}>
{purchaseOrderVO.state === "DRAFT" && (
<View className={"flex flex-row justify-end gap-2"}>
<Button
type={"default"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/create", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
{purchaseOrderVO.active === 7 && (
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/purchaser/preview",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
)}
<Button type={"danger"} size={"small"}>
</Button>
</View>
)}
{purchaseOrderVO.state === "WAITING_AUDIT" && (
<View className={"flex flex-row justify-end gap-2"}>
<Button
type={"default"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/preview", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
<PurchaseOrderWithdrawReview
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
</View>
)}
</View>
)}
</View>
</View>
);
}}
toolbar={toolbar}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
//@ts-ignore
state: state !== "ALL" ? state : undefined,
...(dealerVO
? {
dealerId: dealerVO.dealerId,
}
: {}),
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
});

View File

@ -1,279 +0,0 @@
import {
ActionType,
PageList,
PurchaseOrderWithdrawReview,
State,
ToolBar,
} from "@/components";
import Taro, { useShareAppMessage } from "@tarojs/taro";
import { useRef } from "react";
import { business } from "@/services";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl, formatCurrency, PurchaseOrderCalculator } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
import purchaseOrder from "@/constant/purchaseOrder";
import dayjs from "dayjs";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const actionRef = useRef<ActionType>();
const toolbar: ToolBar = {
actions: [
<View className={"flex flex-row gap-2 p-3"} key={"create"}>
<View className={"flex-1"}>
<View
className="bg-primary flex w-full flex-col items-center justify-center space-y-2 rounded-xl py-2.5 text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/create"),
});
}}
>
<View className="text-base font-bold"></View>
</View>
</View>
</View>,
],
};
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View
className={"flex flex-col divide-y-2 divide-neutral-100"}
onClick={(event) => {
if (purchaseOrderVO.active === 7) {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/preview", {
orderId: purchaseOrderVO.orderId,
}),
});
event.stopPropagation();
}
}}
>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
{/* 复制 */}
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle?.vehicleNo
? "第" +
purchaseOrderVO.orderVehicle?.vehicleNo +
"车"
: "暂未生成车次"}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</View>
<State
state={purchaseOrderVO.state}
stateMap={purchaseOrder.stateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.createdByName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
线
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.origin} {"->"}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle.dealerName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.plate}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSupplierList.length}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{formatCurrency(calculator.getTotalGrossWeight())}{" "}
/ {" "}
{formatCurrency(calculator.getTotalNetWeight())}
</Text>
</View>
</View>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{purchaseOrderVO.state === "DRAFT" && (
<>
<Button
type={"default"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/purchaser/create", {
orderId: purchaseOrderVO.orderId,
}),
});
e.stopPropagation();
}}
>
</Button>
{purchaseOrderVO.active === 7 && (
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/purchaser/preview",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
)}
<Button type={"danger"} size={"small"}>
</Button>
</>
)}
{purchaseOrderVO.state === "WAITING_AUDIT" && (
<>
<PurchaseOrderWithdrawReview
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
</>
)}
</View>
</View>
</View>
</View>
);
}}
toolbar={toolbar}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
state: "DRAFT",
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
});

View File

@ -1,224 +0,0 @@
import {
ActionType,
PageList,
PurchaseOrderRejectApprove,
State,
} from "@/components";
import Taro, { useShareAppMessage } from "@tarojs/taro";
import { useRef } from "react";
import { business } from "@/services";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { Label, Text, View } from "@tarojs/components";
import { buildUrl, formatCurrency, PurchaseOrderCalculator } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
import purchaseOrder from "@/constant/purchaseOrder";
import dayjs from "dayjs";
export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props;
const actionRef = useRef<ActionType>();
useShareAppMessage((res) => {
console.log("useShareAppMessage1", res, shareOptions);
// 如果是按钮触发的转发,使用默认配置
if (res.from === "button") {
return shareOptions;
}
// 页面转发使用设置的配置
return {};
});
return (
<PageList<BusinessAPI.PurchaseOrderVO, BusinessAPI.PurchaseOrderPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
type={"infinite"}
actionRef={actionRef}
render={(purchaseOrderVO: BusinessAPI.PurchaseOrderVO, index) => {
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
return (
<View className={"mb-2.5"} key={index}>
<View
className={
"relative flex flex-col divide-y-2 divide-neutral-100 rounded-lg bg-white px-2.5"
}
>
<View className={"flex flex-col divide-y-2 divide-neutral-100"}>
<View className={"py-2.5"}>
<View className={"flex flex-row items-center"}>
<View className={"flex flex-1 flex-col gap-2"}>
<View className={"flex flex-row gap-1"}>
{/* 复制 */}
<Text
className={"text-neutral-darkest text-xl font-bold"}
>
{purchaseOrderVO.orderVehicle?.vehicleNo
? "第" +
purchaseOrderVO.orderVehicle?.vehicleNo +
"车"
: "暂未生成车次"}
</Text>
</View>
<Text className={"text-neutral-dark text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</View>
<State
state={purchaseOrderVO.state}
stateMap={purchaseOrder.stateMap}
/>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-col gap-2"}>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.createdByName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{dayjs(purchaseOrderVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
线
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.origin} {"->"}
{purchaseOrderVO.orderVehicle?.destination}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle.dealerName}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderVehicle?.plate}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSupplierList.length}
</Text>
</View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<Text className={"text-neutral-darkest text-sm"}>
{formatCurrency(calculator.getTotalGrossWeight())}{" "}
/ {" "}
{formatCurrency(calculator.getTotalNetWeight())}
</Text>
</View>
</View>
</View>
</View>
<View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}>
{purchaseOrderVO.state === "WAITING_AUDIT" && (
<View className={"flex flex-row justify-end gap-2"}>
<PurchaseOrderRejectApprove
purchaseOrderVO={purchaseOrderVO}
size={"small"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
<Button
type={"primary"}
size={"small"}
onClick={(e) => {
Taro.navigateTo({
url: buildUrl(
"/pages/purchase/reviewer/audit/audit",
{
orderId: purchaseOrderVO.orderId,
},
),
});
e.stopPropagation();
}}
>
</Button>
</View>
)}
</View>
</View>
</View>
</View>
);
}}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.purchaseOrder.pagePurchaseOrder({
purchaseOrderPageQry: {
...params,
state: "WAITING_AUDIT",
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
});

View File

@ -1,12 +1,13 @@
import { ActionType, PageList, ToolBar } from "@/components"; import { ActionType, Icon, PageList, Phone, ToolBar } from "@/components";
import { useShareAppMessage } from "@tarojs/taro"; import Taro, { useShareAppMessage } from "@tarojs/taro";
import { useRef } from "react"; import { useRef } from "react";
import { business } from "@/services"; import { business } from "@/services";
import hocAuth from "@/hocs/auth"; import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings"; import { CommonComponent } from "@/types/typings";
import { Label, Text, View } from "@tarojs/components"; import { Label, Text, View } from "@tarojs/components";
import dayjs from "dayjs"; import dayjs from "dayjs";
import Phone from "../../components/biz/Phone"; import { buildUrl } from "@/utils";
import { Button } from "@nutui/nutui-react-taro";
export default hocAuth(function Page(props: CommonComponent) { export default hocAuth(function Page(props: CommonComponent) {
const { shareOptions } = props; const { shareOptions } = props;
@ -24,6 +25,22 @@ export default hocAuth(function Page(props: CommonComponent) {
}, },
], ],
}, },
actions: [
<View className={"flex flex-row gap-2 p-3"} key={"create"}>
<View className={"flex-1"}>
<View
className="bg-primary flex w-full flex-col items-center justify-center space-y-2 rounded-xl py-2.5 text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/supplier/create"),
});
}}
>
<View className="text-base font-bold"></View>
</View>
</View>
</View>,
],
}; };
useShareAppMessage((res) => { useShareAppMessage((res) => {
@ -62,6 +79,19 @@ export default hocAuth(function Page(props: CommonComponent) {
</Text> </Text>
</View> </View>
</View> </View>
<Button
size={"small"}
type={"primary"}
fill={"none"}
icon={<Icon name={"pen-to-square"} size={18} />}
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/supplier/create", {
supplierId: supplierVO.supplierId,
}),
});
}}
/>
</View> </View>
</View> </View>
<View className={"py-2.5"}> <View className={"py-2.5"}>
@ -94,11 +124,68 @@ export default hocAuth(function Page(props: CommonComponent) {
<Phone phone={supplierVO.phone} /> <Phone phone={supplierVO.phone} />
</View> </View>
</View> </View>
<View
className={
"flex flex-row items-center justify-between gap-2.5"
}
>
<Label className={"text-neutral-dark text-sm"}>
</Label>
<View
className={
"flex flex-1 flex-row items-center justify-end gap-1"
}
>
12 | 2
</View>
</View>
</View> </View>
</View> </View>
</View> </View>
<View className={"py-2.5"}> <View className={"py-2.5"}>
<View className={"flex flex-row justify-end gap-2"}></View> <View className={"flex flex-row justify-end gap-2"}>
{/* 联系 */}
<Button
size={"small"}
type={"default"}
onClick={() => {
Taro.makePhoneCall({
phoneNumber: supplierVO.phone,
});
}}
>
</Button>
{/* 新建采购 */}
<Button
size={"small"}
type={"default"}
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/purchase/enter/create", {
supplierId: supplierVO.supplierId,
}),
});
}}
>
</Button>
{/* 协助开票 */}
<Button
size={"small"}
type={"primary"}
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/invoice/upload", {
supplierId: supplierVO.supplierId,
}),
});
}}
>
</Button>
</View>
</View> </View>
</View> </View>
</View> </View>

View File

@ -0,0 +1,4 @@
export default definePageConfig({
navigationBarTitleText: "瓜农管理",
navigationBarBackgroundColor: "#fff",
});

View File

@ -0,0 +1,604 @@
import { View } from "@tarojs/components";
import {
Button,
Input,
Toast,
Uploader,
UploaderFileItem,
} from "@nutui/nutui-react-taro";
import { Icon } from "@/components";
import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings";
import { useEffect, useState } from "react";
import { business } from "@/services";
import Taro from "@tarojs/taro";
import { buildUrl, generateShortId, uploadFile } from "@/utils";
export default hocAuth(function Page(props: CommonComponent) {
const { setLoading, router } = props;
const supplierId = router.params
.supplierId as BusinessAPI.SupplierVO["supplierId"];
const [supplierVO, setSupplierVO] = useState<BusinessAPI.SupplierCreateCmd>({
supplierId: generateShortId(),
name: "",
idCard: "",
phone: "",
bankCard: "",
status: true,
});
const [btnLoading, setBtnLoading] = useState(false);
const [picList, setPicList] = useState<UploaderFileItem[]>([]);
// 错误状态
const [nameError, setNameError] = useState(false);
const [idCardError, setIdCardError] = useState(false);
const [bankCardError, setBankCardError] = useState(false);
const [phoneError, setPhoneError] = useState(false);
const [nameDuplicateError, setNameDuplicateError] = useState(false); // 姓名重复错误
// 初始化微信二维码图片列表
useEffect(() => {
if (supplierId) {
setLoading(true);
business.supplier
.showSupplier({
supplierShowQry: {
supplierId: supplierId,
},
})
.then(({ data: { data: supplierVO } }) => {
if (supplierVO) {
setSupplierVO({
...supplierVO,
});
if (supplierVO.wechatQr) {
setPicList([
{
url: supplierVO.wechatQr,
name: "wechat-qrcode",
status: "success",
},
]);
}
}
})
.finally(() => {
setLoading(false);
});
}
}, [supplierId]);
// 微信二维码变更处理函数
const handleWechatQrChange = (files: UploaderFileItem[]) => {
setPicList(files);
// 如果有文件且上传成功保存URL到supplierVO
if (files.length > 0 && files[0].url) {
setSupplierVO((prev) => ({
...prev,
wechatQr: files[0].url,
}));
} else {
// 如果没有文件清空URL
setSupplierVO((prev) => ({
...prev,
wechatQr: undefined,
}));
}
};
// 校验姓名函数
const validateName = (name: string) => {
if (!name) {
return false;
}
// 姓名至少2个字符
return name.length >= 2;
};
// 校验身份证号函数
const validateIdCard = (idCard: string) => {
if (!idCard) {
return false;
}
// 18位身份证号正则表达式
const idCardRegex =
/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
return idCardRegex.test(idCard);
};
// 校验银行卡号函数
const validateBankCard = (bankCard: string) => {
if (!bankCard) {
return false;
}
// 银行卡号一般为16-19位数字
const bankCardRegex = /^\d{16,19}$/;
return bankCardRegex.test(bankCard);
};
// 校验手机号函数 (使用项目中已有的规则)
const validatePhone = (phone: string) => {
if (!phone) {
return false;
}
// 使用项目规范的手机号正则表达式
const phoneRegex = /^1[3456789]\d{9}$/;
return phoneRegex.test(phone);
};
// 处理姓名变化
const handleNameChange = (value: string) => {
setSupplierVO({
...supplierVO,
name: value,
});
// 校验并更新错误状态
const isValid = validateName(value);
setNameError(!isValid && value !== "");
if (isValid) {
setNameError(false);
}
// 清除姓名重复错误提示
setNameDuplicateError(false);
};
// 处理姓名失焦
const handleNameBlur = async (value: string) => {
if (value && !validateName(value)) {
setNameError(true);
return;
} else {
setNameError(false);
}
// 检查瓜农姓名是否在系统中存在
if (value) {
setLoading(true);
try {
const { data } = await business.supplier.checkSupplier({
supplierCheckQry: {
name: value,
},
});
if (data.success && data.data) {
// 系统中已存在该瓜农信息,设置姓名重复错误状态
setNameDuplicateError(true);
} else {
setNameDuplicateError(false);
}
} catch (error) {
console.error("检查瓜农信息失败", error);
setNameDuplicateError(false);
} finally {
setLoading(false);
}
}
};
// 处理身份证号变化
const handleIdCardChange = (value: string) => {
setSupplierVO({
...supplierVO,
idCard: value,
});
// 校验并更新错误状态
const isValid = validateIdCard(value);
setIdCardError(!isValid && value !== "");
if (isValid) {
setIdCardError(false);
}
};
// 处理身份证号失焦
const handleIdCardBlur = (value: string) => {
if (value && !validateIdCard(value)) {
setIdCardError(true);
} else {
setIdCardError(false);
}
};
// 处理银行卡号变化
const handleBankCardChange = (value: string) => {
setSupplierVO({
...supplierVO,
bankCard: value,
});
// 校验并更新错误状态
const isValid = validateBankCard(value);
setBankCardError(!isValid && value !== "");
if (isValid) {
setBankCardError(false);
}
};
// 处理银行卡号失焦
const handleBankCardBlur = (value: string) => {
if (value && !validateBankCard(value)) {
setBankCardError(true);
} else {
setBankCardError(false);
}
};
// 处理手机号变化
const handlePhoneChange = (value: string) => {
setSupplierVO({
...supplierVO,
phone: value,
});
// 校验并更新错误状态
const isValid = validatePhone(value);
setPhoneError(!isValid && value !== "");
if (isValid) {
setPhoneError(false);
}
};
// 处理手机号失焦
const handlePhoneBlur = (value: string) => {
if (value && !validatePhone(value)) {
setPhoneError(true);
} else {
setPhoneError(false);
}
};
const handleSave = async () => {
// 校验表单
const isNameValid = validateName(supplierVO.name || "");
const isIdCardValid = validateIdCard(supplierVO.idCard || "");
const isBankCardValid = validateBankCard(supplierVO.bankCard || "");
const isPhoneValid = validatePhone(supplierVO.phone || "");
setNameError(!isNameValid);
setIdCardError(!isIdCardValid);
setBankCardError(!isBankCardValid);
setPhoneError(!isPhoneValid);
// 检查是否已存在同名瓜农
let isDuplicate = false;
if (isNameValid) {
try {
setBtnLoading(true);
const { data: checkData } = await business.supplier.checkSupplier({
supplierCheckQry: {
name: supplierVO.name,
},
});
if (checkData.success && checkData.data) {
isDuplicate = true;
setNameDuplicateError(true);
}
} catch (error) {
console.error("检查瓜农信息失败", error);
} finally {
setBtnLoading(false);
}
}
const isValid =
isNameValid &&
isIdCardValid &&
isBankCardValid &&
isPhoneValid &&
!isDuplicate;
if (!isValid) {
if (isDuplicate) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "该瓜农已存在,请勿重复创建",
});
} else {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "请完善瓜农信息后再进行保存操作",
});
}
return;
}
// 创建新瓜农
try {
setBtnLoading(true);
const { data } = await business.supplier.createSupplier({
supplierId: supplierVO.supplierId,
name: supplierVO.name,
idCard: supplierVO.idCard,
phone: supplierVO.phone,
bankCard: supplierVO.bankCard,
wechatQr: supplierVO.wechatQr,
status: supplierVO.status,
});
if (data.success) {
Toast.show("toast", {
icon: "success",
title: "成功",
content: "瓜农创建成功",
});
setTimeout(() => {
Taro.navigateBack();
}, 1500);
} else {
Toast.show("toast", {
icon: "fail",
title: "失败",
content: data.errMessage || "创建失败",
});
}
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "错误",
content: "创建过程中发生错误",
});
console.error("创建瓜农失败:", error);
} finally {
setBtnLoading(false);
}
};
return (
<>
<View className="flex-1">
<View
className="flex flex-1 flex-col gap-2.5 p-2.5"
style={{
//@ts-ignore
"--nutui-input-padding": 0,
}}
>
{/* 功能提醒 */}
<View className="flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5">
<Icon
className={"mr-1"}
name="circle-info"
color={"var(--color-blue-700)"}
size={18}
/>
<View className={"text-sm text-blue-700"}>
</View>
</View>
{/* 快捷工具 */}
<View className="flex gap-2">
<View className={"flex-1"}>
<Button
block
icon={<Icon name={"id-card"} size={28} color={"white"} />}
type={"primary"}
size={"xlarge"}
className="bg-primary flex flex-1 items-center justify-center text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/public/camera/ocr", {
type: "idcard",
}),
complete: () => {
Taro.eventCenter.on("ocr", (res) => {
console.log("识别结果为:", res.result);
setSupplierVO({
...supplierVO,
name: res.result.name,
idCard: res.result.idCard,
});
Taro.eventCenter.off("ocr");
});
},
});
}}
>
<View></View>
</Button>
</View>
<View className={"flex-1"}>
<Button
block
icon={<Icon name={"credit-card"} size={28} color={"white"} />}
type={"primary"}
size={"xlarge"}
className="bg-primary flex flex-1 items-center justify-center text-white"
onClick={() => {
Taro.navigateTo({
url: buildUrl("/pages/public/camera/ocr", {
type: "bankcard",
}),
complete: () => {
Taro.eventCenter.on("ocr", (res) => {
console.log("识别结果为:", res.result);
setSupplierVO({
...supplierVO,
bankCard: res.result.number,
});
Taro.eventCenter.off("ocr");
});
},
});
}}
>
<View></View>
</Button>
</View>
</View>
{/* 瓜农信息 */}
<View className="rounded-lg bg-white p-2.5 shadow-sm">
<View className="mb-2.5">
<View className="flex items-center justify-between">
<View className={"text-primary text-sm font-bold"}>
{supplierVO.name || "瓜农"}
</View>
</View>
</View>
<View className="mb-2.5">
<View className="mb-1 block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${nameError || nameDuplicateError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon name="user" size={16} color="#999" className="mx-2" />
<Input
type="text"
placeholder="请输入姓名"
value={supplierVO.name}
onChange={(value) => handleNameChange(value)}
onBlur={() => handleNameBlur(supplierVO.name || "")}
className="flex-1"
/>
</View>
{nameError && (
<View className="mt-1 text-xs text-red-500">
{`姓名"${supplierVO.name}"至少2个字符`}
</View>
)}
{nameDuplicateError && (
<View className="mt-1 text-xs text-red-500">
</View>
)}
</View>
<View className="mb-2.5">
<View className="mb-1 block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${idCardError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon name="id-card" size={16} color="#999" className="mx-2" />
<Input
type="idcard"
placeholder="请输入身份证号"
value={supplierVO.idCard}
onChange={(value) => handleIdCardChange(value)}
onBlur={() => handleIdCardBlur(supplierVO.idCard || "")}
className="flex-1"
/>
</View>
{idCardError && (
<View className="mt-1 text-xs text-red-500">
</View>
)}
</View>
<View className="mb-2.5">
<View className="mb-1 block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${bankCardError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon
name="credit-card"
size={16}
color="#999"
className="mx-2"
/>
<Input
type="digit"
placeholder="请输入银行卡号"
value={supplierVO.bankCard}
onChange={(value) => handleBankCardChange(value)}
onBlur={() => handleBankCardBlur(supplierVO.bankCard || "")}
className="flex-1"
/>
</View>
{bankCardError && (
<View className="mt-1 text-xs text-red-500">
</View>
)}
</View>
<View className="mb-2.5">
<View className="mb-1 block text-sm font-normal text-[#000000]">
</View>
<View
className={`flex h-10 w-full items-center rounded-md ${phoneError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
>
<Icon name="phone" size={16} color="#999" className="mx-2" />
<Input
type="tel"
placeholder="请输入手机号码"
value={supplierVO.phone}
onChange={(value) => handlePhoneChange(value)}
onBlur={() => handlePhoneBlur(supplierVO.phone || "")}
className="flex-1"
/>
</View>
{phoneError && (
<View className="mt-1 text-xs text-red-500">
</View>
)}
</View>
</View>
{/* 若瓜农无法开发票,则可打款到微信 */}
<View className="rounded-lg bg-white p-2.5 shadow-sm">
<View className={`flex w-full border-gray-300`}>
<Uploader
className={"w-full"}
value={picList}
onChange={handleWechatQrChange}
sourceType={["album", "camera"]}
uploadIcon={<Icon name={"camera"} size={36} />}
uploadLabel={
<View className={"flex flex-col items-center"}>
<View className="text-sm"></View>
<View className="mt-1 text-xs text-gray-400">
</View>
<View className="mt-1 text-xs text-gray-400">
</View>
</View>
}
maxCount={1}
//@ts-ignore
upload={uploadFile}
multiple
/>
</View>
</View>
</View>
</View>
<View className="sticky bottom-0 z-10 bg-white">
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
<View className={"flex-1"}>
<Button
block
type="primary"
size={"xlarge"}
onClick={handleSave}
loading={btnLoading}
>
</Button>
</View>
</View>
</View>
</>
);
});

View File

@ -2912,8 +2912,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: AgreementVO[]; data?: AgreementVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseBoxBrandVO = { type PageResponseBoxBrandVO = {
@ -2925,8 +2925,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: BoxBrandVO[]; data?: BoxBrandVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseBoxProductVO = { type PageResponseBoxProductVO = {
@ -2938,8 +2938,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: BoxProductVO[]; data?: BoxProductVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseBoxSpecVO = { type PageResponseBoxSpecVO = {
@ -2951,8 +2951,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: BoxSpecVO[]; data?: BoxSpecVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseChannelVO = { type PageResponseChannelVO = {
@ -2964,8 +2964,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: ChannelVO[]; data?: ChannelVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseCompanyPaymentAccountVO = { type PageResponseCompanyPaymentAccountVO = {
@ -2977,8 +2977,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: CompanyPaymentAccountVO[]; data?: CompanyPaymentAccountVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseCompanyVO = { type PageResponseCompanyVO = {
@ -2990,8 +2990,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: CompanyVO[]; data?: CompanyVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseCostItemVO = { type PageResponseCostItemVO = {
@ -3003,8 +3003,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: CostItemVO[]; data?: CostItemVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseDealerPaymentAccountVO = { type PageResponseDealerPaymentAccountVO = {
@ -3016,8 +3016,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: DealerPaymentAccountVO[]; data?: DealerPaymentAccountVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseDealerRebateCustomerVO = { type PageResponseDealerRebateCustomerVO = {
@ -3029,8 +3029,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: DealerRebateCustomerVO[]; data?: DealerRebateCustomerVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseDealerVO = { type PageResponseDealerVO = {
@ -3042,8 +3042,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: DealerVO[]; data?: DealerVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseDealerWarehouseVO = { type PageResponseDealerWarehouseVO = {
@ -3055,8 +3055,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: DealerWarehouseVO[]; data?: DealerWarehouseVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseDictionaryVO = { type PageResponseDictionaryVO = {
@ -3068,8 +3068,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: DictionaryVO[]; data?: DictionaryVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseEmployeeVO = { type PageResponseEmployeeVO = {
@ -3081,8 +3081,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: EmployeeVO[]; data?: EmployeeVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseGiftBoxVO = { type PageResponseGiftBoxVO = {
@ -3094,8 +3094,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: GiftBoxVO[]; data?: GiftBoxVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseMaterialVO = { type PageResponseMaterialVO = {
@ -3107,8 +3107,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: MaterialVO[]; data?: MaterialVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseOrderSupplierVO = { type PageResponseOrderSupplierVO = {
@ -3120,8 +3120,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: OrderSupplierVO[]; data?: OrderSupplierVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponsePermissionVO = { type PageResponsePermissionVO = {
@ -3133,8 +3133,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: PermissionVO[]; data?: PermissionVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponsePlatformVO = { type PageResponsePlatformVO = {
@ -3146,8 +3146,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: PlatformVO[]; data?: PlatformVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseProductVO = { type PageResponseProductVO = {
@ -3159,8 +3159,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: ProductVO[]; data?: ProductVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponsePurchaseOrderVO = { type PageResponsePurchaseOrderVO = {
@ -3172,8 +3172,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: PurchaseOrderVO[]; data?: PurchaseOrderVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseRoleVO = { type PageResponseRoleVO = {
@ -3185,8 +3185,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: RoleVO[]; data?: RoleVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseShipOrderVO = { type PageResponseShipOrderVO = {
@ -3198,8 +3198,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: ShipOrderVO[]; data?: ShipOrderVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseSupplierVO = { type PageResponseSupplierVO = {
@ -3211,8 +3211,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: SupplierVO[]; data?: SupplierVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type PageResponseUserVO = { type PageResponseUserVO = {
@ -3224,8 +3224,8 @@ declare namespace BusinessAPI {
pageIndex?: number; pageIndex?: number;
data?: UserVO[]; data?: UserVO[];
empty?: boolean; empty?: boolean;
totalPages?: number;
notEmpty?: boolean; notEmpty?: boolean;
totalPages?: number;
}; };
type pageRoleParams = { type pageRoleParams = {
@ -3479,16 +3479,16 @@ declare namespace BusinessAPI {
type PurchaseOrderCountQry = { type PurchaseOrderCountQry = {
/** 状态1_启用0_禁用 */ /** 状态1_启用0_禁用 */
status?: boolean; status?: boolean;
/** 采购订单状态: 0_草稿1_审核中2_审批中3_待发货4_已发货5_已驳回6_已撤回7_已关闭8_已完结 */ /** 采购订单状态: 0_草稿1_审核中2_已完成3_已驳回4_已关闭 */
state?: state?: "DRAFT" | "WAITING_AUDIT" | "COMPLETED" | "REJECTED" | "CLOSED";
| "DRAFT" /** 采购单审核状态: 1_待报价审核2_待老板审批3_老板审批通过4_报价审核驳回5_老板审批驳回 */
| "WAITING_AUDIT" auditState?:
| "WAITING_APPROVE" | "NONE"
| "WAITING_SHIPMENT" | "PENDING_QUOTE_APPROVAL"
| "SHIPPED" | "PENDING_BOSS_APPROVAL"
| "PAID" | "BOSS_APPROVED"
| "COMPLETED" | "QUOTE_REJECTED"
| "REJECTED"; | "BOSS_REJECTED";
}; };
type PurchaseOrderCreateCmd = { type PurchaseOrderCreateCmd = {
@ -3552,16 +3552,16 @@ declare namespace BusinessAPI {
vehicleNo?: string; vehicleNo?: string;
/** 采购订单编号 */ /** 采购订单编号 */
orderSn?: string; orderSn?: string;
/** 采购订单状态: 0_草稿1_审核中2_审批中3_待发货4_已发货5_已驳回6_已撤回7_已关闭8_已完结 */ /** 采购订单状态: 0_草稿1_审核中2_已完成3_已驳回4_已关闭 */
state?: state?: "DRAFT" | "WAITING_AUDIT" | "COMPLETED" | "REJECTED" | "CLOSED";
| "DRAFT" /** 采购单审核状态: 1_待报价审核2_待老板审批3_老板审批通过4_报价审核驳回5_老板审批驳回 */
| "WAITING_AUDIT" auditState?:
| "WAITING_APPROVE" | "NONE"
| "WAITING_SHIPMENT" | "PENDING_QUOTE_APPROVAL"
| "SHIPPED" | "PENDING_BOSS_APPROVAL"
| "PAID" | "BOSS_APPROVED"
| "COMPLETED" | "QUOTE_REJECTED"
| "REJECTED"; | "BOSS_REJECTED";
/** 供应商名称 */ /** 供应商名称 */
supplierName?: string; supplierName?: string;
/** 经销商ID */ /** 经销商ID */
@ -3688,16 +3688,16 @@ declare namespace BusinessAPI {
freightCharge?: number; freightCharge?: number;
/** 瓜农数量 */ /** 瓜农数量 */
supplierCount?: number; supplierCount?: number;
/** 采购订单状态: 0_草稿1_审核中2_审批中3_待发货4_已发货5_已驳回6_已撤回7_已关闭8_已完结 */ /** 采购订单状态: 0_草稿1_审核中2_已完成3_已驳回4_已关闭 */
state?: state?: "DRAFT" | "WAITING_AUDIT" | "COMPLETED" | "REJECTED" | "CLOSED";
| "DRAFT" /** 采购单审核状态: 1_待报价审核2_待老板审批3_老板审批通过4_报价审核驳回5_老板审批驳回 */
| "WAITING_AUDIT" auditState?:
| "WAITING_APPROVE" | "NONE"
| "WAITING_SHIPMENT" | "PENDING_QUOTE_APPROVAL"
| "SHIPPED" | "PENDING_BOSS_APPROVAL"
| "PAID" | "BOSS_APPROVED"
| "COMPLETED" | "QUOTE_REJECTED"
| "REJECTED"; | "BOSS_REJECTED";
/** 备注 */ /** 备注 */
remark?: string; remark?: string;
/** 创建人ID */ /** 创建人ID */

View File

@ -5,11 +5,13 @@ type State = {
selected?: number; selected?: number;
}; };
userRoleVO?: AuthAPI.UserRoleVO; userRoleVO?: AuthAPI.UserRoleVO;
loading?: boolean;
}; };
type Action = { type Action = {
setTabBar: (selected: number) => void; setTabBar: (selected: number) => void;
setUserRoleVO: (userRoleVO: AuthAPI.UserRoleVO) => void; setUserRoleVO: (userRoleVO: AuthAPI.UserRoleVO) => void;
setLoading: (loading: boolean) => void;
}; };
export const globalStore = create<State & Action>((set) => ({ export const globalStore = create<State & Action>((set) => ({
@ -25,4 +27,9 @@ export const globalStore = create<State & Action>((set) => ({
userRoleVO: userRoleVO, userRoleVO: userRoleVO,
})); }));
}, },
setLoading: (loading: boolean) => {
set(() => ({
loading: loading,
}));
},
})); }));

File diff suppressed because one or more lines are too long