212 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			212 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | ||
|   <section class="AppISMap">
 | ||
|     <device-slider :show.sync="slider" :instance="instance" :dict="dict" @list="v=>list=v" @select="markerClickEvent"/>
 | ||
|     <div id="amap"/>
 | ||
|     <div ref="selectedInfoWin" class="selected">
 | ||
|       <b>{{ selected.deviceName }}</b>
 | ||
|       <div>{{ selected.lng }},{{ selected.lat }}</div>
 | ||
|       <div v-if="selected.address">{{ selected.address }}</div>
 | ||
|       <div btn @click="handleShowMonitor">查看监控</div>
 | ||
|     </div>
 | ||
|     <el-dialog class="monitorDialog" :modal="false" :visible.sync="dialog" :title="selected.deviceName||'视频监控'"
 | ||
|                width="640px" @closed="monitor=''">
 | ||
|       <iframe v-if="monitor" :src="monitor" allow="autoplay *; microphone *; fullscreen *" allowfullscreen
 | ||
|               allowtransparency allowusermedia frameBorder="no"/>
 | ||
|     </el-dialog>
 | ||
|   </section>
 | ||
| </template>
 | ||
| 
 | ||
| <script>
 | ||
| import DeviceSlider from "./components/deviceSlider";
 | ||
| import AMapLoader from "@amap/amap-jsapi-loader";
 | ||
| 
 | ||
| export default {
 | ||
|   name: "AppISMap",
 | ||
|   components: {DeviceSlider},
 | ||
|   label: "监控地图",
 | ||
|   props: {
 | ||
|     instance: Function,
 | ||
|     dict: Object,
 | ||
|     permissions: Function
 | ||
|   },
 | ||
|   data() {
 | ||
|     return {
 | ||
|       slider: true,
 | ||
|       AMap: null,
 | ||
|       map: null,
 | ||
|       selected: {},
 | ||
|       list: [],
 | ||
|       deviceToken: "",
 | ||
|       dialog: false,
 | ||
|       monitor: ""
 | ||
|     }
 | ||
|   },
 | ||
|   watch: {
 | ||
|     list: {
 | ||
|       immediate: true,
 | ||
|       handler(v) {
 | ||
|         if (v.length > 0) {
 | ||
|           this.renderDevicesOnMap()
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
|   },
 | ||
|   methods: {
 | ||
|     initMap() {
 | ||
|       return new Promise(resolve => AMapLoader.load({
 | ||
|         key: "b553334ba34f7ac3cd09df9bc8b539dc",
 | ||
|         version: '2.0',
 | ||
|         plugins: ['AMap.Marker', 'AMap.PlaceSearch'],
 | ||
|       }).then(AMap => {
 | ||
|         this.AMap = AMap
 | ||
|         this.map = new this.AMap.Map('amap', {
 | ||
|           zoom: 14,
 | ||
|         })
 | ||
|         resolve()
 | ||
|       }))
 | ||
|     },
 | ||
|     renderDevicesOnMap() {
 | ||
|       this.list?.map(e => {
 | ||
|         if (this.AMap && e?.lat) {
 | ||
|           e.marker = new this.AMap.Marker({
 | ||
|             icon: this.$cdn + 'monitor/camera.png',
 | ||
|             position: new this.AMap.LngLat(e.lng, e.lat)
 | ||
|           }).on('click', () => this.markerClickEvent(e))
 | ||
|           this.map.add(e.marker)
 | ||
|         }
 | ||
|       })
 | ||
|     },
 | ||
|     markerClickEvent(device) {
 | ||
|       if (device?.marker) {
 | ||
|         this.map?.setCenter(new this.AMap.LngLat(device.lng, device.lat))
 | ||
|         device.marker.setIcon(this.$cdn + 'monitor/cameraSelected.png')
 | ||
|         this.selected = device
 | ||
|         let win = new this.AMap.InfoWindow({
 | ||
|           isCustom: true,
 | ||
|           autoMove: true,
 | ||
|           closeWhenClickMap: true,
 | ||
|           content: this.$refs.selectedInfoWin
 | ||
|         }).on('close', () => {
 | ||
|           device.marker.setIcon(this.$cdn + 'monitor/camera.png')
 | ||
|           this.selected = {}
 | ||
|         })
 | ||
|         win.open(this.map, new this.AMap.LngLat(device.lng, device.lat))
 | ||
|       }
 | ||
|     },
 | ||
|     getDeviceToken() {
 | ||
|       this.instance.post("/app/appzyvideoequipment/getAppUserToken").then(res => {
 | ||
|         if (res?.data) {
 | ||
|           this.deviceToken = res.data
 | ||
|         }
 | ||
|       })
 | ||
|     },
 | ||
|     handleShowMonitor() {
 | ||
|       this.dialog = true
 | ||
|       this.instance.post("/app/appzyvideoequipment/getWebSdkUrl", null, {
 | ||
|         params: {token: this.deviceToken, deviceId: this.selected.deviceId}
 | ||
|       }).then(res => {
 | ||
|         if (res?.data) {
 | ||
|           let data = JSON.parse(res.data)
 | ||
|           this.monitor = data.url
 | ||
|         }
 | ||
|       })
 | ||
|     }
 | ||
|   },
 | ||
|   created() {
 | ||
|     this.initMap().then(() => setTimeout(() => this.renderDevicesOnMap(), 1000))
 | ||
|   }
 | ||
| }
 | ||
| </script>
 | ||
| 
 | ||
| <style lang="scss" scoped>
 | ||
| .AppISMap {
 | ||
|   background: #202330;
 | ||
|   position: relative;
 | ||
| 
 | ||
|   .deviceSlider {
 | ||
|     position: absolute;
 | ||
|     left: 0;
 | ||
|     top: 0;
 | ||
|     bottom: 0;
 | ||
|     z-index: 66;
 | ||
|   }
 | ||
| 
 | ||
|   #amap {
 | ||
|     width: 100%;
 | ||
|     height: 100%;
 | ||
|   }
 | ||
| 
 | ||
|   .selected {
 | ||
|     background: #fff;
 | ||
|     min-width: 280px;
 | ||
|     box-sizing: border-box;
 | ||
|     box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.1);
 | ||
|     padding: 12px;
 | ||
|     color: #999;
 | ||
|     font-size: 12px;
 | ||
| 
 | ||
|     b {
 | ||
|       color: #333;
 | ||
|       font-size: 16px;
 | ||
|     }
 | ||
| 
 | ||
|     & > * + * {
 | ||
|       margin-top: 4px;
 | ||
|     }
 | ||
| 
 | ||
|     div[btn] {
 | ||
|       cursor: pointer;
 | ||
|       color: #89b;
 | ||
|       font-size: 14px;
 | ||
|     }
 | ||
| 
 | ||
|   }
 | ||
| 
 | ||
|   :deep( .monitorDialog ){
 | ||
| 
 | ||
|     .el-dialog__header {
 | ||
|       font-size: 14px;
 | ||
|       color: #FFF;
 | ||
|       height: 40px;
 | ||
|       padding: 0 16px;
 | ||
|       background: linear-gradient(180deg, #313B5B 0%, #1B202F 100%);
 | ||
|       display: flex;
 | ||
|       align-items: center;
 | ||
|       width: 100%;
 | ||
|       box-sizing: border-box;
 | ||
| 
 | ||
|       span {
 | ||
|         color: #fff;
 | ||
|         flex: 1;
 | ||
|         min-width: 0;
 | ||
|       }
 | ||
| 
 | ||
|       .el-dialog__headerbtn {
 | ||
|         position: relative;
 | ||
|         top: unset;
 | ||
|         right: unset;
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     .el-dialog__body {
 | ||
|       padding: 0;
 | ||
|       height: 360px;
 | ||
|     }
 | ||
| 
 | ||
|     iframe {
 | ||
|       width: 100%;
 | ||
|       height: 100%;
 | ||
|     }
 | ||
|   }
 | ||
| 
 | ||
|   :deep( .amap-logo), :deep( .amap-copyright ){
 | ||
|     display: none !important;
 | ||
|   }
 | ||
| 
 | ||
|   :deep( .amap-marker-label ){
 | ||
|     border-color: transparent;
 | ||
|     box-shadow: 1px 1px 0 0 rgba(#999, .2);
 | ||
|   }
 | ||
| }
 | ||
| </style>
 |