Newer
Older
sensorHubPlusFront / src / views / dashboard / index.vue
<script lang="ts" setup name="Statistics">
import { getCurrentInstance, ref } from 'vue'
import type { Ref } from 'vue'
import { ElMessage, type DateModelType } from 'element-plus'
import groupPng from '@/assets/images/dashboard/group.png'
import devicePng from '@/assets/images/dashboard/device.png'
import productPng from '@/assets/images/dashboard/product.png'
import dataPng from '@/assets/images/dashboard/data.png'
import { getDictByCode } from '@/api/system/dict'
import { getGroupListPage } from '@/api/basic/group'
import { getDeviceListPage } from '@/api/basic/device'
const router = useRouter()

// 每个展示块高度
const blockHeight = ref(300)
// 上面概览数据
const overview = ref({
  groupCount: '****',
  deviceCount: '****',
  productCount: '****',
  dataCount: '****',
})

// ---------------------------------分组管理-----------------------------------------------
// 默认查询条件
const groupListQuery = ref({
  groupName: '', // 分组名
  beginTime: '', // 创建时间-起始
  endTime: '', // 创建时间-结束
  offset: 1,
  limit: 20,
})
const groupList: any = ref([])
const groupColumn: any = [
  { text: '分组名称', value: 'groupName', align: 'center'},
  { text: '分组内设备数量', value: 'deviceCount', align: 'center' },
  { text: '订阅数量', value: 'subscribeCount', align: 'center' },
]
const groupTotal = ref(0)
const groupLoadingTable = ref(false)

// 获取分组数据
function fetchGroupList(isNowPage = false) {
  groupLoadingTable.value = true
  if (!isNowPage) {
    // 是否显示当前页,否则跳转第一页
    groupListQuery.value.offset = 1
  }
  getGroupListPage(groupListQuery.value).then((response) => {
    if (response.code === 200) {
      groupList.value = response.data.rows
      groupTotal.value = parseInt(response.data.total)
      // overview.value.groupCount = groupTotal.value + ''
    }
    groupLoadingTable.value = false
  }).catch(() => {
    groupLoadingTable.value = false
  })
}
// ---------------------------------离线设备-----------------------------------------------
// 默认查询条件
const offlineListQuery = ref({
  groupId: '', // 分组
  productId: '',
  devcode: '',
  imei: '',
  deviceType: '',
  status: '',
  endCell: '',
  offset: 1,
  limit: 20,
})
const offlineList: any = ref([])
const offlineColumn: any = [
  { text: '分组名称', value: 'groupName', align: 'center'},
  { text: '设备编号', value: 'devcode', align: 'center' },
  { text: '最后上传时间', value: 'logtime', align: 'center' },
  { text: '无数据天数', value: 'count', align: 'center', width: '100' },
]
const offlineTotal = ref(0)
const offlineLoadingTable = ref(false)
// 获取离线设备
function fetchOfflineList(isNowPage = false) {
  offlineLoadingTable.value = true
  if (!isNowPage) {
    // 是否显示当前页,否则跳转第一页
    offlineListQuery.value.offset = 1
  }
  getDeviceListPage(offlineListQuery.value).then((response) => {
    if (response.code === 200) {
      offlineList.value = response.data.rows.map((item: any) => {
        return {
          ...item,
        }
      })
      offlineTotal.value = parseInt(response.data.total)
    }
    offlineLoadingTable.value = false
  }).catch(() => {
    offlineLoadingTable.value = false
  })
}
// ---------------------------------低电量设备-----------------------------------------------
// 默认查询条件
const lowBatteryListQuery = ref({
  groupId: '', // 分组
  productId: '',
  devcode: '',
  imei: '',
  deviceType: '',
  status: '',
  endCell: '10',
  beginCell: '0',
  offset: 1,
  limit: 20,
})
const lowBatteryList: any = ref([])
const lowBatteryColumn: any = [
  { text: '分组名称', value: 'groupName', align: 'center'},
  { text: '设备编号', value: 'devcode', align: 'center' },
  { text: '最后上传时间', value: 'logtime', align: 'center' },
  { text: '电量(%)', value: 'cell', align: 'center', width: '80', styleFilter: (row: any) => { return 'color: red' }  },
]
const lowBatteryTotal = ref(0)
const lowBatteryLoadingTable = ref(false)
// 获取低电量数据
function fetchLowBatteryList(isNowPage = false) {
  lowBatteryLoadingTable.value = true
  if (!isNowPage) {
    // 是否显示当前页,否则跳转第一页
    lowBatteryListQuery.value.offset = 1
  }
  getDeviceListPage(lowBatteryListQuery.value).then((response) => {
    if (response.code === 200) {
      lowBatteryList.value = response.data.rows.map((item: any) => {
        return {
          ...item,
        }
      })
      lowBatteryTotal.value = parseInt(response.data.total)
    }
    lowBatteryLoadingTable.value = false
  }).catch(() => {
    lowBatteryLoadingTable.value = false
  })
}
// ---------------------------------异常设备-----------------------------------------------
// 默认查询条件
const errorListQuery = ref({
  groupId: '', // 分组
  productId: '',
  devcode: '',
  imei: '',
  deviceType: '',
  status: '',
  endCell: '',
  offset: 1,
  limit: 20,
})
const errorList: any = ref([])
const errorColumn: any = [
  { text: '分组名称', value: 'groupName', align: 'center'},
  { text: '设备编号', value: 'devcode', align: 'center' },
  { text: '报警类型', value: 'count', align: 'center', width: '100' },
  { text: '报警时间', value: 'count', align: 'center' },
]
const errorTotal = ref(0)
const errorLoadingTable = ref(false)
// 获取异常设备
function fetchErrorList(isNowPage = false) {
  errorLoadingTable.value = true
  if (!isNowPage) {
    // 是否显示当前页,否则跳转第一页
    errorListQuery.value.offset = 1
  }
  getDeviceListPage(errorListQuery.value).then((response) => {
    if (response.code === 200) {
      errorList.value = response.data.rows.map((item: any) => {
        return {
          ...item,
        }
      })
      errorTotal.value = parseInt(response.data.total)
    }
    errorLoadingTable.value = false
  }).catch(() => {
    errorLoadingTable.value = false
  })
}
// ---------------------------------异常设备-----------------------------------------------

// 页数发生变化后的操作,可能是页码变化,可能是每页容量变化,此函数必写
const changePage = (val: { size?: number; page?: number }, type = '') => {
  switch(type) {
    case 'group':
      if (val && val.size) {
        groupListQuery.value.limit = val.size
      }
      if (val && val.page) {
        groupListQuery.value.offset = val.page
      }
      fetchGroupList(true)
      break;
    case 'offline':
      ElMessage.info('敬请期待')
      return
      if (val && val.size) {
        offlineListQuery.value.limit = val.size
      }
      if (val && val.page) {
        offlineListQuery.value.offset = val.page
      }
      fetchOfflineList(true)
      break;
    case 'lowBattery':
      if (val && val.size) {
        lowBatteryListQuery.value.limit = val.size
      }
      if (val && val.page) {
        lowBatteryListQuery.value.offset = val.page
      }
      fetchLowBatteryList(true)
      break;
    case 'error':
      ElMessage.info('敬请期待')
      return
      if (val && val.size) {
        errorListQuery.value.limit = val.size
      }
      if (val && val.page) {
        errorListQuery.value.offset = val.page
      }
      fetchErrorList(true)
      break;
  }

}
// 处理操作中的按钮
const handleOperateButton = (type = '', row: any) => {
  switch(type) {
    case 'group':
      router.push({
        query: {
          type: 'detail',
          // id: row.id,
          id: '1922544288985513986'
        },
        path: '/basic/group/detail',
      })
      break
      default: // 离线设备、低电量设备、异常设备
      router.push({
    query: {
      type: 'detail',
      id: row.id,
    },
    path: '/basic/device/detail?',
  })
      break
  }
}

// 点击标题跳转页面
const handleClickTitle = (title = '') => {
  console.log('点击的title', title);
  switch(title) {
    case '分组管理':
      router.push('/basic/group/list')
      break;
    case '低电量设备(低于10%)':
      router.push({
        path: '/basic/device/list',
        query: {
          fromPage: 'dashboard',
          queryType: 'lowBattery'
        }
      })
      break;
  }

}


function calcBlockSize() {
  // 计算工作台区域高度 - 顶部-面包屑-边距
  const bodyHeight = document.body.clientHeight - 50 - 20
  blockHeight.value = (bodyHeight - 100) / 2 // 左侧菜单使用
}

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

onBeforeMount(() => {
  calcBlockSize()
})
onMounted(() => {
  fetchGroupList() // 获取分组表格
  fetchLowBatteryList() // 获取低电量设备
  // fetchOfflineList() // 获取离线设备
  // fetchErrorList() // 获取异常设备
})
</script>

<template>
  <app-container style="overflow: hidden;padding-top: 10px;">
    <div style="display: flex;height: 90px;text-align: center;width: 100%;justify-content: space-evenly;">
      <div class="item">
        <el-image :src="groupPng" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">
            分组数量
          </div>
          <div class="num">
            {{ overview.groupCount }}
            <!-- <span class="unit">台</span> -->
          </div>
        </div>
      </div>
      <div class="item">
        <el-image :src="devicePng" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">
            设备数量
          </div>
          <div class="num">
            {{ overview.deviceCount }}
            <!-- <span class="unit">台</span> -->
          </div>
        </div>
      </div>
      <div class="item">
        <el-image :src="productPng" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">
            产品数量
          </div>
          <div class="num">
            {{ overview.productCount }}
            <!-- <span class="unit">%</span> -->
          </div>
        </div>
      </div>
      <div class="item">
        <el-image :src="dataPng" class="base-map-image" mode="fill" />
        <div class="item-text">
          <div style="color: #0f67e7;">
            今日收到数据
          </div>
          <div class="num">
            {{ overview.dataCount }}
            <!-- <span class="unit">%</span> -->
          </div>
        </div>
      </div>
    </div>
    <div class="device-bench">
      <el-row :gutter="10">
        <el-col :span="12">
          <bench-col icon="icon-group1" title="分组管理" :height="blockHeight" @handleClickTitle="handleClickTitle">
            <normal-table :data="groupList" :height="blockHeight - 94" :columns="groupColumn" :total="groupTotal" :query="groupListQuery" :list-loading="groupLoadingTable"
              @change="(val) => changePage(val, 'group')">
              <template #preColumns>
                <el-table-column label="序号" width="55" align="center">
                  <template #default="scope">
                    {{ (groupListQuery.offset! - 1) * groupListQuery.limit! + scope.$index + 1 }}
                  </template>
                </el-table-column>
              </template>

              <template #columns>
                <el-table-column fixed="right" label="操作" align="center" width="80">
                  <template #default="{ row }">
                    <el-button size="small" type="primary" link @click="handleOperateButton('group', row)">
                      进入分组
                    </el-button>
                  </template>
                </el-table-column>
              </template>
            </normal-table>
          </bench-col>
        </el-col>
        <el-col :span="12">
          <bench-col icon="icon-offline" title="离线设备" :height="blockHeight"  @handleClickTitle="handleClickTitle">
            <normal-table :data="offlineList" :height="blockHeight - 94" :columns="offlineColumn" :total="offlineTotal" :query="offlineListQuery" :list-loading="offlineLoadingTable"
              @change="(val) => changePage(val, 'offline')">
              <template #preColumns>
                <el-table-column label="序号" width="55" align="center">
                  <template #default="scope">
                    {{ (offlineListQuery.offset! - 1) * offlineListQuery.limit! + scope.$index + 1 }}
                  </template>
                </el-table-column>
              </template>

              <template #columns>
                <el-table-column fixed="right" label="操作" align="center" width="80">
                  <template #default="{ row }">
                    <el-button size="small" type="primary" link @click="handleOperateButton('offline', row)">
                      详情
                    </el-button>
                  </template>
                </el-table-column>
              </template>
            </normal-table>
          </bench-col>
        </el-col>
      </el-row>
    </div>
    <div class="device-bench" style="margin-top: 10px;">
      <el-row :gutter="10">
        <el-col :span="12">
          <bench-col icon="icon-lowBattery" title="低电量设备(低于10%)" :height="blockHeight" @handleClickTitle="handleClickTitle">
            <normal-table :data="lowBatteryList" :height="blockHeight - 94" :columns="lowBatteryColumn" :total="lowBatteryTotal" :query="lowBatteryListQuery" :list-loading="lowBatteryLoadingTable"
              @change="(val) => changePage(val, 'lowBattery')">
              <template #preColumns>
                <el-table-column label="序号" width="55" align="center">
                  <template #default="scope">
                    {{ (lowBatteryListQuery.offset! - 1) * lowBatteryListQuery.limit! + scope.$index + 1 }}
                  </template>
                </el-table-column>
              </template>

              <template #columns>
                <el-table-column fixed="right" label="操作" align="center" width="80">
                  <template #default="{ row }">
                    <el-button size="small" type="primary" link @click="handleOperateButton('lowBattery', row)">
                      详情
                    </el-button>
                  </template>
                </el-table-column>
              </template>
            </normal-table>
          </bench-col>
        </el-col>
        <el-col :span="12">
          <bench-col icon="icon-error" title="异常设备" :height="blockHeight" @handleClickTitle="handleClickTitle">
            <normal-table :data="errorList" :height="blockHeight - 94" :columns="errorColumn" :total="errorTotal" :query="errorListQuery" :list-loading="errorLoadingTable"
              @change="(val) => changePage(val, 'error')">
              <template #preColumns>
                <el-table-column label="序号" width="55" align="center">
                  <template #default="scope">
                    {{ (errorListQuery.offset! - 1) * errorListQuery.limit! + scope.$index + 1 }}
                  </template>
                </el-table-column>
              </template>

              <template #columns>
                <el-table-column fixed="right" label="操作" align="center" width="80">
                  <template #default="{ row }">
                    <el-button size="small" type="primary" link @click="handleOperateButton('error', row)">
                      详情
                    </el-button>
                  </template>
                </el-table-column>
              </template>
            </normal-table>
          </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;
    }
  }
}

.item {
  width: 300px;
  display: flex;
  justify-content: left;
  align-items: center;
  height: 80px;
  border-radius: 10px;
  border: 2px solid #398bff;

  &:hover {
    background-color: #e7f1fd;
    cursor: pointer;
    color: #398bff;
  }
}
</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;
}

.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>