feat(purchase): 优化采购订单费用管理功能
- 移除调试日志输出 - 新增 requireQuantityAndPrice 字段支持 - 调整页面样式间距统一为 p-2.5 - 交换工头垫付与产地垫付显示逻辑 - 完善费用弹窗编辑功能,支持数量单价分别输入 - 增加新手引导 tour 功能 - 优化订单成本列表更新逻辑,避免重复项 - 导出新增的费用 section 组件 - 替换 LaborInfoSection为 WorkerAdvanceSection - 引入 ProductionAdvanceSection 组件
This commit is contained in:
parent
3f8c6d962a
commit
cbde9caac1
@ -34,3 +34,5 @@ export { default as TaxSubsidySection } from "./section/TaxSubsidySection";
|
||||
export { default as TaxProvisionSection } from "./section/TaxProvisionSection";
|
||||
export { default as CostDifferenceSection } from "./section/CostDifferenceSection";
|
||||
export { default as MaterialCostSection } from "./section/MaterialCostSection";
|
||||
export { default as ProductionAdvanceSection } from "./section/ProductionAdvanceSection";
|
||||
export { default as WorkerAdvanceSection } from "./section/WorkerAdvanceSection";
|
||||
|
||||
@ -53,8 +53,6 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
|
||||
(costItem) => costItem.itemId === item.itemId,
|
||||
);
|
||||
|
||||
console.log("existingItem", existingItem, value)
|
||||
|
||||
return {
|
||||
orderCostId: existingItem
|
||||
? existingItem.orderCostId
|
||||
@ -68,6 +66,9 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
|
||||
payerType: existingItem ? existingItem.payerType : undefined,
|
||||
principal: existingItem ? existingItem.principal : "",
|
||||
costType: item.costType,
|
||||
requireQuantityAndPrice: existingItem
|
||||
? existingItem.requireQuantityAndPrice
|
||||
: false,
|
||||
};
|
||||
}) || [];
|
||||
|
||||
@ -91,6 +92,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
|
||||
payerType: item.payerType,
|
||||
principal: item.principal,
|
||||
costType: item.costType,
|
||||
requireQuantityAndPrice: item.requireQuantityAndPrice,
|
||||
};
|
||||
}) || []),
|
||||
]);
|
||||
@ -421,7 +423,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
|
||||
};
|
||||
|
||||
return (
|
||||
<View className="flex flex-1 flex-col bg-[#D1D5DB] p-2.5 pt-2.5 gap-2.5">
|
||||
<View className="flex flex-1 flex-col gap-2.5 bg-[#D1D5DB] p-2.5 pt-2.5">
|
||||
<View className={"flex flex-1 flex-col gap-2.5"}>
|
||||
<View className="text-sm font-bold">人工费用</View>
|
||||
<View className="flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5">
|
||||
|
||||
@ -537,7 +537,10 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
|
||||
className="min-h-20 w-full !border !border-none p-2.5 !text-lg"
|
||||
placeholder="「粘贴识别」获输入文本,智能拆分车牌号、司机姓名、联系电话、出发地、目的地和运费"
|
||||
/>
|
||||
<View className="absolute right-0 bottom-0 z-9 flex gap-2">
|
||||
<View
|
||||
className="absolute right-0 bottom-0 z-9 flex gap-2"
|
||||
id={"target1"}
|
||||
>
|
||||
{text ? (
|
||||
<Button
|
||||
size={"large"}
|
||||
@ -667,6 +670,7 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
|
||||
<View className={"flex flex-row gap-2.5"}>
|
||||
<View>
|
||||
<View
|
||||
id={"target2"}
|
||||
className={`relative flex h-10 w-full items-center rounded-md ${dealerNameError ? "border-4 border-red-500" : "border-4 border-gray-300"}`}
|
||||
>
|
||||
<DealerPicker
|
||||
|
||||
@ -471,7 +471,7 @@ export default function BasicInfoSection(props: {
|
||||
</View>
|
||||
{readOnly ? (
|
||||
<View
|
||||
className="flex flex-row items-center justify-between rounded-md p-4"
|
||||
className="flex flex-row items-center justify-between rounded-md p-2.5"
|
||||
style={{
|
||||
background: "linear-gradient(101deg, #F8FAFF 25%, #F0F5FF 74%)",
|
||||
}}
|
||||
@ -507,7 +507,7 @@ export default function BasicInfoSection(props: {
|
||||
运费信息
|
||||
</View>
|
||||
<View
|
||||
className="flex flex-row items-center justify-between rounded-md p-4"
|
||||
className="flex flex-row items-center justify-between rounded-md p-2.5"
|
||||
style={{
|
||||
background: "linear-gradient(101deg, #F8FAFF 25%, #F0F5FF 74%)",
|
||||
}}
|
||||
@ -549,7 +549,7 @@ export default function BasicInfoSection(props: {
|
||||
</View>
|
||||
|
||||
<View
|
||||
className="flex flex-row items-center justify-between rounded-md p-4"
|
||||
className="flex flex-row items-center justify-between rounded-md p-2.5"
|
||||
style={{
|
||||
background: "linear-gradient(101deg, #F8FAFF 25%, #F0F5FF 74%)",
|
||||
}}
|
||||
|
||||
@ -211,10 +211,11 @@ export default function LaborInfoSection(props: {
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
<View className="grid grid-cols-1 gap-2.5">
|
||||
<View className={"text-sm font-bold"}>产地垫付</View>
|
||||
{/* 产地垫付 */}
|
||||
{productionAdvanceCosts.map((item, index) => {
|
||||
|
||||
<View className="flex flex-col gap-2.5">
|
||||
<View className={"text-sm font-bold"}>工头垫付</View>
|
||||
{/* 工头垫付 */}
|
||||
{workerAdvanceCosts.map((item, index) => {
|
||||
// 初始化编辑值,包括费用承担方和工头姓名
|
||||
initEditValues(
|
||||
item.orderCostId,
|
||||
@ -261,10 +262,11 @@ export default function LaborInfoSection(props: {
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
<View className="grid grid-cols-1 gap-2.5">
|
||||
<View className={"text-sm font-bold"}>工头垫付</View>
|
||||
{/* 工头垫付 */}
|
||||
{workerAdvanceCosts.map((item, index) => {
|
||||
|
||||
<View className="flex flex-col gap-2.5">
|
||||
<View className={"text-sm font-bold"}>产地垫付</View>
|
||||
{/* 产地垫付 */}
|
||||
{productionAdvanceCosts.map((item, index) => {
|
||||
// 初始化编辑值,包括费用承担方和工头姓名
|
||||
initEditValues(
|
||||
item.orderCostId,
|
||||
@ -390,7 +392,7 @@ export default function LaborInfoSection(props: {
|
||||
costItems
|
||||
.filter((item) => item.costType === newCostData.costType)
|
||||
.filter((item) => {
|
||||
if (newCostData.costType === 'PRODUCTION_ADVANCE') {
|
||||
if (newCostData.costType === "PRODUCTION_ADVANCE") {
|
||||
// 检查该项目是否已经被选择
|
||||
return !productionAdvanceCosts.some(
|
||||
(hc) => hc.itemId === item.itemId,
|
||||
@ -604,6 +606,8 @@ export default function LaborInfoSection(props: {
|
||||
payerType: newCostData.payerType || "US",
|
||||
costType: newCostData.costType!,
|
||||
principal: "",
|
||||
requireQuantityAndPrice:
|
||||
newCostData.requireQuantityAndPrice,
|
||||
};
|
||||
|
||||
// 更新purchaseOrderVO,将新费用添加到orderCostList中
|
||||
@ -648,395 +652,423 @@ export default function LaborInfoSection(props: {
|
||||
{productionAdvanceCosts.map((item) => {
|
||||
// 获取费用项目的 requireQuantityAndPrice 属性
|
||||
const costItem = costItems.find((cost) => cost.itemId === item.itemId);
|
||||
const requireQuantityAndPrice = costItem?.requireQuantityAndPrice ?? false;
|
||||
const requireQuantityAndPrice =
|
||||
costItem?.requireQuantityAndPrice ?? false;
|
||||
|
||||
return (
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({ ...prev, [item.orderCostId]: false }))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({ ...prev, [item.orderCostId]: false }))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() || ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() ||
|
||||
""
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() || ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<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={(
|
||||
tempEditValues[item.orderCostId]?.price *
|
||||
tempEditValues[item.orderCostId]?.count ||
|
||||
item.price * item.count
|
||||
).toString()}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() => {
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
金额
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...tempEditValues[item.orderCostId],
|
||||
// 如果费用承担方是瓜农,清空工头姓名
|
||||
principal:
|
||||
tempEditValues[item.orderCostId]?.payerType ===
|
||||
"OTHER"
|
||||
? ""
|
||||
: tempEditValues[item.orderCostId]?.principal,
|
||||
},
|
||||
}));
|
||||
|
||||
// 这里应该调用更新接口或更新状态
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</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={
|
||||
(tempEditValues[item.orderCostId]?.price * tempEditValues[item.orderCostId]?.count || item.price * item.count).toString()
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter(
|
||||
(cost) => cost.orderCostId !== item.orderCostId,
|
||||
);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</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={() => {
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...tempEditValues[item.orderCostId],
|
||||
// 如果费用承担方是瓜农,清空工头姓名
|
||||
principal:
|
||||
tempEditValues[item.orderCostId]?.payerType ===
|
||||
"OTHER"
|
||||
? ""
|
||||
: tempEditValues[item.orderCostId]?.principal,
|
||||
},
|
||||
}));
|
||||
|
||||
// 这里应该调用更新接口或更新状态
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter((cost) => cost.orderCostId !== item.orderCostId);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
)})}
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* 工头垫付 */}
|
||||
{workerAdvanceCosts.map((item) => {
|
||||
// 获取费用项目的 requireQuantityAndPrice 属性
|
||||
const costItem = costItems.find((cost) => cost.itemId === item.itemId);
|
||||
const requireQuantityAndPrice = costItem?.requireQuantityAndPrice ?? false;
|
||||
const requireQuantityAndPrice =
|
||||
costItem?.requireQuantityAndPrice ?? false;
|
||||
|
||||
return (
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({ ...prev, [item.orderCostId]: false }))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({ ...prev, [item.orderCostId]: false }))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() || ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() ||
|
||||
""
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() || ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<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={(
|
||||
tempEditValues[item.orderCostId]?.price *
|
||||
tempEditValues[item.orderCostId]?.count ||
|
||||
item.price * item.count
|
||||
).toString()}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() => {
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
金额
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...tempEditValues[item.orderCostId],
|
||||
// 如果费用承担方是瓜农,清空工头姓名
|
||||
principal:
|
||||
tempEditValues[item.orderCostId]?.payerType ===
|
||||
"OTHER"
|
||||
? ""
|
||||
: tempEditValues[item.orderCostId]?.principal,
|
||||
},
|
||||
}));
|
||||
|
||||
// 这里应该调用更新接口或更新状态
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</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={
|
||||
(tempEditValues[item.orderCostId]?.price * tempEditValues[item.orderCostId]?.count || item.price * item.count).toString()
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter(
|
||||
(cost) => cost.orderCostId !== item.orderCostId,
|
||||
);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</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={() => {
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...tempEditValues[item.orderCostId],
|
||||
// 如果费用承担方是瓜农,清空工头姓名
|
||||
principal:
|
||||
tempEditValues[item.orderCostId]?.payerType ===
|
||||
"OTHER"
|
||||
? ""
|
||||
: tempEditValues[item.orderCostId]?.principal,
|
||||
},
|
||||
}));
|
||||
|
||||
// 这里应该调用更新接口或更新状态
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter((cost) => cost.orderCostId !== item.orderCostId);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
)})}
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -606,123 +606,207 @@ export default function MaterialCostSection(props: {
|
||||
</Popup>
|
||||
|
||||
{/* 辅料费编辑弹窗 */}
|
||||
{packagingMaterials.map((item) => (
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({ ...prev, [item.orderCostId]: false }))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({ ...prev, [item.orderCostId]: 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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() ||
|
||||
editValues[item.orderCostId]?.count?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">{item.unit}</View>
|
||||
</View>
|
||||
{packagingMaterials.map((item) => {
|
||||
// 获取费用项目的 requireQuantityAndPrice 属性
|
||||
const costItem = costItems.find((cost) => cost.itemId === item.itemId);
|
||||
const requireQuantityAndPrice =
|
||||
costItem?.requireQuantityAndPrice ?? false;
|
||||
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() ||
|
||||
editValues[item.orderCostId]?.price?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: 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={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: tempEditValues[item.orderCostId],
|
||||
}));
|
||||
return (
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<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={(
|
||||
tempEditValues[item.orderCostId]?.price *
|
||||
tempEditValues[item.orderCostId]?.count ||
|
||||
item.price * item.count
|
||||
).toString()}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: tempEditValues[item.orderCostId],
|
||||
}));
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter(
|
||||
(cost) => cost.orderCostId !== item.orderCostId,
|
||||
);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
))}
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,741 @@
|
||||
import { ScrollView, View } from "@tarojs/components";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Picker,
|
||||
Popup,
|
||||
SafeArea,
|
||||
} from "@nutui/nutui-react-taro";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Icon } from "@/components";
|
||||
import { business } from "@/services";
|
||||
import { formatCurrency, validatePrice } from "@/utils/format";
|
||||
import { generateShortId } from "@/utils/generateShortId";
|
||||
|
||||
export default function ProductionAdvanceSection(props: {
|
||||
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
|
||||
onChange?: (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => void;
|
||||
readOnly?: boolean;
|
||||
}) {
|
||||
const { purchaseOrderVO, onChange, readOnly } = props;
|
||||
|
||||
// 弹窗相关状态
|
||||
const [visiblePopup, setVisiblePopup] = useState<{ [key: string]: boolean }>(
|
||||
{},
|
||||
);
|
||||
|
||||
// 新增人工费弹窗状态
|
||||
const [showAddCostPopup, setShowAddCostPopup] = useState(false);
|
||||
|
||||
// 新增人工费表单数据
|
||||
const [newCostData, setNewCostData] = useState<any>({
|
||||
costType: "PRODUCTION_ADVANCE", // 费用类型
|
||||
itemId: "", // 费用项目ID
|
||||
name: "", // 费用名称
|
||||
quantity: 0, // 数量(人数)
|
||||
unit: "", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
payerType: "US", // 费用承担方,默认我方
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice: false,
|
||||
});
|
||||
|
||||
console.log("newCostData", newCostData);
|
||||
|
||||
// Picker可见状态
|
||||
const [pickerVisible, setPickerVisible] = useState({
|
||||
costType: false, // 费用类型Picker
|
||||
costItem: false, // 费用项目Picker
|
||||
});
|
||||
|
||||
// 费用项目列表
|
||||
const [costItems, setCostItems] = useState<BusinessAPI.CostItemVO[]>([]);
|
||||
|
||||
// 编辑值的状态
|
||||
const [editValues, setEditValues] = useState<{
|
||||
[key: string]: {
|
||||
count: number;
|
||||
price: number;
|
||||
name?: string;
|
||||
principal?: string;
|
||||
payerType?: "US" | "OTHER";
|
||||
};
|
||||
}>({});
|
||||
|
||||
// 临时编辑值的状态(用于在保存前暂存编辑的值)
|
||||
const [tempEditValues, setTempEditValues] = useState<{
|
||||
[key: string]: {
|
||||
count: number;
|
||||
price: number;
|
||||
name?: string;
|
||||
principal?: string;
|
||||
payerType?: "US" | "OTHER";
|
||||
};
|
||||
}>({});
|
||||
|
||||
// 初始化编辑值
|
||||
const initEditValues = (
|
||||
itemId: string,
|
||||
count: number,
|
||||
price: number,
|
||||
name?: string,
|
||||
principal?: string,
|
||||
payerType?: "US" | "OTHER",
|
||||
) => {
|
||||
if (!editValues[itemId]) {
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[itemId]: { count, price, name, principal, payerType },
|
||||
}));
|
||||
}
|
||||
|
||||
// 同时初始化临时编辑值
|
||||
if (!tempEditValues[itemId]) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[itemId]: { count, price, name, principal, payerType },
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
// 获取费用项目列表
|
||||
useEffect(() => {
|
||||
const fetchCostItems = async () => {
|
||||
try {
|
||||
const { data } = await business.costItem.listCostItem({
|
||||
costItemListQry: {
|
||||
status: true,
|
||||
showInEntry: true,
|
||||
},
|
||||
});
|
||||
setCostItems(data.data || []);
|
||||
} catch (error) {
|
||||
console.error("获取费用项目列表失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCostItems();
|
||||
}, []);
|
||||
|
||||
// 产地垫付
|
||||
const productionAdvanceCosts =
|
||||
purchaseOrderVO.orderCostList?.filter(
|
||||
(item) => item.costType === "PRODUCTION_ADVANCE",
|
||||
) || [];
|
||||
|
||||
// 当editValues发生变化时,更新purchaseOrderVO
|
||||
useEffect(() => {
|
||||
// 只有当onChange存在时才更新
|
||||
if (onChange) {
|
||||
// 获取现有的orderCostList
|
||||
const existingOrderCostList = purchaseOrderVO.orderCostList || [];
|
||||
|
||||
// 更新已有的成本项
|
||||
const updatedOrderCostList = existingOrderCostList.map((item) => {
|
||||
if (editValues[item.orderCostId]) {
|
||||
return {
|
||||
...item,
|
||||
price:
|
||||
editValues[item.orderCostId].price !== undefined
|
||||
? editValues[item.orderCostId].price
|
||||
: item.price,
|
||||
count:
|
||||
editValues[item.orderCostId].count !== undefined
|
||||
? editValues[item.orderCostId].count
|
||||
: item.count,
|
||||
name:
|
||||
editValues[item.orderCostId].name !== undefined
|
||||
? editValues[item.orderCostId].name
|
||||
: item.name,
|
||||
principal:
|
||||
editValues[item.orderCostId].principal !== undefined
|
||||
? editValues[item.orderCostId].principal
|
||||
: item.principal,
|
||||
payerType:
|
||||
editValues[item.orderCostId].payerType !== undefined
|
||||
? editValues[item.orderCostId].payerType
|
||||
: item.payerType,
|
||||
};
|
||||
}
|
||||
// 未修改的成本项保持原样
|
||||
return item;
|
||||
});
|
||||
|
||||
// 创建新的purchaseOrderVO对象
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: updatedOrderCostList,
|
||||
};
|
||||
|
||||
// 调用onChange回调
|
||||
onChange(newPurchaseOrderVO as any);
|
||||
}
|
||||
}, [editValues]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className={"flex flex-col gap-2.5 divide-y divide-[#eaeaea]"}>
|
||||
<View className="flex flex-col gap-2.5">
|
||||
<View className={"text-sm font-bold"}>
|
||||
产地负责人:{purchaseOrderVO.originPrincipal}
|
||||
</View>
|
||||
{/* 产地垫付 */}
|
||||
{productionAdvanceCosts.map((item, index) => {
|
||||
// 初始化编辑值,包括费用承担方和工头姓名
|
||||
initEditValues(
|
||||
item.orderCostId,
|
||||
item.count,
|
||||
item.price,
|
||||
item.name,
|
||||
item.principal,
|
||||
item.payerType,
|
||||
);
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex items-center justify-between gap-2.5"
|
||||
key={item.orderCostId}
|
||||
onClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: true,
|
||||
}))
|
||||
}
|
||||
>
|
||||
<View className="text-neutral-dark flex-shrink-0 text-sm">
|
||||
{index + 1}-{item.name}
|
||||
{item.principal && `(${item.principal})`}
|
||||
</View>
|
||||
<View className="text-neutral-darkest flex flex-row items-center justify-between gap-2.5 text-sm font-medium">
|
||||
{formatCurrency(
|
||||
Number(
|
||||
(editValues[item.orderCostId]?.price || item.price) *
|
||||
(editValues[item.orderCostId]?.count || item.count),
|
||||
),
|
||||
)}
|
||||
{!readOnly && (
|
||||
<View className="ml-1 text-gray-500">
|
||||
<Icon
|
||||
name={"pen-to-square"}
|
||||
size={16}
|
||||
color={"#1a73e8"}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
|
||||
{!readOnly && (
|
||||
<Button
|
||||
type={"primary"}
|
||||
block
|
||||
size={"large"}
|
||||
onClick={() => setShowAddCostPopup(true)}
|
||||
>
|
||||
新增其他产地垫付费用
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 新增其他产地垫付费用 */}
|
||||
<Popup
|
||||
visible={showAddCostPopup}
|
||||
position="bottom"
|
||||
title="新增其他产地垫付费用"
|
||||
onClose={() => setShowAddCostPopup(false)}
|
||||
onOverlayClick={() => setShowAddCostPopup(false)}
|
||||
lockScroll
|
||||
>
|
||||
<ScrollView scrollY className="max-h-150">
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{/* 垫付项目 */}
|
||||
{newCostData.costType && (
|
||||
<>
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
垫付项目
|
||||
</View>
|
||||
<View
|
||||
className="border-neutral-base relative flex h-10 w-full items-center rounded-md border border-solid"
|
||||
onClick={() =>
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: true }))
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="请选择垫付项目"
|
||||
value={newCostData.name || ""}
|
||||
disabled
|
||||
/>
|
||||
<Icon
|
||||
name="chevron-down"
|
||||
className="absolute -right-1 mr-4"
|
||||
/>
|
||||
</View>
|
||||
<Picker
|
||||
title="请选择垫付项目"
|
||||
visible={pickerVisible.costItem}
|
||||
options={[
|
||||
costItems
|
||||
.filter((item) => item.costType === newCostData.costType)
|
||||
.filter((item) => {
|
||||
// 检查该项目是否已经被选择
|
||||
return !productionAdvanceCosts.some(
|
||||
(hc) => hc.itemId === item.itemId,
|
||||
);
|
||||
})
|
||||
.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.itemId,
|
||||
})),
|
||||
]}
|
||||
onConfirm={(_, values) => {
|
||||
const selectedValue = values[0] as string;
|
||||
const selectedItem = costItems.find(
|
||||
(item) => item.itemId === selectedValue,
|
||||
);
|
||||
if (selectedItem) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
itemId: selectedValue,
|
||||
name: selectedItem.name,
|
||||
payerType: "US",
|
||||
quantity: selectedItem.requireQuantityAndPrice ? 0 : 1, // 数量(人数)
|
||||
unit: selectedItem.requireQuantityAndPrice
|
||||
? selectedItem.unit
|
||||
: "元", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice:
|
||||
selectedItem.requireQuantityAndPrice,
|
||||
}));
|
||||
}
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: false }));
|
||||
}}
|
||||
onCancel={() =>
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: false }))
|
||||
}
|
||||
onClose={() =>
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: false }))
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 数量输入 */}
|
||||
{newCostData.itemId &&
|
||||
newCostData.costType &&
|
||||
newCostData.requireQuantityAndPrice && (
|
||||
<>
|
||||
<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 flex-1"
|
||||
placeholder="请输入数量"
|
||||
type="digit"
|
||||
value={newCostData.quantity?.toString() || ""}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
quantity: numValue as any,
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">{newCostData.unit}</View>
|
||||
</View>
|
||||
|
||||
{/* 单价输入 */}
|
||||
<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 flex-1"
|
||||
placeholder="请输入单价"
|
||||
type="digit"
|
||||
value={newCostData.unitPrice?.toString() || ""}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
unitPrice: numValue as any,
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
|
||||
{/* 金额展示 */}
|
||||
<View className="flex items-center justify-between rounded-md bg-gray-100 p-3">
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
金额
|
||||
</View>
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
{formatCurrency(
|
||||
Number(newCostData.quantity || 0) *
|
||||
Number(newCostData.unitPrice || 0),
|
||||
)}{" "}
|
||||
元
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
|
||||
{newCostData.itemId &&
|
||||
newCostData.costType &&
|
||||
!newCostData.requireQuantityAndPrice && (
|
||||
<>
|
||||
<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 flex-1"
|
||||
placeholder="请输入金额"
|
||||
type="digit"
|
||||
value={newCostData.amount?.toString() || ""}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
unitPrice: numValue as any,
|
||||
amount: numValue as any,
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() => {
|
||||
setShowAddCostPopup(false);
|
||||
|
||||
// 重置表单
|
||||
setNewCostData({
|
||||
costType: "PRODUCTION_ADVANCE", // 费用类型
|
||||
itemId: "",
|
||||
name: "", // 费用名称
|
||||
quantity: 0, // 数量(人数)
|
||||
unit: "", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
payerType: "", // 费用承担方,默认我方
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice: false,
|
||||
});
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 检查必填项
|
||||
if (!newCostData.itemId) {
|
||||
console.log("请选择辅料项目");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查数量和单价或金额
|
||||
if (
|
||||
newCostData.requireQuantityAndPrice &&
|
||||
(!newCostData.quantity || !newCostData.unitPrice)
|
||||
) {
|
||||
console.log("请填写数量和单价");
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!newCostData.requireQuantityAndPrice &&
|
||||
!newCostData.amount
|
||||
) {
|
||||
console.log("请填写金额");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新的费用项
|
||||
const newOrderCost: BusinessAPI.OrderCost = {
|
||||
orderCostId: generateShortId(),
|
||||
itemId: newCostData.itemId || "",
|
||||
name: newCostData.name,
|
||||
price: Number(newCostData.unitPrice || 0),
|
||||
unit: newCostData.unit,
|
||||
count: Number(newCostData.quantity || 1),
|
||||
//@ts-ignore
|
||||
payerType: newCostData.payerType || "US",
|
||||
costType: newCostData.costType!,
|
||||
principal: "",
|
||||
requireQuantityAndPrice: false,
|
||||
};
|
||||
|
||||
// 更新purchaseOrderVO,将新费用添加到orderCostList中
|
||||
if (onChange) {
|
||||
const updatedOrderCostList = [
|
||||
...(purchaseOrderVO.orderCostList || []),
|
||||
newOrderCost,
|
||||
];
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: updatedOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
setShowAddCostPopup(false);
|
||||
// 重置表单
|
||||
setNewCostData({
|
||||
costType: "PRODUCTION_ADVANCE", // 费用类型
|
||||
itemId: "",
|
||||
name: "", // 费用名称
|
||||
quantity: 0, // 数量(人数)
|
||||
unit: "", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
payerType: "", // 费用承担方,默认我方
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice: false,
|
||||
});
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</ScrollView>
|
||||
</Popup>
|
||||
|
||||
{/* 产地垫付 */}
|
||||
{productionAdvanceCosts.map((item) => {
|
||||
return (
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{item?.requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<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={(
|
||||
tempEditValues[item.orderCostId]?.price *
|
||||
tempEditValues[item.orderCostId]?.count ||
|
||||
item.price * item.count
|
||||
).toString()}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() => {
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...tempEditValues[item.orderCostId],
|
||||
// 如果费用承担方是瓜农,清空工头姓名
|
||||
principal:
|
||||
tempEditValues[item.orderCostId]?.payerType ===
|
||||
"OTHER"
|
||||
? ""
|
||||
: tempEditValues[item.orderCostId]?.principal,
|
||||
},
|
||||
}));
|
||||
|
||||
// 这里应该调用更新接口或更新状态
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter(
|
||||
(cost) => cost.orderCostId !== item.orderCostId,
|
||||
);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,762 @@
|
||||
import { ScrollView, View } from "@tarojs/components";
|
||||
import {
|
||||
Button,
|
||||
Input,
|
||||
Picker,
|
||||
Popup,
|
||||
SafeArea,
|
||||
} from "@nutui/nutui-react-taro";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Icon } from "@/components";
|
||||
import { business } from "@/services";
|
||||
import { formatCurrency, validatePrice } from "@/utils/format";
|
||||
import { generateShortId } from "@/utils/generateShortId";
|
||||
|
||||
export default function WorkerAdvanceSection(props: {
|
||||
purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
|
||||
onChange?: (purchaseOrderVO: BusinessAPI.PurchaseOrderVO) => void;
|
||||
readOnly?: boolean;
|
||||
}) {
|
||||
const { purchaseOrderVO, onChange, readOnly } = props;
|
||||
|
||||
// 弹窗相关状态
|
||||
const [visiblePopup, setVisiblePopup] = useState<{ [key: string]: boolean }>(
|
||||
{},
|
||||
);
|
||||
|
||||
// 新增人工费弹窗状态
|
||||
const [showAddCostPopup, setShowAddCostPopup] = useState(false);
|
||||
|
||||
// 新增人工费表单数据
|
||||
const [newCostData, setNewCostData] = useState<any>({
|
||||
costType: "WORKER_ADVANCE", // 费用类型
|
||||
itemId: "", // 费用项目ID
|
||||
name: "", // 费用名称
|
||||
quantity: 0, // 数量(人数)
|
||||
unit: "", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
payerType: "US", // 费用承担方,默认我方
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice: false,
|
||||
});
|
||||
|
||||
console.log("newCostData", newCostData);
|
||||
|
||||
// Picker可见状态
|
||||
const [pickerVisible, setPickerVisible] = useState({
|
||||
costType: false, // 费用类型Picker
|
||||
costItem: false, // 费用项目Picker
|
||||
});
|
||||
|
||||
// 费用项目列表
|
||||
const [costItems, setCostItems] = useState<BusinessAPI.CostItemVO[]>([]);
|
||||
|
||||
// 编辑值的状态
|
||||
const [editValues, setEditValues] = useState<{
|
||||
[key: string]: {
|
||||
count: number;
|
||||
price: number;
|
||||
name?: string;
|
||||
principal?: string;
|
||||
payerType?: "US" | "OTHER";
|
||||
};
|
||||
}>({});
|
||||
|
||||
// 临时编辑值的状态(用于在保存前暂存编辑的值)
|
||||
const [tempEditValues, setTempEditValues] = useState<{
|
||||
[key: string]: {
|
||||
count: number;
|
||||
price: number;
|
||||
name?: string;
|
||||
principal?: string;
|
||||
payerType?: "US" | "OTHER";
|
||||
};
|
||||
}>({});
|
||||
|
||||
// 初始化编辑值
|
||||
const initEditValues = (
|
||||
itemId: string,
|
||||
count: number,
|
||||
price: number,
|
||||
name?: string,
|
||||
principal?: string,
|
||||
payerType?: "US" | "OTHER",
|
||||
) => {
|
||||
if (!editValues[itemId]) {
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[itemId]: { count, price, name, principal, payerType },
|
||||
}));
|
||||
}
|
||||
|
||||
// 同时初始化临时编辑值
|
||||
if (!tempEditValues[itemId]) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[itemId]: { count, price, name, principal, payerType },
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
// 获取费用项目列表
|
||||
useEffect(() => {
|
||||
const fetchCostItems = async () => {
|
||||
try {
|
||||
const { data } = await business.costItem.listCostItem({
|
||||
costItemListQry: {
|
||||
status: true,
|
||||
showInEntry: true,
|
||||
},
|
||||
});
|
||||
setCostItems(data.data || []);
|
||||
} catch (error) {
|
||||
console.error("获取费用项目列表失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchCostItems();
|
||||
}, []);
|
||||
|
||||
// 人工费
|
||||
const humanCosts =
|
||||
purchaseOrderVO.orderCostList?.filter(
|
||||
(item) =>
|
||||
item.costType === "HUMAN_COST" &&
|
||||
item.payerType === "US" &&
|
||||
item.count > 0,
|
||||
) || [];
|
||||
|
||||
// 工头垫付
|
||||
const workerAdvanceCosts =
|
||||
purchaseOrderVO.orderCostList?.filter(
|
||||
(item) => item.costType === "WORKER_ADVANCE",
|
||||
) || [];
|
||||
|
||||
// 当editValues发生变化时,更新purchaseOrderVO
|
||||
useEffect(() => {
|
||||
// 只有当onChange存在时才更新
|
||||
if (onChange) {
|
||||
// 获取现有的orderCostList
|
||||
const existingOrderCostList = purchaseOrderVO.orderCostList || [];
|
||||
|
||||
// 更新已有的成本项
|
||||
const updatedOrderCostList = existingOrderCostList.map((item) => {
|
||||
if (editValues[item.orderCostId]) {
|
||||
return {
|
||||
...item,
|
||||
price:
|
||||
editValues[item.orderCostId].price !== undefined
|
||||
? editValues[item.orderCostId].price
|
||||
: item.price,
|
||||
count:
|
||||
editValues[item.orderCostId].count !== undefined
|
||||
? editValues[item.orderCostId].count
|
||||
: item.count,
|
||||
name:
|
||||
editValues[item.orderCostId].name !== undefined
|
||||
? editValues[item.orderCostId].name
|
||||
: item.name,
|
||||
principal:
|
||||
editValues[item.orderCostId].principal !== undefined
|
||||
? editValues[item.orderCostId].principal
|
||||
: item.principal,
|
||||
payerType:
|
||||
editValues[item.orderCostId].payerType !== undefined
|
||||
? editValues[item.orderCostId].payerType
|
||||
: item.payerType,
|
||||
};
|
||||
}
|
||||
// 未修改的成本项保持原样
|
||||
return item;
|
||||
});
|
||||
|
||||
// 创建新的purchaseOrderVO对象
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: updatedOrderCostList,
|
||||
};
|
||||
|
||||
// 调用onChange回调
|
||||
onChange(newPurchaseOrderVO as any);
|
||||
}
|
||||
}, [editValues]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className={"flex flex-col gap-2.5 divide-y divide-[#eaeaea]"}>
|
||||
<View className="flex flex-col gap-2.5">
|
||||
<View className={"flex flex-col gap-2.5"}>
|
||||
<View className={"text-sm font-bold"}>
|
||||
工头:{humanCosts?.[0].principal}
|
||||
</View>
|
||||
<View
|
||||
className={
|
||||
"text-neutral-dark flex flex-row flex-wrap gap-2.5 text-xs font-medium"
|
||||
}
|
||||
>
|
||||
{humanCosts.map((item, index) => {
|
||||
return (
|
||||
<View key={index}>{`${item.name} ${item.count}人`}</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
{/* 工头垫付 */}
|
||||
{workerAdvanceCosts.map((item, index) => {
|
||||
// 初始化编辑值,包括费用承担方和工头姓名
|
||||
initEditValues(
|
||||
item.orderCostId,
|
||||
item.count,
|
||||
item.price,
|
||||
item.name,
|
||||
item.principal,
|
||||
item.payerType,
|
||||
);
|
||||
|
||||
return (
|
||||
<View
|
||||
className="flex items-center justify-between gap-2.5"
|
||||
key={item.orderCostId}
|
||||
onClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: true,
|
||||
}))
|
||||
}
|
||||
>
|
||||
<View className="text-neutral-dark flex-shrink-0 text-sm">
|
||||
{index + 1}-{item.name}
|
||||
{item.principal && `(${item.principal})`}
|
||||
</View>
|
||||
<View className="text-neutral-darkest flex flex-row items-center justify-between gap-2.5 text-sm font-medium">
|
||||
{formatCurrency(
|
||||
Number(
|
||||
(editValues[item.orderCostId]?.price || item.price) *
|
||||
(editValues[item.orderCostId]?.count || item.count),
|
||||
),
|
||||
)}
|
||||
{!readOnly && (
|
||||
<View className="ml-1 text-gray-500">
|
||||
<Icon
|
||||
name={"pen-to-square"}
|
||||
size={16}
|
||||
color={"#1a73e8"}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
|
||||
{!readOnly && (
|
||||
<Button
|
||||
type={"primary"}
|
||||
block
|
||||
size={"large"}
|
||||
onClick={() => setShowAddCostPopup(true)}
|
||||
>
|
||||
新增其他工头垫付费用
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
|
||||
{/* 新增其他工头垫付费用 */}
|
||||
<Popup
|
||||
visible={showAddCostPopup}
|
||||
position="bottom"
|
||||
title="新增其他工头垫付费用"
|
||||
onClose={() => setShowAddCostPopup(false)}
|
||||
onOverlayClick={() => setShowAddCostPopup(false)}
|
||||
lockScroll
|
||||
>
|
||||
<ScrollView scrollY className="max-h-150">
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{/* 垫付项目 */}
|
||||
{newCostData.costType && (
|
||||
<>
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
垫付项目
|
||||
</View>
|
||||
<View
|
||||
className="border-neutral-base relative flex h-10 w-full items-center rounded-md border border-solid"
|
||||
onClick={() =>
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: true }))
|
||||
}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="请选择垫付项目"
|
||||
value={newCostData.name || ""}
|
||||
disabled
|
||||
/>
|
||||
<Icon
|
||||
name="chevron-down"
|
||||
className="absolute -right-1 mr-4"
|
||||
/>
|
||||
</View>
|
||||
<Picker
|
||||
title="请选择垫付项目"
|
||||
visible={pickerVisible.costItem}
|
||||
options={[
|
||||
costItems
|
||||
.filter((item) => item.costType === newCostData.costType)
|
||||
.filter((item) => {
|
||||
return !workerAdvanceCosts.some(
|
||||
(hc) => hc.itemId === item.itemId,
|
||||
);
|
||||
})
|
||||
.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.itemId,
|
||||
})),
|
||||
]}
|
||||
onConfirm={(_, values) => {
|
||||
const selectedValue = values[0] as string;
|
||||
const selectedItem = costItems.find(
|
||||
(item) => item.itemId === selectedValue,
|
||||
);
|
||||
if (selectedItem) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
itemId: selectedValue,
|
||||
name: selectedItem.name,
|
||||
payerType: "US",
|
||||
quantity: selectedItem.requireQuantityAndPrice ? 0 : 1, // 数量(人数)
|
||||
unit: selectedItem.requireQuantityAndPrice
|
||||
? selectedItem.unit
|
||||
: "元", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice:
|
||||
selectedItem.requireQuantityAndPrice,
|
||||
}));
|
||||
}
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: false }));
|
||||
}}
|
||||
onCancel={() =>
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: false }))
|
||||
}
|
||||
onClose={() =>
|
||||
setPickerVisible((prev) => ({ ...prev, costItem: false }))
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* 数量输入 */}
|
||||
{newCostData.itemId &&
|
||||
newCostData.costType &&
|
||||
newCostData.requireQuantityAndPrice && (
|
||||
<>
|
||||
<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 flex-1"
|
||||
placeholder="请输入数量"
|
||||
type="digit"
|
||||
value={newCostData.quantity?.toString() || ""}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
quantity: numValue as any,
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">{newCostData.unit}</View>
|
||||
</View>
|
||||
|
||||
{/* 单价输入 */}
|
||||
<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 flex-1"
|
||||
placeholder="请输入单价"
|
||||
type="digit"
|
||||
value={newCostData.unitPrice?.toString() || ""}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
unitPrice: numValue as any,
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
|
||||
{/* 金额展示 */}
|
||||
<View className="flex items-center justify-between rounded-md bg-gray-100 p-3">
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
金额
|
||||
</View>
|
||||
<View className="text-neutral-darkest text-sm font-medium">
|
||||
{formatCurrency(
|
||||
Number(newCostData.quantity || 0) *
|
||||
Number(newCostData.unitPrice || 0),
|
||||
)}{" "}
|
||||
元
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
|
||||
{newCostData.itemId &&
|
||||
newCostData.costType &&
|
||||
!newCostData.requireQuantityAndPrice && (
|
||||
<>
|
||||
<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 flex-1"
|
||||
placeholder="请输入金额"
|
||||
type="digit"
|
||||
value={newCostData.amount?.toString() || ""}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setNewCostData((prev) => ({
|
||||
...prev,
|
||||
unitPrice: numValue as any,
|
||||
amount: numValue as any,
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() => {
|
||||
setShowAddCostPopup(false);
|
||||
|
||||
// 重置表单
|
||||
setNewCostData({
|
||||
costType: "WORKER_ADVANCE", // 费用类型
|
||||
itemId: "",
|
||||
name: "", // 费用名称
|
||||
quantity: 0, // 数量(人数)
|
||||
unit: "", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
payerType: "", // 费用承担方,默认我方
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice: false,
|
||||
});
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 检查必填项
|
||||
if (!newCostData.itemId) {
|
||||
console.log("请选择辅料项目");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查数量和单价或金额
|
||||
if (
|
||||
newCostData.requireQuantityAndPrice &&
|
||||
(!newCostData.quantity || !newCostData.unitPrice)
|
||||
) {
|
||||
console.log("请填写数量和单价");
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!newCostData.requireQuantityAndPrice &&
|
||||
!newCostData.amount
|
||||
) {
|
||||
console.log("请填写金额");
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建新的费用项
|
||||
const newOrderCost: BusinessAPI.OrderCost = {
|
||||
orderCostId: generateShortId(),
|
||||
itemId: newCostData.itemId || "",
|
||||
name: newCostData.name,
|
||||
price: Number(newCostData.unitPrice || 0),
|
||||
unit: newCostData.unit,
|
||||
count: Number(newCostData.quantity || 1),
|
||||
//@ts-ignore
|
||||
payerType: newCostData.payerType || "US",
|
||||
costType: newCostData.costType!,
|
||||
principal: "",
|
||||
requireQuantityAndPrice: false,
|
||||
};
|
||||
|
||||
// 更新purchaseOrderVO,将新费用添加到orderCostList中
|
||||
if (onChange) {
|
||||
const updatedOrderCostList = [
|
||||
...(purchaseOrderVO.orderCostList || []),
|
||||
newOrderCost,
|
||||
];
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: updatedOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
setShowAddCostPopup(false);
|
||||
// 重置表单
|
||||
setNewCostData({
|
||||
costType: "PRODUCTION_ADVANCE", // 费用类型
|
||||
itemId: "",
|
||||
name: "", // 费用名称
|
||||
quantity: 0, // 数量(人数)
|
||||
unit: "", // 单位
|
||||
unitPrice: "", // 单价
|
||||
amount: "", // 金额
|
||||
payerType: "", // 费用承担方,默认我方
|
||||
principal: "", // 工头姓名
|
||||
requireQuantityAndPrice: false,
|
||||
});
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</ScrollView>
|
||||
</Popup>
|
||||
|
||||
{/* 工头垫付 */}
|
||||
{workerAdvanceCosts.map((item) => {
|
||||
return (
|
||||
<Popup
|
||||
key={item.orderCostId}
|
||||
visible={visiblePopup[item.orderCostId]}
|
||||
position="bottom"
|
||||
title={`编辑${item.name}`}
|
||||
onClose={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
onOverlayClick={() =>
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}))
|
||||
}
|
||||
lockScroll
|
||||
>
|
||||
<View className="flex flex-col gap-3 p-2.5">
|
||||
{item?.requireQuantityAndPrice ? (
|
||||
<>
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.count?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
count: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">人</View>
|
||||
</View>
|
||||
|
||||
<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={
|
||||
tempEditValues[item.orderCostId]?.price?.toString() ||
|
||||
""
|
||||
}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<View className="mr-2">元</View>
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<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={(
|
||||
tempEditValues[item.orderCostId]?.price *
|
||||
tempEditValues[item.orderCostId]?.count ||
|
||||
item.price * item.count
|
||||
).toString()}
|
||||
onChange={(value) => {
|
||||
const numValue = validatePrice(value);
|
||||
if (numValue !== undefined) {
|
||||
setTempEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...prev[item.orderCostId],
|
||||
price: numValue as number,
|
||||
count: 1,
|
||||
},
|
||||
}));
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<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={() => {
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
// 保存时才更新editValues状态
|
||||
setEditValues((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: {
|
||||
...tempEditValues[item.orderCostId],
|
||||
// 如果费用承担方是瓜农,清空工头姓名
|
||||
principal:
|
||||
tempEditValues[item.orderCostId]?.payerType ===
|
||||
"OTHER"
|
||||
? ""
|
||||
: tempEditValues[item.orderCostId]?.principal,
|
||||
},
|
||||
}));
|
||||
|
||||
// 这里应该调用更新接口或更新状态
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
保存
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size="large"
|
||||
block
|
||||
type="danger"
|
||||
onClick={() => {
|
||||
// 删除费用项
|
||||
setEditValues((prev) => {
|
||||
const newEditValues = { ...prev };
|
||||
delete newEditValues[item.orderCostId];
|
||||
return newEditValues;
|
||||
});
|
||||
|
||||
// 更新purchaseOrderVO,移除被删除的费用项
|
||||
if (onChange) {
|
||||
const newOrderCostList = (
|
||||
purchaseOrderVO.orderCostList || []
|
||||
).filter(
|
||||
(cost) => cost.orderCostId !== item.orderCostId,
|
||||
);
|
||||
const newPurchaseOrderVO = {
|
||||
...purchaseOrderVO,
|
||||
orderCostList: newOrderCostList,
|
||||
};
|
||||
onChange(newPurchaseOrderVO);
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
setVisiblePopup((prev) => ({
|
||||
...prev,
|
||||
[item.orderCostId]: false,
|
||||
}));
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -1,7 +1,14 @@
|
||||
import hocAuth from "@/hocs/auth";
|
||||
import { CommonComponent, CostItem, SupplierVO } from "@/types/typings";
|
||||
import { View } from "@tarojs/components";
|
||||
import { Button, Dialog, SafeArea, Toast } from "@nutui/nutui-react-taro";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
SafeArea,
|
||||
Toast,
|
||||
Tour,
|
||||
TourList,
|
||||
} from "@nutui/nutui-react-taro";
|
||||
import { purchase } from "@/constant";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
@ -61,6 +68,26 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
const defaultStep = router.params.step as number;
|
||||
const defaultSupplierId = router.params.supplierId as string;
|
||||
|
||||
const [showTour, setShowTour] = useState(true);
|
||||
|
||||
const closeTour = () => {
|
||||
setShowTour(false);
|
||||
};
|
||||
|
||||
const steps: TourList[] = [
|
||||
{
|
||||
content: "粘贴识别",
|
||||
target: "target1",
|
||||
popoverOffset: [0, 12],
|
||||
arrowOffset: 0,
|
||||
},
|
||||
{
|
||||
content: "选择经销商",
|
||||
target: "target2",
|
||||
location: "bottom-left",
|
||||
},
|
||||
];
|
||||
|
||||
const vehicleRef = useRef<OrderVehicleRef>(null);
|
||||
// 创建MelonFarmer组件的ref数组
|
||||
const melonFarmerRefs = useRef<MelonFarmerRef[]>([]);
|
||||
@ -622,29 +649,54 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
}),
|
||||
]);
|
||||
setPurchaseOrder((prev) => {
|
||||
const costItemVOList = productVO.costItemVOList;
|
||||
|
||||
// 将 orderCostList 中 不存在与 costItemVOList 的项 删除,剩余项保留
|
||||
const orderCostList = prev?.orderCostList.filter((item) => {
|
||||
return (
|
||||
(item.costType === "WORKER_ADVANCE" ||
|
||||
item.costType === "PRODUCTION_ADVANCE" ||
|
||||
item.costType === "PACKAGING_MATERIALS") &&
|
||||
costItemVOList?.find(
|
||||
(costItemVO) => costItemVO.itemId === item.itemId,
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// 添加 costItemVOList 中 不存在与 orderCostList 的项
|
||||
costItemVOList?.forEach((item) => {
|
||||
if (
|
||||
!orderCostList?.find(
|
||||
(costItemVO) => costItemVO.itemId === item.itemId,
|
||||
)
|
||||
) {
|
||||
orderCostList?.push({
|
||||
orderCostId: generateShortId(),
|
||||
orderId: purchaseOrder?.orderId,
|
||||
itemId: item.itemId,
|
||||
name: item.name,
|
||||
price: item.price,
|
||||
unit: item.unit,
|
||||
count: 0,
|
||||
payerType: "US" as any,
|
||||
principal: "",
|
||||
costType: item.costType,
|
||||
requireQuantityAndPrice: item.requireQuantityAndPrice,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
...prev!,
|
||||
orderCostList: [
|
||||
...(prev?.orderCostList?.filter((item) => {
|
||||
return (
|
||||
item.costType !== "WORKER_ADVANCE" &&
|
||||
item.costType !== "PRODUCTION_ADVANCE"
|
||||
item.costType !== "PRODUCTION_ADVANCE" &&
|
||||
item.costType !== "PACKAGING_MATERIALS"
|
||||
);
|
||||
}) || []),
|
||||
...(productVO.costItemVOList?.map((item) => {
|
||||
return {
|
||||
orderCostId: generateShortId(),
|
||||
orderId: purchaseOrder?.orderId,
|
||||
itemId: item.itemId,
|
||||
name: item.name,
|
||||
price: item.price,
|
||||
unit: item.unit,
|
||||
count: 0,
|
||||
payerType: "US" as any,
|
||||
principal: "",
|
||||
costType: item.costType,
|
||||
};
|
||||
}) || []),
|
||||
...(orderCostList || []),
|
||||
],
|
||||
};
|
||||
});
|
||||
@ -866,6 +918,15 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
</View>
|
||||
<SafeArea position={"bottom"} />
|
||||
</View>
|
||||
|
||||
<Tour
|
||||
className="nut-custom-tour nut-customword-tour hidden"
|
||||
visible={showTour}
|
||||
onClose={closeTour}
|
||||
list={steps}
|
||||
type="step"
|
||||
location="bottom-right"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
@ -5,13 +5,7 @@ import { business } from "@/services";
|
||||
import { useEffect, useState } from "react";
|
||||
import { View } from "@tarojs/components";
|
||||
import purchaseOrder from "@/constant/purchaseOrder";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
Input,
|
||||
SafeArea,
|
||||
Toast,
|
||||
} from "@nutui/nutui-react-taro";
|
||||
import { ActionSheet, Button, Dialog, Input, Popup, SafeArea, TextArea, Toast } from "@nutui/nutui-react-taro";
|
||||
import {
|
||||
BasicInfoSection,
|
||||
CompanyInfoSection,
|
||||
@ -19,16 +13,16 @@ import {
|
||||
CostSummarySection,
|
||||
DealerInfoSection,
|
||||
EmptyBoxInfoSection,
|
||||
LaborInfoSection,
|
||||
MarketPriceSection,
|
||||
MaterialCostSection,
|
||||
PackageInfoSection,
|
||||
PackagingCostSection,
|
||||
PurchaseOrderRejectApprove,
|
||||
ProductionAdvanceSection,
|
||||
RebateCalcSection,
|
||||
State,
|
||||
TaxProvisionSection,
|
||||
TaxSubsidySection,
|
||||
WorkerAdvanceSection
|
||||
} from "@/components";
|
||||
import buildUrl from "@/utils/buildUrl";
|
||||
import { PurchaseOrderCalculator } from "@/utils/PurchaseOrderCalculator";
|
||||
@ -38,113 +32,86 @@ const sections = {
|
||||
marketPrice: {
|
||||
component: MarketPriceSection,
|
||||
title: "市场报价",
|
||||
containerClass: "border-l-8 border-l-lime-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 我方入账公司
|
||||
supplierInfo: {
|
||||
component: CompanyInfoSection,
|
||||
title: "我方入账公司",
|
||||
containerClass: "border-l-8 border-l-blue-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 下游经销商信息
|
||||
dealerInfo: {
|
||||
component: DealerInfoSection,
|
||||
title: "下游经销商",
|
||||
containerClass: "border-l-8 border-l-green-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 基础信息
|
||||
basicInfo: {
|
||||
component: BasicInfoSection,
|
||||
title: "基础信息",
|
||||
containerClass: "border-l-8 border-l-yellow-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// // 瓜农信息
|
||||
// farmerInfo: {
|
||||
// component: SupplierInfoSection,
|
||||
// title: "瓜农信息",
|
||||
// containerClass: "border-l-8 border-l-purple-500",
|
||||
// contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
// },
|
||||
// // 采购成本
|
||||
// purchaseCostInfo: {
|
||||
// component: PurchaseCostInfoSection,
|
||||
// title: "采购成本",
|
||||
// containerClass: "border-l-8 border-l-red-500",
|
||||
// contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
// },
|
||||
// 包装纸箱费
|
||||
packageInfo: {
|
||||
component: PackageInfoSection,
|
||||
title: "包装纸箱费复核",
|
||||
containerClass: "border-l-8 border-l-indigo-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 空箱费用
|
||||
emptyBoxInfo: {
|
||||
component: EmptyBoxInfoSection,
|
||||
title: "空箱费用复核",
|
||||
containerClass: "border-l-8 border-l-pink-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 用工信息
|
||||
laborInfo: {
|
||||
component: LaborInfoSection,
|
||||
title: "人工费复核",
|
||||
containerClass: "border-l-8 border-l-teal-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
// 工头垫付费用复核
|
||||
foremanAdvance: {
|
||||
component: WorkerAdvanceSection,
|
||||
title: "工头垫付费用复核",
|
||||
},
|
||||
// 产地垫付费用复核
|
||||
originAdvance: {
|
||||
component: ProductionAdvanceSection,
|
||||
title: "产地垫付费用复核",
|
||||
},
|
||||
// 辅料费用复核
|
||||
materialCost: {
|
||||
component: MaterialCostSection,
|
||||
title: "辅料费复核",
|
||||
containerClass: "border-l-8 border-l-orange-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 其他费用复核
|
||||
otherCost: {
|
||||
component: PackagingCostSection,
|
||||
title: "其他费用复核",
|
||||
containerClass: "border-l-8 border-l-orange-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 成本合计
|
||||
costSummary: {
|
||||
component: CostSummarySection,
|
||||
title: "成本合计",
|
||||
containerClass: "border-l-8 border-l-cyan-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 个人返点复核
|
||||
rebateCalc: {
|
||||
component: RebateCalcSection,
|
||||
title: "个人返点复核",
|
||||
containerClass: "border-l-8 border-l-amber-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 公司返点复核
|
||||
taxSubsidy: {
|
||||
component: TaxSubsidySection,
|
||||
title: "公司返点复核",
|
||||
containerClass: "border-l-8 border-l-amber-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 计提税金复核
|
||||
taxProvision: {
|
||||
component: TaxProvisionSection,
|
||||
title: "计提税金复核",
|
||||
containerClass: "border-l-8 border-l-amber-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
// 调诚信志远分红
|
||||
costDifference: {
|
||||
component: CostDifferenceSection,
|
||||
title: "调诚信志远分红",
|
||||
containerClass: "border-l-8 border-l-amber-500",
|
||||
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
|
||||
},
|
||||
};
|
||||
|
||||
@ -157,16 +124,75 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
const [purchaseOrderVO, setPurchaseOrderVO] =
|
||||
useState<BusinessAPI.PurchaseOrderVO>();
|
||||
|
||||
const [originPrincipal, setOriginPrincipal] = useState("");
|
||||
// 驳回原因弹窗相关状态
|
||||
const [rejectVisible, setRejectVisible] = useState(false);
|
||||
const [rejectReason, setRejectReason] = useState("");
|
||||
|
||||
const [collapsedSections, setCollapsedSections] = useState<
|
||||
Record<string, boolean>
|
||||
>(Object.keys(sections).reduce((acc, key) => ({ ...acc, [key]: false }), {}));
|
||||
// 驳回操作
|
||||
const handleReject = () => {
|
||||
setRejectVisible(true);
|
||||
};
|
||||
|
||||
// 确认驳回
|
||||
const confirmReject = async () => {
|
||||
if (!purchaseOrderVO) {
|
||||
Toast.show("toast", {
|
||||
icon: "fail",
|
||||
title: "提示",
|
||||
content: "请稍后再试",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rejectReason.trim()) {
|
||||
Toast.show("toast", {
|
||||
icon: "fail",
|
||||
title: "提示",
|
||||
content: "请输入驳回原因",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用驳回API
|
||||
await business.purchaseOrder.rejectApprovePurchaseOrder({
|
||||
orderId: purchaseOrderVO?.orderId,
|
||||
rejectReason: rejectReason,
|
||||
});
|
||||
|
||||
Toast.show("toast", {
|
||||
icon: "success",
|
||||
title: "提示",
|
||||
content: "驳回成功,正在跳转我的审核...",
|
||||
});
|
||||
|
||||
// 关闭弹窗
|
||||
setRejectVisible(false);
|
||||
setRejectReason("");
|
||||
|
||||
setTimeout(() => {
|
||||
Taro.redirectTo({ url: buildUrl("/pages/purchase/reviewer/list") });
|
||||
}, 1000);
|
||||
|
||||
// 返回采购单页面
|
||||
} catch (error) {
|
||||
Toast.show("toast", {
|
||||
icon: "fail",
|
||||
title: "提示",
|
||||
content: error.message || "驳回失败",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const [originPrincipal, setOriginPrincipal] = useState("");
|
||||
|
||||
// 暂存和提交审核的Dialog状态
|
||||
const [saveDialogVisible, setSaveDialogVisible] = useState(false);
|
||||
const [submitDialogVisible, setSubmitDialogVisible] = useState(false);
|
||||
|
||||
// 控制更多操作的ActionSheet显示状态
|
||||
const [moreActionVisible, setMoreActionVisible] = useState(false);
|
||||
|
||||
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
|
||||
|
||||
const initDealer = async (dealerId: BusinessAPI.DealerVO["dealerId"]) => {
|
||||
@ -180,13 +206,6 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
setDealerVO(data.data);
|
||||
};
|
||||
|
||||
const toggleSection = (section: string) => {
|
||||
setCollapsedSections((prev) => ({
|
||||
...prev,
|
||||
[section]: !prev[section],
|
||||
}));
|
||||
};
|
||||
|
||||
// 暂存操作
|
||||
const handleSave = () => {
|
||||
setSaveDialogVisible(true);
|
||||
@ -335,124 +354,119 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
const personalProfit = calculator.getPersonalProfit();
|
||||
|
||||
return (
|
||||
<View className={"flex flex-col gap-2.5"} id={"purchase-order-audit"}>
|
||||
{/* 顶部导航 */}
|
||||
<View className="flex flex-col gap-2.5 bg-white p-2.5">
|
||||
<View className={"flex flex-row justify-between gap-2.5"}>
|
||||
<View className="text-lg font-bold">
|
||||
{purchaseOrderVO?.orderDealer?.shortName || "-"} 第
|
||||
{purchaseOrderVO?.orderVehicle?.vehicleNo || "-"}车
|
||||
</View>
|
||||
|
||||
<State
|
||||
state={purchaseOrderVO.state}
|
||||
stateMap={purchaseOrder.stateMap}
|
||||
/>
|
||||
</View>
|
||||
<View className="text-neutral-darker text-sm font-medium">
|
||||
{purchaseOrderVO?.orderVehicle.origin || "-"} 至{" "}
|
||||
{purchaseOrderVO?.orderVehicle.destination || "-"}
|
||||
</View>
|
||||
|
||||
{/* 展示产地负责人*/}
|
||||
<View className="flex flex-row items-center gap-2.5">
|
||||
<View className="flex-shrink-0 text-base font-bold text-gray-900">
|
||||
产地负责人
|
||||
</View>
|
||||
|
||||
<View
|
||||
className={`flex h-12 w-full items-center rounded-lg border-2 border-gray-300 bg-gray-50 px-3`}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
disabled={
|
||||
role === "boss" ||
|
||||
(role === "reviewer" &&
|
||||
purchaseOrderVO.state !== "WAITING_AUDIT")
|
||||
}
|
||||
placeholder="请输入产地负责人姓名"
|
||||
value={originPrincipal || purchaseOrderVO.createdByName}
|
||||
onChange={(value) => setOriginPrincipal(value)}
|
||||
onBlur={() => {
|
||||
// 更新采购订单中的产地负责人
|
||||
setPurchaseOrderVO((prev) => ({
|
||||
...prev!,
|
||||
originPrincipal: originPrincipal,
|
||||
}));
|
||||
}}
|
||||
className="w-full bg-transparent"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 循环渲染各部分内容 */}
|
||||
{Object.keys(sections).map((sectionKey) => {
|
||||
const section = sections[sectionKey];
|
||||
const isCollapsed = collapsedSections[sectionKey];
|
||||
|
||||
if (!dealerVO?.enableCompanyRebate && sectionKey === "taxSubsidy") {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!dealerVO?.enableAccrualTax && sectionKey === "taxProvision") {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!dealerVO?.enableShare && sectionKey === "costDifference") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View className="overflow-hidden bg-white" key={sectionKey}>
|
||||
<View
|
||||
className={`z-10 flex items-center justify-between p-4 shadow-sm ${section.containerClass}`}
|
||||
onClick={() => toggleSection(sectionKey)}
|
||||
>
|
||||
<View className="text-base font-bold text-gray-800">
|
||||
{section.title}
|
||||
<>
|
||||
<View
|
||||
className={"overflow-x-hidden overflow-y-auto bg-[#D1D5DB]"}
|
||||
id={"purchase-order-audit"}
|
||||
>
|
||||
<View className={"flex flex-col gap-2.5 p-2.5"}>
|
||||
{/* 顶部导航 */}
|
||||
<View className="flex flex-col gap-2.5 rounded-md bg-white p-2.5 shadow-sm">
|
||||
<View className={"flex flex-row justify-between gap-2.5"}>
|
||||
<View className="text-lg font-bold">
|
||||
{purchaseOrderVO?.orderDealer?.shortName || "-"} 第
|
||||
{purchaseOrderVO?.orderVehicle?.vehicleNo || "-"}车
|
||||
</View>
|
||||
<View className="text-neutral-darker text-lg">
|
||||
{isCollapsed ? "▲" : "▼"}
|
||||
|
||||
<State
|
||||
state={purchaseOrderVO.state}
|
||||
stateMap={purchaseOrder.stateMap}
|
||||
/>
|
||||
</View>
|
||||
<View className="text-neutral-darker text-sm font-medium">
|
||||
{purchaseOrderVO?.orderVehicle.origin || "-"} 至{" "}
|
||||
{purchaseOrderVO?.orderVehicle.destination || "-"}
|
||||
</View>
|
||||
|
||||
{/* 展示产地负责人*/}
|
||||
<View className="flex flex-row items-center gap-2.5">
|
||||
<View className="flex-shrink-0 text-base font-bold text-gray-900">
|
||||
产地负责人
|
||||
</View>
|
||||
|
||||
<View
|
||||
className={`flex h-10 flex-1 items-center rounded-md border-4 border-gray-300`}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
disabled={
|
||||
role === "boss" ||
|
||||
(role === "reviewer" &&
|
||||
purchaseOrderVO.state !== "WAITING_AUDIT")
|
||||
}
|
||||
placeholder="请输入产地负责人姓名"
|
||||
value={originPrincipal || purchaseOrderVO.createdByName}
|
||||
onChange={(value) => setOriginPrincipal(value)}
|
||||
onBlur={() => {
|
||||
// 更新采购订单中的产地负责人
|
||||
setPurchaseOrderVO((prev) => ({
|
||||
...prev!,
|
||||
originPrincipal: originPrincipal,
|
||||
}));
|
||||
}}
|
||||
className="w-full bg-transparent"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
{!isCollapsed && (
|
||||
<View className={section.contentClass}>
|
||||
<section.component
|
||||
dealerVO={dealerVO}
|
||||
purchaseOrderVO={purchaseOrderVO}
|
||||
onChange={setPurchaseOrderVO}
|
||||
// readOnly={
|
||||
// role === "boss" ||
|
||||
// (role === "reviewer" &&
|
||||
// purchaseOrderVO.state !== "WAITING_AUDIT")
|
||||
// }
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 循环渲染各部分内容 */}
|
||||
{Object.keys(sections).map((sectionKey) => {
|
||||
const section = sections[sectionKey];
|
||||
|
||||
if (!dealerVO?.enableCompanyRebate && sectionKey === "taxSubsidy") {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!dealerVO?.enableAccrualTax && sectionKey === "taxProvision") {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!dealerVO?.enableShare && sectionKey === "costDifference") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<View className="text-sm font-bold">{section.title}</View>
|
||||
<View
|
||||
className={`overflow-x-auto rounded-md rounded-b-lg bg-white p-2.5 shadow-sm`}
|
||||
>
|
||||
<section.component
|
||||
dealerVO={dealerVO}
|
||||
purchaseOrderVO={purchaseOrderVO}
|
||||
onChange={setPurchaseOrderVO}
|
||||
/>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* 个人利润 */}
|
||||
<View
|
||||
className={
|
||||
"flex flex-row items-center rounded-md border border-[#FFBB96] p-4"
|
||||
}
|
||||
style={{
|
||||
background: "linear-gradient(100deg, #FFF2E8 25%, #FFE7D9 75%)",
|
||||
}}
|
||||
>
|
||||
<View className={"flex-1 text-center"}>个人利润</View>
|
||||
{personalProfit > 0 ? (
|
||||
<View
|
||||
className={"text-primary flex-1 text-left text-2xl font-bold"}
|
||||
>
|
||||
¥ {personalProfit || "-"}
|
||||
</View>
|
||||
) : (
|
||||
<View
|
||||
className={"flex-1 text-left text-2xl font-bold text-red-500"}
|
||||
>
|
||||
¥ {personalProfit || "-"}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* 个人利润 */}
|
||||
<View
|
||||
className={
|
||||
"m-2.5 flex flex-row items-center rounded-md border border-[#FFBB96] p-4"
|
||||
}
|
||||
style={{
|
||||
background: "linear-gradient(100deg, #FFF2E8 25%, #FFE7D9 75%)",
|
||||
}}
|
||||
>
|
||||
<View className={"flex-1 text-center"}>个人利润</View>
|
||||
{personalProfit > 0 ? (
|
||||
<View className={"text-primary flex-1 text-left text-2xl font-bold"}>
|
||||
¥ {personalProfit || "-"}
|
||||
</View>
|
||||
) : (
|
||||
<View className={"flex-1 text-left text-2xl font-bold text-red-500"}>
|
||||
¥ {personalProfit || "-"}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
{/* 按钮操作 */}
|
||||
@ -460,25 +474,15 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
<View className="flex justify-between gap-2 border-t border-gray-200 p-2.5">
|
||||
{purchaseOrderVO.state === "WAITING_AUDIT" && (
|
||||
<>
|
||||
<View className={"flex-1"}>
|
||||
<PurchaseOrderRejectApprove
|
||||
purchaseOrderVO={purchaseOrderVO}
|
||||
size={"xlarge"}
|
||||
onFinish={() => {
|
||||
// 返回首页
|
||||
Taro.redirectTo({ url: "/pages/purchase/reviewer/list" });
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
<View className={"flex-1"}>
|
||||
<Button
|
||||
block
|
||||
type={"default"}
|
||||
size={"xlarge"}
|
||||
className="bg-gray-200 text-gray-700"
|
||||
onClick={handleSave}
|
||||
onClick={() => setMoreActionVisible(true)}
|
||||
>
|
||||
暂存
|
||||
更多操作
|
||||
</Button>
|
||||
</View>
|
||||
<View className={"flex-1"}>
|
||||
@ -489,7 +493,7 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
className="bg-primary text-white"
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
提交老板审核
|
||||
提交老板审批
|
||||
</Button>
|
||||
</View>
|
||||
</>
|
||||
@ -531,6 +535,86 @@ export default hocAuth(function Page(props: CommonComponent) {
|
||||
onCancel={() => setSubmitDialogVisible(false)}
|
||||
onConfirm={confirmSubmit}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 更多操作ActionSheet */}
|
||||
<ActionSheet
|
||||
title="更多操作"
|
||||
visible={moreActionVisible}
|
||||
options={[
|
||||
{
|
||||
name: "暂存",
|
||||
},
|
||||
{
|
||||
name: "驳回",
|
||||
description: "此采购单将退回到产地录入员",
|
||||
danger: true,
|
||||
},
|
||||
]}
|
||||
onCancel={() => setMoreActionVisible(false)}
|
||||
onSelect={(item) => {
|
||||
setMoreActionVisible(false);
|
||||
if (item.name === "暂存") {
|
||||
// 暂存操作
|
||||
handleSave();
|
||||
} else if (item.name === "驳回") {
|
||||
// 驳回操作
|
||||
handleReject();
|
||||
}
|
||||
}}
|
||||
cancelText="取消"
|
||||
/>
|
||||
|
||||
{/* 驳回原因弹窗 */}
|
||||
<Popup
|
||||
visible={rejectVisible}
|
||||
position="bottom"
|
||||
onClose={() => {
|
||||
setRejectVisible(false);
|
||||
setRejectReason("");
|
||||
}}
|
||||
closeable
|
||||
destroyOnClose
|
||||
title={"驳回"}
|
||||
description={"此采购单将退回到产地录入员"}
|
||||
>
|
||||
<View className="p-4">
|
||||
<View className="mb-4 text-lg font-bold">请输入驳回原因</View>
|
||||
<TextArea
|
||||
value={rejectReason}
|
||||
onChange={(value) => setRejectReason(value)}
|
||||
placeholder="请输入驳回原因"
|
||||
rows={4}
|
||||
maxLength={200}
|
||||
showCount
|
||||
/>
|
||||
<View className="mt-4 flex justify-between gap-2">
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size={"large"}
|
||||
block
|
||||
type="default"
|
||||
onClick={() => {
|
||||
setRejectVisible(false);
|
||||
setRejectReason("");
|
||||
}}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</View>
|
||||
<View className="flex-1">
|
||||
<Button
|
||||
size={"large"}
|
||||
block
|
||||
type="primary"
|
||||
onClick={confirmReject}
|
||||
>
|
||||
确认
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<SafeArea position="bottom" />
|
||||
</Popup>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
@ -2392,6 +2392,8 @@ declare namespace BusinessAPI {
|
||||
| "FIXED_COST"
|
||||
| "WORKER_ADVANCE"
|
||||
| "PRODUCTION_ADVANCE";
|
||||
/** 是否需要填写数量和单价 */
|
||||
requireQuantityAndPrice: boolean;
|
||||
};
|
||||
|
||||
type OrderDealer = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user