viviandjava 5 месяцев назад
Родитель
Сommit
c75d1913cd

BIN
src/assets/images/detail.png


BIN
src/assets/images/detail2.jpg


BIN
src/assets/images/fireWarn.png


BIN
src/assets/images/img.png


BIN
src/assets/images/overflowWarn.png


BIN
src/assets/images/simulate.png


BIN
src/assets/images/sthouse.jpg


BIN
src/assets/images/tempWarn.png


BIN
src/assets/images/video.png


BIN
src/assets/images/wetWarn.png


BIN
src/assets/images/workPro.png


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/assets/json/thly.json


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
src/assets/json/thly2.json


+ 1 - 1
src/layout/components/Navbar.vue

@@ -19,7 +19,7 @@ const navbarBackgroundStyle = computed(() => {
 const showMenu = computed(() => route.path !== '/index')
 let leftMenu = [
   {name: '总  览', path: '/index', type: 'left', style: {}},
-  {name: '监测感知', path: '/situational/63304700', type: 'left', style: {}}
+  {name: '态势感知', path: '/situational/63304700', type: 'left', style: {}}
 ]
 let rightMenu = [
   {name: '智慧运维', path: '/intelloper/63304700', type: 'right', style: {}},

+ 8 - 2
src/layout/index.vue

@@ -19,8 +19,10 @@ function changeFloorType(path) {
   if (path === '/index') {
     appStore.changeFloorType('map')
     // appStore.changeFloorType('img')
-  } else if (path.indexOf('/detail') > -1) {
+  } else if (path.indexOf('/detail') > -1 || path.indexOf('/device') > -1) {
     appStore.changeFloorType('detail')
+  } else if (path.indexOf('/sthouse') > -1) {
+    appStore.changeFloorType('sthouse')
   } else {
     appStore.changeFloorType('ue')
   }
@@ -36,6 +38,7 @@ onMounted(() => {
 
 const yztSrc = ref(new URL('@/assets/images/yzt.png', import.meta.url).href)
 const detailSrc = ref(new URL('@/assets/images/detail.png', import.meta.url).href)
+const sthouseSrc = ref(new URL('@/assets/images/sthouse.jpg', import.meta.url).href)
 
 </script>
 
@@ -43,7 +46,10 @@ const detailSrc = ref(new URL('@/assets/images/detail.png', import.meta.url).hre
   <div :style="{ '--current-color': theme }" class="app-wrapper">
 
     <div v-show="appStore.floorType === 'img'" class="floor-container"><img :src="yztSrc"></div>
-    <div v-show="appStore.floorType === 'detail'" class="floor-container"><img :src="detailSrc"></div>
+    <div v-show="appStore.floorType === 'detail'" class="floor-container"><img :src="detailSrc"
+                                                                               style="width: 100%;height: 100%;"></div>
+    <div v-show="appStore.floorType === 'sthouse'" class="floor-container"><img :src="sthouseSrc"
+                                                                               style="width: 100%;height: 100%;"></div>
     <antv-map v-show="appStore.floorType === 'map'" class="floor-container"></antv-map>
     <ue-player v-show="appStore.floorType === 'ue'" class="floor-container"></ue-player>
 

+ 5 - 1
src/router/index.ts

@@ -28,9 +28,13 @@ const router = createRouter({
           path: 'intelloper/:stcd',
           name: 'intelloper',
           component: () => import('@/views/IntellOper.vue'),
+        },{
+          path: 'sthouse/:stcd',
+          name: 'sthouse',
+          component: () => import('@/views/StationHouse.vue'),
         },
         {
-          path: 'detail/:stcd',
+          path: 'detail/:id',
           name: 'detail',
           component: () => import('@/views/Detail.vue'),
         },

+ 21 - 17
src/utils/device.ts

@@ -1,12 +1,13 @@
 const deviceDetailList = [
-  {id: 1, name: '控制单元', inputName: '控制单元', gName: '控制单元', idx: [], detail: ""},
+  { id: 1, name: '控制单元', inputName: '控制单元', gName: '控制单元', idx: [], detail: '' },
   {
     id: 11,
     name: '高锰酸盐指数分析仪(NSY)',
     gName: 'CODmn',
     idx: ['CODMN'],
     inputName: '高锰酸盐指数分析仪',
-    detail: "仪表选型来自水利部南京水利水文自动化研究所自研的NSY-CODmn型智能高锰酸盐指数在线分析仪。\n检测方法:高锰酸盐氧化法,光度滴定测量法。"
+    img: new URL('@/assets/images/detail2.jpg', import.meta.url).href,
+    detail: '仪表选型来自水利部南京水利水文自动化研究所自研的NSY-CODmn型智能高锰酸盐指数在线分析仪。\n检测方法:高锰酸盐氧化法,光度滴定测量法。'
   },
   {
     id: 6,
@@ -14,7 +15,7 @@ const deviceDetailList = [
     gName: '氨氮总氮',
     idx: ['TN', 'NH3N'],
     inputName: '总氮、氨氮分析仪',
-    detail: "仪表选型来自国产仪表厂商宝仪环境科技(上海)有限公司。\n总氮测量原理:碱性过硫酸盐消解紫外分光光度法;\n氨氮测量原理:水杨酸分光光度法。"
+    detail: '仪表选型来自国产仪表厂商宝仪环境科技(上海)有限公司。\n总氮测量原理:碱性过硫酸盐消解紫外分光光度法;\n氨氮测量原理:水杨酸分光光度法。'
   },
   {
     id: 4,
@@ -22,7 +23,7 @@ const deviceDetailList = [
     gName: '总磷',
     idx: ['TP'],
     inputName: '总磷分析仪',
-    detail: "仪表选型来自国产仪表厂商宝怡环境科技(上海)有限公司。\n总磷测量原理:钼酸铵分光光度法。"
+    detail: '仪表选型来自国产仪表厂商宝怡环境科技(上海)有限公司。\n总磷测量原理:钼酸铵分光光度法。'
   },
   {
     id: 10,
@@ -30,44 +31,47 @@ const deviceDetailList = [
     gName: 'TOC',
     idx: [],
     inputName: '总有机碳分析仪',
-    detail: "仪表选型来自著名仪表厂商岛津。型号为TOC-4200。测量原理是680℃燃烧催化剂氧化-NDIR检测法。"
+    detail: '仪表选型来自著名仪表厂商岛津。型号为TOC-4200。测量原理是680℃燃烧催化剂氧化-NDIR检测法。'
   },
   {
-    id: 1,
+    id: 2,
     name: '常规六参数测定仪',
     gName: '多参数',
     idx: ['WT', 'PH', 'COND', 'REDOX', 'TURB'],
+    img: new URL('@/assets/images/detail2.jpg', import.meta.url).href,
     inputName: '常规六参数测定仪',
-    detail: "监测指标:\n水温(工作原理:热电阻温度传感器是利用导体或半导体的电阻值随温度变化而变化的原理进行测温的);\n" +
-      "pH/ORP(工作原理:利用玻璃电极对水溶液中氢离子浓度变化的选择性响应,与Ag/AgCl参比电极一起在溶液中组合形成“化学电池”。通过对其电动势变化的测量,确定溶液的pH值。)\n" +
-      "电导率(四极式电导率电极。相比2极式电导率,多了另外两个极板,这两个极板之间没有电流流过,只负责提供稳定不变的参考电位。当系统有变化时,如电极受到 污染了,电极根据感测到的信号自动调节加在电流极板上的电压大小,从而自动实现背景补偿。)\n" +
-      "溶解氧(荧光法溶解氧探头在顶端的薄膜上覆盖了一层荧光染料。 当一束短波长的光照射到荧光染料时,荧光染料从应激态回到基态时会发射长波长的红光,红光就是测试信号。溶解氧的浓度越高,红光持续的时间越短,通过测试红光的持续时间就可以知道溶解氧的浓度。)\n" +
-      "浊度(浊度是由水中的悬浮颗粒引起的,悬浮颗粒会漫 反射入射光,通常采用 90 度那个方向的散射光做为 测试信号,这样测试出来的单位称为 NTU。)"
+    detail: '监测指标:\n水温(工作原理:热电阻温度传感器是利用导体或半导体的电阻值随温度变化而变化的原理进行测温的);\n' +
+      'pH/ORP(工作原理:利用玻璃电极对水溶液中氢离子浓度变化的选择性响应,与Ag/AgCl参比电极一起在溶液中组合形成“化学电池”。通过对其电动势变化的测量,确定溶液的pH值。)\n' +
+      '电导率(四极式电导率电极。相比2极式电导率,多了另外两个极板,这两个极板之间没有电流流过,只负责提供稳定不变的参考电位。当系统有变化时,如电极受到 污染了,电极根据感测到的信号自动调节加在电流极板上的电压大小,从而自动实现背景补偿。)\n' +
+      '溶解氧(荧光法溶解氧探头在顶端的薄膜上覆盖了一层荧光染料。 当一束短波长的光照射到荧光染料时,荧光染料从应激态回到基态时会发射长波长的红光,红光就是测试信号。溶解氧的浓度越高,红光持续的时间越短,通过测试红光的持续时间就可以知道溶解氧的浓度。)\n' +
+      '浊度(浊度是由水中的悬浮颗粒引起的,悬浮颗粒会漫 反射入射光,通常采用 90 度那个方向的散射光做为 测试信号,这样测试出来的单位称为 NTU。)'
   },
   {
+    id: 3,
     name: '预处理单元',
     gName: '预处理单元',
     inputName: '预处理单元',
     idx: [],
-    detail: ""
+    detail: ''
   },
   {
+    id: 5,
     name: '水情单元',
     gName: '水情单元',
     idx: [],
     inputName: '水情单元',
-    detail: ""
-  },
+    detail: ''
+  }
   // {
   //   id: 2,
   //   name: '总氮分析仪(PowerMon)',
   //   inputName: '总氮分析仪',
   //   detail: ""
   // },
-];
+]
 
 function getDeviceByName(name: string) {
-  return deviceDetailList.find(item => item.inputName === name);
+  return deviceDetailList.find(item => item.inputName === name)
 }
 
-export {deviceDetailList, getDeviceByName};
+export { deviceDetailList, getDeviceByName }

+ 12 - 11
src/utils/mapConfig.ts

@@ -5,9 +5,10 @@ import {formatStringByTemplate} from "@/utils/string";
 import bus from "@/utils/bus";
 import boundary from '@/assets/json/zmw.json'
 import thData from '@/assets/json/th.json'
-import river2Data from '@/assets/json/river2.json'
-import river4Data from '@/assets/json/river4.json'
-import river5Data from '@/assets/json/river5.json'
+import thRiverData from '@/assets/json/thly2.json'
+// import river2Data from '@/assets/json/river2.json'
+// import river4Data from '@/assets/json/river4.json'
+// import river5Data from '@/assets/json/river5.json'
 
 export let scene: Scene;
 // 加载状态
@@ -94,14 +95,14 @@ function loadBoundaryLayer() {
 
 // 添加河网数据
 function loadRiverLayer() {
-  const river2Layer=new PolygonLayer().source(river2Data).shape('line').size(1.5).color('#4b59b4')
-  scene.addLayer(river2Layer);
-  const river4Layer=new PolygonLayer().source(river4Data).shape('line').size(1).color('#808a93')
-  scene.addLayer(river4Layer);
-  const river5Layer=new PolygonLayer().source(river5Data).shape('line').size(0.5).color('#aed5f3')
-  scene.addLayer(river5Layer);
-  const thLayer=new PolygonLayer().source(thData).shape('line').size(2).color('#d7a8d0')
-  scene.addLayer(thLayer);
+  // const river2Layer=new PolygonLayer().source(river2Data).shape('line').size(1.5).color('#4b59b4')
+  // scene.addLayer(river2Layer);
+  // const river4Layer=new PolygonLayer().source(river4Data).shape('line').size(1).color('#808a93')
+  // scene.addLayer(river4Layer);
+  // const river5Layer=new PolygonLayer().source(river5Data).shape('line').size(0.5).color('#aed5f3')
+  // scene.addLayer(river5Layer);
+  const thRiverLayer=new PolygonLayer().source(thRiverData).shape('line').size(0.8).color('#08DAF1')
+  scene.addLayer(thRiverLayer);
 
 }
 

+ 32 - 38
src/views/Detail.vue

@@ -1,68 +1,62 @@
 <script lang="ts" setup>
-import {onMounted, reactive, ref} from "vue";
-import {useRoute} from 'vue-router';
-import RightFrame from "@/components/RightFrame.vue";
-import Card01 from "@/components/card/Card01.vue";
-import {stations} from "@/utils/station";
+import { onMounted, reactive, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import RightFrame from '@/components/RightFrame.vue'
+import Card01 from '@/components/card/Card01.vue'
+import { device } from '@/utils/device'
 
 const route = useRoute()
 let dibaImage = ref(new URL('@/assets/images/dike.png', import.meta.url).href)
 const jiankong = new URL('@/assets/images/tmp/jiankong.png', import.meta.url).href
 
 
-function getStation(stcd) {
-  return stations.find(item => item.stcd === stcd)
+function getDevice(id) {
+  debugger
+  return device.find(item => item.id === id)
 }
 
-const station = ref(getStation(route.params.stcd))
-const introduces = ref(station.value.detail?.split('\n'))
-const introduceImg = new URL(station.value.img, import.meta.url).href
+const device = ref(getDevice(route.params.id))
+const introduces = ref(device.value.detail?.split('\n'))
+const introduceImg = new URL(device.value.img, import.meta.url).href
+const detailImg = ref(new URL('@/assets/images/detail2.jpg', import.meta.url).href)
 
 const deviceInfoColumns = [
-  {label: '设备名称', prop: 'name'},
-  {label: '设备位置', prop: 'loc', width: '110'},
-  {label: '设备状态', prop: 'status', width: '110'},
+  { label: '设备名称', prop: 'name' },
+  { label: '设备位置', prop: 'loc', width: '110' },
+  { label: '设备状态', prop: 'status', width: '110' }
 ]
 
 const deviceInfoData = [
-  {name: '总磷分析仪', loc: '100米', status: '正常'},
-  {name: '总氮分析仪', loc: '100米', status: '正常'},
-  {name: '水位计', loc: '100米', status: '正常'},
-  {name: '氢氮分析仪', loc: '100米', status: '正常'},
+  { name: '总磷分析仪', loc: '100米', status: '正常' },
+  { name: '总氮分析仪', loc: '100米', status: '正常' },
+  { name: '水位计', loc: '100米', status: '正常' },
+  { name: '氢氮分析仪', loc: '100米', status: '正常' }
 ]
 
-const wqData = ref([])
-const wlData = reactive({ss: '3.80', zg: '4.65', zd: '4.65', bz: '4.65', jj: '4.65'})
 
 onMounted(() => {
-  wqData.value = [
-    {label: '水温', value: '22.3', unit: '℃', imgSrc: new URL('@/assets/images/sz-wd.png', import.meta.url).href},
-    {label: '浊度', value: '235', unit: 'NTU', imgSrc: new URL('@/assets/images/sz-zd.png', import.meta.url).href},
-    {label: '溶解氧', value: '8.22', unit: 'mg/L', imgSrc: new URL('@/assets/images/sz-rjy.png', import.meta.url).href},
-    {
-      label: '电导率',
-      value: '8.22',
-      unit: 'US/cm',
-      imgSrc: new URL('@/assets/images/sz-ddl.png', import.meta.url).href
-    },
-    {label: '总磷', value: '22.3', unit: 'mg/L', imgSrc: new URL('@/assets/images/sz-zl.png', import.meta.url).href},
-    {label: '总氮', value: '22.3', unit: 'mg/L', imgSrc: new URL('@/assets/images/sz-tn.png', import.meta.url).href},
-    {label: '氨氮', value: '22.3', unit: 'mg/L', imgSrc: new URL('@/assets/images/sz-ad.png', import.meta.url).href},
-  ]
 
 })
 </script>
 
 <template>
   <right-frame>
-    <template #rightModule>
+
+    <template #leftModule>
       <card01 style="height: 60%" title="设备简介">
-        <h3 class="introduce-title">{{ station.stnm + station.sttp }}</h3>
-        <p v-for="text in introduces" class="introduce-text" v-html="text"></p>
-        <img v-if="station.img" :src="introduceImg" alt="" class="introduce-img"/>
+        <h3 class="introduce-title">氨氮</h3>
+        <el-row>
+          <el-col :span="12">
+            <p v-for="text in introduces" class="introduce-text" v-html="text"></p>
+          </el-col>
+          <el-col :span="12">
+            <img v-if="device.img" :src="detailImg" alt="" class="introduce-img" />
+          </el-col>
+        </el-row>
+
       </card01>
       <card01 style="height: 30%" title="设备状态">
-        <img :src="jiankong" alt="" style="width: 100%;height: 100%;"/>
+        <img :src="jiankong" alt="" style="width: 100%;height: 100%;" />
       </card01>
     </template>
   </right-frame>

+ 69 - 55
src/views/Device.vue

@@ -1,51 +1,51 @@
 <script lang="ts" setup>
-import {onMounted, ref} from "vue";
-import {useRoute} from 'vue-router';
-import RightFrame from "@/components/RightFrame.vue";
-import Card01 from "@/components/card/Card01.vue";
-import StripeTable from "@/components/StripeTable.vue";
-import {getDeviceByName} from "@/utils/device";
-import Chart from "@/components/Chart.vue";
+import { onMounted, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import RightFrame from '@/components/RightFrame.vue'
+import Card01 from '@/components/card/Card01.vue'
+import StripeTable from '@/components/StripeTable.vue'
+import { getDeviceByName } from '@/utils/device'
+import Chart from '@/components/Chart.vue'
 
 const route = useRoute()
 const right3Ref = ref(null)
-const device = ref(getDeviceByName("高锰酸盐指数分析仪"))
+const device = ref(getDeviceByName('高锰酸盐指数分析仪'))
 
 
 const deviceStatusColumns = [
-  {label: '设备名称', prop: 'name'},
-  {label: '设备位置', prop: 'loc', width: '110'},
-  {label: '设备状态', prop: 'status', width: '110'},
+  { label: '试剂名称', prop: 'name' },
+  { label: '添加体积', prop: 'volume', width: '110' },
+  { label: '更换时间', prop: 'updateTm', width: '110' }
 ]
+
 const deviceStatusData = [
-  {name: '总磷分析仪', loc: '100米', status: '正常'},
-  {name: '总氮分析仪', loc: '100米', status: '正常'},
-  {name: '水位计', loc: '100米', status: '正常'},
-  {name: '氢氮分析仪', loc: '100米', status: '正常'},
+  { name: '总磷分析仪', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '总氮分析仪', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '水位计', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '氢氮分析仪', volume: 2, updateTm: '11-20 15:00:00' }
 ]
-
 const accessoriesColumns = [
-  {label: '设备名称', prop: 'name'},
-  {label: '设备位置', prop: 'loc', width: '110'},
-  {label: '设备状态', prop: 'status', width: '110'},
+  { label: '试剂名称', prop: 'name' },
+  { label: '添加体积', prop: 'volume', width: '110' },
+  { label: '更换时间', prop: 'updateTm', width: '110' }
 ]
 const accessoriesData = [
-  {name: '总磷分析仪', loc: '100米', status: '正常'},
-  {name: '总氮分析仪', loc: '100米', status: '正常'},
-  {name: '水位计', loc: '100米', status: '正常'},
-  {name: '氢氮分析仪', loc: '100米', status: '正常'},
+  { name: '总磷分析仪', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '总氮分析仪', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '水位计', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '氢氮分析仪', volume: 2, updateTm: '11-20 15:00:00' }
 ]
 
 const reagentColumns = [
-  {label: '设备名称', prop: 'name'},
-  {label: '设备位置', prop: 'loc', width: '110'},
-  {label: '设备状态', prop: 'status', width: '110'},
+  { label: '试剂名称', prop: 'name' },
+  { label: '添加体积', prop: 'volume', width: '110' },
+  { label: '更换时间', prop: 'updateTm', width: '110' }
 ]
 const reagentData = [
-  {name: '总磷分析仪', loc: '100米', status: '正常'},
-  {name: '总氮分析仪', loc: '100米', status: '正常'},
-  {name: '水位计', loc: '100米', status: '正常'},
-  {name: '氢氮分析仪', loc: '100米', status: '正常'},
+  { name: '总磷分析仪', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '总氮分析仪', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '水位计', volume: 2, updateTm: '11-20 15:00:00' },
+  { name: '氢氮分析仪', volume: 2, updateTm: '11-20 15:00:00' }
 ]
 
 function reloadRight3(list) {
@@ -55,25 +55,26 @@ function reloadRight3(list) {
 
   const typeSet = new Set()
   const times = []
+  debugger
   list.forEach((item, index) => {
     Object.keys(item).forEach(key => typeSet.add(key))
     times.push(item['maintainDate'] || index + 1)
   })
-  typeSet.delete('maintainDate');
+  typeSet.delete('maintainDate')
   const types = Array.from(typeSet)
-  const rawData = [];
+  const rawData = []
   types.forEach(t => {
     let array = []
     list.forEach(d => array.push(d[t] || 0))
     rawData.push(array)
   })
-  const totalData = [];
+  const totalData = []
   for (let i = 0; i < rawData[0].length; ++i) {
-    let sum = 0;
+    let sum = 0
     for (let j = 0; j < rawData.length; ++j) {
-      sum += Number(rawData[j][i]);
+      sum += Number(rawData[j][i])
     }
-    totalData.push(sum);
+    totalData.push(sum)
   }
   const grid = {
     left: 10,
@@ -81,17 +82,17 @@ function reloadRight3(list) {
     top: 50,
     bottom: 10,
     containLabel: true
-  };
+  }
   const series = types.map((name, sid) => {
     return {
       name,
       type: 'bar',
       stack: 'total',
       barWidth: '60%',
-      label: {show: false,},
+      label: { show: false },
       data: rawData[sid]
-    };
-  });
+    }
+  })
   series.push({
     name: '总计',
     type: 'bar',
@@ -104,7 +105,7 @@ function reloadRight3(list) {
     },
     data: totalData.map(t => 0)
   })
-  let maxValue = totalData.reduce((a, b) => Math.max(a, b));
+  let maxValue = totalData.reduce((a, b) => Math.max(a, b))
   const option = {
     tooltip: {
       trigger: 'axis',
@@ -112,19 +113,19 @@ function reloadRight3(list) {
         type: 'shadow'
       },
       formatter(params) {
-        let circle = `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color:`;
+        let circle = `<span style="display:inline-block;margin-right:5px;border-radius:50%;width:10px;height:10px;left:5px;background-color:`
         let info = params[0].axisValueLabel
         for (let i = 0; i < params.length; i++) {
-          let param = params[i];
+          let param = params[i]
           if (i === params.length - 1) {
-            info += `<br/>${circle}${param.color}"></span> ${param.seriesName}: ${totalData[param.dataIndex]}个`;
+            info += `<br/>${circle}${param.color}"></span> ${param.seriesName}: ${totalData[param.dataIndex]}个`
           } else {
             if (param.value > 0) {
-              info += `<br/>${circle}${param.color}"></span> ${param.seriesName}: ${param.value}个`;
+              info += `<br/>${circle}${param.color}"></span> ${param.seriesName}: ${param.value}个`
             }
           }
         }
-        return info;
+        return info
       }
     },
     legend: {
@@ -134,30 +135,30 @@ function reloadRight3(list) {
       selectedMode: false,
       textStyle: {
         color: '#fff'
-      },
+      }
     },
     grid,
     yAxis: {
       type: 'value',
       name: '个',
       nameTextStyle: {
-        color: '#fff',
+        color: '#fff'
       },
       minInterval: 1,
       interval: Math.ceil(maxValue / 5),
       axisLabel: {
-        color: '#fff',
-      },
+        color: '#fff'
+      }
     },
     xAxis: {
       type: 'category',
       axisLabel: {
-        color: '#fff',
+        color: '#fff'
       },
       data: times
     },
     series
-  };
+  }
   right3Ref.value.loadChart(option)
 }
 
@@ -170,9 +171,22 @@ onMounted(() => {
 <template>
   <right-frame>
     <template #leftModule>
-      <card01 :title="device.name" style="height: 60%">
-        <p v-for="text in device.detail.split('\n')" class="introduce-text" v-html="text"></p>
-        <img v-if="device.img" :src="device.img" alt="" class="introduce-float-img"/>
+      <card01 :title="device.name" style="height: 65%">
+        <h4 style="color: #00ccff">设备简介</h4>
+        <el-row>
+          <el-col :span="16">
+            <p v-for="text in device.detail.split('\n')" class="introduce-text" v-html="text"></p>
+          </el-col>
+          <el-col :span="8">
+            <img v-if="device.img" :src="device.img" alt="" class="introduce-float-img" />
+          </el-col>
+        </el-row>
+        <h4 style="color: #00ccff">维护记录</h4>
+        <p>维护日期‌:2024年11月20日</p>
+        <p>维护内容:</p>
+        <p>·清洗采样过滤头及管路,检查位置确保采样顺利。</p>
+        <p>·检查电源线路,确保干燥和稳定。</p>
+        <p>·校准仪器,确保测量准确性。</p>
       </card01>
       <card01 style="height: 40%" title="设备状态">
         <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>

+ 140 - 28
src/views/IntellOper.vue

@@ -1,15 +1,16 @@
 <script lang="ts" setup>
-import {onMounted, reactive, ref} from 'vue'
-import {useRoute} from 'vue-router'
+import { onMounted, reactive, ref } from 'vue'
+import { useRoute } from 'vue-router'
 import RightFrame from '@/components/RightFrame.vue'
 import Card01 from '@/components/card/Card01.vue'
 import StripeTable from '@/components/StripeTable.vue'
 import ColorTag from '@/components/tag/ColorTag.vue'
-import {getDeviceInfo, getOperationsPersonnelData} from '@/api/device'
+import { getDeviceInfo, getOperationsPersonnelData } from '@/api/device'
 import Chart from '@/components/Chart.vue'
-import {getPie3DSimple} from "@/utils/chart";
-import bus from "@/utils/bus";
-import {jumpPage} from "@/utils";
+import { getPie3DSimple } from '@/utils/chart'
+import bus from '@/utils/bus'
+import { jumpPage } from '@/utils'
+import { Label, Setting, View } from '@/utils/tdInstruction'
 
 const route = useRoute()
 
@@ -17,21 +18,21 @@ const color = ['#005aff', '#f8b551']
 const equipmentStatusData = reactive({
   total: 10,
   onlineTotal: 8,
-  "缺数": 0,
-  "上下限异常": 1,
-  "数据中断": 0,
-  "其他": 1,
+  '缺数': 0,
+  '上下限异常': 1,
+  '数据中断': 0,
+  '其他': 1
 })
 const operationsPersonnelColumns = [
-  {label: '姓名', prop: 'name'},
-  {label: '已处理', prop: 'processed', width: '100'},
-  {label: '未处理', prop: 'untreated', width: '100'},
+  { label: '姓名', prop: 'name' },
+  { label: '已处理', prop: 'processed', width: '100' },
+  { label: '未处理', prop: 'untreated', width: '100' }
 ]
 const operationsPersonnelData = reactive([])
 const deviceColumns = [
-  {label: '设备类型', prop: 'deviceType', width: '110'},
-  {label: '设备名称', prop: 'deviceName'},
-  {label: '运行状态', prop: 'state', width: '90'}
+  { label: '设备类型', prop: 'deviceType', width: '110' },
+  { label: '设备名称', prop: 'deviceName' },
+  { label: '运行状态', prop: 'state', width: '90' }
 ]
 const deviceData = reactive([])
 
@@ -43,8 +44,8 @@ function reloadRight3() {
       name: '故障',
       value: 1,
       itemStyle: {
-        color: '#f3914b',
-      },
+        color: '#f3914b'
+      }
     },
     {
       name: '提醒',
@@ -68,7 +69,7 @@ function reloadRight3() {
       }
     }
   ]
-  const option = getPie3DSimple(optionData, 0.8);
+  const option = getPie3DSimple(optionData, 0.8)
   //是否需要label指引线,如果要就添加一个透明的2d饼状图并调整角度使得labelLine和3d的饼状图对齐,并再次setOption
   option.series.push({
     name: 'pie2d',
@@ -96,7 +97,7 @@ function reloadRight3() {
       item.itemStyle.opacity = 0
       return item
     })
-  });
+  })
   right3Ref.value.loadChart(option, 'bindListen')
 }
 
@@ -127,6 +128,19 @@ bus.on('handle_ue_response', (data) => {
     jumpPage(`/device/${route.params.stcd}/${data.Data.Name}`)
   }
 })
+
+const homeSrc = ref(new URL('@/assets/images/home.png', import.meta.url).href)
+const weatherSrc = ref(new URL('@/assets/images/weather.png', import.meta.url).href)
+const flagSrc = ref(new URL('@/assets/images/flag.png', import.meta.url).href)
+const walkSrc = ref(new URL('@/assets/images/walk.png', import.meta.url).href)
+const cultureSrc = ref(new URL('@/assets/images/culture.png', import.meta.url).href)
+
+const labelState = reactive({'测站主页': false, '仪器运维': false})
+
+function setStationLabel(type = "测站主页") {
+  labelState[type] = !labelState[type]
+  Label.setStationLabel(type, labelState[type])
+}
 </script>
 
 <template>
@@ -142,8 +156,8 @@ bus.on('handle_ue_response', (data) => {
           </el-col>
           <el-col :span="10">
             <div style="display: flex;justify-content: center;">
-              <div style="position: absolute;bottom:40%;font-size:16px;">设备清单</div>
-              <img :src="imgSrc" style="height: 120px;"/>
+<!--              <div style="position: absolute;bottom:40%;font-size:16px;">设备清单</div>-->
+              <img :src="imgSrc" style="height: 120px;" />
             </div>
           </el-col>
           <el-col :span="7">
@@ -172,18 +186,61 @@ bus.on('handle_ue_response', (data) => {
           </el-col>
         </el-row>
       </card01>
-      <card01 style="height: 33%" title="维护情况">
-        <chart ref="right3Ref"></chart>
-      </card01>
-      <card01 style="height: 33%" title="运维人员统计">
-        <stripe-table :columns="operationsPersonnelColumns" :data="operationsPersonnelData"></stripe-table>
+      <card01 title="设备清单" style="height: 65%">
+        <stripe-table :columns="deviceColumns" :data="deviceData"></stripe-table>
       </card01>
+<!--      <card01 style="height: 33%" title="运维人员统计">-->
+<!--        <stripe-table :columns="operationsPersonnelColumns" :data="operationsPersonnelData"></stripe-table>-->
+<!--      </card01>-->
     </template>
     <template #rightModule>
-      <card01 title="设备清单">
+
+      <card01 style="height: 33%" title="维护情况">
+        <chart ref="right3Ref"></chart>
+      </card01>
+      <card01 title="故障报警列表" style="height: 65%">
         <stripe-table :columns="deviceColumns" :data="deviceData"></stripe-table>
       </card01>
     </template>
+    <template #btnGroup>
+      <div class="right-btn-container">
+        <div class="right-btn-item"><img :src="homeSrc"></div>
+        <div class="right-btn-item">
+          <img :src="weatherSrc">
+          <div class="right-btn-option-list">
+            <div class="right-btn-option" @click="Setting.setWeather('晴')">晴</div>
+            <div class="right-btn-option" @click="Setting.setWeather('多云')">多云</div>
+            <div class="right-btn-option" @click="Setting.setWeather('阴天')">阴天</div>
+            <div class="right-btn-option" @click="Setting.setWeather('小雨')">小雨</div>
+            <div class="right-btn-option" @click="Setting.setWeather('中雨')">中雨</div>
+            <div class="right-btn-option" @click="Setting.setWeather('大雨')">大雨</div>
+          </div>
+        </div>
+        <div class="right-btn-item">
+          <img :src="flagSrc">
+          <div class="right-btn-option-list">
+            <div class="right-btn-option" @click="setStationLabel('测站主页')">
+              测站标签
+              <Elview v-show="labelState['测站主页']"></Elview>
+              <Hide v-show="!labelState['测站主页']"></Hide>
+            </div>
+            <div class="right-btn-option" @click="setStationLabel('仪器运维')">
+              仪器运维
+              <Elview v-show="labelState['仪器运维']"></Elview>
+              <Hide v-show="!labelState['仪器运维']"></Hide>
+            </div>
+          </div>
+        </div>
+        <div class="right-btn-item">
+          <img :src="walkSrc">
+          <div class="right-btn-option-list">
+            <div class="right-btn-option" @click="View.changeView('远')">远</div>
+            <div class="right-btn-option" @click="View.changeView('近')">近</div>
+          </div>
+        </div>
+        <div class="right-btn-item"><img :src="cultureSrc"></div>
+      </div>
+    </template>
   </right-frame>
 </template>
 <style lang="scss" scoped>
@@ -205,4 +262,59 @@ bus.on('handle_ue_response', (data) => {
   justify-content: center;
   height: 100%;
 }
+
+.right-btn-container {
+  display: flex;
+  flex-direction: column;
+
+  .right-btn-item {
+    cursor: pointer;
+    position: relative;
+
+    &:hover, &.active {
+
+      img {
+        background-color: rgba(16, 136, 215, 0.6);
+        border-radius: 8px;
+      }
+
+      > .right-btn-option-list {
+        display: block;
+      }
+
+    }
+
+    .right-btn-option-list {
+      display: none;
+      position: absolute;
+      top: 0;
+      right: 1.8rem;
+      width: 160px;
+      padding: 0 20px;
+    }
+
+    .right-btn-option {
+      padding: 10px;
+      margin-bottom: 10px;
+      border-radius: 4px;
+      background-color: #394139;
+      text-align: center;
+      color: #fff;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-size: 1rem;
+
+      svg {
+        width: 1rem;
+        height: 1rem;
+        margin-left: .5rem;
+      }
+
+    }
+
+  }
+}
+
 </style>

+ 355 - 0
src/views/StationHouse.vue

@@ -0,0 +1,355 @@
+<script lang="ts" setup>
+import { onMounted, reactive, ref } from 'vue'
+import { useRoute } from 'vue-router'
+import RightFrame from '@/components/RightFrame.vue'
+import Card01 from '@/components/card/Card01.vue'
+import { stationList, stations } from '@/utils/station'
+import ColorTag from '@/components/tag/ColorTag.vue'
+import Chart from '@/components/Chart.vue'
+import DataTag from '@/components/tag/DataTag.vue'
+import {
+  getRainfallListOfPageByStcd,
+  getWaterLevelAndFlowLatest,
+  getWaterLevelAndFlowListOfPageByStcd,
+  getWaterQualityLatest,
+  getWaterQualityListOfPageByStcd
+} from '@/api/gx'
+import { formatd } from '@/utils/ruoyi'
+import { filterWaterQualitys } from '@/utils/unit'
+import { Label, Setting, View } from '@/utils/tdInstruction'
+import { getLatestTimeWithMinuteMultipleOfFive } from '@/utils/date'
+import { Hide, View as Elview } from '@element-plus/icons-vue'
+import StripeTable from '@/components/StripeTable.vue'
+import { getRStLLMaxDate } from '@/api/home'
+
+const route = useRoute()
+const dibaImage = (new URL('@/assets/images/dike.png', import.meta.url).href)
+const homeSrc = ref(new URL('@/assets/images/home.png', import.meta.url).href)
+const weatherSrc = ref(new URL('@/assets/images/weather.png', import.meta.url).href)
+const flagSrc = ref(new URL('@/assets/images/flag.png', import.meta.url).href)
+const walkSrc = ref(new URL('@/assets/images/walk.png', import.meta.url).href)
+const cultureSrc = ref(new URL('@/assets/images/culture.png', import.meta.url).href)
+const workProSrc = ref(new URL('@/assets/images/workPro.png', import.meta.url).href)
+const videoSrc = ref(new URL('@/assets/images/video.png', import.meta.url).href)
+const simulateSrc = ref(new URL('@/assets/images/simulate.png', import.meta.url).href)
+const tempWarnSrc = ref(new URL('@/assets/images/tempWarn.png', import.meta.url).href)
+const overflowWarnSrc = ref(new URL('@/assets/images/overflowWarn.png', import.meta.url).href)
+const fireWarnSrc = ref(new URL('@/assets/images/fireWarn.png', import.meta.url).href)
+const wetWarnSrc = ref(new URL('@/assets/images/wetWarn.png', import.meta.url).href)
+
+const wqData = ref({ d1: '6', d2: '22.3', d3: '5', d4: '20', d5: '6', d6: '22.3', d7: '5', d8: '20' })
+const station = ref(getStation(route.params.stcd))
+const wlData = reactive({
+  ss: '0',
+  zg: '0',
+  zd: '0',
+  bz: station.value.grz ? station.value.grz + '' : '0',
+  jj: station.value.wrz ? station.value.wrz + '' : '0'
+})
+
+function getStation(stcd) {
+  return stations.find(item => item.stcd === stcd)
+}
+
+/**
+ * 获取最新水质数据
+ */
+function getLatestWaterQuality() {
+  getWaterQualityLatest({ stcds: route.params.stcd }).then(res => {
+    const data = res.data[0]
+    wqData.value = {
+      d1: data.ph,
+      d2: data.dox,
+      d3: data.chla,
+      d4: data.turb,
+      d5: data.wt,
+      d6: data.cond,
+      d7: data.tn,
+      d8: data.tp
+    }
+  })
+}
+
+const labelState = reactive({ '测站主页': false, '仪器运维': false })
+
+function setStationLabel(type = '测站主页') {
+  labelState[type] = !labelState[type]
+  Label.setStationLabel(type, labelState[type])
+}
+
+const tableColumns = [
+  {
+    label: '站名', prop: 'stnm', convertFn: (data) => {
+      return data ? data.trim() : ''
+    }
+  },
+  {
+    label: '时间', prop: 'tm', width: '90', convertFn: (data) => {
+      return data ? data.substring(5, 16) : ''
+    }
+  },
+  {
+    label: '水位(m)', prop: 'z', width: '80', convertFn: (data) => {
+      return Number(data).toFixed(2)
+    }
+  },
+  {
+    label: '流量', prop: 'q', width: '70', convertFn: (data) => {
+      return Number(data).toFixed(2)
+    }
+  },
+  {
+    label: '雨量', prop: 'drp', width: '65', convertFn: (data) => {
+      return data | 0
+    }
+  }
+]
+const tableData = reactive([])
+
+function getStationList() {
+  getRStLLMaxDate().then(res => {
+    tableData.push(...res)
+    initPoints()
+  })
+}
+const left1Ref = ref(null)
+async function reloadLeft1() {
+  const sevenDayAgo = new Date(new Date().getTime() - 1 * 24 * 60 * 60 * 1000)
+  const flowData = await getWaterLevelAndFlowListOfPageByStcd({
+    stcd: route.params.stcd,
+    startTime: formatd(sevenDayAgo),
+    endTime: formatd(new Date())
+  }).then(res => {
+    return res.rows
+  })
+  const option = {
+    // backgroundColor: "#0B2D55",
+    tooltip: {
+      trigger: 'axis',
+    },
+    grid: {
+      top: '14%',
+      left: '2%',
+      right: '4%',
+      bottom: '2%',
+      containLabel: true
+    },
+    xAxis: [{
+      type: 'category',
+      boundaryGap: false,
+      axisLine: { // 坐标轴轴线相关设置。数学上的x轴
+        show: true,
+        lineStyle: {
+          color: '#233e64'
+        }
+      },
+      axisLabel: { // 坐标轴刻度标签的相关设置
+        color: '#02cacf'
+      },
+      axisTick: {show: false},
+      data: flowData.map(item => item.tm ? item.tm.substring(11, 16) + '\n' + item.tm.substring(5, 10) : '')
+    }],
+    yAxis: [{
+      name: 'm³/s',
+      nameTextStyle: {
+        color: '#02cacf'
+      },
+      min: value => (value.min - 10).toFixed(0),
+      max: value => (value.max + 10).toFixed(0),
+      axisLabel: {
+        color: '#02cacf'
+      },
+      splitLine: {
+        show: true,
+        lineStyle: {
+          color: '#233e64'
+        }
+      },
+      axisLine: {
+        show: true
+      }
+    }],
+    series: [{
+      name: '流量',
+      type: 'line',
+      areaStyle: {},
+      smooth: true, //是否平滑曲线显示
+      lineStyle: {
+        color: '#3deaff'
+      },
+      // barWidth: 18,
+      // label: {
+      //   show: true,
+      //   position: 'top'
+      // },
+      data: flowData.map(item => item.q)
+    }
+    ]
+  }
+  left1Ref.value.loadChart(option)
+}
+
+
+onMounted(() => {
+  reloadLeft1()
+
+  // 获取最新水质数据
+  getLatestWaterQuality()
+  getStationList()
+
+})
+</script>
+<template>
+  <right-frame>
+    <template #leftModule>
+      <card01 style="height: 45%;" title="运行监控">
+        <el-row :gutter="10" justify="space-around" style="height: 100%;">
+         <div style="width:100%;height: 50%;"><chart ref="left1Ref" style="width: 100%;height: 100%;"></chart></div>
+          <el-col :span="12" style="height: 23%;">
+            <img :src="tempWarnSrc" alt="" class="difang-image" />
+          </el-col>
+          <el-col :span="12" style="height: 23%;">
+            <img :src="overflowWarnSrc" alt="" class="difang-image" />
+          </el-col>
+          <el-col :span="12" style="height: 23%;">
+            <img :src="fireWarnSrc" alt="" class="difang-image" />
+          </el-col>
+          <el-col :span="12" style="height: 23%;">
+            <img :src="wetWarnSrc" alt="" class="difang-image" />
+          </el-col>
+        </el-row>
+      </card01>
+      <card01 style="height: 55%" title="告警记录">
+        <stripe-table :columns="tableColumns" :data="tableData"></stripe-table>
+      </card01>
+    </template>
+    <template #rightModule>
+      <card01 style="height: 65%" title="监测流程">
+        <img :src="workProSrc" style="width: 100%;height: 83%;">
+        <img :src="simulateSrc" style="width: 100%;">
+      </card01>
+      <card01 style="height: 35%" title="站房监控">
+        <img :src="videoSrc" style="width: 100%;height: 100%;">
+      </card01>
+    </template>
+    <template #btnGroup>
+      <div class="right-btn-container">
+        <div class="right-btn-item"><img :src="homeSrc"></div>
+        <div class="right-btn-item">
+          <img :src="weatherSrc">
+          <div class="right-btn-option-list">
+            <div class="right-btn-option" @click="Setting.setWeather('晴')">晴</div>
+            <div class="right-btn-option" @click="Setting.setWeather('多云')">多云</div>
+            <div class="right-btn-option" @click="Setting.setWeather('阴天')">阴天</div>
+            <div class="right-btn-option" @click="Setting.setWeather('小雨')">小雨</div>
+            <div class="right-btn-option" @click="Setting.setWeather('中雨')">中雨</div>
+            <div class="right-btn-option" @click="Setting.setWeather('大雨')">大雨</div>
+          </div>
+        </div>
+        <div class="right-btn-item">
+          <img :src="flagSrc">
+          <div class="right-btn-option-list">
+            <div class="right-btn-option" @click="setStationLabel('测站主页')">
+              测站标签
+              <Elview v-show="labelState['测站主页']"></Elview>
+              <Hide v-show="!labelState['测站主页']"></Hide>
+            </div>
+            <div class="right-btn-option" @click="setStationLabel('仪器运维')">
+              仪器运维
+              <Elview v-show="labelState['仪器运维']"></Elview>
+              <Hide v-show="!labelState['仪器运维']"></Hide>
+            </div>
+          </div>
+        </div>
+        <div class="right-btn-item">
+          <img :src="walkSrc">
+          <div class="right-btn-option-list">
+            <div class="right-btn-option" @click="View.changeView('远')">远</div>
+            <div class="right-btn-option" @click="View.changeView('近')">近</div>
+          </div>
+        </div>
+        <div class="right-btn-item"><img :src="cultureSrc"></div>
+      </div>
+    </template>
+  </right-frame>
+</template>
+<style lang="scss" scoped>
+@use "@/assets/styles/introduce.scss";
+
+.difang-water-level {
+  position: absolute;
+  bottom: 10px;
+  width: 80%;
+  height: 60%;
+  background-color: rgba(0, 204, 255, 0.6);
+  border-top: 3px solid rgba(0, 204, 255);
+
+  .difang-water-level-value {
+    position: absolute;
+    top: -2rem;
+    font-size: 1.2rem;
+    color: #fff;
+  }
+
+}
+
+.difang-image {
+  position: relative;
+  width: 100%;
+  height: 100%;
+}
+
+.right-btn-container {
+  display: flex;
+  flex-direction: column;
+
+  .right-btn-item {
+    cursor: pointer;
+    position: relative;
+
+    &:hover, &.active {
+
+      img {
+        background-color: rgba(16, 136, 215, 0.6);
+        border-radius: 8px;
+      }
+
+      > .right-btn-option-list {
+        display: block;
+      }
+
+    }
+
+    .right-btn-option-list {
+      display: none;
+      position: absolute;
+      top: 0;
+      right: 1.8rem;
+      width: 160px;
+      padding: 0 20px;
+    }
+
+    .right-btn-option {
+      padding: 10px;
+      margin-bottom: 10px;
+      border-radius: 4px;
+      background-color: #394139;
+      text-align: center;
+      color: #fff;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      font-size: 1rem;
+
+      svg {
+        width: 1rem;
+        height: 1rem;
+        margin-left: .5rem;
+      }
+
+    }
+
+  }
+}
+</style>

Некоторые файлы не были показаны из-за большого количества измененных файлов