Newer
Older
smart-metering-front / src / views / business / bench / bench.vue
dutingting on 27 Feb 14 KB 需求更改、excel在线编辑
<!-- 工作台 -->
<script lang="ts" setup name="BusinessBench">
import { getCurrentInstance, ref } from 'vue'
import type { Ref } from 'vue'
import { SCHEDULE } from '@/utils/scheduleDict'
import type { pieDataI } from '@/components/Echart/echart-interface'
import { getPieData, getSampleMeasureList, getSampleMonitorList, getSamplestatusMonth } from '@/api/business/bench/bench'
import { getReportList } from '@/api/business/lab/report'
import type { TableColumn } from '@/components/NormalTable/table_interface'
import { getJobAccountList } from '@/api/business/board/jobAccount'

// 每个展示块高度
const blockHeight = ref(300)
const blockWidth = ref(400)
const { proxy } = getCurrentInstance() as any
// 样品监控表头
const sampleMonitorData = ref([])
// 样品监控表头
const sampleMonitorHead = [
  { text: '样品名称', value: 'sampleName' },
  { text: '当前检测实验室', value: 'currentSegment', width: '125' },
  { text: '下一检测实验室', value: 'nextSegment', width: '125' },
  { text: '进度', value: 'progressData', width: '140' },
]
// 样品监控查询条件
const listQuerySampleMonitor = ref({
  offset: 1,
  limit: 10,
})
const loadingTableSampleMonitor = ref(false) // 样品监控loading
const totalSampleMonitor = ref(0) // 样品监控数据总数
// 样品检测表头
const sampleMeasureHead = [
  { text: '样品名称', value: 'sampleName' },
  { text: '委托方名称', value: 'customerName', width: '100' },
  { text: '检测状态', value: 'measureStatusName' },
]
// 我的检测表格数据
const sampleMeasureData = ref([])
// 进度条添加后缀 %
const format = (percentage: number) => (percentage === 100 ? 'Full' : `${percentage}%`)
// 证书报告数据
const reportData = ref([])
// 表头
const reportHead = ref<TableColumn[]>([
  { text: '名称', value: 'certificateReportName', align: 'center' },
  { text: '检定员', value: 'measurePerson', align: 'center' },
  { text: '状态', value: 'approvalStatusName', align: 'center', width: '110' },
])

// 表头
const realTimeWorkStatisticsHead = ref<TableColumn[]>([
  { text: '检测实验室', value: 'organizeName', align: 'center' },
  { text: '今日检完样品', value: 'samplesCompletedToday', align: 'center' },
  { text: '今日出具证书数', value: 'certificatesToday', align: 'center' },
  { text: '超期率', value: 'expireRate', align: 'center' },
])
// 实时工作统计表格数据
const realTimeWorkStatisticsData = ref()
// 饼图--图例配置项
const picLegend = ref({
  show: false,
  orient: 'vertical',
  right: '20%',
  top: 'center',
  icon: 'circle',
  itemWidth: 12,
  itemHeight: 12,
  itemStyle: {
    fontSize: 18,
  },
})

// 按钮跳转数据
const buttonTypes = ref([
  { id: '1', text: '证书打印', url: '/schedule/certPrintList' },
  { id: '2', text: '环境记录单', url: '/lab/environmentalList' },
  { id: '3', text: '原始记录', url: '/lab/primitiveLogList' },
  { id: '4', text: '现场检测申请', url: '/fieldTest/approve' },
  { id: '5', text: '分包项目登记', url: '/subpackage/itemApply' },
  { id: '6', text: '分包方档案', url: '/subpackage/archives' },
])
// 当前进行中样品状态数据
const statusData = ref<{ status: string;quantity: string }[]>([])
const router = useRouter()

// 点击按钮组
const handleClickButton = (id: string) => {
  const index = buttonTypes.value.findIndex(item => item.id === id)
  if (index !== -1 && buttonTypes.value[index].url) {
    router.push(buttonTypes.value[index].url)
  }
}
// 计算工作台区域高度 - 顶部-面包屑-边距
const benchDivHeight = ref()
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)
  benchDivHeight.value = blockHeight.value - 60
}

// ---------------------------------------获取数据------------------------------------
// 样品监控
const fetchSampleMonitorList = (isNowPage = false) => {
  loadingTableSampleMonitor.value = true
  if (!isNowPage) {
    // 是否显示当前页,否则跳转第一页
    listQuerySampleMonitor.value.offset = 1
  }
  getSampleMonitorList(listQuerySampleMonitor.value).then((res) => {
    loadingTableSampleMonitor.value = false
    sampleMonitorData.value = res.data.rows.map((item: { progress: string; progressData: number }) => {
      if (item.progress.includes('%')) {
        item.progressData = Number(item.progress.slice(0, item.progress.indexOf('%')))
      }
      console.log('进度', typeof item.progressData, item.progressData)
      return item
    })
    totalSampleMonitor.value = parseInt(res.data.total)
  }).catch(() => {
    loadingTableSampleMonitor.value = false
  })
}
// 页数发生变化后的操作,可能是页码变化,可能是每页容量变化,此函数必写
const changePage = (val: { size?: number; page?: number }) => {
  if (val && val.size) {
    listQuerySampleMonitor.value.limit = val.size
  }
  if (val && val.page) {
    listQuerySampleMonitor.value.offset = val.page
  }
  fetchSampleMonitorList(true)
}

// 证书报告
const listQueryReport = ({
  approvalStatus: '0', // 审批状态 -- 全部
  certificateReportCode: '', // 证书号
  customerName: '', // 委托方名称
  measureCategory: '', // 检校类别
  orderCode: '', // 委托单编号
  sampleName: '', // 样品名称
  sampleNo: '', // 样品编号
  formId: SCHEDULE.BUSINESS_REPORT_ON_CREDENTIALS,
  offset: 1,
  limit: 20,
})
// 证书报告获取列表数据
const fetchReportData = () => {
  getReportList(listQueryReport).then((response) => {
    reportData.value = response.data.rows.map((item: { approvalStatusName: string }) => {
      return {
        ...item,
        // 已通过-可打印、审批中-审批中、其他所有状态-编制中
        approvalStatusName: item.approvalStatusName === '审批中' ? '审批中' : item.approvalStatusName === '已通过' ? '可打印' : '编制中',
      }
    })
  }).catch((_) => {
  })
}

// 实时工作统计
function fetchJobAccountList() {
  getJobAccountList().then((response) => {
    realTimeWorkStatisticsData.value = response.data
  })
}

// 样品检测列表
function fetchSampleMeasureList() {
  getSampleMeasureList().then((response) => {
    sampleMeasureData.value = response.data.rows
  })
}

// 本月样品状态
const fetchSamplestatusMonth = () => {
  getSamplestatusMonth().then((res) => {
    statusData.value = res.data
  })
}

const totalQuantity = ref(0) // 总数(饼图中间)
const pieData = ref() // 饼图数据
// 饼图
const fetchPieData = () => {
  getPieData().then((res) => {
    pieData.value = res.data.map((item: { measureQuantity: number; rate: string;measureStatusName: string }) => {
      return {
        ...item,
        name: item.measureStatusName,
        value: item.measureQuantity,
      }
    })
    res.data.forEach((item: { totalQuantity: number }) => {
      totalQuantity.value += item.totalQuantity
    })
  })
}
onMounted(() => {
  calcBlockSize()
  fetchSampleMonitorList() // 样品监控
  fetchReportData() // 证书报告
  fetchJobAccountList() // 实时工作统计
  fetchSamplestatusMonth() // 本月样品状态
  fetchSampleMeasureList() // 样品检测列表
  fetchPieData() // 饼图
})
</script>

<template>
  <app-container>
    <el-row :gutter="10">
      <el-col :span="8">
        <bench-col
          icon="icon-file"
          title="样品监控"
          :height="blockHeight"
          :pagination="true"
          :query="listQuerySampleMonitor"
          :total="totalSampleMonitor"
          @change="changePage"
        >
          <el-table
            v-loading="loadingTableSampleMonitor"
            :data="sampleMonitorData"
            :height="blockHeight - 90"
            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 sampleMonitorHead"
              :key="item.value"
              :prop="item.value"
              align="center"
              :label="item.text"
              show-overflow-tooltip
              :width="item.width"
            >
              <template v-if="item.value === 'progressData'" #default="scope">
                <el-progress :stroke-width="5" :percentage="scope.row.progressData" />
              </template>
            </el-table-column>
          </el-table>
        </bench-col>
      </el-col>
      <el-col :span="8">
        <bench-col icon="icon-line" title="样品检测" :height="blockHeight" path-url="/lab/myMeasureList">
          <div class="my-tests" style="width: 100%;">
            <div style="width: 60%;">
              <el-table
                :data="sampleMeasureData"
                :max-height="blockHeight - 60"
                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 sampleMeasureHead"
                  :key="item.value"
                  :prop="item.value"
                  align="center"
                  :label="item.text"
                  :width="item.width"
                />
              </el-table>
            </div>
            <div style="width: 40%;">
              <pie-chart
                style="width: 100%;"
                :data="pieData"
                :radius="['50%', '70%']"
                :colors="['#3d7eff', '#caddff', '#1d9cce', '#1D9CAF']"
                right="0%"
                :legend="picLegend"
                :label-formatter="`${totalQuantity}`"
              />
            </div>
          </div>
        </bench-col>
      </el-col>
      <el-col :span="8">
        <bench-col :height="blockHeight">
          <div
            :max-height="blockHeight - 60"
            style="width: 100%; height: 100%;
            padding: 32px 0;
            display: flex;flex-wrap: wrap;
            justify-content: center;
            align-items: center;"
          >
            <div
              v-for="(item, index) of buttonTypes"
              :key="index"
              class="right-top-box"
              @click="handleClickButton(item.id)"
            >
              {{ item.text }}
            </div>
          </div>
        </bench-col>

        <!-- <div
          v-for="item of buttonTypes"
          :key="item.text"
          class="right-top-box"
        >
          <span>
            {{ item.text }}
          </span>
        </div> -->
      </el-col>
    </el-row>
    <div style="margin-top: 10px;" />
    <el-row :gutter="10">
      <el-col :span="8">
        <bench-col
          icon="icon-book"
          title="计量数据"
          path-url="/lab/measureDataList"
          :style="{ height: blockHeight }"
          :height="blockHeight"
        >
          <el-table
            :data="reportData"
            :max-height="blockHeight - 60"
            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 reportHead"
              :key="item.value"
              :prop="item.value"
              align="center"
              :label="item.text"
              :width="item.width"
              show-overflow-tooltip
            />
          </el-table>
        </bench-col>
      </el-col>
      <el-col :span="8">
        <bench-col
          icon="icon-timeTotal"
          title="实时工作统计"
          :style="{ height: blockHeight }"
          path-url="/board/jobAccount"
          :height="blockHeight"
        >
          <el-table
            :data="realTimeWorkStatisticsData"
            :max-height="blockHeight - 60"
            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 realTimeWorkStatisticsHead"
              :key="item.value"
              :prop="item.value"
              align="center"
              :label="item.text"
              :width="item.width"
              show-overflow-tooltip
            >
              <template v-if="item.value === 'schedule'" #default="scope">
                <el-progress :stroke-width="5" :percentage="scope.row.schedule" />
              </template>
            </el-table-column>
          </el-table>
        </bench-col>
      </el-col>
      <el-col :span="8" :style="{ height: blockHeight }" :height="blockHeight">
        <bench-col
          title="本月样品状态" icon="icon-status" :max-height="blockHeight - 60"
          style="width: 100%; height: 100%;"
        >
          <div class="status-box">
            <div v-for="(item, index) in statusData" :key="index" class="status-box-item">
              <div>
                {{ item.quantity }}
              </div>
              <div style="font-size: 12px;">
                {{ item.status }}
              </div>
              <div class="status-box-bgc" />
            </div>
          </div>
        </bench-col>
      </el-col>
    </el-row>
  </app-container>
</template>

<style lang="scss" scoped>
.my-tests {
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.status-box {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-around;
  height: 100%;

  .status-box-item {
    width: 40%;
    height: 8vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-around;
    text-align: center;

    .status-box-bgc {
      width: 50%;
      height: 5vh;
      background: url("../../../assets/images/bench/sampie-status.png") no-repeat center / cover;
    }
  }
}

.right-top-box {
  width: calc(33% - 20px);
  height: 20%;
  padding: 10px;
  margin: 5px;
  border-radius: 5px;
  white-space: nowrap;
  // 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;
  }
}
</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>