feat(purchase): 优化采购订单界面交互与数据展示

- 调整 CompanyPicker、DealerPicker 等组件的样式与布局
- 更新 BasicInfoSection 中车次号输入框及参考信息展示方式
- 修改 CompanyInfoSection 和 DealerInfoSection 的选择按钮样式与文案
- 增加 costItemVOList 数据字段支持
- 完善审核页面对空数据情况的处理逻辑
- 新增 smart recognition prompt 配置类型定义
- 升级 APP 版本至 v0.0.22
This commit is contained in:
shenyifei 2025-11-19 21:51:14 +08:00
parent a05015fd19
commit 221e3434a0
11 changed files with 174 additions and 161 deletions

View File

@ -1,5 +1,5 @@
import { Popup, SafeArea } from "@nutui/nutui-react-taro";
import { ScrollView, View, Image } from "@tarojs/components";
import { Image, ScrollView, View } from "@tarojs/components";
import React, { useEffect, useState } from "react";
import { business } from "@/services";
@ -35,6 +35,10 @@ export default function CompanyPicker(props: ICompanyPickerProps) {
return (
<>
<View
className={"flex flex-1 flex-row items-center justify-between"}
style={{
color: "var(--nutui-color-title, #1a1a1a)",
}}
onClick={(event) => {
setVisible(true);
event.stopPropagation();
@ -69,29 +73,38 @@ export default function CompanyPicker(props: ICompanyPickerProps) {
)}
{companyVOList?.map((companyVO) => (
<View
className={
"flex flex-col items-center justify-center p-4"
}
className={"flex flex-col items-center justify-center p-4"}
key={companyVO.companyId}
onClick={async () => {
setCompanyVO(companyVO);
setVisible(false);
}}
>
<View className={"w-16 h-16 rounded-full bg-white border-2 border-gray-200 flex items-center justify-center shadow-sm"}>
<View
className={
"flex h-16 w-16 items-center justify-center rounded-full border-2 border-gray-200 bg-white shadow-sm"
}
>
{companyVO?.logo ? (
<Image
src={companyVO.logo}
className={"w-14 h-14 rounded-full"}
className={"h-14 w-14 rounded-full"}
mode="aspectFit"
/>
) : (
<View className={"w-14 h-14 rounded-full bg-blue-100 flex items-center justify-center text-blue-500 font-medium text-xl"}>
{(companyVO?.shortName || companyVO?.fullName)?.substring(0, 2)}
<View
className={
"flex h-14 w-14 items-center justify-center rounded-full bg-blue-100 text-xl font-medium text-blue-500"
}
>
{(companyVO?.shortName || companyVO?.fullName)?.substring(
0,
2,
)}
</View>
)}
</View>
<View className={"text-center mt-2 text-base font-medium"}>
<View className={"mt-2 text-center text-base font-medium"}>
{companyVO?.shortName}
</View>
</View>

View File

@ -64,7 +64,7 @@ export default function DealerPicker(props: IDealerPickerProps) {
return (
<>
<View
className={"flex flex-1 flex-row items-center justify-between px-5"}
className={"flex flex-1 flex-row items-center justify-between"}
style={{
color: "var(--nutui-color-title, #1a1a1a)",
}}

View File

@ -756,12 +756,16 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
onFinish={setDealerVO}
enableManualInput
trigger={
<>
<View
className={
"flex flex-1 flex-row items-center justify-between px-5"
}
>
<View className={"text-sm"}>
{orderVehicle?.dealerName || "选择经销商"}
</View>
<Icon name={"chevron-down"} />
</>
</View>
}
/>
</View>

View File

@ -4,6 +4,7 @@ import dayjs from "dayjs";
import { formatCurrency } from "@/utils/format";
import { useEffect, useState } from "react";
import businessServices from "@/services/business";
import { Icon } from "@/components";
export default function BasicInfoSection(props: {
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
@ -463,12 +464,17 @@ export default function BasicInfoSection(props: {
</View>
</Popup>
<View className="rounded-lg border border-solid border-gray-200 bg-white p-3">
<View className="flex flex-col gap-2.5 rounded-lg border border-solid border-gray-200 bg-white p-2.5">
{/* 本车次号 */}
<View className="mb-4">
<View className="flex flex-col gap-2.5">
<View className={"flex flex-row items-center justify-between"}>
<View className="text-neutral-darkest mb-1 text-sm font-bold">
</View>
<View className="text-center text-xs text-gray-500">
{displayReferenceVehicleNo()}
</View>
</View>
{readOnly ? (
<View
className="flex flex-row items-center justify-between rounded-md p-2.5"
@ -483,7 +489,6 @@ export default function BasicInfoSection(props: {
</View>
</View>
) : (
<View className="flex flex-row items-center justify-between">
<View
className={`flex h-10 flex-1 items-center rounded-md border-4 border-gray-300`}
>
@ -494,16 +499,12 @@ export default function BasicInfoSection(props: {
onChange={(value) => updateVehicleNo(value)}
/>
</View>
<View className="flex-1 text-center text-xs text-gray-500">
{displayReferenceVehicleNo()}
</View>
</View>
)}
</View>
{/* 运费信息 */}
<View className="mb-4 flex flex-col gap-2.5">
<View className="text-neutral-darkest mb-1 text-sm font-bold">
<View className="flex flex-col gap-2.5">
<View className="text-neutral-darkest text-sm font-bold">
</View>
<View
@ -543,10 +544,8 @@ export default function BasicInfoSection(props: {
</View>
{/* 草帘 */}
<View className="mb-4 flex flex-col gap-2.5">
<View className="text-neutral-darkest mb-1 text-sm font-bold">
</View>
<View className="flex flex-col gap-2.5">
<View className="text-neutral-darkest text-sm font-bold"></View>
<View
className="flex flex-row items-center justify-between rounded-md p-2.5"
@ -567,8 +566,8 @@ export default function BasicInfoSection(props: {
</View>
{/* 路线和其他信息卡片 */}
<View className="mb-4 rounded-lg bg-gray-50 p-3">
<View className="mb-2 flex flex-row justify-between">
<View className="flex flex-col gap-2.5 rounded-lg bg-gray-50 p-2.5">
<View className="flex flex-row justify-between">
<View className="text-neutral-dark text-xs">线</View>
<View className="text-neutral-darkest text-xs font-medium">
{orderVehicle?.origin || "发货地"} {"->"}{" "}
@ -586,12 +585,15 @@ export default function BasicInfoSection(props: {
</View>
</View>
</View>
{!readOnly && (
<View className="flex justify-center border-t border-gray-200 p-2">
<View className="flex-1 border-t border-gray-200 pt-2.5">
<Button
size="small"
icon={<Icon name="pen-to-square" size={18} />}
size="large"
type="primary"
fill="outline"
block
onClick={openBasicInfoPopup}
>

View File

@ -20,9 +20,7 @@ export default function CompanyInfoSection(props: {
}, [purchaseOrderVO]);
// 处理公司账户选择完成事件
const handleCompanySelect = (
companyVO: BusinessAPI.CompanyVO,
) => {
const handleCompanySelect = (companyVO: BusinessAPI.CompanyVO) => {
if (readOnly) return;
// 构造新的 orderCompany 对象
@ -66,10 +64,8 @@ export default function CompanyInfoSection(props: {
};
return (
<View>
{orderCompany ? (
<View className="relative flex flex-col gap-2.5 rounded-lg border border-solid border-gray-200 p-2.5">
{!readOnly && (
{!readOnly && orderCompany && (
<View
className="absolute -top-2 -right-2 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full bg-gray-100"
onClick={handleRemoveCompany}
@ -77,42 +73,30 @@ export default function CompanyInfoSection(props: {
<Icon name="circle-xmark" size={24} color="#999" />
</View>
)}
<View className="flex flex-row items-center justify-between">
<View className="text-neutral-dark text-sm font-medium">
</View>
<View className="text-neutral-dark text-sm font-medium"></View>
<View className="text-neutral-darkest text-sm">
{orderCompany?.fullName}
{orderCompany?.fullName || "请先选择销售方"}
</View>
</View>
{!readOnly && (
<View className="flex justify-center">
<CompanyPicker
onFinish={handleCompanySelect}
trigger={
<Button size="small" type="primary" fill="outline">
<View className={"flex-1"}>
<Button
icon={<Icon name="pen-to-square" size={18} />}
size="large"
type="primary"
fill="outline"
block
>
{orderCompany ? "修改我方入账公司" : "选择我方入账公司"}
</Button>
}
/>
</View>
)}
</View>
) : readOnly ? (
<View className="flex flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 p-5">
<View className="text-neutral-darker text-sm"></View>
</View>
) : (
<View className="flex flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 p-5">
<View className="text-neutral-darker mb-3 text-sm">
</View>
<CompanyPicker
onFinish={handleCompanySelect}
trigger={
<Button size="small" type="primary" fill="outline">
</Button>
}
/>
</View>

View File

@ -72,7 +72,7 @@ export default function CostDifferenceSection(props: {
<View className="flex">
<View className="flex-1">
{!readOnly ? (
{!readOnly && orderDealer?.shareAdjusted ? (
<View
onClick={() => {
// 打开弹窗时将当前costDifference值同步到临时状态

View File

@ -64,10 +64,8 @@ export default function (props: {
};
return (
<View>
{orderDealer ? (
<View className="relative flex flex-col gap-2.5 rounded-lg border border-solid border-gray-200 p-2.5">
{!readOnly && (
{!readOnly && orderDealer && (
<View
className="absolute -top-2 -right-2 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full bg-gray-100"
onClick={(e) => {
@ -84,57 +82,38 @@ export default function (props: {
</View>
<View className="text-neutral-darkest text-sm font-medium">
{orderDealer.shortName}
{orderDealer?.shortName || "请先选择经销商"}
</View>
</View>
{dealerNameOnly && (
<View className="text-xs text-orange-500">
<View>{dealerNameOnly}</View>
<View className="mt-1"> </View>
<View> </View>
</View>
)}
{!readOnly && (
<DealerPicker
onFinish={(dealer) => {
handleDealerSelect(dealer);
}}
trigger={
<View
className={"flex flex-1 flex-row items-center justify-center"}
<View className={"flex-1"}>
<Button
icon={<Icon name="pen-to-square" size={18} />}
size="large"
type="primary"
fill="outline"
block
>
<Button size="small" type="primary" fill="outline">
{orderDealer ? "修改经销商" : "选择经销商"}
</Button>
</View>
}
/>
)}
</View>
) : readOnly ? (
<View className="flex flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 p-2.5">
<View className="text-neutral-darker text-sm"></View>
</View>
) : (
<View className="flex flex-col items-center justify-center rounded-lg border border-dashed border-gray-300 p-2.5">
<View className="text-neutral-darker mb-3 text-sm">
</View>
<View className="flex flex-col items-center">
{dealerNameOnly && (
<View className="mb-3 text-xs text-orange-500">
<View>{dealerNameOnly}</View>
<View className="mt-1">
</View>
<View> </View>
</View>
)}
<DealerPicker
onFinish={handleDealerSelect}
trigger={
<Button size="small" type="primary" fill="outline">
</Button>
}
/>
</View>
</View>
)}
</View>
);
}

View File

@ -1,2 +1,2 @@
// App 相关常量
export const APP_VERSION = "v0.0.21";
export const APP_VERSION = "v0.0.22";

View File

@ -479,6 +479,14 @@ export default hocAuth(function Page(props: CommonComponent) {
return null;
}
if (
(!purchaseOrderVO.orderPackageList ||
purchaseOrderVO?.orderPackageList.length === 0) &&
sectionKey === "emptyBoxInfo"
) {
return null;
}
return (
<>
<View className="text-sm font-bold">{section.title}</View>
@ -486,6 +494,7 @@ export default hocAuth(function Page(props: CommonComponent) {
className={`overflow-x-auto rounded-md rounded-b-lg bg-white p-2.5 shadow-sm`}
>
<section.component
readOnly={purchaseOrderVO.state !== "WAITING_AUDIT"}
purchaseOrderVO={purchaseOrderVO}
onChange={setPurchaseOrderVO}
costItemVOList={costItemVOList}

View File

@ -1097,6 +1097,8 @@ declare namespace BusinessAPI {
enableCompanyRebate?: boolean;
/** 公司返点比例 */
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
};
type DealerDestroyCmd = {
@ -1413,6 +1415,8 @@ declare namespace BusinessAPI {
enableCompanyRebate?: boolean;
/** 公司返点比例 */
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
/** 发货单模板 */
deliveryTemplate?: string;
};
@ -1456,6 +1460,8 @@ declare namespace BusinessAPI {
enableCompanyRebate?: boolean;
/** 公司返点比例 */
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
};
type DealerWarehouseCreateCmd = {
@ -2528,6 +2534,8 @@ declare namespace BusinessAPI {
enableCompanyRebate?: boolean;
/** 公司返点比例 */
companyRebateRatio?: number;
/** 是否可调整比例 */
shareAdjusted?: boolean;
/** 税费补贴 */
taxSubsidy?: number;
/** 计提税金 */
@ -2780,8 +2788,6 @@ declare namespace BusinessAPI {
strawCurtainPrice?: number;
/** 采购日期 */
deliveryTime: string;
/** 原始数据 */
originalData: string;
};
type OssTokenVO = {
@ -3426,6 +3432,8 @@ declare namespace BusinessAPI {
active?: number;
/** 产地负责人 */
originPrincipal?: string;
/** 工头 */
foreman?: string;
/** 备注 */
remark?: string;
/** 车辆信息 */
@ -3604,6 +3612,8 @@ declare namespace BusinessAPI {
active?: number;
/** 产地负责人 */
originPrincipal?: string;
/** 工头 */
foreman?: string;
/** 备注 */
remark?: string;
/** 车辆信息 */
@ -3818,7 +3828,8 @@ declare namespace BusinessAPI {
| "CHARGING_PILE_PURCHASE_CONFIG"
| "CUSTOM_THEME_CONFIG"
| "CUSTOM_MENU_CONFIG"
| "WX_CP_NOTIFY_CONFIG";
| "WX_CP_NOTIFY_CONFIG"
| "SMART_RECOGNITION_PROMPT";
};
type SettingUpdateCmd = {
@ -3840,13 +3851,15 @@ declare namespace BusinessAPI {
| "CHARGING_PILE_PURCHASE_CONFIG"
| "CUSTOM_THEME_CONFIG"
| "CUSTOM_MENU_CONFIG"
| "WX_CP_NOTIFY_CONFIG";
| "WX_CP_NOTIFY_CONFIG"
| "SMART_RECOGNITION_PROMPT";
/** 系统设置项内容 */
settingValue:
| AliPayConfigValue
| ChargingPilePurchaseConfig
| CustomMenuConfigValue
| CustomThemeConfigValue
| SmartRecognitionPromptValue
| TencentMapConfigValue
| WxCpNotifyConfigValue
| WxMaCodeUploadConfigValue
@ -3879,13 +3892,15 @@ declare namespace BusinessAPI {
| "CHARGING_PILE_PURCHASE_CONFIG"
| "CUSTOM_THEME_CONFIG"
| "CUSTOM_MENU_CONFIG"
| "WX_CP_NOTIFY_CONFIG";
| "WX_CP_NOTIFY_CONFIG"
| "SMART_RECOGNITION_PROMPT";
/** 系统设置项内容 */
settingValue:
| AliPayConfigValue
| ChargingPilePurchaseConfig
| CustomMenuConfigValue
| CustomThemeConfigValue
| SmartRecognitionPromptValue
| TencentMapConfigValue
| WxCpNotifyConfigValue
| WxMaCodeUploadConfigValue
@ -4007,7 +4022,7 @@ declare namespace BusinessAPI {
};
type ShipOrderPackage = {
/** 发货单子项ID */
/** 发货单包装信息Id */
orderPackageId: string;
/** 发货单ID */
shipOrderId: string;
@ -4510,6 +4525,13 @@ declare namespace BusinessAPI {
data?: VehicleExtractionVO;
};
type SmartRecognitionPromptValue =
// #/components/schemas/SettingValue
SettingValue & {
/** 提示词 */
prompt?: string;
};
type SupplierCheckQry = {
pageSize?: number;
pageIndex?: number;

File diff suppressed because one or more lines are too long