Compare commits

...

4 Commits

Author SHA1 Message Date
318f178c3d 111 2025-01-24 22:27:42 +08:00
0746100243 11 2025-01-23 14:36:49 +08:00
5a634b8ca4 Merge branch 'refs/heads/tx' 2024-12-27 10:36:54 +08:00
tx
7c86916a53 11 2024-12-27 10:29:51 +08:00
3 changed files with 378 additions and 218 deletions

View File

@ -1,5 +1,5 @@
<template>
<div class="place-search-map" :style="{ width: width, height: height }" v-loading="loading">
<div class="place-search-map" :style="{ width: width, height: height }" >
<div id="container"></div>
<!-- 轨迹回放控制面板 -->
@ -72,6 +72,10 @@
<span class="label">锁状态:</span>
<span class="value">{{ currentLockStatus }}</span>
</div>
<div class="info-item">
<span class="label">电门:</span>
<span class="value">{{ currentEleLock }}</span>
</div>
</div>
</div>
</div>
@ -162,7 +166,8 @@ export default {
parkingPolygons: [],
currentStatus: '',
currentBattery: '',
currentLockStatus: ''
currentLockStatus: '',
currentEleLock: ''
}
},
@ -175,7 +180,7 @@ export default {
//
await this.getAreas()
//
} catch (error) {
console.error('初始化失败:', error)
this.$message.error('初始化失败')
@ -192,14 +197,17 @@ export default {
methods: {
async getAreas() {
if (!this.areaId) return
// areaId,
if (!this.areaId) {
this.initAMap();
return;
}
// areaId
getArea(this.areaId).then(response => {
console.log(response, 'responseresponse');
this.area = response.data;
listParking({ areaId: this.area.areaId }).then(response => {
let list = response.rows;
console.log(list, 'listlistlist');
@ -217,6 +225,35 @@ export default {
});
});
},
clearTrackData() {
if (this.polyline) {
this.map.remove(this.polyline);
}
if (this.passedPolyline) {
this.map.remove(this.passedPolyline);
}
if (this.marker) {
this.map.remove(this.marker);
}
//
if (this.startMarker) {
this.map.remove(this.startMarker);
}
if (this.endMarker) {
this.map.remove(this.endMarker);
}
this.trackPoints = [];
this.currentProgress = 0;
this.currentPoint = null;
this.currentPointTime = '';
this.currentSpeed = '0.00';
this.location = '';
this.currentStatus = '';
this.currentBattery = '';
this.currentLockStatus = '';
this.currentEleLock = ''
},
formatStatus(status) {
const statusMap = {
'0': '仓库中',
@ -256,23 +293,29 @@ export default {
initMarker() {
this.removeAllMarker()
if (this.currentLng != null && this.currentLat != null) {
this.updateTrackData()
this.addArea(JSON.parse(this.area.boundaryStr) || []);
//
this.parkingList.forEach(parking => {
this.addParking(JSON.parse(parking.boundaryStr) || [], parking.parkingName, parking.longitude, parking.latitude);
this.addMarker2(parking, "https://lxnapi.ccttiot.com/FqcYf6ecsnbC0OT6YYAF5npgu-kh", parking.parkingName, "#1890ff");
});
//
this.noParkingList.forEach(noparking => {
this.addNoParking(JSON.parse(noparking.boundaryStr) || []);
this.addMarker2(noparking, "https://lxnapi.ccttiot.com/FjKE5PWbnEnZUq3k-wVIvV4lv8Ab", noparking.parkingName, "#ff4444");
});
//
this.noridingList.forEach(noriding => {
this.addNoriding(JSON.parse(noriding.boundaryStr) || [], noriding.parkingName, noriding.longitude, noriding.latitude);
this.addMarker2(noriding, "https://lxnapi.ccttiot.com/FmX1diEPPbFYe1vcUfKp6qbKzzh2", noriding.parkingName, "#ffcc00");
});
this.updateTrackData()
//
if(this.area) {
this.addArea(JSON.parse(this.area.boundaryStr) || []);
//
this.parkingList.forEach(parking => {
this.addParking(JSON.parse(parking.boundaryStr) || [], parking.parkingName, parking.longitude, parking.latitude);
this.addMarker2(parking, "https://lxnapi.ccttiot.com/FqcYf6ecsnbC0OT6YYAF5npgu-kh", parking.parkingName, "#1890ff");
});
//
this.noParkingList.forEach(noparking => {
this.addNoParking(JSON.parse(noparking.boundaryStr) || []);
this.addMarker2(noparking, "https://lxnapi.ccttiot.com/FjKE5PWbnEnZUq3k-wVIvV4lv8Ab", noparking.parkingName, "#ff4444");
});
//
this.noridingList.forEach(noriding => {
this.addNoriding(JSON.parse(noriding.boundaryStr) || [], noriding.parkingName, noriding.longitude, noriding.latitude);
this.addMarker2(noriding, "https://lxnapi.ccttiot.com/FmX1diEPPbFYe1vcUfKp6qbKzzh2", noriding.parkingName, "#ffcc00");
});
}
//
this.addMarker(this.currentLng, this.currentLat, this.deviceSn, this.deviceInfo.status, this.deviceInfo.onlineStatus)
}
},
@ -576,6 +619,11 @@ export default {
async updateTrackData() {
try {
//
this.stopPlayback()
//
this.clearTrackData()
const params = {
sn: this.deviceSn,
startTime: this.startTime,
@ -586,23 +634,26 @@ export default {
if (res.code === 200) {
if (!res.data?.length) {
this.$message.warning('该时间段内无轨迹数据')
this.clearTrackData()
return
}
//
//
this.trackPoints = res.data.map(point => ({
latitude: parseFloat(point.latitude),
longitude: parseFloat(point.longitude),
time: point.at,
status: point.status,
onlineStatus: point.onlineStatus
onlineStatus: point.onlineStatus,
bat: point.bat,
lockStatus: point.lockStatus,
q: point.q
}))
// 线
// 线
this.drawTrackLine()
//
this.resetPlayback()
//
this.currentProgress = 0
this.updateMapPoint(0)
}
} catch (error) {
console.error("获取轨迹数据失败:", error)
@ -610,6 +661,48 @@ export default {
}
},
clearTrackData() {
//
if (this.playbackTimer) {
clearInterval(this.playbackTimer)
this.playbackTimer = null
}
//
if (this.polyline) {
this.map.remove(this.polyline)
this.polyline = null
}
if (this.passedPolyline) {
this.map.remove(this.passedPolyline)
this.passedPolyline = null
}
if (this.marker) {
this.map.remove(this.marker)
this.marker = null
}
if (this.startMarker) {
this.map.remove(this.startMarker)
this.startMarker = null
}
if (this.endMarker) {
this.map.remove(this.endMarker)
this.endMarker = null
}
//
this.trackPoints = []
this.currentProgress = 0
this.currentPoint = null
this.currentPointTime = ''
this.currentSpeed = '0.00'
this.location = ''
this.currentStatus = ''
this.currentBattery = ''
this.currentLockStatus = ''
this.currentEleLock = ''
this.isPlaying = false
},
processTrackData(data) {
this.trackPoints = data.map(point => ({
latitude: parseFloat(point.latitude),
@ -631,6 +724,12 @@ export default {
if (this.polyline) {
this.map.remove(this.polyline)
}
if (this.passedPolyline) {
this.map.remove(this.passedPolyline)
}
if (this.marker) {
this.map.remove(this.marker)
}
// 线
this.polyline = new this.AMap.Polyline({
@ -701,6 +800,7 @@ export default {
this.currentStatus = ''
this.currentBattery = ''
this.currentLockStatus = ''
this.currentEleLock = ''
},
updateMapPoint(index) {
@ -710,43 +810,91 @@ export default {
this.currentPoint = point
this.currentPointTime = point.time
this.location = `${point.longitude}, ${point.latitude}`
//
console.log(point,'pointpointpoint');
//
this.currentStatus = this.formatStatus(point.status)
this.currentBattery = point.bta == null ? '未知' : (point.bta / 10).toFixed(1) + 'V'
this.currentBattery = point.bat == null ? '未知' : (point.bat / 10).toFixed(1) + 'V'
this.currentLockStatus = point.lockStatus == '0' ? '关锁' : '开锁'
this.currentEleLock = point.q == null ? '未知' : (point.q == '0' ? '关锁' : '开锁')
//
if (index > 0) {
const prevPoint = this.trackPoints[index - 1]
const distance = this.calculateDistance(
// 使 Haversine
const distance = this.calculateHaversineDistance(
prevPoint.latitude,
prevPoint.longitude,
point.latitude,
point.longitude
)
const timeGap = (new Date(point.time) - new Date(prevPoint.time)) / 1000
this.currentSpeed = timeGap > 0 ? ((distance / timeGap) * 3.6).toFixed(1) : '0.00'
//
const timeGap = (new Date(point.time) - new Date(prevPoint.time)) / (1000 * 3600)
// /
this.currentSpeed = timeGap > 0 ? (distance / timeGap).toFixed(2) : '0.00'
} else {
this.currentSpeed = '0.00'
}
// 线
this.updatePassedPolyline(index)
this.updateMarkerPosition(point)
//
if (!this.marker) {
this.marker = new this.AMap.Marker({
position: [point.longitude, point.latitude],
icon: this.getMarkerIcon(point.status, point.onlineStatus),
offset: new this.AMap.Pixel(-12.5, -19.5)
})
this.map.add(this.marker)
} else {
this.marker.setPosition([point.longitude, point.latitude])
this.marker.setIcon(this.getMarkerIcon(point.status, point.onlineStatus))
}
},
// Haversine
calculateHaversineDistance(lat1, lon1, lat2, lon2) {
//
const R = 6371
//
const dLat = this.toRad(lat2 - lat1)
const dLon = this.toRad(lon2 - lon1)
const radLat1 = this.toRad(lat1)
const radLat2 = this.toRad(lat2)
// Haversine
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(radLat1) * Math.cos(radLat2)
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
//
return R * c
},
//
toRad(degrees) {
return degrees * Math.PI / 180
},
updatePassedPolyline(index) {
const passedPath = this.trackPoints
.slice(0, index + 1)
.map(p => [p.longitude, p.latitude])
if (!this.passedPolyline) {
this.passedPolyline = new this.AMap.Polyline({
path: passedPath,
strokeColor: "#AF5",
strokeWeight: 6
})
this.map.add(this.passedPolyline)
} else {
this.passedPolyline.setPath(passedPath)
// 线
if (this.passedPolyline) {
this.map.remove(this.passedPolyline)
}
// 线
this.passedPolyline = new this.AMap.Polyline({
path: passedPath,
strokeColor: "#AF5",
strokeWeight: 6
})
this.map.add(this.passedPolyline)
},
updateMarkerPosition(point) {
@ -770,17 +918,14 @@ export default {
},
startPlayback() {
if (this.playbackTimer) return
if (this.playbackTimer) {
clearInterval(this.playbackTimer)
}
this.playbackTimer = setInterval(() => {
if (this.currentProgress >= this.trackPoints.length - 1) {
this.pausePlayback()
this.isPlaying = false
//
setTimeout(() => {
this.currentProgress = 0
this.updateMapPoint(0)
}, 1000)
return
}
this.currentProgress++
@ -794,12 +939,12 @@ export default {
this.playbackTimer = null
}
},
stopPlayback() {
this.pausePlayback()
if (this.playbackTimer) {
clearInterval(this.playbackTimer)
this.playbackTimer = null
}
this.isPlaying = false
this.currentProgress = 0
this.updateMapPoint(0) //
},
changeSpeed(direction) {
@ -852,13 +997,15 @@ export default {
},
onSliderChange(value) {
this.stopPlayback() //
this.currentProgress = value
this.updateMapPoint(value)
},
onSliderChanging(value) {
// this.stopPlayback() //
this.updateMapPoint(value)
}
},
}
}
</script>

View File

@ -44,10 +44,9 @@
<div class="info-row">
<div class="info-item">
<span class="label">电门</span>
<el-tag :type="deviceInfo.powerStatus === '1' ? 'success' : 'danger'" size="small">
{{ deviceInfo.powerStatus === '1' ? '开' : '关' }}
<el-tag :type="deviceInfo.quality === 1 ? 'success' : 'danger'" size="small">
{{ deviceInfo.quality === 1 ? '开' : '关' }}
</el-tag>
<!-- <span class="value">{{ deviceInfo.quality || '-' }}</span> -->
</div>
<div class="info-item">
<span class="label">锁信号</span>
@ -1157,4 +1156,4 @@ export default {
height: calc(100% - 41px); // header
}
}
</style>
</style>

View File

@ -357,17 +357,17 @@
<!-- 代理商运营区车辆型号一行 -->
<el-col :span="8" v-if="userName == 'admin'">
<el-form-item label="代理商" prop="deptId">
<el-select
v-model="form.deptId"
clearable
filterable
placeholder="请选择代理商"
<el-select
v-model="form.deptId"
clearable
filterable
placeholder="请选择代理商"
@change="handleDeptChange"
style="width: 100%">
<el-option
v-for="item in deptOptions"
:key="item.deptId"
:label="item.deptName"
<el-option
v-for="item in deptOptions"
:key="item.deptId"
:label="item.deptName"
:value="item.deptId">
</el-option>
</el-select>
@ -375,17 +375,17 @@
</el-col>
<el-col :span="8">
<el-form-item label="运营区" prop="areaId">
<el-select
v-model="form.areaId"
clearable
filterable
placeholder="请选择运营区"
<el-select
v-model="form.areaId"
clearable
filterable
placeholder="请选择运营区"
@change="handleAreaChange"
style="width: 100%">
<el-option
v-for="item in areaOptions"
:key="item.areaId"
:label="item.areaName"
<el-option
v-for="item in areaOptions"
:key="item.areaId"
:label="item.areaName"
:value="item.areaId">
</el-option>
</el-select>
@ -393,16 +393,16 @@
</el-col>
<el-col :span="8">
<el-form-item label="车辆型号" prop="modelId">
<el-select
v-model="form.modelId"
clearable
placeholder="请选择车辆型号"
<el-select
v-model="form.modelId"
clearable
placeholder="请选择车辆型号"
@change="handleModelChange"
style="width: 100%">
<el-option
v-for="item in modelOptions"
:key="item.modelId"
:label="item.model"
<el-option
v-for="item in modelOptions"
:key="item.modelId"
:label="item.model"
:value="item.modelId">
</el-option>
</el-select>
@ -414,17 +414,17 @@
<!-- 硬件版本 -->
<el-col :span="8">
<el-form-item label="硬件版本" prop="hardwareVersionId" v-if="hardwareVersionOptions.length > 0 && userName == 'admin'">
<el-select
v-model="form.hardwareVersionId"
clearable
placeholder="请选择硬件版本"
<el-select
v-model="form.hardwareVersionId"
clearable
placeholder="请选择硬件版本"
:disabled="userName != 'admin'"
@change="handleHardwareVersionChange"
style="width: 100%">
<el-option
v-for="item in hardwareVersionOptions"
:key="item.id"
:label="item.version"
<el-option
v-for="item in hardwareVersionOptions"
:key="item.id"
:label="item.version"
:value="item.id">
</el-option>
</el-select>
@ -840,100 +840,102 @@ export default {
}
},
/** 当选择代理商时调用 */
handleDeptChange(val) {
if (!this.isUpdating) {
if (val) {
this.isUpdating = true;
selectAreaListByDeptId(val).then((response) => {
//
this.areaOptions = response.data.areaList || [];
this.modelOptions = response.data.modelList || [];
//
this.form.areaId = null;
this.form.modelId = null;
//
if (this.areaOptions.length > 0) {
this.form.areaId = this.areaOptions[0].areaId;
}
if (this.modelOptions.length > 0) {
this.form.modelId = this.modelOptions[0].modelId;
}
handleDeptChange(val) {
if (!this.isUpdating) {
if (val) {
this.isUpdating = true;
selectAreaListByDeptId(val).then((response) => {
//
this.areaOptions = response.data.areaList || [];
this.modelOptions = response.data.modelList || [];
//
if (this.areaOptions.length === 0) {
this.$message.warning('该代理商暂无运营区');
}
if (this.modelOptions.length === 0) {
this.$message.warning('该代理商暂无可用车型');
}
}).finally(() => {
this.isUpdating = false;
});
} else {
//
this.isUpdating = true;
listArea(this.queryParams2).then((response) => {
this.areaOptions = response.rows || [];
this.form.areaId = null;
this.form.modelId = null;
this.modelOptions = [];
}).finally(() => {
this.isUpdating = false;
});
}
}
},
/** 当选择运营区时调用 */
handleAreaChange(val) {
if (!this.isUpdating) {
if (val) {
this.isUpdating = true;
selectDeptByAreaId(val).then((response) => {
//
if (!this.form.deptId && response.data.sysDept) {
this.form.deptId = response.data.sysDept.deptId;
//
selectAreaListByDeptId(this.form.deptId).then((deptResponse) => {
this.modelOptions = deptResponse.data.modelList || [];
if (this.modelOptions.length > 0) {
this.form.modelId = this.modelOptions[0].modelId;
} else {
this.form.modelId = null;
this.$message.warning('该代理商暂无可用车型');
// ,
if (!this.areaOptions.find(area => area.areaId === this.form.areaId)) {
this.form.areaId = null;
}
if (!this.modelOptions.find(model => model.modelId === this.form.modelId)) {
this.form.modelId = null;
}
// ,
if (this.areaOptions.length > 0 && !this.form.areaId) {
this.form.areaId = this.areaOptions[0].areaId;
}
if (this.modelOptions.length > 0 && !this.form.modelId) {
this.form.modelId = this.modelOptions[0].modelId;
}
}).catch(() => {
this.areaOptions = [];
this.modelOptions = [];
this.form.areaId = null;
this.form.modelId = null;
}).finally(() => {
this.isUpdating = false;
});
} else {
// 使
this.modelOptions = response.data.modelList || [];
if (!this.form.modelId && this.modelOptions.length > 0) {
this.form.modelId = this.modelOptions[0].modelId;
} else if (this.modelOptions.length === 0) {
// ,
this.isUpdating = true;
listArea(this.queryParams2).then((response) => {
this.areaOptions = response.rows || [];
this.form.areaId = null;
this.form.modelId = null;
this.$message.warning('该运营区暂无可用车型');
}
this.modelOptions = [];
}).finally(() => {
this.isUpdating = false;
});
}
}).finally(() => {
this.isUpdating = false;
});
} else {
//
this.form.modelId = null;
this.modelOptions = [];
}
}
},
}
},
/** 当选择车型时调用 */
handleModelChange(val) {
//
if (!val) {
this.form.modelId = null;
}
},
/** 当选择运营区时调用 */
handleAreaChange(val) {
if (!this.isUpdating) {
if (val) {
this.isUpdating = true;
selectDeptByAreaId(val).then((response) => {
//
if (!this.form.deptId && response.data.sysDept) {
this.form.deptId = response.data.sysDept.deptId;
//
selectAreaListByDeptId(this.form.deptId).then((deptResponse) => {
this.modelOptions = deptResponse.data.modelList || [];
if (this.modelOptions.length > 0) {
this.form.modelId = this.modelOptions[0].modelId;
} else {
this.form.modelId = null;
this.$message.warning('该代理商暂无可用车型');
}
});
} else {
// 使
this.modelOptions = response.data.modelList || [];
if (!this.form.modelId && this.modelOptions.length > 0) {
this.form.modelId = this.modelOptions[0].modelId;
} else if (this.modelOptions.length === 0) {
this.form.modelId = null;
this.$message.warning('该运营区暂无可用车型');
}
}
}).finally(() => {
this.isUpdating = false;
});
} else {
//
this.form.modelId = null;
this.modelOptions = [];
}
}
},
/** 当选择车型时调用 */
handleModelChange(val) {
//
if (!val) {
this.form.modelId = null;
}
},
//
handleHardwareVersionChange(val) {
@ -1012,8 +1014,8 @@ handleAreaChange(val) {
// }
},
/** 排序触发事件 */
handleSortChange(column, prop, order) {
this.queryParams.orderByColumn = column.prop;
@ -1162,16 +1164,16 @@ handleAreaChange(val) {
if(this.queryParams2.deptId){
selectAreaListByDeptId(this.queryParams2.deptId).then((deptResponse) => {
this.modelOptions = deptResponse.data.modelList || [];
});
}else{
listModel(this.queryParams2).then((response) => {
this.modelOptions = response.rows;
});
}
},
//
cancel() {
@ -1215,7 +1217,7 @@ handleAreaChange(val) {
}
);
}
listModel(this.queryParams2).then((response) => {
this.modelOptions = response.rows;
});
@ -1229,14 +1231,14 @@ handleAreaChange(val) {
this.form.modelId = null;
this.areaOptions = [];
this.modelOptions = [];
//
if (this.userName === "admin") {
listDept2({ status: "0", pageNum: 1, pageSize: 999 }).then((response) => {
this.deptOptions = response.rows;
});
}
//
listArea(this.queryParams2).then((response) => {
this.areaOptions = response.rows;
@ -1271,7 +1273,7 @@ handleAreaChange(val) {
},
/** 详情按钮 */
handleView(row) {
const deviceId = row.deviceId
const deviceId = row.deviceId
this.$router.push(`/system/deviceDetail/index/${deviceId}`)
// this.$router.push({
// path: '/system/deviceDetail/index',
@ -1343,41 +1345,53 @@ handleAreaChange(val) {
getDevice(deviceId).then((response) => {
this.form = response.data;
this.selectHardwareVersion(response.data.hardwareVersionId);
this.selectHardwareVersion(response.data.hardwareVersionId)
// this.fetchData3(response.data.areaId)
// this.fetchData(response.data.deptId)
// this.open = true;
// this.title = "1";
if (response.data.deptId) {
//
if (!response.data.deptId) {
//
this.modelOptions = [];
this.areaOptions = [];
// ,
if (this.userName === 'admin') {
listArea(this.queryParams2).then((response) => {
this.areaOptions = response.rows || [];
});
}
this.open = true;
this.title = "修改设备";
this.isUpdating = false;
} else {
// ,
selectAreaListByDeptId(response.data.deptId).then((res) => {
// 1: 使Vue.set
setTimeout(() => {
console.log('=调用了11');
this.$set(this, 'modelOptions', []);
this.$set(this, 'areaOptions', []);
this.$set(this, 'modelOptions', res.data.modelList);
this.$set(this, 'areaOptions', res.data.areaList);
this.$forceUpdate()
this.modelOptions = res.data.modelList || [];
this.areaOptions = res.data.areaList || [];
// ,
if (this.areaOptions.length > 0 && !this.areaOptions.find(area => area.areaId === this.form.areaId)) {
this.form.areaId = null;
}
if (this.modelOptions.length > 0 && !this.modelOptions.find(model => model.modelId === this.form.modelId)) {
this.form.modelId = null;
}
this.open = true;
this.title = "修改设备";
}).catch(() => {
// ,
this.modelOptions = [];
this.areaOptions = [];
this.open = true;
this.title = "修改设备";
}, 800);
// 2: 使nextTickDOM
// this.$nextTick(() => {
// this.modelOptions = res.data.modelList;
// this.areaOptions = res.data.areaList;
// },600);
// setTimeout$forceUpdate
}).finally(() => {
this.isUpdating = false;
});
} else {
this.isUpdating = false;
}
}).catch(() => {
this.isUpdating = false;
this.$modal.msgError("获取设备信息失败");
});
},
handleListing(row) {