ERPTurbo_Client/packages/app-client/src/components/audit/ApprovalList.tsx
shenyifei ac170e8628 feat(audit): 新增审核功能模块
- 新增审核列表、详情、更新接口
- 新增审核相关常量配置
- 新增审核页面组件及路由
- 调整采购订单驳回描述文案
- 优化费用统计导出功能
- 修复部分页面tabbar显示问题
- 更新应用版本号至v0.0.52
2025-12-23 00:20:43 +08:00

321 lines
12 KiB
TypeScript

import {
ActionType,
CopyText,
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 Taro from "@tarojs/taro";
import audit from "@/constant/audit";
interface IApprovalListProps {
params: BusinessAPI.AuditPageQry;
toolbar?: ToolBar;
actionRef?: React.MutableRefObject<ActionType | undefined>;
}
export default function ApprovalList(props: IApprovalListProps) {
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-primary flex h-6 items-center rounded-md border-2 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
type={"FARMER"}
onFinish={(supplierVO) => {
setSupplierVO(supplierVO);
actionRef.current?.reload();
}}
trigger={
<View
className={`border-primary flex h-6 items-center rounded-md border-2 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.AuditVO, BusinessAPI.AuditPageQry>
rowId={"purchaseOrderId"}
itemHeight={182}
toolbar={toolbar}
type={"infinite"}
actionRef={actionRef}
render={(auditVO: BusinessAPI.AuditVO, index) => {
const purchaseOrderVO = auditVO.purchaseOrderVO;
return (
purchaseOrderVO && (
<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={auditVO.state}
stateMap={audit.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>
<CopyText copyData={purchaseOrderVO?.orderSn || "-"}>
<Text className={"text-neutral-darkest text-sm"}>
{purchaseOrderVO.orderSn}
</Text>
</CopyText>
</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.type === "PRODUCTION_PURCHASE"
? "产地采购"
: "市场采购"}
</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"}>
{auditVO.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(auditVO.createdAt).format("MM-DD HH:mm")}
</Text>
</View>
{auditVO.state === "AUDIT_REJECTED" && (
<>
<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"}>
{auditVO.auditReason}
</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"}>
{auditVO.auditByName}
</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(auditVO.auditAt).format("MM-DD HH:mm")}
</Text>
</View>
</>
)}
</View>
</View>
</View>
<View className={"py-2.5"}>
{auditVO.state === "WAITING_AUDIT" &&
auditVO.type === "BOSS_AUDIT" && (
<View className={"flex flex-row gap-2"}>
<View className={"flex-1"}>
<PurchaseOrderRejectFinal
purchaseOrderVO={purchaseOrderVO}
size={"large"}
onFinish={() => {
actionRef.current?.reload();
}}
/>
</View>
<View className={"flex-1"}>
<Button
type={"primary"}
size={"large"}
block
onClick={(e) => {
Taro.navigateTo({
url: buildUrl("/pages/approval/audit", {
orderId: purchaseOrderVO.orderId,
auditId: auditVO.auditId,
}),
});
e.stopPropagation();
}}
>
</Button>
</View>
</View>
)}
</View>
</View>
</View>
)
);
}}
request={async (params) => {
const {
data: { data, success, notEmpty },
} = await business.audit.pageAudit({
auditPageQry: {
...params,
...bizParams,
},
});
return {
data,
success,
hasMore: notEmpty,
};
}}
pagination={{
pageSize: 10,
}}
/>
);
}