ERPTurbo_Client/packages/app-client/src/components/purchase/section/CostDifferenceSection.tsx
shenyifei 5bdd8afdd6 feat(app-client): 优化采购订单审核与供应商发票上传功能
- 优化 PageList 组件的选中行样式与全选逻辑
- 重构采购订单相关组件,移除冗余的 dealerVO 属性,统一使用 orderDealer
- 完善成本差异、税金计提、税金补贴等模块的默认值计算逻辑
- 新增供应商发票与合同照片上传弹窗功能
- 改进供应商页面的车次选择与数据统计展示
- 升级 app 版本号至 v0.0.19
- 优化头像图片样式与组件代码结构
- 修复 dealerVO 数据获取逻辑,替换为 dealerRebateCustomer 数据源
- 增加页面加载状态控制与条件渲染逻辑
- 完善 uploader 组件的文件变更处理与提交逻辑
2025-11-18 22:55:57 +08:00

192 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useEffect, useState } from "react";
import { Text, View } from "@tarojs/components";
import { Button, Input, Popup, SafeArea } from "@nutui/nutui-react-taro";
import { validatePrice } from "@/utils/format";
import { PurchaseOrderCalculator } from "@/utils/PurchaseOrderCalculator";
export default function CostDifferenceSection(props: {
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
onChange?: (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => void;
readOnly?: boolean;
}) {
const { purchaseOrderVO, onChange, readOnly } = props;
const orderDealer = purchaseOrderVO.orderDealer;
const calculator = new PurchaseOrderCalculator(purchaseOrderVO);
const [visible, setVisible] = useState(false);
// 主状态,用于页面显示
const [costDifference, setCostDifference] = useState<number>(
orderDealer?.costDifference || 0,
);
// 弹窗内的临时状态
const [tempCostDifference, setTempCostDifference] = useState<number>(
orderDealer?.costDifference || 0,
);
const profitSharing =
calculator.getDefaultNetProfit() || orderDealer?.profitSharing || 0;
useEffect(() => {
if (!orderDealer?.costDifference) {
const defaultCostDifference = calculator.getCostDifference();
setCostDifference(defaultCostDifference);
setTempCostDifference(defaultCostDifference);
// 更新父组件的状态
onChange?.({
...purchaseOrderVO,
orderDealer: {
...orderDealer,
costDifference: defaultCostDifference,
profitSharing: profitSharing,
},
});
}
}, []);
// 保存调整成本
const saveCostDifference = () => {
// 将临时状态的值应用到主状态
setCostDifference(tempCostDifference);
onChange?.({
...purchaseOrderVO,
orderDealer: {
...orderDealer,
costDifference: tempCostDifference,
profitSharing: profitSharing,
},
});
setVisible(false);
};
return (
<View className={"flex flex-col gap-2.5"}>
{/* 卡片形式展示分成信息 */}
<View className="bg-primary/3 rounded-lg border-b border-gray-100 p-2.5">
<View className="mb-2">
<Text className="text-sm font-medium"></Text>
</View>
<View className="flex">
<View className="flex-1">
{!readOnly ? (
<View
onClick={() => {
// 打开弹窗时将当前costDifference值同步到临时状态
setTempCostDifference(costDifference);
setVisible(true);
}}
>
<View className="mb-2 flex items-center justify-between">
<Text className="text-sm text-gray-500"></Text>
<Text className="text-sm text-gray-500"></Text>
</View>
<View className="relative flex">
<Text className="w-full border-b-2 border-red-500 pb-2 text-3xl font-bold text-red-500 focus:outline-none">
-{costDifference || "0.00"}
</Text>
</View>
</View>
) : (
<View>
<View className="mb-2 flex items-center justify-between">
<Text className="text-sm text-gray-500"></Text>
<Text className="text-sm text-gray-500"></Text>
</View>
<View className="relative">
<Text className="w-full py-2 text-3xl font-bold text-red-500">
{costDifference || "0.00"}
</Text>
</View>
</View>
)}
</View>
<View className="flex flex-1 flex-col gap-2 pl-4">
<View className="flex items-center justify-between">
<Text className="text-sm text-gray-500"></Text>
</View>
<View className="flex items-center justify-between">
<Text className="text-primary text-2xl font-bold text-nowrap">
{profitSharing}
</Text>
</View>
</View>
</View>
</View>
{/* 分成弹窗 */}
<Popup
duration={150}
style={{
minHeight: "auto",
}}
visible={visible}
className={"flex flex-col"}
position="bottom"
title={"调分成金额"}
onClose={() => setVisible(false)}
onOverlayClick={() => {
setVisible(false);
}}
lockScroll
>
<View className={"flex flex-col gap-3 p-2.5"}>
<View className={"text-neutral-darkest text-sm font-medium"}>
</View>
<View
className={
"border-neutral-base flex flex-row items-center rounded-md border border-solid"
}
>
<Input
className={"placeholder:text-neutral-dark"}
placeholder={"请输入调分成金额"}
type={"digit"}
value={tempCostDifference?.toString()}
onChange={(value) => {
const numValue = validatePrice(value);
if (numValue !== undefined) {
setTempCostDifference(numValue as number);
}
}}
/>
<View className={"mr-2"}></View>
</View>
</View>
<View className={"flex w-full flex-col bg-white"}>
<View className={"flex flex-row gap-2 p-3"}>
<View className={"flex-1"}>
<Button
size={"large"}
block
type="default"
onClick={() => {
setVisible(false);
}}
>
</Button>
</View>
<View className={"flex-1"}>
<Button
size={"large"}
block
type="primary"
onClick={saveCostDifference}
>
</Button>
</View>
</View>
<SafeArea position={"bottom"} />
</View>
</Popup>
</View>
);
}