Newer
Older
HuangJiPC / src / pages / views / WatershedOneMap / newPart / modal / shuizhiModal.vue
@zhangdeliang zhangdeliang on 21 Jun 13 KB update
<template>
  <!-- 水质监测站详情弹窗 -->
  <div class="shuizhiModals">
    <n-tabs type="line" @update:value="changeTab" animated>
      <n-tab-pane name="0" tab="监测详情">
        <div class="szjcz">
          <div class="contLeft">
            <div class="title">站点基本信息</div>
            <div class="part">
              <div class="detail" v-for="(val, keys, index) in detailName" :key="index">
                <p>{{ val }}</p>
                <p v-if="keys != 'status'">{{ detailVal[keys] }}</p>
                <p v-if="keys == 'status'">{{ detailVal[keys] == 0 ? '在线' : '离线' }}</p>
              </div>
            </div>
          </div>
          <div class="contRight">
            <div class="search">
              <n-date-picker v-model:value="dateRange" @update:value="getLineTableData" type="daterange" />
              <n-select :options="szOptions" v-model:value="yinziVal" placeholder="选择因子" @update:value="getLineTableData" />
            </div>
            <div id="echartYz"></div>
            <div class="table">
              <n-data-table
                :columns="columns"
                :data="tableData"
                :loading="tableLoading"
                :remote="true"
                :pagination="pagination"
                :bordered="false"
              />
            </div>
          </div>
        </div>
      </n-tab-pane>
      <n-tab-pane name="1" v-if="detailVal.videoPathList.length > 0" tab="视频监控">
        <div class="cameraBtn">
          <n-button type="primary" @click="changeTab(2, item.key)" v-for="(item, index) in detailVal.videoPathList" :key="'a' + index">
            {{ item.label }}
          </n-button>
        </div>
        <!-- 视频盒子 -->
        <div id="fxPlay" v-if="ifShowVideo" class="fxPlayBox"></div>
      </n-tab-pane>
    </n-tabs>
  </div>
</template>

<script>
import { ref, toRefs, onMounted, reactive, onBeforeUnmount, nextTick } from 'vue';
import * as echarts from 'echarts';
import { lyInfoStationDetail, lyInfoStationLine, lyInfoStationTable } from '@/services';
import { formatDate } from '@/utils/util';

export default {
  name: 'shuizhiModals',
  props: {
    stationCode: String,
  },
  setup(props, context) {
    console.log(props.stationCode);
    const allData = reactive({
      ifShowVideo: false,
      tableLoading: false,
      tableData: [],
      columns: [
        { key: 'ttTime', title: '时间' },
        { key: 'value', title: '观测值' },
        { key: 'waterLevelDesc', title: '水质评价' },
        { key: 'assessmentScope', title: '水质评价范围' },
        { key: 'alarmValue', title: '触发报警值' },
        { key: 'warningValue', title: '触发预警值' },
      ],
      dateRange: [Date.now() - 1 * 24 * 60 * 60 * 1000, Date.now()],
      yinziVal: 'codmn',
      szOptions: [
        { value: 'codmn', label: 'COD(mg/L)' },
        { value: 'ph', label: 'PH' },
        { value: 'do', label: 'DO(mg/L)' },
        { value: 'nh4n', label: 'NH3-N(mg/L)' },
        { value: 'tp', label: 'TP(mg/L)' },
      ],
      detailName: {
        stName: '站点名称',
        stCode: '站点编码',
        stationType: '站点类型',
        area: '河道名称',
        createTime: '安装时间',
        lon: '经度',
        lat: '纬度',
        platformName: '项目名称',
        person: '负责人',
        address: '安装地址',
        status: '站点状态',
      },
      detailVal: {
        videoPathList: [],
      },

      oWebControl: null,
      plugKey: '',
      Count: 0,
      width: 900,
      height: 480,
      showVideos: {
        cameraIndexCode: '4097ade6e64142d7ac7adff80b4617f0', // 监控点编号4097ade6e64142d7ac7adff80b4617f0
        streamMode: 0, // 主子码流标识:0-主码流,1-子码流
        transMode: 1, // 传输协议:0-UDP,1-TCP
        gpuMode: 0, // 是否启用GPU硬解,0-不启用,1-启用
        wndId: 1, // 播放窗口序号
      },
      szOption: {
        legend: {
          show: false,
        },
        grid: {
          left: '2%',
          right: '4%',
          bottom: '0%',
          top: '16%',
          containLabel: true,
        },
        tooltip: {
          trigger: 'axis',
        },
        xAxis: {
          type: 'category',
          data: ['06-01', '06-02', '06-03'],
          axisLabel: {
            textStyle: {
              color: '#B4C9E0',
            },
          },
          axisLine: {
            show: false,
          },
          splitLine: {
            show: false,
          },
          axisTick: {
            show: false,
          },
        },
        yAxis: {
          type: 'value',
          splitLine: {
            show: false,
          },
        },
        series: [
          {
            name: '水质值',
            areaStyle: { normal: {} },
            type: 'line',
            smooth: true,
            color: '#C72B31',
            data: [5, 7, 3],
          },
        ],
      },
    });
    //分页
    const paginationReactive = reactive({
      page: 1,
      pageSize: 4,
      showSizePicker: true,
      pageSizes: [4, 20, 50],
      showQuickJumper: true,
      pageCount: 0,
      itemCount: 0,
      pageSlot: 5,
      prefix: () => {
        return '共 ' + paginationReactive.itemCount + ' 项';
      },
      onChange: (page) => {
        paginationReactive.page = page;
        getTableData();
      },
      onPageSizeChange: (pageSize) => {
        paginationReactive.pageSize = pageSize;
        paginationReactive.page = 1;
        getTableData();
      },
    });
    // tab切换
    const changeTab = (val, code) => {
      if (val == 0) {
        nextTick(() => {
          getLineTableData();
        });
        allData.ifShowVideo = false;
        if (allData.oWebControl) {
          allData.oWebControl.JS_HideWnd();
          allData.oWebControl.JS_DestroyWnd();
          allData.oWebControl = null;
          allData.ifShowVideo = false;
        }
      } else {
        allData.ifShowVideo = true;
        let video = {
          cameraIndexCode: code ? code : allData.detailVal.videoPathList[0].key, // 监控点编号4097ade6e64142d7ac7adff80b4617f0
          streamMode: 0, // 主子码流标识:0-主码流,1-子码流
          transMode: 1, // 传输协议:0-UDP,1-TCP
          gpuMode: 0, // 是否启用GPU硬解,0-不启用,1-启用
          wndId: -1, // 播放窗口序号
        };
        allData.showVideos = video;
        if (allData.oWebControl == null) {
          initPlugin();
        } else {
          allData.oWebControl.JS_HideWnd();
          allData.oWebControl.JS_DestroyWnd();
          allData.oWebControl = null;
          initPlugin();
        }
      }
    };
    /* 创建插件实例 */
    function initPlugin() {
      const dll = { dllPath: './VideoPluginConnect.dll' };
      allData.oWebControl = new WebControl({
        szPluginContainer: 'fxPlay', // 指定容器id
        iServicePortStart: 15900,
        iServicePortEnd: 15909,
        szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
        cbConnectSuccess: () => {
          allData.oWebControl.JS_StartService('window', dll).then(() => {
            // 设置视频 web 插件消息回调
            allData.oWebControl.JS_SetWindowControlCallback({
              // cbIntegrationCallBack: msg => { }
            });
            // 启动插件服务成功
            allData.oWebControl.JS_CreateWnd('fxPlay', allData.width, allData.height).then(() => {
              // JS_CreateWnd创建视频播放窗口,宽高可设定
              initVideo(allData.oWebControl); // 创建播放实例成功后初始化
              console.log('启动插件成功!');
            });
          });
          allData.oWebControl.oDocOffset.top = 60;
        },
        // 插件服务启动失败,弹框提示
        cbConnectError: () => {
          allData.oWebControl = null;
          allData.Count++;
          if (allData.Count < 2) {
            WebControl.JS_WakeUp('VideoWebPlugin://');

            setTimeout(() => {
              initPlugin();
            }, 8000);
          } else {
          }
          console.log('创建插件失败');
        },
      });
    }
    /* 获取公钥 */
    function initVideo(oWebControl) {
      const params = {
        funcName: 'getRSAPubKey',
        argument: JSON.stringify({ keyLength: 1024 }),
      };

      oWebControl.JS_RequestInterface(params).then((res) => {
        if (res.responseMsg.data) {
          allData.plugKey = res.responseMsg.data;
          getVideoConfig(oWebControl);
        }
      });
    }
    /* 视频插件配置  插件初始化 */
    function getVideoConfig(oWebControl) {
      const configObj = {
        funcName: 'init',
        argument: JSON.stringify({
          appkey: '26265267', // API网关提供的appkey
          secret: setEncrypt('CHtVgUwdLsJjE6CWYLMy'), // API网关提供的secret
          ip: '192.168.10.49', // API网关IP地址z
          playMode: 0, // 播放模式 0-预览,1-回放
          port: 443, // 端口
          snapDir: 'D:\\SnapDir', // 抓图存储路径
          videoDir: 'D:\\VideoDir', // 紧急录像或录像剪辑存储路径
          layout: '1x1', // 布局
          enableHTTPS: 1, // 是否启用HTTPS协议 0https 1http
          encryptedFields: 'secret', // 加密字段
          showToolbar: 1, // 是否显示工具栏
          showSmart: 1, // 是否显示智能信息
          showToolbar: 0, //是否显示工具栏 0不显示   1显示
          // buttonIDs: "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769", // 自定义工具条按钮 新的
        }),
      };
      oWebControl.JS_RequestInterface(configObj).then(() => {
        oWebControl.JS_Resize(allData.width, allData.height);
        getClickAction();
      });
    }
    /* 视频流RSA加密 */
    function setEncrypt(value) {
      const encrypt = new JSEncrypt();
      encrypt.setPublicKey(allData.plugKey);
      return encrypt.encrypt(value);
    }
    /* 视频预览 */
    function getClickAction() {
      console.log(allData.showVideos, 'showVideos');
      allData.oWebControl.JS_RequestInterface({
        funcName: 'startPreview',
        argument: JSON.stringify(allData.showVideos),
      });
    }
    // 折线图加载
    let echartShuizhijc = null;
    const shuizhiEcharts = () => {
      echartShuizhijc = echarts.init(document.getElementById('echartYz'));
      echartShuizhijc.clear();
      echartShuizhijc.setOption(allData.szOption);
    };
    // 折线图表格数据加载
    async function getLineTableData() {
      let params = {
        stCode: props.stationCode,
        property: allData.yinziVal,
        startTime: formatDate(allData.dateRange[0]),
        endTime: formatDate(allData.dateRange[1]),
      };
      let res = await lyInfoStationLine(params);
      if (res && res.code == 1) {
        allData.szOption.xAxis.data = res.data.tt;
        allData.szOption.series[0].data = res.data.property;
        shuizhiEcharts();
      }
      getTableData();
    }
    async function getTableData() {
      let params = {
        current: paginationReactive.page,
        size: paginationReactive.pageSize,
        data: {
          stCode: props.stationCode,
          property: allData.yinziVal,
          startTime: formatDate(allData.dateRange[0]),
          endTime: formatDate(allData.dateRange[1]),
        },
      };
      let res = await lyInfoStationTable(params);
      if (res && res.code == 1) {
        allData.tableData = res.data.list;
        paginationReactive.pageCount = res.data.pages;
        paginationReactive.itemCount = res.data.total;
      }
    }
    // 加载基本信息数据
    const getBaseData = async () => {
      let params = {
        stCode: props.stationCode,
      };
      let res = await lyInfoStationDetail(params);
      if (res && res.code == 1) {
        let datas = res.data;
        allData.detailVal = datas;
      }
    };
    onMounted(() => {
      getLineTableData();
      getBaseData();
    });
    onBeforeUnmount(() => {
      if (allData.oWebControl != null) {
        allData.ifShowVideo = false;
        allData.oWebControl.JS_HideWnd();
        allData.oWebControl.JS_DestroyWnd();
        allData.oWebControl = null;
      }
      if (!!echartShuizhijc) echartShuizhijc.dispose();
    });
    return {
      ...toRefs(allData),
      pagination: paginationReactive,
      changeTab,
      getLineTableData,
    };
  },
};
</script>

<style lang="less">
.shuizhiModals {
  color: #b4c9e0;
  height: 575px;
  .title {
    font-size: 18px;
    font-weight: bold;
  }
  .szjcz {
    display: flex;
    margin: 10px 0px;
    .contLeft {
      width: 300px;
      .part {
        margin-top: 10px;
        .detail {
          width: 100%;
          display: flex;
          font-size: 14px;
          background: rgba(1, 27, 46, 0.6);
          p {
            height: 34px;
            line-height: 34px;
            width: 100%;
          }

          p:nth-of-type(1) {
            width: 35%;
            text-align: center;
          }
          p:nth-of-type(2) {
            flex: 1;
            text-align: left;
          }
        }
        .detail:nth-of-type(odd) {
          background: rgba(1, 27, 46, 0.3);
        }
      }
    }
    .contRight {
      flex: 1;
      padding-left: 20px;
      margin-left: 20px;
      border-left: 2px solid rgba(1, 27, 46, 0.5);
      .search {
        display: flex;
        .n-date-picker {
          width: 260px;
          margin: 0px 20px;
        }
        .n-select {
          width: 150px;
        }
      }
      #echartYz {
        margin-top: 10px;
        width: 580px;
        height: 200px;
      }
      .table {
        width: 100%;
        margin-top: 20px;
        max-height: 240px;
        overflow: auto;
        .n-data-table-td,
        .n-data-table-th {
          padding: 6px !important;
          text-align: center;
        }
      }
    }
  }
  .fxPlayBox {
    width: 900px;
    height: 480px;
    margin-top: 10px;
  }
  .cameraBtn {
    overflow: auto;
    height: 34px;
    .n-button {
      margin-right: 15px;
    }
  }
  .n-tabs-tab {
    font-size: 15px;
  }
}
</style>