| | |
| | | <!-- 实时监测 --> |
| | | |
| | | <script> |
| | | import axiosInstance from '../utils/request.js'; |
| | | import axiosInstanceInstance from '../utils/request.js'; |
| | | // 异步组件 |
| | | const DashBoard = defineAsyncComponent(() => |
| | | import('../sfc/DashBoardTest.vue') |
| | | import('../sfc/DashboardChart.vue') |
| | | ) |
| | | export default { |
| | | components:{ |
| | |
| | | }, |
| | | data() { |
| | | return { |
| | | // 卡片大小 |
| | | cardSize: 'medium', |
| | | // 默认打开的折叠面板 |
| | | activeNames:'1', |
| | | // isShow:false, |
| | | // 要展示的仪表盘数量 |
| | | // totalCharts: 0, |
| | | // 实时更新间隔 3秒 |
| | | // 实时更新间隔 60秒 |
| | | timeInterval:60000, |
| | | // 外部设备 |
| | | outside: { |
| | | // 搜索 |
| | | searchText:'', |
| | | isall:false, |
| | | isLoading:false, |
| | | // 设备信息表的数据 |
| | | shopnames: [], |
| | | // 当前展示的多选框组值 |
| | | displayedShopnames:[], |
| | | // 当前页 |
| | | currentPage:1, |
| | | // 每页显示的数量 |
| | | pageSize:5, |
| | | // 是否已加载完所有数据 |
| | | allDataLoaded:false, |
| | | // 是否全选 |
| | | checkAll: false, |
| | | isIndeterminate: false, |
| | | // 已选择店铺 |
| | | checkedShops: [], |
| | | |
| | | //返回选择的所有店铺的数据 |
| | | realTimeData: [] |
| | | }, |
| | | |
| | | // 内部设备 |
| | | inner: { |
| | | searchText:'', |
| | | isall:false, |
| | | isLoading:false, |
| | | // 内部接口返回的所有数据 |
| | | getData:[], |
| | | // 选中的店铺对应全部字段信息 |
| | | inFumeValue:[], |
| | | // 店铺名字 |
| | | // 所有店铺名字 |
| | | shopnames: [], |
| | | // 当前展示的多选框组值 |
| | | displayedShopnames:[], |
| | | // 当前页 |
| | | currentPage:1, |
| | | // 每页显示的数量 |
| | | pageSize:2, |
| | | // 是否已加载完所有数据 |
| | | allDataLoaded:false, |
| | | // 是否全选 |
| | | checkAll: false, |
| | | isIndeterminate: false, |
| | | // 已选择店铺 |
| | |
| | | // devices: [] |
| | | }; |
| | | }, |
| | | computed: { |
| | | cardStyle() { |
| | | let width = '400px'; |
| | | let height = '500px'; |
| | | if (this.cardSize === 'small') { |
| | | width = '200px'; |
| | | height = '200px'; |
| | | } else if (this.cardSize === 'large') { |
| | | width = '600px'; |
| | | height = '600px'; |
| | | } |
| | | return { |
| | | width, |
| | | height |
| | | }; |
| | | }, |
| | | |
| | | watch:{ |
| | | // 'outside.checkedShops'(){ |
| | | // this.saveOutsideData() |
| | | // console.log('111'); |
| | | // } |
| | | }, |
| | | methods: { |
| | | // 同步改变仪表盘大小 |
| | | getDashBoardStyle() { |
| | | if (this.cardSize === 'small') { |
| | | return { |
| | | width: '180px', |
| | | height: '120px', |
| | | margin: '10px' |
| | | }; |
| | | } else if (this.cardSize === 'large') { |
| | | return { |
| | | width: '380px', |
| | | height: '220px', |
| | | margin: '10px' |
| | | }; |
| | | } else { |
| | | return { |
| | | width: '280px', |
| | | height: '170px', |
| | | margin: '10px' |
| | | }; |
| | | } |
| | | }, |
| | | // 改变布局大小 从而实现每行放置仪表盘数量增多 |
| | | getColSpan(){ |
| | | if (this.cardSize === 'small') { |
| | | return 3 |
| | | } else if (this.cardSize === 'medium') { |
| | | return 4 |
| | | } |
| | | else if (this.cardSize === 'large'){ |
| | | return 8 |
| | | } |
| | | return 6 |
| | | }, |
| | | |
| | | // 改变卡片大小 |
| | | changeCardSize(size) { |
| | | this.cardSize = size; |
| | | }, |
| | | //获取所有店铺名字 |
| | | getDeviceInfo() { |
| | | // 获取外部设备的店铺名称 |
| | | axiosInstance.get('/fume/device').then((result) => { |
| | | // 获取所有外部设备的店铺名称 |
| | | axiosInstanceInstance.get('/fume/device').then((result) => { |
| | | result.data.data.forEach((item) => { |
| | | this.outside.shopnames.push(item.diName); |
| | | }); |
| | | this.outside.displayedShopnames = this.outside.shopnames.slice(0, this.outside.pageSize); |
| | | if (this.outside.shopnames.length <= this.outside.pageSize) { |
| | | this.outside.allDataLoaded = true; |
| | | } |
| | | }); |
| | | |
| | | //从内部接口获取实时数据的所有店铺名称 |
| | | axiosInstance |
| | | axiosInstanceInstance |
| | | .get('https://fyami.com.cn/device/min/value/real_time', { |
| | | params: { page: 1, per_page: 20 } |
| | | }) |
| | |
| | | // 保存内部接口获取的所有信息 |
| | | this.getData = result.data.data |
| | | result.data.data.forEach((item) => { |
| | | |
| | | this.inner.shopnames.push(item.siteName); |
| | | }); |
| | | this.inner.displayedShopnames = this.inner.shopnames.slice(0, this.inner.pageSize); |
| | | if (this.inner.shopnames.length <= this.inner.pageSize) { |
| | | this.inner.allDataLoaded = true; |
| | | } |
| | | |
| | | }); |
| | | }, |
| | | loadMore() { |
| | | this.outside.isLoading = true |
| | | setTimeout(() => { |
| | | const startIndex = this.outside.currentPage * this.outside.pageSize; |
| | | const endIndex = startIndex + this.outside.pageSize; |
| | | this.outside.displayedShopnames = this.outside.displayedShopnames.concat(this.outside.shopnames.slice(startIndex, endIndex)); |
| | | this.outside.currentPage++; |
| | | if (this.outside.displayedShopnames.length === this.outside.shopnames.length) { |
| | | this.outside.allDataLoaded = true; |
| | | this.outside.isall = true |
| | | } |
| | | this.outside.isLoading = false |
| | | }, 100); |
| | | }, |
| | | loadMoreInner() { |
| | | this.inner.isLoading = true |
| | | setTimeout(() => { |
| | | const startIndex = this.inner.currentPage * this.inner.pageSize; |
| | | const endIndex = startIndex + this.inner.pageSize; |
| | | this.inner.displayedShopnames = this.inner.displayedShopnames.concat(this.inner.shopnames.slice(startIndex, endIndex)); |
| | | this.inner.currentPage++; |
| | | if (this.inner.displayedShopnames.length === this.inner.shopnames.length) { |
| | | this.inner.allDataLoaded = true; |
| | | this.inner.isall = true |
| | | } |
| | | this.inner.isLoading = false |
| | | }, 100); |
| | | }, |
| | | // 过滤数据 |
| | | filterData (keyword) { |
| | | return this.outside.shopnames.filter((item) => item.includes(keyword)); |
| | | }, |
| | | |
| | | // 处理搜索 |
| | | handleSearch (){ |
| | | if(this.outside.searchText != ''){ |
| | | this.outside.displayedShopnames = this.filterData(this.outside.searchText); |
| | | this.outside.currentPage = 1; // 重置页码 |
| | | this.outside.allDataLoaded = this.outside.displayedShopnames === this.outside.shopnames.length; |
| | | } |
| | | else |
| | | { |
| | | // 加载默认数量的 |
| | | this.outside.displayedShopnames = this.outside.shopnames.slice(0, this.outside.pageSize); |
| | | if(this.outside.shopnames.length <= this.outside.pageSize){ |
| | | this.outside.allDataLoaded.value = true; |
| | | } |
| | | this.outside.checkedShops = [] |
| | | } |
| | | }, |
| | | |
| | | // 处理搜索 |
| | | handleSearchInner(){ |
| | | if(this.inner.searchText != ''){ |
| | | this.inner.displayedShopnames = this.filterData(this.inner.searchText); |
| | | this.inner.currentPage = 1; // 重置页码 |
| | | this.inner.allDataLoaded = this.inner.displayedShopnames === this.inner.shopnames.length; |
| | | } |
| | | else |
| | | { |
| | | // 加载默认数量的 |
| | | this.inner.displayedShopnames = this.inner.shopnames.slice(0, this.inner.pageSize); |
| | | if(this.inner.shopnames.length <= this.inner.pageSize){ |
| | | this.inner.allDataLoaded.value = true; |
| | | } |
| | | this.inner.checkedShops = [] |
| | | } |
| | | }, |
| | | // 外部设备全选 |
| | | handleCheckAllChangeOutside(val) { |
| | | this.outside.checkedShops = val ? this.outside.shopnames : []; |
| | | this.outside.checkedShops = val ? this.outside.displayedShopnames : []; |
| | | this.outside.isIndeterminate = false; |
| | | }, |
| | | handleCheckedCitiesChangOutside(value) { |
| | | const checkedCount = value.length; |
| | | this.outside.checkAll = checkedCount === this.outside.shopnames.length; |
| | | this.outside.checkAll = checkedCount === this.outside.displayedShopnames.length; |
| | | this.outside.isIndeterminate = |
| | | checkedCount > 0 && checkedCount < this.outside.shopnames.length; |
| | | checkedCount > 0 && checkedCount < this.outside.displayedShopnames.length; |
| | | }, |
| | | |
| | | // 内部设备全选 |
| | |
| | | if (this.outside.checkedShops.length != 0) { |
| | | params['shops'] = temp; |
| | | } |
| | | axiosInstance.get('/fume/lastest', { params: params }).then((result) => { |
| | | axiosInstanceInstance.get('/fume/lastest', { params: params }).then((result) => { |
| | | this.outside.realTimeData = result.data.data; |
| | | console.log('66', this.outside.realTimeData); |
| | | // console.log('长度为:',this.outside.realTimeData.length); |
| | |
| | | // this.updateCharts(); |
| | | }); |
| | | } |
| | | |
| | | |
| | | // 选择了内部设备 |
| | | if(this.inner.checkedShops.length!=0){ |
| | | // 清空数据 |
| | |
| | | setInterval(() => { |
| | | this.request(); |
| | | }, this.timeInterval); |
| | | |
| | | // 得到要展示的仪表盘数量 |
| | | // this.totalCharts = |
| | | // this.outside.checkedShops.length + this.inner.checkedShops.length; |
| | | } |
| | | }, |
| | | // saveOutsideData(){ |
| | | // let temp = JSON.parse(localStorage.getItem('outsideData')); |
| | | // if(temp!=null && temp.length!=0){ |
| | | // temp.concat(this.outside.checkedShops) |
| | | // localStorage.setItem('outsideData', JSON.stringify(temp)); |
| | | // }else{ |
| | | // localStorage.setItem('outsideData', JSON.stringify(this.outside.checkedShops)); |
| | | // } |
| | | // }, |
| | | // getOutsideData () { |
| | | // const data = localStorage.getItem('outsideData'); |
| | | // this.outside.displayedShopnames = JSON.parse(data); |
| | | |
| | | // } |
| | | }, |
| | | mounted() { |
| | | // 获取所有店铺名字 |
| | | this.getDeviceInfo(); |
| | | // 优先展示浏览器缓存中的 |
| | | // this.getOutsideData() |
| | | } |
| | | }; |
| | | |
| | | |
| | | |
| | | } |
| | | </script> |
| | | |
| | | |
| | | <template> |
| | | |
| | | <div> |
| | | |
| | | <el-collapse v-model="activeNames" > |
| | | <el-collapse-item name="1"> |
| | | <template #title> |
| | |
| | | content="点击可折叠" |
| | | placement="right-start" |
| | | > |
| | | <h2>选择某个设备的实时数据:</h2> |
| | | <h2 style="margin-left: 10px;">监测站点选择</h2> |
| | | </el-tooltip> |
| | | </template> |
| | | <el-card shadow="always" class="form-card"> |
| | | <el-form label-width="120px"> |
| | | <el-form-item label="外部设备"> |
| | | <el-form-item label="其他设备"> |
| | | <el-checkbox |
| | | v-model="outside.checkAll" |
| | | :indeterminate="outside.isIndeterminate" |
| | | @change="handleCheckAllChangeOutside" |
| | | >全选</el-checkbox |
| | | > |
| | | |
| | | <el-checkbox-group |
| | | v-model="outside.checkedShops" |
| | | @change="handleCheckedCitiesChangOutside" |
| | | > |
| | | |
| | | <el-checkbox |
| | | v-for="shop in outside.shopnames" |
| | | v-for="shop in outside.displayedShopnames" |
| | | :key="shop" |
| | | :label="shop" |
| | | >{{ shop }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <div>已选择外部设备数量为:{{outside.checkedShops.length}}</div> |
| | | </el-form-item> |
| | | <!-- ------------------------------- --> |
| | | |
| | | <el-form-item label="内部设备"> |
| | | <div class="input-search"> |
| | | <el-input type="text" v-model="outside.searchText" placeholder="搜索店铺名称" @input="handleSearch" /> |
| | | </div> |
| | | |
| | | |
| | | <div> |
| | | <el-button type="primary" v-if="!outside.allDataLoaded && !outside.isLoading && !outside.isall" @click="loadMore">加载更多</el-button> |
| | | <el-button type="primary" loading v-if="!outside.allDataLoaded && outside.isLoading " @click="loadMore">加载更多</el-button> |
| | | <div>已选择其他设备数量为:{{outside.checkedShops.length}}</div> |
| | | </div> |
| | | <br/> |
| | | <hr/> |
| | | <br/> |
| | | |
| | | <el-form-item label="试点设备"> |
| | | <el-checkbox |
| | | v-model="inner.checkAll" |
| | | :indeterminate="inner.isIndeterminate" |
| | |
| | | class="inner-checkbox-group" |
| | | > |
| | | |
| | | <el-checkbox v-for="shop in inner.shopnames" :key="shop" :label="shop" |
| | | <el-checkbox v-for="shop in inner.displayedShopnames" :key="shop" :label="shop" |
| | | >{{ shop }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <div>已选择内部设备数量为:{{inner.checkedShops.length}}</div> |
| | | </el-form-item> |
| | | <el-form-item > |
| | | <!-- <div class="right-form"> --> |
| | | <div class="input-search"> |
| | | <el-input type="text" v-model="inner.searchText" placeholder="搜索店铺名称" @input="handleSearchInner" /> |
| | | |
| | | </div> |
| | | |
| | | <div> |
| | | <el-button type="primary" v-if="!inner.allDataLoaded && !inner.isLoading && !inner.isall" @click="loadMoreInner">加载更多</el-button> |
| | | <el-button type="primary" loading v-if="!inner.allDataLoaded && inner.isLoading " @click="loadMoreInner">加载更多</el-button> |
| | | <div>已选择试点设备数量为:{{inner.checkedShops.length}}</div> |
| | | </div> |
| | | <!-- <el-form-item > --> |
| | | |
| | | <div class="time-interval"> |
| | | 实时更新间隔为:{{timeInterval/1000}}秒 |
| | | </div> |
| | | <!-- </div> --> |
| | | </el-form-item> |
| | | |
| | | <!-- </el-form-item> --> |
| | | </el-form> |
| | | </el-card> |
| | | </el-collapse-item> |
| | | </el-collapse> |
| | | </div> |
| | | |
| | | |
| | | <div> |
| | | <div> |
| | | <el-tooltip |
| | | class="box-item" |
| | | effect="dark" |
| | | content="点击展示实时数据" |
| | | placement="top-start" |
| | | > |
| | | <el-button type="success" @click="show"> 展示 </el-button> |
| | | <el-button type="success" @click="show" style="margin-left: 10px;"> 展示 </el-button> |
| | | </el-tooltip> |
| | | </div> |
| | | <!-- |
| | | {{ outside.checkedShops }} |
| | | <br /> |
| | | {{ inner.checkedShops }} --> |
| | | |
| | | <!-- 仪表盘 --> |
| | | |
| | | |
| | | <!-- 仪表盘 --> |
| | | <!-- <div class="charts-container" v-for="(device,index) in outside.realTimeData" :key="device.mvStatCode"> |
| | | <div ref="chartsOutside" class="echarts" :id="`chartAP-${index}`"></div> |
| | | </div> --> |
| | | <el-button-group> |
| | | <el-button @click="changeCardSize('small')">缩小</el-button> |
| | | <el-button @click="changeCardSize('medium')">中等</el-button> |
| | | <el-button @click="changeCardSize('large')">放大</el-button> |
| | | </el-button-group> |
| | | |
| | | <div class="dashBorder-area"> |
| | | <h3 v-show="outside.realTimeData.length" class="outside-leble">外部设备:</h3> |
| | | <div v-if="outside.realTimeData"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="getColSpan" v-for="device in outside.realTimeData" :key="device.mvStatCode"> |
| | | <el-card :style="cardStyle"> |
| | | <el-col :span="6" v-for="device in outside.realTimeData" :key="device.mvStatCode"> |
| | | <el-card> |
| | | <template #header> |
| | | <div class="card-header">{{ device.diName }}</div> |
| | | </template> |
| | | <DashBoard :styleDashB="cardSize" :data="device.mvFumeConcentration2"></DashBoard> |
| | | <DashBoard :data="device.mvFumeConcentration2"></DashBoard> |
| | | <div>设备编号:{{ device.mvStatCode }}</div> |
| | | <hr class="divider-margin"/> |
| | | <divr class="data">风机电流(A):{{ device.mvFanElectricity}} </divr> |
| | | <hr class="divider-margin"> |
| | | <div class="data">净化器电流(A):{{ device.mvPurifierElectricity}}</div> |
| | | <hr class="divider-margin"/> |
| | | <div>产生时间:{{ device.mvDataTime }}</div> |
| | | <div>数据发布时间:{{ device.mvDataTime }}</div> |
| | | <div class="status" :class="{'exceed': device.mvFumeConcentration2 >= 1}"> {{ device.mvFumeConcentration2 >= 1 ? '超标' : '' }}</div> |
| | | <!-- <div class="status1" :class="{'exceed1': device.mvFumeConcentration2 < 1}"> {{ device.mvFumeConcentration2 < 1 ? '未超标' : '' }}</div> --> |
| | | </el-card> |
| | |
| | | </el-row> |
| | | </div> |
| | | |
| | | |
| | | <hr v-show="outside.realTimeData.length && inner.inFumeValue.length" class="line-marign"/> |
| | | <h3 v-show="inner.inFumeValue.length">内部设备:</h3> |
| | | <h3 v-show="inner.inFumeValue.length" class="inner-leble">内部设备:</h3> |
| | | <div v-if="inner.inFumeValue"> |
| | | <el-row :gutter="20"> |
| | | <el-col :span="6" v-for="device in inner.inFumeValue" :key="device.mnCode"> |
| | |
| | | <DashBoard :data="device.value"></DashBoard> |
| | | <div>设备编号:{{ device.mnCode }}</div> |
| | | <hr class="divider-margin"/> |
| | | <div>产生时间:{{ device.time }}</div> |
| | | <div>数据发布时间:{{ device.time }}</div> |
| | | <div class="status" :class="{'exceed': device.value > 1}"> {{ device.value >= 1 ? '超标' : '' }}</div> |
| | | <!-- <div class="status1" :class="{'exceed1': device.value < 1}"> {{ device.value < 1 ? '未超标' : '' }}</div> --> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | |
| | | </div> |
| | | </template> |
| | | |
| | | <style lang="scss" scoped> |
| | | // 更新时间 |
| | | .time-interval { |
| | | display: flex; |
| | | justify-content: right; |
| | | font-size: 16px; |
| | | } |
| | | .form-card { |
| | | margin: 20px 10px; |
| | | // width: 96%; |
| | |
| | | .outside-leble { |
| | | margin-top: 10px; |
| | | } |
| | | .inner-leble { |
| | | margin-top: 10px; |
| | | } |
| | | // 分割线 |
| | | .line-marign { |
| | | margin: 20px 0; |
| | | } |
| | | .el-dialog { |
| | | width: 700px; |
| | | } |
| | | .dashBorder-area { |
| | | margin-left: 10px; |
| | | } |
| | | .dashboard { |
| | | margin-bottom: 20px; |
| | |
| | | .divider-margin { |
| | | margin: 3px 0px ; |
| | | } |
| | | .el-input { |
| | | width: calc(100% / 6); |
| | | // margin-left: 70px; |
| | | |
| | | } |
| | | // .input-search { |
| | | // display: flex; |
| | | // justify-content: left; |
| | | // } |
| | | </style> |