<template> <app-container id="editroute"> <el-collapse v-model="activeNames" class="route-coll"> <el-collapse-item title="(一)基本信息" name="1" > <el-form ref="dataForm" :rules="rules" :model="routeForm" size="small" label-position="right" label-width="130px" style="padding-top:20px;padding-right: 40px"> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="路线描述" prop="routeName" > <el-input v-model.trim="routeForm.routeName" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'必填'" type="text"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="报警类型" prop="alarmType"> <el-select v-model="routeForm.alarmType" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'必填'" filterable clearable value="" style="width: 100%"> <el-option v-for="item in alarmlist" :key="item.value" :label="item.name" :value="item.value"/> </el-select> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="偏离报警距离(米)" prop="alarmDistance"> <el-input v-model.trim="routeForm.alarmDistance" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'必填'" type="text" oninput="value=value.replace(/^\.+|[^\d.]/g,'')"/> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="起点地址"> <el-input v-model.trim="routeForm.startAddress" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'起点地址'" type="text"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="终点地址"> <el-input v-model.trim="routeForm.endAddress" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'终点地址'" type="text"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="主要途径道路"> <el-input v-model.trim="routeForm.mainRoad" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'主要途径道路'" type="text"/> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="8"> <el-form-item label="开始日期"> <el-date-picker v-model="routeForm.startDate" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'开始日期'" style="width: 100%" type="date" value-format="yyyy-MM-dd"/> </el-form-item> </el-col> <el-col :span="8"> <el-form-item label="结束日期"> <el-date-picker v-model="routeForm.endDate" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'结束日期'" style="width: 100%" type="date" value-format="yyyy-MM-dd"/> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="24"> <el-form-item label="准行时间段"> <el-checkbox-group v-model="accessTime"> <el-checkbox v-for="time in times" :label="time" :key="time" :disabled="dialogStatus=='detail'" style="width: 90px;line-height: 10px">{{ time }}:00</el-checkbox> </el-checkbox-group> </el-form-item> </el-col> </el-row> <el-row :gutter="20"> <el-col :span="24"> <el-form-item label="备注"> <el-input v-model.trim="routeForm.remarks" :disabled="dialogStatus=='detail'" :placeholder="dialogStatus=='detail'?'':'备注'" type="textarea" /> </el-form-item> </el-col> </el-row> </el-form> <div style="text-align:center"> <el-button :disabled="!click1" type="primary" style="width: 200px;font-size: 15px;font-weight: bold" @click="saveData">修改路线基本信息</el-button> </div> </el-collapse-item> <el-collapse-item title="(二)关联车辆" name="2"> <el-tabs v-model="activeTab" style="padding-top: 10px;padding-left: 20px;padding-right: 10px" @tab-click="handleClick"> <el-tab-pane label="解绑当前车辆" name="first"> <div class="infinite-list-wrapper" style="overflow:auto;height: 100px;padding-left: 40px;padding-top: 20px"> <el-checkbox-group v-model="removelist" class="checkbox"> <el-checkbox v-for="item in carlist" :label="item.id" :key="item.id" style="width: 150px">{{ item.description }}</el-checkbox> </el-checkbox-group> </div> <div style="text-align:center;padding-top: 10px"> <el-button :disabled="!click2" type="primary" style="width: 200px;font-size: 15px;font-weight: bold" @click="removeCar">解绑车辆</el-button> </div> </el-tab-pane> <el-tab-pane label="增加绑定车辆" name="second"> <el-form ref="selectForm" :inline="true" :model="listQuery" class="form-container" size="small" style="padding-left: 20px"> <el-form-item class="selectForm-container-item" prop="keywords"> <el-input v-model.trim="listQuery.description" style="width: 180px" placeholder="车辆描述" clearable/> </el-form-item> <el-form-item class="selectForm-container-item" prop="keywords"> <el-input v-model="listQuery.carCode" style="width: 180px" placeholder="车牌号" clearable/> </el-form-item> <el-form-item class="selectForm-container-item" prop="keywords"> <el-select v-model="listQuery.carType" style="width: 180px" filterable placeholder="车辆类型" clearable value="" @change="fetchData"> <el-option v-for="item in cartypelist" :key="item.value" :label="item.name" :value="item.value"/> </el-select> </el-form-item> <el-form-item class="selectForm-container-item" prop="keywords"> <dept-select v-if=" activeTab==='second'" v-model="listQuery.deptId" :dept-show="deptShow" style="width: 180px" placeholder="使用单位" clearable value=""/> </el-form-item> <el-button class="filter-item" type="primary" icon="el-icon-search" size="small" @click="search">查 询</el-button> </el-form> <div class="infinite-list-wrapper" style="overflow:auto;height: 100px;padding-left: 20px"> <el-checkbox-group v-model="addlist" class="checkbox"> <el-checkbox v-for="item in list" :label="item.id" :key="item.id" style="width: 150px">{{ item.description }}</el-checkbox> </el-checkbox-group> </div> <div style="text-align:center;padding-top: 10px"> <el-button :disabled="!click3" type="primary" style="width: 200px;font-size: 15px;font-weight: bold" @click="addCar">增加绑定车辆</el-button> </div> </el-tab-pane> </el-tabs> </el-collapse-item> <el-collapse-item title="(三)地图展示" name="3"> <div id="map"/> </el-collapse-item> </el-collapse> </app-container> </template> <script> import { getDictCode } from '@/api/dict' import { updateRouteInfo, listUnbindCar, bindCar, unbindCar, getRouteInfo } from '@/api/routeInfo' import DeptSelect from '@/components/DeptSelect' import L from 'leaflet' import 'leaflet/dist/leaflet.css' export default { components: { DeptSelect }, data() { return { dialogStatus: 'edit', // 对话框类型:create,update activeNames: ['1', '2', '3'], activeTab: 'first', deptShow: true, paramsdata: null, routeId: '', map: null, list: [], click1: true, click2: true, click3: true, alarmlist: [], cartypelist: [], accessTime: [], carlist: [], addlist: [], removelist: [], pathlist: [], baselayer: [], markerlayer: null, addCarForm: { routeId: '', carIds: [] }, removeCarForm: { routeId: '', carIds: [] }, listQuery: { routeId: '', description: '', carCode: '', carType: '', deptId: '' }, routeForm: { id: '', routeName: '', alarmType: '', alarmDistance: '', startAddress: '', endAddress: '', mainRoad: '', startDate: '', endDate: '', accessTime: '', remarks: '' }, // 表单 times: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23], options: [{ value: '0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23', label: '全天(0-23)' }, { value: '8,9,10,11,12,13,14,15,16,17,18', label: '工作时间段(8-18)' }, { value: '8,9,10,11,12', label: '上午工作时间段(8-12)' }, { value: '14,15,16,17,18', label: '下午工作时间段(14-18)' }, { value: '-1', label: '自定义时间段' }], rules: { routeName: [{ required: true, message: '路线描述不能为空', trigger: ['blur', 'change'] }], alarmType: [{ required: true, message: '报警类型必选', trigger: ['blur', 'change'] }], alarmDistance: [{ required: true, message: '偏离报警距离不能为空', trigger: ['blur', 'change'] }] } } }, activated() { this.initdata() }, mounted() { getDictCode('routeAlarmType').then(response => { this.alarmlist = response.data }) getDictCode('carType').then(response => { this.cartypelist = response.data }) this.initMap() this.initdata() }, methods: { setZoom(points) { console.log(points) if (points.length > 0) { var maxLng = points[0][1] var minLng = points[0][1] var maxLat = points[0][0] var minLat = points[0][0] var res for (var i = points.length - 1; i >= 0; i--) { res = points[i] if (res[1] > maxLng) maxLng = res[1] if (res[1] < minLng) minLng = res[1] if (res[0] > maxLat) maxLat = res[0] if (res[0] < minLat) minLat = res[0] } var cenLng = (parseFloat(maxLng) + parseFloat(minLng)) / 2 var cenLat = (parseFloat(maxLat) + parseFloat(minLat)) / 2 var zoom = this.getZoom(maxLng, minLng, maxLat, minLat) this.map.setView({ lat: cenLat, lng: cenLng }, zoom) } else { // 没有坐标,显示全中国 this.map.setView({ lat: 103.388611, lng: 35.563611 }, 5) } }, getZoom(maxLng, minLng, maxLat, minLat) { var zoom = ['50', '100', '200', '500', '1000', '2000', '5000', '10000', '20000', '25000', '50000', '100000', '200000', '500000', '1000000', '2000000']// 级别18到3。 var latlng = L.latLng(maxLat, maxLng) var distance = latlng.distanceTo(L.latLng(minLat, minLng)) // var distance = pointA.distanceTo(pointB)// 获取两点距离,保留小数点后两位 for (var i = 0, zoomLen = zoom.length; i < zoomLen; i++) { if (zoom[i] - distance > 0) { console.log(i) return 18 - i + 2 // 之所以会多2,是因为地图范围常常是比例尺距离的10倍以上。所以级别会增加3。 } } }, setCenter(points) { // 获取折线中心点坐标 if (points.length > 0) { let maxLng = points[0][1] let minLng = points[0][1] let maxLat = points[0][0] let minLat = points[0][0] let res for (let i = points.length - 1; i >= 0; i--) { res = points[i] if (res[1] > maxLng) maxLng = res[1] if (res[1] < minLng) minLng = res[1] if (res[0] > maxLat) maxLat = res[0] if (res[0] < minLat) minLat = res[0] } const cenLng = (parseFloat(maxLng) + parseFloat(minLng)) / 2 const cenLat = (parseFloat(maxLat) + parseFloat(minLat)) / 2 this.map.setView({ lat: cenLat, lng: cenLng }) } }, initdata() { if (this.$route.query) { this.routeId = this.$route.query.id this.listQuery.routeId = this.$route.query.id this.routeForm = { id: this.$route.query.id, routeName: this.$route.query.routeName, alarmType: this.$route.query.alarmType, alarmDistance: this.$route.query.alarmDistance, startAddress: this.$route.query.startAddress, endAddress: this.$route.query.endAddress, mainRoad: this.$route.query.mainRoad, startDate: this.$route.query.startDate, endDate: this.$route.query.endDate, accessTime: this.$route.query.accessTime, remarks: this.$route.query.remarks } if (this.routeForm.accessTime.length !== 0) { var accesslist = this.routeForm.accessTime.split(',') this.accessTime = [] for (var i = 0; i < accesslist.length; i++) { this.accessTime.push(Number(accesslist[i])) } } } getRouteInfo(this.routeId).then(response => { this.carlist = response.data.carList this.removelist = [] for (var i = 0; i < this.carlist.length; i++) { this.removelist.push(this.carlist[i].id) } this.pathlist = [] for (i = 0; i < response.data.pathList.length; i++) { var item = [Number(response.data.pathList[i].startLat), Number(response.data.pathList[i].startLng)] this.pathlist.push(item) if (i === response.data.pathList.length - 1) { item = [Number(response.data.pathList[i].endLat), Number(response.data.pathList[i].endLng)] this.pathlist.push(item) } } if (this.pathlist.length !== 0) { this.drawmap() } }) this.fetchData() }, handleClick() { getRouteInfo(this.routeId).then(response => { this.carlist = response.data.carList this.addlist = [] this.removelist = [] for (var i = 0; i < this.carlist.length; i++) { this.removelist.push(this.carlist[i].id) } this.fetchData() }) }, initMap() { const map = L.map('map', { minZoom: 3, maxZoom: 18, center: [27.75962, 116.06021], zoom: 12, zoomControl: false, attributionControl: false, crs: L.CRS.EPSG3857 }) this.map = map // data上需要挂载 window.map = map this.baselayer.push(L.tileLayer( 'https://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=216ee92889e17ab1b083fae665d522b8', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } ).addTo(map)) this.baselayer.push(L.tileLayer( 'https://t0.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=216ee92889e17ab1b083fae665d522b8', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] } ).addTo(map)) }, drawmap() { var myStyle = { 'color': '#409eff', 'weight': 4.5, 'opacity': 0.7 } L.polyline(this.pathlist, myStyle).addTo(this.map) var Icon for (var i = 0; i < this.pathlist.length; i++) { if (i === 0) { Icon = L.icon({ iconUrl: require('../../assets/global_images/start.png'), iconSize: [45, 45] }) } else if (i === this.pathlist.length - 1) { Icon = L.icon({ iconUrl: require('../../assets/global_images/end.png'), iconSize: [45, 45] }) } else { Icon = L.divIcon({ className: 'my-div-icon', // 自定义icon css样式 iconSize: [15, 15]// 点大小 }) } L.marker([this.pathlist[i][0], this.pathlist[i][1]], { icon: Icon }).addTo(this.map) } this.setZoom(this.pathlist) }, fetchData() { listUnbindCar(this.listQuery).then(response => { this.list = response.data }) }, search() { this.fetchData(false) }, addCar() { this.click3 = false if (this.addlist.length === 0) { this.click3 = true this.$message.warning('请至少选择一辆车') } else { this.addCarForm.routeId = this.routeId this.addCarForm.carIds = [] for (var i = 0; i < this.addlist.length; i++) { this.addCarForm.carIds.push(Number(this.addlist[i])) } bindCar(this.addCarForm).then(response => { if (response.code === 200) { this.$message.success('绑定车辆信息成功!') } }) } }, removeCar() { this.click2 = false if (this.removelist.length === 0) { this.click2 = true this.$message.warning('请至少选择一辆车解绑') } else { this.removeCarForm.routeId = this.routeId this.removeCarForm.carIds = [] for (var i = 0; i < this.removelist.length; i++) { this.removeCarForm.carIds.push(Number(this.removelist[i])) } console.log(this.removeCarForm) unbindCar(this.removeCarForm).then(response => { if (response.code === 200) { this.$message.success('解绑车辆成功!') this.handleClick() } }) } }, saveData() { this.click1 = false this.$refs['dataForm'].validate((valid) => { if (valid) { if (this.routeForm.startDate > this.routeForm.endDate) { this.click1 = true this.$message.warning('请确认输入正确起止时间') } else { this.routeForm.accessTime = this.accessTime[0] for (var i = 1; i < this.accessTime.length; i++) { this.routeForm.accessTime += (',' + this.accessTime[i]) } updateRouteInfo(this.routeForm).then(response => { if (response.code === 200) { this.$message.success('修改规划路线基本信息成功!') } }) } } else { this.click1 = true } }) } } } </script> <style rel="stylesheet/scss" lang="scss"> /*#editroute . {*/ /*font-size: 15px ;*/ /*font-weight: bold;*/ /*}*/ #editroute .el-checkbox__label { font-size: 15px ; font-weight: bold; } #editroute .el-form-item { margin-bottom: 18px; } #editroute .el-dialog__body { padding-top: 0px ; padding-left: 0px; padding-right: 0px; } #map { width:100%; height:50vh; } .my-div-icon { width: 10px; height: 10px; background-color: orange; border-radius: 50%; } .route-coll{ .el-collapse-item__header{ font-weight: bolder; margin-left: 10px; } } </style>