gongchunyi
19 小时以前 e1535c267711c7c8d560e8916437167bbcd3156b
src/views/reportAnalysis/qualityAnalysis/components/center-bottom.vue
@@ -1,6 +1,9 @@
<template>
  <div>
    <PanelHeader title="工单执行效率分析" />
    <div class="chart-header">
      <PanelHeader title="完成检验数" />
      <div class="warn-range" @click="handleRangeClick">近7天</div>
    </div>
    <div class="main-panel panel-item-customers">
      <Echarts
          ref="chart"
@@ -20,7 +23,7 @@
<script setup>
import { ref, onMounted } from 'vue'
import { qualityStatistics } from '@/api/viewIndex.js'
import { completedInspectionCount } from '@/api/viewIndex.js'
import PanelHeader from './PanelHeader.vue'
import Echarts from '@/components/Echarts/echarts.vue'
@@ -29,21 +32,25 @@
  height: '135%',
}
const grid = { left: '3%', right: '4%', bottom: '3%', top: '10%', containLabel: true }
const grid = { left: '8%', right: '8%', bottom: '8%', top: '15%', containLabel: true }
const barLegend = {
  show: true,
  textStyle: { color: '#B8C8E0' },
  data: ['开工', '完成'],
  top: '5%',
  left: 'center',
  textStyle: { color: '#B8C8E0', fontSize: 14 },
  itemGap: 30,
  data: ['合格', '不合格', '合格率'],
}
// 柱状图:开工、完成;折线图:良品率(颜色 rgba(90, 216, 166, 1))
// 柱状图:合格(黄色)、不合格(紫色);折线图:合格率(蓝色)
const chartSeries = ref([
  {
    name: '开工',
    name: '合格',
    type: 'bar',
    barWidth: 20,
    barGap: '40%',
    barGap: '20%',
    yAxisIndex: 0,
    emphasis: { focus: 'series' },
    itemStyle: {
      color: {
@@ -53,18 +60,19 @@
        x2: 0,
        y2: 1,
        colorStops: [
          { offset: 1, color: 'rgba(0, 164, 237, 0)' },
          { offset: 0, color: 'rgba(78, 228, 255, 1)' },
          { offset: 0, color: 'rgba(255, 215, 0, 1)' }, // 金黄色顶部
          { offset: 1, color: 'rgba(255, 215, 0, 0.5)' }, // 半透明底部
        ],
      },
    },
    data: [],
  },
  {
    name: '完成',
    name: '不合格',
    type: 'bar',
    barGap: '40%',
    barGap: '20%',
    barWidth: 20,
    yAxisIndex: 0,
    emphasis: { focus: 'series' },
    itemStyle: {
      color: {
@@ -74,9 +82,34 @@
        x2: 0,
        y2: 1,
        colorStops: [
          { offset: 1, color: 'rgba(83, 126, 245, 0.19)' },
          { offset: 0, color: 'rgba(144, 97, 248, 1)' },
          { offset: 0, color: 'rgba(144, 97, 248, 1)' }, // 紫色顶部
          { offset: 1, color: 'rgba(144, 97, 248, 0.6)' }, // 半透明底部
        ],
      },
    },
    data: [],
  },
  {
    name: '合格率',
    type: 'line',
    yAxisIndex: 1,
    smooth: true,
    symbol: 'circle',
    symbolSize: 8,
    lineStyle: {
      color: 'rgba(78, 228, 255, 1)', // 青色
      width: 2,
    },
    itemStyle: {
      color: 'rgba(78, 228, 255, 1)',
      borderWidth: 2,
      borderColor: '#fff',
    },
    emphasis: {
      focus: 'series',
      itemStyle: {
        shadowBlur: 10,
        shadowColor: 'rgba(78, 228, 255, 0.8)',
      },
    },
    data: [],
@@ -86,53 +119,87 @@
const tooltip = {
  trigger: 'axis',
  axisPointer: { type: 'cross' },
  backgroundColor: 'rgba(0, 0, 0, 0.8)',
  borderColor: 'rgba(78, 228, 255, 0.5)',
  borderWidth: 1,
  textStyle: { color: '#B8C8E0' },
  formatter(params) {
    let result = params[0].axisValueLabel + '<br/>'
    params.forEach((item) => {
      const unit = item.seriesName === '近7天'
      result += `<div>${item.marker} ${item.seriesName}: ${item.value}${unit}</div>`
      let unit = ''
      if (item.seriesName === '合格率') {
        unit = '%'
      } else {
        unit = '件'
      }
      result += `<div style="margin: 4px 0;">${item.marker} ${item.seriesName}: ${item.value}${unit}</div>`
    })
    return result
  },
}
const xAxis1 = ref([
  { type: 'category', axisTick: { show: false }, axisLabel: { color: '#B8C8E0' }, data: [] },
  {
    type: 'category',
    axisTick: { show: false },
    axisLabel: { color: '#B8C8E0', fontSize: 12 },
    axisLine: { lineStyle: { color: 'rgba(184, 200, 224, 0.3)' } },
    data: [],
  },
])
const yAxis1 = [
  { type: 'value', name: '件', axisLabel: { color: '#B8C8E0' }, nameTextStyle: { color: '#B8C8E0' } },
  {
    type: 'value',
    name: '近7天',
    name: '单位: 件',
    nameLocation: 'start',
    nameTextStyle: { color: '#B8C8E0', fontSize: 12, padding: [0, 0, 0, 10] },
    axisLabel: { color: '#B8C8E0', fontSize: 12 },
    axisLine: { show: false },
    splitLine: {
      show: true,
      lineStyle: { color: 'rgba(184, 200, 224, 0.2)', type: 'dashed' },
    },
  },
  {
    type: 'value',
    name: '单位: %',
    nameLocation: 'end',
    nameTextStyle: { color: '#B8C8E0', fontSize: 12, padding: [0, 0, 0, 10] },
    min: 0,
    max: 100,
    axisLabel: { color: '#B8C8E0', formatter: '{value}%' },
    nameTextStyle: { color: '#B8C8E0' },
    splitLine: { lineStyle: { color: 'rgba(184, 200, 224, 0.2)' } },
    axisLabel: { color: '#B8C8E0', fontSize: 12, formatter: '{value}' },
    axisLine: { show: false },
    splitLine: {
      show: true,
      lineStyle: { color: 'rgba(184, 200, 224, 0.2)', type: 'dashed' },
    },
  },
]
const fetchData = () => {
  qualityStatistics()
      .then((res) => {
        if (!res?.data?.item || !Array.isArray(res.data.item)) return
        const items = res.data.item
        xAxis1.value[0].data = items.map((d) => d.date)
        // 开工:过程检验数
        chartSeries.value[0].data = items.map((d) => Number(d.processNum) || 0)
        // 完成:出厂数
        chartSeries.value[1].data = items.map((d) => Number(d.factoryNum) || 0)
        // 良品率:出厂数/过程数*100(无单独接口时用此占位)
        chartSeries.value[2].data = items.map((d) => {
          const processNum = Number(d.processNum) || 0
          const factoryNum = Number(d.factoryNum) || 0
          if (processNum <= 0) return 0
          return Math.min(100, Math.round((factoryNum / processNum) * 100))
        })
      })
      .catch((err) => {
        console.error('获取开工与良品率数据失败:', err)
      })
  completedInspectionCount()
    .then((res) => {
      if (res?.code === 200 && Array.isArray(res?.data)) {
        const items = res.data
        // 更新X轴日期数据
        xAxis1.value[0].data = items.map((d) => d.dateStr || '')
        // 更新合格数(黄色柱状图)
        chartSeries.value[0].data = items.map((d) => Number(d.qualifiedCount) || 0)
        // 更新不合格数(紫色柱状图)
        chartSeries.value[1].data = items.map((d) => Number(d.unqualifiedCount) || 0)
        // 更新合格率(蓝色折线图)
        chartSeries.value[2].data = items.map((d) => Number(d.passRate) || 0)
      }
    })
    .catch((err) => {
      console.error('获取完成检验数数据失败:', err)
    })
}
const handleRangeClick = () => {
  // 先按截图做静态"近7天",后续有真实筛选需求再接入
  fetchData()
}
onMounted(() => {
@@ -141,6 +208,35 @@
</script>
<style scoped>
.chart-header {
  position: relative;
  display: flex;
  align-items: center;
}
.warn-range {
  position: absolute;
  right: 0;
  top: 0;
  height: 32px;
  padding: 0 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  color: #ffffff;
  font-weight: 600;
  font-size: 14px;
  background: linear-gradient(180deg, rgba(51, 120, 255, 1) 0%, rgba(0, 164, 237, 1) 100%);
  border: 1px solid rgba(78, 228, 255, 0.25);
  cursor: pointer;
  z-index: 10;
}
.warn-range:hover {
  background: linear-gradient(180deg, rgba(51, 140, 255, 1) 0%, rgba(0, 184, 237, 1) 100%);
}
.main-panel {
  display: flex;
  flex-direction: column;
@@ -152,5 +248,7 @@
  padding: 18px;
  width: 100%;
  height: 449px;
  position: relative;
  background: radial-gradient(circle at 50% 50%, rgba(78, 228, 255, 0.05) 0%, rgba(0, 0, 0, 0) 70%);
}
</style>