From 70d9db252a3f37687386b29855791a23c47c429d Mon Sep 17 00:00:00 2001
From: xuqiuyun <1113560936@qq.com>
Date: Wed, 5 Nov 2025 14:39:27 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD=E4=B8=8B?=
=?UTF-8?q?=E8=BD=BD=E9=AA=8C=E6=94=B6=E5=8D=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pc-cattle-transportation/src/api/shipping.js | 9 +
pc-cattle-transportation/src/utils/axios.ts | 15 +-
.../src/views/entry/attestation.vue | 113 ++-
.../views/shipping/createDeliveryDialog.vue | 34 +-
.../src/views/shipping/orderDialog.vue | 20 +
.../controller/DeliveryController.java | 722 +++++++++++++++++-
.../business/dto/DeliveryCreateDto.java | 7 -
.../cattletrade/business/entity/Order.java | 6 +
.../service/impl/DeliveryServiceImpl.java | 26 +-
.../service/impl/OrderServiceImpl.java | 28 +-
.../common/core/utils/TencentCloudUtil.java | 7 +
11 files changed, 919 insertions(+), 68 deletions(-)
diff --git a/pc-cattle-transportation/src/api/shipping.js b/pc-cattle-transportation/src/api/shipping.js
index 6a255dc..96ebfc5 100644
--- a/pc-cattle-transportation/src/api/shipping.js
+++ b/pc-cattle-transportation/src/api/shipping.js
@@ -284,6 +284,15 @@ export function downloadDeliveryPackage(id) {
});
}
+// 下载验收单(生成HTML格式的牛只发车验收单)
+export function downloadAcceptanceForm(id) {
+ return request({
+ url: `/delivery/downloadAcceptanceForm?id=${id}`,
+ method: 'GET',
+ responseType: 'blob', // 用于下载HTML文件
+ });
+}
+
// 获取运送清单详情(用于编辑)
export function getDeliveryDetail(id) {
return request({
diff --git a/pc-cattle-transportation/src/utils/axios.ts b/pc-cattle-transportation/src/utils/axios.ts
index 1402ac0..c3643c8 100644
--- a/pc-cattle-transportation/src/utils/axios.ts
+++ b/pc-cattle-transportation/src/utils/axios.ts
@@ -52,15 +52,17 @@ axios.interceptors.response.use(
// 单独判断导出问题-start
if(toString.call(responseData) === '[object Blob]' && (responseData.type !== 'application/json')) {
download(response);
- return ElMessage({
- type: 'success',
- message: '导出成功!',
- });
+ ElMessage({
+ type: 'success',
+ message: '导出成功!',
+ });
+ return Promise.resolve(response.data); // 返回 Promise,避免返回对象
}else if(toString.call(responseData) === '[object Blob]' && (responseData.type == 'application/json')){
setTimeout(() => {
window.location.href = '/login';
}, 1000);
- return ElMessage.error(`登录过期,请重新登录!`);
+ ElMessage.error(`登录过期,请重新登录!`);
+ return Promise.reject('登录过期,请重新登录!'); // 返回 Promise.reject,避免返回对象
}
// 单独判断导出问题-end
@@ -71,7 +73,8 @@ axios.interceptors.response.use(
setTimeout(() => {
window.location.href = '/login';
}, 1000);
- return ElMessage.error(`登录过期,请重新登录!`);
+ ElMessage.error(`登录过期,请重新登录!`);
+ return Promise.reject('登录过期,请重新登录!'); // 返回 Promise.reject,避免返回对象
}
// console.log(responseData);
// if (responseData && (responseData.code === 650)) {
diff --git a/pc-cattle-transportation/src/views/entry/attestation.vue b/pc-cattle-transportation/src/views/entry/attestation.vue
index ceec278..2968460 100644
--- a/pc-cattle-transportation/src/views/entry/attestation.vue
+++ b/pc-cattle-transportation/src/views/entry/attestation.vue
@@ -102,6 +102,7 @@
编辑
修改状态
打包文件
+ 下载验收单
删除
@@ -125,7 +126,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
import baseSearch from '@/components/common/searchCustom/index.vue';
import createDeliveryDialog from '@/views/shipping/createDeliveryDialog.vue';
import { inspectionList, downloadZip, pageDeviceList } from '@/api/abroad.js';
-import { updateDeliveryStatus, deleteDeliveryLogic, downloadDeliveryPackage, getDeliveryDetail } from '@/api/shipping.js';
+import { updateDeliveryStatus, deleteDeliveryLogic, downloadDeliveryPackage, getDeliveryDetail, downloadAcceptanceForm } from '@/api/shipping.js';
const router = useRouter();
const route = useRoute();
@@ -679,10 +680,52 @@ const downloadPackage = async (row) => {
ElMessage.info('正在打包文件,请稍候...');
// 调用后端API打包文件(包含图片、视频和信息)
+ // 注意:由于响应拦截器设置了 responseType: 'blob',返回的是 Blob 对象
const res = await downloadDeliveryPackage(row.id);
- // 创建下载链接
- const blob = new Blob([res], { type: 'application/zip' });
+ // 确保 res 是 Blob 对象,如果不是则转换为 Blob
+ let blob;
+ if (res instanceof Blob) {
+ blob = res;
+ } else {
+ // 如果不是 Blob,尝试转换为 Blob
+ blob = new Blob([res], { type: 'application/zip' });
+ }
+
+ // 检查响应是否是有效的ZIP文件(通过检查ZIP文件魔数)
+ // ZIP 文件的魔数是:50 4B 03 04 (PK\x03\x04)
+ const arrayBuffer = await blob.arrayBuffer();
+ const uint8Array = new Uint8Array(arrayBuffer);
+
+ // 检查是否是ZIP文件(前4个字节是 50 4B 03 04)
+ const isZipFile = uint8Array.length >= 4 &&
+ uint8Array[0] === 0x50 &&
+ uint8Array[1] === 0x4B &&
+ uint8Array[2] === 0x03 &&
+ uint8Array[3] === 0x04;
+
+ if (!isZipFile) {
+ // 响应是错误信息(JSON或文本),尝试读取并显示错误
+ try {
+ const decoder = new TextDecoder('utf-8');
+ const errorText = decoder.decode(uint8Array);
+ let errorMsg = '打包文件失败';
+ try {
+ // 尝试解析为 JSON
+ const errorObj = JSON.parse(errorText);
+ errorMsg = errorObj.msg || errorObj.message || errorText;
+ } catch (e) {
+ // 不是 JSON,直接使用文本
+ errorMsg = errorText || '打包文件失败,请重试';
+ }
+ ElMessage.error(errorMsg);
+ } catch (e) {
+ ElMessage.error('打包文件失败,请重试');
+ }
+ return;
+ }
+
+ // 创建下载链接(使用验证后的 Blob)
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
@@ -695,7 +738,69 @@ const downloadPackage = async (row) => {
ElMessage.success('文件打包成功');
} catch (error) {
console.error('打包文件失败:', error);
- ElMessage.error('打包文件失败,请重试');
+ ElMessage.error(error.message || '打包文件失败,请重试');
+ } finally {
+ downLoading[row.id] = false;
+ }
+};
+
+// 下载验收单
+const downloadAcceptanceFormHandler = async (row) => {
+ try {
+ downLoading[row.id] = true;
+ ElMessage.info('正在生成验收单,请稍候...');
+
+ // 调用后端API生成验收单
+ const res = await downloadAcceptanceForm(row.id);
+
+ // 确保 res 是 Blob 对象
+ let blob;
+ if (res instanceof Blob) {
+ blob = res;
+ } else {
+ blob = new Blob([res], { type: 'text/html;charset=UTF-8' });
+ }
+
+ // 检查是否是HTML文件(通过检查内容)
+ const arrayBuffer = await blob.arrayBuffer();
+ const uint8Array = new Uint8Array(arrayBuffer);
+
+ // 尝试解码为文本,检查是否是HTML
+ const decoder = new TextDecoder('utf-8');
+ const htmlText = decoder.decode(uint8Array);
+
+ // 检查是否是错误响应(JSON格式)
+ if (htmlText.trim().startsWith('{') || htmlText.trim().startsWith('[')) {
+ try {
+ const errorObj = JSON.parse(htmlText);
+ ElMessage.error(errorObj.msg || errorObj.message || '生成验收单失败,请重试');
+ } catch (e) {
+ ElMessage.error('生成验收单失败,请重试');
+ }
+ return;
+ }
+
+ // 创建下载链接
+ const url = window.URL.createObjectURL(blob);
+ const link = document.createElement('a');
+ link.href = url;
+ link.download = `牛只发车验收单_${row.deliveryNumber || row.id}_${new Date().getTime()}.html`;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ window.URL.revokeObjectURL(url);
+
+ // 同时在新窗口中打开,方便预览
+ const newWindow = window.open('', '_blank');
+ if (newWindow) {
+ newWindow.document.write(htmlText);
+ newWindow.document.close();
+ }
+
+ ElMessage.success('验收单生成成功');
+ } catch (error) {
+ console.error('生成验收单失败:', error);
+ ElMessage.error(error.message || '生成验收单失败,请重试');
} finally {
downLoading[row.id] = false;
}
diff --git a/pc-cattle-transportation/src/views/shipping/createDeliveryDialog.vue b/pc-cattle-transportation/src/views/shipping/createDeliveryDialog.vue
index a7fe2b2..f360aa5 100644
--- a/pc-cattle-transportation/src/views/shipping/createDeliveryDialog.vue
+++ b/pc-cattle-transportation/src/views/shipping/createDeliveryDialog.vue
@@ -224,17 +224,6 @@
/>
-
-
-
-
-
@@ -671,7 +660,6 @@ const formData = reactive({
endLat: '',
endLon: '',
cattleCount: 1,
- estimatedWeight: null,
quarantineCertNo: '',
remark: '',
// 装车相关字段
@@ -746,7 +734,6 @@ const rules = {
startLocation: [{ required: true, message: '请输入起点地址', trigger: 'blur' }],
endLocation: [{ required: true, message: '请输入目的地地址', trigger: 'blur' }],
cattleCount: [{ required: true, message: '请输入牛只数量', trigger: 'blur' }],
- estimatedWeight: [{ required: true, message: '请输入预估重量', trigger: 'blur' }],
};
// 计算耳标设备列表(包含体重输入)
@@ -817,7 +804,6 @@ const buildSubmitData = () => {
// 其他信息
cattleCount: formData.cattleCount,
- estimatedWeight: formData.estimatedWeight,
quarantineCertNo: formData.quarantineCertNo,
remark: formData.remark,
@@ -850,12 +836,24 @@ const buildSubmitData = () => {
}
// 将所有undefined值转换为空字符串,确保字段被提交
+ // 但是对于数值类型的字段(如cattleCount),保留null或原值,不要转换为空字符串
Object.keys(data).forEach(key => {
if (data[key] === undefined) {
- data[key] = '';
+ // 数值类型字段保留null,其他字段转换为空字符串
+ if (key === 'cattleCount' ||
+ key === 'orderId' || key === 'shipperId' || key === 'buyerId' ||
+ key === 'driverId' || key === 'serverId') {
+ data[key] = null;
+ } else {
+ data[key] = '';
+ }
}
});
+ // 确保cattleCount不为空字符串,如果是空字符串则转换为null
+ if (data.cattleCount === '') {
+ data.cattleCount = null;
+ }
return data;
};
@@ -955,6 +953,9 @@ const fillFormWithEditData = (editData) => {
formData.entruckWeight = delivery.entruckWeight || null;
formData.landingEntruckWeight = delivery.landingEntruckWeight || null;
+ // 牛只数量(从ratedQuantity字段映射)
+ formData.cattleCount = delivery.ratedQuantity || 1;
+
// 照片
formData.quarantineTickeyUrl = delivery.quarantineTickeyUrl || '';
formData.poundListImg = delivery.poundListImg || '';
@@ -1246,7 +1247,8 @@ const handleSubmit = () => {
// 判断是编辑还是新增
if (formData.editId) {
// 编辑模式:调用更新接口
-
+ // 将cattleCount映射为ratedQuantity(后端DeliveryEditDto使用ratedQuantity字段)
+ submitData.ratedQuantity = submitData.cattleCount;
submitData.deliveryId = formData.editId; // 添加deliveryId字段(后端需要)
res = await shippingApi.updateDeliveryInfo(submitData);
} else {
diff --git a/pc-cattle-transportation/src/views/shipping/orderDialog.vue b/pc-cattle-transportation/src/views/shipping/orderDialog.vue
index 145cd5e..22aa615 100644
--- a/pc-cattle-transportation/src/views/shipping/orderDialog.vue
+++ b/pc-cattle-transportation/src/views/shipping/orderDialog.vue
@@ -76,6 +76,17 @@
+
+
+
+
@@ -89,6 +100,7 @@