Newer
Older
smart-metering-front / src / views / measure / bench / bench.vue
<script lang="ts" setup name="bench">
import { getCurrentInstance, ref } from 'vue'
import type { Ref } from 'vue'
import type { trainLogStatistic } from './bench-interface'
import { getCertificateStatistic, getStaffSStatistic, getStatistic, getTrainLogSStatistic } from '@/api/system/bench'
import { getPlanList } from '@/api/system/plan'
import { listPageApi } from '@/api/measure/file'
import Linechart from '@/components/Echart/LineChart.vue'
import Piechart from '@/components/echarts/pie.vue'
import BenchCol from '@/components/benchCol/index.vue'
import type { lineDataI, pieDataI } from '@/components/Echart/echart-interface'
import useUserStore from '@/store/modules/user'
// 每个展示块高度
const blockHeight = ref(300)
const blockWidth = ref(400)
const { username } = useUserStore()
const buttomTypes = ref([
  { id: '1', text: '培训记录', url: '/train/trainLog' },
  { id: '2', text: '证书到期提醒', url: '/person/remind' },
  { id: '3', text: '溯源供方', url: '/source/list' },
  { id: '4', text: '实验室', url: '/measureDept/ks' },
  { id: '5', text: '工程组', url: '/measureDept/gcz' },
  { id: '6', text: '计量人员', url: '/person/list' },
])
const tableData = ref([])
const meterageTableData = ref([])
const columns = ref([
  { text: '培训名称', value: 'planName' },
  { text: '负责人', value: 'director', width: '120' },
  { text: '培训时间', value: 'trainTime', width: '180' },
])
const meterageColumns = ref([
  { text: '文件名称', value: 'fileName' },
  { text: '类别', value: 'fileTypeName', width: '110' },
  { text: '发布时间', value: 'publishTime', width: '180' },
])
const CertificateColumns = ref([
  { text: '证书名称', value: 'certificateName' },
  { text: '到期时间', value: 'validDate', width: '180' },
])
const CertificatesColumns = ref([
  { text: '证书名称', value: 'certificateName' },
  { text: '人员名称', value: 'name', width: '110' },
  { text: '到期时间', value: 'validDate', width: '180' },
])
const StatisticxAxis: Ref<string[]> = ref([])
const StatisticData: Ref<lineDataI[]> = ref([])
const StaffSStatisticData: Ref<lineDataI[]> = ref([])
const maxStaffCount = ref(10)
const StaffSStatisticxAxis: Ref<string[]> = ref([])
const TrainLogSList: Ref<pieDataI[]> = ref([])
const TrainLogTitle = ref(0)
const CertificateList = ref([])
// 我的证书返回值
interface validReturn {
  certificateName:	string
  count:	string
  date:	string
  lastValidDate:	number
  name:	string
  notQualified:	number
  qualified:	number
  qualifiedCount:	number
  trainCount:	number
  validDate:	string
}
const CertificateObject = ref<validReturn>({
  certificateName:	'',
  count:	'',
  date:	'',
  lastValidDate:	0,
  name:	'',
  notQualified:	0,
  qualified:	0,
  qualifiedCount:	0,
  trainCount:	0,
  validDate:	'',
})

// 获得权限
const { proxy } = getCurrentInstance() as any
const getStatisticList = () => {
  const params = {
    createTime: '',
    deptId: 0,
    director: '',
    effectiveCompany: '',
    trainTime: '',
    offset: 1,
    limit: 10000,
  }
  getPlanList(params).then((res) => {
    tableData.value = res.data.rows
  })
  // 培训计划统计返回值
  interface planReturn {
    date: string
    count: string | number
  }
  getStatistic().then((res) => {
    StatisticxAxis.value = res.data.map((item: planReturn) => {
      return item.date
    })
    const yValue = res.data.map((item: planReturn) => {
      return Number(item.count)
    })
    StatisticData.value = [{ name: '培训计划', data: yValue }]
  })
  getStaffSStatistic().then((res) => {
    StaffSStatisticxAxis.value = res.data.map((item: planReturn) => item.date)
    const yValue = res.data.map((item: planReturn) => Number(item.count))
    maxStaffCount.value = Math.max(yValue) > 10 ? Math.max(yValue) : 10
    StaffSStatisticData.value = [{ name: '人数', data: yValue }]
  })

  // 返回值
  interface CertificatReturn {
    lastValidDate: number
  }
  const param = {
    account: username,
  }
  getCertificateStatistic(param).then((res) => {
    CertificateList.value = res.data
    CertificateObject.value = res.data.sort((nex: CertificatReturn, max: CertificatReturn) => {
      return nex.lastValidDate - max.lastValidDate
    })[0]
  })
}

function fetchMyTrainLog() {
  const param = {
    account: username,
  }
  getTrainLogSStatistic(param).then((res) => {
    const result: trainLogStatistic = res.data
    const notQualified: number = Number(result.trainCount) - result.qualifiedCount
    const qualifiedRate = ((result.qualifiedCount / result.trainCount) * 100).toFixed(2) // 合格率
    const notQualifiedRate = ((notQualified / result.trainCount) * 100).toFixed(2) // 不合格率
    TrainLogSList.value = [
      { name: `合   格   ${result.qualifiedCount}-${qualifiedRate}%`, value: result.qualifiedCount },
      { name: `不合格   ${notQualified}- ${notQualifiedRate}%`, value: notQualified },
    ]
    TrainLogTitle.value = res.data.trainCount
  }).catch((_) => {
    // 处理异常
    TrainLogSList.value = [
      { name: '合   格   0 - 50%', value: 0 },
      { name: '不合格   0 - 50%', value: 0 },
    ]
    TrainLogTitle.value = 0
  })
}
const getmeterageList = () => {
  const params = {
    fileNo: '', // 编号
    fileName: '', // 名称
    publishTime: '', // 发布时间
    fileCode: '', // 文件号
    effectiveTime: '', // 实施时间
    effectiveStatus: '', // 实施状态
    limit: 10,
    offset: 1,
    fileType: '', // 类型
  }
  listPageApi(params).then((res) => {
    meterageTableData.value = res.data.rows
  })
}

function calcBlockSize() {
  // 计算工作台区域高度 - 顶部-面包屑-边距
  const bodyHeight = document.body.clientHeight - 60 - 50 - 20
  blockHeight.value = bodyHeight > 610 ? (bodyHeight - 10) / 2 : 300
  blockWidth.value = (document.body.clientWidth - 180 - 20 - 20) / 3
  console.log(blockHeight.value, blockWidth.value - 20)
}
window.addEventListener('resize', () => {
  calcBlockSize()
})

onMounted(() => {
  calcBlockSize()
  fetchMyTrainLog() // 获取我的培训考核
  getmeterageList()
  getStatisticList()
})
</script>

<template>
  <app-container>
    <div class="bench">
      <el-row :gutter="10">
        <el-col :span="8">
          <bench-col
            v-if="proxy.hasPerm('/workbench/meterTrainStatistic')"
            icon="icon-book"
            title="培训计划"
            path-url="/train/plan"
            :style="{ height: blockHeight }"
            :height="blockHeight"
          >
            <el-table :data="tableData" style="width: 100%; height: 100%;" stripe header-row-class-name="bench-table-header" row-class-name="bench-table-row" class="bench-table">
              <el-table-column
                v-for="item in columns"
                :key="item.value"
                :prop="item.value"
                align="center"
                :label="item.text"
                :width="item.width"
              />
            </el-table>
          </bench-col>
        </el-col>
        <el-col :span="8">
          <bench-col
            v-if="proxy.hasPerm('/workbench/meterTrain/line')"
            icon="icon-line"
            title="培训计划"
            :height="blockHeight"
          >
            <line-chart
              :x-axis-data="StatisticxAxis"
              :data="StatisticData"
              :width="`${blockWidth - 20}px`"
              unit="个"
            />
          </bench-col>
        </el-col>
        <el-col :span="8">
          <div class="bench-right block" :style="{ height: `${blockHeight}px` }">
            <bench-col height="40%">
              <div class="bench-right-top">
                <div v-for="item of buttomTypes" :key="item.text" class="right-top-box" @click="$router.push(item.url)">
                  {{ item.text }}
                </div>
              </div>
            </bench-col>
            <div style="flex: 1;margin-top: 10px;">
              <bench-col
                v-if="proxy.hasPerm('/workbench/meterTrain/train')"
                title="我的培训考核"
                icon="icon-book"
                height="100%"
              >
                <div class="pie-chart">
                  <div class="pie-chart-info">
                    <pie-chart
                      :data="TrainLogSList"
                      :radius="['50%', '70%']"
                      right="40%"
                      :width="`${blockWidth - 20}px`"
                      :label-formatter="`${TrainLogTitle}`"
                    />
                  </div>
                </div>
              </bench-col>
            </div>
          </div>
        </el-col>
      </el-row>
    </div>
    <div class="bench">
      <el-row :gutter="10">
        <el-col :span="8">
          <bench-col
            v-if="proxy.hasPerm('/measure/file/quality')"
            title="计量文件"
            icon="icon-file"
            path-url="/file/quality"
            :height="blockHeight"
            class="flex-full block"
          >
            <el-table :data="meterageTableData" style="width: 100%; height: 100%;" stripe header-row-class-name="bench-table-header" row-class-name="bench-table-row" class="bench-table">
              <el-table-column
                v-for="item in meterageColumns"
                :key="item.value"
                :prop="item.value"
                align="center"
                :label="item.text"
                :width="item.width"
              />
            </el-table>
          </bench-col>
        </el-col>
        <el-col :span="8">
          <bench-col
            v-if="proxy.hasPerm('/workbench/person/remind')"
            title="我的证书"
            icon="icon-certi"
            :height="blockHeight"
            path-url="/person/remind"
            class="flex-full block"
          >
            <div style="display: flex;">
              <el-table :data="CertificateList" style="width: 65%; height: 100%;" stripe header-row-class-name="bench-table-header" row-class-name="bench-table-row" class="bench-table">
                <el-table-column
                  v-for="item in CertificateColumns"
                  :key="item.value"
                  :prop="item.value"
                  align="center"
                  :label="item.text"
                  :width="item.width"
                />
              </el-table>
              <div class="validDate">
                <div class="validDate-top">
                  <span class="validate-text">{{ CertificateObject.lastValidDate }}<span style="font-size: 12px;">天</span></span>
                </div>
                <div class="validDate-bottom">
                  最近到期时间 <br>
                  <span>{{ CertificateObject.validDate || '无' }}</span>
                </div>
              </div>
            </div>
          </bench-col>
          <bench-col
            v-if="proxy.hasPerm('/workbench/person/certificate') && !proxy.hasPerm('/workbench/person/remind')"
            title="证书预警"
            icon="icon-certi"
            path-url="/person/remind"
            :height="blockHeight"
            class="flex-full block"
          >
            <el-table :data="CertificateList" style="width: 100%; height: 100%;" stripe header-row-class-name="bench-table-header" row-class-name="bench-table-row" class="bench-table">
              <el-table-column
                v-for="item in CertificatesColumns"
                :key="item.value"
                :prop="item.value"
                align="center"
                :label="item.text"
                :width="item.width"
              />
            </el-table>
          </bench-col>
        </el-col>
        <el-col :span="8">
          <bench-col
            v-if="proxy.hasPerm('/workbench/person/list')"
            title="计量人员"
            icon="icon-line"
            :height="blockHeight"
            class="flex-full block"
          >
            <line-chart
              :x-axis-data="StaffSStatisticxAxis"
              :width="`${blockWidth - 20}px`"
              :max="maxStaffCount"
              :data="StaffSStatisticData"
              unit="人"
            />
          </bench-col>
        </el-col>
      </el-row>
    </div>
  </app-container>
</template>

<style lang="scss" scoped>
.bench {
  // display: flex;
  // justify-content: flex-start;
  width: 100%;
  box-sizing: border-box;

  .flex-full {
    flex: 1;
  }

  .block + .block {
    margin-left: 10px;
  }

  .bench-right {
    flex: 1;
    display: flex;
    flex-direction: column;
    height: 40vh;

    .bench-right-top {
      width: 100%;
      height: 100%;
      padding: 0 10px;
      display: flex;
      flex-wrap: wrap;
      align-items: center;
      box-sizing: border-box;

      .right-top-box {
        width: calc(33% - 10px);
        height: calc(50% - 10px);
        padding: 10px;
        margin: 5px;
        border-radius: 5px;
        text-align: center;
        font-size: 14px;
        color: #fff;
        cursor: pointer;
        background-color: #3d7eff;
        display: flex;
        justify-content: center;
        align-items: center;

        &:hover {
          background-color: #286ffd;
        }
      }
    }
  }
}

.bench + .bench {
  margin-top: 10px;
}

.validDate {
  width: 35%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;

  .validDate-top {
    position: relative;
    width: 100px;
    height: 100px;
    margin-bottom: 20px;
    background:
      url("../../../assets/images/bench/clock.png") no-repeat center /
      cover;

    .validate-text {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      font-size: 20px;
    }
  }

  .validDate-bottom {
    font-size: 16px;
    font-weight: 500;

    span {
      font-size: 14px;
      line-height: 2;
      font-weight: 400;
    }
  }
}

.pie-chart {
  display: flex;
  align-items: center;
  width: 100%;
  height: 100%;

  .pie-chart-info {
    flex: 1;
    font-size: 12px;
    height: 100%;

    .chart-info-title {
      display: flex;
      align-items: center;
      margin-top: 10px;

      .chart-info-bg {
        width: 10px;
        height: 10px;
        border-radius: 50%;
        margin-right: 8px;
        background-color: #3d7eff;
      }
    }
  }
}
</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;
}
</style>