调整目录结构使其能够被引用
This commit is contained in:
		| @@ -6,7 +6,7 @@ | ||||
|         <ai-search-bar> | ||||
|           <template #right> | ||||
|             <el-input prefix-icon="iconfont iconSearch" v-model="search.title" placeholder="设备名、MAC号" clearable | ||||
|             @clear="page.current = 1,search.title = '', getTableData()" | ||||
|                       @clear="page.current = 1,search.title = '', getTableData()" | ||||
|                       v-throttle="() => {page.current = 1, getTableData()}" size="small"/> | ||||
|           </template> | ||||
|         </ai-search-bar> | ||||
| @@ -26,18 +26,17 @@ | ||||
|         </ai-table> | ||||
|       </template> | ||||
|     </ai-list> | ||||
|     <locate-dialog v-model="locate" :ins="instance" @confirm="v=>handleLocate(detail,v)"/> | ||||
|     <ai-locate-dialog v-model="locate" :ins="instance" @confirm="v=>handleLocate(detail,v)"/> | ||||
|     <setting-dialog v-model="dialog" :ins="instance"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import LocateDialog from "./components/locateDialog"; | ||||
| import SettingDialog from "./components/settingDialog"; | ||||
|  | ||||
| export default { | ||||
|   name: "AppMonitorDevice", | ||||
|   components: {SettingDialog, LocateDialog}, | ||||
|   components: {SettingDialog}, | ||||
|   label: "监控设备管理", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|   | ||||
| @@ -25,169 +25,168 @@ | ||||
|         </el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|     <locate-dialog v-model="locate" :ins="instance" :latlng="latlng" @confirm="v=>handleLocate(selected,v)"/> | ||||
|     <ai-locate-dialog v-model="locate" :ins="instance" :latlng="latlng" @confirm="v=>handleLocate(selected,v)"/> | ||||
|     <ai-area custom-clicker :input-clicker="false" v-model="selected.areaId" :hideLevel="disabledLevel" :instance="instance" ref="BindArea" | ||||
|              @change="handleSubmit(selected)"/> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
|   import { mapState } from 'vuex' | ||||
|   import DeviceSlider from "./components/deviceSlider"; | ||||
|   import LocateDialog from "./components/locateDialog"; | ||||
| import {mapState} from 'vuex' | ||||
| import DeviceSlider from "./components/deviceSlider"; | ||||
|  | ||||
|   export default { | ||||
|     name: "AppMonitorManage", | ||||
|     components: {LocateDialog, DeviceSlider}, | ||||
|     label: "监控实况", | ||||
|     props: { | ||||
|       instance: Function, | ||||
|       dict: Object, | ||||
|       permissions: Function | ||||
| export default { | ||||
|   name: "AppMonitorManage", | ||||
|   components: {DeviceSlider}, | ||||
|   label: "监控实况", | ||||
|   props: { | ||||
|     instance: Function, | ||||
|     dict: Object, | ||||
|     permissions: Function | ||||
|   }, | ||||
|   computed: { | ||||
|     splitOps() { | ||||
|       return [ | ||||
|         {label: "单分屏", value: 1, per: "100%"}, | ||||
|         {label: "四分屏", value: 4, per: "49%"}, | ||||
|         {label: "九分屏", value: 9, per: "32%"} | ||||
|       ] | ||||
|     }, | ||||
|     computed: { | ||||
|       splitOps() { | ||||
|         return [ | ||||
|           {label: "单分屏", value: 1, per: "100%"}, | ||||
|           {label: "四分屏", value: 4, per: "49%"}, | ||||
|           {label: "九分屏", value: 9, per: "32%"} | ||||
|         ] | ||||
|       }, | ||||
|       currentSplitStyle() { | ||||
|         let per = this.splitOps.find(e => e.value == this.splitScreen)?.per || "100%" | ||||
|         return {width: per, height: per} | ||||
|       }, | ||||
|       ...mapState(['user']) | ||||
|     currentSplitStyle() { | ||||
|       let per = this.splitOps.find(e => e.value == this.splitScreen)?.per || "100%" | ||||
|       return {width: per, height: per} | ||||
|     }, | ||||
|     ...mapState(['user']) | ||||
|   }, | ||||
|  | ||||
|     data() { | ||||
|       return { | ||||
|         slider: true, | ||||
|         fullscreen: false, | ||||
|         splitScreen: 1, | ||||
|         monitors: [], | ||||
|         dialog: false, | ||||
|         locate: false, | ||||
|         selected: { | ||||
|           areaId: '' | ||||
|         }, | ||||
|         latlng: null, | ||||
|         disabledLevel: 0, | ||||
|         rules: { | ||||
|           name: [{required: true, message: "请填写 设备名称"}] | ||||
|         } | ||||
|   data() { | ||||
|     return { | ||||
|       slider: true, | ||||
|       fullscreen: false, | ||||
|       splitScreen: 1, | ||||
|       monitors: [], | ||||
|       dialog: false, | ||||
|       locate: false, | ||||
|       selected: { | ||||
|         areaId: '' | ||||
|       }, | ||||
|       latlng: null, | ||||
|       disabledLevel: 0, | ||||
|       rules: { | ||||
|         name: [{required: true, message: "请填写 设备名称"}] | ||||
|       } | ||||
|     }, | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|     created () { | ||||
|       this.selected.areaId = this.user.info.areaId | ||||
|       this.disabledLevel = this.user.info.areaList.length | ||||
|     }, | ||||
|   created() { | ||||
|     this.selected.areaId = this.user.info.areaId | ||||
|     this.disabledLevel = this.user.info.areaList.length | ||||
|   }, | ||||
|  | ||||
|     methods: { | ||||
|       handleFullscreen() { | ||||
|         this.fullscreen = !this.fullscreen | ||||
|         this.$fullscreen(this.fullscreen) | ||||
|       }, | ||||
|       handleSelectMonitor(monitor) { | ||||
|         let {id} = monitor, | ||||
|             index = this.monitors.findIndex(e => e.id == id) | ||||
|         if (index > -1) { | ||||
|           this.monitors.splice(index, 1) | ||||
|           this.monitors.map((e, i) => { | ||||
|             if (i > index) { | ||||
|               this.showMonitor(e, true) | ||||
|             } | ||||
|           }) | ||||
|         } else if (this.monitors.length >= this.splitScreen && this.splitScreen > 1) { | ||||
|           this.$message.warning("可分屏监控已满,请先取消其他的监控") | ||||
|         } else { | ||||
|           this.showMonitor(monitor) | ||||
|         } | ||||
|       }, | ||||
|       showMonitor(monitor, refresh = false) { | ||||
|         let {id: deviceId} = monitor | ||||
|         deviceId && this.instance.post("/app/appzyvideoequipment/getWebSdkUrl", null, { | ||||
|           params: {deviceId} | ||||
|         }).then(res => { | ||||
|           if (res?.data) { | ||||
|             let data = JSON.parse(res.data) | ||||
|             if (refresh) { | ||||
|               monitor.url = data.url | ||||
|             } else if (this.splitScreen == 1) { | ||||
|               this.monitors = [{...monitor, ...data}] | ||||
|             } else { | ||||
|               this.monitors.push({...monitor, ...data}) | ||||
|             } | ||||
|   methods: { | ||||
|     handleFullscreen() { | ||||
|       this.fullscreen = !this.fullscreen | ||||
|       this.$fullscreen(this.fullscreen) | ||||
|     }, | ||||
|     handleSelectMonitor(monitor) { | ||||
|       let {id} = monitor, | ||||
|           index = this.monitors.findIndex(e => e.id == id) | ||||
|       if (index > -1) { | ||||
|         this.monitors.splice(index, 1) | ||||
|         this.monitors.map((e, i) => { | ||||
|           if (i > index) { | ||||
|             this.showMonitor(e, true) | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       renderTreeItem: function (h, {node, data}) { | ||||
|         let show = data.deviceStatus==1 ? 'show' : '' | ||||
|         if (node.isLeaf) { | ||||
|           return ( | ||||
|               <div class="flexRow"> | ||||
|                 <i class={['iconfont', 'iconshipinjiankong', show]}/> | ||||
|                 <div>{node.label}</div> | ||||
|                 <el-dropdown class="menuBtn" onCommand={e => this.handleSliderOption(e, data)}> | ||||
|                   <i class="iconfont iconMore"/> | ||||
|                   <el-dropdown-menu slot="dropdown"> | ||||
|                     <el-dropdown-item command="edit">修改名称</el-dropdown-item> | ||||
|                     <el-dropdown-item command="area">行政地区</el-dropdown-item> | ||||
|                     <el-dropdown-item command="locate">地图标绘</el-dropdown-item> | ||||
|                   </el-dropdown-menu> | ||||
|                 </el-dropdown> | ||||
|               </div> | ||||
|           ) | ||||
|         } else return ( | ||||
|       } else if (this.monitors.length >= this.splitScreen && this.splitScreen > 1) { | ||||
|         this.$message.warning("可分屏监控已满,请先取消其他的监控") | ||||
|       } else { | ||||
|         this.showMonitor(monitor) | ||||
|       } | ||||
|     }, | ||||
|     showMonitor(monitor, refresh = false) { | ||||
|       let {id: deviceId} = monitor | ||||
|       deviceId && this.instance.post("/app/appzyvideoequipment/getWebSdkUrl", null, { | ||||
|         params: {deviceId} | ||||
|       }).then(res => { | ||||
|         if (res?.data) { | ||||
|           let data = JSON.parse(res.data) | ||||
|           if (refresh) { | ||||
|             monitor.url = data.url | ||||
|           } else if (this.splitScreen == 1) { | ||||
|             this.monitors = [{...monitor, ...data}] | ||||
|           } else { | ||||
|             this.monitors.push({...monitor, ...data}) | ||||
|           } | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     renderTreeItem: function (h, {node, data}) { | ||||
|       let show = data.deviceStatus == 1 ? 'show' : '' | ||||
|       if (node.isLeaf) { | ||||
|         return ( | ||||
|             <div class="flexRow"> | ||||
|               <i class={['iconfont', 'iconshipinjiankong', show]}/> | ||||
|               <div>{node.label}</div> | ||||
|               {data.id != 'no_area' ? <div class="sta"> | ||||
|                     <p>{data.online || 0}</p>/{data.sum || 0} | ||||
|                   </div> | ||||
|                   : <div/>} | ||||
|               <el-dropdown class="menuBtn" onCommand={e => this.handleSliderOption(e, data)}> | ||||
|                 <i class="iconfont iconMore"/> | ||||
|                 <el-dropdown-menu slot="dropdown"> | ||||
|                   <el-dropdown-item command="edit">修改名称</el-dropdown-item> | ||||
|                   <el-dropdown-item command="area">行政地区</el-dropdown-item> | ||||
|                   <el-dropdown-item command="locate">地图标绘</el-dropdown-item> | ||||
|                 </el-dropdown-menu> | ||||
|               </el-dropdown> | ||||
|             </div> | ||||
|         ) | ||||
|       }, | ||||
|       handleSliderOption(command, data) { | ||||
|         this.selected = JSON.parse(JSON.stringify({...data, command})) | ||||
|         if (command == "edit") {//修改名称 | ||||
|           this.dialog = true | ||||
|         } else if (command == "area") {//绑定areaId | ||||
|           this.$refs.BindArea?.chooseArea() | ||||
|         } else if (command == "locate") {//地图标绘 | ||||
|           this.latlng = data.lat && data.lng ? { | ||||
|             lat: data.lat, | ||||
|             lng: data.lng | ||||
|           } : '' | ||||
|           this.locate = true | ||||
|         } | ||||
|       }, | ||||
|       handleSubmit(row) { | ||||
|         delete row.createTime | ||||
|         return this.instance.post("/app/appzyvideoequipment/addOrUpdate", { | ||||
|           ...row | ||||
|         }).then(res => { | ||||
|           if (res?.code == 0) { | ||||
|             this.$message.success("提交成功!") | ||||
|             this.dialog = false | ||||
|             this.$refs.DeviceSlider?.getDevices() | ||||
|           } | ||||
|         }) | ||||
|       }, | ||||
|       handleLocate(row, locate) { | ||||
|         if (locate) { | ||||
|           let {lat, lng} = locate.location | ||||
|           this.handleSubmit({...row, lat, lng}).then(() => { | ||||
|             this.locate = false | ||||
|           }) | ||||
|         } | ||||
|       } else return ( | ||||
|           <div class="flexRow"> | ||||
|             <div>{node.label}</div> | ||||
|             {data.id != 'no_area' ? <div class="sta"> | ||||
|                   <p>{data.online || 0}</p>/{data.sum || 0} | ||||
|                 </div> | ||||
|                 : <div/>} | ||||
|           </div> | ||||
|       ) | ||||
|     }, | ||||
|     handleSliderOption(command, data) { | ||||
|       this.selected = JSON.parse(JSON.stringify({...data, command})) | ||||
|       if (command == "edit") {//修改名称 | ||||
|         this.dialog = true | ||||
|       } else if (command == "area") {//绑定areaId | ||||
|         this.$refs.BindArea?.chooseArea() | ||||
|       } else if (command == "locate") {//地图标绘 | ||||
|         this.latlng = data.lat && data.lng ? { | ||||
|           lat: data.lat, | ||||
|           lng: data.lng | ||||
|         } : '' | ||||
|         this.locate = true | ||||
|       } | ||||
|     }, | ||||
|     beforeDestroy() { | ||||
|       this.monitors = [] | ||||
|     handleSubmit(row) { | ||||
|       delete row.createTime | ||||
|       return this.instance.post("/app/appzyvideoequipment/addOrUpdate", { | ||||
|         ...row | ||||
|       }).then(res => { | ||||
|         if (res?.code == 0) { | ||||
|           this.$message.success("提交成功!") | ||||
|           this.dialog = false | ||||
|           this.$refs.DeviceSlider?.getDevices() | ||||
|         } | ||||
|       }) | ||||
|     }, | ||||
|     handleLocate(row, locate) { | ||||
|       if (locate) { | ||||
|         let {lat, lng} = locate.location | ||||
|         this.handleSubmit({...row, lat, lng}).then(() => { | ||||
|           this.locate = false | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     this.monitors = [] | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   | ||||
| @@ -1,181 +0,0 @@ | ||||
| <template> | ||||
|   <section class="locateDialog"> | ||||
|     <ai-dialog :visible.sync="dialog" title="标绘" @closed="$emit('visible',false),selected={}" | ||||
|                @opened="$nextTick(()=>initMap())" | ||||
|                @onConfirm="handleConfirm"> | ||||
|       <div id="amap" v-if="dialog"/> | ||||
|       <div class="poi"> | ||||
|         <el-input ref="poiInput" v-model="search" size="small" clearable @change="handleSearch" placeholder="请输入地点"/> | ||||
|       </div> | ||||
|       <el-form class="selected" v-if="!!selected.location" id="result" size="mini" label-suffix=":" | ||||
|                label-position="left"> | ||||
|         <div class="header"> | ||||
|           <i class="iconfont iconLocation"/> | ||||
|           <span v-html="[selected.location.lng, selected.location.lat].join(',')"/> | ||||
|         </div> | ||||
|         <el-form-item label="地点">{{ selected.name || "未知地名" }}</el-form-item> | ||||
|         <el-form-item label="类型" v-if="!!selected.type">{{ selected.type }}</el-form-item> | ||||
|         <el-form-item label="地址" v-if="!!selected.address">{{ selected.address }}</el-form-item> | ||||
|       </el-form> | ||||
|     </ai-dialog> | ||||
|   </section> | ||||
| </template> | ||||
|  | ||||
| <script> | ||||
| import AMapLoader from '@amap/amap-jsapi-loader' | ||||
|  | ||||
| export default { | ||||
|   name: "locateDialog", | ||||
|   model: { | ||||
|     prop: "visible", | ||||
|     event: "visible", | ||||
|   }, | ||||
|   props: ['latlng', 'visible'], | ||||
|   data() { | ||||
|     return { | ||||
|       dialog: false, | ||||
|       search: "", | ||||
|       poi: null, | ||||
|       map: null, | ||||
|       AMap: null, | ||||
|       selected: {}, | ||||
|       geo: null | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     visible(v) { | ||||
|       this.dialog = v | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     initMap() { | ||||
|       AMapLoader.load({ | ||||
|         key: "b553334ba34f7ac3cd09df9bc8b539dc", | ||||
|         version: '2.0', | ||||
|         plugins: ['AMap.PlaceSearch', 'AMap.Marker', 'AMap.Geolocation'], | ||||
|       }).then(AMap => { | ||||
|         this.AMap = AMap | ||||
|         this.map = new AMap.Map('amap', { | ||||
|           zoom: 14, | ||||
|           center: this.latlng ? [this.latlng.lng, this.latlng.lat] : '' | ||||
|         }).on('click', res => { | ||||
|           this.map.clearMap() | ||||
|           this.selected = {location: res.lnglat} | ||||
|           this.poi?.searchNearBy('', res.lnglat, 100) | ||||
|         }); | ||||
|         if (this.latlng) { | ||||
|           let marker = new AMap.Marker({ | ||||
|             position: [this.latlng.lng, this.latlng.lat] | ||||
|           }) | ||||
|           this.map.add(marker) | ||||
|         } | ||||
|         this.poi = new AMap.PlaceSearch().on('complete', ({poiList}) => { | ||||
|           this.map.clearMap() | ||||
|           if (poiList?.length > 0) { | ||||
|             poiList?.pois?.map(e => { | ||||
|               let marker = new AMap.Marker({ | ||||
|                 position: e.location, | ||||
|               }).on('click', () => this.selected = e) | ||||
|               this.map.add(marker) | ||||
|             }) | ||||
|           } else { | ||||
|             let marker = new AMap.Marker({ | ||||
|               position: this.selected.location, | ||||
|             }) | ||||
|             this.map.add(marker) | ||||
|           } | ||||
|         }) | ||||
|         this.geo = new AMap.Geolocation({ | ||||
|           enableHighAccuracy: true,//是否使用高精度定位 | ||||
|           zoomToAccuracy: true//定位成功后是否自动调整地图视野到定位点 | ||||
|         }) | ||||
|         this.map.addControl(this.geo) | ||||
|       }) | ||||
|     }, | ||||
|     handleSearch(v) { | ||||
|       if (v) { | ||||
|         this.poi.searchNearBy(v, this.map.getCenter(), 50000) | ||||
|       } | ||||
|     }, | ||||
|     handleConfirm() { | ||||
|       if (this.selected?.location) { | ||||
|         this.$emit('confirm', this.selected) | ||||
|       } else { | ||||
|         this.$message.error('请先选择坐标位置') | ||||
|       } | ||||
|  | ||||
|     } | ||||
|   }, | ||||
|   created() { | ||||
|     this.dialog = this.visible | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .locateDialog { | ||||
|   ::v-deep .el-dialog__body { | ||||
|     padding: 0; | ||||
|     height: 480px; | ||||
|     position: relative; | ||||
|  | ||||
|     .ai-dialog__content--wrapper { | ||||
|       padding: 0 !important; | ||||
|     } | ||||
|  | ||||
|     #amap { | ||||
|       width: 100%; | ||||
|       height: 480px; | ||||
|  | ||||
|       .amap-logo, .amap-copyright { | ||||
|         display: none !important; | ||||
|       } | ||||
|  | ||||
|       .amap-marker-label { | ||||
|         border-color: transparent; | ||||
|         box-shadow: 1px 1px 0 0 rgba(#999, .2); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .poi { | ||||
|       position: absolute; | ||||
|       left: 10px; | ||||
|       top: 10px; | ||||
|       display: flex; | ||||
|       height: 32px; | ||||
|       flex-direction: column; | ||||
|  | ||||
|       div { | ||||
|         flex-shrink: 0; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     .selected { | ||||
|       position: absolute; | ||||
|       right: 16px; | ||||
|       top: 16px; | ||||
|       background: #fff; | ||||
|       min-width: 200px; | ||||
|       box-sizing: border-box; | ||||
|       box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | ||||
|  | ||||
|       .header { | ||||
|         color: #fff; | ||||
|         background: #26f; | ||||
|         text-align: center; | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         height: 32px; | ||||
|         font-size: 14px; | ||||
|         gap: 4px; | ||||
|         padding: 0 8px; | ||||
|       } | ||||
|  | ||||
|       .el-form-item { | ||||
|         padding: 0 8px; | ||||
|         margin: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
		Reference in New Issue
	
	Block a user