目前还差物联网分配问题

This commit is contained in:
xuqiuyun
2025-10-21 17:29:52 +08:00
parent 5fe7a5c48a
commit 0249dfc5bb
314 changed files with 91767 additions and 91 deletions

View File

@@ -87,7 +87,7 @@
link
v-if="scope.row.status == 4 || scope.row.status == 5"
v-hasPermi="['entry:download']"
@click="download(scope.row.zipUrl)"
@click="download(scope.row)"
:loading="downLoading[scope.row.id]"
style="padding: 0"
>下载文件</el-button
@@ -137,21 +137,29 @@ const formItemList = reactive([
param: 'licensePlate',
labelWidth: 65,
span: 7,
placeholder: '请输入完整车牌号',
},
{
label: '创建时间',
type: 'daterange',
type: 'date',
format: 'YYYY-MM-DD',
valueFormat: 'YYYY-MM-DD',
param: 'myTimes',
param: 'createTime',
labelWidth: 80,
span: 7,
placeholder: '请选择创建日期',
},
{
label: '核验状态',
type: 'select',
selectOptions: [
{ value: 1, text: '待核验' },
{ value: 2, text: '已核验' },
{ value: 1, text: '待装车' },
{ value: 2, text: '已装车/预付款已支付' },
{ value: 3, text: '已装车/尾款待支付' },
{ value: 4, text: '已核验/待买家付款' },
{ value: 5, text: '尾款已付款' },
{ value: 6, text: '发票待开/进项票' },
{ value: 7, text: '发票待开/销项' },
],
param: 'status',
span: 7,
@@ -177,12 +185,20 @@ const getDataList = () => {
};
params.interfaceType = 2;
// 安全处理时间参数
if (searchParams.myTimes && Array.isArray(searchParams.myTimes) && searchParams.myTimes.length > 0) {
params.startTime = searchParams.myTimes[0];
params.endTime = searchParams.myTimes[1];
// 处理精确的创建时间查询
if (searchParams.createTime) {
params.createTime = searchParams.createTime;
console.log('精确创建时间查询:', searchParams.createTime);
}
// 处理精确的车牌号查询
if (searchParams.licensePlate) {
params.licensePlate = searchParams.licensePlate.trim();
console.log('精确车牌号查询:', params.licensePlate);
}
console.log('查询参数:', params);
inspectionList(params)
.then((ret) => {
console.log('入境检疫列表返回结果:', ret);
@@ -202,6 +218,22 @@ const getDataList = () => {
driverName: firstRow.driverName,
licensePlate: firstRow.licensePlate
});
// 检查Word导出所需字段
console.log('Word导出字段检查:', {
supplierName: firstRow.supplierName,
buyerName: firstRow.buyerName,
startLocation: firstRow.startLocation,
createTime: firstRow.createTime,
endLocation: firstRow.endLocation,
driverName: firstRow.driverName,
driverMobile: firstRow.driverMobile,
licensePlate: firstRow.licensePlate,
ratedQuantity: firstRow.ratedQuantity,
landingEntruckWeight: firstRow.landingEntruckWeight,
emptyWeight: firstRow.emptyWeight,
firmPrice: firstRow.firmPrice
});
}
})
.catch(() => {
@@ -219,19 +251,263 @@ const details = (row, length) => {
},
});
};
// 下载文件
const download = (url) => {
window.location.href = url;
// 下载文件 - 生成HTML文档可打印为PDF或Word
const download = async (row) => {
try {
downLoading[row.id] = true;
// 计算字段
const landingWeight = parseFloat(row.landingEntruckWeight || 0);
const emptyWeight = parseFloat(row.emptyWeight || 0);
const totalWeight = ((landingWeight - emptyWeight) / 2).toFixed(2);
const unitPrice = (parseFloat(row.firmPrice || 0) / 2).toFixed(2);
const totalAmount = (parseFloat(totalWeight) * parseFloat(unitPrice)).toFixed(2);
// 准备数据 - 使用回退机制
const data = {
supplierName: row.supplierName || row.supplierMobile || '',
buyerName: row.buyerName || row.buyerMobile || '',
startLocation: row.startLocation || '',
createTime: row.createTime || '',
endLocation: row.endLocation || '',
driverName: row.driverName || '',
driverMobile: row.driverMobile || '',
licensePlate: row.licensePlate || '',
ratedQuantity: row.ratedQuantity || '',
totalWeight: totalWeight,
unitPrice: unitPrice,
totalAmount: totalAmount
};
console.log('生成Word文档数据:', data);
console.log('原始数据字段检查:', {
supplierName: row.supplierName,
buyerName: row.buyerName,
supplierMobile: row.supplierMobile,
buyerMobile: row.buyerMobile,
fundName: row.fundName,
fundMobile: row.fundMobile
});
// 生成HTML内容
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>牛只发车验收单</title>
<style>
@media print {
body { margin: 0; }
.no-print { display: none; }
}
body {
font-family: "Microsoft YaHei", "SimSun", Arial, sans-serif;
margin: 20px;
line-height: 1.4;
}
.header {
text-align: center;
font-size: 20px;
font-weight: bold;
margin-bottom: 30px;
border-bottom: 2px solid #000;
padding-bottom: 10px;
}
.order-number {
text-align: right;
margin-bottom: 20px;
font-size: 14px;
}
.info-grid {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
font-size: 14px;
}
.info-grid td {
border: 1px solid #000;
padding: 10px;
vertical-align: top;
}
.info-grid .label {
background-color: #f5f5f5;
font-weight: bold;
width: 20%;
text-align: center;
}
.cattle-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
font-size: 14px;
}
.cattle-table th, .cattle-table td {
border: 1px solid #000;
padding: 10px;
text-align: center;
}
.cattle-table th {
background-color: #f5f5f5;
font-weight: bold;
}
.signature-section {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
font-size: 14px;
}
.signature-section td {
border: 1px solid #000;
padding: 10px;
vertical-align: top;
}
.signature-section .label {
background-color: #f5f5f5;
font-weight: bold;
width: 25%;
text-align: center;
}
.print-button {
background-color: #409EFF;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin: 20px 0;
}
.print-button:hover {
background-color: #66b1ff;
}
</style>
</head>
<body>
<div class="header">牛只发车验收单</div>
<div class="order-number">订单编号: </div>
<table class="info-grid">
<tr>
<td class="label">供货单位</td>
<td>${data.supplierName}</td>
<td class="label">收货单位</td>
<td>${data.buyerName}</td>
</tr>
<tr>
<td class="label">发车地点</td>
<td>${data.startLocation}</td>
<td class="label">发车时间</td>
<td>${data.createTime}</td>
</tr>
<tr>
<td class="label">到达地点</td>
<td>${data.endLocation}</td>
<td class="label">动物检疫合格证明编号</td>
<td></td>
</tr>
<tr>
<td class="label">司机姓名及联系方式</td>
<td>${data.driverName} ${data.driverMobile}</td>
<td class="label">装车车牌号</td>
<td>${data.licensePlate}</td>
</tr>
</table>
<table class="cattle-table">
<thead>
<tr>
<th>序号</th>
<th>活牛品种</th>
<th>单只体重范围 (斤)</th>
<th>下车总数量 (头)</th>
<th>下车总重量 (斤)</th>
<th>单价 (元/斤)</th>
<th>总金额 (元)</th>
<th>备注</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td>${data.ratedQuantity}</td>
<td>${data.totalWeight}</td>
<td>${data.unitPrice}</td>
<td>${data.totalAmount}</td>
<td></td>
</tr>
</tbody>
</table>
<table class="signature-section">
<tr>
<td class="label">已支付货款时间</td>
<td></td>
<td class="label">已支付货款金额</td>
<td></td>
</tr>
<tr>
<td class="label">应支付尾款时间</td>
<td></td>
<td class="label">应支付尾款金额</td>
<td></td>
</tr>
<tr>
<td class="label">验收结论</td>
<td></td>
<td class="label">验收时间</td>
<td></td>
</tr>
<tr>
<td class="label">供货单位指定验收人签字及联系方式</td>
<td></td>
<td class="label">收货单位指定验收人签字及联系方式</td>
<td></td>
</tr>
<tr>
<td class="label">供货单位盖章</td>
<td></td>
<td class="label">收货单位盖章</td>
<td></td>
</tr>
</table>
<div class="no-print">
<button class="print-button" onclick="window.print()">打印/保存为PDF</button>
<p style="color: #666; font-size: 12px;">
提示:点击"打印/保存为PDF"按钮可以将此文档打印或保存为PDF格式。
在打印对话框中,您也可以选择"另存为PDF"来保存文档。
</p>
</div>
</body>
</html>`;
// 在新窗口中打开HTML文档
const newWindow = window.open('', '_blank');
newWindow.document.write(htmlContent);
newWindow.document.close();
ElMessage.success('文档已生成,可以在新窗口中查看和打印');
} catch (error) {
console.error('生成文档失败:', error);
ElMessage.error('生成文档失败,请重试');
} finally {
downLoading[row.id] = false;
}
};
// 状态文本转换
const getStatusText = (status) => {
const statusMap = {
1: '待装车',
2: '已装车/待资金方付款',
3: '待核验/资金方已付款',
2: '已装车/预付款已支付',
3: '已装车/尾款待支付',
4: '已核验/待买家付款',
5: '买家已付款'
5: '尾款已付款',
6: '发票待开/进项票',
7: '发票待开/销项'
};
return statusMap[status] || '未知状态';
};
@@ -240,10 +516,12 @@ const getStatusText = (status) => {
const getStatusTagType = (status) => {
const typeMap = {
1: 'warning', // 待装车 - 橙色
2: 'info', // 已装车/待资金方付款 - 蓝色
3: 'warning', // 待核验/资金方已付款 - 橙色
2: 'info', // 已装车/预付款已支付 - 蓝色
3: 'warning', // 已装车/尾款待支付 - 橙色
4: 'success', // 已核验/待买家付款 - 绿色
5: 'success' // 买家已付款 - 绿色
5: 'success', // 尾款已付款 - 绿色
6: 'info', // 发票待开/进项票 - 蓝色
7: 'info' // 发票待开/销项 - 蓝色
};
return typeMap[status] || 'info';
};

View File

@@ -88,6 +88,9 @@
<el-descriptions-item label="装车过磅重量:">{{
data.baseInfo.entruckWeight ? data.baseInfo.entruckWeight + 'kg' : ''
}}</el-descriptions-item>
<el-descriptions-item label="落地过磅重量:">{{
data.baseInfo.landingEntruckWeight ? data.baseInfo.landingEntruckWeight + 'kg' : ''
}}</el-descriptions-item>
<!-- 照片上传区域 -->
<el-descriptions-item label="检疫票:">

View File

@@ -84,6 +84,13 @@
>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="落地过磅重量" prop="landingEntruckWeight">
<el-input v-model="ruleForm.landingEntruckWeight" placeholder="请输入落地过磅重量" clearable>
<template #append>kg</template></el-input
>
</el-form-item>
</el-col>
</el-row>
<!-- 照片上传区域 -->
<el-divider content-position="left">
@@ -366,7 +373,7 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted, nextTick } from 'vue';
import { hostList, orderLoadDetail, orderLoadSave } from '@/api/shipping.js';
import { useUserStore } from '../../store/user';
@@ -393,6 +400,7 @@ const ruleForm = reactive({
serverDeviceSn: '', // 主机id
emptyWeight: '', // 空车过磅重量
entruckWeight: '', // 装车过磅重量
landingEntruckWeight: '', // 落地过磅重量
quarantineTickeyUrl: '', // 检疫票
poundListImg: '', // 传纸质磅单(双章)
entruckWeightVideo: '', // 装车过磅视频
@@ -408,18 +416,73 @@ const ruleForm = reactive({
xqDevices: [],
});
const rules = reactive({});
// 自动填充表单数据映射函数
const autoFillFormData = (apiData) => {
if (!apiData) return;
// 基础信息映射
// 不要覆盖已经设置的 deliveryId
if (apiData.id && apiData.id !== '') {
ruleForm.deliveryId = apiData.id;
}
ruleForm.estimatedDeliveryTime = apiData.estimatedDeliveryTime || '';
ruleForm.serverDeviceSn = apiData.serverDeviceId || '';
// 重量信息映射
ruleForm.emptyWeight = apiData.emptyWeight || '';
ruleForm.entruckWeight = apiData.entruckWeight || '';
ruleForm.landingEntruckWeight = apiData.landingEntruckWeight || '';
// 照片URL映射
ruleForm.quarantineTickeyUrl = apiData.quarantineTickeyUrl || '';
ruleForm.poundListImg = apiData.poundListImg || '';
ruleForm.emptyVehicleFrontPhoto = apiData.emptyVehicleFrontPhoto || '';
ruleForm.loadedVehicleFrontPhoto = apiData.loadedVehicleFrontPhoto || '';
ruleForm.loadedVehicleWeightPhoto = apiData.loadedVehicleWeightPhoto || '';
ruleForm.driverIdCardPhoto = apiData.driverIdCardPhoto || '';
// 视频URL映射
ruleForm.entruckWeightVideo = apiData.entruckWeightVideo || '';
ruleForm.emptyWeightVideo = apiData.emptyWeightVideo || '';
ruleForm.entruckVideo = apiData.entruckVideo || '';
ruleForm.controlSlotVideo = apiData.controlSlotVideo || '';
ruleForm.cattleLoadingCircleVideo = apiData.cattleLoadingCircleVideo || '';
console.log('表单数据已自动填充:', ruleForm);
console.log('API数据映射详情:', {
deliveryId: apiData.id,
estimatedDeliveryTime: apiData.estimatedDeliveryTime,
emptyWeight: apiData.emptyWeight,
entruckWeight: apiData.entruckWeight,
landingEntruckWeight: apiData.landingEntruckWeight,
quarantineTickeyUrl: apiData.quarantineTickeyUrl,
poundListImg: apiData.poundListImg
});
};
// 查询详情
const getOrderDetail = () => {
orderLoadDetail({
deliveryId: data.deliveryId,
}).then((res) => {
console.log('getOrderDetail API 响应:', res);
if (res.code === 200) {
console.log('API 返回的数据:', res.data);
const ear = res.data && res.data.deliveryDevices;
const collar = res.data && res.data.xqDevices;
// 兼容后端返回数组或 { rows, total } 两种格式
data.deliveryDevices = Array.isArray(ear) ? ear : (ear && ear.rows ? ear.rows : []);
data.xqDevices = Array.isArray(collar) ? collar : (collar && collar.rows ? collar.rows : []);
console.log('准备调用 autoFillFormData数据:', res.data);
// 自动填充表单数据
autoFillFormData(res.data);
} else {
console.error('getOrderDetail API 调用失败:', res);
}
}).catch((error) => {
console.error('getOrderDetail API 调用异常:', error);
});
};
// 智能主机远程搜索
@@ -553,7 +616,27 @@ const onClickSave = () => {
data.saveLoading = true;
ruleForm.deliveryDevices = data.deliveryDevices;
ruleForm.xqDevices = data.xqDevices;
orderLoadSave(ruleForm).then((res) => {
// 确保 deliveryId 是数字类型
const saveData = { ...ruleForm };
console.log('保存时的 deliveryId:', saveData.deliveryId, '类型:', typeof saveData.deliveryId);
if (saveData.deliveryId) {
const parsedId = parseInt(saveData.deliveryId);
console.log('解析后的 ID:', parsedId, 'isNaN:', isNaN(parsedId));
if (isNaN(parsedId)) {
ElMessage.error('运送清单ID格式错误');
data.saveLoading = false;
return;
}
saveData.deliveryId = parsedId;
} else {
ElMessage.error('运送清单ID不能为空');
data.saveLoading = false;
return;
}
orderLoadSave(saveData).then((res) => {
data.saveLoading = false;
if (res.code === 200) {
ElMessage({
@@ -577,7 +660,7 @@ const handleClose = () => {
formDataRef.value.resetFields();
}
};
const onShowDialog = (row) => {
const onShowDialog = (row, apiData = null) => {
data.dialogVisible = true;
if (formDataRef.value) {
formDataRef.value.resetFields();
@@ -586,7 +669,16 @@ const onShowDialog = (row) => {
nextTick(() => {
data.deliveryId = row.id;
ruleForm.deliveryId = row.id;
getOrderDetail();
console.log('设置 deliveryId:', row.id, '类型:', typeof row.id);
// 如果提供了API数据直接填充表单
if (apiData) {
autoFillFormData(apiData);
} else {
// 否则从服务器获取详情
getOrderDetail();
}
getHostList();
});
}

View File

@@ -1,17 +1,21 @@
<template>
<div>
<base-search :formItemList="formItemList" @search="searchFrom" ref="baseSearchRef"> </base-search>
<div style="display: flex; padding: 10px; background: #fff; margin-bottom: 10px">
<el-button type="primary" v-hasPermi="['loading:create']" @click="showAddDialog(null)">创建装车订单</el-button>
<!-- <el-button
type="primary"
v-hasPermi="['loading:add']"
@click="showCreateDeliveryDialog"
style="margin-left: 10px"
>
新增运送清单
</el-button> -->
<!-- 横向滚动操作栏 -->
<div class="operation-scroll-bar">
<div class="operation-scroll-container">
<el-button type="primary" v-hasPermi="['loading:create']" @click="showAddDialog(null)">创建装车订单</el-button>
<!-- <el-button
type="primary"
v-hasPermi="['loading:add']"
@click="showCreateDeliveryDialog"
style="margin-left: 10px"
>
新增运送清单
</el-button> -->
</div>
</div>
<div class="main-container">
<el-table :data="rows" :key="data.tableKey" border v-loading="data.dataListLoading" element-loading-text="数据加载中..." style="width: 100%">
<el-table-column label="装车订单编号" prop="deliveryNumber">
@@ -440,17 +444,19 @@ const del = (id) => {
};
// 装车
const loadClick = (row) => {
console.log('装车按钮点击row数据:', row);
if (LoadDialogRef.value) {
LoadDialogRef.value.onShowDialog(row);
// 直接传递row数据作为API数据
LoadDialogRef.value.onShowDialog(row, row);
}
};
// 编辑状态
const editStatus = (row) => {
ElMessageBox.prompt('请输入状态(1-待装车 2-已装车/待资金方付款 3-待核验/资金方已付款 4-已核验/待买家付款 5-买家已付款)', '修改状态', {
ElMessageBox.prompt('请输入状态(1-待装车 2-已装车/预付款已支付 3-已装车/尾款待支付 4-已核验/待买家付款 5-尾款已付款 6-发票待开/进项票 7-发票待开/销项)', '修改状态', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /^[12345]$/,
inputErrorMessage: '请输入1、2、3、4或5',
inputPattern: /^[1234567]$/,
inputErrorMessage: '请输入1、2、3、4、5、6或7',
inputValue: String(row.status || 1)
}).then(({ value }) => {
updateDeliveryStatus({ id: row.id, status: parseInt(value) })
@@ -473,10 +479,12 @@ const editStatus = (row) => {
const getStatusText = (status) => {
const statusMap = {
1: '待装车',
2: '已装车/待资金方付款',
3: '待核验/资金方已付款',
2: '已装车/预付款已支付',
3: '已装车/尾款待支付',
4: '已核验/待买家付款',
5: '买家已付款'
5: '尾款已付款',
6: '发票待开/进项票',
7: '发票待开/销项'
};
return statusMap[status] || '未知状态';
};
@@ -485,10 +493,12 @@ const getStatusText = (status) => {
const getStatusTagType = (status) => {
const typeMap = {
1: 'warning', // 待装车 - 橙色
2: 'info', // 已装车/待资金方付款 - 蓝色
3: 'warning', // 待核验/资金方已付款 - 橙色
2: 'info', // 已装车/预付款已支付 - 蓝色
3: 'warning', // 已装车/尾款待支付 - 橙色
4: 'success', // 已核验/待买家付款 - 绿色
5: 'success' // 买家已付款 - 绿色
5: 'success', // 尾款已付款 - 绿色
6: 'info', // 发票待开/进项票 - 蓝色
7: 'info' // 发票待开/销项 - 蓝色
};
return typeMap[status] || 'info';
};
@@ -545,6 +555,7 @@ const getProcessedCarPhotos = (row) => {
return carImgUrls;
};
// 监听rows变化强制更新表格
watch(rows, (newRows) => {
console.log('rows数据变化:', newRows);
@@ -564,4 +575,65 @@ onMounted(() => {
});
</script>
<style lang="less" scoped></style>
<style lang="less" scoped>
/* 横向滚动操作栏样式 */
.operation-scroll-bar {
background: #fff;
border: 1px solid #e9ecef;
border-radius: 8px;
margin-bottom: 16px;
padding: 12px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.operation-scroll-container {
display: flex;
overflow-x: auto;
gap: 10px;
padding-bottom: 5px;
/* 自定义滚动条样式 */
&::-webkit-scrollbar {
height: 6px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
&:hover {
background: #a8a8a8;
}
}
/* 确保按钮不会被压缩 */
.el-button {
flex-shrink: 0;
white-space: nowrap;
}
}
/* 响应式设计 */
@media (max-width: 768px) {
.operation-scroll-bar {
padding: 8px;
margin-bottom: 12px;
}
.operation-scroll-container {
gap: 8px;
.el-button {
font-size: 12px;
padding: 6px 12px;
}
}
}
</style>