于洋 3 mēneši atpakaļ
vecāks
revīzija
10d69b00d5

+ 3 - 0
.vscode/settings.json

@@ -77,4 +77,7 @@
   "i18n-ally.localesPaths": [
     "src/lang"
   ],
+  "[vue]": {
+    "editor.defaultFormatter": "esbenp.prettier-vscode"
+  },
 }

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

@@ -36,3 +36,10 @@ export function updateData(data) {
     data,
   });
 }
+export function getTaskCode(data) {
+  return request({
+    url: "/api/v1/quality/task/list",
+    method: "post",
+    data,
+  });
+}

+ 2 - 0
src/api/spc/index.js

@@ -65,3 +65,5 @@ export function deleteRuleData(data) {
     data,
   });
 }
+
+

+ 2 - 2
src/components/Search/index.vue

@@ -59,13 +59,13 @@ const props = defineProps({
     type: Array,
   },
 });
-const emit = defineEmits(["dataList"]);
+const emit = defineEmits(["resetList", "dataList"]);
 const searchForm = ref({});
 const getData = () => {
   emit("dataList");
 };
 const reset = () => {
-  console.log(searchForm.value, "222");
+  emit("resetList");
 };
 const setSearchFrom = () => {
   props.searchOptions.forEach((option) => {});

+ 9 - 0
src/router/modules/analysis.ts

@@ -66,5 +66,14 @@ export default {
         icon: "Guide",
       },
     },
+    {
+      path: "charts",
+      component: () => import("@/views/charts/index.vue"),
+      name: "Charts",
+      meta: {
+        title: "图表分析",
+        icon: "Guide",
+      },
+    },
   ],
 };

+ 223 - 144
src/views/analysis/process/index.vue

@@ -19,25 +19,25 @@
       </div>
       <div class="body">
         <div class="text">
-          规格上限:{{ value ? JSON.parse(value).up : "-" }}
+          Xbar-UCL:{{ value ? JSON.parse(value).avgMax : "-" }}
         </div>
         <div class="text">
-          规格下限:{{ value ? JSON.parse(value).down : "-" }}
+          Xbar-MED:{{ value ? JSON.parse(value).avgMid : "-" }}
         </div>
         <div class="text">
-          计量单位:{{ value ? JSON.parse(value).unit : "-" }}
+          Xbar-LCL:{{ value ? JSON.parse(value).avgMin : "-" }}
         </div>
         <div class="text">
-          Xbar-UCL:{{ showData.avgMax ? showData.avgMax : "-" }}
+          R-UCL:{{ value ? JSON.parse(value).rangeMax : "-" }}
         </div>
         <div class="text">
-          Xbar-LCL:{{ showData.avgMin ? showData.avgMin : "0" }}
+          R-MED:{{ value ? JSON.parse(value).rangeMid : "-" }}
         </div>
         <div class="text">
-          R-UCL:{{ showData.rangeMax ? showData.rangeMax : "-" }}
+          R-LCL:{{ value ? JSON.parse(value).rangeMin : "-" }}
         </div>
         <div class="text">
-          R-LCL:{{ showData.rangeMin ? showData.rangeMin : "0" }}
+          计量单位:{{ value ? JSON.parse(value).unit : "-" }}
         </div>
       </div>
     </div>
@@ -49,6 +49,14 @@
               <div class="bg"></div>
               样本数据录入
             </div>
+            <div class="header" v-show="!addStatus && !editStatus">
+              <Search
+                :searchOptions="searchForm"
+                ref="searchRef"
+                @data-list="getTableData"
+                @reset-list="reset"
+              />
+            </div>
             <div class="btns">
               <!-- <el-button
                 v-if="!editStatus && !addStatus"
@@ -60,6 +68,7 @@
               <el-button
                 v-if="!addStatus && !editStatus"
                 type="primary"
+                size="small"
                 class="btn"
                 @click="changeaddstatus"
                 >新增</el-button
@@ -67,6 +76,7 @@
               <el-button
                 v-if="editStatus || addStatus"
                 type="success"
+                size="small"
                 class="btn"
                 @click="submit"
                 >确定</el-button
@@ -74,23 +84,11 @@
               <el-button
                 v-if="editStatus || addStatus"
                 type="info"
+                size="small"
                 class="btn"
                 @click="canceleOp"
                 >取消</el-button
-              ><span v-if="!addStatus && !editStatus" style="margin: 10px"
-                >年份:</span
               >
-              <el-date-picker
-                v-if="!addStatus && !editStatus"
-                v-model="year"
-                class="btn"
-                type="year"
-                style="width: 160px"
-                placeholder="Pick a year"
-                value-format="YYYY"
-                :clear-icon="''"
-                @change="getTableData"
-              />
             </div>
             <!-- 导入代码 -->
             <!-- <div class="btns">
@@ -163,7 +161,14 @@
                   ><span>{{ row.batchNo }}</span>
                 </template>
               </el-table-column>
-              <el-table-column align="center" :label="title">
+              <el-table-column width="100" prop="accuracys" label="数据">
+                <template #default="{ row }">
+                  <div v-for="(item, index) in row.accuracys" :key="index">
+                    <span>数值{{ index }}:{{ item }}</span>
+                  </div>
+                </template>
+              </el-table-column>
+              <!-- <el-table-column align="center" :label="title">
                 <el-table-column
                   align="center"
                   prop="accuracy1"
@@ -214,7 +219,8 @@
                     ><span>{{ row.accuracy5 }}</span>
                   </template>
                 </el-table-column> </el-table-column
-              ><el-table-column
+              > -->
+              <el-table-column
                 align="center"
                 prop="avg"
                 label="平均值"
@@ -266,6 +272,7 @@
                 <template #default="{ row }">
                   <el-button
                     type="primary"
+                    size="small"
                     class="btn"
                     @click="updataItem(row)"
                     style="height: 25px"
@@ -273,6 +280,7 @@
                   >
                   <el-button
                     type="info"
+                    size="small"
                     class="btn"
                     style="height: 25px"
                     @click="deleteSubmit(row.id)"
@@ -306,7 +314,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-           
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -323,7 +331,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-        
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -340,7 +348,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-     
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -358,7 +366,7 @@
                   <template #default="{ row }"
                     >
                     <el-input-number
-       
+
                       v-model="row.accuracy1"
                       :precision="2"
                       :step="0.01"
@@ -375,7 +383,7 @@
                   <template #default="{ row }"
                     >
                     <el-input-number
-          
+
                       v-model="row.accuracy2"
                       :precision="2"
                       :step="0.01"
@@ -391,7 +399,7 @@
                   <template #default="{ row }"
                     >
                     <el-input-number
-              
+
                       v-model="row.accuracy3"
                       :precision="2"
                       :step="0.01"
@@ -407,7 +415,7 @@
                   <template #default="{ row }"
                     >
                     <el-input-number
-          
+
                       v-model="row.accuracy4"
                       :precision="2"
                       :step="0.01"
@@ -423,7 +431,7 @@
                   <template #default="{ row }"
                     >
                     <el-input-number
-          
+
                       v-model="row.accuracy5"
                       :precision="2"
                       :step="0.01"
@@ -434,7 +442,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-            
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -445,7 +453,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-             
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -456,7 +464,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-              
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -471,7 +479,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-           
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -483,7 +491,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-    
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -495,7 +503,7 @@
                 <template #default="{ row }"
                   >
                   <el-input-number
-              
+
                     v-model="row.accuracy1"
                     :precision="2"
                     :step="0.01"
@@ -530,50 +538,45 @@
                   value-format="YYYY-MM-DD"
                 />
               </el-form-item>
+              <el-form-item label="任务编号" prop="qualityTaskId">
+                <el-select
+                  v-model="addData.qualityTaskId"
+                  @change="
+                    (value) => {
+                      taskChange(value);
+                    }
+                  "
+                >
+                  <el-option
+                    v-for="(item, index) in taskOption"
+                    :key="index"
+                    :label="item.taskCode"
+                    :value="item.id"
+                  />
+                </el-select>
+              </el-form-item>
               <el-form-item label="产品型号" prop="model">
-                <el-input v-model="addData.model" />
+                <el-input :disabled="true" v-model="addData.model" />
               </el-form-item>
               <el-form-item label="生产批号" prop="batchNo">
                 <el-input v-model="addData.batchNo" />
               </el-form-item>
-              <el-form-item label="数值1" prop="accuracy1">
-                <el-input-number
-                  :precision="2"
-                  :step="0.01"
-                  style="width: 100%"
-                  v-model="addData.accuracy1"
-                />
-              </el-form-item>
-              <el-form-item label="数值2" prop="accuracy2">
-                <el-input-number
-                  :precision="2"
-                  :step="0.01"
-                  v-model="addData.accuracy2"
-                  style="width: 100%"
-                />
-              </el-form-item>
-              <el-form-item label="数值3" prop="accuracy3">
-                <el-input-number
-                  :precision="2"
-                  :step="0.01"
-                  style="width: 100%"
-                  v-model="addData.accuracy3"
-                />
-              </el-form-item>
-              <el-form-item label="数值4" prop="accuracy4">
+              <el-form-item
+                v-for="(item, index) in addData.accuracys"
+                :label="'数值' + (index + 1)"
+                :key="index"
+                :rules="[
+                  {
+                    required: true,
+                    trigger: 'change',
+                  },
+                ]"
+              >
                 <el-input-number
                   :precision="2"
                   :step="0.01"
                   style="width: 100%"
-                  v-model="addData.accuracy4"
-                />
-              </el-form-item>
-              <el-form-item label="数值5" prop="accuracy5">
-                <el-input-number
-                  :precision="2"
-                  style="width: 100%"
-                  :step="0.01"
-                  v-model="addData.accuracy5"
+                  v-model="addData.accuracys[index]"
                 />
               </el-form-item>
               <!-- <el-form-item label="平均值" prop="avg">
@@ -615,14 +618,16 @@
 
             <el-button
               type="primary"
-              v-print="'#charts'"
+              v-print="'#print'"
               style="margin-left: 10px; height: 25px"
               >打 印</el-button
             >
           </div>
           <div class="info">
-            <div id="charts" :style="{ height: maxHeight / 2 + 'px' }"></div>
-            <div id="charts1" :style="{ height: maxHeight / 2 + 'px' }"></div>
+            <div id="print">
+              <div id="charts" :style="{ height: maxHeight / 2 + 'px' }"></div>
+              <div id="charts1" :style="{ height: maxHeight / 2 + 'px' }"></div>
+            </div>
           </div>
         </div>
       </el-scrollbar>
@@ -633,7 +638,14 @@
 <script setup>
 import * as echarts from "echarts";
 import { useDictionaryStore } from "@/store";
-import { getData, addDatas, deleteData, updateData } from "@/api/analysis";
+import {
+  getData,
+  addDatas,
+  deleteData,
+  updateData,
+  getTaskCode,
+} from "@/api/analysis";
+import Search from "@/components/Search/index.vue";
 const year = ref("0");
 const currentOption = reactive({
   total: 0,
@@ -642,11 +654,19 @@ const currentOption = reactive({
   pageSizes: [12],
 });
 const lableValue = ref("");
+const searchRef = ref(null);
+const getTaskOption = async () => {
+  const { data } = await getTaskCode({
+    operationCode: JSON.parse(value.value).value,
+  });
+  taskOption.value = data;
+};
 const getTableData = async () => {
   const { data, code, msg } = await getData({
+    ...searchRef.value.searchForm,
     pageNo: currentOption.page,
     pageSize: currentOption.limit,
-    yearStr: year.value,
+    // yearStr: year.value,
     operation: lableValue.value,
   });
   if (code == "200") {
@@ -662,6 +682,23 @@ const getTableData = async () => {
   }
   disabled.value = false;
 };
+const searchForm = [
+  {
+    label: "创建时间",
+    prop: "created",
+    type: "daterange",
+  },
+  {
+    label: "产品型号",
+    prop: "model",
+    type: "input",
+  },
+  {
+    label: "生产批号",
+    prop: "batchNo",
+    type: "input",
+  },
+];
 //编辑状态
 const editStatus = ref(false);
 const addStatus = ref(false);
@@ -690,8 +727,8 @@ const setY1value = () => {
 
   chartsOption1.value.series[0].data = Y1value.value;
 };
-const setX1array = () => {
-  X1array.value = [];
+const setX1array = async () => {
+  X1array.value = await [];
   tableData.value.forEach((item, index) => {
     X1array.value.push(index + 1);
   });
@@ -724,6 +761,12 @@ const addItem = {
   range: 0,
 };
 const rules = {
+  qualityTaskId: [
+    {
+      required: true,
+      trigger: "change",
+    },
+  ],
   dateStr: [
     {
       required: true,
@@ -817,38 +860,39 @@ const rules = {
 };
 const resItem = {
   // abnormal: "",
-  accuracy1: 0,
-  accuracy2: 0,
-  accuracy3: 0,
-  accuracy4: 0,
-  accuracy5: 0,
   analyseUser: "",
-  avg: 0,
   batchNo: "",
   checkDeviceNo: "",
   checkUser: "",
   dateStr: "",
   measure: "",
   model: "",
-  range: 0,
 };
 const addData = ref({
   // abnormal: "",
-  accuracy1: 0,
-  accuracy2: 0,
-  accuracy3: 0,
-  accuracy4: 0,
-  accuracy5: 0,
   analyseUser: "",
-  avg: 0,
   batchNo: "",
   checkDeviceNo: "",
   checkUser: "",
   dateStr: "",
   measure: "",
   model: "",
-  range: 0,
 });
+const accuracysSum = ref(0);
+const taskChange = (value) => {
+  taskOption.value.forEach((item) => {
+    if (item.id == value) {
+      addData.value.model = item.prodtModel;
+      accuracysSum.value = Number(item.processCount);
+      addData.value.accuracys = [];
+      let array = [];
+      for (let i = 0; i < accuracysSum.value; i++) {
+        array.push(0);
+      }
+      addData.value.accuracys = array;
+    }
+  });
+};
 const oldDataJSON = ref("");
 const showData = ref({});
 const url = ref(import.meta.env.VITE_APP_BASE_API + "/api/v1/spc/import");
@@ -857,29 +901,47 @@ const opOptions = ref([...dicts.spc_operation]);
 const setChart1Info = () => {
   // chartsOption1.value.title[0].text = `上限=${showData.value.avgMax ? showData.value.avgMax : "-"}`;
   // chartsOption1.value.title[0].text = `x̄=${showData.value.avgAvg ? showData.value.avgAvg : "-"}`;
-  chartsOption1.value.series[0].markLine.data[0].yAxis = showData.value.avgMax;
-  chartsOption1.value.series[0].markLine.data[0].label.formatter = `                          上限=${showData.value.avgMax ? showData.value.avgMax : "0"}`;
-  chartsOption1.value.series[0].markLine.data[1].yAxis = showData.value.avgMin
-    ? showData.value.avgMin
+  chartsOption1.value.series[0].markLine.data[0].yAxis = JSON.parse(
+    value.value
+  ).avgMax;
+  chartsOption1.value.series[0].markLine.data[0].label.formatter = `                          上限=${
+    JSON.parse(value.value).avgMax ? JSON.parse(value.value).avgMax : "0"
+  }`;
+  chartsOption1.value.series[0].markLine.data[1].yAxis = JSON.parse(value.value)
+    .avgMin
+    ? JSON.parse(value.value).avgMin
     : 0;
-  chartsOption1.value.series[0].markLine.data[1].label.formatter = `           下限=${showData.value.avgMin ? showData.value.avgMin : "0"}`;
-  chartsOption1.value.series[0].markLine.data[2].yAxis = showData.value.avgAvg;
-  chartsOption1.value.series[0].markLine.data[2].label.formatter = `x̄=${showData.value.avgAvg}`;
+  chartsOption1.value.series[0].markLine.data[1].label.formatter = `           下限=${JSON.parse(value.value).avgMin ? JSON.parse(value.value).avgMin : "0"}`;
+  chartsOption1.value.series[0].markLine.data[2].yAxis = JSON.parse(
+    value.value
+  ).avgMid;
+  chartsOption1.value.series[0].markLine.data[2].label.formatter = `x̄=${
+    JSON.parse(value.value).avgMid
+  }`;
   // chartsOption1.value.title[2].text = `下限=${showData.value.avgMin ? showData.value.avgMin : "0"}`;
 };
 const setChart2Info = () => {
   // chartsOption2.value.title[0].text = `上限=${showData.value.rangeMax ? showData.value.rangeMax : "-"}`;
   // chartsOption2.value.title[0].text = `R=${showData.value.rangeAvg ? showData.value.rangeAvg : "-"}`;
-  chartsOption2.value.series[0].markLine.data[0].yAxis =
-    showData.value.rangeMax;
-  chartsOption2.value.series[0].markLine.data[0].label.formatter = `                          上限=${showData.value.rangeMax ? showData.value.rangeMax : "0"}`;
-  chartsOption2.value.series[0].markLine.data[1].yAxis = showData.value.rangeMin
-    ? showData.value.rangeMin
+  chartsOption2.value.series[0].markLine.data[0].yAxis = JSON.parse(
+    value.value
+  ).rangeMax;
+  chartsOption2.value.series[0].markLine.data[0].label.formatter = `                          上限=${
+    JSON.parse(value.value).rangeMax ? JSON.parse(value.value).rangeMax : "0"
+  }`;
+  chartsOption2.value.series[0].markLine.data[1].yAxis = JSON.parse(value.value)
+    .rangeMin
+    ? JSON.parse(value.value).rangeMin
     : 0;
-  chartsOption2.value.series[0].markLine.data[1].label.formatter = `           下限=${showData.value.rangeMin ? showData.value.rangeMin : "0"}`;
-  chartsOption2.value.series[0].markLine.data[2].yAxis =
-    showData.value.rangeAvg;
-  chartsOption2.value.series[0].markLine.data[2].label.formatter = `x̄=${showData.value.rangeAvg}`;
+  chartsOption2.value.series[0].markLine.data[1].label.formatter = `           下限=${
+    JSON.parse(value.value).rangeMin ? JSON.parse(value.value).rangeMin : "0"
+  }`;
+  chartsOption2.value.series[0].markLine.data[2].yAxis = JSON.parse(
+    value.value
+  ).rangeMid;
+  chartsOption2.value.series[0].markLine.data[2].label.formatter = `x̄=${
+    JSON.parse(value.value).rangeMid
+  }`;
   // chartsOption2.value.title[2].text = `下限=${showData.value.rangeMin ? showData.value.rangeMin : "0"}`;
 };
 const setChart1 = () => {
@@ -915,13 +977,14 @@ const onSuccess = (res) => {
     ElMessage.success(msg);
   }
 };
-
+const taskOption = ref([]);
 const value = ref(opOptions.value[0].remark);
 const title = ref("调阻精度");
 
 const showLable = ref("调阻");
 const changeSelect = () => {
-  setTimeout(() => {
+  setTimeout(async () => {
+    getTaskOption();
     showLable.value = selectRef.value.currentPlaceholder;
     opOptions.value.forEach((item) => {
       if (item.dictLabel == showLable.value) {
@@ -942,8 +1005,8 @@ const changeSelect = () => {
         title.value = "调阻精度";
         break;
     }
-    getTableData();
-    chartsOption1.value.title[3].text = `${title.value}的Xbar-R控制图`;
+    await getTableData();
+    chartsOption1.value.title[0].text = `${title.value}的Xbar-R控制图`;
     // tableData.value.forEach((item) => {
     //   item.accuracy1 = 0;
     //   item.accuracy2 = 0;
@@ -1057,15 +1120,15 @@ const chartsOption1 = ref({
       symbol: "circle",
       itemStyle: {
         color: (params) => {
-          const dataIndex = params.dataIndex;
-          if (dataIndex == 0) {
+          const avg = JSON.parse(value.value);
+          const paramValue = Number(params.value);
+          if (
+            paramValue <= Number(avg.avgMax) &&
+            paramValue >= Number(avg.avgMin)
+          ) {
             return "rgb(26, 122, 240)";
           } else {
-            return tableData.value[dataIndex - 1]
-              ? tableData.value[dataIndex - 1].abnormal != "否"
-                ? "red"
-                : "rgb(26, 122, 240)"
-              : "rgb(26, 122, 240)";
+            return "red";
           }
         },
       },
@@ -1077,7 +1140,7 @@ const chartsOption1 = ref({
             yAxis: 0,
             label: {
               position: "end",
-              formatter: `上限=${showData.value.avgMax ? showData.value.avgMax : "-"}`,
+              formatter: `上限=${JSON.parse(value.value).avgMax ? JSON.parse(value.value).avgMax : "-"}`,
               color: "#333",
             },
             lineStyle: { type: "solid", color: "#333", width: 2 },
@@ -1087,7 +1150,7 @@ const chartsOption1 = ref({
             yAxis: 0,
             label: {
               position: "end",
-              formatter: `下限=${showData.value.avgMin ? showData.value.avgMin : "-"}`,
+              formatter: `下限=${JSON.parse(value.value).avgMin ? JSON.parse(value.value).avgMin : "-"}`,
               color: "#333",
             },
             lineStyle: {
@@ -1182,15 +1245,15 @@ const chartsOption2 = ref({
       symbol: "circle",
       itemStyle: {
         color: (params) => {
-          const dataIndex = params.dataIndex;
-          if (dataIndex == 0) {
+          const range = JSON.parse(value.value);
+          const paramValue = Number(params.value);
+          if (
+            paramValue <= Number(range.rangeMax) &&
+            paramValue >= Number(range.rangeMin)
+          ) {
             return "rgb(26, 122, 240)";
           } else {
-            return tableData.value[dataIndex - 1]
-              ? tableData.value[dataIndex - 1].abnormal != "否"
-                ? "red"
-                : "rgb(26, 122, 240)"
-              : "rgb(26, 122, 240)";
+            return "red";
           }
         },
       },
@@ -1202,7 +1265,7 @@ const chartsOption2 = ref({
             yAxis: 0,
             label: {
               position: "end",
-              formatter: `上限=${showData.value.rangeMax ? showData.value.rangeMax : "-"}`,
+              formatter: `上限=${JSON.parse(value.value).rangeMax ? JSON.parse(value.value).rangeMax : "-"}`,
               color: "#333",
             },
             lineStyle: { type: "solid", color: "#333", width: 2 },
@@ -1212,7 +1275,7 @@ const chartsOption2 = ref({
             yAxis: 0,
             label: {
               position: "end",
-              formatter: `下限=${showData.value.rangeMin ? showData.value.rangeMin : "-"}`,
+              formatter: `下限=${JSON.parse(value.value).rangeMin ? JSON.parse(value.value).rangeMin : "-"}`,
               color: "#333",
             },
             lineStyle: { type: "solid", color: "#333", width: 2 },
@@ -1312,6 +1375,7 @@ const reset = () => {
   addStatus.value = false;
   editStatus.value = false;
   addData.value = { ...resItem };
+  searchRef.value.searchForm = {};
   currentOption.value = {
     total: 0,
     page: 0,
@@ -1319,6 +1383,7 @@ const reset = () => {
     pageSizes: [12],
     operation: value.value,
   };
+  getTableData();
 };
 const setView = () => {
   setHeight();
@@ -1328,6 +1393,7 @@ const setView = () => {
   charts2.value.setOption(chartsOption2.value, true);
 };
 onMounted(() => {
+  getTaskOption();
   setHeight();
   year.value = new Date().getFullYear() + "";
   opOptions.value.forEach((item) => {
@@ -1350,6 +1416,11 @@ onBeforeUnmount(() => {
 </script>
 
 <style lang="scss" scoped>
+@media print {
+  #print {
+    margin-left: -18%;
+  }
+}
 .formStyle {
   width: 400px;
   margin: 20px auto;
@@ -1386,23 +1457,31 @@ onBeforeUnmount(() => {
         margin: 10px 0;
         padding-right: 40px;
       }
-      .title {
-        height: 30px;
+      .header {
+        margin-top: 20px;
+        //margin-left: 100px;
         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;
-          }
-        }
+        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;
       }

+ 93 - 31
src/views/analysis/spc/index.vue

@@ -35,6 +35,10 @@
             >
           </template>
         </el-table-column>
+        <el-table-column prop="processCount" label="工序采集点数" />
+        <el-table-column prop="centralValue" label="中心值" />
+        <el-table-column prop="upperLimit" label="上限" />
+        <el-table-column prop="floor" label="下限" />
         <el-table-column prop="created" label="创建时间" />
         <el-table-column
           align="center"
@@ -85,6 +89,9 @@
           label-width="auto"
           class="formStyle"
         >
+          <el-form-item label="任务编号" prop="taskCode">
+            <el-input v-model="formData.taskCode" />
+          </el-form-item>
           <el-form-item label="产品型号" prop="Index1">
             <el-select v-model="formData.Index1">
               <el-option
@@ -98,9 +105,9 @@
           <el-form-item label="工序名称" prop="Index2">
             <el-select v-model="formData.Index2">
               <el-option
-                v-for="(item, index) in opInfoData2"
+                v-for="(item, index) in opOptions"
                 :key="index"
-                :label="item.name"
+                :label="item.dictLabel"
                 :value="index"
               />
             </el-select>
@@ -117,6 +124,26 @@
           <el-form-item label="控制图" prop="chart">
             <el-input :disabled="true" v-model="formData.chart" />
           </el-form-item>
+          <el-form-item label="工序采集点数" prop="processCount">
+            <el-input-number
+              v-model="formData.processCount"
+              :min="1"
+              :step="1"
+            />
+          </el-form-item>
+          <el-form-item label="上限" prop="upperLimit">
+            <el-input-number v-model="formData.upperLimit" />
+          </el-form-item>
+          <el-form-item label="下限" prop="floor">
+            <el-input-number v-model="formData.floor" />
+          </el-form-item>
+          <el-form-item label="中心值" prop="centralValue">
+            <el-input-number
+              :min="formData.floor"
+              :max="formData.upperLimit"
+              v-model="formData.centralValue"
+            />
+          </el-form-item>
         </el-form>
         <div style="display: flex; justify-content: space-evenly">
           <el-button
@@ -143,13 +170,14 @@
 
 <script setup>
 import Search from "@/components/Search/index.vue";
-import { useSpcStore } from "@/store";
+import { useDictionaryStore, useSpcStore } from "@/store";
 import {
   getTableData,
   getBaseData,
   add,
   updateData,
   deleteData,
+
 } from "@/api/spc";
 defineOptions({
   name: "SPCrules",
@@ -166,7 +194,6 @@ const currentOption = reactive({
   total: 0,
   page: 1,
   limit: 10,
-
 });
 const showStatus = ref(true);
 const tableData = ref([]);
@@ -187,12 +214,8 @@ const searchForm = [
     prop: "prodtModel",
     type: "input",
   },
-  // {
-  //   label: "工序名称",
-  //   prop: "sss",
-  //   type: "select",
-  // },
 ];
+
 const maxHeight = ref(null);
 const setHeight = () => {
   maxHeight.value = document.querySelector(".table").clientHeight;
@@ -212,7 +235,6 @@ const toRuler = (row) => {
   router.push({ name: "SPCrules" });
 };
 const getData = async (obj) => {
-
   const { data, code } = await getTableData({
     ...searchRef.value.searchForm,
     pageNo: currentOption.page,
@@ -224,13 +246,22 @@ const getData = async (obj) => {
   }
 };
 const ruleFormRef = ref(null);
+const { dicts } = useDictionaryStore();
+const opOptions = ref([...dicts.spc_operation]);
 
 const rules = {
-  Index1: [
+  taskCode: [
     {
       required: true,
       trigger: "change",
+      message: "请输入任务编号",
+    },
+  ],
+  Index1: [
+    {
+      required: true,
       message: "请选择产品型号",
+      trigger: "change",
     },
   ],
   Index2: [
@@ -240,6 +271,13 @@ const rules = {
       trigger: "change",
     },
   ],
+  operationName: [
+    {
+      required: true,
+      trigger: "change",
+      message: "请选择工序名称",
+    },
+  ],
   source: [
     {
       required: true,
@@ -268,6 +306,34 @@ const rules = {
       trigger: "change",
     },
   ],
+  processCount: [
+    {
+      required: true,
+
+      trigger: "change",
+    },
+  ],
+  centralValue: [
+    {
+      required: true,
+
+      trigger: "change",
+    },
+  ],
+  upperLimit: [
+    {
+      required: true,
+
+      trigger: "change",
+    },
+  ],
+  floor: [
+    {
+      required: true,
+
+      trigger: "change",
+    },
+  ],
 };
 const opInfoData = ref([]);
 const toAdd = () => {
@@ -279,8 +345,8 @@ const setEditFormData = (row) => {
       formData.value.Index1 = index;
     }
   });
-  opInfoData.value[formData.value.Index1].operations.forEach((item, index) => {
-    if (item.code == row.operationCode) {
+  opOptions.value.forEach((item, index) => {
+    if (item.dictLabel == row.operationName) {
       formData.value.Index2 = index;
     }
   });
@@ -312,22 +378,19 @@ const toSubmit = async () => {
       if (valid) {
         const { data, code } = await add({
           chart: formData.value.chart,
-          operationCode:
-            opInfoData.value[formData.value.Index1].operations[
-              formData.value.Index2
-            ].code,
-          operationName:
-            opInfoData.value[formData.value.Index1].operations[
-              formData.value.Index2
-            ].name,
-
+          operationCode: opOptions.value[formData.value.Index2].dictValue,
+          operationName: opOptions.value[formData.value.Index2].dictLabel,
           prodtCode: opInfoData.value[formData.value.Index1].prodtCode,
           prodtModel: opInfoData.value[formData.value.Index1].prodtModel,
           prodtName: opInfoData.value[formData.value.Index1].prodtName,
           unit: opInfoData.value[formData.value.Index1].unit,
           param: formData.value.param,
-
           source: formData.value.source,
+          processCount: formData.value.processCount,
+          centralValue: formData.value.centralValue,
+          upperLimit: formData.value.upperLimit,
+          floor: formData.value.floor,
+          taskCode: formData.value.taskCode,
         });
         if (code == "200") {
           ElMessage.success("添加成功!");
@@ -343,14 +406,8 @@ const toSubmit = async () => {
       if (valid) {
         const { data, code } = await updateData({
           ...formData.value,
-          operationCode:
-            opInfoData.value[formData.value.Index1].operations[
-              formData.value.Index2
-            ].code,
-          operationName:
-            opInfoData.value[formData.value.Index1].operations[
-              formData.value.Index2
-            ].name,
+          operationCode: opOptions.value[formData.value.Index2].dictValue,
+          operationName: opOptions.value[formData.value.Index2].dictLabel,
           prodtCode: opInfoData.value[formData.value.Index1].prodtCode,
           prodtModel: opInfoData.value[formData.value.Index1].prodtModel,
           prodtName: opInfoData.value[formData.value.Index1].prodtName,
@@ -386,25 +443,30 @@ onMounted(() => {
   padding: 20px;
   display: flex;
   flex-direction: column;
+
   .header {
     width: 100%;
     height: auto;
   }
+
   .table {
     flex: 1;
     padding-bottom: 20px;
   }
+
   .formView {
     width: 100%;
     height: 100%;
     display: flex;
     flex-direction: column;
     align-items: center;
+
     .formTitle {
       text-align: center;
       font-size: 20px;
       margin-bottom: 20px;
     }
+
     .formStyle {
       width: 400px;
     }

+ 184 - 0
src/views/charts/index.vue

@@ -0,0 +1,184 @@
+<template>
+  <div ref="chartRef" style="width: 100%; height: 400px"></div>
+</template>
+
+<script setup>
+import { ref, onMounted, watch } from "vue";
+import * as echarts from "echarts";
+
+// 假设的数据
+const data = [
+  { sampleId: "1", value: 10, ewma: 10.5, ucl: 15, lcl: 2 },
+  { sampleId: "2", value: 9, ewma: 11.0, ucl: 16, lcl: 3 },
+  { sampleId: "3", value: 13, ewma: 11.5, ucl: 17, lcl: 4 },
+  { sampleId: "4", value: 28, ewma: 12.0, ucl: 18, lcl: 5 },
+  { sampleId: "5", value: 7, ewma: 12.5, ucl: 22, lcl: 6 },
+  { sampleId: "6", value: 15, ewma: 13.0, ucl: 34, lcl: 8 },
+  { sampleId: "7", value: 12, ewma: 13.5, ucl: 34, lcl: 8 },
+  { sampleId: "8", value: 14, ewma: 14.0, ucl: 34, lcl: 8 },
+  { sampleId: "9", value: 16, ewma: 14.5, ucl: 34, lcl: 8 },
+  { sampleId: "10", value: 4, ewma: 15.0, ucl: 34, lcl: 8 },
+];
+
+const chartRef = ref(null);
+const chartInstance = ref(null);
+
+const prepareData = () => {
+  const sampleIds = data.map((item) => item.sampleId);
+  const values = data.map((item) => item.value);
+  const ewmaValues = data.map((item) => item.ewma);
+  const uclValues = data.map((item) => item.ucl);
+  const lclValues = data.map((item) => item.lcl);
+  const meanValue =
+    data.reduce((acc, item) => acc + item.value, 0) / data.length;
+
+  return {
+    sampleIds,
+    values,
+    ewmaValues,
+    uclValues,
+    lclValues,
+    meanValue,
+  };
+};
+
+const initChart = (chartDom) => {
+  const myChart = echarts.init(chartDom);
+  const { sampleIds, values, ewmaValues, uclValues, lclValues, meanValue } =
+    prepareData();
+
+  const option = {
+    title: {
+      text: "EWMA 控制图",
+    },
+    tooltip: {
+      trigger: "axis",
+    },
+    xAxis: {
+      type: "category",
+      boundaryGap: false, // 不留白,从原点开始
+      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: "EWMA",
+      //   type: "line",
+      //   step: "start",
+      //   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",
+        step: "start",
+        data: uclValues,
+        showSymbol: false,
+        lineStyle: {
+          color: "red",
+          type: "dashed",
+        },
+      },
+      {
+        name: "LCL",
+        type: "line",
+        step: "start",
+        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(() => {
+  initChart(chartRef.value);
+  window.addEventListener("resize", resizeChart);
+});
+
+watch(data, () => {
+  if (chartInstance.value) {
+    const { sampleIds, values, ewmaValues, uclValues, lclValues, meanValue } =
+      prepareData();
+    const option = {
+      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);
+  }
+});
+</script>
+
+<style scoped>
+/* 样式可以根据需要进行调整 */
+</style>