<template> <app-container id="overview"> <div id="map"> <div v-if="bottombtn==='消防车'" slot="header" class="rightcard"> <el-row> <el-col :span="3"> <div style="font-size: 14px;padding-top: 10px;">在线:{{ online }}</div> </el-col> <el-col :span="3"> <div style="font-size: 14px;padding-top: 10px">离线:{{ offline }}</div> </el-col> <el-col :span="3"> <div style="font-size: 14px;padding-top: 10px;padding-left: 5px">刷新时间</div> </el-col> <el-col :span="9" style="padding-top: 12px;padding-left: 10px"> <el-radio-group v-model="refresh" @change="clicktime"> <el-radio label="10">10秒</el-radio> <el-radio label="30">30秒</el-radio> <el-radio label="60">60秒</el-radio> </el-radio-group> </el-col> <el-col :span="4" style="padding-top: 10px"> <label style="font-size: 14px;padding-left: 5px;color: red">{{ sec }}</label> <label style="font-size: 14px">秒后刷新</label> </el-col> <el-col :span="2" style="padding-top: 4px;padding-left: 5px"> <el-button type="primary" size="small" @click="fetchData(false)">立即刷新</el-button> </el-col> </el-row> </div> <div slot="header" class="table-title" @click="showtable=!showtable"> <div class="table-name"> {{ bottombtn }}列表 </div> <i v-if="showtable==true" class="el-icon-arrow-down" style="position:absolute; right:20px;top:20px;margin-top:-8px;"/> <i v-if="showtable==false" class="el-icon-arrow-right" style="position:absolute; right:20px;top:20px;margin-top:-8px;"/> </div> <div v-if="showtable==true"> <div v-if="bottombtn==='消防车'" class="search-bar"> <el-input v-model.trim="listQuery.description" style="width: 180px;margin-right: 10px" placeholder="车辆描述" size="small" clearable/> <el-input v-model="listQuery.carCode" style="width: 180px;margin-right: 10px" placeholder="车牌号" size="small" clearable/> <el-button type="primary" size="small" style="height:32px" @click="search">搜索</el-button> </div> <el-table v-loading="listLoading" :row-style="{height: '35px'}" :cell-style="{padding: '0px'}" :header-cell-style="{background: '#ffffff'}" :data="list" max-height="300" class="table" border @row-dblclick="dbSelected" @selection-change="handleSelectionChange"> <el-table-column :index="indexMethod" align="center" type="index" label="序号" width="55"/> <el-table-column v-for="column in columns" :key="column.value" :label="column.text" :width="column.width" :align="column.align" show-overflow-tooltip> <template slot-scope="scope"> <span :class="column.class">{{ scope.row[column.value] }}</span> </template> </el-table-column> <el-table-column v-if="bottombtn==='消防车'" label="更多" width="110" align="center"> <template slot-scope="scope"> <el-button type="text" size="mini" @click="track(scope.row.carId)">跟踪</el-button> <el-button type="text" size="mini" @click="trail(scope.row.carId,scope.row)">轨迹</el-button> </template> </el-table-column> </el-table> <div class="pagination-container" style="width: 460px"> <el-pagination v-show="total>listQuery.limit" :current-page="listQuery.offset" :page-sizes="[10,15,20,30]" :page-size="listQuery.limit" :total="total" class="table-bottom" page-count="5" small="true" align="center" layout="total, sizes, prev, pager, next" @size-change="handleSizeChange" @current-change="handleCurrentChange"/> </div> </div> <div class="btn_bottom" style="margin-bottom: 10px"> <div style="width: 252px;position: relative;margin: 0px auto;text-align: center"> <el-radio-group v-model="bottombtn" @change="fetchData(false)"> <el-radio-button label="消防车"> <el-image :src="require('../../assets/global_images/car1.png')" fit="contain" style="width: 35px;height: 35px"/> <div>消防车</div> </el-radio-button> <el-radio-button label="井盖"> <el-image :src="require('../../assets/global_images/wall.png')" fit="contain" style="width: 35px;height: 35px;" /> <div>井盖</div> </el-radio-button> <el-radio-button label="消防栓"> <el-image :src="require('../../assets/global_images/hydrant.png')" fit="contain" style="width: 35px;height: 35px;"/> <div>消防栓</div> </el-radio-button> </el-radio-group> </div> </div> </div> </app-container> </template> <script> // import editCarInfo from '@/views/carinfo/editCarInfo' import { getOverviewList, offlineCount, getOverviewAllList } from '@/api/overview' import DeptSelect from '@/components/DeptSelect' import L from 'leaflet' import 'leaflet/dist/leaflet.css' import 'leaflet-rotatedmarker/leaflet.rotatedMarker.js' import { getWellList, watchDataByWell } from '@/api/well' export default { name: 'ListOverview', components: { DeptSelect }, data() { return { bottombtn: '消防车', dialogFormVisible: false, // 是否显示编辑框 refresh: '30', showBase: false, online: 0, offline: 0, showtable: true, deptShow: true, listQuery: { description: '', wellType: '', carCode: '', carType: '', deptId: '', offset: 1, limit: 15 }, // 查询条件 listLoading: true, // 加载动画 columns: [ { text: '车辆描述', value: 'description', align: 'center' }, { text: '车牌号', value: 'carCode', align: 'center', width: 90 }, { text: '状态', value: 'status', align: 'center', width: 70 } ], // 动态加载的表头 pointlayer: null, featurelayer: null, baselayer: [], baseUrl: '', mapUrl: '', list: [], // 列表数据 alllist: [], // 列表数据 map: null, initlocation: false, total: 0, // 数据总数 sec: 10, // 数据总数 // listLoading: true, // 加载动画 fullscreenLoading: false, // 全屏加载动画 deptlist: [] // 类型列表 } }, watch: { showBase(val) { if (val) this.map.addLayer(this.featurelayer) else this.map.removeLayer(this.featurelayer) }, sec(val) { if (val === 0) { this.sec = Number(this.refresh) if (this.bottombtn === '消防车') { this.fetchData(true) } } } }, mounted() { this.initMap() setInterval(() => { this.sec-- }, 1000) }, methods: { dbSelected(row) { this.map.setView({ lat: Number(row.lat), lng: Number(row.lng) }, 18) }, // detail(id) { // this.dialogFormVisible = true // var item = { id: id } // this.$refs.editCarInfo.initDialog('detail', this.dialogFormVisible, item) // }, track(id) { this.$router.push({ name: 'Track', query: { id: id } }) }, trail(id, row) { this.$router.push({ name: 'Trail', query: { id: id, name: row.carCode + '-' + row.carTypeName } }) }, async initMap() { const map = L.map('map', { minZoom: 3, maxZoom: 18, center: [27.75962, 116.06021], zoom: 16, zoomControl: false, attributionControl: false, crs: L.CRS.EPSG3857 }) map.doubleClickZoom.disable() this.map = map // data上需要挂载 window.map = map var url = 'http://webrd0{s}.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8' this.baselayer.push( L.tileLayer(url, { subdomains: '1234' }).addTo(map)) this.fetchData(false) }, search() { this.fetchData(false) }, clicktime() { this.sec = Number(this.refresh) }, 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) { return 18 - i + 2 // 之所以会多2,是因为地图范围常常是比例尺距离的10倍以上。所以级别会增加3。 } } }, fetchData(isNowPage = true) { this.listLoading = true this.list = [] if (this.bottombtn === '消防车') { this.columns = [ { text: '车辆描述', value: 'description', align: 'center' }, { text: '车牌号', value: 'carCode', align: 'center', width: 90 }, { text: '状态', value: 'status', align: 'center', width: 70 } ] offlineCount(this.listQuery).then(response => { this.online = response.data.online this.offline = response.data.offline }) this.sec = Number(this.refresh) if (!isNowPage) { this.listQuery.offset = 1 } getOverviewList(this.listQuery).then(response => { this.list = response.data.rows this.total = parseInt(response.data.total) this.listLoading = false }) getOverviewAllList(this.listQuery).then(response => { this.alllist = response.data if (this.pointlayer !== null) this.map.removeLayer(this.pointlayer) this.pointlayer = new L.layerGroup().addTo(this.map) var list = [] for (i = 0; i < this.alllist.length; i++) { if (Number(this.alllist[i].lat) === 0 && Number(this.alllist[i].lng) === 0) { continue } var item = [Number(this.alllist[i].lat), Number(this.alllist[i].lng)] list.push(item) } // if (list.length !== 0) { // this.setZoom(list) // } var Icon for (var i = 0; i < this.alllist.length; i++) { if (i === 0 && !this.initlocation) { this.map.setView({ lat: this.alllist[0].lat, lng: this.alllist[0].lng }, 16) this.initlocation = true } if (this.alllist[i].status === '离线') { Icon = L.icon({ iconUrl: require('../../assets/global_images/car-offline.png'), // 灰 iconSize: [40, 40] }) } else if (this.alllist[i].status === '超时') { Icon = L.icon({ iconUrl: require('../../assets/global_images/car-timeout.png'), // 橙 iconSize: [40, 40] }) } else if (this.alllist[i].status === '停车') { Icon = L.icon({ iconUrl: require('../../assets/global_images/car-stop.png'), // 黄 iconSize: [40, 40] }) } else if (this.alllist[i].status === '行驶') { Icon = L.icon({ iconUrl: require('../../assets/global_images/car-online.png'), // 绿 iconSize: [40, 40] }) } else if (this.alllist[i].status === '报警') { Icon = L.icon({ iconUrl: require('../../assets/global_images/car-alarm.png'), // 红 iconSize: [40, 40] }) } var myIcon = L.divIcon({ html: '<div style="font-size: 13px;font-weight: bold;padding-top: 17px;text-align:center;"> ' + this.alllist[i].description + '</div>', className: '', iconSize: [100, 15] }) L.marker([this.alllist[i].lat, this.alllist[i].lng], { icon: myIcon }).addTo(this.pointlayer) const { carId, description, carTypeName, deptName, status, lng, lat, upTime, speed, liquidValue } = this.alllist[i] var btndetail = 'btndetail' + carId var btntrack = 'btntrack' + carId var btntrail = 'btntrail' + carId var str = `<div style="font-size: 15px;padding: 6px"> <div style="font-weight: bold;padding-bottom: 10px">车辆位置概要信息</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">描述</label> ${description}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">类型</label> ${carTypeName}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">单位</label> ${deptName}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">状态</label> ${status}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">定位</label> ${lng} , ${lat}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">时间</label> ${upTime}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">速度</label> ${speed} (km/h)</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">液位值</label> ${liquidValue} </div> <!--<div style="padding-top: 8px"><button style="margin-left: 80px;background-color: #42b983;border-color: #42b983;color: white;padding: 5px 8px;font-size: 12px;border-radius: 4px" id=${btndetail}>详情</button>--> <button style="padding-top: 8px;margin-right: 5px;margin-left: 5px;background-color: #409eff;border-color: #409eff; color: white;padding: 5px 8px;font-size: 12px;border-radius: 4px" id=${btntrack}>跟踪</button> <button style="background-color: #e6a23c;border-color: #e6a23c;color: white;padding: 5px 8px;font-size: 12px;border-radius: 4px" id=${btntrail}>轨迹</button></div></div>` var popup = L.popup().setContent(str) var marker = L.marker([this.alllist[i].lat, this.alllist[i].lng], { icon: Icon, slug: this.alllist[i], rotationAngle: this.alllist[i].direction, zIndexOffset: 100000 }).addTo(this.pointlayer).bindPopup(popup) var that = this marker.on('click', function(e) { var carId = e.sourceTarget.options.slug.carId var btndetail = 'btndetail' + carId var btntrack = 'btntrack' + carId var btntrail = 'btntrail' + carId console.log('按钮:', document.getElementById(btndetail)) // document.getElementById(btndetail).onclick = function() { // console.log('carId:', e.sourceTarget.options.slug.carId) // that.detail(e.sourceTarget.options.slug.carId) // } document.getElementById(btntrack).onclick = function() { that.track(e.sourceTarget.options.slug.carId) } document.getElementById(btntrail).onclick = function() { that.trail(e.sourceTarget.options.slug.carId, e.sourceTarget.options.slug) } }) } }) } else { this.inittable(this.bottombtn) } }, inittable(type) { const that = this if (type === '井盖') { this.columns = [ { text: '井盖编号', value: 'wellCode', align: 'center' }, { text: '井盖名称', value: 'wellName', align: 'center' }, { text: '类型', value: 'wellTypeName', align: 'center', width: 90 } ] } else if (type === '消防栓') { this.columns = [ { text: '消防栓编号', value: 'wellCode', align: 'center' }, { text: '消防栓名称', value: 'wellName', align: 'center' }, { text: '类型', value: 'wellTypeName', align: 'center', width: 70 } ] } this.listQuery.wellType = type === '井盖' ? '1' : '2' getWellList(this.listQuery).then(response => { this.list = response.data.rows this.total = response.data.total this.listLoading = false if (this.pointlayer !== null) this.map.removeLayer(this.pointlayer) this.pointlayer = new L.layerGroup().addTo(this.map) var list = [] for (i = 0; i < this.list.length; i++) { if (Number(this.list[i].latGaode) === 0 && Number(this.list[i].lngGaode) === 0) { continue } var item = [Number(this.list[i].latGaode), Number(this.list[i].lngGaode)] list.push(item) } if (list.length !== 0) { this.setZoom(list) } var Icon = L.icon({ iconUrl: require('../../assets/global_images/' + type + '.png'), iconSize: [40, 40] }) for (var i = 0; i < this.list.length; i++) { // if (i === 0 && !this.initlocation) { // this.map.setView({ lat: this.list[0].lat, lng: this.list[0].lng }, 16) // this.initlocation = true // } const { wellCode, wellName, position, bfztName, lngGaode, latGaode } = this.list[i] const str = `<div style="font-size: 15px;padding: 6px;width: 300px"> <div style="font-weight: bold;padding-bottom: 10px">${type}概要信息</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">编号</label> ${wellCode}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">名称</label> ${wellName}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">详细地址</label> ${position}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">布防状态</label> ${bfztName}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">定位</label> ${Number(lngGaode).toFixed(6)} , ${Number(latGaode).toFixed(6)}</div> <div style="padding-bottom: 6px"><label style="font-weight: bold;padding-right: 15px">设备监测值</label></div></div>` // const popup = L.popup().setContent(str) L.marker([this.list[i].latGaode, this.list[i].lngGaode], { id: this.list[i].id, icon: Icon, slug: str, rotationAngle: this.list[i].direction, zIndexOffset: 100000 }).addTo(this.pointlayer)// .bindPopup(popup) .on('click', function(e) { console.log(e) watchDataByWell(e.target.options.id).then(response => { let content = e.sourceTarget.options.slug if (response.data.length !== 0) { content = content.slice(0, content.length - 12) + response.data[0].data + content.slice(content.length - 12) } L.popup().setLatLng(e.latlng).setContent(content).openOn(that.map)// 通过popup添加点击弹出框 }) }) } }) }, indexMethod(index) { return this.listQuery.limit * (this.listQuery.offset - 1) + index + 1 }, // 改变页容量 handleSizeChange(val) { this.listQuery.limit = val this.fetchData(true) }, // 改变当前页 handleCurrentChange(val) { this.listQuery.offset = val this.fetchData(true) }, // 多选触发方法 handleSelectionChange(val) { this.multipleSelection = val } } } </script> <style rel="stylesheet/scss" lang="scss" scoped> .rightcard{ /*width: 750px;*/ height: 40px; z-index: 10000; position: absolute; /*left:500px;*/ top:10px; right: 0; background-color: #ffffff; padding-left: 20px; padding-right: 50px; } .table-bottom{ position: relative; left: 11px; /*top: 20px;*/ z-index: 10001; float: left; width: 458px; background-color: #ffffff; /* margin-top: 20px; */ margin-top: 25px; padding-bottom: 10px; } .table-name{ position:relative; width: 100px; color:#666666; top:20px; margin:-10px auto; //外面的div高度的一半 z-index: 100001; } .table-title{ font-size: 15px; text-align:center; width: 460px; height: 40px; background-color: #ffffff; z-index: 10000; position: absolute; left:10px; top:0px; font-weight: bold; } #map { width:100%; height: 90vh; /*border-top: 12px solid #ebebeb;*/ } /deep/ .el-table--scrollable-y .el-table__body-wrapper{ padding-bottom: 11px !important; } /deep/ .el-radio{ margin-right: 5px; } /deep/ .el-radio__label{ padding-left: 5px; } .table{ width: 460px; z-index: 10000; position: relative; left:10px; top:40px; } .search-bar{ width: 460px; z-index: 10000; position: relative; left:10px; top:40px; padding: 0px 10px; display: flex; height: 40px; background-color: white; z-index: 1000; } .btn_bottom{ text-align:center; width: 100%; height:70px; z-index: 1000; position: fixed; bottom: 0; left: 0;right:0; } </style>