初步完成轨迹
This commit is contained in:
@@ -49,10 +49,10 @@ export function inspectionList(data) {
|
||||
});
|
||||
}
|
||||
|
||||
// 查询百度鹰眼轨迹与停留点
|
||||
export function getYingyanTrack(data) {
|
||||
// 查询运单轨迹(基于车牌号,使用 OpenAPI)
|
||||
export function getDeliveryTrack(data) {
|
||||
return request({
|
||||
url: '/delivery/yingyan/track',
|
||||
url: '/delivery/track',
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
|
||||
@@ -369,14 +369,6 @@
|
||||
<el-empty description="暂无轨迹数据" :image-size="100" />
|
||||
</div>
|
||||
|
||||
<div v-if="yingyanMeta.entityName" class="track-meta-panel">
|
||||
<el-descriptions :column="3" border>
|
||||
<el-descriptions-item label="终端名称">{{ yingyanMeta.entityName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="查询开始">{{ formatTimestamp(yingyanMeta.startTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="查询结束">{{ formatTimestamp(yingyanMeta.endTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
<div v-if="latestPoint" class="latest-point-panel">
|
||||
<h4>最新定位</h4>
|
||||
<el-descriptions :column="3" border>
|
||||
@@ -461,7 +453,7 @@ import { ref, reactive, computed, nextTick, onUnmounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { Location, VideoPlay, Refresh, InfoFilled, Connection, DataLine, Loading } from '@element-plus/icons-vue';
|
||||
import { BMPGL } from '@/utils/loadBmap.js';
|
||||
import { pageDeviceList, getCollarLogs, getEarTagLogs, getHostLogs, getYingyanTrack, waybillDetail } from '@/api/abroad.js';
|
||||
import { pageDeviceList, getCollarLogs, getEarTagLogs, getHostLogs, getDeliveryTrack, waybillDetail } from '@/api/abroad.js';
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const warningData = reactive({
|
||||
@@ -510,11 +502,6 @@ const trackBMapGL = ref(null); // 保存 BMapGL 实例,避免重复加载
|
||||
const stayPoints = ref([]); // 停留点列表
|
||||
const latestPoint = ref(null); // 最新轨迹点
|
||||
const segmentStats = ref([]);
|
||||
const yingyanMeta = reactive({
|
||||
entityName: '',
|
||||
startTime: null,
|
||||
endTime: null
|
||||
});
|
||||
|
||||
// 计算属性:判断预警类型
|
||||
const isTemperatureWarning = computed(() => {
|
||||
@@ -939,16 +926,8 @@ const handleTrackClick = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
await loadYingyanTrack();
|
||||
|
||||
if (trackPath.value.length === 0) {
|
||||
// TODO: 接入新的轨迹服务
|
||||
trackLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化地图
|
||||
await nextTick();
|
||||
await initTrackMap();
|
||||
};
|
||||
|
||||
// 获取运送清单运输状态
|
||||
@@ -981,16 +960,13 @@ const getDeliveryStatus = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
// 加载百度鹰眼轨迹与停留点
|
||||
// 加载运单轨迹(基于车牌号,使用 OpenAPI)
|
||||
const loadYingyanTrack = async () => {
|
||||
stayPoints.value = [];
|
||||
trackPath.value = [];
|
||||
latestPoint.value = null;
|
||||
segmentStats.value = [];
|
||||
trackMapShow.value = false;
|
||||
yingyanMeta.entityName = '';
|
||||
yingyanMeta.startTime = null;
|
||||
yingyanMeta.endTime = null;
|
||||
|
||||
if (!warningData.deliveryId) {
|
||||
ElMessage.warning('运单ID缺失,无法查询轨迹');
|
||||
@@ -998,11 +974,10 @@ const loadYingyanTrack = async () => {
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await getYingyanTrack({ deliveryId: warningData.deliveryId });
|
||||
const res = await getDeliveryTrack({ deliveryId: warningData.deliveryId });
|
||||
console.info('[TRACK] 后端轨迹接口响应', res);
|
||||
|
||||
if (res.code === 200 && res.data) {
|
||||
segmentStats.value = Array.isArray(res.data.segmentStats) ? res.data.segmentStats : [];
|
||||
console.info('[TRACK] 分段统计', segmentStats.value);
|
||||
const rawPoints = Array.isArray(res.data.trackPoints) ? res.data.trackPoints : [];
|
||||
trackPath.value = rawPoints
|
||||
.map(item => {
|
||||
@@ -1019,30 +994,18 @@ const loadYingyanTrack = async () => {
|
||||
})
|
||||
.filter(Boolean);
|
||||
|
||||
stayPoints.value = Array.isArray(res.data.stayPoints) ? res.data.stayPoints : [];
|
||||
yingyanMeta.entityName = res.data.entityName || '';
|
||||
yingyanMeta.startTime = res.data.startTime || null;
|
||||
yingyanMeta.endTime = res.data.endTime || null;
|
||||
latestPoint.value = parseLatestPoint(res.data.latestPoint);
|
||||
console.info('[TRACK] 轨迹点数量', trackPath.value.length);
|
||||
|
||||
if (trackPath.value.length > 0) {
|
||||
trackMapShow.value = true;
|
||||
} else if (latestPoint.value) {
|
||||
trackPath.value.push({
|
||||
lng: latestPoint.value.lng,
|
||||
lat: latestPoint.value.lat,
|
||||
locTime: latestPoint.value.locTime || null,
|
||||
});
|
||||
trackMapShow.value = true;
|
||||
} else {
|
||||
ElMessage.warning('暂无有效轨迹点');
|
||||
ElMessage.warning(res.data.message || '暂无有效轨迹点');
|
||||
}
|
||||
} else {
|
||||
ElMessage.warning(res.msg || '暂无轨迹数据');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[TRACK] 加载百度鹰眼轨迹失败:', error);
|
||||
console.error('[TRACK] 加载轨迹失败:', error);
|
||||
ElMessage.error('加载轨迹数据失败');
|
||||
}
|
||||
};
|
||||
@@ -1345,9 +1308,6 @@ const handleTrackDialogClose = () => {
|
||||
trackPath.value = [];
|
||||
trackMapShow.value = false;
|
||||
stayPoints.value = [];
|
||||
yingyanMeta.entityName = '';
|
||||
yingyanMeta.startTime = null;
|
||||
yingyanMeta.endTime = null;
|
||||
};
|
||||
|
||||
// 组件卸载时清理
|
||||
|
||||
@@ -142,9 +142,17 @@
|
||||
<el-empty description="暂无轨迹数据" :image-size="100" />
|
||||
</div>
|
||||
<div v-else class="track-info">
|
||||
<el-tag type="info" style="margin-bottom: 15px;">
|
||||
轨迹点数:{{ trackPath.length }}
|
||||
</el-tag>
|
||||
<div class="track-summary">
|
||||
<el-tag type="info">轨迹点数:{{ trackPath.length }}</el-tag>
|
||||
<el-tag v-if="trackMileage" type="success">总里程:{{ trackMileage }} km</el-tag>
|
||||
<el-tag v-if="trackParkSize > 0" type="warning">停车次数:{{ trackParkSize }}</el-tag>
|
||||
</div>
|
||||
<div v-if="trackParks.length > 0" class="park-list">
|
||||
<span class="park-title">停车列表:</span>
|
||||
<span v-for="(p, idx) in trackParks" :key="idx" class="park-item">
|
||||
{{ p.name }} ({{ p.lng }}, {{ p.lat }})
|
||||
</span>
|
||||
</div>
|
||||
<div id="trackMap" style="width: 100%; height: 500px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -162,7 +170,7 @@ import baseSearch from '@/components/common/searchCustom/index.vue';
|
||||
import Pagination from '@/components/Pagination/index.vue';
|
||||
import { orderPageQuery, orderDelete, orderBatchImport } from '@/api/shipping.js';
|
||||
import { memberListByType, userAdd } from '@/api/userManage.js';
|
||||
import { getYingyanTrack, waybillDetail } from '@/api/abroad.js';
|
||||
import { getDeliveryTrack, waybillDetail } from '@/api/abroad.js';
|
||||
import { BMPGL } from '@/utils/loadBmap.js';
|
||||
import { nextTick } from 'vue';
|
||||
import OrderDialog from './orderDialog.vue';
|
||||
@@ -178,6 +186,9 @@ const fileInputRef = ref();
|
||||
const trackDialogVisible = ref(false);
|
||||
const trackLoading = ref(false);
|
||||
const trackPath = ref([]);
|
||||
const trackMileage = ref(''); // 总里程 km
|
||||
const trackParkSize = ref(0); // 停车次数
|
||||
const trackParks = ref([]); // 停车列表
|
||||
const deliveryStatus = ref(null);
|
||||
const trackMapInstance = ref(null);
|
||||
const formItemList = reactive([
|
||||
@@ -398,34 +409,86 @@ const viewTrack = async (deliveryId, status) => {
|
||||
trackDialogVisible.value = true;
|
||||
trackLoading.value = true;
|
||||
trackPath.value = [];
|
||||
trackMileage.value = '';
|
||||
trackParkSize.value = 0;
|
||||
trackParks.value = [];
|
||||
deliveryStatus.value = status;
|
||||
|
||||
try {
|
||||
const res = await getYingyanTrack({ deliveryId: deliveryId });
|
||||
const res = await getDeliveryTrack({ deliveryId: deliveryId });
|
||||
console.info('[track] response data:', res?.data);
|
||||
if (res.code === 200 && res.data) {
|
||||
const rawPoints = Array.isArray(res.data.trackPoints) ? res.data.trackPoints : [];
|
||||
trackPath.value = rawPoints
|
||||
const data = res.data;
|
||||
|
||||
// 尝试解析原始响应(兜底 trackArray/parkArray)
|
||||
let rawTrackFromResp = [];
|
||||
let rawParkFromResp = [];
|
||||
if (!Array.isArray(data.trackArray) && data.rawResponse) {
|
||||
try {
|
||||
const rawObj = JSON.parse(data.rawResponse);
|
||||
rawTrackFromResp = Array.isArray(rawObj?.result?.trackArray) ? rawObj.result.trackArray : [];
|
||||
rawParkFromResp = Array.isArray(rawObj?.result?.parkArray) ? rawObj.result.parkArray : [];
|
||||
console.info('[track] parsed rawResponse trackArray len:', rawTrackFromResp.length, 'parkArray len:', rawParkFromResp.length);
|
||||
} catch (e) {
|
||||
console.warn('解析 rawResponse 失败', e);
|
||||
}
|
||||
}
|
||||
|
||||
// 里程/停车
|
||||
trackMileage.value = data.mileage || '';
|
||||
trackParkSize.value = Number(data.parkSize || 0);
|
||||
const parkArray = Array.isArray(data.parkArray) ? data.parkArray : rawParkFromResp;
|
||||
trackParks.value = parkArray
|
||||
.map((p, idx) => {
|
||||
const lng = parseFloat(p.lon ?? p.lng ?? p.longitude ?? 0);
|
||||
const lat = parseFloat(p.lat ?? p.latitude ?? 0);
|
||||
return {
|
||||
name: `停车点${idx + 1}`,
|
||||
lng,
|
||||
lat
|
||||
};
|
||||
})
|
||||
.filter(p => !Number.isNaN(p.lng) && !Number.isNaN(p.lat) && p.lng !== 0 && p.lat !== 0);
|
||||
|
||||
// 轨迹
|
||||
const rawTrack = Array.isArray(data.trackArray)
|
||||
? data.trackArray
|
||||
: (Array.isArray(data.trackPoints) ? data.trackPoints : rawTrackFromResp);
|
||||
console.info('[track] source arrays len -> trackArray:', Array.isArray(data.trackArray) ? data.trackArray.length : 0,
|
||||
'trackPoints:', Array.isArray(data.trackPoints) ? data.trackPoints.length : 0,
|
||||
'rawTrackFromResp:', rawTrackFromResp.length);
|
||||
trackPath.value = rawTrack
|
||||
.map(item => {
|
||||
const lng = parseFloat(item.longitude ?? item.lng ?? 0);
|
||||
const lat = parseFloat(item.latitude ?? item.lat ?? 0);
|
||||
let lng = parseFloat(item.lon ?? item.lng ?? item.longitude ?? 0);
|
||||
let lat = parseFloat(item.lat ?? item.latitude ?? 0);
|
||||
// 如果疑似放大(>180/90),尝试除以600000
|
||||
if (Math.abs(lng) > 180 || Math.abs(lat) > 90) {
|
||||
lng = lng / 600000;
|
||||
lat = lat / 600000;
|
||||
}
|
||||
if (Number.isNaN(lng) || Number.isNaN(lat) || lng === 0 || lat === 0) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
lng,
|
||||
lat,
|
||||
locTime: item.locTime
|
||||
locTime: item.locTime || item.timestamp || item.utc || item.gtm || '',
|
||||
speed: item.spd || item.speed || '',
|
||||
direction: item.agl || item.direction || '',
|
||||
altitude: item.hgt || item.altitude || '',
|
||||
mileage: item.mlg || ''
|
||||
};
|
||||
})
|
||||
.filter(Boolean);
|
||||
console.info('[track] normalized trackPath len:', trackPath.value.length,
|
||||
'sample:', trackPath.value.slice(0, 3));
|
||||
|
||||
if (trackPath.value.length === 0) {
|
||||
ElMessage.warning('暂无有效轨迹点');
|
||||
ElMessage.warning(data.message || '暂无有效轨迹点');
|
||||
trackLoading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化地图
|
||||
await nextTick();
|
||||
await initTrackMap();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user