Newer
Older
safe_production_front / src / views / ycjg / sjtj / statistics.vue
wangxitong on 16 Aug 9 KB first commit
<script lang="ts" setup name="Statistics" xmlns="">
import { getCurrentInstance, ref } from 'vue'
import type { Ref } from 'vue'
import type { DateModelType } from 'element-plus'
import type { DateReturn, ITableData, TypeReturn } from './statistics-interface'
import LineChart from '@/components/Echart/LineChart.vue'
import BarChartHorizontal from '@/components/Echart/BarChartHorizontal.vue'
import type { lineDataI } from '@/components/Echart/echart-interface'
import { areaDev, areaDevOnline, dayDev, getTotal } from '@/api/ycjg/statistics'
import PieChart from '@/components/Echart/PieChart.vue';
import sbzxs from '@/assets/images/ycjg/设备在线数.png'
import sbzs from '@/assets/images/ycjg/设备总数.png'
import sblxl from '@/assets/images/ycjg/设备离线率.png'
import BarChartVertical from "@/components/Echart/BarChartVertical.vue";

// 每个展示块高度
const blockHeight = ref(300)
const blockWidth = ref(400)

const onlineBarLoading = ref(false)
const devBarLoading = ref(false)
const areaPieLoading = ref(false)
const onlineLineLoading = ref(false)
const list = ref({
  devTotal: '****',
  onlineNum: '****',
  onlineRate: '****',
})
const showType = ref('柱状图')

const timeRange = ref<[DateModelType, DateModelType]>(['', ''])

// 默认查询条件
const defaultQuery = {
  stationId: '',
  monitorId: '',
  startTime: '',
  endTime: '',
}
const listQuery = reactive({ ...defaultQuery })
const stationList: Ref<any[]> = ref([])
const monitorList: Ref<any[]> = ref([])

const devTableData = ref<ITableData[]>([])
// 设备台账检定提醒表头
const devTableHead = [
  { text: '场站名称', value: 'stationName', width: '180' },
  { text: '云台数量', value: 'total' },
  { text: '在线', value: 'online' },
  { text: '离线', value: 'offline' },
]

const total = ref(20)

const devBarXData: Ref<string[]> = ref([])
const onlineBarXData: Ref<string[]> = ref([])
const devBarData: Ref<lineDataI[]> = ref([])
const onlineBarData: Ref<lineDataI[]> = ref([])
const devBarYDataMax = ref()
const onlineBarYDataMax = ref()

const onlineLineDateXData: Ref<string[]> = ref([])
const onlineLineDateData: Ref<lineDataI[]> = ref([])
const alarmDateYDataMax = ref()

const alarmTypeXData: Ref<string[]> = ref([])
const alarmTypeData: Ref<lineDataI[]> = ref([])
const alarmTypeYDataMax = ref()
const areaPieData: Ref<any[]> = ref([])

function getDevData() {
  devBarLoading.value = true
  areaPieLoading.value = true
  areaDev().then((res) => {
    const value = res.data.map((item: any) => Number(item.value))
    devBarData.value = [{ name: '设备数量', data: value }]
    devBarYDataMax.value = Math.max(value) > 10 ? Math.max(value) : 10
    devBarXData.value = res.data.map((item: any) => item.areaName)
    areaPieData.value = res.data.map((item: any) => {
      return {
        name: item.areaName,
        value: Number(item.value),
      }
    })
    devBarLoading.value = false
    areaPieLoading.value = false
  })
}

function getAreaDevOnline() {
  onlineBarLoading.value = true
  areaDevOnline().then((res) => {
    const value = res.data.map((item: any) => Number(item.value))
    onlineBarData.value = [{ name: '设备在线数量', data: value }]
    onlineBarYDataMax.value = Math.max(value) > 10 ? Math.max(value) : 10
    onlineBarXData.value = res.data.map((item: any) => item.areaName)
    onlineBarLoading.value = false
  })
}

function getDayDev() {
  onlineLineLoading.value = true
  dayDev().then((res) => {
    const onlineValue = res.data.map((item: any) => Number(item.online))
    const offlineValue = res.data.map((item: any) => Number(item.offline))
    onlineLineDateXData.value = res.data.map((item: any) => item.date)
    onlineLineDateData.value = [{ name: '离线设备', data: offlineValue }, { name: '在线设备', data: onlineValue }]
    onlineLineLoading.value = false
  })
}

function calcBlockSize() {
  // 计算工作台区域高度 - 顶部-面包屑-边距
  const bodyHeight = document.body.clientHeight - 60 - 50 - 20
  blockHeight.value = (bodyHeight - 100) / 2
  blockWidth.value = (document.body.clientWidth - 180 - 20 - 20)
}

window.addEventListener('resize', () => {
  calcBlockSize()
})

onBeforeMount(() => {
  calcBlockSize()
})
onMounted(() => {
  getTotal().then((res) => {
    if (res.code === 200) {
      list.value = res.data
      if (list.value.onlineNum === '' || list.value.onlineNum === null || list.value.onlineNum === undefined) {
        list.value.onlineNum = '0'
      }
      // list.value.rate = (Number(list.value.onlineNum) / Number(list.value.devTotal) * 100).toFixed(2)
      // if (Number.isNaN(list.value.rate)) {
      //   list.value.rate = '****'
      // }
    }
  })
  getDevData()
  getAreaDevOnline()
  getDayDev()
})
</script>

<template>
  <app-container style="background-color: white;overflow: hidden">
    <div style="display: flex;height: 90px;text-align: center;width: 100%;justify-content: space-evenly">
      <div class="item">
        <el-image :src="sbzs" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">设备总数</div>
          <div class="num">{{ list.devTotal }}<span class="unit">台</span></div>
        </div>
      </div>
      <div class="item">
        <el-image :src="sbzxs" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">设备在线数</div>
          <div class="num">{{ list.onlineNum }}<span class="unit">台</span></div>
        </div>
      </div>
      <div class="item">
        <el-image :src="sblxl" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">设备在线率</div>
          <div class="num">{{ list.onlineRate }}<span class="unit">%</span></div>
        </div>
      </div>
    </div>
    <div class="device-bench">
      <el-row :gutter="10">
        <el-col :span="8">
          <bench-col v-loading="devBarLoading" icon="icon-bar" title="各地区设备数量" :height="blockHeight">
            <bar-chart-vertical
              style="margin-top: -20px"
              unit="台"
              title="各地区设备数量"
              :x-axis-data="devBarXData"
              :width="`${blockWidth / 3 - 10}px`"
              :height="`${blockHeight - 30}px`"
              :data="devBarData"
              :max="devBarYDataMax"
            />
          </bench-col>
        </el-col>
        <el-col :span="8">
          <bench-col v-loading="onlineBarLoading" icon="icon-bar" title="各地区设备在线情况" :height="blockHeight">
            <bar-chart-horizontal
              style="margin-top: -20px"
              unit="台"
              title="各地区设备在线情况"
              :x-axis-data="onlineBarXData"
              :width="`${blockWidth / 3 - 10}px`"
              :height="`${blockHeight - 30}px`"
              :data="onlineBarData"
              :max="onlineBarYDataMax"
            />
          </bench-col>
        </el-col>
        <el-col :span="8">
          <bench-col
            v-loading="areaPieLoading" icon="icon-pie" title="设备区域分布情况" :height="blockHeight">
            <pie-chart
              title="设备区域分布情况"
              style="margin-top: -20px;"
              unit="台"
              :data="areaPieData"
              :radius="['0%', '70%']"
              :width="`${blockWidth / 3 - 10}px`"
              :height="`${blockHeight - 30}px`"
            />
          </bench-col>
        </el-col>
      </el-row>
    </div>
    <div class="device-bench" style="margin-top: 10px;">
      <el-row :gutter="10">
        <el-col :span="24">
          <bench-col v-loading="onlineLineLoading" icon="icon-line" title="设备在线趋势" :height="blockHeight">
            <line-chart
              :x-axis-data="onlineLineDateXData"
              :width="`${blockWidth - 10}px`"
              :data="onlineLineDateData"
              unit="台"
            />
          </bench-col>
        </el-col>
      </el-row>
    </div>
  </app-container>
</template>

<style lang="scss" scoped>
.device-bench {
  width: 100%;
  height: 100%;
  box-sizing: border-box;

  .the-month-total-Data {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    padding: 0 20px;

    .title {
      display: flex;
      justify-content: space-between;
      font-weight: 500;
      margin-bottom: 3px;
    }

    .content {
      width: 100%;

      .item {
        display: flex;
        flex-direction: column;
        flex: 1;
        margin-right: 10px;
        padding: 3px 0;
        justify-content: center;
        align-items: center;
        background-image: linear-gradient(to bottom, #e9f5ff, #3d7eff);
        border-radius: 8px;

        &:last-child {
          margin-right: 0;
        }
      }
    }
  }

  .my-equipment {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    padding: 20px;

    .item {
      height: 40%;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      background-image: linear-gradient(to right, #caddff, #3d7eff);
      border-radius: 16px;
    }
  }
}
</style>

<style lang="scss">
.bench-table {
  .el-table__header-wrapper {
    border-radius: 8px;
  }
}

.bench-table-header {
  th {
    font-weight: normal;
    font-size: 14px;
  }
}

.bench-table-row {
  border-radius: 8px;
}
.item{
  background-color: #e7f1fd;
  width: 300px;
  display: flex;
  justify-content: left;
  align-items: center;
  height: 80px;
  border-radius: 10px;
  border: 2px solid #398bff;
}
.num{
  text-shadow: 0 0 5px #0f67e7;
  color: #0f67e7;
  font-size: 30px;
  padding-top: 2px;
  font-weight: bold;
}
.unit{
  color: #0f67e7;
  font-size: 14px;
  margin-left: 3px;
}
.item-text{
  text-shadow: 0 0 2px #0f67e7;
  flex: 1;
  text-align: center;
  font-size: 18px;
}
.base-map-image{
  width: 60px;
  height: 60px;
  margin-left: 20px;
}
</style>