完善小细节

This commit is contained in:
xuqiuyun
2025-10-24 17:32:42 +08:00
parent ecccd025d1
commit a40ce28318
73 changed files with 7238 additions and 114 deletions

View File

@@ -54,16 +54,16 @@
<el-table-column label="预计送达时间" prop="estimatedDeliveryTime"> </el-table-column>
<el-table-column label="登记设备数量" prop="registeredJbqCount" width="120">
<template #default="scope">
{{ scope.row.registeredJbqCount || '0' }}
{{ getTotalDeviceCount(scope.row.id) }}
</template>
</el-table-column>
<el-table-column label="车内盘点耳标数量" prop="earTagCount" width="140">
<template #default="scope">
<span v-if="scope.row.earTagCount == scope.row.registeredJbqCount">
{{ scope.row.earTagCount || '0' }}
<span v-if="getEarTagCount(scope.row.id) == getTotalDeviceCount(scope.row.id)">
{{ getEarTagCount(scope.row.id) }}
</span>
<span style="color: red" v-else>
{{ scope.row.earTagCount || '0' }}
{{ getEarTagCount(scope.row.id) }}
</span>
</template>
</el-table-column>
@@ -105,10 +105,10 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import baseSearch from '@/components/common/searchCustom/index.vue';
import { inspectionList, downloadZip } from '@/api/abroad.js';
import { inspectionList, downloadZip, pageDeviceList } from '@/api/abroad.js';
const router = useRouter();
const route = useRoute();
@@ -122,6 +122,7 @@ const form = reactive({
const data = reactive({
rows: [],
total: 20,
deviceCounts: {}, // 存储每个订单的设备数量 {orderId: {host: 0, ear: 0, collar: 0, total: 0}}
});
const formItemList = reactive([
{
@@ -166,6 +167,63 @@ const formItemList = reactive([
},
]);
// 获取指定订单的设备数量
const getDeviceCounts = async (deliveryId) => {
try {
console.log('=== 获取订单设备数量deliveryId:', deliveryId);
// 获取所有设备类型的数据
const [hostRes, earRes, collarRes] = await Promise.all([
pageDeviceList({ pageNum: 1, pageSize: 100, deliveryId: parseInt(deliveryId), deviceType: 1 }),
pageDeviceList({ pageNum: 1, pageSize: 100, deliveryId: parseInt(deliveryId), deviceType: 2 }),
pageDeviceList({ pageNum: 1, pageSize: 100, deliveryId: parseInt(deliveryId), deviceType: 4 })
]);
const hostCount = hostRes.code === 200 ? hostRes.data.length : 0;
const earCount = earRes.code === 200 ? earRes.data.length : 0;
const collarCount = collarRes.code === 200 ? collarRes.data.length : 0;
const totalCount = hostCount + earCount + collarCount;
console.log('=== 设备数量统计:', {
deliveryId,
hostCount,
earCount,
collarCount,
totalCount
});
// 存储设备数量
data.deviceCounts[deliveryId] = {
host: hostCount,
ear: earCount,
collar: collarCount,
total: totalCount
};
return {
host: hostCount,
ear: earCount,
collar: collarCount,
total: totalCount
};
} catch (error) {
console.error('获取设备数量失败:', error);
return { host: 0, ear: 0, collar: 0, total: 0 };
}
};
// 获取订单的设备总数
const getTotalDeviceCount = (deliveryId) => {
const counts = data.deviceCounts[deliveryId];
return counts ? counts.total : 0;
};
// 获取订单的耳标数量
const getEarTagCount = (deliveryId) => {
const counts = data.deviceCounts[deliveryId];
return counts ? counts.ear : 0;
};
const searchFrom = () => {
form.pageNum = 1;
getDataList();
@@ -200,12 +258,23 @@ const getDataList = () => {
console.log('查询参数:', params);
inspectionList(params)
.then((ret) => {
.then(async (ret) => {
console.log('入境检疫列表返回结果:', ret);
data.rows = ret.data.rows;
data.total = ret.data.total;
dataListLoading.value = false;
// 为每个订单获取设备数量
if (ret.data.rows && ret.data.rows.length > 0) {
console.log('=== 开始为每个订单获取设备数量');
for (const row of ret.data.rows) {
if (row.id) {
await getDeviceCounts(row.id);
}
}
console.log('=== 所有订单设备数量获取完成');
}
// 调试:检查第一行数据的字段
if (ret.data.rows && ret.data.rows.length > 0) {
const firstRow = ret.data.rows[0];

View File

@@ -29,7 +29,7 @@
<el-descriptions-item label="送达目的地:">{{ data.baseInfo.endLocation || '-' }}</el-descriptions-item>
<el-descriptions-item label="预计送达时间:">{{ data.baseInfo.estimatedDeliveryTime || '-' }}</el-descriptions-item>
<el-descriptions-item label="创建时间:">{{ data.baseInfo.createTime || '' }}</el-descriptions-item>
<el-descriptions-item label="登记设备数量:">{{ data.baseInfo.registeredJbqCount || '-' }} </el-descriptions-item>
<el-descriptions-item label="登记设备数量:">{{ totalRegisteredDevices }} </el-descriptions-item>
<el-descriptions-item label="状态:">
<el-tag :type="data.baseInfo.status === 2 ? 'success' : 'warning'">{{ getStatusText(data.baseInfo.status) }}</el-tag>
</el-descriptions-item>
@@ -64,7 +64,7 @@
<span class="red">{{ item.warningTypeDesc }}</span>
</el-descriptions-item>
<el-descriptions-item label="预警时间:">{{ item.warningTime || '--' }}</el-descriptions-item>
<el-descriptions-item label="智能耳标数:"> {{ data.baseInfo.registeredJbqCount || '--' }} </el-descriptions-item>
<el-descriptions-item label="智能耳标数:"> {{ totalRegisteredDevices }} </el-descriptions-item>
<el-descriptions-item label="车内盘点数量:"> {{ item.inventoryJbqCount || '--' }} </el-descriptions-item>
</template>
<template v-if="item.warningType == 3">
@@ -214,12 +214,12 @@
</el-descriptions-item>
</el-descriptions>
</div>
<!-- <div class="ear-box">
<div class="ear-box">
<div class="title">智能主机</div>
<el-table
:data="data.collarRows"
:data="data.hostRows"
border
v-loading="data.collarDataListLoading"
v-loading="data.hostDataListLoading"
element-loading-text="数据加载中..."
style="width: 100%"
>
@@ -238,23 +238,13 @@
</el-table-column>
<el-table-column label="操作" prop="">
<template #default="scope">
<el-button link type="primary" @click="collarLogClick(scope.row)">日志</el-button>
<el-button link type="primary" @click="collarTrackClick(scope.row)">运动轨迹</el-button>
<el-button link type="primary" @click="hostLogClick(scope.row)">日志</el-button>
<el-button link type="primary" @click="hostTrackClick(scope.row)">运动轨迹</el-button>
<el-button link type="primary" @click="hostLocationClick(scope.row)">定位</el-button>
</template>
</el-table-column>
</el-table>
<el-descriptions :column="1">
<el-descriptions-item label="主机编号:">
{{ data.serverIds }}
<el-button type="primary" style="margin-left: 20px" size="small" @click="locationClick(item)" v-if="data.serverIds"
>查看主机定位</el-button
>
<el-button type="primary" style="margin-left: 20px" size="small" @click="trackClick(data.serverIds)" v-if="data.serverIds"
>查看运动轨迹</el-button
>
</el-descriptions-item>
</el-descriptions>
</div> -->
</div>
<div class="ear-box">
<div class="title">智能项圈</div>
<el-table
@@ -271,8 +261,8 @@
<el-table-column label="步数" prop="steps">
<template #default="scope"> {{ scope.row.steps || scope.row.walkSteps || '-' }}</template>
</el-table-column>
<el-table-column label="设备温度" prop="temperature">
<template #default="scope"> {{ scope.row.temperature || scope.row.deviceTemp || '-' }} </template>
<el-table-column label="设备温度" prop="deviceTemp">
<template #default="scope"> {{ scope.row.deviceTemp || scope.row.temperature || '-' }} </template>
</el-table-column>
<el-table-column label="数据最后更新时间" prop="time">
<template #default="scope"> {{ scope.row.time || scope.row.updateTime || scope.row.createTime || '-' }}</template>
@@ -295,8 +285,9 @@
<div class="title">智能耳标</div>
<el-table :data="data.rows" border v-loading="data.dataListLoading" element-loading-text="数据加载中..." style="width: 100%">
<el-table-column label="智能耳标编号" prop="deviceId"></el-table-column>
<el-table-column label="设备电量" prop="deviceVoltage">
<template #default="scope"> {{ scope.row.deviceVoltage || scope.row.battery || '-' }}% </template>
<el-table-column label="设备电量" prop="battery">
<template #default="scope"> {{ scope.row.battery || scope.row.deviceVoltage || '-' }}% </template>
</el-table-column>
<el-table-column label="步数" prop="walkSteps">
<template #default="scope"> {{ scope.row.walkSteps || scope.row.steps || '-' }}</template>
@@ -310,6 +301,7 @@
<el-table-column label="操作" prop="">
<template #default="scope">
<el-button link type="primary" @click="earLogClick(scope.row)">日志</el-button>
<el-button link type="primary" @click="earTrackClick(scope.row)">运动轨迹</el-button>
</template>
</el-table-column>
</el-table>
@@ -440,7 +432,7 @@
<!-- 项圈日志 -->
<el-dialog v-model="data.collarDialogVisible" title="设备日志" style="width: 900px; padding-bottom: 20px">
<el-table :data="data.collarLogRows" border v-loading="data.logListLoading" element-loading-text="数据加载中..." style="width: 100%">
<el-table-column label="智能项圈编号" prop="sn"></el-table-column>
<el-table-column label="智能项圈编号" prop="deviceId"></el-table-column>
<el-table-column label="设备电量" prop="battery">
<template #default="scope"> {{ scope.row.battery || scope.row.deviceVoltage || '-' }}% </template>
</el-table-column>
@@ -466,16 +458,42 @@
@pagination="getCollarLogList"
/>
</el-dialog>
<!-- 智能主机日志 -->
<el-dialog v-model="data.hostLogDialogVisible" title="智能主机日志" style="width: 900px; padding-bottom: 20px">
<el-table :data="data.hostLogRows" border v-loading="data.logListLoading" element-loading-text="数据加载中..." style="width: 100%">
<el-table-column label="智能主机编号" prop="deviceId"></el-table-column>
<el-table-column label="设备电量" prop="deviceVoltage">
<template #default="scope"> {{ scope.row.deviceVoltage || scope.row.battery || '-' }}% </template>
</el-table-column>
<el-table-column label="步数" prop="walkSteps">
<template #default="scope"> {{ scope.row.walkSteps || scope.row.steps || '-' }}</template>
</el-table-column>
<el-table-column label="设备温度" prop="deviceTemp">
<template #default="scope"> {{ scope.row.deviceTemp || scope.row.temperature || '-' }} </template>
</el-table-column>
<el-table-column label="小时时间" prop="hourTime" width="200">
<template #default="scope"> {{ scope.row.hourTime || '-' }}</template>
</el-table-column>
<el-table-column label="数据最后更新时间" prop="updateTime" width="200">
<template #default="scope"> {{ scope.row.updateTime || scope.row.createTime || '-' }}</template>
</el-table-column>
<el-table-column label="操作" prop="">
<template #default="scope">
<el-button link type="primary" @click="hostLocationClick(scope.row)">定位</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
<TrackDialog ref="TrackDialogRef" />
</section>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
import { ref, reactive, onMounted, computed } from 'vue';
import { useRoute } from 'vue-router';
import { ElMessage } from 'element-plus';
import { earList, hostLocation, hostTrack, waybillDetail, collarList, collarLogList, earLogList, testDeliveryDevices, pageDeviceList } from '@/api/abroad.js';
import { earList, hostLocation, hostTrack, waybillDetail, collarList, collarLogList, earLogList, testDeliveryDevices, pageDeviceList, getEarTagLogs, getCollarLogs, getHostLogs, getEarTagTrajectory, getCollarTrajectory, getHostTrajectory } from '@/api/abroad.js';
import startIcon from '../../assets/images/qi.png';
import endIcon from '../../assets/images/zhong.png';
import TrackDialog from '../hardware/trackDialog.vue';
@@ -536,11 +554,18 @@ const data = reactive({
earLogRows: [],
earLogDialogVisible: false,
collarDialogVisible: false,
hostLogDialogVisible: false,
earLogTotal: 0,
collarLogRows: [],
collarLogTotal: 0,
hostLogRows: [],
hostLogTotal: 0,
deviceId: '', // 耳标编号
sn: '', // 项圈编号
// 智能主机相关
hostDataListLoading: false,
hostRows: [],
hostTotal: 0,
});
const form = reactive({
pageNum: 1,
@@ -593,13 +618,15 @@ const getDetail = () => {
.catch(() => {});
};
// 获取智能主机信息
const getHostDeviceInfo = () => {
// 智能主机列表查询
const getHostList = () => {
if (!route.query.id) {
console.warn('=== 警告deliveryId为空跳过主机设备查询');
console.warn('=== 警告deliveryId为空跳过主机列表查询');
data.hostDataListLoading = false;
return;
}
data.hostDataListLoading = true;
pageDeviceList({
pageNum: 1,
pageSize: 100, // 获取所有主机设备
@@ -608,10 +635,14 @@ const getHostDeviceInfo = () => {
})
.then((res) => {
console.log('=== 主机设备API返回结果:', res);
data.hostDataListLoading = false;
if (res.code === 200) {
console.log('=== 主机设备数据:', res.data);
// 新API返回的是数组格式过滤出智能主机设备
const hostDevices = res.data.filter(device => device.deviceType === 1 || device.deviceType === '1');
data.hostRows = hostDevices || [];
data.hostTotal = hostDevices.length || 0;
if (hostDevices.length > 0) {
// 如果有主机设备,取第一个作为主要主机
data.serverIds = hostDevices[0].deviceId || hostDevices[0].sn || '';
@@ -619,17 +650,31 @@ const getHostDeviceInfo = () => {
} else {
data.serverIds = '';
}
console.log('=== 设置后的hostRows:', data.hostRows);
console.log('=== 设置后的hostTotal:', data.hostTotal);
} else {
console.warn('获取主机设备信息失败:', res.msg);
data.hostRows = [];
data.hostTotal = 0;
data.serverIds = '';
}
})
.catch((err) => {
console.error('获取主机设备信息异常:', err);
data.hostDataListLoading = false;
data.hostRows = [];
data.hostTotal = 0;
data.serverIds = '';
});
};
// 获取智能主机信息(保留原有功能)
const getHostDeviceInfo = () => {
// 现在直接调用getHostList来获取主机信息
getHostList();
};
// 查看主机定位
const locationClick = (item) => {
getHostLocation(item);
@@ -728,10 +773,72 @@ const getEarList = () => {
});
};
const earLogClick = (row) => {
console.log('=== 智能耳标日志点击 ===');
console.log('设备信息:', row);
data.deviceId = row.deviceId || row.sn || '';
data.earLogDialogVisible = true;
getEarLogList();
// 调用新的API获取60分钟间隔的日志数据
getEarTagLogs({
deviceId: data.deviceId,
deliveryId: parseInt(route.query.id)
}).then((res) => {
console.log('=== 智能耳标日志API返回结果:', res);
if (res.code === 200) {
// 新API返回的是按60分钟分组的日志数据
data.earLogRows = res.data || [];
data.earLogTotal = res.data.length || 0;
console.log('=== 设置后的earLogRows:', data.earLogRows);
console.log('=== 设置后的earLogTotal:', data.earLogTotal);
} else {
ElMessage.error(res.msg || '获取智能耳标日志失败');
data.earLogRows = [];
data.earLogTotal = 0;
}
}).catch((error) => {
console.error('获取智能耳标日志异常:', error);
ElMessage.error('获取智能耳标日志失败');
data.earLogRows = [];
data.earLogTotal = 0;
});
};
// 智能耳标运动轨迹
const earTrackClick = (row) => {
console.log('=== 智能耳标运动轨迹点击 ===');
console.log('设备信息:', row);
// 调用新的API获取60分钟间隔的轨迹数据
getEarTagTrajectory({
deviceId: row.deviceId || row.sn || '',
deliveryId: parseInt(route.query.id)
}).then((res) => {
console.log('=== 智能耳标轨迹API返回结果:', res);
if (res.code === 200 && res.data && res.data.length > 0) {
// 新API返回的是按60分钟分组的轨迹点数据
const trajectoryPoints = res.data;
console.log('=== 轨迹点数据:', trajectoryPoints);
// 使用TrackDialog显示轨迹
if (TrackDialogRef.value) {
const info = {
deliveryId: route.query.id,
deviceId: row.deviceId || row.sn || '',
type: 'order',
trajectoryPoints: trajectoryPoints // 传递轨迹点数据
};
TrackDialogRef.value.onShowTrackDialog(info);
}
} else {
ElMessage.warning('该设备暂无运动轨迹数据');
}
}).catch((error) => {
console.error('获取智能耳标轨迹异常:', error);
ElMessage.error('获取智能耳标运动轨迹失败');
});
};
// 智能项圈列表查询
const getCollarList = () => {
if (!route.query.id) {
@@ -769,9 +876,35 @@ const getCollarList = () => {
});
};
const collarLogClick = (row) => {
console.log('=== 智能项圈日志点击 ===');
console.log('设备信息:', row);
data.sn = row.sn || row.deviceId || '';
data.collarDialogVisible = true;
getCollarLogList();
// 调用新的API获取60分钟间隔的日志数据
getCollarLogs({
deviceId: data.sn,
deliveryId: parseInt(route.query.id)
}).then((res) => {
console.log('=== 智能项圈日志API返回结果:', res);
if (res.code === 200) {
// 新API返回的是按60分钟分组的日志数据
data.collarLogRows = res.data || [];
data.collarLogTotal = res.data.length || 0;
console.log('=== 设置后的collarLogRows:', data.collarLogRows);
console.log('=== 设置后的collarLogTotal:', data.collarLogTotal);
} else {
ElMessage.error(res.msg || '获取智能项圈日志失败');
data.collarLogRows = [];
data.collarLogTotal = 0;
}
}).catch((error) => {
console.error('获取智能项圈日志异常:', error);
ElMessage.error('获取智能项圈日志失败');
data.collarLogRows = [];
data.collarLogTotal = 0;
});
};
const handler = ({ BMap, map }) => {
// 自动获取展示的比例
@@ -855,16 +988,123 @@ const getCollarLogList = () => {
};
// 查看运动轨迹
const collarTrackClick = (row) => {
if (TrackDialogRef.value) {
const info = {
deliveryId: route.query.id,
deviceId: row.sn || row.deviceId || '',
type: 'order',
};
TrackDialogRef.value.onShowTrackDialog(info);
}
console.log('=== 智能项圈运动轨迹点击 ===');
console.log('设备信息:', row);
// 调用新的API获取60分钟间隔的轨迹数据
getCollarTrajectory({
deviceId: row.sn || row.deviceId || '',
deliveryId: parseInt(route.query.id)
}).then((res) => {
console.log('=== 智能项圈轨迹API返回结果:', res);
if (res.code === 200 && res.data && res.data.length > 0) {
// 新API返回的是按60分钟分组的轨迹点数据
const trajectoryPoints = res.data;
console.log('=== 轨迹点数据:', trajectoryPoints);
// 使用TrackDialog显示轨迹
if (TrackDialogRef.value) {
const info = {
deliveryId: route.query.id,
deviceId: row.sn || row.deviceId || '',
type: 'order',
trajectoryPoints: trajectoryPoints // 传递轨迹点数据
};
TrackDialogRef.value.onShowTrackDialog(info);
}
} else {
ElMessage.warning('该设备暂无运动轨迹数据');
}
}).catch((error) => {
console.error('获取智能项圈轨迹异常:', error);
ElMessage.error('获取智能项圈运动轨迹失败');
});
};
// 智能主机操作函数
const hostLogClick = (row) => {
console.log('=== 智能主机日志点击 ===');
console.log('设备信息:', row);
data.deviceId = row.deviceId || row.sn || '';
data.hostLogDialogVisible = true;
// 调用新的API获取60分钟间隔的日志数据
getHostLogs({
deviceId: data.deviceId,
deliveryId: parseInt(route.query.id)
}).then((res) => {
console.log('=== 智能主机日志API返回结果:', res);
if (res.code === 200) {
// 新API返回的是按60分钟分组的日志数据
data.hostLogRows = res.data || [];
data.hostLogTotal = res.data.length || 0;
console.log('=== 设置后的hostLogRows:', data.hostLogRows);
console.log('=== 设置后的hostLogTotal:', data.hostLogTotal);
} else {
ElMessage.error(res.msg || '获取智能主机日志失败');
data.hostLogRows = [];
data.hostLogTotal = 0;
}
}).catch((error) => {
console.error('获取智能主机日志异常:', error);
ElMessage.error('获取智能主机日志失败');
data.hostLogRows = [];
data.hostLogTotal = 0;
});
};
const hostTrackClick = (row) => {
console.log('=== 智能主机运动轨迹点击 ===');
console.log('设备信息:', row);
// 调用新的API获取60分钟间隔的轨迹数据
getHostTrajectory({
deviceId: row.deviceId || row.sn || '',
deliveryId: parseInt(route.query.id)
}).then((res) => {
console.log('=== 智能主机轨迹API返回结果:', res);
if (res.code === 200 && res.data && res.data.length > 0) {
// 新API返回的是按60分钟分组的轨迹点数据
const trajectoryPoints = res.data;
console.log('=== 轨迹点数据:', trajectoryPoints);
// 使用TrackDialog显示轨迹
if (TrackDialogRef.value) {
const info = {
deliveryId: route.query.id,
deviceId: row.deviceId || row.sn || '',
type: 'order',
trajectoryPoints: trajectoryPoints // 传递轨迹点数据
};
TrackDialogRef.value.onShowTrackDialog(info);
}
} else {
ElMessage.warning('该设备暂无运动轨迹数据');
}
}).catch((error) => {
console.error('获取智能主机轨迹异常:', error);
ElMessage.error('获取智能主机运动轨迹失败');
});
};
const hostLocationClick = (row) => {
data.center.lng = row.longitude;
data.center.lat = row.latitude;
data.updateTime = row.updateTime || row.createTime || '';
data.dialogVisible = true;
};
// 状态文本转换
// 计算所有绑定设备的总数
const totalRegisteredDevices = computed(() => {
const hostCount = data.hostTotal || 0;
const earCount = data.total || 0;
const collarCount = data.collarTotal || 0;
const total = hostCount + earCount + collarCount;
console.log('=== 计算设备总数 - 主机:', hostCount, '耳标:', earCount, '项圈:', collarCount, '总计:', total);
return total;
});
const getStatusText = (status) => {
const statusMap = {
1: '待装车',
@@ -901,6 +1141,7 @@ onMounted(() => {
});
getDetail(); // 查详情
getHostList(); // 主机列表查询
getEarList(); // 耳标列表查询
getCollarList(); // 项圈类别查询
});

View File

@@ -46,13 +46,9 @@ const form = reactive({
pageSize: 20,
pageNum: 1,
total: 0,
obj:{
deviceId: '',
orgId: 385082,
type: '',
subtype: ''
}
deviceId: '',
startNo: '',
endNo: '',
});
// 计算电量百分比3V为100%2.4V为0%
@@ -120,6 +116,7 @@ const searchClick = async () => {
};
const resetClick = async (el) => {
form.pageNum = 1;
form.deviceId = '';
form.endNo = '';
form.startNo = '';
el.resetFields();

View File

@@ -374,7 +374,8 @@
<script setup>
import { ref, reactive, onMounted, nextTick } from 'vue';
import { hostList, orderLoadDetail, orderLoadSave } from '@/api/shipping.js';
import { hostList, orderLoadDetail, orderLoadSave, testOrderDevices, updateDeviceDeliveryId, updateDeviceWeights, getOrderHostDevice } from '@/api/shipping.js';
import { pageDeviceList } from '@/api/abroad.js';
import { useUserStore } from '../../store/user';
const userStore = useUserStore();
@@ -463,21 +464,22 @@ const autoFillFormData = (apiData) => {
// 查询详情
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);
// 使用新的统一设备接口获取智能耳标和智能项圈
getDevicesByOrder();
// 检查订单绑定的智能主机
checkOrderHostDevice();
} else {
console.error('getOrderDetail API 调用失败:', res);
}
@@ -485,29 +487,168 @@ const getOrderDetail = () => {
console.error('getOrderDetail API 调用异常:', error);
});
};
// 使用统一设备接口获取智能耳标和智能项圈
const getDevicesByOrder = () => {
if (!data.deliveryId) {
console.warn('deliveryId为空无法获取设备信息');
return;
}
console.log('=== 开始获取订单设备信息deliveryId:', data.deliveryId);
// 先调用测试接口检查订单设备数据
testOrderDevices(parseInt(data.deliveryId)).then((res) => {
console.log('=== 测试接口返回结果:', res);
if (res.code === 200) {
console.log('=== 订单设备数据:', res.data);
console.log('=== 设备总数:', res.data.totalDevices);
console.log('=== 设备列表:', res.data.devices);
}
}).catch((error) => {
console.error('=== 测试接口调用失败:', error);
});
// 获取智能耳标 (deviceType: 2)
pageDeviceList({
pageNum: 1,
pageSize: 100,
deliveryId: parseInt(data.deliveryId),
deviceType: 2, // 智能耳标
}).then((res) => {
console.log('=== 智能耳标设备API返回结果:', res);
console.log('=== API返回的原始数据:', res.data);
console.log('=== 数据类型:', typeof res.data, '是否为数组:', Array.isArray(res.data));
if (res.code === 200) {
if (res.data && Array.isArray(res.data)) {
console.log('=== 原始设备数据:', res.data);
// 过滤出智能耳标设备并转换为需要的格式
const earDevices = res.data.filter(device => {
console.log('=== 检查设备:', device, 'deviceType:', device.deviceType, '类型:', typeof device.deviceType);
return device.deviceType === 2 || device.deviceType === '2';
});
console.log('=== 过滤后的智能耳标设备:', earDevices);
data.deliveryDevices = earDevices.map(device => ({
deviceId: device.deviceId,
bindWeight: device.bindWeight || '', // 如果有绑定重量则使用,否则为空
}));
console.log('=== 设置后的智能耳标设备:', data.deliveryDevices);
console.log('=== data.deliveryDevices长度:', data.deliveryDevices.length);
} else {
console.warn('API返回的数据不是数组格式:', res.data);
data.deliveryDevices = [];
}
} else {
console.error('获取智能耳标设备失败:', res.msg);
data.deliveryDevices = [];
}
}).catch((error) => {
console.error('获取智能耳标设备异常:', error);
data.deliveryDevices = [];
});
// 获取智能项圈 (deviceType: 4)
pageDeviceList({
pageNum: 1,
pageSize: 100,
deliveryId: parseInt(data.deliveryId),
deviceType: 4, // 智能项圈
}).then((res) => {
console.log('=== 智能项圈设备API返回结果:', res);
console.log('=== API返回的原始数据:', res.data);
console.log('=== 数据类型:', typeof res.data, '是否为数组:', Array.isArray(res.data));
if (res.code === 200) {
if (res.data && Array.isArray(res.data)) {
console.log('=== 原始设备数据:', res.data);
// 过滤出智能项圈设备并转换为需要的格式
const collarDevices = res.data.filter(device => {
console.log('=== 检查设备:', device, 'deviceType:', device.deviceType, '类型:', typeof device.deviceType);
return device.deviceType === 4 || device.deviceType === '4';
});
console.log('=== 过滤后的智能项圈设备:', collarDevices);
data.xqDevices = collarDevices.map(device => ({
deviceId: device.deviceId,
bindWeight: device.bindWeight || '', // 如果有绑定重量则使用,否则为空
}));
console.log('=== 设置后的智能项圈设备:', data.xqDevices);
console.log('=== data.xqDevices长度:', data.xqDevices.length);
} else {
console.warn('API返回的数据不是数组格式:', res.data);
data.xqDevices = [];
}
} else {
console.error('获取智能项圈设备失败:', res.msg);
data.xqDevices = [];
}
}).catch((error) => {
console.error('获取智能项圈设备异常:', error);
data.xqDevices = [];
});
};
// 智能主机远程搜索
const hostRemoteMethod = (e) => {
data.hostNumber = e;
data.hostPageNum = 1;
getHostList();
};
// 主机列表
// 主机列表 - 使用统一设备接口
const getHostList = () => {
data.hostLoading = true;
const params = {
// 使用统一设备接口获取智能主机 (deviceType: 1)
// 获取所有可用的智能主机(没有绑定到特定订单的)
pageDeviceList({
pageNum: data.hostPageNum,
pageSize: 10,
deviceId: data.hostNumber,
};
hostList(params)
.then((res) => {
data.hostLoading = false;
data.hostOptions = res.data.rows;
data.hostTotal = res.data.total;
})
.catch(() => {
data.hostLoading = false;
});
deviceType: 1, // 智能主机
// 如果有搜索条件可以根据deviceId搜索
...(data.hostNumber ? { deviceId: data.hostNumber } : {}),
// 不传递deliveryId获取所有可用的主机
}).then((res) => {
console.log('=== 智能主机设备API返回结果:', res);
data.hostLoading = false;
if (res.code === 200) {
// 过滤出智能主机设备
const hostDevices = res.data.filter(device => device.deviceType === 1 || device.deviceType === '1');
// 转换为下拉选择需要的格式
data.hostOptions = hostDevices.map(device => ({
id: device.deviceId,
deviceId: device.deviceId,
deviceType: device.deviceType,
deviceTypeName: device.deviceTypeName || '智能主机',
battery: device.battery,
deviceVoltage: device.deviceVoltage,
deviceTemp: device.deviceTemp,
latitude: device.latitude,
longitude: device.longitude,
updateTime: device.updateTime,
createTime: device.createTime,
}));
data.hostTotal = hostDevices.length;
console.log('=== 设置后的智能主机选项:', data.hostOptions);
} else {
console.error('获取智能主机设备失败:', res.msg);
data.hostOptions = [];
data.hostTotal = 0;
}
}).catch((error) => {
console.error('获取智能主机设备异常:', error);
data.hostLoading = false;
data.hostOptions = [];
data.hostTotal = 0;
});
};
// 选择智能主机分页
const hostHandleCurrentChange = (val) => {
@@ -620,6 +761,7 @@ const onClickSave = () => {
// 确保 deliveryId 是数字类型
const saveData = { ...ruleForm };
console.log('保存时的 deliveryId:', saveData.deliveryId, '类型:', typeof saveData.deliveryId);
console.log('选择的智能主机:', saveData.serverDeviceSn);
if (saveData.deliveryId) {
const parsedId = parseInt(saveData.deliveryId);
@@ -636,23 +778,167 @@ const onClickSave = () => {
return;
}
// 先保存装车信息
orderLoadSave(saveData).then((res) => {
data.saveLoading = false;
if (res.code === 200) {
ElMessage({
message: res.msg,
type: 'success',
});
emits('success');
if (formDataRef.value) {
formDataRef.value.resetFields();
console.log('装车信息保存成功:', res);
// 如果选择了智能主机需要更新主机的delivery_id
if (saveData.serverDeviceSn) {
updateHostDeliveryId(saveData.serverDeviceSn, saveData.deliveryId);
} else {
// 没有选择主机,直接更新设备重量
updateDeviceWeightsLocal();
}
data.dialogVisible = false;
} else {
ElMessage.error(res.msg);
data.saveLoading = false;
}
}).catch((error) => {
console.error('保存装车信息失败:', error);
ElMessage.error('保存失败');
data.saveLoading = false;
});
};
// 更新智能主机的delivery_id
const updateHostDeliveryId = (hostDeviceId, deliveryId) => {
console.log('=== 开始更新智能主机delivery_id ===');
console.log('主机设备ID:', hostDeviceId);
console.log('订单ID:', deliveryId);
// 调用后端接口更新主机的delivery_id
updateDeviceDeliveryId({
deviceId: hostDeviceId,
deliveryId: deliveryId
}).then((res) => {
if (res.code === 200) {
console.log('智能主机delivery_id更新成功:', res);
// 更新设备重量
updateDeviceWeightsLocal();
} else {
console.error('智能主机delivery_id更新失败:', res.msg);
ElMessage.error('智能主机绑定失败: ' + res.msg);
data.saveLoading = false;
}
}).catch((error) => {
console.error('智能主机delivery_id更新异常:', error);
ElMessage.error('智能主机绑定失败');
data.saveLoading = false;
});
};
// 更新设备重量
const updateDeviceWeightsLocal = (customDevices = null) => {
console.log('=== 开始更新设备重量 ===');
// 收集所有设备的重量信息
const devices = [];
if (customDevices && customDevices.length > 0) {
// 如果传入了自定义设备列表,使用它
devices.push(...customDevices);
} else {
// 否则收集当前表单中的设备重量
// 添加智能耳标的重量
data.deliveryDevices.forEach(device => {
if (device.bindWeight && device.bindWeight.trim() !== '') {
devices.push({
deviceId: device.deviceId,
weight: parseFloat(device.bindWeight)
});
}
});
// 添加智能项圈的重量
data.xqDevices.forEach(device => {
if (device.bindWeight && device.bindWeight.trim() !== '') {
devices.push({
deviceId: device.deviceId,
weight: parseFloat(device.bindWeight)
});
}
});
}
console.log('需要更新重量的设备:', devices);
if (devices.length === 0) {
console.log('没有设备需要更新重量,直接完成保存');
completeSave();
return;
}
// 调用后端接口批量更新设备重量
updateDeviceWeights({
deliveryId: parseInt(data.deliveryId),
devices: devices
}).then((res) => {
if (res.code === 200) {
console.log('设备重量更新成功:', res);
completeSave();
} else {
console.error('设备重量更新失败:', res.msg);
ElMessage.error('设备重量更新失败: ' + res.msg);
data.saveLoading = false;
}
}).catch((error) => {
console.error('设备重量更新异常:', error);
ElMessage.error('设备重量更新失败');
data.saveLoading = false;
});
};
// 检查订单绑定的智能主机
const checkOrderHostDevice = () => {
if (!data.deliveryId) {
console.warn('deliveryId为空无法检查订单绑定的智能主机');
return;
}
console.log('=== 检查订单绑定的智能主机 ===');
console.log('订单ID:', data.deliveryId);
console.log('调用API前的ruleForm.serverDeviceSn:', ruleForm.serverDeviceSn);
getOrderHostDevice(parseInt(data.deliveryId)).then((res) => {
console.log('=== 订单绑定主机查询结果:', res);
console.log('API返回的完整响应:', JSON.stringify(res, null, 2));
if (res.code === 200) {
if (res.data) {
// 订单已绑定智能主机,自动填充
console.log('订单已绑定智能主机:', res.data.deviceId);
console.log('设置前的ruleForm.serverDeviceSn:', ruleForm.serverDeviceSn);
ruleForm.serverDeviceSn = res.data.deviceId;
console.log('设置后的ruleForm.serverDeviceSn:', ruleForm.serverDeviceSn);
console.log('自动填充智能主机成功');
} else {
// 订单未绑定智能主机
console.log('订单未绑定智能主机');
ruleForm.serverDeviceSn = '';
console.log('清空智能主机选择');
}
} else {
console.error('查询订单绑定主机失败:', res.msg);
}
}).catch((error) => {
console.error('查询订单绑定主机异常:', error);
});
};
// 完成保存操作
const completeSave = () => {
data.saveLoading = false;
ElMessage({
message: '保存成功',
type: 'success',
});
emits('success');
if (formDataRef.value) {
formDataRef.value.resetFields();
}
data.dialogVisible = false;
};
// 取消
const handleClose = () => {
data.dialogVisible = false;
@@ -674,11 +960,16 @@ const onShowDialog = (row, apiData = null) => {
// 如果提供了API数据直接填充表单
if (apiData) {
autoFillFormData(apiData);
// 获取设备信息
getDevicesByOrder();
// 检查订单绑定的智能主机
checkOrderHostDevice();
} else {
// 否则从服务器获取详情
getOrderDetail();
}
// 获取智能主机列表(未绑定的)
getHostList();
});
}

View File

@@ -60,12 +60,12 @@
</el-table-column>
<el-table-column label="已分配设备数量" prop="bindJbqCount">
<template #default="scope">
{{ scope.row.bindJbqCount || '0' }}
{{ getTotalDeviceCount(scope.row.id) }}
</template>
</el-table-column>
<el-table-column label="已佩戴设备数量" prop="wareCount">
<template #default="scope">
<span :style="{ color: scope.row.bindJbqCount == scope.row.wareCount ? '' : 'red' }">
<span :style="{ color: getTotalDeviceCount(scope.row.id) == scope.row.wareCount ? '' : 'red' }">
{{ scope.row.wareCount || '0' }}
</span>
</template>
@@ -92,15 +92,15 @@
<el-table-column label="登记设备数量" prop="registeredJbqCount" width="120" :key="`count-${data.forceUpdate}`">
<template #default="scope">
<!-- 调试信息 -->
<div style="display: none;">{{ console.log('设备数量调试:', { registeredJbqCount: scope.row.registeredJbqCount }) }}</div>
<span :key="`count-span-${scope.row.id}-${data.forceUpdate}`">{{ scope.row.registeredJbqCount || '0' }}</span>
<div style="display: none;">{{ console.log('设备数量调试:', { registeredJbqCount: scope.row.registeredJbqCount, totalDeviceCount: getTotalDeviceCount(scope.row.id) }) }}</div>
<span :key="`count-span-${scope.row.id}-${data.forceUpdate}`">{{ getTotalDeviceCount(scope.row.id) }}</span>
</template>
</el-table-column>
<el-table-column label="车内盘点耳标数量" prop="earTagCount" width="140" :key="`ear-tag-${data.forceUpdate}`">
<template #default="scope">
<!-- 调试信息 -->
<div style="display: none;">{{ console.log('耳标数量调试:', { earTagCount: scope.row.earTagCount }) }}</div>
<span :key="`ear-tag-span-${scope.row.id}-${data.forceUpdate}`">{{ scope.row.earTagCount || '0' }}</span>
<div style="display: none;">{{ console.log('耳标数量调试:', { earTagCount: scope.row.earTagCount, actualEarTagCount: getEarTagCount(scope.row.id) }) }}</div>
<span :key="`ear-tag-span-${scope.row.id}-${data.forceUpdate}`">{{ getEarTagCount(scope.row.id) }}</span>
</template>
</el-table-column>
<el-table-column label="车牌号" prop="licensePlate" width="120">
@@ -173,7 +173,8 @@ import { ref, reactive, onMounted, nextTick, watch } from 'vue';
import { ElMessage, ElMessageBox } from 'element-plus';
import { Picture } from '@element-plus/icons-vue';
import baseSearch from '@/components/common/searchCustom/index.vue';
import { orderList, orderDel, updateDeliveryStatus } from '@/api/shipping.js';
import { orderList, orderDel, updateDeliveryStatus, clearDeviceDeliveryId } from '@/api/shipping.js';
import { pageDeviceList } from '@/api/abroad.js';
import { getImageList, handleImageError } from '@/utils/imageUtils.js';
import OrderDialog from './orderDialog.vue';
import LookDialog from './lookDialog.vue';
@@ -250,6 +251,7 @@ const data = reactive({
dataListLoading: false,
tableKey: 0, // 用于强制重新渲染表格
forceUpdate: 0, // 用于强制更新
deviceCounts: {}, // 存储每个订单的设备数量 {orderId: {host: 0, ear: 0, collar: 0, total: 0}}
});
// 使用ref确保响应式更新
@@ -258,6 +260,63 @@ const form = reactive({
pageNum: 1,
pageSize: 10,
});
// 获取指定订单的设备数量
const getDeviceCounts = async (deliveryId) => {
try {
console.log('=== 获取装车订单设备数量deliveryId:', deliveryId);
// 获取所有设备类型的数据
const [hostRes, earRes, collarRes] = await Promise.all([
pageDeviceList({ pageNum: 1, pageSize: 100, deliveryId: parseInt(deliveryId), deviceType: 1 }),
pageDeviceList({ pageNum: 1, pageSize: 100, deliveryId: parseInt(deliveryId), deviceType: 2 }),
pageDeviceList({ pageNum: 1, pageSize: 100, deliveryId: parseInt(deliveryId), deviceType: 4 })
]);
const hostCount = hostRes.code === 200 ? hostRes.data.length : 0;
const earCount = earRes.code === 200 ? earRes.data.length : 0;
const collarCount = collarRes.code === 200 ? collarRes.data.length : 0;
const totalCount = hostCount + earCount + collarCount;
console.log('=== 装车订单设备数量统计:', {
deliveryId,
hostCount,
earCount,
collarCount,
totalCount
});
// 存储设备数量
data.deviceCounts[deliveryId] = {
host: hostCount,
ear: earCount,
collar: collarCount,
total: totalCount
};
return {
host: hostCount,
ear: earCount,
collar: collarCount,
total: totalCount
};
} catch (error) {
console.error('获取装车订单设备数量失败:', error);
return { host: 0, ear: 0, collar: 0, total: 0 };
}
};
// 获取订单的设备总数
const getTotalDeviceCount = (deliveryId) => {
const counts = data.deviceCounts[deliveryId];
return counts ? counts.total : 0;
};
// 获取订单的耳标数量
const getEarTagCount = (deliveryId) => {
const counts = data.deviceCounts[deliveryId];
return counts ? counts.ear : 0;
};
const searchFrom = () => {
console.log('=== 搜索功能被触发 ===');
form.pageNum = 1;
@@ -365,10 +424,22 @@ const getDataList = () => {
}
// 使用setTimeout确保DOM完全更新
setTimeout(() => {
setTimeout(async () => {
// 强制重新赋值,确保响应式更新
rows.value = [...res.data.rows];
data.total = res.data.total;
// 为每个订单获取设备数量
if (res.data.rows && res.data.rows.length > 0) {
console.log('=== 开始为每个装车订单获取设备数量');
for (const row of res.data.rows) {
if (row.id) {
await getDeviceCounts(row.id);
}
}
console.log('=== 所有装车订单设备数量获取完成');
}
// 更新表格key强制重新渲染
data.tableKey = Date.now();
// 强制更新
@@ -383,7 +454,7 @@ const getDataList = () => {
setTimeout(() => {
data.forceUpdate = Date.now();
console.log('二次强制更新完成');
}, 100);
}, 200);
}, 50);
})
.catch(() => {
@@ -431,14 +502,26 @@ const showDetailDialog = (row) => {
};
// 删除
const del = (id) => {
ElMessageBox.confirm('请确认是否删除', '提示', {
ElMessageBox.confirm('请确认是否删除订单删除后将同时清空该订单关联的所有智能设备的delivery_id和weight字段', '提示', {
cancelButtonText: '取消',
confirmButtonText: '确定',
type: 'warning',
}).then(() => {
orderDel(id).then(() => {
ElMessage.success('操作成功');
getDataList();
// 先清空设备的delivery_id
clearDeviceDeliveryId(id).then(() => {
console.log('设备delivery_id清空成功');
// 然后删除订单
orderDel(id).then(() => {
ElMessage.success('订单删除成功,相关设备的绑定和重量信息已清空');
getDataList();
}).catch((error) => {
console.error('删除订单失败:', error);
ElMessage.error('删除订单失败');
});
}).catch((error) => {
console.error('清空设备delivery_id失败:', error);
ElMessage.error('清空设备绑定失败');
});
});
};