gaoluyang
2026-08-06 377c0a70c094d024aeb0bb94f4b791c6d5530c1e
src/views/reportAnalysis/reportManagement/index.vue
@@ -13,7 +13,8 @@
                <span>各类型完成数量</span>
              </div>
            </template>
            <div class="top-container">
            <div class="top-container"
                 :class="{ 'two-cols': !ENABLE_SEMI_FINISHED }">
              <div class="typeNum">
                <div class="typeNum-left">
                  <img src="~@/assets/images/chartCard.svg"
@@ -37,7 +38,8 @@
                  </div>
                </div>
              </div>
              <div class="typeNum">
              <div class="typeNum"
                   v-if="ENABLE_SEMI_FINISHED">
                <div class="typeNum-left">
                  <img src="~@/assets/images/chartCard2.svg"
                       alt="图表"
@@ -98,7 +100,8 @@
                <span>质检合格率</span>
              </div>
            </template>
            <div class="top-container flex-center">
            <div class="top-container flex-center"
                 :class="{ 'quality-two-cols': !ENABLE_SEMI_FINISHED }">
              <div class="quality-card blue-card">
                <div class="quality-card-title">
                  <img src="~@/assets/images/chartCard.svg"
@@ -127,7 +130,8 @@
                  </div>
                </div>
              </div>
              <div class="quality-card green-card">
              <div class="quality-card green-card"
                   v-if="ENABLE_SEMI_FINISHED">
                <div class="quality-card-title">
                  <img src="~@/assets/images/chartCard2.svg"
                       alt="半成品"
@@ -210,12 +214,14 @@
                <div style="height: 80%; width: 100%;"
                     ref="inspectionChartRef">
                </div>
                <div class="container-line-right-bottom">
                <div class="container-line-right-bottom"
                     :class="{ 'two-boxes': !ENABLE_SEMI_FINISHED }">
                  <div class="inspection-chart-box">
                    <div class="chart-box-title">原材料总数</div>
                    <div class="chart-box-num">{{ getYearlyStatValue(0, 'totalCount') }}</div>
                  </div>
                  <div class="inspection-chart-box">
                  <div class="inspection-chart-box"
                       v-if="ENABLE_SEMI_FINISHED">
                    <div class="chart-box-title">半成品总数</div>
                    <div class="chart-box-num">{{ getYearlyStatValue(1, 'totalCount') }}</div>
                  </div>
@@ -295,6 +301,7 @@
                   :class="{ active: activeTab === 'raw' }"
                   @click="activeTab = 'raw'">原材料</div>
              <div class="tab-item"
                   v-if="ENABLE_SEMI_FINISHED"
                   :class="{ active: activeTab === 'semi' }"
                   @click="activeTab = 'semi'">半成品</div>
              <div class="tab-item"
@@ -309,7 +316,7 @@
</template>
<script setup>
  import { ref, reactive, onMounted, nextTick } from "vue";
  import { ref, reactive, onMounted, nextTick, watch } from "vue";
  import { ElMessage } from "element-plus";
  import * as echarts from "echarts";
  import {
@@ -320,6 +327,8 @@
    getMonthlyCompletionDetails,
    getTopParameters,
  } from "@/api/reportAnalysis/qualityReport";
  const ENABLE_SEMI_FINISHED = false;
  // 响应式数据
  const filterForm = reactive({
@@ -349,20 +358,20 @@
  };
  const getYearlyStatValue = (type, field) => {
    const stat = yearlyPassRateData.value.find(item => item.inspectType === type);
    const stat = yearlyPassRateData.value.find(item => item.modelType === type);
    return stat ? stat[field] : 0;
  };
  const getInspectStatValue = (type, field) => {
    const stat = inspectStatisticsData.value.find(
      item => item.inspectType === type
      item => item.modelType === type
    );
    return stat ? stat[field] : 0;
  };
  const getPassRateStatValue = (type, field) => {
    const stat = passRateStatisticsData.value.find(
      item => item.inspectType === type
      item => item.modelType === type
    );
    if (stat) {
      if (field === "completionRate" || field === "passRate") {
@@ -438,15 +447,19 @@
  const fetchTopParametersData = async () => {
    try {
      const typeMap = { raw: 0, semi: 1, final: 2 };
      const res = await getTopParameters(typeMap[activeTab.value]);
      const typeMap = {
        raw: 1,
        final: 3,
        ...(ENABLE_SEMI_FINISHED ? { semi: 2 } : {}),
      };
      const tabKey = ENABLE_SEMI_FINISHED
        ? activeTab.value
        : activeTab.value === "semi"
        ? "raw"
        : activeTab.value;
      const res = await getTopParameters(typeMap[tabKey] ?? 1);
      if (res.code === 200) {
        topParametersData.value = res.data;
        sumnum.value = topParametersData.value.list.reduce(
          (acc, cur) => acc + cur.count,
          0
        );
        console.log(sumnum.value);
        initSampleChart();
      }
    } catch (error) {
@@ -471,16 +484,19 @@
    const currentYear = new Date().getFullYear();
    return time.getFullYear() > currentYear;
  };
  const sumnum = ref(0);
  // 监听年份变化
  import { watch } from "vue";
  watch(value3, () => {
    fetchMonthlyPassRateData();
    fetchYearlyPassRateData();
    fetchMonthlyCompletionDetailsData();
  });
  watch(activeTab, () => {
  watch(activeTab, val => {
    if (!ENABLE_SEMI_FINISHED && val === "semi") {
      activeTab.value = "raw";
      return;
    }
    fetchTopParametersData();
  });
@@ -520,37 +536,29 @@
        title: {
          show: false,
        },
        // tooltip: {
        //   trigger: "item",
        //   formatter: "{a} <br/>{b}: {c} ({d}%)",
        tooltip: {
          trigger: "item",
          formatter: "{a} <br/>{b}: {c} ({d}%)",
        },
        // legend: {
        //   orient: "vertical",
        //   left: "left",
        // },
        series: [
          {
            name: "",
            name: "检测项目",
            type: "pie",
            radius: ["40%", "80%"],
            avoidLabelOverlap: false,
            label: {
              show: true,
              show: false,
              position: "center",
              formatter: function () {
                return `{a|检测数量}\n{b|${sumnum.value}}`;
              },
              disabled: true,
              rich: {
                a: {
                  fontSize: 14,
                  color: "#606266",
                  fontWeight: "normal",
                  lineHeight: 20,
                },
                b: {
                  fontSize: 20,
                  color: "#303133",
                  fontWeight: "bold",
                  lineHeight: 24,
                  padding: [5, 0, 0, 0],
                },
            },
            emphasis: {
              label: {
                show: true,
                fontSize: "18",
                fontWeight: "bold",
              },
            },
            labelLine: {
@@ -572,6 +580,49 @@
  const initEquipmentChart = () => {
    if (equipmentChartRef.value) {
      equipmentChart = echarts.init(equipmentChartRef.value);
      const legendData = ENABLE_SEMI_FINISHED
        ? ["原材料", "半成品", "成品"]
        : ["原材料", "成品"];
      const barWidth = ENABLE_SEMI_FINISHED ? "15%" : "20%";
      const series = [
        {
          name: "原材料",
          type: "bar",
          barWidth,
          data: monthlyCompletionDetailsData.value.map(
            item => item.rawMaterialCount
          ),
          itemStyle: {
            color: "#409EFF",
          },
        },
        ...(ENABLE_SEMI_FINISHED
          ? [
              {
                name: "半成品",
                type: "bar",
                barWidth,
                data: monthlyCompletionDetailsData.value.map(
                  item => item.processCount
                ),
                itemStyle: {
                  color: "#67C23A",
                },
              },
            ]
          : []),
        {
          name: "成品",
          type: "bar",
          barWidth,
          data: monthlyCompletionDetailsData.value.map(
            item => item.outgoingCount
          ),
          itemStyle: {
            color: "#E6A23C",
          },
        },
      ];
      const option = {
        title: {
          show: false,
@@ -589,8 +640,8 @@
          containLabel: true,
        },
        legend: {
          data: ["原材料", "半成品", "成品"], // 图例数据
          icon: ["circle", "circle", "circle"],
          data: legendData, // 图例数据
          icon: legendData.map(() => "circle"),
          itemWidth: 10, // 设置图标宽度
          itemHeight: 10,
          itemGap: 30,
@@ -617,43 +668,7 @@
          type: "value",
          name: "数(个)",
        },
        series: [
          {
            name: "原材料",
            type: "bar",
            barWidth: "15%",
            data: monthlyCompletionDetailsData.value.map(
              item => item.rawMaterialCount
            ),
            itemStyle: {
              color: "#409EFF",
            },
          },
          {
            name: "半成品",
            type: "bar",
            barWidth: "15%",
            data: monthlyCompletionDetailsData.value.map(
              item => item.processCount
            ),
            itemStyle: {
              color: "#67C23A",
            },
          },
          {
            name: "成品",
            type: "bar",
            barWidth: "15%",
            data: monthlyCompletionDetailsData.value.map(
              item => item.outgoingCount
            ),
            itemStyle: {
              color: "#E6A23C",
            },
          },
        ],
        series,
      };
      equipmentChart.setOption(option);
    }
@@ -663,6 +678,27 @@
  const initInspectionChart = () => {
    if (inspectionChartRef.value) {
      inspectionChart = echarts.init(inspectionChartRef.value);
      const data = [
        {
          value: getYearlyStatValue(0, "totalCount"),
          name: "原材料",
          itemStyle: { color: "#1890FF" },
        },
        ...(ENABLE_SEMI_FINISHED
          ? [
              {
                value: getYearlyStatValue(1, "totalCount"),
                name: "半成品",
                itemStyle: { color: "#F7BA1E" },
              },
            ]
          : []),
        {
          value: getYearlyStatValue(2, "totalCount"),
          name: "成品",
          itemStyle: { color: "#14C9C9" },
        },
      ];
      const option = {
        title: {
          show: false,
@@ -674,23 +710,7 @@
          {
            type: "pie",
            radius: "70%",
            data: [
              {
                value: getYearlyStatValue(0, "totalCount"),
                name: "原材料",
                itemStyle: { color: "#1890FF" },
              },
              {
                value: getYearlyStatValue(1, "totalCount"),
                name: "半成品",
                itemStyle: { color: "#F7BA1E" },
              },
              {
                value: getYearlyStatValue(2, "totalCount"),
                name: "成品",
                itemStyle: { color: "#14C9C9" },
              },
            ],
            data,
            label: {
              show: true,
              formatter: "{b}: {c}",
@@ -715,6 +735,44 @@
    if (usageChartRef.value) {
      // 初始化 ECharts 实例
      usageChart = echarts.init(usageChartRef.value);
      const legendData = ENABLE_SEMI_FINISHED
        ? ["原材料", "半成品", "成品"]
        : ["原材料", "成品"];
      const series = [
        {
          name: "原材料",
          type: "line",
          symbol: "circle",
          itemStyle: {
            color: "#1890FF",
          },
          data: monthlyPassRateData.value.map(item => item.rawMaterial.passRate),
        },
        ...(ENABLE_SEMI_FINISHED
          ? [
              {
                name: "半成品",
                type: "line",
                symbol: "circle",
                itemStyle: {
                  color: "#F7BA1E",
                },
                data: monthlyPassRateData.value.map(
                  item => item.process.passRate
                ),
              },
            ]
          : []),
        {
          name: "成品",
          type: "line",
          symbol: "circle",
          itemStyle: {
            color: "#14C9C9",
          },
          data: monthlyPassRateData.value.map(item => item.outgoing.passRate),
        },
      ];
      // 配置图表选项
      const option = {
        // 标题配置(隐藏)
@@ -736,8 +794,8 @@
        },
        // 图例配置
        legend: {
          data: ["原材料", "半成品", "成品"], // 图例数据
          icon: ["circle", "circle", "circle"],
          data: legendData, // 图例数据
          icon: legendData.map(() => "circle"),
          itemWidth: 10, // 设置图标宽度
          itemHeight: 10,
          itemGap: 30,
@@ -767,40 +825,7 @@
          name: "单位:%",
        },
        // 系列数据
        series: [
          {
            name: "原材料", // 系列名称
            type: "line", // 图表类型为折线图
            // stack: "Total", // 堆叠名称
            symbol: "circle",
            itemStyle: {
              color: "#1890FF", // 设置这条线的颜色
            },
            data: monthlyPassRateData.value.map(
              item => item.rawMaterial.passRate
            ),
          },
          {
            name: "半成品", // 系列名称
            type: "line", // 图表类型为折线图
            // stack: "Total", // 堆叠名称
            symbol: "circle",
            itemStyle: {
              color: "#F7BA1E", // 设置这条线的颜色
            },
            data: monthlyPassRateData.value.map(item => item.process.passRate),
          },
          {
            name: "成品", // 系列名称
            type: "line", // 图表类型为折线图
            // stack: "Total", // 堆叠名称
            symbol: "circle",
            itemStyle: {
              color: "#14C9C9", // 设置这条线的颜色
            },
            data: monthlyPassRateData.value.map(item => item.outgoing.passRate),
          },
        ],
        series,
      };
      // 将配置应用到图表
      usageChart.setOption(option);
@@ -853,16 +878,21 @@
      "#52c41a",
      getPassRateStatValue(0, "passRate")
    );
    semiCompletionChartInstance = initQualityChart(
      semiCompletionChart,
      "#1890ff",
      getPassRateStatValue(1, "completionRate")
    );
    semiQualityChartInstance = initQualityChart(
      semiQualityChart,
      "#52c41a",
      getPassRateStatValue(1, "passRate")
    );
    if (ENABLE_SEMI_FINISHED) {
      semiCompletionChartInstance = initQualityChart(
        semiCompletionChart,
        "#1890ff",
        getPassRateStatValue(1, "completionRate")
      );
      semiQualityChartInstance = initQualityChart(
        semiQualityChart,
        "#52c41a",
        getPassRateStatValue(1, "passRate")
      );
    } else {
      semiCompletionChartInstance = null;
      semiQualityChartInstance = null;
    }
    finalCompletionChartInstance = initQualityChart(
      finalCompletionChart,
      "#1890ff",
@@ -962,6 +992,9 @@
  // 生命周期
  onMounted(() => {
    if (!ENABLE_SEMI_FINISHED && activeTab.value === "semi") {
      activeTab.value = "raw";
    }
    fetchInspectStatisticsData();
    fetchPassRateStatisticsData();
    fetchMonthlyPassRateData();
@@ -985,8 +1018,10 @@
      // 调整质检合格率图表大小
      materialCompletionChartInstance?.resize();
      materialQualityChartInstance?.resize();
      semiCompletionChartInstance?.resize();
      semiQualityChartInstance?.resize();
      if (ENABLE_SEMI_FINISHED) {
        semiCompletionChartInstance?.resize();
        semiQualityChartInstance?.resize();
      }
      finalCompletionChartInstance?.resize();
      finalQualityChartInstance?.resize();
    });
@@ -996,10 +1031,9 @@
<style scoped>
  .report-management {
    padding: 20px;
    background-color: #f5f5f5;
    min-height: 100vh;
    /* height: 87vh;
                                                                                                                            overflow: hidden; */
      overflow: hidden; */
  }
  .page-header {
@@ -1200,7 +1234,6 @@
    color: #1d2129;
    font-size: 16px;
    font-weight: 500;
    line-height: 37px;
  }
  .info-line {
@@ -1208,7 +1241,6 @@
    display: flex;
    padding-left: 20px;
    align-items: center;
    flex: 1;
  }
  .info-icon {
@@ -1244,6 +1276,10 @@
    height: 130px;
    width: 100%;
    display: flex;
  }
  .top-container.two-cols .typeNum {
    width: 50%;
  }
  .typeNum {
@@ -1396,6 +1432,14 @@
    flex-direction: column;
  }
  .top-container.quality-two-cols .quality-card {
    width: 48%;
  }
  .container-line-right-bottom.two-boxes .inspection-chart-box {
    width: 45%;
  }
  .blue-card {
    background-color: #e6f7ff;
  }
@@ -1471,8 +1515,8 @@
  }
  /* .flex-center {
                                                                                                                          justify-content: space-evenly;
                                                                                                                          } */
    justify-content: space-evenly;
    } */
  .blue-chart {
    /* background-color: rgba(24, 144, 255, 0.1); */