Pārlūkot izejas kodu

Merge branch 'master' of http://39.98.38.2:13000/lql/tba-nbhs

viviandjava 4 mēneši atpakaļ
vecāks
revīzija
be311c329b

+ 4 - 4
src/api/device.ts

@@ -16,13 +16,13 @@ export function getDeviceInfo() {
     },
     {
       "deviceType": "水质测验设备",
-      "deviceName": "氨氮",
-      "state": "常",
+      "deviceName": "氨氮分析仪",
+      "state": "常",
     },
     {
       "deviceType": "水质测验设备",
       "deviceName": "总磷总氮",
-      "state": "常",
+      "state": "常",
     },
     {
       "deviceType": "水质测验设备",
@@ -32,7 +32,7 @@ export function getDeviceInfo() {
     {
       "deviceType": "水质测验设备",
       "deviceName": "多参数采样器",
-      "state": "常",
+      "state": "常",
     },
     {
       "deviceType": "水质测验设备",

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 112 - 112
src/assets/json/typical_63304700_dsb.json


+ 13 - 0
src/assets/svg/underwater.svg

@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+        "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1734661239225" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7547"
+     xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
+    <path d="M74.053818 228.212364c-23.552 142.801455 159.883636 393.821091 371.758546 560.360727 192.791273 151.458909 376.692364 157.789091 412.858181-16.290909l8.797091-43.380364c49.757091-254.882909 21.736727-416.814545-160.768-487.703273l-32.907636-12.520727c-128.930909-47.709091-259.444364-83.176727-361.751273-94.859636-136.192-15.592727-224.116364 10.24-237.986909 94.394182z m231.656727-38.912c97.140364 11.077818 223.604364 45.474909 348.485819 91.694545l32.488727 12.334546c147.316364 57.250909 170.961455 194.187636 125.998545 424.634181l-8.750545 43.101091c-24.576 118.411636-157.882182 113.803636-323.584-16.430545-196.747636-154.577455-370.222545-391.959273-351.185455-507.345455 7.074909-42.961455 66.885818-60.509091 176.546909-47.988363z"
+          fill="" p-id="7548"></path>
+    <path d="M419.746909 334.336c-56.413091-0.325818-92.392727 30.999273-92.392727 91.648 0 107.799273 91.089455 209.175273 201.029818 253.533091 101.888 41.099636 174.778182 10.472727 193.117091-90.763636 16.477091-90.903273-34.397091-163.560727-130.094546-205.544728l-35.048727-14.149818c-58.042182-22.667636-100.072727-34.443636-136.610909-34.722909z m-0.325818 55.854545c27.554909 0.186182 64.698182 10.658909 116.363636 30.72l33.978182 13.777455c73.309091 32.209455 108.078545 81.780364 96.814546 144.151273-11.496727 63.255273-45.893818 77.730909-117.294546 48.872727-90.903273-36.677818-166.074182-120.32-166.074182-201.728 0-27.927273 9.216-35.933091 36.212364-35.793455z"
+          fill="" p-id="7549"></path>
+    <path d="M899.863273 0A124.136727 124.136727 0 0 1 1024 124.136727v775.726546A124.136727 124.136727 0 0 1 899.863273 1024H124.136727A124.136727 124.136727 0 0 1 0 899.863273V124.136727A124.136727 124.136727 0 0 1 124.136727 0h775.726546z m0 55.854545H124.136727c-35.514182 0-64.698182 27.089455-67.956363 61.672728l-0.325819 6.609454v775.726546c0 35.514182 27.089455 64.698182 61.672728 67.956363l6.609454 0.325819h775.726546c35.514182 0 64.698182-27.089455 67.956363-61.672728l0.325819-6.609454V124.136727c0-35.514182-27.089455-64.698182-61.672728-67.956363l-6.609454-0.325819z"
+          fill="" p-id="7550"></path>
+    <path d="M0 487.098182c79.685818 151.645091 174.359273 262.330182 284.020364 332.101818l47.569454 30.068364A6703.616 6703.616 0 0 0 625.012364 1024H124.136727A124.136727 124.136727 0 0 1 0 899.863273v-412.765091z m55.808 192.791273l0.046545 219.973818c0 35.514182 27.089455 64.698182 61.672728 67.956363l6.609454 0.325819 293.934546-0.046546-22.760728-13.730909c-26.996364-16.477091-54.784-33.605818-83.269818-51.432727l-58.042182-36.631273c-66.094545-42.030545-126.789818-97.419636-182.085818-165.888l-16.104727-20.526545zM899.863273 0A124.136727 124.136727 0 0 1 1024 124.136727v187.066182c-105.751273-73.728-251.438545-142.987636-367.150545-187.671273A5624.413091 5624.413091 0 0 0 375.063273 23.598545L325.352727 7.586909 282.903273 0 899.863273 0z m0 55.854545l-263.866182-0.046545 40.96 15.639273a2142.952727 2142.952727 0 0 1 273.966545 128.512l17.175273 9.867636 0.046546-85.690182c0-35.514182-27.089455-64.698182-61.672728-67.956363l-6.609454-0.325819z"
+          fill="" p-id="7551"></path>
+</svg>

+ 9 - 1
src/components/Chart.vue

@@ -5,7 +5,7 @@ import 'echarts-gl' // 3d图表库
 import {waterQualitys} from "@/utils/unit.js";
 import {nextTick, onMounted, onUnmounted, ref} from "vue";
 
-defineExpose({loadChart, carousel, bindListen})
+defineExpose({loadChart, carousel, bindListen, markLineChange})
 
 const chartRef = ref(null)
 let chart = null
@@ -26,6 +26,14 @@ async function loadChart(option, type = null) {
   }
 }
 
+function markLineChange(index) {
+  if (chart) {
+    const option = chart.getOption()
+    option.series[0].markLine.data = [{xAxis: index}]
+    chart.setOption(option, true);
+  }
+}
+
 function reloadChart() {
   const checkAndResize = () => {
     if (chart) {

+ 3 - 2
src/components/CrossSection.vue

@@ -28,12 +28,13 @@ function calculateWaterArea() {
     const waterArea = waterAreaData.find(d => d.z === 2.91)
     v += waterArea?.area || 0
     totalValue['水面积'] = v + (totalValue['水位'] - 2.91) * totalValue['水面宽']
+    totalValue['水面积'] = (totalValue['水面积']).toFixed(2)
   } else {
     const waterArea = waterAreaData.find(d => d.z === totalValue['水位'])
     if (waterArea) {
-      totalValue['水面积'] = waterArea.area
+      totalValue['水面积'] = (waterArea.area).toFixed(2)
     } else {
-      totalValue['水面积'] = 0
+      totalValue['水面积'] = 0.00
     }
   }
 }

+ 17 - 1
src/components/StationRightButtonGroup.vue

@@ -8,6 +8,7 @@ import {jumpPage} from "@/utils";
 import {useAppStore} from '@/stores/app'
 import {useStationStore} from '@/stores/station'
 import handle from "@/assets/svg/handle.svg";
+import underwater from "@/assets/svg/underwater.svg";
 import horizontalContract from "@/assets/svg/horizontal-contract.svg";
 import horizontalExpand from "@/assets/svg/horizontal-expand.svg";
 import roam from "@/assets/svg/roam.svg";
@@ -68,7 +69,7 @@ const station = computed(() => getStation(route.params.stcd))
 const hasBack = computed(() => route.path.indexOf('/sthouse/') > -1 || route.path.indexOf('/device/') > -1)
 // 是否显示模拟按钮
 const hasHandle = computed(() => route.path.indexOf('/situational/') > -1)
-
+const underwaterState = ref(false)
 // 测站标签
 const label1State = computed({
   get: () => stationStore.labelState['测站主页'],
@@ -271,6 +272,10 @@ watch(() => route.path, path => {
   }
 }, {deep: true, immediate: true})
 
+watch(() => underwaterState.value, (value) => {
+  Operate.setUnderwaterState(route.params.stcd, value)
+})
+
 onUnmounted(() => {
   if (riverRoamStatus.value !== 0) {
     Operate.roam('river', '结束')
@@ -341,6 +346,17 @@ watch(() => stationRoamStatus.value, (value) => {
         </el-button>
       </el-button-group>
     </el-popover>
+
+    <el-popover placement="left-start" trigger="hover" width="auto">
+      <template #reference>
+        <div class="right-btn-item">
+          <img :src="backgroundSrc" alt="" style="position: absolute;"/>
+          <icon :data="underwater"/>
+        </div>
+      </template>
+      水下地形&nbsp;<el-switch v-model="underwaterState" :active-action-icon="Elview" :inactive-action-icon="Hide"/>
+    </el-popover>
+
     <el-popover placement="left-start" trigger="hover" width="auto">
       <template #reference>
         <div v-if="route.params.stcd === '63304700'" class="right-btn-item">

+ 8 - 7
src/components/TimeScrollbar.vue

@@ -1,5 +1,5 @@
 <script lang="ts" setup>
-import {getCurrentInstance, onMounted, onUnmounted, ref} from "vue";
+import {getCurrentInstance, onUnmounted, ref} from "vue";
 import {RefreshLeft, VideoPause, VideoPlay} from '@element-plus/icons-vue'
 
 defineProps({
@@ -14,7 +14,11 @@ defineProps({
   formatTooltip: {
     type: Function,
     default: value => value
-  }
+  },
+  step: {
+    type: Number,
+    default: 1
+  },
 })
 const sliderRef = ref(null)
 const emit = defineEmits(['change', "input"]);
@@ -32,7 +36,7 @@ function play() {
     if (value.value === props.max) {
       closeTimer()
     }
-    value.value++
+    value.value = value.value + props.step
   }, 1000);
 }
 
@@ -54,9 +58,6 @@ function closeTimer() {
   }
 }
 
-onMounted(() => {
-})
-
 onUnmounted(() => {
   closeTimer()
 })
@@ -70,7 +71,7 @@ onUnmounted(() => {
     </div>
     <div class="time-slider-container">
       <el-slider ref="sliderRef" v-model="value" :format-tooltip="props.formatTooltip" :marks="props.marks"
-                 :max="props.max"
+                 :max="props.max" :step="props.step"
                  style="width: 100%;" tooltip-class="show-tooltip"></el-slider>
     </div>
   </div>

+ 21 - 3
src/components/TypicalChart.vue

@@ -1,9 +1,10 @@
 <script lang="ts" setup>
 import * as echarts from "echarts";
 import Chart from "@/components/Chart.vue";
-import {getCurrentInstance, onMounted, ref} from "vue";
+import {getCurrentInstance, onMounted, ref, watch} from "vue";
 import {useStationStore} from '@/stores/station'
 import {getTypicalData} from "@/utils/typicalYear";
+import Bus from "@/utils/bus";
 
 defineProps({
   stcd: {},
@@ -47,14 +48,14 @@ async function reloadChart(data) {
         formatter: value => (value).toFixed(2)
       },
     },
-    dataZoom: [{start: 30, end: 70}],
+    // dataZoom: [{start: 0, end: 100}],
     series: [
       {
         name: '水位',
         type: 'line',
         symbol: 'none',
         // sampling: 'lttb',
-        smooth: true, //是否平滑曲线显示
+        smooth: true, // 是否平滑曲线显示
         itemStyle: {
           color: '#00ccff'
         },
@@ -71,6 +72,11 @@ async function reloadChart(data) {
             }
           ])
         },
+        markLine: {
+          symbol: ['none', 'none'],
+          label: {show: false},
+          data: [{xAxis: 0}]
+        },
         data: data.map(item => item.z)
       },
     ]
@@ -82,6 +88,18 @@ onMounted(async () => {
   const data = await getTypicalData(props.stcd, props.name)
   reloadChart(data)
 })
+
+watch(() => props.name, async (name) => {
+  debugger
+  const data = await getTypicalData(props.stcd, name)
+  reloadChart(data)
+})
+
+Bus.on("TypicalChartMarkLineChange", index => {
+  if (chartRef.value) {
+    chartRef.value.markLineChange(index)
+  }
+})
 </script>
 <template>
   <chart ref="chartRef"></chart>

+ 2 - 1
src/components/tag/DataTag.vue

@@ -2,6 +2,7 @@
 import {getCurrentInstance, ref, watch} from 'vue'
 import {getWaterQualityAssessment} from "@/api/gx";
 import {useRoute} from "vue-router";
+import {notEmpty} from "@/utils/validate";
 
 defineProps({
   data: {type: Object, default: () => ({})}
@@ -40,7 +41,7 @@ watch(() => props.data, (val) => {
       <el-col :span="12">
         <div style="position: relative;display: flex;justify-content: center;">
           <!-- Ⅰ Ⅱ  Ⅲ  Ⅳ Ⅴ Ⅵ   -->
-          <div style="position: absolute;bottom:35%;font-size:36px;">Ⅲ</div>
+          <div style="position: absolute;bottom:35%;font-size:36px;">{{ notEmpty(props.data) ? '' : '' }}</div>
           <img :src="szpjTitleSrc" style="position: absolute;bottom:10%;"/>
           <img :src="imgSrc" style="height: 140px;"/>
         </div>

+ 1 - 1
src/utils/chart.ts

@@ -251,7 +251,7 @@ const getParametricEquation = (startRatio: number, endRatio: number, isSelected:
       if (u > Math.PI * 2.5) {
         return Math.sin(u) * h * 0.1
       }
-      return Math.sin(v) > 0 ? 1 * h * 0.1 : -1
+      return Math.sin(v) > 0 ? h * 0.1 : -1
     }
   }
 }

+ 3 - 5
src/utils/device.ts

@@ -31,8 +31,7 @@ const deviceDetailList = [
     "nanshuiDevId": "D4",
     idx: ['CODMN'],
     img: new URL('@/assets/images/device/COD分析仪.png', import.meta.url).href,
-    detail: '仪器是一种在线自动测试系统,仪器结构由水样采集装置、试样计量器、试剂计量器、氧化反应器、反应终点测定装置、数据显示装置、药液输送装置、试液排出装置、自动清洗装置、程序控制装置、数据传输装置(通信接口)以及机箱、面板等部件组成。 \n' +
-      '仪器采用温度传感器用于加热器控制,终点判定采用光度法检测颜色变化;采用 PLC 技术实现滴定过程控制以及数据计算、记录、显示、远程传输,仪器在测量周期间隙可调,使用已知浓度的标准溶液可进行自动标定。同时,根据需要可在任意时间进行手动校准。采用多种安全报警措施,包括电子切换装置,自动校准程序,为用户提供了一个简单的菜单设置程序,以满足使用要求。',
+    detail: '仪器是一种在线自动测试系统,仪器结构由水样采集装置、试样计量器、试剂计量器、氧化反应器、反应终点测定装置、数据显示装置、药液输送装置、试液排出装置、自动清洗装置、程序控制装置、数据传输装置(通信接口)以及机箱、面板等部件组成。',
     list: [{}]
   },
   {
@@ -87,8 +86,7 @@ const deviceDetailList = [
     "deviceName": "翻斗式雨量传感器",
     "ueDeviceName": "翻斗式雨量桶",
     img: new URL('@/assets/images/device/翻斗式雨量传感器.png', import.meta.url).href,
-    detail: '翻斗式雨量传感器 是一种水文、气象仪器,用以测量自然界降雨量,同时将降雨量转换为以开关量形式表示的数字信息量输出,以满足信息传输、处理、记录和显示等的需要。 国内首先研制成功的0.2、0.5mm翻斗式雨量计,可用于国家水文、气象站网雨量数据长期收集的雨量传感器。翻斗式雨量计是降水量测量一次仪表,其性能符合国家标准GB/T11832-2002《翻斗式雨量计》和国家标准GB/T11831-2002《水文测报装置遥测雨量计》相关要求。\n' +
-      '该仪器与记录或显示部分配套,可进行有线雨量数据传输、显示、自记。与无线水情自动测报系统配套,作为专设站雨情遥测报汛的传感器。 广泛用于全国各水文站,并且批量出口东西方国家,获国家实用新型专利。该型雨量传感器经中国气象局产业发展与装备部选型试验、考核,证明性能稳定性,性能达到国际先进水平。'
+    detail: '翻斗式雨量传感器 是一种水文、气象仪器,用以测量自然界降雨量,同时将降雨量转换为以开关量形式表示的数字信息量输出,以满足信息传输、处理、记录和显示等的需要。 国内首先研制成功的0.2、0.5mm翻斗式雨量计,可用于国家水文、气象站网雨量数据长期收集的雨量传感器。翻斗式雨量计是降水量测量一次仪表,其性能符合国家标准GB/T11832-2002《翻斗式雨量计》和国家标准GB/T11831-2002《水文测报装置遥测雨量计》相关要求。'
   },
   {
     "deviceType": "降雨观测设备",
@@ -96,7 +94,7 @@ const deviceDetailList = [
     "ueDeviceName": "称重式雨量桶",
     img: new URL('@/assets/images/device/翻斗式雨量传感器.png', import.meta.url).href,
     detail: '称重式自记雨量计利用一个弹簧装置或一个重量平衡系统,将储水器连同其中积存的降水的总重量作连续记录。没有自动倒水,固定容积,需减小蒸发损失(加油或其他蒸发抑制剂),特别适合测量固体降水。\n' +
-      '称重式自记雨量计可以连续记录接雨杯上的以及存储在其内的降水的重量。记录方式可以用机械发条装置或平衡锤系统,将全部降水量的重量如数记录下来,并能够记录雪、冰雹及雨雪混合降水。用以连续测量记录降雨量、降雨历时和降雨强度。适用于气象台(站)、水文站、环保、防汛排涝以及农、林等有关部门用来测量降水量。'
+      '称重式自记雨量计可以连续记录接雨杯上的以及存储在其内的降水的重量。'
   },
   {
     "deviceType": "监控",

+ 30 - 1
src/utils/tdInstruction/operate.ts

@@ -33,6 +33,24 @@ export async function setWaterLevel(stcd: any, value: any = waterLevel, speed: a
   console.log("-- 设置测站水位,流速", JSON.stringify(descriptor));
 }
 
+
+export async function setUnderwaterState(stcd: any, show = true) {
+  let value = "-5"
+  if (!show) {
+    const store = useStationStore()
+    value = waterLevel ? waterLevel : await store.getZ() + ''
+  }
+  let descriptor = {
+    "command": "WaterLevel",
+    "data": {
+      "ID": stcd,
+      "code": value,
+    }
+  }
+  Bus.emit('emitUIInteraction', descriptor)
+  console.log("-- 水下地形:", JSON.stringify(descriptor));
+}
+
 /**
  * 设置测站流速
  * @param stcd 测站编码
@@ -101,5 +119,16 @@ export function roam(type: any = 'river', operate: any = 'play') {
   console.log("-- 漫游:" + (type === 'river' ? "河道" : "测站"), JSON.stringify(descriptor));
 }
 
-
+export function setPointState(stcd: any, name: string, type: string) {
+  let descriptor = {
+    "command": "POIwarning",
+    "data": {
+      "ID": stcd,
+      "Name": name,
+      "type": type
+    }
+  }
+  Bus.emit('emitUIInteraction', descriptor);
+  console.log("-- 设置设备告警:", JSON.stringify(descriptor));
+}
 

+ 7 - 0
src/utils/validate.ts

@@ -109,3 +109,10 @@ export function isNumber(val: any) {
   }
   return !isNaN(val)
 }
+
+export function notEmpty(val: any) {
+  if (typeof val === 'object') {
+    return Object.keys(val).length > 0;
+  }
+  return false
+}

+ 29 - 16
src/views/Device.vue

@@ -51,7 +51,7 @@ const accessoriesColumns = [
       var formatDate = 'yyyy-MM-DD'
       var curday = moment().format(formatDate)
       var outday = moment(data)
-      return outday.diff(curday, 'days')
+      return outday.diff(curday, 'days') + '天'
     }
   },
   {
@@ -345,6 +345,22 @@ onUnmounted(() => {
     Label.adcpfx(route.params.stcd, false)
   }
 })
+
+const contentType = {
+  '1': '数据中断',
+  '2': '超出上限',
+  '3': '超出下限',
+  '4': '缺数',
+  '5': '临近保质期',
+}
+
+function getMaintainContent(warnContent) {
+  if (warnContent) {
+    return contentType[warnContent] || ''
+  }
+  return ''
+}
+
 </script>
 
 <template>
@@ -355,20 +371,18 @@ onUnmounted(() => {
           <device-introduce></device-introduce>
           <h4 style="color: #00ccff">维护记录</h4>
           <p>维护日期‌:{{ maintainRecord.handleTime }}</p>
-          <p>维护内容:</p>
-          <p>{{ maintainRecord.warnContent }}</p>
+          <p>维护内容:{{ getMaintainContent(maintainRecord.warnContent) }}</p>
         </card01>
-<!--        <card01 style="height: 40%" title="设备维护情况">-->
-<!--          <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>-->
-<!--        </card01>-->
+        <!--        <card01 style="height: 40%" title="设备维护情况">-->
+        <!--          <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>-->
+        <!--        </card01>-->
       </template>
       <template v-if="deviceType === 'waterQuality'">
         <card01 :title="device.deviceName" style="height: 65%">
           <device-introduce></device-introduce>
           <h4 style="color: #00ccff">维护记录</h4>
           <p>维护日期‌:{{ maintainRecord.handleTime }}</p>
-          <p>维护内容:</p>
-          <p>{{ maintainRecord.warnContent }}</p>
+          <p>维护内容:{{ getMaintainContent(maintainRecord.warnContent) }}</p>
         </card01>
         <card01 style="height: 40%" title="水质监测">
           <water-quality-analysis></water-quality-analysis>
@@ -381,12 +395,11 @@ onUnmounted(() => {
           <device-introduce></device-introduce>
           <h4 style="color: #00ccff">维护记录</h4>
           <p>维护日期‌:{{ maintainRecord.handleTime }}</p>
-          <p>维护内容:</p>
-          <p>{{ maintainRecord.warnContent }}</p>
+          <p>维护内容:{{ getMaintainContent(maintainRecord.warnContent) }}</p>
         </card01>
-<!--        <card01 style="height: 40%" title="设备维护情况">-->
-<!--          <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>-->
-<!--        </card01>-->
+        <!--        <card01 style="height: 40%" title="设备维护情况">-->
+        <!--          <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>-->
+        <!--        </card01>-->
       </template>
       <template v-if="deviceType=== 'video'">
         <card01 style="height: 40%" title="视频监控">
@@ -413,9 +426,9 @@ onUnmounted(() => {
         </card01>
       </template>
       <template v-if="deviceType=== 'waterQuality'">
-<!--        <card01 style="height: 33%" title="设备维护情况">-->
-<!--          <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>-->
-<!--        </card01>-->
+        <!--        <card01 style="height: 33%" title="设备维护情况">-->
+        <!--          <stripe-table :columns="deviceStatusColumns" :data="deviceStatusData"></stripe-table>-->
+        <!--        </card01>-->
         <card01 style="height: 33%" title="配件运维信息">
           <stripe-table :columns="accessoriesColumns" :data="accessoriesData"></stripe-table>
         </card01>

+ 50 - 22
src/views/IntellOper.vue

@@ -1,18 +1,23 @@
 <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, getEquipmentData, getOperationsPersonnelData } from '@/api/device'
+import {
+  getDeviceInfo,
+  getEquipmentData,
+  getHistoryStationFailureCount,
+  getMaintenanceStatistics,
+  getOperationsPersonnelData
+} from '@/api/device'
 import Chart from '@/components/Chart.vue'
-import { getPie3DSimple } from '@/utils/chart'
-import { View } from '@/utils/tdInstruction'
+import {getPie3DSimple} from '@/utils/chart'
+import {Operate, View} from '@/utils/tdInstruction'
 import StationRightButtonGroup from '@/components/StationRightButtonGroup.vue'
-import { getDeviceByName } from '@/utils/device'
-import { getAlarmInfo } from '@/api/alarm'
-import { getMaintenanceStatistics, getHistoryStationFailureCount } from '@/api/device'
+import {getDeviceByName} from '@/utils/device'
+import {getAlarmInfo} from '@/api/alarm'
 import moment from 'moment'
 
 const route = useRoute()
@@ -27,15 +32,15 @@ const equipmentStatusData = reactive({
   '临近质保期': 0
 })
 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([])
 
@@ -50,7 +55,17 @@ const alarmType = ref({
 const alarmColumns = [
   {
     label: '报警类型', prop: 'warnType', width: '80', convertFn: (data) => {
-      return data ? alarmType.value[data.trim()] : ''
+      switch (data) {
+        case '1':
+          return '故障'
+        case '2':
+          return '提醒'
+        case '3':
+          return '巡检'
+        case '4':
+          return '定期巡检'
+      }
+      return ''
     }
   },
   {
@@ -65,7 +80,7 @@ const alarmColumns = [
   },
   {
     label: '告警内容', prop: 'warnContent', convertFn: (data) => {
-      return data ? data.trim() : ''
+      return data ? alarmType.value[data.trim()] : ''
     }
   }
 ]
@@ -206,19 +221,32 @@ function reloadRight3() {
 function getDeviceInfoList() {
   getDeviceInfo().then(res => {
     deviceData.push(...res)
+    deviceData.forEach(device => {
+      const deviceInfo = getDeviceByName(device.deviceName, "deviceName")
+      if (deviceInfo) {
+        switch (device.state) {
+          case "正常":
+            Operate.setPointState(route.params.stcd, deviceInfo.ueDeviceName, '蓝')
+            break
+          case "异常":
+            Operate.setPointState(route.params.stcd, deviceInfo.ueDeviceName, '红')
+            break
+        }
+      }
+    })
   })
 }
 
 function getEquipmentList() {
-  var data={
-    "page":1,
-    "pageSize":1000,
-    "stationCode":route.params.stcd
+  var data = {
+    "page": 1,
+    "pageSize": 1000,
+    "stationCode": route.params.stcd
   }
   getEquipmentData(data).then(res => {
     if (res.status == 200) {
       equipmentStatusData.total = res.data.records.length
-      var num=0
+      var num = 0
       res.data.records.forEach(d => {
         if (d.status != 1) {
           num++
@@ -272,7 +300,7 @@ function handleDeviceClick(row) {
           <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;" />
+              <img :src="imgSrc" style="height: 120px;"/>
             </div>
           </el-col>
           <el-col :span="7">

+ 24 - 14
src/views/Station.vue

@@ -14,7 +14,7 @@ import TimeScrollbar from "@/components/TimeScrollbar.vue";
 import {Label, Operate, Setting, View} from "@/utils/tdInstruction";
 import {getRainfallLatest, getWaterLevelAndFlowLatest} from "@/api/gx";
 import {getRainfallLevel} from "@/utils/rainfall";
-import bus from "@/utils/bus";
+import Bus from "@/utils/bus";
 
 const route = useRoute()
 const stationStore = useStationStore()
@@ -40,22 +40,32 @@ const handleEventChange = async (name: string) => {
   event.value = typicalEvents.value.find(t => t.name === name)
   eventData.value = await getTypicalData(route.params.stcd, event.value.id)
   max.value = eventData.value ? eventData.value.length : 100
+  const split = (max.value / 12).toFixed(0)
+  marks.value = eventData.value.reduce((acc, cur, index) => {
+    if (index % split === 0) {
+      acc[index] = cur.tm.substring(11) + "\n" + cur.tm.substring(5, 10)
+    }
+    return acc
+  }, {})
 }
 
 function sliderlTooltip(val) {
+  Bus.emit("TypicalChartMarkLineChange", val)
   if (eventData.value && eventData.value.length > 0) {
     const data = eventData.value[val]
-    Operate.setWaterLevel(route.params.stcd, data.z, (data.q * 4).toFixed(2))
-    let weather = "晴"
-    if (data.z >= 3.6) {
-      weather = "大雨"
-    } else if (data.z >= 3.4) {
-      weather = "中雨"
-    } else if (data.z >= 3.3) {
-      weather = "小雨"
+    if (data){
+      Operate.setWaterLevel(route.params.stcd, data.z, (data.q * 4).toFixed(2))
+      let weather = "晴"
+      if (data.z >= 3.6) {
+        weather = "大雨"
+      } else if (data.z >= 3.4) {
+        weather = "中雨"
+      } else if (data.z >= 3.3) {
+        weather = "小雨"
+      }
+      Setting.setWeather(weather)
+      return `${data.tm}\n 水位: ${data.z}m\n 流量: ${data.q}m³/s\n 平均流速: ${data.smv}m³/s\n`
     }
-    Setting.setWeather(weather)
-    return `${data.tm}\n 水位: ${data.z}m\n 流量: ${data.q}m³/s\n 平均流速: ${data.smv}m³/s\n`
   }
   return ''
 }
@@ -98,7 +108,7 @@ onMounted(() => {
   handleSetLED()
 })
 
-bus.on("roam", roaming => {
+Bus.on("roam", roaming => {
   typicalEventTimeScrollbarShow.value = !roaming
 })
 </script>
@@ -113,7 +123,7 @@ bus.on("roam", roaming => {
         </card01>
         <card01 style="height: 30%" title="现场监控">
           <!--  34102206531322000100 这是有视频的CODE  -->
-          <gw-video :imageSrc="jiankong" :code="videoCode"></gw-video>
+          <gw-video :code="videoCode" :imageSrc="jiankong"></gw-video>
         </card01>
       </template>
       <template #rightModule>
@@ -142,7 +152,7 @@ bus.on("roam", roaming => {
       </template>
     </right-frame>
     <div v-if="typicalEventTimeScrollbarShow" class="typical-event-time-scrollbar">
-      <time-scrollbar :formatTooltip="sliderlTooltip" :marks="marks" :max="max"
+      <time-scrollbar :formatTooltip="sliderlTooltip" :marks="marks" :max="max" :step="144"
                       @change="handleTimeChange"></time-scrollbar>
     </div>
   </div>

+ 89 - 26
src/views/StationHouse.vue

@@ -7,7 +7,6 @@ import stop from '@/assets/svg/stop2.svg'
 import RightFrame from '@/components/RightFrame.vue'
 import Card01 from '@/components/card/Card01.vue'
 import Chart from '@/components/Chart.vue'
-import {getWaterQualityLatest} from '@/api/gx'
 import StripeTable from '@/components/StripeTable.vue'
 import {getAlarmInfo} from '@/api/alarm.ts'
 import StationRightButtonGroup from "@/components/StationRightButtonGroup.vue";
@@ -15,10 +14,12 @@ import GwVideo from "@/components/Video/index.vue";
 import {getVideoCodeByMark} from "@/components/Video/video";
 import {Operate} from "@/utils/tdInstruction";
 import {getDeviceByType} from "@/utils/device";
-import {getDeviceStatus} from "@/api/nanshui";
+import {getDeviceStatus, getTaskRead, getWaterQualityData, runTest, setTaskRead} from "@/api/nanshui";
 import {HexToRgb} from "@/utils/color";
 import bus from "@/utils/bus";
 import DataTag from "@/components/tag/DataTag.vue";
+import {ElMessage, ElMessageBox} from "element-plus";
+import {VideoPlay} from "@element-plus/icons-vue";
 
 const route = useRoute()
 const videoSrc = ref(new URL('@/assets/images/video.png', import.meta.url).href)
@@ -39,9 +40,9 @@ const RGB_RED = HexToRgb(RED)
 // 浅红色
 const LIGHT_RED = `rgba(${RGB_RED[0]}, ${RGB_RED[1]}, ${RGB_RED[2]}, 0.3)`
 
-const frequency = ref([2, 8])
+const frequency = ref([])
 
-const wqData = ref({d1: '6', d2: '22.3', d3: '5', d4: '20', d5: '6', d6: '22.3', d7: '5', d8: '20'})
+const wqData = ref({})
 // 设备列表
 const deviceList = reactive(getDeviceByType('水质测验设备').filter(d => d.deviceName !== '控制单元'))
 // 水质测验模拟 0:结束 1:播放 2:暂停
@@ -97,17 +98,14 @@ function deviceStatus() {
  * 获取最新水质数据
  */
 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
+  getWaterQualityData(route.params.stcd).then(res => {
+    if (res.data.wqdata && res.data.wqdata.wq && Object.keys(res.data.wqdata.wq).length > 0) {
+      res.data.wqdata.wq['tm'] = res.data.wqdata.tm
+      const data = Object.keys(res.data.wqdata.wq).reduce((acc, key) => {
+        acc[key.toLowerCase()] = res.data.wqdata.wq[key];
+        return acc;
+      }, {});
+      wqData.value = data
     }
   })
 }
@@ -123,7 +121,17 @@ const alarmType = ref({
 const alarmColumns = [
   {
     label: '报警类型', prop: 'warnType', width: '100', convertFn: (data) => {
-      return data ? alarmType.value[data.trim()] : ''
+      switch (data) {
+        case '1':
+          return '故障'
+        case '2':
+          return '提醒'
+        case '3':
+          return '巡检'
+        case '4':
+          return '定期巡检'
+      }
+      return ''
     }
   },
   {
@@ -133,7 +141,7 @@ const alarmColumns = [
   },
   {
     label: '告警内容', prop: 'warnContent', width: '180', convertFn: (data) => {
-      return data ? data.trim() : ''
+      return data ? alarmType.value[Number(data)] : ''
     }
   },
 ]
@@ -150,7 +158,6 @@ function getAlarmList() {
     if (res.status == 200) {
       alarmData.push(...res.data.records)
     }
-    // initPoints()
   })
 }
 
@@ -235,10 +242,53 @@ async function reloadLeft1() {
   left1Ref.value.loadChart(option)
 }
 
+function getFrequency() {
+  getTaskRead(route.params.stcd).then(res => {
+    frequency.value = res.data.hour.split(',')
+  })
+}
+
+function handleFrequencyChange(value) {
+  ElMessageBox.confirm('是否要修改监测频率?', '修改检测频率',
+    {
+      confirmButtonText: '确认',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(() => setTaskRead(route.params.stcd, value))
+    .then(() => {
+      ElMessage({type: 'success', message: '检测频率修改成功'})
+    })
+    .catch(() => {
+      ElMessage({type: 'info', message: '检测频率修改失败',})
+    })
+}
+
+function handleRunTest() {
+  ElMessageBox.confirm('是否要运行水质测验?水质测验需要2小时.', '执行水质测验',
+    {
+      confirmButtonText: '确认',
+      cancelButtonText: '取消',
+      type: 'warning',
+    }
+  )
+    .then(() => runTest(route.params.stcd))
+    .then(() => {
+      ElMessage({type: 'success', message: '运行水质测验成功'})
+    })
+    .catch(() => {
+      ElMessage({type: 'info', message: '运行水质测验失败',})
+    })
+}
+
+
 onMounted(() => {
   reloadLeft1()
   getAlarmList()
   deviceStatus()
+  getFrequency()
+  getLatestWaterQuality()
 })
 
 onUnmounted(() => {
@@ -285,13 +335,20 @@ bus.on('test_simulation', (data) => {
       <card01 style="height: 65%" title="监测流程">
         <el-form label-width="auto">
           <el-form-item label="检测频率">
-            <el-select v-model="frequency" multiple placeholder="Select" style="width: 240px">
-              <el-option v-for="item in 24" :key="item" :label="item + '时'" :value="item"></el-option>
-              <template #tag>
-                <el-tag v-for="color in frequency" :key="color" color="#4167F0" style="color: #fff;">{{ color + '时' }}
-                </el-tag>
-              </template>
-            </el-select>
+            <div style="width: 100%;display: flex;align-items: center;justify-content: space-between;">
+              <el-select v-model="frequency" multiple placeholder="Select" style="width: 200px"
+                         @blur="handleFrequencyChange">
+                <el-option v-for="item in 24" :key="item" :label="item + '时'" :value="item"></el-option>
+                <template #tag>
+                  <el-tag v-for="color in frequency" :key="color" color="#4167F0" style="color: #fff;">
+                    {{ color + '时' }}
+                  </el-tag>
+                </template>
+              </el-select>
+              <el-button :icon="VideoPlay" style="margin-left: 10px;width: 6rem;" type="primary" @click="handleRunTest">
+                水质测验
+              </el-button>
+            </div>
           </el-form-item>
         </el-form>
         <div :style="{ 'background-image': `url(${simulateSrc})`}" class="video-control-bar test-simulation">
@@ -302,7 +359,13 @@ bus.on('test_simulation', (data) => {
           <icon v-if="testSimulationStatus != 0" :data="stop" class="video-btn" @click="handleTestSimulation('stop')"/>
         </div>
         <div>
-          <h3>测验结果:</h3>
+          <h3 style="display: flex;align-items: center;justify-content: space-between;">
+            测验结果:
+            <span style="font-size: 1rem;display: flex;align-items: center;">
+              <Timer style="width: 1em; height: 1em; margin-right: 8px"/>
+              {{ wqData.tm }}
+            </span>
+          </h3>
           <DataTag :data="wqData"></DataTag>
         </div>
       </card01>

+ 2 - 2
vite.config.ts

@@ -38,7 +38,7 @@ export default defineConfig({
         changeOrigin: true,
         rewrite: path => path.replace(/^\/szybh_api/, '')
       },
-      '/lantai': {
+      '/lantai_api': {
         // 共享平台
         target: 'http://10.8.48.235:9139/sunnyDevOps/',
         changeOrigin: true,
@@ -52,7 +52,7 @@ export default defineConfig({
       },
       '/video_api': {
         // 地听视频
-        target: 'http://10.8.48.234:8081/',
+        target: 'http://10.8.4.147:8090/',
         changeOrigin: true,
         rewrite: path => path.replace(/^\/video_api/, '')
       },

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels