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 @@ + + + +