560 lines
15 KiB
TypeScript
Executable File
560 lines
15 KiB
TypeScript
Executable File
import { defineFakeRoute } from "vite-plugin-fake-server/client";
|
|
|
|
// 生成出库单号
|
|
const generateOutboundNumber = () => {
|
|
const date = new Date();
|
|
const year = date.getFullYear().toString().slice(-2);
|
|
const month = (date.getMonth() + 1).toString().padStart(2, "0");
|
|
const day = date.getDate().toString().padStart(2, "0");
|
|
const random = Math.floor(Math.random() * 1000)
|
|
.toString()
|
|
.padStart(3, "0");
|
|
return `CK${year}${month}${day}${random}`;
|
|
};
|
|
|
|
// 模拟提货明细数据
|
|
const mockDeliveryDetails = [
|
|
{
|
|
id: "1",
|
|
outboundNumber: generateOutboundNumber(),
|
|
deliveryOrderNumber: "TH240310001",
|
|
blNumber: "BL20240001",
|
|
licensePlate: "京A12345",
|
|
driverName: "张师傅",
|
|
driverPhone: "13800138001",
|
|
commodity: "copper_ore",
|
|
commodityCode: "CU-20240310-001",
|
|
batchNumber: "BATCH001",
|
|
quantity: 100,
|
|
unit: "ton",
|
|
unitPrice: 5000,
|
|
totalAmount: 500000,
|
|
outboundDate: "2024-03-10",
|
|
outboundTime: "09:30:00",
|
|
warehouse: "chaoyang",
|
|
location: "A-01-01",
|
|
operator: "王管理员",
|
|
outboundStatus: "completed",
|
|
receiptStatus: "completed",
|
|
receivedQuantity: 100,
|
|
receiptDate: "2024-03-11",
|
|
receiver: "李收货员",
|
|
remark: "第一批铜矿出库",
|
|
createTime: "2024-03-10 09:30:00",
|
|
updateTime: "2024-03-11 10:15:00"
|
|
},
|
|
{
|
|
id: "2",
|
|
outboundNumber: generateOutboundNumber(),
|
|
deliveryOrderNumber: "TH240310002",
|
|
blNumber: "BL20240002",
|
|
licensePlate: "沪B23456",
|
|
driverName: "李师傅",
|
|
driverPhone: "13800138002",
|
|
commodity: "aluminum_material",
|
|
commodityCode: "AL-20240310-001",
|
|
batchNumber: "BATCH002",
|
|
quantity: 50,
|
|
unit: "ton",
|
|
unitPrice: 15000,
|
|
totalAmount: 750000,
|
|
outboundDate: "2024-03-10",
|
|
outboundTime: "10:45:00",
|
|
warehouse: "pudong",
|
|
location: "B-02-01",
|
|
operator: "王管理员",
|
|
outboundStatus: "completed",
|
|
receiptStatus: "partial",
|
|
receivedQuantity: 30,
|
|
receiptDate: "2024-03-12",
|
|
receiver: "张收货员",
|
|
remark: "铝材出库,分批收货",
|
|
createTime: "2024-03-10 10:45:00",
|
|
updateTime: "2024-03-12 14:20:00"
|
|
},
|
|
{
|
|
id: "3",
|
|
outboundNumber: generateOutboundNumber(),
|
|
deliveryOrderNumber: "TH240311001",
|
|
blNumber: "BL20240003",
|
|
licensePlate: "粤C34567",
|
|
driverName: "王师傅",
|
|
driverPhone: "13800138003",
|
|
commodity: "steel",
|
|
commodityCode: "ST-20240311-001",
|
|
batchNumber: "BATCH003",
|
|
quantity: 80,
|
|
unit: "ton",
|
|
unitPrice: 4500,
|
|
totalAmount: 360000,
|
|
outboundDate: "2024-03-11",
|
|
outboundTime: "14:20:00",
|
|
warehouse: "tianhe",
|
|
location: "C-03-01",
|
|
operator: "赵操作员",
|
|
outboundStatus: "completed",
|
|
receiptStatus: "pending",
|
|
receivedQuantity: 0,
|
|
receiptDate: "",
|
|
receiver: "",
|
|
createTime: "2024-03-11 14:20:00",
|
|
updateTime: "2024-03-11 14:20:00"
|
|
},
|
|
{
|
|
id: "4",
|
|
outboundNumber: generateOutboundNumber(),
|
|
deliveryOrderNumber: "TH240311002",
|
|
blNumber: "BL20240004",
|
|
licensePlate: "浙D45678",
|
|
driverName: "赵师傅",
|
|
driverPhone: "13800138004",
|
|
commodity: "copper_material",
|
|
commodityCode: "CU-M-20240311-001",
|
|
batchNumber: "BATCH004",
|
|
quantity: 60,
|
|
unit: "ton",
|
|
unitPrice: 5500,
|
|
totalAmount: 330000,
|
|
outboundDate: "2024-03-11",
|
|
outboundTime: "16:30:00",
|
|
warehouse: "xihu",
|
|
location: "D-04-01",
|
|
operator: "钱操作员",
|
|
outboundStatus: "in_progress",
|
|
receiptStatus: "pending",
|
|
receivedQuantity: 0,
|
|
receiptDate: "",
|
|
receiver: "",
|
|
remark: "正在出库中",
|
|
createTime: "2024-03-11 16:30:00",
|
|
updateTime: "2024-03-11 16:30:00"
|
|
},
|
|
{
|
|
id: "5",
|
|
outboundNumber: generateOutboundNumber(),
|
|
deliveryOrderNumber: "TH240312001",
|
|
blNumber: "BL20240005",
|
|
licensePlate: "苏E56789",
|
|
driverName: "刘师傅",
|
|
driverPhone: "13800138005",
|
|
commodity: "iron_ore",
|
|
commodityCode: "IR-20240312-001",
|
|
batchNumber: "BATCH005",
|
|
quantity: 120,
|
|
unit: "ton",
|
|
unitPrice: 800,
|
|
totalAmount: 96000,
|
|
outboundDate: "2024-03-12",
|
|
outboundTime: "09:15:00",
|
|
warehouse: "gulou",
|
|
location: "E-05-01",
|
|
operator: "孙操作员",
|
|
outboundStatus: "pending",
|
|
receiptStatus: "pending",
|
|
receivedQuantity: 0,
|
|
receiptDate: "",
|
|
receiver: "",
|
|
remark: "待出库",
|
|
createTime: "2024-03-12 09:15:00",
|
|
updateTime: "2024-03-12 09:15:00"
|
|
}
|
|
];
|
|
|
|
// 收货历史记录
|
|
const mockReceiptHistory = [
|
|
{
|
|
id: "1",
|
|
deliveryDetailId: "1",
|
|
receiptDate: "2024-03-11",
|
|
receivedQuantity: 100,
|
|
receiver: "李收货员",
|
|
remark: "全部收货完成",
|
|
createTime: "2024-03-11 10:15:00"
|
|
},
|
|
{
|
|
id: "2",
|
|
deliveryDetailId: "2",
|
|
receiptDate: "2024-03-12",
|
|
receivedQuantity: 30,
|
|
receiver: "张收货员",
|
|
remark: "第一批收货",
|
|
createTime: "2024-03-12 14:20:00"
|
|
}
|
|
];
|
|
|
|
export default defineFakeRoute([
|
|
// 获取提货明细列表
|
|
{
|
|
url: "/delivery-details/list",
|
|
method: "get",
|
|
response: ({ query }) => {
|
|
let list = [...mockDeliveryDetails];
|
|
|
|
// 应用搜索条件
|
|
if (query.outboundNumber) {
|
|
const outboundNumber = Array.isArray(query.outboundNumber)
|
|
? query.outboundNumber[0]
|
|
: query.outboundNumber;
|
|
list = list.filter(item =>
|
|
item.outboundNumber.includes(outboundNumber)
|
|
);
|
|
}
|
|
if (query.deliveryOrderNumber) {
|
|
const deliveryOrderNumber = Array.isArray(query.deliveryOrderNumber)
|
|
? query.deliveryOrderNumber[0]
|
|
: query.deliveryOrderNumber;
|
|
list = list.filter(item =>
|
|
item.deliveryOrderNumber.includes(deliveryOrderNumber)
|
|
);
|
|
}
|
|
if (query.blNumber) {
|
|
const blNumber = Array.isArray(query.blNumber)
|
|
? query.blNumber[0]
|
|
: query.blNumber;
|
|
list = list.filter(item => item.blNumber.includes(blNumber));
|
|
}
|
|
if (query.licensePlate) {
|
|
const licensePlate = Array.isArray(query.licensePlate)
|
|
? query.licensePlate[0]
|
|
: query.licensePlate;
|
|
list = list.filter(item => item.licensePlate.includes(licensePlate));
|
|
}
|
|
if (query.commodity) {
|
|
list = list.filter(item => item.commodity === query.commodity);
|
|
}
|
|
if (query.outboundStatus) {
|
|
list = list.filter(
|
|
item => item.outboundStatus === query.outboundStatus
|
|
);
|
|
}
|
|
if (query.receiptStatus) {
|
|
list = list.filter(item => item.receiptStatus === query.receiptStatus);
|
|
}
|
|
if (query.startDate && query.endDate) {
|
|
list = list.filter(item => {
|
|
const outboundDate = new Date(item.outboundDate).getTime();
|
|
const startDate = new Date(
|
|
Array.isArray(query.startDate)
|
|
? query.startDate[0]
|
|
: query.startDate
|
|
).getTime();
|
|
const endDate = new Date(
|
|
Array.isArray(query.endDate) ? query.endDate[0] : query.endDate
|
|
).getTime();
|
|
return outboundDate >= startDate && outboundDate <= endDate;
|
|
});
|
|
}
|
|
|
|
// 分页处理
|
|
const page = parseInt(
|
|
Array.isArray(query.page) ? query.page[0] : (query.page ?? "1")
|
|
);
|
|
const pageSize = parseInt(
|
|
Array.isArray(query.pageSize)
|
|
? query.pageSize[0]
|
|
: (query.pageSize ?? "10")
|
|
);
|
|
const total = list.length;
|
|
const startIndex = (page - 1) * pageSize;
|
|
const endIndex = startIndex + pageSize;
|
|
const paginatedList = list.slice(startIndex, endIndex);
|
|
|
|
return {
|
|
success: true,
|
|
message: "获取提货明细列表成功",
|
|
data: {
|
|
items: paginatedList,
|
|
total,
|
|
page,
|
|
pageSize
|
|
}
|
|
};
|
|
}
|
|
},
|
|
|
|
// 获取提货明细详情
|
|
{
|
|
url: "/delivery-details/detail/:id",
|
|
method: "get",
|
|
response: ({ params }) => {
|
|
const item = mockDeliveryDetails.find(item => item.id === params.id);
|
|
|
|
if (item) {
|
|
return {
|
|
success: true,
|
|
message: "获取提货明细详情成功",
|
|
data: item
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: false,
|
|
message: "提货明细不存在"
|
|
};
|
|
}
|
|
},
|
|
|
|
// 新增出库单
|
|
{
|
|
url: "/delivery-details/create",
|
|
method: "post",
|
|
response: ({ body }) => {
|
|
try {
|
|
const items = body.items || [];
|
|
|
|
// 为每个出库项创建出库单
|
|
const createdItems = items.map((item: any) => {
|
|
const newDeliveryDetail = {
|
|
id: (mockDeliveryDetails.length + 1).toString(),
|
|
outboundNumber: generateOutboundNumber(),
|
|
deliveryOrderNumber: body.deliveryOrderNumber,
|
|
blNumber: body.blNumber,
|
|
licensePlate: body.licensePlate,
|
|
driverName: body.driverName,
|
|
driverPhone: body.driverPhone,
|
|
commodity: item.commodity,
|
|
commodityCode: item.commodityCode || "",
|
|
batchNumber: item.batchNumber || "",
|
|
quantity: item.quantity,
|
|
unit: item.unit,
|
|
unitPrice: item.unitPrice,
|
|
totalAmount: item.quantity * item.unitPrice,
|
|
outboundDate: body.outboundDate,
|
|
outboundTime: new Date()
|
|
.toTimeString()
|
|
.split(" ")[0]
|
|
.substring(0, 8),
|
|
warehouse: body.warehouse,
|
|
location: item.location || "",
|
|
operator: body.operator,
|
|
outboundStatus: "pending",
|
|
receiptStatus: "pending",
|
|
receivedQuantity: 0,
|
|
receiptDate: "",
|
|
receiver: "",
|
|
remark: body.remark || item.remark || "",
|
|
createTime: new Date()
|
|
.toISOString()
|
|
.replace("T", " ")
|
|
.substring(0, 19),
|
|
updateTime: new Date()
|
|
.toISOString()
|
|
.replace("T", " ")
|
|
.substring(0, 19)
|
|
};
|
|
|
|
mockDeliveryDetails.unshift(newDeliveryDetail);
|
|
return newDeliveryDetail;
|
|
});
|
|
|
|
return {
|
|
success: true,
|
|
message: "出库单创建成功",
|
|
data: {
|
|
items: createdItems,
|
|
count: createdItems.length
|
|
}
|
|
};
|
|
} catch {
|
|
return {
|
|
success: false,
|
|
message: "出库单创建失败"
|
|
};
|
|
}
|
|
}
|
|
},
|
|
|
|
// 更新出库单
|
|
{
|
|
url: "/delivery-details/update/:id",
|
|
method: "put",
|
|
response: ({ body, params }) => {
|
|
const index = mockDeliveryDetails.findIndex(
|
|
item => item.id === params.id
|
|
);
|
|
|
|
if (index !== -1) {
|
|
// 更新出库单信息
|
|
mockDeliveryDetails[index] = {
|
|
...mockDeliveryDetails[index],
|
|
...body,
|
|
updateTime: new Date()
|
|
.toISOString()
|
|
.replace("T", " ")
|
|
.substring(0, 19)
|
|
};
|
|
|
|
// 如果更新了数量或单价,重新计算总金额
|
|
if (body.quantity || body.unitPrice) {
|
|
const quantity = body.quantity || mockDeliveryDetails[index].quantity;
|
|
const unitPrice =
|
|
body.unitPrice || mockDeliveryDetails[index].unitPrice;
|
|
mockDeliveryDetails[index].totalAmount = quantity * unitPrice;
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
message: "出库单更新成功",
|
|
data: mockDeliveryDetails[index]
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: false,
|
|
message: "出库单不存在"
|
|
};
|
|
}
|
|
},
|
|
|
|
// 收货确认
|
|
{
|
|
url: "/delivery-details/confirm-receipt/:id",
|
|
method: "put",
|
|
response: ({ body, params }) => {
|
|
const index = mockDeliveryDetails.findIndex(
|
|
item => item.id === params.id
|
|
);
|
|
|
|
if (index !== -1) {
|
|
const deliveryDetail = mockDeliveryDetails[index];
|
|
const receivedQuantity = body.receivedQuantity;
|
|
|
|
// 计算总收货数量
|
|
const totalReceived =
|
|
deliveryDetail.receivedQuantity + receivedQuantity;
|
|
|
|
// 更新收货状态
|
|
let newReceiptStatus = "partial";
|
|
if (totalReceived >= deliveryDetail.quantity) {
|
|
newReceiptStatus = "completed";
|
|
} else if (totalReceived === 0) {
|
|
newReceiptStatus = "pending";
|
|
}
|
|
|
|
// 检查是否有差异
|
|
if (totalReceived !== deliveryDetail.quantity && totalReceived > 0) {
|
|
newReceiptStatus = "discrepancy";
|
|
}
|
|
|
|
// 更新记录
|
|
mockDeliveryDetails[index] = {
|
|
...deliveryDetail,
|
|
receivedQuantity: totalReceived,
|
|
receiptDate:
|
|
body.receiptDate || new Date().toISOString().split("T")[0],
|
|
receiver: body.receiver,
|
|
receiptStatus: newReceiptStatus,
|
|
updateTime: new Date()
|
|
.toISOString()
|
|
.replace("T", " ")
|
|
.substring(0, 19)
|
|
};
|
|
|
|
// 添加到收货历史记录
|
|
const newReceiptRecord = {
|
|
id: (mockReceiptHistory.length + 1).toString(),
|
|
deliveryDetailId: Array.isArray(params.id) ? params.id[0] : params.id,
|
|
receiptDate: body.receiptDate,
|
|
receivedQuantity: receivedQuantity,
|
|
receiver: body.receiver,
|
|
remark: body.discrepancyReason || body.remark || "",
|
|
createTime: new Date()
|
|
.toISOString()
|
|
.replace("T", " ")
|
|
.substring(0, 19)
|
|
};
|
|
|
|
mockReceiptHistory.push(newReceiptRecord);
|
|
|
|
return {
|
|
success: true,
|
|
message: "收货确认成功",
|
|
data: {
|
|
deliveryDetail: mockDeliveryDetails[index],
|
|
receiptRecord: newReceiptRecord
|
|
}
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: false,
|
|
message: "出库单不存在"
|
|
};
|
|
}
|
|
},
|
|
|
|
// 获取收货历史记录
|
|
{
|
|
url: "/delivery-details/receipt-history/:id",
|
|
method: "get",
|
|
response: ({ params }) => {
|
|
const history = mockReceiptHistory.filter(
|
|
record => record.deliveryDetailId === params.id
|
|
);
|
|
|
|
return {
|
|
success: true,
|
|
message: "获取收货历史记录成功",
|
|
data: history
|
|
};
|
|
}
|
|
},
|
|
|
|
// 下载出库单模板
|
|
{
|
|
url: "/delivery-details/template/download",
|
|
method: "get",
|
|
response: () => {
|
|
return {
|
|
success: true,
|
|
message: "获取模板成功",
|
|
data: {
|
|
fileName: "出库单模板.xlsx",
|
|
url: "/templates/outbound-order-template.xlsx"
|
|
}
|
|
};
|
|
}
|
|
},
|
|
|
|
// 导出提货明细
|
|
{
|
|
url: "/delivery-details/export",
|
|
method: "get",
|
|
response: () => {
|
|
return {
|
|
success: true,
|
|
message: "导出成功",
|
|
data: {
|
|
fileName: `提货明细_${new Date().toISOString().split("T")[0]}.xlsx`,
|
|
url: "/exports/delivery-details.xlsx"
|
|
}
|
|
};
|
|
}
|
|
},
|
|
|
|
// 打印提货单
|
|
{
|
|
url: "/delivery-details/print/:id",
|
|
method: "get",
|
|
response: ({ params }) => {
|
|
const item = mockDeliveryDetails.find(item => item.id === params.id);
|
|
|
|
if (item) {
|
|
return {
|
|
success: true,
|
|
message: "打印任务已创建",
|
|
data: {
|
|
fileName: `${item.outboundNumber}_提货单.pdf`,
|
|
url: `/print/delivery-order-${params.id}.pdf`
|
|
}
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: false,
|
|
message: "出库单不存在"
|
|
};
|
|
}
|
|
}
|
|
]);
|