feat(purchase): 优化采购模块人工费用和车辆信息处理逻辑

- 调整API域名配置,区分h5和小程序环境
- 重构OrderCost组件,支持多种费用类型筛选和展示
- 优化OrderVehicle组件,简化经销商信息赋值逻辑
- Weigh组件新增西瓜品种选择功能,包含弹窗和校验逻辑
- 重写LaborInfoSection组件,支持新增和编辑人工费用项
- 改进费用承担方和工头信息的处理流程
- 优化UI布局和交互体验
This commit is contained in:
shenyifei 2025-11-16 19:14:15 +08:00
parent a62ca1fb95
commit 3f8c6d962a
32 changed files with 4867 additions and 669 deletions

View File

@ -10,7 +10,10 @@ export default {
}, },
defineConstants: { defineConstants: {
"process.env.TARO_APP_ID": '"wxa080848726642f73"', "process.env.TARO_APP_ID": '"wxa080848726642f73"',
"process.env.TARO_API_DOMAIN": '"/api"', "process.env.TARO_API_DOMAIN":
process.env.TARO_ENV === "h5"
? '"/api"'
: '"https://api.erp.qilincloud168.com"',
}, },
mini: { mini: {
miniCssExtractPluginOption: { miniCssExtractPluginOption: {

View File

@ -18,7 +18,10 @@ export default {
}, },
defineConstants: { defineConstants: {
"process.env.TARO_APP_ID": '"wxa080848726642f73"', "process.env.TARO_APP_ID": '"wxa080848726642f73"',
"process.env.TARO_API_DOMAIN": '"https://api.erp.qilincloud168.com"', "process.env.TARO_API_DOMAIN":
process.env.TARO_ENV === "h5"
? '"/api"'
: '"https://api.erp.qilincloud168.com"',
}, },
mini: { mini: {
miniCssExtractPluginOption: { miniCssExtractPluginOption: {

View File

@ -18,4 +18,12 @@ export default [
projectName: "business", projectName: "business",
namespace: "BusinessAPI", namespace: "BusinessAPI",
}, },
{
requestLibPath: "import request from '../poster-request';",
// schemaPath: 'http://localhost:8080/mdb-business/v3/api-docs',
schemaPath: path.resolve(__dirname, "../../swagger/poster.json"),
serversPath: "./src/services",
projectName: "poster",
namespace: "PosterAPI",
},
]; ];

View File

@ -40,7 +40,7 @@ config = {
// 发货单 // 发货单
{ {
root: "pages/delivery", root: "pages/delivery",
pages: ["list", "document"], pages: ["list", "document/delivery", "document/purchase"],
}, },
], ],
permission: { permission: {
@ -49,7 +49,7 @@ config = {
}, },
}, },
tabBar: { tabBar: {
custom: false, custom: process.env.TARO_ENV === "weapp",
color: "#000000", color: "#000000",
selectedColor: "#DC143C", selectedColor: "#DC143C",
backgroundColor: "#ffffff", backgroundColor: "#ffffff",

View File

@ -36,38 +36,75 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
showInEntry: true, showInEntry: true,
}, },
}); });
const initialList = const costItemList = data.data;
data.data?.map((item) => {
// 查找是否在purchaseOrder中已有该item的记录
const existingItem = value?.find(
(costItem) => costItem.itemId === item.itemId,
);
return { if (costItemList) {
orderCostId: generateShortId(), // 人工辅料选中
itemId: item.itemId, const initialList =
name: item.name, costItemList
price: item.price, ?.filter(
unit: item.unit, (item) =>
selected: existingItem ? existingItem.selected : false, item.costType === "HUMAN_COST" ||
count: existingItem ? existingItem.count : 1, item.costType === "PACKAGING_MATERIALS",
payerType: existingItem ? existingItem.payerType : undefined, )
principal: existingItem ? existingItem.principal : "", .map((item) => {
costType: item.costType, // 查找是否在purchaseOrder中已有该item的记录
}; const existingItem = value?.find(
}) || []; (costItem) => costItem.itemId === item.itemId,
);
setCostItemVOList(initialList as CostItem[]); console.log("existingItem", existingItem, value)
// 初始化总的工头姓名(如果有启用且费用承担方为"我方"的项目) return {
const enabledUsItems = initialList.filter( orderCostId: existingItem
(item) => ? existingItem.orderCostId
item.selected && : generateShortId(),
item.payerType === "US" && itemId: item.itemId,
item.costType === "HUMAN_COST", name: item.name,
); price: item.price,
if (enabledUsItems.length > 0 && enabledUsItems[0].principal) { unit: item.unit,
setPrincipal(enabledUsItems[0].principal || ""); selected: existingItem ? existingItem.selected : false,
count: existingItem ? existingItem.count : 1,
payerType: existingItem ? existingItem.payerType : undefined,
principal: existingItem ? existingItem.principal : "",
costType: item.costType,
};
}) || [];
setCostItemVOList([
...(initialList || []),
...(value
?.filter(
(item) =>
item.costType === "WORKER_ADVANCE" ||
item.costType === "PRODUCTION_ADVANCE",
)
.map((item) => {
return {
orderCostId: item.orderCostId,
itemId: item.itemId,
name: item.name,
price: item.price,
unit: item.unit,
selected: item.selected,
count: item.count,
payerType: item.payerType,
principal: item.principal,
costType: item.costType,
};
}) || []),
]);
// 初始化总的工头姓名(如果有启用且费用承担方为"我方"的项目)
const enabledUsItems = initialList.filter(
(item) =>
item.selected &&
item.payerType === "US" &&
item.costType === "HUMAN_COST",
);
if (enabledUsItems.length > 0 && enabledUsItems[0].principal) {
setPrincipal(enabledUsItems[0].principal || "");
}
} }
}; };
@ -253,7 +290,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
// 渲染项目列表 // 渲染项目列表
const renderItemList = (items: CostItem[], type: string) => { const renderItemList = (items: CostItem[], type: string) => {
return items.map((item) => ( return items.map((item) => (
<View className="mb-2.5" key={item.orderCostId}> <View key={item.orderCostId}>
<View className={"flex flex-col gap-2.5 rounded-lg bg-white p-2.5"}> <View className={"flex flex-col gap-2.5 rounded-lg bg-white p-2.5"}>
<View className={"flex flex-row justify-between"}> <View className={"flex flex-row justify-between"}>
<View className="block text-sm font-normal text-[#000000]"> <View className="block text-sm font-normal text-[#000000]">
@ -384,10 +421,10 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
}; };
return ( return (
<View className="flex flex-1 flex-col bg-[#D1D5DB] px-2.5 pt-2.5"> <View className="flex flex-1 flex-col bg-[#D1D5DB] p-2.5 pt-2.5 gap-2.5">
<View className={"mb-2.5"}> <View className={"flex flex-1 flex-col gap-2.5"}>
<View className="mb-2.5 text-sm font-bold"></View> <View className="text-sm font-bold"></View>
<View className="mb-2.5 flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5"> <View className="flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5">
<Icon <Icon
className={"mr-1"} className={"mr-1"}
name="circle-info" name="circle-info"
@ -400,7 +437,7 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
{/* 总的工头姓名输入框 */} {/* 总的工头姓名输入框 */}
{shouldShowPrincipalInput() && ( {shouldShowPrincipalInput() && (
<View className="mt-2.5"> <View>
<View className="mb-1 text-sm font-medium"></View> <View className="mb-1 text-sm font-medium"></View>
<View <View
className={`flex h-12 items-center rounded-md px-3 ${principalError ? "border-2 border-red-500 bg-red-100" : "border-2 border-gray-300 bg-white"}`} className={`flex h-12 items-center rounded-md px-3 ${principalError ? "border-2 border-red-500 bg-red-100" : "border-2 border-gray-300 bg-white"}`}
@ -424,9 +461,9 @@ export default forwardRef<OrderCostRef, IOrderCostProps>(
</View> </View>
)} )}
</View> </View>
<View className={"mb-2.5"}> <View className={"flex flex-1 flex-col gap-2.5"}>
<View className="mb-2.5 text-sm font-bold"></View> <View className="text-sm font-bold"></View>
<View className="mb-2.5 flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5"> <View className="flex items-center rounded-lg border border-blue-200 bg-blue-50 p-2.5">
<Icon <Icon
className={"mr-1"} className={"mr-1"}
name="circle-info" name="circle-info"

View File

@ -77,15 +77,7 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
setOrderDealer({ setOrderDealer({
...orderDealer, ...orderDealer,
dealerId: dealerVO.dealerId, ...dealerVO,
shortName: dealerVO?.shortName!,
dealerType: dealerVO.dealerType!,
enableShare: dealerVO.enableShare,
shareRatio: dealerVO.shareRatio,
freightCostFlag: dealerVO.freightCostFlag,
strawMatCostFlag: dealerVO.strawMatCostFlag,
includePackingFlag: dealerVO.includePackingFlag,
documentTypes: dealerVO.documentTypes,
}); });
// 校验经销商信息 // 校验经销商信息
@ -485,7 +477,7 @@ export default forwardRef<OrderVehicleRef, IOrderVehicleProps>(
const { data } = await business.extraction.vehicleExtraction({ const { data } = await business.extraction.vehicleExtraction({
message: message, message: message,
dealerNames: '', dealerNames: "",
}); });
const newVehicle = data.data as BusinessAPI.VehicleExtractionVO; const newVehicle = data.data as BusinessAPI.VehicleExtractionVO;

View File

@ -5,12 +5,14 @@ import {
Toast, Toast,
Uploader, Uploader,
UploaderFileItem, UploaderFileItem,
Popup,
} from "@nutui/nutui-react-taro"; } from "@nutui/nutui-react-taro";
import { Icon } from "@/components"; import { Icon } from "@/components";
import { SupplierVO } from "@/types/typings"; import { SupplierVO } from "@/types/typings";
import { forwardRef, useEffect, useImperativeHandle, useState } from "react"; import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
import { uploadFile } from "@/utils/uploader"; import { uploadFile } from "@/utils/uploader";
import { validatePrice } from "@/utils/format"; import { validatePrice } from "@/utils/format";
import { business } from "@/services";
// 定义ref暴露的方法接口 // 定义ref暴露的方法接口
export interface WeighRef { export interface WeighRef {
@ -22,13 +24,30 @@ interface IWeightProps {
onChange: (supplierVO: SupplierVO) => void; onChange: (supplierVO: SupplierVO) => void;
isFirst?: boolean; isFirst?: boolean;
changePaper: (isPaper: boolean) => void; changePaper: (isPaper: boolean) => void;
changeProduct: (productVO: BusinessAPI.ProductVO) => void;
} }
export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) { export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
const { value, onChange, isFirst, changePaper } = props; const { value, onChange, isFirst, changePaper, changeProduct } = props;
const [supplierVO, setSupplierVO] = useState<SupplierVO>(); const [supplierVO, setSupplierVO] = useState<SupplierVO>();
useEffect(() => {
// 获取产品列表
business.product
.listProduct({
productListQry: {
status: true,
},
})
.then(({ data }) => {
if (data.success) {
const products = data.data || [];
setProductList(products);
}
});
}, []);
// 初始化数据 // 初始化数据
useEffect(() => { useEffect(() => {
setSupplierVO(value); setSupplierVO(value);
@ -69,10 +88,19 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
UploaderFileItem[] UploaderFileItem[]
>([]); >([]);
const [isProductIdError, setProductIdError] = useState<{
[key: string]: boolean;
}>({}); // 添加瓜农是否选择西瓜品牌的错误状态
const [isPaperError, setIsPaperError] = useState<{ const [isPaperError, setIsPaperError] = useState<{
[key: string]: boolean; [key: string]: boolean;
}>({}); // 添加是否为最后一个瓜农的错误状态 }>({}); // 添加是否为最后一个瓜农的错误状态
const [productPopupVisible, setProductPopupVisible] = useState(false);
const [selectedProduct, setSelectedProduct] = useState("");
const [customProduct, setCustomProduct] = useState("");
const [productList, setProductList] = useState<BusinessAPI.ProductVO[]>([]);
// 添加三个字段的错误状态 // 添加三个字段的错误状态
const [emptyWeightError, setEmptyWeightError] = useState<{ const [emptyWeightError, setEmptyWeightError] = useState<{
[key: string]: boolean; [key: string]: boolean;
@ -136,6 +164,23 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
return isPaper !== undefined && isPaper !== null; return isPaper !== undefined && isPaper !== null;
}; };
// 校验西瓜品种
const validateProductId = (productId: any) => {
if (productId === "" || productId === undefined || productId === null) {
setProductIdError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: true,
}));
return false;
}
setProductIdError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
return true;
};
// 校验空磅重量 // 校验空磅重量
const validateEmptyWeight = (value: any) => { const validateEmptyWeight = (value: any) => {
if (value === "" || value === undefined || value === null) { if (value === "" || value === undefined || value === null) {
@ -225,6 +270,7 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
supplierVO.purchasePrice, supplierVO.purchasePrice,
); );
const isPaperValid = validateIsPaper(supplierVO.isPaper); const isPaperValid = validateIsPaper(supplierVO.isPaper);
const isProductIdValid = validateProductId(supplierVO.productId);
// 更新错误状态 // 更新错误状态
setIsPaperError((prev) => ({ setIsPaperError((prev) => ({
@ -232,6 +278,12 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
[id]: !isPaperValid, [id]: !isPaperValid,
})); }));
// 更新错误状态
setProductIdError((prev) => ({
...prev,
[id]: !isProductIdValid,
}));
setPriceError((prev) => ({ setPriceError((prev) => ({
...prev, ...prev,
[id]: !isPurchasePriceValid, [id]: !isPurchasePriceValid,
@ -251,6 +303,7 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
isEmptyWeightValid && isEmptyWeightValid &&
isTotalWeightValid && isTotalWeightValid &&
isPurchasePriceValid && isPurchasePriceValid &&
isProductIdValid &&
isPaperValid; isPaperValid;
if (!isValid) { if (!isValid) {
@ -266,53 +319,222 @@ export default forwardRef<WeighRef, IWeightProps>(function Weigh(props, ref) {
return ( return (
<View className="flex flex-1 flex-col gap-2.5 p-2.5"> <View className="flex flex-1 flex-col gap-2.5 p-2.5">
{isFirst && ( {/* 西瓜品种选择弹窗 */}
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm"> <Popup
<View className={"flex items-center justify-between gap-2.5"}> visible={productPopupVisible}
<View className="text-sm"></View> position="bottom"
<View className="text-neutral-darkest text-sm font-medium"> title="请选择具体品种"
<Radio.Group onClose={() => setProductPopupVisible(false)}
direction="horizontal" round
value={ closeable
supplierVO.isPaper === true >
? "true" <View className="p-4">
: supplierVO.isPaper === false <View id="sub-options" className="slide-in mt-3">
? "false" <View className="mb-3 text-sm font-medium text-gray-500">
: undefined
} </View>
onChange={(value) => { <View className="grid grid-cols-2 gap-2">
// 清除错误状态 {productList.map((product) => (
setIsPaperError((prev) => ({ <View
...prev, className={`cursor-pointer rounded-lg border p-3 text-center hover:bg-gray-50 ${selectedProduct === product.name ? "border-primary border-2" : "border-gray-200"}`}
[supplierVO.orderSupplierId]: false, key={product.productId}
})); onClick={() => setSelectedProduct(product.name)}
>
// 根据用户选择设置是否包含空纸箱 <View
const isPaperValue = className={
value === "true" selectedProduct === product.name
? true ? "text-primary font-medium"
: value === "false" : ""
? false }
: undefined; >
setSupplierVO({ {product.name}
...supplierVO, </View>
isPaper: isPaperValue, </View>
}); ))}
</View>
changePaper(isPaperValue!); {selectedProduct === "其他(请注明)" && (
<View className="mt-4">
<View
className={`flex h-10 w-full items-center rounded-md ${selectedProduct === "其他(请注明)" && customProduct ? "border-primary border-4" : "border-4 border-gray-300"}`}
>
<Input
placeholder="请输入品种"
type="text"
value={customProduct}
onChange={(value) => {
setCustomProduct(value);
}}
/>
</View>
</View>
)}
<View className="mt-6 flex gap-3">
<View
className="border-primary text-primary flex-1 cursor-pointer rounded-md border py-3 text-center"
onClick={() => {
setProductPopupVisible(false);
setSelectedProduct("");
setCustomProduct("");
}} }}
> >
<Radio value="true"></Radio>
<Radio value="false"></Radio> </View>
</Radio.Group> <View
className="bg-primary flex-1 cursor-pointer rounded-md py-3 text-center text-white"
onClick={() => {
let finalProduct = "";
if (selectedProduct === "其他(请注明)") {
finalProduct = customProduct;
} else if (selectedProduct) {
// 从产品列表中找到选中产品的ID
const selectedProductObj = productList.find(
(p) => p.name === selectedProduct,
);
if (selectedProductObj) {
finalProduct = selectedProductObj.productId;
}
}
if (finalProduct) {
// 找到选中的产品对象
const productObj = productList.find(
(p) => p.name === selectedProduct,
);
if (productObj) {
setSupplierVO({
...supplierVO,
productId: productObj.productId,
productName:
selectedProduct === "其他(请注明)"
? customProduct
: productObj.name,
});
changeProduct({
...productObj,
name:
selectedProduct === "其他(请注明)"
? customProduct
: productObj.name,
});
}
setProductPopupVisible(false);
setSelectedProduct("");
setCustomProduct("");
}
}}
>
</View>
</View> </View>
</View> </View>
{isPaperError[supplierVO.orderSupplierId] && ( </View>
<View className="mt-1 text-xs text-red-500"> </Popup>
{isFirst && (
<>
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">
<View className={"flex items-center justify-between gap-2.5"}>
<View className="text-sm"></View>
<View className="text-neutral-darkest text-sm font-medium">
<Radio.Group
direction="horizontal"
value={
supplierVO.isPaper === true
? "true"
: supplierVO.isPaper === false
? "false"
: undefined
}
onChange={(value) => {
// 清除错误状态
setIsPaperError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
// 根据用户选择设置是否包含空纸箱
const isPaperValue =
value === "true"
? true
: value === "false"
? false
: undefined;
setSupplierVO({
...supplierVO,
isPaper: isPaperValue,
});
changePaper(isPaperValue!);
}}
>
<Radio value="true"></Radio>
<Radio value="false"></Radio>
</Radio.Group>
</View>
</View>
{isPaperError[supplierVO.orderSupplierId] && (
<View className="mt-1 text-xs text-red-500">
</View>
)}
</View>
{productList.length > 0 && (
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">
<View className={"flex items-center justify-between gap-2.5"}>
<View className="text-sm">西</View>
<View className="text-neutral-darkest text-sm font-medium">
<Radio.Group
direction="horizontal"
value={supplierVO.productId}
onChange={(value) => {
// 清除错误状态
setProductIdError((prev) => ({
...prev,
[supplierVO.orderSupplierId]: false,
}));
if (value === "other") {
// 点击"其他"时打开弹窗
setProductPopupVisible(true);
} else {
// 根据用户选择设置西瓜品种
const productId = value as string;
const productVO = productList.find(
(p) => p.productId === productId,
);
if (productVO) {
setSupplierVO({
...supplierVO,
productId: productVO?.productId,
productName: productVO?.name,
});
changeProduct(productVO);
}
}
}}
>
<Radio
value={supplierVO.productId || productList?.[0].productId}
>
{supplierVO.productName || productList?.[0].name}
</Radio>
<Radio value="other"></Radio>
</Radio.Group>
</View>
</View>
{isProductIdError[supplierVO.orderSupplierId] && (
<View className="mt-1 text-xs text-red-500">
西
</View>
)}
</View> </View>
)} )}
</View> </>
)} )}
<View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm"> <View className="border-primary rounded-lg border-4 bg-white p-2.5 shadow-sm">

View File

@ -1,7 +1,16 @@
import { Text, View } from "@tarojs/components"; import { Text, View } from "@tarojs/components";
import { Button, Input, Popup, SafeArea } from "@nutui/nutui-react-taro"; import {
Button,
Input,
Picker,
Popup,
SafeArea,
} from "@nutui/nutui-react-taro";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { validatePrice } from "@/utils/format"; import { validatePrice } from "@/utils/format";
import { generateShortId } from "@/utils/generateShortId";
import { business } from "@/services";
import { Icon } from "@/components";
export default function MaterialCostSection(props: { export default function MaterialCostSection(props: {
purchaseOrderVO: BusinessAPI.PurchaseOrderVO; purchaseOrderVO: BusinessAPI.PurchaseOrderVO;
@ -15,6 +24,28 @@ export default function MaterialCostSection(props: {
{}, {},
); );
// 新增辅料费弹窗状态
const [showAddCostPopup, setShowAddCostPopup] = useState(false);
// 新增辅料费表单数据
const [newCostData, setNewCostData] = useState<any>({
itemId: "", // 费用项目ID
name: "", // 费用名称
quantity: 0, // 数量
unit: "", // 单位
unitPrice: "", // 单价
amount: "", // 金额
requireQuantityAndPrice: false,
});
// Picker可见状态
const [pickerVisible, setPickerVisible] = useState({
costItem: false, // 费用项目Picker
});
// 费用项目列表
const [costItems, setCostItems] = useState<BusinessAPI.CostItemVO[]>([]);
// 编辑值的状态 // 编辑值的状态
const [editValues, setEditValues] = useState<{ const [editValues, setEditValues] = useState<{
[key: string]: { [key: string]: {
@ -81,6 +112,26 @@ export default function MaterialCostSection(props: {
return updates; return updates;
}; };
// 获取费用项目列表
useEffect(() => {
const fetchCostItems = async () => {
try {
const { data } = await business.costItem.listCostItem({
costItemListQry: {
status: true,
showInEntry: true,
costType: "PACKAGING_MATERIALS", // 只获取辅料费用项目
},
});
setCostItems(data.data || []);
} catch (error) {
console.error("获取费用项目列表失败:", error);
}
};
fetchCostItems();
}, []);
// 辅料费(商标费和网套费) // 辅料费(商标费和网套费)
const packagingMaterials = const packagingMaterials =
purchaseOrderVO.orderCostList?.filter( purchaseOrderVO.orderCostList?.filter(
@ -230,7 +281,7 @@ export default function MaterialCostSection(props: {
<Text className="text-sm text-gray-500"></Text> <Text className="text-sm text-gray-500"></Text>
</View> </View>
<View className="relative flex"> <View className="relative flex">
<Text className="text-red-500 border-red-500 w-full border-b-2 pb-2 text-3xl font-bold focus:outline-none"> <Text className="w-full border-b-2 border-red-500 pb-2 text-3xl font-bold text-red-500 focus:outline-none">
{amount.toFixed(2) || "0.00"} {amount.toFixed(2) || "0.00"}
</Text> </Text>
</View> </View>
@ -268,8 +319,292 @@ export default function MaterialCostSection(props: {
</View> </View>
); );
})} })}
{!readOnly && (
<Button
type={"primary"}
block
size={"large"}
onClick={() => setShowAddCostPopup(true)}
>
</Button>
)}
</View> </View>
{/* 新增其他辅料费 */}
<Popup
visible={showAddCostPopup}
position="bottom"
title="新增其他辅料费用"
onClose={() => setShowAddCostPopup(false)}
onOverlayClick={() => setShowAddCostPopup(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 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) => {
// 检查该项目是否已经被选择
return !packagingMaterials.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,
quantity: selectedItem.requireQuantityAndPrice ? 0 : 1, // 数量
unit: selectedItem.requireQuantityAndPrice
? selectedItem.unit
: "元", // 单位
unitPrice: "", // 单价
amount: "", // 金额
requireQuantityAndPrice: selectedItem.requireQuantityAndPrice,
}));
}
setPickerVisible((prev) => ({ ...prev, costItem: false }));
}}
onCancel={() =>
setPickerVisible((prev) => ({ ...prev, costItem: false }))
}
onClose={() =>
setPickerVisible((prev) => ({ ...prev, costItem: false }))
}
/>
{/* 数量输入 */}
{newCostData.itemId && 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">
{(
Number(newCostData.quantity || 0) *
Number(newCostData.unitPrice || 0)
).toFixed(2)}{" "}
</View>
</View>
</>
)}
{newCostData.itemId && !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({
itemId: "",
name: "", // 费用名称
quantity: 0, // 数量
unit: "", // 单位
unitPrice: "", // 单价
amount: "", // 金额
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.requireQuantityAndPrice
? newCostData.unitPrice || 0
: newCostData.amount || 0,
),
unit: newCostData.unit,
count: Number(
newCostData.requireQuantityAndPrice
? newCostData.quantity || 1
: 1,
),
payerType: "US",
costType: "PACKAGING_MATERIALS",
principal: "",
};
// 更新purchaseOrderVO将新费用添加到orderCostList中
if (onChange) {
const updatedOrderCostList = [
...(purchaseOrderVO.orderCostList || []),
newOrderCost,
];
const newPurchaseOrderVO = {
...purchaseOrderVO,
orderCostList: updatedOrderCostList,
};
onChange(newPurchaseOrderVO);
}
setShowAddCostPopup(false);
// 重置表单
setNewCostData({
itemId: "",
name: "", // 费用名称
quantity: 0, // 数量
unit: "", // 单位
unitPrice: "", // 单价
amount: "", // 金额
requireQuantityAndPrice: false,
});
}}
>
</Button>
</View>
</View>
</View>
<SafeArea position="bottom" />
</Popup>
{/* 辅料费编辑弹窗 */} {/* 辅料费编辑弹窗 */}
{packagingMaterials.map((item) => ( {packagingMaterials.map((item) => (
<Popup <Popup

View File

@ -151,7 +151,7 @@ export default function PackagingCostSection(props: {
onChange(newPurchaseOrderVO as any); onChange(newPurchaseOrderVO as any);
} }
} }
}, [purchaseOrderVO.orderCostList]); }, [purchaseOrderVO.orderCostList, onChange, fixedCosts]);
// 当editValues发生变化时更新purchaseOrderVO // 当editValues发生变化时更新purchaseOrderVO
useEffect(() => { useEffect(() => {
@ -204,7 +204,7 @@ export default function PackagingCostSection(props: {
return ( return (
<> <>
<View className="grid grid-cols-1 gap-2.5"> <View className="flex flex-col gap-2.5">
{/* 固定费用 */} {/* 固定费用 */}
{fixedCosts.map((item, index) => { {fixedCosts.map((item, index) => {
// 初始化编辑值 // 初始化编辑值
@ -212,7 +212,7 @@ export default function PackagingCostSection(props: {
return ( return (
<View <View
className="flex items-center justify-between gap-2.5 p-2.5" className="flex items-center justify-between gap-2.5"
key={item.orderCostId} key={item.orderCostId}
onClick={() => onClick={() =>
setVisiblePopup((prev) => ({ setVisiblePopup((prev) => ({
@ -254,7 +254,7 @@ export default function PackagingCostSection(props: {
return ( return (
<View <View
className="flex items-center justify-between gap-2.5 p-2.5" className="flex items-center justify-between gap-2.5"
key={item.orderCostId} key={item.orderCostId}
onClick={() => onClick={() =>
setVisiblePopup((prev) => ({ setVisiblePopup((prev) => ({
@ -283,18 +283,18 @@ export default function PackagingCostSection(props: {
</View> </View>
); );
})} })}
</View>
{!readOnly && ( {!readOnly && (
<Button <Button
type={"primary"} type={"primary"}
block block
size={"large"} size={"large"}
onClick={() => setShowAddCostPopup(true)} onClick={() => setShowAddCostPopup(true)}
> >
</Button> </Button>
)} )}
</View>
{/* 新增其他费用*/} {/* 新增其他费用*/}
<Popup <Popup
@ -311,49 +311,32 @@ export default function PackagingCostSection(props: {
<View className="text-neutral-darkest text-sm font-medium"> <View className="text-neutral-darkest text-sm font-medium">
</View> </View>
<View <View className="flex flex-row gap-4">
className="border-neutral-base relative flex h-10 w-full items-center rounded-md border border-solid" {costTypeOptions.map((option) => (
onClick={() => <View
setPickerVisible((prev) => ({ ...prev, costType: true })) key={option.value}
} className={`flex flex-1 flex-row items-center justify-center rounded-md py-2 ${
> newCostData.costType === option.value
<Input ? "bg-blue-100 text-blue-600"
type="text" : "border border-gray-300"
placeholder="请选择费用类型" }`}
value={ onClick={() => {
costTypeOptions.find( setNewCostData((prev) => ({
(option) => option.value === newCostData.costType, ...prev,
)?.label || "" costType: option.value,
} itemId: "",
disabled name: "",
/> payee: "",
<Icon name="chevron-down" className="absolute -right-1 mr-4" /> quantity: "",
unitPrice: "",
amount: "",
}));
}}
>
{option.label}
</View>
))}
</View> </View>
<Picker
title="请选择费用类型"
visible={pickerVisible.costType}
options={[costTypeOptions]}
onConfirm={(_, values) => {
const selectedValue = values[0] as string;
setNewCostData((prev) => ({
...prev,
costType: selectedValue,
itemId: "",
name: "",
payee: "",
quantity: "",
unitPrice: "",
amount: "",
}));
setPickerVisible((prev) => ({ ...prev, costType: false }));
}}
onCancel={() =>
setPickerVisible((prev) => ({ ...prev, costType: false }))
}
onClose={() =>
setPickerVisible((prev) => ({ ...prev, costType: false }))
}
/>
{/* 固定费用子类型 */} {/* 固定费用子类型 */}
{newCostData.costType === "FIXED_COST" && ( {newCostData.costType === "FIXED_COST" && (
@ -381,7 +364,14 @@ export default function PackagingCostSection(props: {
<Picker <Picker
title="请选择固定费用类型" title="请选择固定费用类型"
visible={pickerVisible.fixedCost} visible={pickerVisible.fixedCost}
options={[fixedCostOptions]} options={[
fixedCostOptions.filter((option) => {
// 检查该固定费用类型是否已存在于fixedCosts中
return !fixedCosts.some(
(cost) => cost.name === option.label,
);
}),
]}
onConfirm={(_, values) => { onConfirm={(_, values) => {
const selectedValue = values[0] as string; const selectedValue = values[0] as string;
const selectedItem = fixedCostOptions.find( const selectedItem = fixedCostOptions.find(
@ -479,7 +469,21 @@ export default function PackagingCostSection(props: {
size="large" size="large"
block block
type="default" type="default"
onClick={() => setShowAddCostPopup(false)} onClick={() => {
setShowAddCostPopup(false);
// 重置表单
setNewCostData({
payerType: "",
principal: "",
costType: "",
itemId: generateShortId(),
name: "",
payee: "",
quantity: "",
unitPrice: "",
amount: "",
});
}}
> >
</Button> </Button>

View File

@ -2265,7 +2265,6 @@ export default hocAuth(function Page(props: CommonComponent) {
type="default" type="default"
size="large" size="large"
block block
className="max-w-[150px] flex-1"
onClick={handleDownload} onClick={handleDownload}
> >
@ -2279,7 +2278,6 @@ export default hocAuth(function Page(props: CommonComponent) {
type="default" type="default"
size="large" size="large"
block block
className="max-w-[150px] flex-1"
onClick={handleView} onClick={handleView}
> >
@ -2290,7 +2288,6 @@ export default hocAuth(function Page(props: CommonComponent) {
type="primary" type="primary"
size="large" size="large"
block block
className="max-w-[150px] flex-1"
onClick={handleShare} onClick={handleShare}
> >

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,12 @@ export default hocAuth(function Page(props: CommonComponent) {
const [state, setState] = useState<BusinessAPI.ShipOrderPageQry["state"]>(); const [state, setState] = useState<BusinessAPI.ShipOrderPageQry["state"]>();
const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>(); const [dealerVO, setDealerVO] = useState<BusinessAPI.DealerVO>();
const [deliveryTemplate, setDeliveryTemplate] = useState<BusinessAPI.DealerVO['deliveryTemplate']>(); const [canGenerateDocuments, setCanGenerateDocuments] = useState({
shipDocument: false,
purchaseDocument: false,
});
const [deliveryTemplate, setDeliveryTemplate] =
useState<BusinessAPI.DealerVO["deliveryTemplate"]>();
// 控制弹窗显示状态 // 控制弹窗显示状态
const [popupVisible, setPopupVisible] = useState(false); const [popupVisible, setPopupVisible] = useState(false);
@ -31,6 +36,66 @@ export default hocAuth(function Page(props: CommonComponent) {
const [currentShipOrder, setCurrentShipOrder] = const [currentShipOrder, setCurrentShipOrder] =
useState<BusinessAPI.ShipOrderVO | null>(null); useState<BusinessAPI.ShipOrderVO | null>(null);
// 生成发货单据
const generateShipDocument = async () => {
if (!currentShipOrder?.shipOrderId) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "未找到关联的发货单",
});
return;
}
try {
// 跳转到发货单据生成页面
Taro.navigateTo({
url: buildUrl("/pages/delivery/document/delivery", {
shipOrderId: currentShipOrder.shipOrderId,
}),
success: () => {
setPopupVisible(false);
},
});
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "跳转发货单据页面失败",
});
}
};
// 生成采购底单单据
const generatePurchaseDocument = () => {
if (!currentShipOrder?.shipOrderId) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "未找到关联的发货单",
});
return;
}
try {
// 跳转到发货单据生成页面
Taro.navigateTo({
url: buildUrl("/pages/delivery/document/purchase", {
shipOrderId: currentShipOrder.shipOrderId,
}),
success: () => {
setPopupVisible(false);
},
});
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "跳转发货单据页面失败",
});
}
};
const actionRef = useRef<ActionType>(); const actionRef = useRef<ActionType>();
const toolbar: ToolBar = { const toolbar: ToolBar = {
search: { search: {
@ -60,7 +125,7 @@ export default hocAuth(function Page(props: CommonComponent) {
}, },
render: () => ( render: () => (
<> <>
{/* 生成发货单据弹窗 */} {/* 生成单据弹窗 */}
<Popup <Popup
duration={150} duration={150}
style={{ style={{
@ -69,7 +134,7 @@ export default hocAuth(function Page(props: CommonComponent) {
visible={popupVisible} visible={popupVisible}
className={"flex flex-col"} className={"flex flex-col"}
position="bottom" position="bottom"
title={"生成发货单据"} title={"生成单据"}
onClose={() => setPopupVisible(false)} onClose={() => setPopupVisible(false)}
onOverlayClick={() => setPopupVisible(false)} onOverlayClick={() => setPopupVisible(false)}
lockScroll lockScroll
@ -104,19 +169,44 @@ export default hocAuth(function Page(props: CommonComponent) {
</View> </View>
)} )}
{deliveryTemplate ? ( {currentShipOrder && (
<View className="border-t border-gray-200 pt-2.5"> <View className="border-t border-gray-200 pt-2.5">
<View className="mb-2"> <View className="mb-2">
<Text className="text-lg font-semibold"></Text> <Text className="text-lg font-semibold"></Text>
</View> </View>
<View className="text-sm text-gray-600">
<View className="flex flex-col gap-3">
</View> {canGenerateDocuments.shipDocument && (
</View> <>
) : ( {!deliveryTemplate ? (
<View className="flex flex-col gap-3"> <View className="border-t border-gray-200 pt-2.5">
<View className="mt-2.5 text-center text-sm text-red-500"> <View className="flex flex-col gap-3">
<View className="mt-2.5 text-center text-sm text-red-500">
</View>
</View>
</View>
) : (
<View className="border-t border-gray-200 pt-2.5">
<View className="flex flex-col gap-3">
<View className="text-primary mt-2.5 text-center text-sm">
</View>
</View>
</View>
)}
</>
)}
{!canGenerateDocuments.purchaseDocument &&
!canGenerateDocuments.shipDocument && (
<View className="border-t border-gray-200 pt-2.5">
<View className="flex flex-col gap-3">
<View className="mt-2.5 text-center text-sm text-red-500">
</View>
</View>
</View>
)}
</View> </View>
</View> </View>
)} )}
@ -124,27 +214,44 @@ export default hocAuth(function Page(props: CommonComponent) {
<View className={"flex w-full flex-col bg-white"}> <View className={"flex w-full flex-col bg-white"}>
<View className={"flex flex-row gap-2 p-3"}> <View className={"flex flex-row gap-2 p-3"}>
<View className={"flex-1"}> {canGenerateDocuments.purchaseDocument && currentShipOrder && (
<Button <View className={"flex-1"}>
size={"large"} <Button
block type="default"
type="default" size={"xlarge"}
onClick={() => setPopupVisible(false)} block
> onClick={generatePurchaseDocument}
>
</Button>
</View> </Button>
<View className={"flex-1"}> </View>
<Button )}
size={"large"} {canGenerateDocuments.shipDocument && currentShipOrder && (
block <View className={"flex-1"}>
disabled={!deliveryTemplate} <Button
type="primary" type="primary"
onClick={confirmGenerateDocument} size={"xlarge"}
> disabled={!deliveryTemplate}
block
</Button> onClick={generateShipDocument}
</View> >
</Button>
</View>
)}
{!canGenerateDocuments.purchaseDocument &&
!canGenerateDocuments.shipDocument && (
<View className={"flex-1"}>
<Button
type="default"
size={"xlarge"}
block
onClick={() => setPopupVisible(false)}
>
</Button>
</View>
)}
</View> </View>
<SafeArea position={"bottom"} /> <SafeArea position={"bottom"} />
</View> </View>
@ -194,7 +301,7 @@ export default hocAuth(function Page(props: CommonComponent) {
}); });
// 生成发货单据 // 生成发货单据
const generateShipDocument = async (shipOrderVO: BusinessAPI.ShipOrderVO) => { const generateDocument = async (shipOrderVO: BusinessAPI.ShipOrderVO) => {
setCurrentShipOrder(shipOrderVO); setCurrentShipOrder(shipOrderVO);
const { data: dealerData } = await business.dealer.showDealer({ const { data: dealerData } = await business.dealer.showDealer({
@ -205,40 +312,24 @@ export default hocAuth(function Page(props: CommonComponent) {
if (dealerData.success) { if (dealerData.success) {
const deliveryTemplate = dealerData.data?.deliveryTemplate; const deliveryTemplate = dealerData.data?.deliveryTemplate;
setDeliveryTemplate(deliveryTemplate) setDeliveryTemplate(deliveryTemplate);
const documentTypes = dealerData.data?.documentTypes;
if (documentTypes) {
setCanGenerateDocuments({
shipDocument: documentTypes.includes("delivery"),
purchaseDocument: documentTypes.includes("purchase"),
});
} else {
setCanGenerateDocuments({
shipDocument: false,
purchaseDocument: false,
});
}
} }
setPopupVisible(true); setPopupVisible(true);
}; };
// 确认生成发货单据
const confirmGenerateDocument = () => {
if (!currentShipOrder?.shipOrderId) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "未找到关联的发货单",
});
return;
}
try {
// 跳转到发货单据生成页面
Taro.navigateTo({
url: buildUrl("/pages/delivery/document", {
shipOrderId: currentShipOrder.shipOrderId,
}),
});
setPopupVisible(false);
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "跳转发货单据页面失败",
});
}
};
return ( return (
<PageList<BusinessAPI.ShipOrderVO, BusinessAPI.ShipOrderPageQry> <PageList<BusinessAPI.ShipOrderVO, BusinessAPI.ShipOrderPageQry>
rowId={"shipOrderId"} rowId={"shipOrderId"}
@ -323,11 +414,11 @@ export default hocAuth(function Page(props: CommonComponent) {
type={"primary"} type={"primary"}
size={"small"} size={"small"}
onClick={async (e) => { onClick={async (e) => {
await generateShipDocument(shipOrderVO); await generateDocument(shipOrderVO);
e.stopPropagation(); e.stopPropagation();
}} }}
> >
</Button> </Button>
</View> </View>
</View> </View>

View File

@ -1,16 +1,9 @@
import hocAuth from "@/hocs/auth"; import hocAuth from "@/hocs/auth";
import { CommonComponent } from "@/types/typings"; import { CommonComponent } from "@/types/typings";
import { View, Text } from "@tarojs/components"; import { Text, View } from "@tarojs/components";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { auth } from "@/services"; import { auth } from "@/services";
import { import { Button, Dialog, Image, Popup, Toast } from "@nutui/nutui-react-taro";
Button,
Dialog,
Image,
Popup,
SafeArea,
Toast,
} from "@nutui/nutui-react-taro";
import dayjs from "dayjs"; import dayjs from "dayjs";
import Taro from "@tarojs/taro"; import Taro from "@tarojs/taro";
import buildUrl from "@/utils/buildUrl"; import buildUrl from "@/utils/buildUrl";
@ -382,8 +375,6 @@ export default hocAuth(function Page(props: CommonComponent) {
</Button> </Button>
</View> </View>
<SafeArea position={"bottom"} />
</Popup> </Popup>
</> </>
); );

View File

@ -15,10 +15,11 @@ export default hocAuth(function Page(props: CommonComponent) {
useState<BusinessAPI.PurchaseOrderVO>(); useState<BusinessAPI.PurchaseOrderVO>();
const [canGenerateDocuments, setCanGenerateDocuments] = useState({ const [canGenerateDocuments, setCanGenerateDocuments] = useState({
shipDocument: false, shipDocument: false,
costDocument: false, purchaseDocument: false,
}); });
const [shipOrder, setShipOrder] = useState<BusinessAPI.ShipOrderVO>(); const [shipOrder, setShipOrder] = useState<BusinessAPI.ShipOrderVO>();
const [deliveryTemplate, setDeliveryTemplate] = useState<BusinessAPI.DealerVO['deliveryTemplate']>(); const [deliveryTemplate, setDeliveryTemplate] =
useState<BusinessAPI.DealerVO["deliveryTemplate"]>();
const init = async (orderId: string) => { const init = async (orderId: string) => {
setLoading(true); setLoading(true);
@ -59,7 +60,7 @@ export default hocAuth(function Page(props: CommonComponent) {
setDeliveryTemplate(dealerData.data.deliveryTemplate); setDeliveryTemplate(dealerData.data.deliveryTemplate);
setCanGenerateDocuments({ setCanGenerateDocuments({
shipDocument: documentTypes.includes("delivery"), shipDocument: documentTypes.includes("delivery"),
costDocument: documentTypes.includes("cost"), purchaseDocument: documentTypes.includes("purchase"),
}); });
} }
} }
@ -104,7 +105,7 @@ export default hocAuth(function Page(props: CommonComponent) {
try { try {
// 跳转到发货单据生成页面 // 跳转到发货单据生成页面
Taro.navigateTo({ Taro.navigateTo({
url: buildUrl("/pages/delivery/document", { url: buildUrl("/pages/delivery/document/delivery", {
shipOrderId: shipOrder.shipOrderId, shipOrderId: shipOrder.shipOrderId,
}), }),
}); });
@ -117,22 +118,40 @@ export default hocAuth(function Page(props: CommonComponent) {
} }
}; };
// 生成成本单 // 生成采购底单单据
const generateCostDocument = () => { const generatePurchaseDocument = () => {
if (!canGenerateDocuments.costDocument) { if (!canGenerateDocuments.purchaseDocument) {
Toast.show("toast", { Toast.show("toast", {
icon: "fail", icon: "fail",
title: "提示", title: "提示",
content: "当前经销商不支持生成成本单", content: "当前经销商不支持生成采购底单单据",
}); });
return; return;
} }
Toast.show("toast", { if (!shipOrder?.shipOrderId) {
icon: "success", Toast.show("toast", {
title: "提示", icon: "fail",
content: "成本单生成成功", title: "提示",
}); content: "未找到关联的发货单",
});
return;
}
try {
// 跳转到发货单据生成页面
Taro.navigateTo({
url: buildUrl("/pages/delivery/document/purchase", {
shipOrderId: shipOrder.shipOrderId,
}),
});
} catch (error) {
Toast.show("toast", {
icon: "fail",
title: "提示",
content: "跳转发货单据页面失败",
});
}
}; };
return ( return (
@ -189,53 +208,40 @@ export default hocAuth(function Page(props: CommonComponent) {
</View> </View>
</View> </View>
{deliveryTemplate ? ( {shipOrder && (
<View className="border-t border-gray-200 pt-2.5"> <View className="border-t border-gray-200 pt-2.5">
<View className="mb-2"> <View className="mb-2">
<Text className="text-lg font-semibold"></Text> <Text className="text-lg font-semibold"></Text>
</View> </View>
<View className="flex flex-col gap-3"> <View className="flex flex-col gap-3">
{canGenerateDocuments.shipDocument && shipOrder && ( {canGenerateDocuments.shipDocument &&
<Button (deliveryTemplate ? (
type="primary" <Button
size={"xlarge"} type="primary"
block size={"xlarge"}
onClick={generateShipDocument} block
> onClick={generateShipDocument}
>
</Button>
)} </Button>
) : (
<View className="mt-2.5 text-center text-sm text-red-500">
</View>
))}
{canGenerateDocuments.costDocument && ( {canGenerateDocuments.purchaseDocument && shipOrder && (
<Button <Button
type="default" type="default"
size={"xlarge"} size={"xlarge"}
block block
onClick={generateCostDocument} onClick={generatePurchaseDocument}
> >
</Button> </Button>
)} )}
</View> </View>
{!shipOrder && (
<View className="mt-2.5 text-center text-sm text-red-500">
</View>
)}
</View>
) : (
<View className="border-t border-gray-200 pt-2.5">
<View className="mb-2">
<Text className="text-lg font-semibold"></Text>
</View>
<View className="flex flex-col gap-3">
<View className="mt-2.5 text-center text-sm text-red-500">
</View>
</View>
</View> </View>
)} )}
</View> </View>

View File

@ -139,7 +139,8 @@ export default hocAuth(function Page(props: CommonComponent) {
const orderCostList1 = purchaseOrder.orderCostList.map( const orderCostList1 = purchaseOrder.orderCostList.map(
(item: CostItem) => ({ (item: CostItem) => ({
...item, ...item,
selected: true, // 设置默认选中,
selected: item.count > 0,
}), }),
) as any; ) as any;
setOrderCostList(orderCostList1); setOrderCostList(orderCostList1);
@ -308,6 +309,7 @@ export default hocAuth(function Page(props: CommonComponent) {
orderId: orderId, orderId: orderId,
active: active, active: active,
orderSupplierList: purchaseOrder.orderSupplierList, orderSupplierList: purchaseOrder.orderSupplierList,
orderCostList: purchaseOrder.orderCostList,
}); });
if (data.success) { if (data.success) {
@ -611,6 +613,42 @@ export default hocAuth(function Page(props: CommonComponent) {
}), }),
]); ]);
}} }}
changeProduct={(productVO: BusinessAPI.ProductVO) => {
setOrderSupplierList([
...orderSupplierList.map((item: SupplierVO) => {
item.productId = productVO.productId;
item.productName = productVO.name;
return item;
}),
]);
setPurchaseOrder((prev) => {
return {
...prev!,
orderCostList: [
...(prev?.orderCostList?.filter((item) => {
return (
item.costType !== "WORKER_ADVANCE" &&
item.costType !== "PRODUCTION_ADVANCE"
);
}) || []),
...(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,
};
}) || []),
],
};
});
}}
isFirst={index === 0} isFirst={index === 0}
key={item.orderSupplierId} key={item.orderSupplierId}
ref={(ref) => { ref={(ref) => {
@ -778,7 +816,6 @@ export default hocAuth(function Page(props: CommonComponent) {
const selectedIndex = orderSupplierList.findIndex( const selectedIndex = orderSupplierList.findIndex(
(supplier) => supplier.selected, (supplier) => supplier.selected,
); );
console.log("selectedIndex", selectedIndex);
if ( if (
selectedIndex !== -1 && selectedIndex !== -1 &&
orderPackageRefs.current[selectedIndex]?.validate() orderPackageRefs.current[selectedIndex]?.validate()

View File

@ -24,7 +24,6 @@ import {
MaterialCostSection, MaterialCostSection,
PackageInfoSection, PackageInfoSection,
PackagingCostSection, PackagingCostSection,
PurchaseCostInfoSection,
PurchaseOrderRejectApprove, PurchaseOrderRejectApprove,
RebateCalcSection, RebateCalcSection,
State, State,
@ -70,13 +69,13 @@ const sections = {
// containerClass: "border-l-8 border-l-purple-500", // containerClass: "border-l-8 border-l-purple-500",
// contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto", // contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
// }, // },
// 采购成本 // // 采购成本
purchaseCostInfo: { // purchaseCostInfo: {
component: PurchaseCostInfoSection, // component: PurchaseCostInfoSection,
title: "采购成本", // title: "采购成本",
containerClass: "border-l-8 border-l-red-500", // containerClass: "border-l-8 border-l-red-500",
contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto", // contentClass: "p-4 bg-white rounded-b-lg shadow-sm overflow-x-auto",
}, // },
// 包装纸箱费 // 包装纸箱费
packageInfo: { packageInfo: {
component: PackageInfoSection, component: PackageInfoSection,

View File

@ -7,6 +7,7 @@ import * as supplier from "./supplier";
import * as shipOrder from "./shipOrder"; import * as shipOrder from "./shipOrder";
import * as setting from "./setting"; import * as setting from "./setting";
import * as purchaseOrder from "./purchaseOrder"; import * as purchaseOrder from "./purchaseOrder";
import * as product from "./product";
import * as platform from "./platform"; import * as platform from "./platform";
import * as menu from "./menu"; import * as menu from "./menu";
import * as material from "./material"; import * as material from "./material";
@ -34,6 +35,7 @@ export default {
shipOrder, shipOrder,
setting, setting,
purchaseOrder, purchaseOrder,
product,
platform, platform,
menu, menu,
material, material,

View File

@ -0,0 +1,156 @@
// @ts-ignore
/* eslint-disable */
import request from "../request";
/** 创建产品 POST /operation/createProduct */
export async function createProduct(
body: BusinessAPI.ProductCreateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseProductVO>(
"/operation/createProduct",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
},
);
}
/** 产品删除 DELETE /operation/destroyProduct */
export async function destroyProduct(
body: BusinessAPI.ProductDestroyCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.Response>("/operation/destroyProduct", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 产品拖拽排序 PUT /operation/dragProduct */
export async function dragProduct(
body: BusinessAPI.ProductDragCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.Response>("/operation/dragProduct", {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 产品拖拽排序 PATCH /operation/dragProduct */
export async function dragProduct1(
body: BusinessAPI.ProductDragCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.Response>("/operation/dragProduct", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}
/** 产品列表 GET /operation/listProduct */
export async function listProduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.listProductParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.MultiResponseProductVO>("/operation/listProduct", {
method: "GET",
params: {
...params,
productListQry: undefined,
...params["productListQry"],
},
...(options || {}),
});
}
/** 产品列表 GET /operation/pageProduct */
export async function pageProduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.pageProductParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.PageResponseProductVO>("/operation/pageProduct", {
method: "GET",
params: {
...params,
productPageQry: undefined,
...params["productPageQry"],
},
...(options || {}),
});
}
/** 产品详情 GET /operation/showProduct */
export async function showProduct(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: BusinessAPI.showProductParams,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseProductVO>(
"/operation/showProduct",
{
method: "GET",
params: {
...params,
productShowQry: undefined,
...params["productShowQry"],
},
...(options || {}),
},
);
}
/** 产品更新 PUT /operation/updateProduct */
export async function updateProduct(
body: BusinessAPI.ProductUpdateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseProductVO>(
"/operation/updateProduct",
{
method: "PUT",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
},
);
}
/** 产品更新 PATCH /operation/updateProduct */
export async function updateProduct1(
body: BusinessAPI.ProductUpdateCmd,
options?: { [key: string]: any },
) {
return request<BusinessAPI.SingleResponseProductVO>(
"/operation/updateProduct",
{
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
},
);
}

View File

@ -798,12 +798,14 @@ declare namespace BusinessAPI {
type CostItemCreateCmd = { type CostItemCreateCmd = {
/** 项目ID */ /** 项目ID */
itemId: string; itemId: string;
/** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用 */ /** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用5_工头垫付6_产地垫付 */
costType: costType:
| "PACKAGING_MATERIALS" | "PACKAGING_MATERIALS"
| "HUMAN_COST" | "HUMAN_COST"
| "OTHER_COST" | "OTHER_COST"
| "FIXED_COST"; | "FIXED_COST"
| "WORKER_ADVANCE"
| "PRODUCTION_ADVANCE";
/** 项目名称 */ /** 项目名称 */
name: string; name: string;
/** 单位 */ /** 单位 */
@ -812,6 +814,8 @@ declare namespace BusinessAPI {
price: number; price: number;
/** 是否在录入时显示 */ /** 是否在录入时显示 */
showInEntry: boolean; showInEntry: boolean;
/** 是否需要填写数量和单价 */
requireQuantityAndPrice: boolean;
/** 备注 */ /** 备注 */
remark?: string; remark?: string;
/** 状态1_启用0_禁用 */ /** 状态1_启用0_禁用 */
@ -837,12 +841,14 @@ declare namespace BusinessAPI {
status?: boolean; status?: boolean;
/** 费用项目ID */ /** 费用项目ID */
itemId?: string; itemId?: string;
/** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用 */ /** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用5_工头垫付6_产地垫付 */
costType?: costType?:
| "PACKAGING_MATERIALS" | "PACKAGING_MATERIALS"
| "HUMAN_COST" | "HUMAN_COST"
| "OTHER_COST" | "OTHER_COST"
| "FIXED_COST"; | "FIXED_COST"
| "WORKER_ADVANCE"
| "PRODUCTION_ADVANCE";
/** 是否在录入时显示 */ /** 是否在录入时显示 */
showInEntry?: boolean; showInEntry?: boolean;
}; };
@ -864,12 +870,14 @@ declare namespace BusinessAPI {
status?: boolean; status?: boolean;
/** 费用项目ID */ /** 费用项目ID */
itemId?: string; itemId?: string;
/** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用 */ /** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用5_工头垫付6_产地垫付 */
costType?: costType?:
| "PACKAGING_MATERIALS" | "PACKAGING_MATERIALS"
| "HUMAN_COST" | "HUMAN_COST"
| "OTHER_COST" | "OTHER_COST"
| "FIXED_COST"; | "FIXED_COST"
| "WORKER_ADVANCE"
| "PRODUCTION_ADVANCE";
/** 项目名称 */ /** 项目名称 */
name?: string; name?: string;
offset?: number; offset?: number;
@ -885,12 +893,14 @@ declare namespace BusinessAPI {
type CostItemUpdateCmd = { type CostItemUpdateCmd = {
/** 费用项目ID */ /** 费用项目ID */
itemId: string; itemId: string;
/** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用 */ /** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用5_工头垫付6_产地垫付 */
costType: costType:
| "PACKAGING_MATERIALS" | "PACKAGING_MATERIALS"
| "HUMAN_COST" | "HUMAN_COST"
| "OTHER_COST" | "OTHER_COST"
| "FIXED_COST"; | "FIXED_COST"
| "WORKER_ADVANCE"
| "PRODUCTION_ADVANCE";
/** 项目名称 */ /** 项目名称 */
name: string; name: string;
/** 单位 */ /** 单位 */
@ -899,6 +909,8 @@ declare namespace BusinessAPI {
price: number; price: number;
/** 是否在录入时显示 */ /** 是否在录入时显示 */
showInEntry: boolean; showInEntry: boolean;
/** 是否需要填写数量和单价 */
requireQuantityAndPrice: boolean;
/** 备注 */ /** 备注 */
remark?: string; remark?: string;
/** 状态1_启用0_禁用 */ /** 状态1_启用0_禁用 */
@ -908,12 +920,14 @@ declare namespace BusinessAPI {
type CostItemVO = { type CostItemVO = {
/** 项目ID */ /** 项目ID */
itemId: string; itemId: string;
/** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用 */ /** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用5_工头垫付6_产地垫付 */
costType: costType:
| "PACKAGING_MATERIALS" | "PACKAGING_MATERIALS"
| "HUMAN_COST" | "HUMAN_COST"
| "OTHER_COST" | "OTHER_COST"
| "FIXED_COST"; | "FIXED_COST"
| "WORKER_ADVANCE"
| "PRODUCTION_ADVANCE";
/** 项目名称 */ /** 项目名称 */
name: string; name: string;
/** 单位 */ /** 单位 */
@ -922,6 +936,8 @@ declare namespace BusinessAPI {
price: number; price: number;
/** 是否在录入时显示 */ /** 是否在录入时显示 */
showInEntry: boolean; showInEntry: boolean;
/** 是否需要填写数量和单价 */
requireQuantityAndPrice: boolean;
/** 备注 */ /** 备注 */
remark?: string; remark?: string;
/** 状态1_启用0_禁用 */ /** 状态1_启用0_禁用 */
@ -1859,6 +1875,10 @@ declare namespace BusinessAPI {
platformListQry: PlatformListQry; platformListQry: PlatformListQry;
}; };
type listProductParams = {
productListQry: ProductListQry;
};
type listPurchaseOrderParams = { type listPurchaseOrderParams = {
purchaseOrderListQry: PurchaseOrderListQry; purchaseOrderListQry: PurchaseOrderListQry;
}; };
@ -2251,6 +2271,15 @@ declare namespace BusinessAPI {
notEmpty?: boolean; notEmpty?: boolean;
}; };
type MultiResponseProductVO = {
success?: boolean;
errCode?: string;
errMessage?: string;
data?: ProductVO[];
empty?: boolean;
notEmpty?: boolean;
};
type MultiResponsePurchaseOrderVO = { type MultiResponsePurchaseOrderVO = {
success?: boolean; success?: boolean;
errCode?: string; errCode?: string;
@ -2352,15 +2381,17 @@ declare namespace BusinessAPI {
/** 数量 */ /** 数量 */
count: number; count: number;
/** 付款方类型:1-我方,2-对方 */ /** 付款方类型:1-我方,2-对方 */
payerType: "US" | "OTHER"; payerType?: "US" | "OTHER";
/** 负责人 */ /** 负责人 */
principal?: string; principal?: string;
/** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用 */ /** 费用类型1_包装材料2_人工费用3_其他费用4_固定费用5_工头垫付6_产地垫付 */
costType: costType:
| "PACKAGING_MATERIALS" | "PACKAGING_MATERIALS"
| "HUMAN_COST" | "HUMAN_COST"
| "OTHER_COST" | "OTHER_COST"
| "FIXED_COST"; | "FIXED_COST"
| "WORKER_ADVANCE"
| "PRODUCTION_ADVANCE";
}; };
type OrderDealer = { type OrderDealer = {
@ -2501,6 +2532,10 @@ declare namespace BusinessAPI {
contractUpload: boolean; contractUpload: boolean;
/** 合同 */ /** 合同 */
contractImg?: string[]; contractImg?: string[];
/** 产品ID */
productId?: string;
/** 产品名称 */
productName?: string;
/** 采购订单包装箱信息 */ /** 采购订单包装箱信息 */
orderPackageList?: OrderPackage[]; orderPackageList?: OrderPackage[];
}; };
@ -2615,6 +2650,10 @@ declare namespace BusinessAPI {
platformPageQry: PlatformPageQry; platformPageQry: PlatformPageQry;
}; };
type pageProductParams = {
productPageQry: ProductPageQry;
};
type pagePurchaseOrderParams = { type pagePurchaseOrderParams = {
purchaseOrderPageQry: PurchaseOrderPageQry; purchaseOrderPageQry: PurchaseOrderPageQry;
}; };
@ -2840,6 +2879,19 @@ declare namespace BusinessAPI {
totalPages?: number; totalPages?: number;
}; };
type PageResponseProductVO = {
success?: boolean;
errCode?: string;
errMessage?: string;
totalCount?: number;
pageSize?: number;
pageIndex?: number;
data?: ProductVO[];
empty?: boolean;
notEmpty?: boolean;
totalPages?: number;
};
type PageResponsePurchaseOrderVO = { type PageResponsePurchaseOrderVO = {
success?: boolean; success?: boolean;
errCode?: string; errCode?: string;
@ -3021,6 +3073,107 @@ declare namespace BusinessAPI {
homePage: string; homePage: string;
}; };
type ProductCreateCmd = {
/** 产品ID */
productId: string;
/** 产品名称 */
name: string;
/** 关联成本费用id */
costItemIds?: number[];
/** 备注 */
remark?: string;
/** 排序号 */
sort: number;
/** 状态1_启用0_禁用 */
status: boolean;
/** 创建时间 */
createdAt?: string;
};
type ProductDestroyCmd = {
/** 产品表ID */
productId: string;
};
type ProductDragCmd = {
/** 相邻元素前 */
prevId?: number;
/** 相邻元素后 */
nextId?: number;
/** 当前元素 */
currentId?: number;
};
type ProductListQry = {
/** 状态1_启用0_禁用 */
status?: boolean;
/** 产品表ID */
productId?: string;
};
type ProductPageQry = {
pageSize?: number;
pageIndex?: number;
orderBy?: string;
orderDirection?: string;
groupBy?: string;
needTotalCount?: boolean;
/** 自定义字段key */
customFieldKey?: string;
/** 自定义字段value */
customFieldValue?: string;
/** 备注 */
remark?: string;
/** 状态1_启用0_禁用 */
status?: boolean;
/** 产品表ID */
productId?: string;
offset?: number;
};
type ProductShowQry = {
/** 状态1_启用0_禁用 */
status?: boolean;
/** 产品表ID */
productId?: string;
};
type ProductUpdateCmd = {
/** 产品表ID */
productId: string;
/** 产品名称 */
name: string;
/** 关联成本费用id */
costItemIds?: number[];
/** 备注 */
remark?: string;
/** 排序号 */
sort: number;
/** 状态1_启用0_禁用 */
status: boolean;
/** 创建时间 */
createdAt?: string;
};
type ProductVO = {
/** 产品ID */
productId: string;
/** 产品名称 */
name: string;
/** 关联成本费用id */
costItemIds?: number[];
/** 备注 */
remark?: string;
/** 排序号 */
sort: number;
/** 状态1_启用0_禁用 */
status: boolean;
/** 成本费用 */
costItemVOList?: CostItemVO[];
/** 创建时间 */
createdAt?: string;
};
type PurchaseOrderApproveCmd = { type PurchaseOrderApproveCmd = {
/** 采购订单ID */ /** 采购订单ID */
orderId: string; orderId: string;
@ -3169,6 +3322,8 @@ declare namespace BusinessAPI {
active?: number; active?: number;
/** 供应商信息 */ /** 供应商信息 */
orderSupplierList: OrderSupplier[]; orderSupplierList: OrderSupplier[];
/** 采购订单费用信息 */
orderCostList: OrderCost[];
}; };
type PurchaseOrderStep3Cmd = { type PurchaseOrderStep3Cmd = {
@ -3838,6 +3993,10 @@ declare namespace BusinessAPI {
platformShowQry: PlatformShowQry; platformShowQry: PlatformShowQry;
}; };
type showProductParams = {
productShowQry: ProductShowQry;
};
type showPurchaseOrderParams = { type showPurchaseOrderParams = {
purchaseOrderShowQry: PurchaseOrderShowQry; purchaseOrderShowQry: PurchaseOrderShowQry;
}; };
@ -4009,6 +4168,13 @@ declare namespace BusinessAPI {
data?: PlatformVO; data?: PlatformVO;
}; };
type SingleResponseProductVO = {
success?: boolean;
errCode?: string;
errMessage?: string;
data?: ProductVO;
};
type SingleResponsePurchaseOrderVO = { type SingleResponsePurchaseOrderVO = {
success?: boolean; success?: boolean;
errCode?: string; errCode?: string;

View File

@ -0,0 +1,107 @@
import axios from "axios";
import Taro from "@tarojs/taro";
import { Toast } from "@nutui/nutui-react-taro";
const request = axios.create({
baseURL: process.env.TARO_API_DOMAIN,
});
// 创建全局的axios实例并安装请求拦截器
request.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么
const saToken = Taro.getStorageSync("saToken");
if (saToken) {
config.headers.saToken = saToken;
}
const slug = Taro.getStorageSync("userRoleVO")?.slug;
if (slug) {
config.headers["Xh-Role-Slug"] = slug;
}
return config;
},
(error) => {
// 处理请求错误
return Promise.reject(error);
},
);
// 在获取到响应后,安装响应拦截器
request.interceptors.response.use(
async (response) => {
console.log("response", response);
const {
data: { success, data },
} = response;
// 处理响应成功的情况
if (success) {
const saToken = data?.meta?.accessToken;
if (saToken) {
Taro.setStorageSync("saToken", saToken);
Taro.setStorageSync("user", data.userVO);
Taro.setStorageSync("userRoleVO", data.userRoleVOList?.[0]);
}
} else {
// 异常处理
if (response.data.errCode === "403") {
Toast.show("toast", {
icon: "fail",
title: "暂无权限",
content: response.data.errMessage,
});
}
// 如果是401则重新登录然后重新发起请求
if (response.data.errCode === "401") {
// 移除缓存
Taro.removeStorageSync("saToken");
Taro.removeStorageSync("user");
Taro.removeStorageSync("userRoleVO");
// const { code } = await Taro.login();
// const data = await wxMaLogin(code);
// if (data) {
// response.config.headers.saToken = `${Taro.getStorageSync("saToken")}`;
// return request(response.config);
// }
// 跳转到登录页面
Taro.navigateTo({
url: "/pages/public/login/index",
});
return response;
}
console.log("response.data.errCode", response.data.errCode);
if (response.data.errCode === "400") {
Toast.show("toast", {
icon: "fail",
title: "请求失败",
content: response.data.errMessage,
});
}
if (response.data.errCode === "500") {
Toast.show("toast", {
icon: "fail",
title: "服务器错误",
content: response.data.errMessage,
});
} else {
Toast.show("toast", {
icon: "fail",
title: "请求失败",
content: response.data.errMessage,
});
}
}
return response;
},
(error) => {
// 处理响应错误的情况
return Promise.reject(error);
},
);
export default request;

View File

@ -0,0 +1,16 @@
// @ts-ignore
/* eslint-disable */
import request from "../poster-request";
/** 健康检查 检查服务是否正常运行 GET /status */
export async function getStatus(options?: { [key: string]: any }) {
return request<{
success?: boolean;
data?: Record<string, any>;
message?: string;
code?: number;
}>("/status", {
method: "GET",
...(options || {}),
});
}

View File

@ -0,0 +1,12 @@
// @ts-ignore
/* eslint-disable */
// API 更新时间:
// API 唯一标识:
import * as health from "./health";
import * as poster from "./poster";
import * as pdf from "./pdf";
export default {
health,
poster,
pdf,
};

View File

@ -0,0 +1,34 @@
// @ts-ignore
/* eslint-disable */
import request from "../poster-request";
/** 生成PDF 从网页URL或HTML内容生成PDF文档 POST /api/v1/pdf */
export async function postApiV1Pdf(
body: {
/** 要生成PDF的网页URL */
webpage?: string;
/** 要生成PDF的HTML内容可选优先级高于webpage */
html?: string;
/** 设备缩放因子 */
device?: number;
/** PDF宽度 */
width?: number;
/** PDF高度 */
height?: number;
},
options?: { [key: string]: any },
) {
return request<{
success?: boolean;
data?: { name?: string; path?: string };
message?: string;
code?: number;
}>("/api/v1/pdf", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}

View File

@ -0,0 +1,38 @@
// @ts-ignore
/* eslint-disable */
import request from "../poster-request";
/** 生成海报 从网页URL或HTML内容生成海报图像 POST /api/v1/poster */
export async function postApiV1Poster(
body: {
/** 要生成海报的网页URL */
webpage?: string;
/** 要生成海报的HTML内容可选优先级高于webpage */
html?: string;
/** 设备缩放因子 */
device?: number;
/** 海报宽度 */
width?: number;
/** 海报高度 */
height?: number;
/** 输出图像类型 */
type?: string;
/** 编码类型 */
encoding?: string;
},
options?: { [key: string]: any },
) {
return request<{
success?: boolean;
data?: { name?: string; path?: string };
message?: string;
code?: number;
}>("/api/v1/poster", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
data: body,
...(options || {}),
});
}

View File

@ -0,0 +1 @@
declare namespace PosterAPI {}

View File

@ -26,7 +26,7 @@ async function ocr(tempFilePath: string, path: string) {
name: "file", name: "file",
header: { header: {
saToken: Taro.getStorageSync("saToken"), saToken: Taro.getStorageSync("saToken"),
"Content-Type": "multipart/form-data", // "Content-Type": "multipart/form-data",
}, },
}); });

View File

@ -10,7 +10,7 @@ export const uploadFile = async (file: File | string) => {
name: "file", name: "file",
header: { header: {
saToken: Taro.getStorageSync("saToken"), saToken: Taro.getStorageSync("saToken"),
"Content-Type": "multipart/form-data", // "Content-Type": "multipart/form-data",
}, },
}); });

File diff suppressed because one or more lines are too long

1
swagger/poster.json Normal file

File diff suppressed because one or more lines are too long