Newer
Older
HuangJiPC / src / pages / views / alarmWarning / realTimeMonitoring.vue
@zhangdeliang zhangdeliang on 21 Jun 17 KB update
<template>
  <div class="realTimeMonitoring">
    <div class="monitorLeft">
      <n-space>
        <n-select v-model:value="selectedValue" filterable placeholder="选择站点类型" :options="options" style="width: 310px" />
        <n-input v-model:value="searchValue1" clearable placeholder="请输入站点名称/站点编号" style="width: 210px" />
        <n-button type="primary" @click="handleClick('search1')">
          <template #icon>
            <n-icon><Search /></n-icon>
          </template>
          搜索
        </n-button>
      </n-space>
      <ul class="monitorList">
        <li v-for="(item, i) in monitorList" :key="i" @click="getRight(item, i)" :class="{ monitorLiactive: ListIndex == i }">
          <div class="inner">
            <div class="text">
              <h4>{{ item.stName }}</h4>
              <span>站点编号:{{ item.stCode }}</span>
              <span>观测时间:{{ item.ttTime }}</span>
              <span>上传时间:{{ item.utTime }}</span>
            </div>
            <div class="btn" :class="[item.status == 0 ? 'green' : item.status == 1 ? 'grey' : item.status == 2 ? 'yellow' : '']">
              {{ item.status == 0 ? '在线' : item.status == 1 ? '离线' : item.status == 2 ? '异常' : '低电压' }}
            </div>
          </div>

          <div class="hover">
            <span>编号:{{ item.stCode }}</span>
            <span>名称:{{ item.stName }}</span>
          </div>
        </li>
      </ul>
    </div>
    <div class="monitorRight">
      <div class="table">
        <n-data-table
          ref="tableRef"
          :bordered="false"
          :loading="tableLoading1"
          :max-height="700"
          :scroll-x="columns1.length * 180"
          striped
          :columns="columns1"
          :data="data1"
        >
        </n-data-table>
      </div>

      <div class="search">
        <n-space>
          <span style="position: relative; top: 8px">日期选择:</span>
          <n-date-picker v-model:value="timeRange" type="daterange" />
          <n-button type="primary" @click="handleClick('search')">
            <template #icon>
              <n-icon><Search /></n-icon>
            </template>
            搜索
          </n-button>
          <n-button type="primary" @click="handleClick('downLoad')">
            <template #icon>
              <n-icon><ArrowDown /></n-icon>
            </template>
            导出
          </n-button>
        </n-space>
      </div>
      <div class="tab">
        <n-tabs type="line" v-model:value="value" @update:value="changeTabs">
          <n-tab-pane v-for="panel in panels" :key="panel" :name="panel">
            <div class="tableBox" v-if="value == '表格展示'">
              <n-data-table
                ref="tableRef"
                :bordered="false"
                :loading="tableLoading2"
                :max-height="500"
                :scroll-x="columns1.length * 180"
                striped
                :columns="columns1"
                :data="data2"
                :remote="true"
                :pagination="pagination"
              >
              </n-data-table>
            </div>
            <div class="chartBox" v-if="value == '图形展示'">
              <n-space>
                <span>上因子:</span>
                <n-select
                  v-model:value="searchValue2"
                  filterable
                  clearable
                  :options="optionsTop"
                  placeholder="请选择上因子"
                  @update:value="handleChange"
                />
                <span>下因子:</span>
                <n-select
                  v-model:value="searchValue3"
                  filterable
                  clearable
                  :options="optionsTop"
                  placeholder="请选择下因子"
                  @update:value="handleChange"
                />
              </n-space>
              <div class="chart">
                <LineChart :data="chartData" :refresh="refresh" />
              </div>
            </div>
            <ul class="statistics" v-if="value == '数据统计'">
              <n-button type="primary" @click="handleClick('downLoadStatistics')">
                <template #icon>
                  <n-icon><ArrowDown /></n-icon>
                </template>
                导出
              </n-button>
              <div class="head">
                <span>站点编号</span>
                <span>统计开始时间</span>
                <span>统计结束时间</span>
                <span>监测因子</span>
                <span>区间最大值</span>
                <span>区间最小值</span>
                <span>区间平均值</span>
                <span>区间累计值</span>
                <span>累计值</span>
              </div>
              <li v-for="(item, i) in statisticsList" :key="i">
                <span>{{ item.stCode }}</span>
                <span>{{ item.startTime }}</span>
                <span>{{ item.endTime }}</span>
                <span>{{ item.codeProperty }}</span>
                <span>{{ item.maxValue ? item.maxValue : '-' }}</span>
                <span>{{ item.minValue ? item.minValue : '-' }}</span>
                <span>{{ item.averageValue ? item.averageValue : '-' }}</span>
                <span>{{ item.sectionCumulativeValue ? item.sectionCumulativeValue : '-' }}</span>
                <span>{{ item.cumulativeValue ? item.cumulativeValue : '-' }}</span>
              </li>
            </ul>
          </n-tab-pane>
        </n-tabs>
      </div>
    </div>
  </div>
</template>

<script>
import { ref, nextTick, onMounted, reactive, toRefs } from 'vue';
import { Search, ArrowDown } from '@vicons/ionicons5';
import { formatDate, downloadBlob } from '@/utils/util';
import LineChart from './conponents/LineChart.vue';
import { useMessage } from 'naive-ui';
import {
  selectSiteNoByGroupsNo,
  getSiteHeads,
  selectSiteSiteManBySerial,
  selectSiteSiteManHistoryData,
  selectSitePropertyList,
  siteDataEchat,
  selectStationData,
} from '@/services';
import axios from 'axios';
export default {
  name: 'realTimeMonitoring',
  components: {
    Search,
    ArrowDown,
    LineChart,
  },
  setup() {
    const message = useMessage();
    const valueRef = ref('表格展示');
    const panelsRef = ref(['表格展示', '图形展示', '数据统计']);
    const state = reactive({
      // 左侧
      searchValue1: '',
      selectedValue: '0',
      monitorList: [],
      ListIndex: 0,
      options: [
        {
          label: '全部',
          value: '0',
        },
        {
          label: '液位计',
          value: '1',
        },
        {
          label: '雨量计',
          value: '2',
        },
        {
          label: '流量计',
          value: '3',
        },
      ],
      // 右侧
      // 顶部表格
      columns1: [],
      data1: [],
      tableLoading1: true,
      tableLoading2: true,
      timeRange: [Date.now() - 24 * 30 * 60 * 60 * 1000, Date.now() + 24 * 60 * 60 * 1000],
      data2: [],
      //图标展示
      stCode: null,
      searchValue2: null,
      searchValue3: null,
      optionsTop: [],
      chartData: {
        xData: [
          '2022-04-06 12:00:00',
          '2022-04-06 13:00:00',
          '2022-04-06 15:00:00',
          '2022-04-06 16:00:00',
          '2022-04-06 17:00:00',
          '2022-04-06 18:00:00',
          '2022-04-06 19:00:00',
          '2022-04-06 20:00:00',
          '2022-04-06 21:15:00',
          '2022-04-06 22:00:00',
          '2022-04-06 23:00:00',
          '2022-04-07 00:00:00',
          '2022-04-07 01:00:00',
          '2022-04-07 02:00:00',
          '2022-04-07 03:00:00',
          '2022-04-07 04:00:00',
          '2022-04-07 05:00:00',
          '2022-04-07 06:00:00',
          '2022-04-07 07:00:00',
          '2022-04-07 08:00:00',
          '2022-04-07 09:00:00',
          '2022-04-07 10:00:00',
          '2022-04-07 11:00:00',
          '2022-04-07 12:00:00',
          '2022-04-07 13:00:00',
          '2022-04-07 17:00:00',
        ],
        info: [
          {
            y: [],
            color: 'red',
            name: '',
            yAxisIndex: 0,
            bgColor: [
              { offset: 0.1, color: 'transparent' },
              { offset: 1, color: 'transparent' },
            ],
          },
          {
            y: [],
            color: 'green',
            yAxisIndex: 1,
            name: '',
            bgColor: [
              { offset: 0.1, color: 'transparent' },
              { offset: 1, color: 'transparent' },
            ],
          },
        ],
        legendShow: true,
        yAxisShow: true,
        yLineShow: true,
        yAxisColor: ['rgba(97, 96, 96, .1)'],
        yName: '',
        yName2: '',
        smooth: false,
      },
      refresh: 1,
      statisticsList: [],
    });
    //分页
    const paginationReactive = reactive({
      page: 1,
      pageSize: 10,
      showSizePicker: true,
      pageSizes: [10, 20, 50],
      showQuickJumper: true,
      pageCount: 0,
      itemCount: 0,
      onChange: (page) => {
        paginationReactive.page = page;
        getRightTabList();
      },
      onPageSizeChange: (pageSize) => {
        paginationReactive.pageSize = pageSize;
        paginationReactive.page = 1;
        getRightTabList();
      },
    });
    // 获取左侧列表
    const getLeftList = async () => {
      let res = await selectSiteNoByGroupsNo(`?\siteName=${state.searchValue1}&stationType=${state.selectedValue}`);
      if (res) {
        state.monitorList = res.data;
        getRight(state.monitorList[0], 0);
      }
    };
    // 获取右侧内容
    const getRight = (item, i) => {
      state.ListIndex = i;
      state.stCode = item.stCode;
      getRightHead();
      getRightHeadList();
      getRightTabList();
      getYinzi(state.stCode);
    };
    // 获取右侧上方表头
    const getRightHead = async () => {
      let res = await getSiteHeads(`?stCode=${state.stCode}`);
      if (res && res.code == 200) {
        state.columns1 = res.data.map((v) => {
          return {
            title: v.title,
            key: v.field,
            align: v.align,
            width: '180',
          };
        });
      }
    };
    // 获取右侧上方表格数据
    const getRightHeadList = async () => {
      state.tableLoading1 = true;
      let res = await selectSiteSiteManBySerial(`?stCode=${state.stCode}`);
      state.data1 = [res];
      state.tableLoading1 = false;
    };
    // 获取tab表格数据
    const getRightTabList = async () => {
      state.tableLoading2 = true;
      let times = formatDate(state.timeRange[0]);
      let timee = formatDate(state.timeRange[1]);
      let res = await selectSiteSiteManHistoryData(
        `?dName=${state.stCode}&rows=${paginationReactive.pageSize}&page=${paginationReactive.page}&startTime=${times}&endTime=${timee}`
      );
      state.data2 = res.rows;
      paginationReactive.itemCount = res.total;
      paginationReactive.pageCount = res.total / paginationReactive.pageSize;
      state.tableLoading2 = false;
    };
    // 获取echarts图表数据
    const getSiteDataEchat = async () => {
      let times = formatDate(state.timeRange[0]);
      let timee = formatDate(state.timeRange[1]);
      let res = await siteDataEchat(
        `?dName=${state.stCode}&up=${state.searchValue2}&down=${state.searchValue3}&startTime=${times}&endTime=${timee}`
      );
      state.chartData.xData = res.tt;
      state.chartData.info[0].y = res.up;
      state.chartData.info[1].y = res.down;
      state.chartData.yName = state.searchValue2;
      state.chartData.yName2 = state.searchValue3;
      let arr1 = state.optionsTop.filter((item) => item.value == state.searchValue2);
      // legend赋值
      state.chartData.info[0].name = arr1[0].label + ' ';
      let arr2 = state.optionsTop.filter((item) => item.value == state.searchValue3);
      state.chartData.info[1].name = arr2[0].label;
      state.refresh = Math.random();
    };
    // 切换tab
    const changeTabs = (value) => {
      if (value == '图形展示') {
        getSiteDataEchat();
      } else if (value == '数据统计') {
        getSelectStationData();
      } else {
        getRightTabList();
      }
    };
    // 获取因子
    const getYinzi = async (stCode) => {
      let res = await selectSitePropertyList(`?siteNo=${stCode}`);
      state.optionsTop = res.map((item) => {
        return {
          label: item.codeProperty,
          value: item.codeAscii,
        };
      });
      state.searchValue2 = state.optionsTop[0].value;
      state.searchValue3 = state.optionsTop[1].value;
    };
    //数据统计数据
    const getSelectStationData = async () => {
      let times = formatDate(state.timeRange[0]);
      let timee = formatDate(state.timeRange[1]);
      let pramas = {
        endTime: timee,
        stCode: state.stCode,
        startTime: times,
      };
      let res = await selectStationData(pramas);
      if (res && res.code == 1) {
        state.statisticsList = res.data;
      }
    };
    const handleClick = (type) => {
      let times = formatDate(state.timeRange[0]);
      let timee = formatDate(state.timeRange[1]);
      let datas = {
        st: state.stCode,
        startTime: times,
        endTime: timee,
      };
      const token = localStorage.getItem('tokenXF');
      switch (type) {
        case 'search1':
          getLeftList();
          break;
        case 'search':
          changeTabs(valueRef.value);
          break;
        case 'downLoad':
          if (state.data2.length == 0) {
            message.error('表格数据为空,无法导出');
            return;
          }
          axios
            .get(`/api/dataReport/batchExportHistoryData`, {
              headers: {
                token: token,
              },
              responseType: 'blob',
              params: datas,
            })
            .then(function (res) {
              console.log(res, 'res');
              downloadBlob(res.data, decodeURIComponent(res.headers['content-disposition'].split('filename=')[1]));
            });
          break;
        case 'downLoadStatistics':
          if (state.statisticsList == null) {
            message.error('表格数据为空,无法导出');
            return;
          }
          axios
            .get(`/api/dataReport/batchExportHistoryData`, {
              headers: {
                token: token,
              },
              responseType: 'blob',
              params: datas,
            })
            .then(function (res) {
              console.log(res, 'res');
              downloadBlob(res.data, decodeURIComponent(res.headers['content-disposition'].split('filename=')[1]));
            });
          break;
      }
    };
    // 修改因子
    const handleChange = (value) => {
      changeTabs('图形展示');
    };
    onMounted(() => {
      nextTick(() => {
        getLeftList();
      });
    });
    return {
      value: valueRef,
      panels: panelsRef,
      ...toRefs(state),
      pagination: paginationReactive,
      getLeftList,
      getRight,
      getRightHead,
      getRightHeadList,
      getRightTabList,
      changeTabs,
      getYinzi,
      getSiteDataEchat,
      getSelectStationData,
      handleClick,
      handleChange,
    };
  },
};
</script>

<style lang="less" scoped>
.realTimeMonitoring {
  width: 100%;
  height: 100%;
  display: flex;
  .monitorLeft {
    margin-right: 10px;
    width: 310px;
    height: calc(100% - 10px);
    .monitorList {
      margin-top: 10px;
      height: calc(100% - 100px);
      overflow: auto;
      background: #012c3f;
      li {
        padding: 10px 20px;
        border-bottom: 1px solid #ccc;
        position: relative;
        cursor: pointer;
        .inner {
          display: flex;
          justify-content: space-between;
          align-items: center;
          cursor: pointer;
          .text {
            display: flex;
            flex-direction: column;
            h4 {
              font-weight: normal;
              line-height: 30px;
            }
            p {
              line-height: 26px;
            }
          }
          .btn {
            padding: 5px 9px;
            border-radius: 10px;
            background: #fd5151;
            &.grey {
              background: #03c2ec;
            }
            &.yellow {
              background: #f7b32e;
            }
            &.green {
              background: #9ad659;
            }
          }
        }
        .hover {
          position: absolute;
          top: 10px;
          left: 0;
          width: 100%;
          height: calc(100% - 20px);
          background: #041023;
          display: flex;
          flex-direction: column;
          justify-content: center;
          align-items: center;
          opacity: 0;
        }
        &:hover {
          .hover {
            opacity: 1;
          }
        }
      }

      .monitorLiactive {
        background: #034159;
      }
    }
  }
  .monitorRight {
    width: calc(100% - 320px);
    height: calc(100% - 10px);
    padding: 10px;
    .table {
      margin-bottom: 20px;
      width: 100%;
      overflow: auto;
    }
    .tab {
      margin-top: 10px;
    }
    .chart {
      width: 100%;
      height: 550px;
    }
    .statistics {
      width: 100%;
      height: 100%;
      .head {
        margin-top: 10px;
        display: flex;
        height: 40px;
        span {
          flex: 1;
          border: 1px solid;
          border-right: none;
          font-size: 16px;
          text-align: center;
          line-height: 40px;
          &:last-child {
            border: 1px solid;
          }
        }
      }
      li {
        display: flex;
        justify-content: center;
        align-items: center;
        span {
          flex: 1;
          height: 40px;
          border: 1px solid;
          border-right: none;
          border-top: none;
          text-align: center;
          line-height: 40px;
          &:last-child {
            border: 1px solid;
            border-top: none;
          }
        }
      }
    }
  }
}
</style>