Browse Source

P控制图

“luofeng” 1 month ago
parent
commit
9c569dbb0c
3 changed files with 348 additions and 0 deletions
  1. 8 0
      src/api/analysis/index.js
  2. 327 0
      src/views/analysis/process/P.vue
  3. 13 0
      src/views/analysis/process/index.vue

+ 8 - 0
src/api/analysis/index.js

@@ -1,5 +1,13 @@
 import request from "@/utils/request";
 
+export function PCompute(data) {
+  return request({
+    url: "/api/v1/spc/PCompute",
+    method: "post",
+    data,
+  });
+}
+
 export function XBarSCompute(data) {
   return request({
     url: "/api/v1/spc/XBarSCompute",

+ 327 - 0
src/views/analysis/process/P.vue

@@ -0,0 +1,327 @@
+<template>
+  <div class="container1">
+    <div class="databox">
+      <el-scrollbar :style="{ height: Height + 'px' }">
+        <div class="box" v-show="!addStatus">
+          <div
+            style="
+              display: flex;
+              align-items: center;
+              justify-content: space-between;
+            "
+          >
+            <div style="display: flex; align-items: center">
+              <div class="bg"></div>
+              控制图绘制
+            </div>
+
+            <el-button
+              type="primary"
+              v-print="'#print'"
+              style="margin-left: 10px; height: 25px"
+              >打 印</el-button
+            >
+          </div>
+          <div class="info">
+            <div id="print">
+              <div ref="chartRef" style="width: 100%; height: 400px"></div>
+            </div>
+          </div>
+        </div>
+      </el-scrollbar>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, onMounted, watch } from "vue";
+import * as echarts from "echarts";
+import { PCompute } from "@/api/analysis";
+
+// 假设的数据
+var chartData = ref([]);
+
+const param = {
+  x: {
+    defectCount: 30,
+    sampleSize: 500,
+  },
+  x2: {
+    defectCount: 50,
+    sampleSize: 600,
+  },
+};
+
+const getTableData = async () => {
+  var resultData = await PCompute(param);
+  // 转换函数
+  const transformData = (data) => {
+    const result = [];
+    let sampleId = 1;
+
+    // 遍历原始数据,排除 total 属性
+    for (const key in data) {
+      if (key !== "total") {
+        const item = data[key];
+        result.push({
+          sampleId: sampleId.toString(),
+          value: item.p,
+          ewma: item.cl,
+          ucl: item.ucl,
+          lcl: item.lcl,
+        });
+        sampleId++;
+      }
+    }
+
+    return result;
+  };
+
+  // 转换后的数据
+  const formattedData = ref(transformData(resultData.data));
+  chartData.value = formattedData.value;
+};
+
+const chartRef = ref(null);
+const chartInstance = ref(null);
+
+const prepareData = () => {
+  let sampleIds = chartData.value.map((item) => item.sampleId);
+  let values = chartData.value.map((item) => item.value);
+  let ewmaValues = chartData.value.map((item) => item.ewma);
+  let uclValues = chartData.value.map((item) => item.ucl);
+  let lclValues = chartData.value.map((item) => item.lcl);
+
+  // 保留四位小数
+  values = values.map((num) => parseFloat(num.toFixed(4)));
+  ewmaValues = ewmaValues.map((num) => parseFloat(num.toFixed(4)));
+  uclValues = uclValues.map((num) => parseFloat(num.toFixed(4)));
+  lclValues = lclValues.map((num) => parseFloat(num.toFixed(4)));
+
+  return {
+    sampleIds,
+    values,
+    ewmaValues,
+    uclValues,
+    lclValues,
+  };
+};
+
+const initChart = (chartDom) => {
+  const myChart = echarts.init(chartDom);
+  const { sampleIds, values, ewmaValues, uclValues, lclValues } = prepareData();
+
+  const option = {
+    title: {
+      text: "P控制图",
+      left: "center",
+    },
+    tooltip: {
+      trigger: "axis",
+    },
+    xAxis: {
+      type: "category",
+      boundaryGap: true, // 不留白,从原点开始
+      data: sampleIds,
+    },
+    yAxis: {
+      type: "value",
+      // name: "EWMA值",
+    },
+    series: [
+      {
+        name: "数值",
+        type: "line",
+        // step: "start",
+        symbol: "circle", //将小圆点改成实心 不写symbol默认空心
+        symbolSize: 8,
+        data: values.map((value, index) => ({
+          value,
+          itemStyle: {
+            color:
+              value > uclValues[index] || value < lclValues[index]
+                ? "red"
+                : "blue",
+          },
+        })),
+      },
+      {
+        name: "均值",
+        type: "line",
+        showSymbol: false,
+        data: ewmaValues,
+        lineStyle: {
+          color: "green",
+        },
+      },
+      // {
+      //   name: "均值",
+      //   type: "line",
+      //   data: Array(sampleIds.length).fill(meanValue),
+      //   showSymbol: false,
+      //   lineStyle: {
+      //     color: "green",
+      //     type: "solid",
+      //   },
+      // },
+      {
+        name: "UCL",
+        type: "line",
+        data: uclValues,
+        showSymbol: false,
+        lineStyle: {
+          color: "red",
+          type: "dashed",
+        },
+      },
+      {
+        name: "LCL",
+        type: "line",
+        data: lclValues,
+        showSymbol: false,
+        lineStyle: {
+          color: "red",
+          type: "dashed",
+        },
+      },
+    ],
+    color: ["blue", "green", "red", "red", "black"],
+  };
+
+  myChart.setOption(option);
+  chartInstance.value = myChart;
+};
+
+const resizeChart = () => {
+  if (chartInstance.value) {
+    chartInstance.value.resize();
+  }
+};
+
+onMounted(() => {
+  window.addEventListener("resize", resizeChart);
+});
+
+watch(chartData, () => {
+  if (chartInstance.value) {
+    const { sampleIds, values, ewmaValues, uclValues, lclValues, meanValue } =
+      prepareData();
+    const option = {
+      title: [
+        {
+          text: `P控制图`,
+          left: "40%",
+        },
+      ],
+      xAxis: {
+        data: sampleIds,
+      },
+      series: [
+        {
+          data: values.map((value, index) => ({
+            value,
+            itemStyle: {
+              color:
+                value > uclValues[index] || value < lclValues[index]
+                  ? "red"
+                  : "blue",
+            },
+          })),
+        },
+        {
+          data: ewmaValues,
+        },
+        {
+          data: uclValues,
+        },
+        {
+          data: lclValues,
+        },
+        {
+          data: Array(sampleIds.length).fill(meanValue),
+        },
+      ],
+    };
+    chartInstance.value.setOption(option);
+  }
+});
+
+const init = () => {
+  nextTick(async () => {
+    await getTableData();
+    await initChart(chartRef.value);
+  });
+};
+
+// 暴露 init 方法
+defineExpose({
+  init,
+});
+</script>
+
+<style lang="scss" scoped>
+/* 样式可以根据需要进行调整 */
+.container1 {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  background-color: white;
+  .infobox {
+    width: 200px;
+    .header {
+      height: 120px;
+      border-bottom: 2px solid #00000010;
+      padding: 20px;
+    }
+    .body {
+      padding: 20px;
+    }
+  }
+  .databox {
+    flex: 1;
+    border-left: 2px solid #00000010;
+    .box {
+      height: 710px;
+      padding: 5px 20px;
+      display: flex;
+      flex-direction: column;
+      .illustrate {
+        padding: 20px 60px;
+      }
+      .tableTitle {
+        text-align: center;
+        margin: 10px 0;
+        padding-right: 40px;
+      }
+      .header {
+        margin-top: 20px;
+        //margin-left: 100px;
+        display: flex;
+        width: 100%;
+        height: auto;
+      }
+      //.title {
+      //  height: 50px;
+      //  display: flex;
+      //  align-items: center;
+      //  margin-bottom: 10px;
+      //  justify-content: space-between;
+      //  .btns {
+      //    display: flex;
+      //    align-items: center;
+      //    .btn {
+      //      height: 24px;
+      //      font-size: 14px;
+      //      margin: 0 5px;
+      //    }
+      //  }
+      //}
+      .info {
+        margin-top: 20px;
+        flex: 1;
+        height: 300px;
+      }
+    }
+  }
+}
+</style>

+ 13 - 0
src/views/analysis/process/index.vue

@@ -676,6 +676,9 @@
           <div class="info" v-if="value2 === 'X̅-S'">
             <XbarS ref="xbarSRef" :process="showLable" />
           </div>
+          <div class="info" v-if="value2 === 'P'">
+            <P ref="pRef" :process="showLable" />
+          </div>
         </div>
       </el-scrollbar>
     </div>
@@ -686,6 +689,7 @@
 import { ref } from "vue";
 import XbarR from "./Xbar-R.vue";
 import XbarS from "./Xbar-S-2.vue";
+import P from "./P.vue";
 import * as echarts from "echarts";
 import { useDictionaryStore } from "@/store";
 import {
@@ -712,6 +716,13 @@ const xbarSRefMethod = async () => {
     xbarSRef.value.init(tableData.value);
   }
 };
+const pRef = ref("pRef");
+const pRefMethod = async () => {
+  await nextTick();
+  if (pRef.value) {
+    pRef.value.init();
+  }
+};
 const year = ref("0");
 const currentOption = reactive({
   total: 0,
@@ -1096,6 +1107,8 @@ const changeSelect2 = () => {
   } else if (value2.value === "X̅-S") {
     console.log("X̅-S");
     xbarSRefMethod();
+  } else if (value2.value === "P") {
+    pRefMethod();
   }
 };