由于不同监测点有不同的传感器,每个传感器的监测数据、监测曲线及分析曲线都不尽相同,因此,需要动态加载不同传感器对应的数据展示组件
没有选择任何传感器时:
选择地表位移传感器时:
选择裂缝传感器时:
选择土壤含水率传感器时:
-
具体代码如下:
- monitorData.vue
<template> <el-container> <el-aside width="400px" style="height: 100vh; padding: 10px;"> <el-tree :data="treeData" :props="defaultProps" :default-expand-all="true" :highlight-current="true" :expand-on-click-node="false" @node-click="handleNodeClick" ></el-tree> </el-aside> <el-main> <el-tabs type="border-card" style="padding: 10px;"> <el-tab-pane> <span slot="label" ><i class="el-icon-s-grid"></i> 监测数据</span > <!-- 使用动态组件并传入属性sensorCode --> <component :is="dynamicComponentConfig.dataComponent" :sensorCode="selectedSensorCode" /> </el-tab-pane> <el-tab-pane> <span slot="label" ><i class="el-icon-s-data"></i> 监测曲线</span > <!-- 使用动态组件并传入属性sensorCode --> <component :is="dynamicComponentConfig.chartComponent" :sensorCode="selectedSensorCode" /> </el-tab-pane> <el-tab-pane> <span slot="label" ><i class="el-icon-s-operation"></i> 曲线分析</span > <!-- 使用动态组件并传入属性sensorCode --> <component :is="dynamicComponentConfig.analysisComponent" :sensorCode="selectedSensorCode" /> </el-tab-pane> </el-tabs> </el-main> </el-container> </template> <script> // 引用异步组件方法 import { defineAsyncComponent } from 'vue' import { find } from '@/api/dz/monitorPointInfo' import { getSensorInfosByMonitorPoint } from '@/api/dz/sensorInfo' let monitorPointCode = '' export default { mounted() { // 获取url传递来的参数 monitorPointCode = this.$route.query.monitorPointCode // 获取传感器类型数组 this.deviceTypeCodes = this.dict.device_type_codes // 获取监测点信息 find(monitorPointCode).then((res) => { this.treeData.push({ label: res.monitorPointName + ' [' + monitorPointCode + ']', children: [], }) }) // 获取监测点包含的传感器 getSensorInfosByMonitorPoint(monitorPointCode).then((res) => { res.forEach((item) => { this.treeData[0].children.push({ label: this.getDeviceTypeCodeName( item.deviceTypeCode ) + ' [' + item.id + ']', }) }) }) }, // 数据字典 dicts: ['device_type_codes'], data() { return { treeData: [], defaultProps: { children: 'children', label: 'label', }, // 传感器类型数组 deviceTypeCodes: [], // 动态组件配置 dynamicComponentConfig: { typeName: '', dataComponent: defineAsyncComponent(() => import('./default/tpDefaultData.vue') ), chartComponent: defineAsyncComponent(() => import('./default/tpDefaultData.vue') ), analysisComponent: defineAsyncComponent(() => import('./default/tpDefaultData.vue') ), }, // 选择的传感器编码 selectedSensorCode: '', } }, methods: { handleNodeClick(node) { if (!node.children) { let pos = node.label.indexOf(' [') let typeName = node.label.substring(0, pos) this.selectedSensorCode = node.label.substring( pos + 2, node.label.length - 1 ) // 依据不同的传感器类型,动态加载不同的每套数据显示组件 if (typeName === '雨量') { // 动态加载组件 this.dynamicComponentConfig = { typeName: typeName, // 数据 dataComponent: defineAsyncComponent(() => import('./yl/tpYLData.vue') ), // 图表 chartComponent: defineAsyncComponent(() => import('./yl/tpYLChart.vue') ), // 分析 analysisComponent: defineAsyncComponent(() => import('./yl/tpYLAnalysis.vue') ), } } else if (typeName === '地表位移') { // 动态加载组件 this.dynamicComponentConfig = { typeName: typeName, // 数据 dataComponent: defineAsyncComponent(() => import('./gnss/tpGNSSData.vue') ), // 图表 chartComponent: defineAsyncComponent(() => import('./gnss/tpGNSSChart.vue') ), // 分析 analysisComponent: defineAsyncComponent(() => import('./gnss/tpGNSSAnalysis.vue') ), } } else if (typeName === '土壤含水率') { // 动态加载组件 this.dynamicComponentConfig = { typeName: typeName, // 数据 dataComponent: defineAsyncComponent(() => import('./trhsl/tpTRHSLData.vue') ), // 图表 chartComponent: defineAsyncComponent(() => import('./trhsl/tpTRHSLChart.vue') ), // 分析 analysisComponent: defineAsyncComponent(() => import('./trhsl/tpTRHSLAnalysis.vue') ), } } else if (typeName === '裂缝') { // 动态加载组件 this.dynamicComponentConfig = { typeName: typeName, // 数据 dataComponent: defineAsyncComponent(() => import('./lfwy/tpLFWYData.vue') ), // 图表 chartComponent: defineAsyncComponent(() => import('./lfwy/tpLFWYChart.vue') ), // 分析 analysisComponent: defineAsyncComponent(() => import('./lfwy/tpLFWYAnalysis.vue') ), } } else { this.dynamicComponentConfig = { typeName: '', dataComponent: defineAsyncComponent(() => import('./default/tpDefaultData.vue') ), chartComponent: defineAsyncComponent(() => import('./default/tpDefaultData.vue') ), analysisComponent: defineAsyncComponent(() => import('./default/tpDefaultData.vue') ), } } } }, // 监测类型转换 getDeviceTypeCodeName(deviceTypeCode) { // 这里不能使用this.dict.device_type_codes,否则返回undefined,估计是异步导致 for (let i = 0; i < this.deviceTypeCodes.length; i++) { if (this.deviceTypeCodes[i].value == deviceTypeCode) { return this.deviceTypeCodes[i].label } } }, }, } </script>
- data/default/tpDefaultData.vue
<template> <div class="app-container"> <!-- 查询 --> <div class="head-container"> <el-select v-model="query.type" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in types" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" format="yyyy-MM-dd HH:mm:ss" @change="toQuery" > </el-date-picker> <span> <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery" >搜索</el-button > <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()" >重置</el-button > </span> </div> <!-- 监测数据 --> <div>未知类型的传感器监测数据...</div> </div> </template> <script> // 导入混入对象 import { timeUtils } from '../timeUtils.js' export default { // 使用混入对象 mixins: [timeUtils], props: { sensorCode: { type: String, required: true, }, }, mounted() { this.toQuery() }, data() { return { types: [ { key: 0, value: '天' }, { key: 1, value: '周' }, { key: 2, value: '月' }, { key: 3, value: '小时' }, { key: 4, value: '实时' }, ], query: { sensorCode: '', type: 0, timeRange: [ // 调用混入方法 getlastMonth this.getlastMonth(), new Date(), ], page: 1, size: 10, }, page: { size: 10, total: 0, page: 0, data: [], }, } }, methods: { toQuery() { this.query.sensorCode = this.sensorCode this.refreshData() }, resetQuery() { this.query.type = 0 this.query.timeRange = [this.getlastMonth(), new Date()] this.query.page = 1 this.query.size = 10 this.refreshData() }, sizeChangeHandler(e) { this.page.size = e this.page.page = 0 this.refreshData() }, pageChangeHandler(e) { this.page.page = e this.refreshData() }, refreshData() {}, }, } </script>
- data/default/tpDefaultChart.vue
<template> <div class="app-container"> <!-- 查询 --> <div class="head-container"> <el-select v-model="query.type" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in types" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" format="yyyy-MM-dd HH:mm:ss" @change="toQuery" > </el-date-picker> <span> <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery" >搜索</el-button > <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()" >重置</el-button > </span> </div> <!-- 数据图表 --> <div>未知类型的传感器数据图表...</div> </div> </template> <script> // 导入混入对象 import { timeUtils } from '../timeUtils.js' export default { // 使用混入对象 mixins: [timeUtils], props: { sensorCode: { type: String, required: true, }, }, mounted() { this.toQuery() }, data() { return { types: [ { key: 0, value: '天' }, { key: 1, value: '周' }, { key: 2, value: '月' }, { key: 3, value: '小时' }, { key: 4, value: '实时' }, ], query: { sensorCode: '', type: 0, timeRange: [ // 调用混入方法 getlastMonth this.getlastMonth(), new Date(), ], }, data: [], chart: null, } }, methods: { toQuery() { this.query.sensorCode = this.sensorCode this.refreshData() }, resetQuery() { this.query.type = 0 this.query.timeRange = [this.getlastMonth(), new Date()] this.refreshData() }, refreshData() {}, }, } </script>
- data/gnss/tpGNSSData.vue
<template> <div class="app-container"> <!-- 查询 --> <div class="head-container"> <el-select v-model="query.category" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in categories" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-select v-model="query.type" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in types" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" format="yyyy-MM-dd HH:mm:ss" @change="toQuery" > </el-date-picker> <span> <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery" >搜索</el-button > <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()" >重置</el-button > </span> </div> <!-- 监测数据 --> <el-table ref="table" :stripe="true" :data="page.data" style="width: 100%;" > <el-table-column type="index" label="序号" width="50px" fixed /> <el-table-column prop="sensorCode" label="传感器编号" /> <el-table-column prop="monitorTime" label="时间" /> <el-table-column prop="gpsTotalX" label="X方向位移" /> <el-table-column prop="gpsTotalY" label="Y方向位移" /> <el-table-column prop="gpsTotalZ" label="Z方向位移" /> </el-table> <el-pagination :page-size.sync="page.size" :total="page.total" :current-page.sync="page.page" style="margin-top: 8px;" layout="total, prev, pager, next, sizes" @size-change="sizeChangeHandler" @current-change="pageChangeHandler" > </el-pagination> </div> </template> <script> import { statisticsPaging } from '@/api/dz/gnss' // 导入混入对象 import { timeUtils } from '../timeUtils.js' export default { // 使用混入对象 mixins: [timeUtils], props: { sensorCode: { type: String, required: true, }, }, mounted() { this.toQuery() }, data() { return { categories: [ { key: 0, value: '累计位移' }, { key: 1, value: '变化速率' }, ], types: [ { key: 0, value: '天' }, { key: 1, value: '周' }, { key: 2, value: '月' }, { key: 3, value: '小时' }, { key: 4, value: '实时' }, ], query: { sensorCode: '', category: 0, type: 0, timeRange: [ // 调用混入方法 getlastMonth this.getlastMonth(), new Date(), ], page: 1, size: 10, }, page: { size: 10, total: 0, page: 0, data: [], }, } }, methods: { toQuery() { this.query.sensorCode = this.sensorCode this.refreshData() }, resetQuery() { this.query.type = 0 this.query.category = 0 this.query.timeRange = [this.getlastMonth(), new Date()] this.query.page = 1 this.query.size = 10 this.refreshData() }, sizeChangeHandler(e) { this.page.size = e this.page.page = 0 this.refreshData() }, pageChangeHandler(e) { this.page.page = e this.refreshData() }, refreshData() { this.query.page = this.page.page - 1 this.query.size = this.page.size statisticsPaging(this.query).then((res) => { this.page.data = res.content this.page.total = res.totalElements }) }, }, } </script>
- data/gnss/tpGNSSChart.vue
<template> <div class="app-container"> <!-- 查询 --> <div class="head-container"> <el-select v-model="query.category" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in categories" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-select v-model="query.type" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in types" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" format="yyyy-MM-dd HH:mm:ss" @change="toQuery" > </el-date-picker> <span> <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery" >搜索</el-button > <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()" >重置</el-button > </span> </div> <!-- 数据图表 --> <div id="chart" style="width: 1200px; height: 800px; border: 1px solid #888;" ></div> </div> </template> <script> // 引入echart组件 import echarts from 'echarts' // require('echarts/theme/macarons') import { statisticsAll } from '@/api/dz/gnss' // 导入混入对象 import { timeUtils } from '../timeUtils.js' export default { // 使用混入对象 mixins: [timeUtils], props: { sensorCode: { type: String, required: true, }, }, mounted() { this.toQuery() }, data() { return { categories: [ { key: 0, value: '累计位移' }, { key: 1, value: '变化速率' }, ], types: [ { key: 0, value: '天' }, { key: 1, value: '周' }, { key: 2, value: '月' }, { key: 3, value: '小时' }, { key: 4, value: '实时' }, ], query: { sensorCode: '', category: 0, type: 0, timeRange: [ // 调用混入方法 getlastMonth this.getlastMonth(), new Date(), ], }, data: [], chart: null, } }, methods: { toQuery() { this.query.sensorCode = this.sensorCode this.refreshData() }, resetQuery() { this.query.type = 0 this.query.category = 0 this.query.timeRange = [this.getlastMonth(), new Date()] this.refreshData() }, refreshData() { statisticsAll(this.query).then((res) => { this.data = res this.initChart() }) }, initChart() { this.chart = echarts.init(document.getElementById('chart')) this.setOptions() }, setOptions() { this.chart.setOption({ title: { text: this.sensorCode + ' (地表位移)', left: 'center', }, tooltip: { trigger: 'axis', }, legend: { data: ['X方向位移', 'Y方向位移', 'Z方向位移'], left: 'left', }, toolbox: { // 显示工具箱 show: true, feature: { // 数据缩放 dataZoom: { yAxisIndex: 'none', }, // 数据视图只读 dataView: { readOnly: false }, // 魔法类型 magicType: { type: ['line', 'bar'] }, // 重置 restore: {}, // 保存图片 saveAsImage: {}, }, }, dataZoom: [{ type: 'inside' }, { type: 'slider' }], xAxis: { type: 'category', data: this.data.map((item) => { return item.monitorTime }), }, yAxis: { type: 'value', }, series: [ { name: 'X方向位移', data: this.data.map((item) => { return item.gpsTotalX }), type: 'line', smooth: true, stack: 'Total', }, { name: 'Y方向位移', data: this.data.map((item) => { return item.gpsTotalY }), type: 'line', smooth: true, stack: 'Total', }, { name: 'Z方向位移', data: this.data.map((item) => { return item.gpsTotalZ }), type: 'line', smooth: true, stack: 'Total', }, ], }) }, }, } </script>
- data/trhsl/tpTRHSLData.vue
<template> <div class="app-container"> <!-- 查询 --> <div class="head-container"> <el-select v-model="query.type" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in types" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" format="yyyy-MM-dd HH:mm:ss" @change="toQuery" > </el-date-picker> <span> <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery" >搜索</el-button > <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()" >重置</el-button > </span> </div> <!-- 监测数据 --> <el-table ref="table" :stripe="true" :data="page.data" style="width: 100%;" > <el-table-column type="index" label="序号" width="50px" fixed /> <el-table-column prop="sensorCode" label="传感器编号" /> <el-table-column prop="monitorTime" label="时间" /> <el-table-column prop="value" label="含水率(%)" /> </el-table> <el-pagination :page-size.sync="page.size" :total="page.total" :current-page.sync="page.page" style="margin-top: 8px;" layout="total, prev, pager, next, sizes" @size-change="sizeChangeHandler" @current-change="pageChangeHandler" > </el-pagination> </div> </template> <script> import { statisticsPaging } from '@/api/dz/trhsl' // 导入混入对象 import { timeUtils } from '../timeUtils.js' export default { // 使用混入对象 mixins: [timeUtils], props: { sensorCode: { type: String, required: true, }, }, mounted() { this.toQuery() }, data() { return { types: [ { key: 0, value: '天' }, { key: 1, value: '周' }, { key: 2, value: '月' }, { key: 3, value: '小时' }, { key: 4, value: '实时' }, ], query: { sensorCode: '', type: 0, timeRange: [ // 调用混入方法 getlastMonth this.getlastMonth(), new Date(), ], page: 1, size: 10, }, page: { size: 10, total: 0, page: 0, data: [], }, } }, methods: { toQuery() { this.query.sensorCode = this.sensorCode this.refreshData() }, resetQuery() { this.query.type = 0 this.query.timeRange = [this.getlastMonth(), new Date()] this.query.page = 1 this.query.size = 10 this.refreshData() }, sizeChangeHandler(e) { this.page.size = e this.page.page = 0 this.refreshData() }, pageChangeHandler(e) { this.page.page = e this.refreshData() }, refreshData() { this.query.page = this.page.page - 1 this.query.size = this.page.size statisticsPaging(this.query).then((res) => { this.page.data = res.content this.page.total = res.totalElements }) }, }, } </script>
- data/trhsl/tpTRHSLChart.vue
<template> <div class="app-container"> <!-- 查询 --> <div class="head-container"> <el-select v-model="query.type" clearable size="small" class="filter-item" style="width: 90px" @change="toQuery" > <el-option v-for="item in types" :key="item.key" :label="item.value" :value="item.key" /> </el-select> <el-date-picker v-model="query.timeRange" type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" format="yyyy-MM-dd HH:mm:ss" @change="toQuery" > </el-date-picker> <span> <el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery" >搜索</el-button > <el-button class="filter-item" size="mini" type="warning" icon="el-icon-refresh-left" @click="resetQuery()" >重置</el-button > </span> </div> <!-- 数据图表 --> <div id="chart" style="width: 1200px; height: 800px; border: 1px solid #888;" ></div> </div> </template> <script> // 引入echart组件 import echarts from 'echarts' // require('echarts/theme/macarons') import { statisticsAll } from '@/api/dz/trhsl' // 导入混入对象 import { timeUtils } from '../timeUtils.js' export default { // 使用混入对象 mixins: [timeUtils], props: { sensorCode: { type: String, required: true, }, }, mounted() { this.toQuery() }, data() { return { types: [ { key: 0, value: '天' }, { key: 1, value: '周' }, { key: 2, value: '月' }, { key: 3, value: '小时' }, { key: 4, value: '实时' }, ], query: { sensorCode: '', type: 0, timeRange: [ // 调用混入方法 getlastMonth this.getlastMonth(), new Date(), ], }, data: [], chart: null, } }, methods: { toQuery() { this.query.sensorCode = this.sensorCode this.refreshData() }, resetQuery() { this.query.type = 0 this.query.timeRange = [this.getlastMonth(), new Date()] this.refreshData() }, refreshData() { statisticsAll(this.query).then((res) => { this.data = res this.initChart() }) }, initChart() { this.chart = echarts.init(document.getElementById('chart')) this.setOptions() }, setOptions() { this.chart.setOption({ title: { text: this.sensorCode + ' (土壤含水率)', left: 'center', }, tooltip: { trigger: 'axis', }, legend: { data: ['含水率(%)'], left: 'left', }, toolbox: { // 显示工具箱 show: true, feature: { // 数据缩放 dataZoom: { yAxisIndex: 'none', }, // 数据视图只读 dataView: { readOnly: false }, // 魔法类型 magicType: { type: ['line', 'bar'] }, // 重置 restore: {}, // 保存图片 saveAsImage: {}, }, }, dataZoom: [{ type: 'inside' }, { type: 'slider' }], xAxis: { type: 'category', data: this.data.map((item) => { return item.monitorTime }), }, yAxis: { type: 'value', }, series: [ { name: '含水率(%)', data: this.data.map((item) => { return item.value }), type: 'line', smooth: true, stack: 'Total', }, ], }) }, }, } </script>