fix: 车辆定位围栏静态完成

This commit is contained in:
cjp 2023-11-20 18:20:04 +08:00
parent 9b0d967048
commit b467a1745b
4 changed files with 467 additions and 47 deletions

View File

Before

Width:  |  Height:  |  Size: 503 B

After

Width:  |  Height:  |  Size: 503 B

View File

Before

Width:  |  Height:  |  Size: 705 B

After

Width:  |  Height:  |  Size: 705 B

View File

@ -84,3 +84,12 @@ export const deletestandardDevApi = data => post('xmgl/vehiclePositionDev/delete
export const getCarDevOption = data => get('xmgl/vehiclePositionDev/list', data);
// 围栏相关API
export const getVehiclePositionFence = data => get('xmgl/vehiclePositionFence/list', data);
export const addVehiclePositionFence = data => post('xmgl/vehiclePositionFence/add', data);
export const editVehiclePositionFence = data => post('xmgl/vehiclePositionFence/edit', data);
export const deleteVehiclePositionFence = data => post('xmgl/vehiclePositionFence/delete', data);
export const deleteBatchVehiclePositionFence = data => post('xmgl/vehiclePositionFence/deleteBatch', data);
// 查询设备状态总数
export const getFenceTypeTotal = data => post('xmgl/vehiclePositionDev/countVehiclePositionDev', data);

View File

@ -11,53 +11,60 @@
</div>
<div v-if="checked === 1">
<div class="list-tool">
<el-input
placeholder="请输入设备名称"
suffix-icon="el-icon-search"
v-model="devName"
size="small"
style="width: 230px;margin-left: 15px"
>
</el-input>
<el-form :inline="true" size="medium" :model="queryInfo" class="demo-form-inline" style="margin-left: 15px">
<el-form-item>
<el-select filterable v-model="queryInfo.devSn" placeholder="请选择" @change="devChange">
<el-option v-for="(item, index) in nameOptions" :key="index" :label="item.label" :value="item.value"> </el-option>
</el-select>
</el-form-item>
</el-form>
<el-button icon="el-icon-refresh-right" class="tool-btn" style="margin-left: 15px"></el-button>
<el-button icon="el-icon-plus" class="tool-btn" @click="handle('add', true)"></el-button>
</div>
<div class="labor-type">
<div class="type-box" @click="laborChange(1)" :class="laborType == 1 ? 'laborActive' : ''">全部</div>
<div class="type-box" @click="laborChange(2)" :class="laborType == 2 ? 'laborActive' : ''">在线</div>
<div class="type-box" @click="laborChange(3)" :class="laborType == 3 ? 'laborActive' : ''">离线</div>
<div class="type-box" @click="laborChange(2)" :class="laborType == 2 ? 'laborActive' : ''">
全部({{ devTypeTotal.count || 0 }})
</div>
<div class="type-box" @click="laborChange(1)" :class="laborType == 1 ? 'laborActive' : ''">
在线({{ devTypeTotal.onlineCount || 0 }})
</div>
<div class="type-box" @click="laborChange(0)" :class="laborType == 0 ? 'laborActive' : ''">
离线({{ devTypeTotal.offlineCount || 0 }})
</div>
</div>
<div class="dev-list">
<div class="dev-list" v-if="devList.length > 0">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" style="margin-left:55px"
>全选</el-checkbox
>
<div style="margin: 15px 0;"></div>
<el-checkbox-group v-model="checkedCities" @change="handleCheckedCitiesChange">
<div v-for="city in cities" class="choice-item">
<div v-for="item in devList" class="choice-item" :key="item.id">
<div class="list-type">
<img src="@/assets/images/carPosition/carOn.png" alt="" />
<!-- <img src="@/assets/images/carPosition/carOff.png" alt=""> -->
<!-- <img src="@/assets/images/carPosition/personOn.png" alt=""> -->
<!-- <img src="@/assets/images/carPosition/personOff.png" alt=""> -->
<img src="@/assets/images/carPosition/carOn.png" v-if="item.type === 1 && item.online === 1" />
<img src="@/assets/images/carPosition/carOff.png" v-if="item.type === 1 && item.online === 0" />
<img src="@/assets/images/carPosition/personOn.png" v-if="item.type === 2 && item.online === 1" />
<img src="@/assets/images/carPosition/personOff.png" v-if="item.type === 2 && item.online === 0" />
</div>
<el-checkbox
onmouseover="this.style.background='#e2e8f8';"
onmouseout="this.style.background='none';"
:label="city"
:key="city"
style="width: 370px;padding: 5px 0 5px 50px"
:label="item.devSn"
:key="item.devSn"
style="width: 370px;padding: 5px 0 5px 55px"
>
{{ item.numberPlate || '' }}{{ item.personName || '' }}
</el-checkbox>
<div class="choice-speed">16km/h</div>
<div class="choice-speed" v-if="item.online === 1">16km/h</div>
</div>
</el-checkbox-group>
</div>
<div v-else style="text-align: center;margin-top:200px">暂无设备</div>
</div>
<div v-if="checked === 2">
<div class="top-select">
<el-form :inline="true" size="medium" :model="queryInfo" class="demo-form-inline">
<el-form-item label="车辆/人员名称">
<el-select v-model="queryInfo.devSn" placeholder="请选择">
<el-select filterable v-model="queryInfo.devSn" placeholder="请选择" @change="devChange">
<el-option v-for="(item, index) in nameOptions" :key="index" :label="item.label" :value="item.value"> </el-option>
</el-select>
</el-form-item>
@ -95,6 +102,92 @@
<div class="right-data">
<div class="map-top">
<div class="map-box" id="mapContainer"></div>
<div class="wei-lan" v-if="checked === 1">
<div class="icon-off" v-if="!fenceShow" @click="openFence">
<img src="@/assets/images/carPosition/iconOff.png" alt="" />
<div>围栏</div>
</div>
<div class="icon-on" v-if="fenceShow" @click="fenceShow = false">
<img src="@/assets/images/carPosition/iconOn.png" alt="" />
<div>围栏</div>
</div>
<!-- **********************围栏弹窗******************************** -->
<div class="fenceDialog" v-if="fenceShow">
<div class="fence-dialog-modal" v-if="fenceCreateShow"></div>
<div class="fence-box">
<div class="close-icon" @click="closeFence">
<i class="el-icon-close" style="font-size: 22px;color:#919398"></i>
</div>
<div class="fence-title">围栏</div>
<div class="fence-tool">
<div class="tool" @click="openFenceCreate">创建围栏</div>
<div class="tool">删除围栏</div>
</div>
<div class="fence-select">
<el-input v-model="fenceSearch" placeholder="请输入" size="small" clearable></el-input>
</div>
<div class="fence-radio">
<el-checkbox :indeterminate="isIndeterminateFence" v-model="checkAllFence" @change="fenceAllChange">全选</el-checkbox>
<vue-scroll>
<div style="margin: 5px 0;"></div>
<el-checkbox-group v-model="checkedFence" @change="fenceCitiesChange">
<div v-for="item in fenceList" class="choice-item" :key="item.id">
<el-checkbox :label="item.id" :key="item.id">{{ item.fenceName }} </el-checkbox>
</div>
</el-checkbox-group>
</vue-scroll>
</div>
</div>
<!-- 创建围栏弹窗 -->
<div class="fenceCreate" v-if="fenceCreateShow">
<!-- <div class="fence-modal"></div> -->
<div class="fenceCrete-box">
<div class="close-icon" @click="closeFenceCreate">
<i class="el-icon-close" style="font-size: 22px;color:#919398"></i>
</div>
<div class="fence-title">创建围栏</div>
<el-form size="medium" :model="addForm" ref="addForm" label-width="80px" :rules="formFenceRules">
<el-form-item label="围栏名称" prop="fenceName">
<el-input v-model="addForm.fenceName" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="范围类型" prop="rangeType">
<el-radio-group
v-model="addForm.rangeType"
style="display: flex;justify-content:space-between;padding-top:10px;padding-right:10px"
@change="changeAreaType"
>
<el-radio :label="1">标准区域</el-radio>
<el-radio :label="2">自定义</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="区域半径" prop="areaRadius" v-if="addForm.rangeType === 1">
<el-input
type="number"
v-model="addForm.areaRadius"
placeholder="请输入"
:maxlength="5"
@input="areaRadiusChange"
></el-input>
</el-form-item>
<el-form-item label="围栏形状" prop="fenceShape" v-if="addForm.rangeType === 2">
<div class="fence-shape">多边形</div>
</el-form-item>
<div class="create-footer">
<el-button class="cancleBtn" @click="fenceCreateShow = false" icon="el-icon-circle-close" size="medium"
>{{ $t('message.alarmValueSet.cancel') }}
</el-button>
<el-button type="primary" icon="el-icon-circle-check" @click="submitFence" size="medium"
>{{ $t('message.alarmValueSet.save') }}
</el-button>
</div>
</el-form>
</div>
</div>
</div>
</div>
<!-- **********************围栏弹窗******************************** -->
<div class="start-track" @click="startAnimation" v-if="checked === 2">
开始轨迹动画
</div>
@ -197,8 +290,17 @@
<script>
import realTimeData from './realTime-data.vue'
import alarmData from './alarm-data.vue'
import { getAlarmRecordInfo, getCarDevOption } from '@/assets/js/api/carManage'
const cityOptions = ['鲁U6675', '刘江', '蒋东', '鲁U9675']
import { getAlarmRecordInfo, getCarDevOption, addstandardDevApi } from '@/assets/js/api/carManage'
// API
import {
getFenceTypeTotal,
getVehiclePositionFence,
addVehiclePositionFence,
editVehiclePositionFence,
deleteVehiclePositionFence,
deleteBatchVehiclePositionFence
} from '@/assets/js/api/carManage'
var mouseTool
var marker
var lineArr
@ -209,19 +311,30 @@ export default {
},
data() {
return {
devTypeTotal: {},
fenceCreateShow: false, //
fenceList: ['围栏1', '围栏2', '围栏3', '围栏4', '围栏5'],
fenceSearch: '', //
fenceShow: false, //
dayValue: '',
nameOptions: [],
checkAll: false,
checkAllFence: false,
checkedCities: [],
cities: cityOptions,
checkedFence: [],
devList: ['鲁U6675', '刘江', '蒋东', '鲁U9675'],
isIndeterminate: true,
isIndeterminateFence: true,
checked: 1,
devName: '',
laborType: 1,
laborType: 2,
map: null,
locationList: [],
addForm: {
areaRadius: 100, //
fenceName: '', //
addr: '',
areaType: 1,
rangeType: 1,
locationList: [
{
fenceId: 0,
@ -232,7 +345,6 @@ export default {
}
],
projectSn: '',
standArea: 100,
enterpriseId: ''
},
pagInfo: {
@ -255,6 +367,23 @@ export default {
type: 1,
driver: ''
},
formFenceRules: {
fenceName: [
{
required: true,
message: this.$t('message.personnelPosition.required'),
trigger: 'blur'
},
{ min: 1, max: 20, message: this.$t('message.alarmValueSet.message1'), trigger: 'blur' }
], // 1 20
areaRadius: [
{
required: true,
message: this.$t('message.personnelPosition.required'),
trigger: 'change'
}
]
},
formRules: {
numberPlate: [
{
@ -278,8 +407,124 @@ export default {
this.initMap()
this.getProgressListData()
this.getCrewListData()
this.getFenceList()
this.getFenceType()
},
methods: {
devChange() {
this.getProgressListData()
},
//
getFenceList() {
let data = {}
getVehiclePositionFence(data).then(res => {
if (res.success) {
console.log('围栏', res)
this.fenceList = res.result
}
})
},
//
getFenceType() {
let data = {
projectSn: this.$store.state.projectSn
}
getFenceTypeTotal(data).then(res => {
if (res.success) {
console.log('设备状态', res)
this.devTypeTotal = res.result
}
})
},
areaRadiusChange() {
if (this.addForm.locationList.length === 1) {
this.drawCircle()
}
},
submitFence() {
this.addForm.locationList = this.locationList
console.log('新增围栏', this.addForm)
let latitude = ''
let longitude = ''
let fenceShape = ''
if (this.addForm.locationList.length === 1) {
latitude = this.addForm.locationList[0].latitude
longitude = this.addForm.locationList[0].longitude
}
if (this.addForm.locationList.length > 1) {
for (let index = 0; index < this.addForm.locationList.length; index++) {
const element = this.addForm.locationList[index]
let currentStr = element.latitude + '|' + element.longitude
if (this.addForm.locationList.length - 1 > index) {
currentStr = currentStr + ','
}
fenceShape = fenceShape + currentStr
}
}
console.log('多边形', fenceShape)
this.$refs['addForm'].validate(valid => {
if (valid) {
let params = {
fenceName: this.addForm.fenceName,
areaRadius: this.addForm.areaRadius,
fenceShapeArr: JSON.stringify(this.addForm.locationList),
fenceShape: fenceShape,
latitude: latitude,
longitude: longitude,
rangeType: this.addForm.rangeType
}
// params.alarmPushWorkerId = this.addForm.alarmPushWorkerId.join(',');
console.log('新增信息', params)
addVehiclePositionFence(params).then(res => {
if (res.success) {
this.$message.success(res.message)
}
})
this.closeFenceCreate()
} else {
console.log('error submit!!')
return false
}
})
},
//
openFenceCreate() {
this.fenceCreateShow = true
},
//
closeFenceCreate() {
this.fenceCreateShow = false
;(this.addForm = {
areaRadius: 100, //
fenceName: '', //
addr: '',
rangeType: 1,
locationList: [
{
fenceId: 0,
id: 0,
latitude: '',
longitude: '',
sortNum: 0
}
],
projectSn: '',
enterpriseId: ''
}),
this.exitEditFn()
this.clearFn()
},
//
openFence() {
this.fenceShow = true
},
//
closeFence() {
this.fenceShow = false
},
// /
submit() {
this.$refs['addEditForm'].validate(valid => {
if (valid) {
@ -342,8 +587,12 @@ export default {
},
//
getCrewListData() {
let onlineType = ''
if (this.laborType !== 2) {
onlineType = this.laborType
}
let data = {
projectSn: this.projectSn
online: onlineType
}
getCarDevOption(data).then(res => {
if (res.code == 200) {
@ -367,19 +616,13 @@ export default {
})
this.nameOptions = nameOption.concat(carOption)
console.log('车牌号/名字下拉', nameOption, carOption)
// this.numOptions = res.result.map( (item)=> {
// return {
// label: item.devSn,
// value: item.devSn
// }
// } )
// console.log('devSn', this.numOptions)
this.devList = res.result
} else {
this.$message.error(res.message)
}
})
},
//
//
getProgressListData() {
let data = {
pageNo: this.pagInfo.pageNo,
@ -395,15 +638,29 @@ export default {
},
laborChange(e) {
this.laborType = e
this.getCrewListData()
},
handleCheckAllChange(val) {
this.checkedCities = val ? cityOptions : []
let nameArr = this.devList.map(item => item.devSn)
this.checkedCities = val ? nameArr : []
this.isIndeterminate = false
},
handleCheckedCitiesChange(value) {
let checkedCount = value.length
this.checkAll = checkedCount === this.cities.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.cities.length
this.checkAll = checkedCount === this.devList.length
this.isIndeterminate = checkedCount > 0 && checkedCount < this.devList.length
},
fenceAllChange(val) {
let nameArr = this.fenceList.map(item => item.id)
this.checkedFence = val ? nameArr : []
this.isIndeterminateFence = false
console.log('全选', val)
},
fenceCitiesChange(value) {
let checkedCount = value.length
this.checkAllFence = checkedCount === this.fenceList.length
this.isIndeterminateFence = checkedCount > 0 && checkedCount < this.fenceList.length
console.log('选中', value)
},
selectChange(e) {
this.checked = e
@ -553,8 +810,12 @@ export default {
}
})
this.map.on('click', e => {
if (!this.fenceCreateShow) {
console.log('还未到创建围栏弹窗')
return
}
console.log('您在 [ ' + e.lnglat.getLng() + ',' + e.lnglat.getLat() + ' ] 的位置单击了地图!')
if (this.addForm.areaType == 1) {
if (this.addForm.rangeType == 1) {
this.locationList = []
this.locationList.push({
longitude: e.lnglat.getLng(),
@ -572,6 +833,7 @@ export default {
latitude: e.lnglat.getLat()
})
}
console.log('当前位置列表', this.locationList)
})
},
select(e) {
@ -583,9 +845,14 @@ export default {
clearFn() {
this.map.clearMap()
},
changeAreaType() {
changeAreaType(e) {
// console.log("",e);
if (e === 1) {
this.drawCircle()
} else {
this.drawPolygon()
}
this.locationList = []
this.clearFn()
},
//
addMarker() {
@ -620,7 +887,7 @@ export default {
this.addMarker()
var circle = new AMap.Circle({
center: [this.locationList[0].longitude, this.locationList[0].latitude],
radius: this.addForm.standArea, //
radius: this.addForm.areaRadius, //
borderWeight: 2,
strokeColor: '#6caffc',
strokeOpacity: 1,
@ -640,6 +907,7 @@ export default {
//
drawRectangle() {
this.clearFn()
console.log('绘制矩形')
mouseTool.rectangle({
strokeColor: '#6caffc',
// strokeOpacity: 0.5,
@ -653,6 +921,7 @@ export default {
},
drawPolygon() {
this.clearFn()
console.log('自定义绘制')
mouseTool.polygon({
strokeColor: '#6caffc',
strokeOpacity: 1,
@ -707,7 +976,111 @@ export default {
}
}
</script>
<!-- 组件自定义样式需嵌套外层class -->
<style lang="scss"></style>
<style lang="scss" scoped>
//
.fence-shape {
display: flex;
justify-content: center;
align-items: center;
width: 74px;
height: 34px;
background: #ffffff;
border-radius: 4px 4px 4px 4px;
border: 1px solid #d8dbe8;
}
//
.fenceDialog {
position: absolute;
background: #fff;
box-sizing: border-box;
padding: 25px;
left: 5%;
top: 20px;
width: 330px;
height: 380px;
.fence-dialog-modal {
position: absolute;
width: 100%;
height: 100%;
top: 0%;
left: 0%;
z-index: 3;
background: rgba(39, 45, 69, 0.5);
}
.close-icon {
position: absolute;
top: 0px;
right: 0px;
cursor: pointer;
}
.fence-title {
border-left: 4px solid #5c81ee;
font-size: 15px;
color: #272d45;
padding-left: 10px;
margin-bottom: 20px;
font-weight: 600;
font-family: Source Han Sans CN, Source Han Sans CN;
}
}
.fenceCreate {
position: absolute;
background: #fff;
box-sizing: border-box;
padding: 25px;
width: 330px;
height: 380px;
left: 40px;
top: 40px;
z-index: 5;
// .fence-modal {
// position: absolute;
// width: 330px;
// height: 90px;
// top: -90px;
// left: 0%;
// background: rgba(39, 45, 69, 0.5);
// }
.fenceCrete-box {
position: relative;
.create-footer {
margin: 100px 0 0 50px;
}
}
}
.fence-box {
position: relative;
.fence-tool {
display: flex;
justify-content: space-around;
padding: 0 25px;
.tool {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 33px;
font-size: 14px;
cursor: pointer;
background: #ffffff;
color: #5181f6;
border-radius: 2px 2px 2px 2px;
border: 1px solid #5181f6;
}
}
.fence-select {
margin: 15px 0;
}
.fence-radio {
height: 160px;
}
}
.choice-type {
display: flex;
align-items: center;
@ -754,7 +1127,6 @@ export default {
.dev-list {
width: 100%;
.choice-item {
width: 376px;
display: flex;
align-items: center;
position: relative;
@ -802,7 +1174,7 @@ export default {
display: flex;
align-items: center;
width: 50%;
height: 50px;
height: 40px;
justify-content: center;
cursor: pointer;
}
@ -810,7 +1182,7 @@ export default {
display: flex;
align-items: center;
width: 50%;
height: 50px;
height: 40px;
justify-content: center;
cursor: pointer;
}
@ -836,6 +1208,45 @@ export default {
height: 58%;
background: #fff;
position: relative;
.wei-lan {
.icon-off {
position: absolute;
padding-top: 5px;
top: 8%;
left: 1%;
width: 48px;
height: 48px;
cursor: pointer;
font-size: 14px;
background: #ffffff;
text-align: center;
border-radius: 2px 2px 2px 2px;
img {
width: 20px;
height: 20px;
margin: 0 auto;
}
}
.icon-on {
position: absolute;
padding-top: 5px;
top: 8%;
left: 1%;
text-align: center;
width: 48px;
height: 48px;
cursor: pointer;
font-size: 14px;
background: #ffffff;
color: #5181f6;
border-radius: 2px 2px 2px 2px;
img {
width: 20px;
height: 20px;
margin: 0 auto;
}
}
}
.start-track {
position: absolute;
display: flex;