Kaynağa Gözat

先提交一下,避免AI乱来

wukai 1 ay önce
ebeveyn
işleme
09e1197e35
2 değiştirilmiş dosya ile 1277 ekleme ve 0 silme
  1. 44 0
      src/api/lean/cap.js
  2. 1233 0
      src/views/lean/cap/index.vue

+ 44 - 0
src/api/lean/cap.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询白坯布重量分析列表
+export function listCap(query) {
+    return request({
+        url: '/lean/cap/list',
+        method: 'get',
+        params: query
+    })
+}
+
+// 查询白坯布重量分析详细
+export function getCap(bwId) {
+    return request({
+        url: '/lean/cap/' + bwId,
+        method: 'get'
+    })
+}
+
+// 新增白坯布重量分析
+export function addCap(data) {
+    return request({
+        url: '/lean/cap',
+        method: 'post',
+        data: data
+    })
+}
+
+// 修改白坯布重量分析
+export function updateCap(data) {
+    return request({
+        url: '/lean/cap',
+        method: 'put',
+        data: data
+    })
+}
+
+// 删除白坯布重量分析
+export function delCap(bwId) {
+    return request({
+        url: '/lean/cap/' + bwId,
+        method: 'delete'
+    })
+}

+ 1233 - 0
src/views/lean/cap/index.vue

@@ -0,0 +1,1233 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="测量时间" prop="dataTime">
+        <el-date-picker clearable
+                        v-model="queryParams.dataTime"
+                        type="date"
+                        value-format="YYYY-MM-DD"
+                        placeholder="请选择测量时间">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="目标值" prop="targetValue">
+        <el-input
+            v-model="queryParams.targetValue"
+            placeholder="请输入目标值"
+            clearable
+            @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+            type="primary"
+            plain
+            icon="Plus"
+            @click="handleAdd"
+        >新增
+        </el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="capList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center"/>
+      <el-table-column label="测量时间" align="center" prop="dataTime" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.dataTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="目标值" align="center" prop="targetValue"/>
+      <el-table-column label="误差范围" align="center" prop="toleranceRange">
+        <template #default="scope">
+          <span>±{{ scope.row.toleranceRange !== null ? (scope.row.toleranceRange + '%') : '' }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="误差值" align="center" prop="toleranceValue"/>
+      <!--      <el-table-column label="测量值" align="center" prop="measuredValue" />-->
+      <el-table-column label="上限过程能力指数CPU" align="center" prop="cpuValue"/>
+      <el-table-column label="下限过程能力指数CPL" align="center" prop="cplValue"/>
+      <el-table-column label="实际过程能力指数CPK" align="center" prop="cpkValue"/>
+      <el-table-column label="标准差" align="center" prop="stdDeviation"/>
+      <el-table-column label="平均值" align="center" prop="meanValue"/>
+      <el-table-column label="最大值" align="center" prop="maxValue"/>
+      <el-table-column label="最小值" align="center" prop="minValue"/>
+      <el-table-column label="规格上限" align="center" prop="usl"/>
+      <el-table-column label="规格下限" align="center" prop="lsl"/>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button link type="primary" icon="View" @click="handleView(scope.row)">查看</el-button>
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)">修改</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+        v-show="total>0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+    />
+
+    <!-- 添加或修改白坯布重量分析对话框 -->
+    <el-dialog :title="title" v-model="open" style="width: 1366px;height: 768px;" append-to-body>
+      <el-form ref="capRef" :model="form" :rules="rules" label-width="125px">
+        <el-row :gutter="20">
+          <el-col :span="8">
+            <el-form-item label="测量时间" prop="dataTime">
+              <el-date-picker clearable
+                              v-model="form.dataTime"
+                              type="date"
+                              value-format="YYYY-MM-DD"
+                              placeholder="请选择测量时间">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="目标值" prop="targetValue">
+              <el-input-number v-model="form.targetValue" placeholder="请输入目标值" :min="0" :precision="0"
+                               controls-position="right"/>
+            </el-form-item>
+          </el-col>
+          <el-col :span="8">
+            <el-form-item label="偏差" prop="toleranceRange">
+              <div style="display: flex; align-items: center;">
+                <span style="margin-right: 5px;">±</span>
+                <el-input-number v-model="form.toleranceRange" placeholder="" :min="0" :precision="0"
+                                 controls-position="right" style="flex: 1;"/>
+                <span style="margin-left: 5px;">%</span>
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <!--        <el-form-item label="测量值" prop="measuredValue">-->
+        <!--          <el-input v-model="form.measuredValue" type="textarea" placeholder="测量值将通过子表录入并自动转换为JSON数组" :disabled="true" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="上限过程能力指数CPU" prop="cpuValue">-->
+        <!--          <el-input v-model="form.cpuValue" placeholder="请输入上限过程能力指数CPU" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="下限过程能力指数CPL" prop="cplValue">-->
+        <!--          <el-input v-model="form.cplValue" placeholder="请输入下限过程能力指数CPL" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="实际过程能力指数CPK" prop="cpkValue">-->
+        <!--          <el-input v-model="form.cpkValue" placeholder="请输入实际过程能力指数CPK" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="标准差" prop="stdDeviation">-->
+        <!--          <el-input v-model="form.stdDeviation" placeholder="请输入标准差" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="平均值" prop="meanValue">-->
+        <!--          <el-input v-model="form.meanValue" placeholder="请输入平均值" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="最大值" prop="maxValue">-->
+        <!--          <el-input v-model="form.maxValue" placeholder="请输入最大值" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="最小值" prop="minValue">-->
+        <!--          <el-input v-model="form.minValue" placeholder="请输入最小值" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="规格上限" prop="usl">-->
+        <!--          <el-input v-model="form.usl" placeholder="请输入规格上限" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="规格下限" prop="lsl">-->
+        <!--          <el-input v-model="form.lsl" placeholder="请输入规格下限" />-->
+        <!--        </el-form-item>-->
+        <!--        <el-form-item label="备注" prop="remark">-->
+        <!--          <el-input v-model="form.remark" placeholder="请输入备注" />-->
+        <!--        </el-form-item>-->
+
+        <!-- 子表录入测量值 -->
+        <el-divider content-position="center">测量值录入</el-divider>
+        <div style="margin-bottom: 10px;">
+          <el-button type="primary" icon="Plus" @click="handleAddMeasuredValueGroup">添加测量值(每行10个)</el-button>
+          <el-button type="danger" icon="Delete" @click="handleDeleteMeasuredValue">删除选中</el-button>
+        </div>
+        <el-table :data="measuredValueList" :row-class-name="rowMeasuredValueIndex"
+                  @selection-change="handleMeasuredValueSelectionChange" ref="measuredValueTable"
+                  style="height: 430px; overflow-y: auto;">
+          <el-table-column type="selection" width="40" align="center"/>
+          <el-table-column label="测量值1" prop="value1">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value1"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值2" prop="value2">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value2"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值3" prop="value3">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value3"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值4" prop="value4">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value4"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值5" prop="value5">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value5"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值6" prop="value6">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value6"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值7" prop="value7">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value7"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值8" prop="value8">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value8"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值9" prop="value9">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value9"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="测量值10" prop="value10">
+            <template #default="scope">
+              <el-input-number
+                  v-model="scope.row.value10"
+                  placeholder="请输入"
+                  controls-position="right"
+                  style="width: 100%"
+                  @change="handleMeasuredValueChanged"
+              />
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" width="60" align="center">
+            <template #default="scope">
+              <el-button
+                  icon="Delete"
+                  @click="deleteSingleMeasuredValue(scope.$index)"
+                  circle
+                  size="small"
+              ></el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 查看白坯布重量分析对话框 -->
+    <el-dialog :title="title" v-model="viewOpen" fullscreen append-to-body>
+      <div style="height: 100%; display: flex; flex-direction: column;">
+        <!-- 图表和信息区域 -->
+        <div style="height: 300px; flex-shrink: 0; margin-bottom: 15px;">
+          <el-row :gutter="15" style="height: 100%;">
+            <el-col :span="16" style="height: 100%;">
+              <div style="width: 100%; height: 100%;" ref="chartContainerRef"></div>
+            </el-col>
+            <el-col :span="8" style="height: 100%; display: flex; flex-direction: column;">
+              <div style="height: 45%; margin-bottom: 15px;">
+                <el-descriptions title="基本信息" :column="2" border size="small" style="height: 100%;">
+                  <el-descriptions-item label="测量时间">{{ parseTime(viewForm.dataTime, '{y}-{m}-{d}') }}</el-descriptions-item>
+                  <el-descriptions-item label="目标值">{{ viewForm.targetValue }}</el-descriptions-item>
+                  <el-descriptions-item label="误差范围">±{{ viewForm.toleranceRange }}%</el-descriptions-item>
+                  <el-descriptions-item label="误差值">{{ viewForm.toleranceValue }}</el-descriptions-item>
+                  <el-descriptions-item label="规格上限">{{ viewForm.usl }}</el-descriptions-item>
+                  <el-descriptions-item label="规格下限">{{ viewForm.lsl }}</el-descriptions-item>
+                </el-descriptions>
+              </div>
+              <div style="height: 55%;">
+                <el-descriptions title="统计信息" :column="2" border size="small" style="height: 100%;">
+                  <el-descriptions-item label="平均值">{{ viewForm.meanValue }}</el-descriptions-item>
+                  <el-descriptions-item label="最大值">{{ viewForm.maxValue }}</el-descriptions-item>
+                  <el-descriptions-item label="最小值">{{ viewForm.minValue }}</el-descriptions-item>
+                  <el-descriptions-item label="标准差">{{ viewForm.stdDeviation }}</el-descriptions-item>
+                  <el-descriptions-item label="上限过程能力指数CPU">{{ viewForm.cpuValue }}</el-descriptions-item>
+                  <el-descriptions-item label="下限过程能力指数CPL">{{ viewForm.cplValue }}</el-descriptions-item>
+                  <el-descriptions-item label="实际过程能力指数CPK" :span="2">
+                    {{ viewForm.cpkValue }}
+                  </el-descriptions-item>
+                </el-descriptions>
+              </div>
+            </el-col>
+          </el-row>
+        </div>
+
+        <!-- 表格区域 -->
+        <div style="flex: 1; overflow: hidden;">
+          <el-row :gutter="15" style="height: 100%;">
+            <el-col :span="10" style="height: 100%; display: flex; flex-direction: column;">
+              <div style="font-size: 14px; font-weight: bold; margin-bottom: 10px;">CPK过程能力评价标准</div>
+              <div style="flex: 1; overflow: auto;">
+                <el-table :data="cpkEvaluation" border :row-class-name="cpkTableRowClassName" size="mini" style="font-size: 12px;">
+                  <el-table-column prop="cpk" label="Cpk值" ></el-table-column>
+                  <el-table-column prop="level" label="等级" width="70"></el-table-column>
+                  <el-table-column prop="evaluation" label="过程能力评价"></el-table-column>
+                  <el-table-column prop="defectRate" label="大约对应不良率"></el-table-column>
+                  <el-table-column prop="description" label="说明" width="320"></el-table-column>
+                </el-table>
+              </div>
+            </el-col>
+            <el-col :span="14" style="height: 100%; display: flex; flex-direction: column;">
+              <div style="font-size: 14px; font-weight: bold; margin-bottom: 10px;">标准差水平评估标准</div>
+              <div style="flex: 1; overflow: auto;">
+                <el-table :data="calculatedStdDeviationEvaluation" border :row-class-name="stdDeviationTableRowClassName" size="mini" style="font-size: 12px;">
+                  <el-table-column prop="level" label="标准差水平"></el-table-column>
+                  <el-table-column prop="stdValue" label="标准差数值"></el-table-column>
+                  <el-table-column prop="cpk" label="Cpk值" width="80"></el-table-column>
+                  <el-table-column prop="evaluation" label="过程能力评价"></el-table-column>
+                  <el-table-column prop="stability" label="稳定性状态"></el-table-column>
+                  <el-table-column prop="defectRate" label="大约不良率"></el-table-column>
+                  <el-table-column prop="description" label="含义与行动建议" width="420"></el-table-column>
+                </el-table>
+              </div>
+            </el-col>
+          </el-row>
+        </div>
+      </div>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="viewOpen = false">关 闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="Cap">
+import * as echarts from 'echarts';
+import {addCap, delCap, getCap, listCap, updateCap} from "@/api/lean/cap";
+
+const {proxy} = getCurrentInstance();
+
+const capList = ref([]);
+const open = ref(false);
+const viewOpen = ref(false); // 查看详情弹窗
+const chartContainerRef = ref(null); // 图表容器引用
+let chartInstance = null; // 保存图表实例
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const title = ref("");
+// 子表相关变量
+const measuredValueList = ref([]);
+const checkedMeasuredValues = ref([]);
+// 查看详情相关变量
+const viewForm = ref({});
+const measuredValues = ref([]); // 解析后的测量值数组
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    dataTime: null,
+    targetValue: null,
+    toleranceRange: null,
+    toleranceValue: null,
+    measuredValue: null,
+    cpuValue: null,
+    cplValue: null,
+    cpkValue: null,
+    stdDeviation: null,
+    meanValue: null,
+    maxValue: null,
+    minValue: null,
+    usl: null,
+    lsl: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null,
+    remark: null
+  },
+  rules: {
+    dataTime: [
+      {required: true, message: "测量时间不能为空", trigger: "blur"}
+    ],
+    targetValue: [
+      {required: true, message: "目标值不能为空", trigger: "blur"}
+    ],
+    toleranceRange: [
+      {required: true, message: "误差范围不能为空", trigger: "blur"}
+    ],
+    measuredValue: [
+      {required: true, message: "测量值不能为空", trigger: "blur"}
+    ],
+  },
+  // CPK评价标准数据
+  cpkEvaluation: [
+    {
+      cpk: "Cpk < 1.0",
+      level: "不足",
+      evaluation: "过程能力严重不足",
+      defectRate: "> 2700 PPM",
+      description: "不可接受。必须立即改进。"
+    },
+    {
+      cpk: "1.0 ≤ Cpk < 1.33",
+      level: "尚可",
+      evaluation: "过程能力尚可",
+      defectRate: "~ 63 PPM",
+      description: "需要加强监控和改善。"
+    },
+    {
+      cpk: "1.33 ≤ Cpk < 1.67",
+      level: "良好",
+      evaluation: "过程能力充足",
+      defectRate: "~ 0.57 PPM",
+      description: "对于大多数行业而言,这是一个良好且可接受的目标。"
+    },
+    {
+      cpk: "Cpk ≥ 1.67",
+      level: "优秀",
+      evaluation: "过程能力很高",
+      defectRate: "~ 0.00034 PPM",
+      description: "达到“六西格玛”水平的标志。世界级制造水平。"
+    }
+  ]
+});
+
+const {queryParams, form, rules, cpkEvaluation} = toRefs(data);
+
+// 标准差评价标准数据
+const stdDeviationEvaluation = [
+  {
+    level: "世界级",
+    stdValue: "7.5 克",
+    cpk: "2.0",
+    evaluation: "过剩",
+    stability: "极其稳定",
+    defectRate: "~ 0.001 PPM",
+    description: "过程波动仅占公差带的17%。稳定性极佳,可考虑缩小公差或降低成本。"
+  },
+  {
+    level: "优秀",
+    stdValue: "~ 11.3 克",
+    cpk: "1.33",
+    evaluation: "充足",
+    stability: "高度稳定",
+    defectRate: "~ 63 PPM",
+    description: "行业优秀水平。波动可控,过程可靠,是优质企业追求的目标。"
+  },
+  {
+    level: "最低可接受",
+    stdValue: "15 克",
+    cpk: "1.0",
+    evaluation: "勉强达标",
+    stability: "基本稳定",
+    defectRate: "~ 2700 PPM",
+    description: "过程波动占公差带的1/3。如履薄冰,需严密监控,否则极易出界。"
+  },
+  {
+    level: "不足",
+    stdValue: "22.5 克",
+    cpk: "~ 0.67",
+    evaluation: "不足",
+    stability: "不稳定",
+    defectRate: "~ 45500 PPM",
+    description: "波动已占公差带的一半。必须采取措施,改进过程。"
+  },
+  {
+    level: "严重不足",
+    stdValue: "30 克",
+    cpk: "0.5",
+    evaluation: "严重不足",
+    stability: "极度不稳定",
+    defectRate: "> 66000 PPM",
+    description: "过程波动极大,失控状态。产品质量无法保证,急需全面整改。"
+  }
+];
+
+/** 查询白坯布重量分析列表 */
+function getList() {
+  loading.value = true;
+  listCap(queryParams.value).then(response => {
+    capList.value = response.rows;
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+// 取消按钮
+function cancel() {
+  open.value = false;
+  reset();
+}
+
+// 表单重置
+function reset() {
+  form.value = {
+    bwId: null,
+    dataTime: null,
+    dataType: null,
+    targetValue: null,
+    toleranceRange: null,
+    toleranceValue: null,
+    measuredValue: null,
+    cpuValue: null,
+    cplValue: null,
+    cpkValue: null,
+    stdDeviation: null,
+    meanValue: null,
+    maxValue: null,
+    minValue: null,
+    usl: null,
+    lsl: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null,
+    remark: null
+  };
+  measuredValueList.value = [];
+  proxy.resetForm("capRef");
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.bwId);
+  single.value = selection.length != 1;
+  multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+function handleAdd() {
+  reset();
+  open.value = true;
+  title.value = "添加白坯布重量分析";
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  reset();
+  const _bwId = row.bwId || ids.value;
+  getCap(_bwId).then(response => {
+    form.value = response.data;
+    // 解析测量值JSON数组
+    try {
+      if (form.value.measuredValue) {
+        // 支持两种格式:简单数组格式 [1,2,3,4,5] 和对象数组格式 [{value: 1}, {value: 2}]
+        const parsed = JSON.parse(form.value.measuredValue);
+        if (Array.isArray(parsed)) {
+          if (parsed.length > 0 && typeof parsed[0] === 'object') {
+            // 对象数组格式 [{value: 1}, {value: 2}]
+            // 转换为每行10个的格式
+            measuredValueList.value = [];
+            for (let i = 0; i < parsed.length; i += 10) {
+              let obj = {};
+              for (let j = 1; j <= 10; j++) {
+                if (parsed[i + j - 1] !== undefined) {
+                  obj[`value${j}`] = parsed[i + j - 1].value || parsed[i + j - 1];
+                } else {
+                  obj[`value${j}`] = null;
+                }
+              }
+              measuredValueList.value.push(obj);
+            }
+
+            // 保存解析后的测量值用于查看
+            measuredValues.value = parsed.map(item =>
+              typeof item === 'object' ? item.value : item
+            );
+          } else if (parsed.length > 0 && typeof parsed[0] === 'number') {
+            // 简单数组格式 [1,2,3,4,5]
+            // 转换为每行10个的格式
+            measuredValueList.value = [];
+            for (let i = 0; i < parsed.length; i += 10) {
+              let obj = {};
+              for (let j = 1; j <= 10; j++) {
+                obj[`value${j}`] = parsed[i + j - 1] !== undefined ? parsed[i + j - 1] : null;
+              }
+              measuredValueList.value.push(obj);
+            }
+
+            // 保存解析后的测量值用于查看
+            measuredValues.value = [...parsed];
+          } else {
+            // 空数组或其他情况
+            measuredValueList.value = [];
+            measuredValues.value = [];
+          }
+        }
+      }
+    } catch (e) {
+      console.error("解析测量值JSON失败", e);
+      measuredValueList.value = [];
+      measuredValues.value = [];
+    }
+    open.value = true;
+    title.value = "修改白坯布重量分析";
+
+    // 加载数据后计算统计值
+    nextTick(() => {
+      calculateStatistics();
+    });
+  });
+}
+
+/** 查看按钮操作 */
+function handleView(row) {
+  viewForm.value = {...row};
+
+  // 解析测量值JSON数组
+  try {
+    if (viewForm.value.measuredValue) {
+      const parsed = JSON.parse(viewForm.value.measuredValue);
+      if (Array.isArray(parsed)) {
+        if (parsed.length > 0 && typeof parsed[0] === 'object') {
+          // 对象数组格式 [{value: 1}, {value: 2}]
+          measuredValues.value = parsed.map(item =>
+            typeof item === 'object' ? item.value : item
+          );
+        } else if (parsed.length > 0 && typeof parsed[0] === 'number') {
+          // 简单数组格式 [1,2,3,4,5]
+          measuredValues.value = [...parsed];
+        } else {
+          measuredValues.value = [];
+        }
+      }
+    }
+  } catch (e) {
+    console.error("解析测量值JSON失败", e);
+    measuredValues.value = [];
+  }
+
+  viewOpen.value = true;
+  title.value = "查看白坯布重量分析";
+
+  // 在弹窗打开后绘制图表
+  nextTick(() => {
+    setTimeout(() => {
+      drawChart();
+    }, 100);
+  });
+}
+
+/** 提交按钮 */
+function submitForm() {
+  proxy.$refs["capRef"].validate(valid => {
+    if (valid) {
+      // 计算误差值:目标值*(1+误差范围%) - 目标值*(1-误差范围%)
+      if (form.value.targetValue !== null && form.value.toleranceRange !== null) {
+        const upperLimit = form.value.targetValue * (1 + form.value.toleranceRange / 100);
+        const lowerLimit = form.value.targetValue * (1 - form.value.toleranceRange / 100);
+        form.value.toleranceValue = (upperLimit - lowerLimit).toFixed(4);
+      }
+
+      // 将测量值子表数据转换为简单数组格式 [1,2,3,4,5]
+      let simpleArray = [];
+
+      // 遍历所有行,收集所有非空的测量值
+      measuredValueList.value.forEach(row => {
+        for (let i = 1; i <= 10; i++) {
+          const value = row[`value${i}`];
+          if (value !== null && value !== undefined) {
+            simpleArray.push(value);
+          }
+        }
+      });
+
+      form.value.measuredValue = JSON.stringify(simpleArray);
+
+      if (form.value.bwId != null) {
+        updateCap(form.value).then(response => {
+          proxy.$modal.msgSuccess("修改成功");
+          open.value = false;
+          getList();
+        });
+      } else {
+        addCap(form.value).then(response => {
+          proxy.$modal.msgSuccess("新增成功");
+          open.value = false;
+          getList();
+        });
+      }
+    }
+  });
+}
+
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _bwIds = row.bwId || ids.value;
+  proxy.$modal.confirm('是否确认删除白坯布重量分析编号为"' + _bwIds + '"的数据项?').then(function () {
+    return delCap(_bwIds);
+  }).then(() => {
+    getList();
+    proxy.$modal.msgSuccess("删除成功");
+  }).catch(() => {
+  });
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('lean/cap/export', {
+    ...queryParams.value
+  }, `cap_${new Date().getTime()}.xlsx`)
+}
+
+// 子表相关函数
+/** 测量值序号 */
+function rowMeasuredValueIndex({row, rowIndex}) {
+  row.index = rowIndex + 1;
+}
+
+/** 测量值添加按钮操作 */
+function handleAddMeasuredValue() {
+  let obj = {};
+  obj.value = null;
+  obj.remark = "";
+  measuredValueList.value.push(obj);
+}
+
+/** 测量值添加按钮操作(每行10个) */
+function handleAddMeasuredValueGroup() {
+  let obj = {};
+  // 使用目标值作为默认值,如果目标值为空则使用null
+  const defaultValue = form.value.targetValue !== null ? form.value.targetValue : null;
+  obj.value1 = defaultValue;
+  obj.value2 = defaultValue;
+  obj.value3 = defaultValue;
+  obj.value4 = defaultValue;
+  obj.value5 = defaultValue;
+  obj.value6 = defaultValue;
+  obj.value7 = defaultValue;
+  obj.value8 = defaultValue;
+  obj.value9 = defaultValue;
+  obj.value10 = defaultValue;
+  measuredValueList.value.push(obj);
+}
+
+/** 测量值删除按钮操作 */
+function handleDeleteMeasuredValue() {
+  if (checkedMeasuredValues.value.length == 0) {
+    proxy.$modal.msgError("请先选择要删除的测量值数据");
+  } else {
+    const measuredValues = measuredValueList.value;
+    const checkedValues = checkedMeasuredValues.value;
+    measuredValueList.value = measuredValues.filter(function (item) {
+      return checkedValues.indexOf(item.index) == -1
+    });
+
+    // 删除后重新计算统计值
+    calculateStatistics();
+  }
+}
+
+/** 删除单个测量值 */
+function deleteSingleMeasuredValue(index) {
+  measuredValueList.value.splice(index, 1);
+  // 重新计算统计值
+  calculateStatistics();
+}
+
+// 根据CPK值确定行的类名
+function tableRowClassName({row, rowIndex}) {
+  return '';
+}
+
+// CPK评价表格行类名
+function cpkTableRowClassName({row, rowIndex}) {
+  // 根据当前viewForm中的cpkValue值来确定应该高亮哪一行
+  if (viewForm.value.cpkValue !== null && viewForm.value.cpkValue !== undefined) {
+    const cpkValue = parseFloat(viewForm.value.cpkValue);
+
+    if (cpkValue < 1.0 && rowIndex === 0) {
+      return 'cpk-current-row'; // Cpk < 1.0 对应第一行
+    } else if (cpkValue >= 1.0 && cpkValue < 1.33 && rowIndex === 1) {
+      return 'cpk-current-row'; // 1.0 ≤ Cpk < 1.33 对应第二行
+    } else if (cpkValue >= 1.33 && cpkValue < 1.67 && rowIndex === 2) {
+      return 'cpk-current-row'; // 1.33 ≤ Cpk < 1.67 对应第三行
+    } else if (cpkValue >= 1.67 && rowIndex === 3) {
+      return 'cpk-current-row'; // Cpk ≥ 1.67 对应第四行
+    }
+  }
+  return '';
+}
+
+// 标准差评价表格行类名
+function stdDeviationTableRowClassName({row, rowIndex}) {
+  // 根据当前viewForm中的stdDeviation值来确定应该高亮哪一行
+  if (viewForm.value.stdDeviation !== null && viewForm.value.stdDeviation !== undefined) {
+    const stdDeviation = parseFloat(viewForm.value.stdDeviation);
+
+    // 获取各个等级的标准差阈值
+    const worldClassLimit = parseFloat(calculateStdDevByCpk("2.0"));
+    const excellentLimit = parseFloat(calculateStdDevByCpk("1.33"));
+    const acceptableLimit = parseFloat(calculateStdDevByCpk("1.0"));
+    const insufficientLimit = parseFloat(calculateStdDevByCpk("0.67"));
+
+    // 确定当前标准差值对应的等级行
+    if (stdDeviation <= worldClassLimit && rowIndex === 0) {
+      return 'cpk-current-row'; // 世界级对应第一行
+    } else if (stdDeviation > worldClassLimit && stdDeviation <= excellentLimit && rowIndex === 1) {
+      return 'cpk-current-row'; // 优秀级对应第二行
+    } else if (stdDeviation > excellentLimit && stdDeviation <= acceptableLimit && rowIndex === 2) {
+      return 'cpk-current-row'; // 最低可接受对应第三行
+    } else if (stdDeviation > acceptableLimit && stdDeviation <= insufficientLimit && rowIndex === 3) {
+      return 'cpk-current-row'; // 不足对应第四行
+    } else if (stdDeviation > insufficientLimit && rowIndex === 4) {
+      return 'cpk-current-row'; // 严重不足对应第五行
+    }
+  }
+  return '';
+}
+
+/** 测量值复选框选中数据 */
+function handleMeasuredValueSelectionChange(selection) {
+  checkedMeasuredValues.value = selection.map(item => item.index)
+}
+
+/** 测量值变化时自动计算统计值 */
+function handleMeasuredValueChanged() {
+  calculateStatistics();
+}
+
+/** 计算统计值 */
+function calculateStatistics() {
+  // 获取所有有效的测量值
+  let validValues = [];
+
+  // 遍历所有行,收集所有非空的测量值
+  measuredValueList.value.forEach(row => {
+    for (let i = 1; i <= 10; i++) {
+      const value = row[`value${i}`];
+      if (value !== null && value !== undefined) {
+        validValues.push(value);
+      }
+    }
+  });
+
+  if (validValues.length === 0) {
+    // 如果没有有效值,清空统计字段
+    form.value.meanValue = null;
+    form.value.maxValue = null;
+    form.value.minValue = null;
+    form.value.stdDeviation = null;
+    return;
+  }
+
+  // 计算平均值
+  const mean = validValues.reduce((sum, value) => sum + value, 0) / validValues.length;
+  form.value.meanValue = mean.toFixed(4);
+
+  // 计算最大值和最小值
+  form.value.maxValue = Math.max(...validValues);
+  form.value.minValue = Math.min(...validValues);
+
+  // 计算标准差
+  const squaredDiffs = validValues.map(value => Math.pow(value - mean, 2));
+  const avgSquaredDiff = squaredDiffs.reduce((sum, value) => sum + value, 0) / validValues.length;
+  form.value.stdDeviation = Math.sqrt(avgSquaredDiff).toFixed(4);
+
+  // 如果目标值和误差范围已设置,计算过程能力指数
+  if (form.value.targetValue !== null && form.value.toleranceRange !== null) {
+    // 修复:误差范围是百分比,需要正确计算规格上下限
+    const usl = form.value.targetValue * (1 + form.value.toleranceRange / 100); // 规格上限
+    const lsl = form.value.targetValue * (1 - form.value.toleranceRange / 100); // 规格下限
+
+    form.value.usl = usl.toFixed(4);
+    form.value.lsl = lsl.toFixed(4);
+
+    // 计算过程能力指数
+    const stdDev = parseFloat(form.value.stdDeviation);
+    if (stdDev !== 0) {
+      // CPU = (USL - mean) / (3 * σ)
+      form.value.cpuValue = ((usl - mean) / (3 * stdDev)).toFixed(4);
+      // CPL = (mean - LSL) / (3 * σ)
+      form.value.cplValue = ((mean - lsl) / (3 * stdDev)).toFixed(4);
+      // CPK = min(CPU, CPL)
+      form.value.cpkValue = (Math.min(parseFloat(form.value.cpuValue), parseFloat(form.value.cplValue))).toFixed(4);
+    }
+  }
+}
+
+// 监听目标值和误差范围变化
+watch(() => [form.value.targetValue, form.value.toleranceRange], () => {
+  calculateStatistics();
+});
+
+// 绘制直方图
+function drawChart() {
+  const chartDom = chartContainerRef.value;
+  if (!chartDom) {
+    console.error('图表容器未找到');
+    return;
+  }
+
+  // 如果已有图表实例,先销毁
+  if (chartInstance) {
+    chartInstance.dispose();
+  }
+
+  // 清空容器
+  chartDom.innerHTML = '';
+
+  chartInstance = echarts.init(chartDom);
+
+  // 准备数据
+  const values = measuredValues.value.filter(val => val !== null && val !== undefined);
+  if (values.length === 0) {
+    console.warn('没有有效的测量值数据');
+    return;
+  }
+
+  // 计算基本统计信息
+  const minValue = Math.min(...values);
+  const maxValue = Math.max(...values);
+  const range = maxValue - minValue;
+
+  // 计算均值和标准差
+  const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
+  const squaredDiffs = values.map(val => Math.pow(val - mean, 2));
+  const avgSquaredDiff = squaredDiffs.reduce((sum, val) => sum + val, 0) / values.length;
+  const stdDev = Math.sqrt(avgSquaredDiff);
+
+  // 如果所有值都相同,则创建一个简单的柱状图
+  if (range === 0) {
+    const option = {
+      title: {
+        text: '测量值分布直方图'
+      },
+      tooltip: {
+        trigger: 'axis',
+        axisPointer: {
+          type: 'shadow'
+        }
+      },
+      grid: {
+        left: '3%',
+        right: '4%',
+        bottom: '3%',
+        containLabel: true
+      },
+      xAxis: [
+        {
+          type: 'category',
+          data: [minValue.toFixed(2)],
+          axisTick: {
+            alignWithLabel: true
+          }
+        }
+      ],
+      yAxis: [
+        {
+          type: 'value',
+          name: '频次'
+        }
+      ],
+      series: [
+        {
+          name: '测量值',
+          type: 'bar',
+          barWidth: '60%',
+          data: [values.length],
+          itemStyle: {
+            color: '#409EFF'
+          }
+        }
+      ]
+    };
+
+    chartInstance.setOption(option);
+    return;
+  }
+
+  // 正常情况下的直方图和正态分布曲线
+  const interval = range / 10;
+
+  // 构造区间和频次
+  const bins = [];
+  const counts = [];
+  const binCenters = []; // 用于正态分布曲线的x轴
+
+  for (let i = 0; i < 10; i++) {
+    const start = minValue + i * interval;
+    const end = i === 9 ? maxValue : minValue + (i + 1) * interval;
+    bins.push(`${start.toFixed(2)}-${end.toFixed(2)}`);
+    binCenters.push((start + end) / 2); // 区间中点
+
+    const count = values.filter(val => val >= start && val < end).length;
+    // 最后一个区间包含最大值
+    if (i === 9) {
+      const maxCount = values.filter(val => val === maxValue).length;
+      counts.push(count + maxCount);
+    } else {
+      counts.push(count);
+    }
+  }
+
+  // 计算正态分布曲线的y值
+  const normalY = binCenters.map(x => {
+    // 正态分布概率密度函数
+    return (1 / (Math.sqrt(2 * Math.PI) * stdDev)) *
+           Math.exp(-0.5 * Math.pow((x - mean) / stdDev, 2));
+  });
+
+  // 将概率密度转换为与直方图可比较的频次
+  const maxValueCount = Math.max(...counts);
+  const maxNormalY = Math.max(...normalY);
+  const normalCounts = normalY.map(y => (y / maxNormalY) * maxValueCount);
+
+  // 配置图表选项(参考calcMaogao中的实现)
+  const option = {
+    grid: {
+      top: "15%",
+      bottom: "15%",
+      left: "5%",
+      right: "5%",
+    },
+    title: {
+      show: true,
+      text: "测量值分布直方图与正态分布曲线",
+      left: "center",
+      top: "0",
+    },
+    color: ['#409EFF', '#ff8896'],
+    legend: {
+      show: true,
+      top: "30",
+      itemGap: 50
+    },
+    xAxis: {
+      type: 'category',
+      data: bins,
+      axisTick: {
+        alignWithLabel: true
+      }
+    },
+    yAxis: [
+      {
+        name: '频次'
+      }
+    ],
+    series: [
+      {
+        name: "测量值分布",
+        data: counts,
+        type: "bar",
+        smooth: true,
+        itemStyle: {
+          color: '#409EFF'
+        }
+      },
+      {
+        name: "正态分布",
+        data: normalCounts,
+        type: "line",
+        smooth: true,
+        symbol: 'none',
+        yAxisIndex: 0,
+        itemStyle: {
+          color: '#ff8896'
+        }
+      }
+    ],
+    tooltip: {
+      trigger: "axis",
+      axisPointer: {
+        type: 'shadow'
+      }
+    }
+  };
+
+  chartInstance.setOption(option);
+
+  // 监听窗口大小变化,自适应调整图表大小
+  const handleResize = () => {
+    if (chartInstance) {
+      chartInstance.resize();
+    }
+  };
+
+  window.addEventListener('resize', handleResize);
+
+  // 监听弹窗打开事件,确保图表正确显示
+  setTimeout(() => {
+    if (chartInstance) {
+      chartInstance.resize();
+    }
+  }, 300);
+
+  // 在组件销毁前清理事件监听器
+  onBeforeUnmount(() => {
+    window.removeEventListener('resize', handleResize);
+    if (chartInstance) {
+      chartInstance.dispose();
+      chartInstance = null;
+    }
+  });
+}
+
+// 监听查看弹窗的开启和关闭
+watch(() => viewOpen.value, (newVal) => {
+  if (!newVal) {
+    // 弹窗关闭时,清理可能存在的图表实例
+    if (chartInstance) {
+      chartInstance.dispose();
+      chartInstance = null;
+    }
+    nextTick(() => {
+      if (chartContainerRef.value) {
+        chartContainerRef.value.innerHTML = '';
+      }
+    });
+  }
+});
+
+getList();
+
+// 计算标准差水平评估数据
+const calculatedStdDeviationEvaluation = computed(() => {
+  return [
+    {
+      level: "世界级",
+      stdValue: "s ≤ " + calculateStdDevByCpk("2.0"),
+      cpk: "≥ 2.0",
+      evaluation: "过剩",
+      stability: "极其稳定",
+      defectRate: "~ 0.001 PPM",
+      description: "过程波动仅占公差带的17%。稳定性极佳,可考虑缩小公差或降低成本。"
+    },
+    {
+      level: "优秀",
+      stdValue: calculateStdDevByCpk("2.0") + " < s ≤ " + calculateStdDevByCpk("1.33"),
+      cpk: "≥ 1.33",
+      evaluation: "充足",
+      stability: "高度稳定",
+      defectRate: "~ 63 PPM",
+      description: "行业优秀水平。波动可控,过程可靠,是优质企业追求的目标。"
+    },
+    {
+      level: "最低可接受",
+      stdValue: calculateStdDevByCpk("1.33") + " < s ≤ " + calculateStdDevByCpk("1.0"),
+      cpk: "≥ 1.0",
+      evaluation: "勉强达标",
+      stability: "基本稳定",
+      defectRate: "~ 2700 PPM",
+      description: "过程波动占公差带的1/3。如履薄冰,需严密监控,否则极易出界。"
+    },
+    {
+      level: "不足",
+      stdValue: calculateStdDevByCpk("1.0") + " < s ≤ " + calculateStdDevByCpk("0.67"),
+      cpk: "~ 0.67",
+      evaluation: "不足",
+      stability: "不稳定",
+      defectRate: "~ 45500 PPM",
+      description: "波动已占公差带的一半。必须采取措施,改进过程。"
+    },
+    {
+      level: "严重不足",
+      stdValue: "s ≥ " + calculateStdDevByCpk("0.67"),
+      cpk: "≤ 0.5",
+      evaluation: "严重不足",
+      stability: "极度不稳定",
+      defectRate: "> 66000 PPM",
+      description: "过程波动极大,失控状态。产品质量无法保证,急需全面整改。"
+    }
+  ];
+});
+
+// 根据表格中的Cpk值计算标准差
+function calculateStdDevByCpk(tableCpkValue) {
+  // 根据标准差计算公式:标准差 = 误差值/(6*表格中的cpk值)
+  if (viewForm.value.toleranceValue && tableCpkValue) {
+    const toleranceValue = parseFloat(viewForm.value.toleranceValue);
+    const cpkValue = parseFloat(tableCpkValue);
+    if (cpkValue !== 0) {
+      return (toleranceValue / (6 * cpkValue)).toFixed(1);
+    }
+  }
+  return 0; // 返回默认值0而不是'N/A',便于数值比较
+}
+
+</script>
+
+<style>
+.cpk-current-row td {
+  background-color: rgba(255, 215, 0, 0.3) !important; /* 金色背景 */
+  font-weight: bold;
+}
+</style>