调试mk
This commit is contained in:
@@ -2212,13 +2212,105 @@
|
||||
<section-card title="物流轨迹">
|
||||
<template #extra>
|
||||
<div class="waybill-manage-page__waybill-track-actions">
|
||||
<el-button plain @click="handleWaybillTrackAction('playback')"
|
||||
<el-button
|
||||
plain
|
||||
:type="waybillTrackMode === 'playback' ? 'primary' : undefined"
|
||||
:loading="waybillTrackLoading"
|
||||
@click="handleWaybillTrackAction('playback')"
|
||||
>轨迹回放</el-button
|
||||
>
|
||||
<el-button plain @click="handleWaybillTrackAction('locate')">实时定位</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:type="waybillTrackMode === 'locate' ? 'primary' : undefined"
|
||||
:loading="waybillLocateLoading"
|
||||
@click="handleWaybillTrackAction('locate')"
|
||||
>实时定位</el-button
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<div class="waybill-manage-page__waybill-map-empty">暂无数据</div>
|
||||
<div
|
||||
v-if="waybillTrackMode === 'playback'"
|
||||
class="waybill-manage-page__waybill-track-toolbar"
|
||||
>
|
||||
<span>时间段</span>
|
||||
<el-date-picker
|
||||
v-model="waybillTrackDateRange"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="YYYY-MM-DD"
|
||||
:clearable="false"
|
||||
:disabled="waybillTrackLoading"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="waybillTrackLoading"
|
||||
@click="loadWaybillTrack"
|
||||
>查询</el-button
|
||||
>
|
||||
<span class="waybill-manage-page__waybill-track-total"
|
||||
>轨迹点 {{ waybillTrackInfo?.total || 0 }} 个</span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-if="waybillTrackMode === 'locate'"
|
||||
class="waybill-manage-page__waybill-locate"
|
||||
>
|
||||
<div v-if="waybillLocateInfo" class="waybill-manage-page__waybill-locate-meta">
|
||||
<div>
|
||||
<span>车牌号</span><strong>{{ waybillLocateInfo.vehicleNo || '-' }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>定位时间</span><strong>{{ waybillLocateInfo.locateTime || '-' }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>速度</span><strong>{{ waybillLocateInfo.speed || '-' }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>方向</span><strong>{{ waybillLocateInfo.direction || '-' }}</strong>
|
||||
</div>
|
||||
<div class="waybill-manage-page__waybill-locate-address">
|
||||
<span>地址</span><strong>{{ waybillLocateInfo.address || '-' }}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>坐标</span
|
||||
><strong
|
||||
>{{
|
||||
waybillLocateInfo.longitude != null && waybillLocateInfo.latitude != null
|
||||
? `${waybillLocateInfo.longitude}, ${waybillLocateInfo.latitude}`
|
||||
: '-'
|
||||
}}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
ref="waybillLocateMap"
|
||||
class="waybill-manage-page__waybill-locate-map"
|
||||
></div>
|
||||
<div
|
||||
v-if="!waybillLocateInfo"
|
||||
class="waybill-manage-page__waybill-map-tip"
|
||||
>
|
||||
{{ waybillLocateHint || '暂无数据' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="waybillTrackMode === 'playback'"
|
||||
class="waybill-manage-page__waybill-locate"
|
||||
>
|
||||
<div
|
||||
ref="waybillTrackMap"
|
||||
class="waybill-manage-page__waybill-locate-map waybill-manage-page__waybill-locate-map--track"
|
||||
></div>
|
||||
<div
|
||||
v-if="!(waybillTrackInfo?.points || []).length"
|
||||
class="waybill-manage-page__waybill-map-tip"
|
||||
>
|
||||
{{ waybillTrackHint || '暂无数据' }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="waybill-manage-page__waybill-map-empty">暂无数据</div>
|
||||
</section-card>
|
||||
</div>
|
||||
</template>
|
||||
@@ -3029,7 +3121,7 @@ import {
|
||||
getList as getProcessConfigList,
|
||||
getVoucherImages as getProcessConfigVoucherImages,
|
||||
} from '@/api/business/process-config';
|
||||
import { getPunchRecords as getWaybillPunchRecords } from '@/api/business/waybill-manage';
|
||||
import { getPunchRecords as getWaybillPunchRecords, locateVehicle, trackVehicle } from '@/api/business/waybill-manage';
|
||||
import { getList as getDriverList } from '@/api/transportCapacity/driver';
|
||||
import { getDictionary } from '@/api/system/dictbiz';
|
||||
import { getDictionary as getSystemDictionary } from '@/api/system/dict';
|
||||
@@ -3292,6 +3384,21 @@ export default {
|
||||
waybillRouteChangeRecords: [],
|
||||
waybillRouteChangeDragIndex: -1,
|
||||
waybillRouteChangeSaving: false,
|
||||
waybillLocateLoading: false,
|
||||
waybillLocateInfo: null,
|
||||
waybillLocateHint: '',
|
||||
waybillLocateMapInstance: null,
|
||||
waybillLocateMarker: null,
|
||||
waybillLocateInfoWindow: null,
|
||||
waybillTrackMode: '',
|
||||
waybillTrackLoading: false,
|
||||
waybillTrackInfo: null,
|
||||
waybillTrackHint: '',
|
||||
waybillTrackDateRange: [],
|
||||
waybillTrackMapInstance: null,
|
||||
waybillTrackPolyline: null,
|
||||
waybillTrackStartMarker: null,
|
||||
waybillTrackEndMarker: null,
|
||||
mileageDialog: {
|
||||
visible: false,
|
||||
submitting: false,
|
||||
@@ -4523,6 +4630,13 @@ export default {
|
||||
});
|
||||
},
|
||||
closeDetail() {
|
||||
this.destroyWaybillLocateMap();
|
||||
this.destroyWaybillTrackMap();
|
||||
this.waybillTrackMode = '';
|
||||
this.waybillLocateInfo = null;
|
||||
this.waybillLocateHint = '';
|
||||
this.waybillTrackInfo = null;
|
||||
this.waybillTrackHint = '';
|
||||
if (this.isStandaloneWaybillDetailPage) {
|
||||
this.$router.$avueRouter?.closeTag?.();
|
||||
this.$router.push({ path: '/business/waybill-manage', query: {} });
|
||||
@@ -4867,7 +4981,262 @@ export default {
|
||||
}
|
||||
},
|
||||
handleWaybillTrackAction(action) {
|
||||
this.$message.info(action === 'playback' ? '暂无可回放的物流轨迹' : '暂无车辆实时定位数据');
|
||||
if (action === 'playback') {
|
||||
this.destroyWaybillLocateMap();
|
||||
this.waybillTrackMode = 'playback';
|
||||
this.waybillLocateInfo = null;
|
||||
this.waybillLocateHint = '';
|
||||
if (!Array.isArray(this.waybillTrackDateRange) || this.waybillTrackDateRange.length !== 2) {
|
||||
this.waybillTrackDateRange = this.buildDefaultTrackDateRange();
|
||||
}
|
||||
this.loadWaybillTrack();
|
||||
return;
|
||||
}
|
||||
this.destroyWaybillTrackMap();
|
||||
this.waybillTrackMode = 'locate';
|
||||
this.waybillTrackInfo = null;
|
||||
this.waybillTrackHint = '';
|
||||
this.loadWaybillLocate();
|
||||
},
|
||||
buildDefaultTrackDateRange() {
|
||||
const pad = value => String(value).padStart(2, '0');
|
||||
const formatDate = date =>
|
||||
`${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
||||
const today = new Date();
|
||||
const yesterday = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 1);
|
||||
return [formatDate(yesterday), formatDate(today)];
|
||||
},
|
||||
destroyWaybillLocateMap() {
|
||||
if (this.waybillLocateMarker) {
|
||||
this.waybillLocateMarker.setMap(null);
|
||||
this.waybillLocateMarker = null;
|
||||
}
|
||||
if (this.waybillLocateInfoWindow) {
|
||||
this.waybillLocateInfoWindow.close();
|
||||
this.waybillLocateInfoWindow = null;
|
||||
}
|
||||
if (this.waybillLocateMapInstance) {
|
||||
this.waybillLocateMapInstance.destroy();
|
||||
this.waybillLocateMapInstance = null;
|
||||
}
|
||||
},
|
||||
destroyWaybillTrackMap() {
|
||||
if (this.waybillTrackPolyline) {
|
||||
this.waybillTrackPolyline.setMap(null);
|
||||
this.waybillTrackPolyline = null;
|
||||
}
|
||||
if (this.waybillTrackStartMarker) {
|
||||
this.waybillTrackStartMarker.setMap(null);
|
||||
this.waybillTrackStartMarker = null;
|
||||
}
|
||||
if (this.waybillTrackEndMarker) {
|
||||
this.waybillTrackEndMarker.setMap(null);
|
||||
this.waybillTrackEndMarker = null;
|
||||
}
|
||||
if (this.waybillTrackMapInstance) {
|
||||
this.waybillTrackMapInstance.destroy();
|
||||
this.waybillTrackMapInstance = null;
|
||||
}
|
||||
},
|
||||
async loadWaybillLocate() {
|
||||
const waybillId = this.detailRow?.id;
|
||||
if (!waybillId) {
|
||||
this.$message.warning('运单信息不完整');
|
||||
return;
|
||||
}
|
||||
if (!this.detailRow.vehicleNo) {
|
||||
this.$message.warning('运单未绑定车牌号,无法实时定位');
|
||||
return;
|
||||
}
|
||||
this.waybillLocateLoading = true;
|
||||
this.waybillLocateHint = '正在获取车辆实时定位...';
|
||||
this.waybillLocateInfo = null;
|
||||
try {
|
||||
const locateApi =
|
||||
typeof this.api.locateVehicle === 'function' ? this.api.locateVehicle : locateVehicle;
|
||||
const res = await locateApi(waybillId);
|
||||
const data = res?.data?.data || null;
|
||||
if (!data || data.longitude == null || data.latitude == null) {
|
||||
this.waybillLocateInfo = null;
|
||||
this.waybillLocateHint = '暂无车辆实时定位数据';
|
||||
this.$message.warning('暂无车辆实时定位数据');
|
||||
return;
|
||||
}
|
||||
this.waybillLocateInfo = data;
|
||||
this.waybillLocateHint = '';
|
||||
await this.$nextTick();
|
||||
await this.renderWaybillLocateMap(data);
|
||||
} catch (error) {
|
||||
this.waybillLocateInfo = null;
|
||||
this.waybillLocateHint = '实时定位获取失败';
|
||||
this.$message.error(error?.message || '实时定位获取失败');
|
||||
} finally {
|
||||
this.waybillLocateLoading = false;
|
||||
}
|
||||
},
|
||||
async loadWaybillTrack() {
|
||||
const waybillId = this.detailRow?.id;
|
||||
if (!waybillId) {
|
||||
this.$message.warning('运单信息不完整');
|
||||
return;
|
||||
}
|
||||
if (!this.detailRow.vehicleNo) {
|
||||
this.$message.warning('运单未绑定车牌号,无法查询历史轨迹');
|
||||
return;
|
||||
}
|
||||
if (!Array.isArray(this.waybillTrackDateRange) || this.waybillTrackDateRange.length !== 2) {
|
||||
this.waybillTrackDateRange = this.buildDefaultTrackDateRange();
|
||||
}
|
||||
const [startDate, endDate] = this.waybillTrackDateRange;
|
||||
this.waybillTrackLoading = true;
|
||||
this.waybillTrackHint = '正在获取历史轨迹...';
|
||||
this.destroyWaybillTrackMap();
|
||||
try {
|
||||
const trackApi =
|
||||
typeof this.api.trackVehicle === 'function' ? this.api.trackVehicle : trackVehicle;
|
||||
const res = await trackApi(waybillId, startDate, endDate);
|
||||
const data = res?.data?.data || null;
|
||||
const points = Array.isArray(data?.points) ? data.points : [];
|
||||
if (!data || points.length === 0) {
|
||||
this.waybillTrackInfo = data || { total: 0, points: [] };
|
||||
this.waybillTrackHint = '暂无可回放的物流轨迹';
|
||||
this.$message.warning('暂无可回放的物流轨迹');
|
||||
return;
|
||||
}
|
||||
this.waybillTrackInfo = data;
|
||||
this.waybillTrackHint = '';
|
||||
await this.$nextTick();
|
||||
await this.renderWaybillTrackMap(points);
|
||||
} catch (error) {
|
||||
this.waybillTrackInfo = null;
|
||||
this.waybillTrackHint = '历史轨迹获取失败';
|
||||
this.$message.error(error?.message || '历史轨迹获取失败');
|
||||
} finally {
|
||||
this.waybillTrackLoading = false;
|
||||
}
|
||||
},
|
||||
async renderWaybillLocateMap(locateInfo) {
|
||||
const longitude = Number(locateInfo?.longitude);
|
||||
const latitude = Number(locateInfo?.latitude);
|
||||
if (!Number.isFinite(longitude) || !Number.isFinite(latitude)) {
|
||||
this.$message.warning('定位坐标无效,无法在地图上展示');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.loadAmap();
|
||||
await this.$nextTick();
|
||||
const container = this.$refs.waybillLocateMap;
|
||||
if (!container || !window.AMap) {
|
||||
this.$message.warning('高德地图容器未就绪');
|
||||
return;
|
||||
}
|
||||
this.destroyWaybillLocateMap();
|
||||
this.waybillLocateMapInstance = new window.AMap.Map(container, {
|
||||
zoom: 15,
|
||||
center: [longitude, latitude],
|
||||
viewMode: '2D',
|
||||
resizeEnable: true,
|
||||
});
|
||||
const content = [
|
||||
`<div style="padding:4px 2px;line-height:1.6;font-size:12px;">`,
|
||||
`<div><b>${locateInfo.vehicleNo || '车辆位置'}</b></div>`,
|
||||
locateInfo.locateTime ? `<div>时间:${locateInfo.locateTime}</div>` : '',
|
||||
locateInfo.address ? `<div>地址:${locateInfo.address}</div>` : '',
|
||||
`<div>坐标:${longitude}, ${latitude}</div>`,
|
||||
`</div>`,
|
||||
].join('');
|
||||
this.waybillLocateInfoWindow = new window.AMap.InfoWindow({
|
||||
content,
|
||||
offset: new window.AMap.Pixel(0, -30),
|
||||
});
|
||||
this.waybillLocateMarker = new window.AMap.Marker({
|
||||
position: [longitude, latitude],
|
||||
title: locateInfo.vehicleNo || '车辆位置',
|
||||
anchor: 'bottom-center',
|
||||
});
|
||||
this.waybillLocateMarker.on('click', () => {
|
||||
this.waybillLocateInfoWindow.open(this.waybillLocateMapInstance, [longitude, latitude]);
|
||||
});
|
||||
this.waybillLocateMapInstance.add(this.waybillLocateMarker);
|
||||
this.waybillLocateInfoWindow.open(this.waybillLocateMapInstance, [longitude, latitude]);
|
||||
this.waybillLocateMapInstance.setFitView([this.waybillLocateMarker], false, [40, 40, 40, 40]);
|
||||
setTimeout(() => {
|
||||
this.waybillLocateMapInstance?.resize?.();
|
||||
}, 80);
|
||||
} catch (error) {
|
||||
window.console.warn('实时定位地图渲染失败', error);
|
||||
this.$message.error('高德地图渲染失败,请稍后重试');
|
||||
}
|
||||
},
|
||||
async renderWaybillTrackMap(points) {
|
||||
const path = (points || [])
|
||||
.map(item => [Number(item.longitude), Number(item.latitude)])
|
||||
.filter(item => Number.isFinite(item[0]) && Number.isFinite(item[1]));
|
||||
if (!path.length) {
|
||||
this.$message.warning('轨迹坐标无效,无法在地图上展示');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await this.loadAmap();
|
||||
await this.$nextTick();
|
||||
const container = this.$refs.waybillTrackMap;
|
||||
if (!container || !window.AMap) {
|
||||
this.$message.warning('高德地图容器未就绪');
|
||||
return;
|
||||
}
|
||||
this.destroyWaybillTrackMap();
|
||||
this.waybillTrackMapInstance = new window.AMap.Map(container, {
|
||||
zoom: 12,
|
||||
center: path[0],
|
||||
viewMode: '2D',
|
||||
resizeEnable: true,
|
||||
});
|
||||
this.waybillTrackPolyline = new window.AMap.Polyline({
|
||||
path,
|
||||
strokeColor: '#409eff',
|
||||
strokeWeight: 6,
|
||||
strokeOpacity: 0.9,
|
||||
lineJoin: 'round',
|
||||
lineCap: 'round',
|
||||
showDir: path.length > 1,
|
||||
});
|
||||
this.waybillTrackStartMarker = new window.AMap.Marker({
|
||||
position: path[0],
|
||||
title: '起点',
|
||||
anchor: 'bottom-center',
|
||||
label: {
|
||||
content: '起',
|
||||
direction: 'top',
|
||||
offset: new window.AMap.Pixel(0, -6),
|
||||
},
|
||||
});
|
||||
this.waybillTrackEndMarker = new window.AMap.Marker({
|
||||
position: path[path.length - 1],
|
||||
title: '终点',
|
||||
anchor: 'bottom-center',
|
||||
label: {
|
||||
content: '终',
|
||||
direction: 'top',
|
||||
offset: new window.AMap.Pixel(0, -6),
|
||||
},
|
||||
});
|
||||
this.waybillTrackMapInstance.add([
|
||||
this.waybillTrackPolyline,
|
||||
this.waybillTrackStartMarker,
|
||||
this.waybillTrackEndMarker,
|
||||
]);
|
||||
this.waybillTrackMapInstance.setFitView(
|
||||
[this.waybillTrackPolyline, this.waybillTrackStartMarker, this.waybillTrackEndMarker],
|
||||
false,
|
||||
[48, 48, 48, 48]
|
||||
);
|
||||
setTimeout(() => {
|
||||
this.waybillTrackMapInstance?.resize?.();
|
||||
}, 80);
|
||||
} catch (error) {
|
||||
window.console.warn('历史轨迹地图渲染失败', error);
|
||||
this.$message.error('高德地图渲染失败,请稍后重试');
|
||||
}
|
||||
},
|
||||
displayStatus(row, prop) {
|
||||
const formatStatus = this.config.formatStatus;
|
||||
@@ -9553,6 +9922,81 @@ export default {
|
||||
border: 1px solid #eff1f7;
|
||||
}
|
||||
|
||||
&__waybill-locate {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
&__waybill-locate-meta {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 8px 16px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #eff1f7;
|
||||
background: #fafafa;
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
|
||||
span {
|
||||
margin-right: 8px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: #303133;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
&__waybill-locate-address {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
&__waybill-locate-map {
|
||||
width: 100%;
|
||||
min-height: 320px;
|
||||
height: 320px;
|
||||
border: 1px solid #eff1f7;
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
&__waybill-locate-map--track {
|
||||
min-height: 420px;
|
||||
height: 420px;
|
||||
}
|
||||
|
||||
&__waybill-map-tip {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
z-index: 2;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: 8px 14px;
|
||||
border-radius: 4px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&__waybill-track-toolbar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
color: #606266;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&__waybill-track-total {
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
&__waybill-track-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
Reference in New Issue
Block a user