123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- <script lang="ts" setup>
- import {onMounted, onUnmounted, reactive, ref} from 'vue'
- import {useRoute} from 'vue-router'
- import play from '@/assets/svg/play2.svg'
- import pause from '@/assets/svg/pause2.svg'
- 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 StripeTable from '@/components/StripeTable.vue'
- import {getAlarmInfo} from '@/api/alarm.ts'
- import StationRightButtonGroup from "@/components/StationRightButtonGroup.vue";
- import GwVideo from "@/components/Video/index.vue";
- import {getVideoCodeByMark} from "@/components/Video/video";
- import {Operate} from "@/utils/tdInstruction";
- import {getWaterQualityData} from "@/api/nanshui";
- import {HexToRgb} from "@/utils/color";
- import bus from "@/utils/bus";
- import DataTag from "@/components/tag/DataTag.vue";
- import {Timer, VideoPlay} from '@element-plus/icons-vue'
- const route = useRoute()
- 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 GREEN = '#67C23A'
- const RGB_GREEN = HexToRgb(GREEN)
- // 浅绿色
- const LIGHT_GREEN = `rgba(${RGB_GREEN[0]}, ${RGB_GREEN[1]}, ${RGB_GREEN[2]}, 0.3)`
- // 红色
- const RED = '#F56C6C'
- 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 wqData = ref({})
- // 水质测验模拟 0:结束 1:播放 2:暂停
- const testSimulationStatus = ref(0)
- // 获取视频CODE
- const videoCode = ref(getVideoCodeByMark(route.params.stcd + '', "室内"))
- const alarmType = ref({
- '1': '巡检维护',
- '2': '故障',
- '3': '仪器校准',
- '4': '提醒'
- })
- const alarmColumns = [
- {
- label: '报警类型', prop: 'warnType', width: '100', convertFn: (data) => {
- return data ? alarmType.value[data.trim()] : ''
- }
- },
- {
- label: '时间', prop: 'reportTime', convertFn: (data) => {
- return data ? data.substring(5, 16) : ''
- }
- },
- {
- label: '告警内容', prop: 'warnContent', width: '180', convertFn: (data) => {
- return data ? data.trim() : ''
- }
- },
- ]
- const alarmData = reactive([])
- const left1Ref = ref(null)
- /**
- * 测验模拟
- * @param mode 播放、暂停、继续、结束
- */
- function handleTestSimulation(mode) {
- switch (mode) {
- case "play":
- if (testSimulationStatus.value === 0) {
- Operate.testSimulation(route.params.stcd, '播放')
- } else {
- Operate.testSimulation(route.params.stcd, '继续')
- }
- testSimulationStatus.value = 1
- break
- case "pause":
- Operate.testSimulation(route.params.stcd, '暂停')
- testSimulationStatus.value = 2
- break
- case "stop":
- Operate.testSimulation(route.params.stcd, '结束')
- testSimulationStatus.value = 0
- break
- default:
- }
- }
- /**
- * 获取最新水质数据
- */
- function getLatestWaterQuality() {
- getWaterQualityData(route.params.stcd).then(res => {
- if (res.data.wqdata && res.data.wqdata.length > 0) {
- wqData.value = Object.keys(res.data.wqdata).reduce((acc, key) => {
- acc[key.toLowerCase()] = res.data.wqdata[key];
- return acc;
- }, {});
- }
- })
- }
- function getAlarmList() {
- const data = {
- 'page': 1,
- 'pageSize': 200,
- 'stationCode': route.params.stcd
- };
- getAlarmInfo(data).then(res => {
- if (res.status == 200) {
- alarmData.push(...res.data.records)
- }
- })
- }
- async function reloadLeft1() {
- const colors = ['#5470C6', '#91CC75', '#EE6666'];
- const option = {
- // title: {
- // text: '环境温湿度',
- // textStyle: {
- // fontSize: 14,
- // color: '#fff',
- // },
- // left:'50'
- //
- // },
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['温度', '湿度'],
- textStyle: {
- fontSize: 12,
- color: '#fff'
- }
- },
- grid: {
- left: '5%',
- right: '4%',
- bottom: '1%',
- top: '20%',
- containLabel: true
- },
- xAxis: {
- type: 'category',
- boundaryGap: false,
- data: ['11::30', '11:35', '11:40', '11:45', '11:50', '11:55', '12:00', '12:05', '12:10', '12:15']
- },
- yAxis: [{
- type: 'value',
- name: ' %',
- position: 'right',
- alignTicks: true,
- axisLine: {
- show: true,
- lineStyle: {
- color: colors[0]
- }
- },
- axisLabel: {
- formatter: '{value} %'
- }
- }, {
- type: 'value',
- name: ' °C',
- position: 'left',
- alignTicks: true,
- axisLine: {
- show: true,
- lineStyle: {
- color: colors[1]
- }
- },
- axisLabel: {
- formatter: '{value} °C'
- }
- }],
- series: [
- {
- name: '温度',
- type: 'line',
- stack: 'Total',
- data: [20, 21, 25, 26, 32, 30, 26, 39, 29, 30]
- },
- {
- name: '湿度',
- type: 'line',
- stack: 'Total',
- data: [40, 45, 30, 31, 36, 33, 31, 50, 30, 20]
- }
- ]
- };
- left1Ref.value.loadChart(option)
- }
- onMounted(() => {
- reloadLeft1()
- getAlarmList()
- getLatestWaterQuality()
- })
- onUnmounted(() => {
- if (testSimulationStatus.value !== 0) {
- handleTestSimulation('stop')
- }
- })
- // 底板回调监听
- bus.on('test_simulation', (data) => {
- if (data.Category && data.Category === 'ClickMesh' && data.Data.Type === '动画结束') {
- // 动画结束,修改状态
- testSimulationStatus.value = 0
- }
- })
- </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="alarmColumns" :data="alarmData"></stripe-table>
- </card01>
- </template>
- <template #rightModule>
- <card01 style="height: 65%" title="监测流程">
- <el-form label-width="auto">
- <el-form-item label="检测频率">
- <div style="width: 100%;display: flex;align-items: center;justify-content: space-between;">
- <el-select v-model="frequency" multiple placeholder="Select" style="width: 200px">
- <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="">水质测验
- </el-button>
- </div>
- </el-form-item>
- </el-form>
- <div :style="{ 'background-image': `url(${simulateSrc})`}" class="video-control-bar test-simulation">
- <icon v-if="testSimulationStatus == 0 || testSimulationStatus == 2" :data="play" class="video-btn"
- @click="handleTestSimulation('play')"/>
- <icon v-if="testSimulationStatus == 1" :data="pause" class="video-btn"
- @click="handleTestSimulation('pause')"/>
- <icon v-if="testSimulationStatus != 0" :data="stop" class="video-btn" @click="handleTestSimulation('stop')"/>
- </div>
- <div>
- <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>
- <card01 style="height: 35%" title="站房监控">
- <gw-video :code="videoCode" :imageSrc="videoSrc"></gw-video>
- </card01>
- </template>
- <template #btnGroup>
- <station-right-button-group></station-right-button-group>
- </template>
- </right-frame>
- </template>
- <style lang="scss" scoped>
- @use "@/assets/styles/introduce.scss";
- @use "@/assets/styles/video.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%;
- }
- .test-simulation {
- background-size: 100% 100%;
- height: 76px;
- margin-bottom: 18px;
- }
- </style>
|