From ed7a42835a7aec7582d8a64ba7e3a3314fdc514e Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 23 六月 2026 16:11:05 +0800
Subject: [PATCH] fix(salesQuotation): 调整价格显示与输入的小数精度为4位

---
 src/views/qualityManagement/metricMaintenance/index.vue | 1311 +++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 917 insertions(+), 394 deletions(-)

diff --git a/src/views/qualityManagement/metricMaintenance/index.vue b/src/views/qualityManagement/metricMaintenance/index.vue
index 016a4c1..6282edd 100644
--- a/src/views/qualityManagement/metricMaintenance/index.vue
+++ b/src/views/qualityManagement/metricMaintenance/index.vue
@@ -1,415 +1,938 @@
 <template>
-  <div class="app-container product-view">
-    <div class="left">
-      <div>
-        <el-input
-            v-model="search"
-            style="width: 210px"
-            placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
-            @change="searchFilter"
-            @clear="searchFilter"
-            clearable
-            prefix-icon="Search"
-        />
-      </div>
-      <div ref="containerRef">
-        <el-tree
-            ref="tree"
-            v-loading="treeLoad"
-            :data="list"
-            @node-click="handleNodeClick"
-            :expand-on-click-node="false"
-            default-expand-all
-            :default-expanded-keys="expandedKeys"
-            :draggable="true"
-            :filter-node-method="filterNode"
-            :props="{ children: 'children', label: 'label' }"
-            highlight-current
-            node-key="id"
-            style="
-            height: calc(100vh - 190px);
-            overflow-y: scroll;
-            scrollbar-width: none;
-          "
-        >
-          <template #default="{ node, data }">
-            <div class="custom-tree-node">
-              <span class="tree-node-content">
-                <el-icon class="orange-icon">
-                  <component :is="data.children && data.children.length > 0
-                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
-                </el-icon>
-                {{ data.label }}
-              </span>
+  <div class="app-container metric-maintenance">
+    <el-tabs v-model="activeTab"
+             @tab-change="handleTabChange"
+             class="metric-tabs">
+      <el-tab-pane label="鍘熸潗鏂欐楠�"
+                   name="0" />
+      <el-tab-pane label="杩囩▼妫�楠�"
+                   name="1" />
+      <el-tab-pane label="鍑哄巶妫�楠�"
+                   name="2" />
+    </el-tabs>
+    <el-row :gutter="16"
+            class="metric-maintenance-row">
+      <!-- 宸︿晶锛氭娴嬫爣鍑嗗垪琛� -->
+      <el-col :xs="24"
+              :sm="24"
+              :md="12"
+              :lg="12"
+              :xl="12"
+              class="left-col">
+        <div class="left-panel">
+          <div class="toolbar">
+            <div class="toolbar-left"></div>
+            <div class="toolbar-right">
+              <el-button type="primary"
+                         @click="openStandardDialog('add')">鏂板</el-button>
+              <el-button type="success"
+                         plain
+                         @click="handleBatchAudit(1)">鎵瑰噯</el-button>
+              <el-button type="warning"
+                         plain
+                         @click="handleBatchAudit(2)">鎾ら攢</el-button>
+              <el-button type="danger"
+                         plain
+                         @click="handleBatchDelete">鍒犻櫎</el-button>
             </div>
-          </template>
-        </el-tree>
-      </div>
-    </div>
-    <div class="right">
-      <div style="margin-bottom: 10px">
-        <el-button type="primary" @click="openModelDia('add')">
-          鏂板妫�娴嬫寚鏍�
-        </el-button>
-        <el-button @click="handleOut">瀵煎嚭</el-button>
-        <el-button
-            type="danger"
-            @click="handleDelete"
-            style="margin-left: 10px"
-            plain
-        >
-          鍒犻櫎
-        </el-button>
-      </div>
-      <PIMTable
-          rowKey="id"
-          :column="tableColumn"
-          :tableData="tableData"
-          :page="page"
-          :isSelection="true"
-          @selection-change="handleSelectionChange"
-          :tableLoading="tableLoading"
-          @pagination="pagination"
-          :total="page.total"
-      ></PIMTable>
-    </div>
-    <el-dialog
-        v-model="modelDia"
-        title="妫�娴嬫寚鏍�"
-        width="400px"
-        @close="closeModelDia"
-    >
-      <el-form
-          :model="modelForm"
-          label-width="140px"
-          label-position="top"
-          :rules="modelRules"
-          ref="modelFormRef"
-      >
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="鎸囨爣锛�" prop="parameterItem">
-              <el-input
-                  v-model="modelForm.parameterItem"
-                  placeholder="璇疯緭鍏ユ寚鏍�"
-                  clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="鍗曚綅锛�" prop="unit">
-              <el-input
-                  v-model="modelForm.unit"
-                  placeholder="璇疯緭鍏ュ崟浣�"
-                  clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="鏍囧噯鍊硷細" prop="standardValue">
-              <el-input
-                  v-model="modelForm.standardValue"
-                  placeholder="璇疯緭鍏ユ爣鍑嗗��"
-                  clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="24">
-            <el-form-item label="鍐呮帶鍊硷細" prop="controlValue">
-              <el-input
-                  v-model="modelForm.controlValue"
-                  placeholder="璇疯緭鍏ュ唴鎺у��"
-                  clearable
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitModelForm">纭</el-button>
-          <el-button @click="closeModelDia">鍙栨秷</el-button>
+          </div>
+          <PIMTable rowKey="id"
+                    :column="standardColumns"
+                    :tableData="standardTableData"
+                    :page="page"
+                    :isSelection="true"
+                    :tableLoading="tableLoading"
+                    :rowClassName="rowClassNameCenter"
+                    :rowClick="handleTableRowClick"
+                    @selection-change="handleSelectionChange"
+                    @pagination="handlePagination"
+                    :total="page.total">
+            <template #standardNoCell="{ row }">
+              <span class="clickable-link"
+                    @click="handleStandardRowClick(row)">
+                {{ row.standardNo }}
+              </span>
+            </template>
+            <!-- 琛ㄥご鎼滅储鎻掓Ы -->
+            <template #standardNoHeader>
+              <el-input v-model="searchForm.standardNo"
+                        placeholder="鏍囧噯缂栧彿"
+                        clearable
+                        size="small"
+                        @change="handleQuery"
+                        @clear="handleQuery" />
+            </template>
+            <template #standardNameHeader>
+              <el-input v-model="searchForm.standardName"
+                        placeholder="鏍囧噯鍚嶇О"
+                        clearable
+                        size="small"
+                        @change="handleQuery"
+                        @clear="handleQuery" />
+            </template>
+            <template #stateHeader>
+              <el-select v-model="searchForm.state"
+                         placeholder="鐘舵��"
+                         clearable
+                         size="small"
+                         style="width: 110px"
+                         @change="handleQuery"
+                         @clear="handleQuery">
+                <el-option label="鑽夌"
+                           value="0" />
+                <el-option label="閫氳繃"
+                           value="1" />
+                <el-option label="鎾ら攢"
+                           value="2" />
+              </el-select>
+            </template>
+          </PIMTable>
         </div>
-      </template>
-    </el-dialog>
+      </el-col>
+      <!-- 鍙充晶锛氭爣鍑嗗弬鏁板垪琛� -->
+      <el-col :xs="24"
+              :sm="24"
+              :md="12"
+              :lg="12"
+              :xl="12"
+              class="right-col">
+        <div class="right-panel">
+          <div class="right-header">
+            <div class="title">鏍囧噯鍙傛暟</div>
+            <div class="desc"
+                 v-if="currentStandard">
+              鎮ㄥ綋鍓嶉�夋嫨鐨勬娴嬫爣鍑嗙紪鍙锋槸锛�
+              <span class="link-text">{{ currentStandard.standardNo }}</span>
+            </div>
+            <div class="desc"
+                 v-else>璇峰厛鍦ㄥ乏渚ч�夋嫨涓�涓娴嬫爣鍑�</div>
+          </div>
+          <div class="right-toolbar">
+            <el-button type="primary"
+                       :disabled="!currentStandard || isStandardReadonly"
+                       @click="openParamDialog('add')">
+              鏂板
+            </el-button>
+            <el-button type="danger"
+                       plain
+                       :disabled="!currentStandard || isStandardReadonly"
+                       @click="handleParamBatchDelete">
+              鍒犻櫎
+            </el-button>
+          </div>
+          <el-table v-loading="detailLoading"
+                    :data="detailTableData"
+                    border
+                    :row-class-name="() => 'row-center'"
+                    class="center-table"
+                    style="width: 100%"
+                    height="calc(100vh - 220px)"
+                    @selection-change="handleParamSelectionChange">
+            <el-table-column type="selection"
+                             width="48"
+                             align="center" />
+            <el-table-column type="index"
+                             label="搴忓彿"
+                             width="60"
+                             align="center" />
+            <el-table-column prop="parameterItem"
+                             label="鍙傛暟椤�"
+                             min-width="120" />
+            <el-table-column prop="unit"
+                             label="鍗曚綅"
+                             width="80" />
+            <el-table-column prop="standardValue"
+                             label="鏍囧噯鍊�"
+                             min-width="120" />
+            <el-table-column prop="controlValue"
+                             label="鍐呮帶鍊�"
+                             min-width="120" />
+            <el-table-column prop="defaultValue"
+                             label="榛樿鍊�"
+                             min-width="120" />
+            <el-table-column label="鎿嶄綔"
+                             width="140"
+                             fixed="right"
+                             align="center">
+              <template #default="{ row }">
+                <el-button link
+                           type="primary"
+                           size="small"
+                           :disabled="isStandardReadonly"
+                           @click="openParamDialog('edit', row)">
+                  缂栬緫
+                </el-button>
+                <el-button link
+                           type="danger"
+                           size="small"
+                           :disabled="isStandardReadonly"
+                           @click="handleParamDelete(row)">
+                  鍒犻櫎
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </el-col>
+    </el-row>
+    <!-- 鏂板 / 缂栬緫妫�娴嬫爣鍑� -->
+    <StandardFormDialog ref="standardFormDialogRef"
+                        v-model="standardDialogVisible"
+                        :operation-type="standardOperationType"
+                        :form="standardForm"
+                        :rules="standardRules"
+                        :inspect-type="activeTab"
+                        :process-options="processOptions"
+                        @confirm="submitStandardForm"
+                        @close="closeStandardDialog"
+                        @cancel="closeStandardDialog" />
+    <ParamFormDialog ref="paramFormDialogRef"
+                     v-model="paramDialogVisible"
+                     :operation-type="paramOperationType"
+                     :inspectType="activeTab.value"
+                     :form="paramForm"
+                     @confirm="submitParamForm"
+                     @close="closeParamDialog"
+                     @cancel="closeParamDialog" />
   </div>
 </template>
 
 <script setup>
-import {ref} from "vue";
-import {addOrEditProductModel, delProductModel, modelListPage, productTreeList} from "@/api/basicData/product.js";
-import ImportExcel from "@/views/basicData/product/ImportExcel/index.vue";
-import {ElMessageBox} from "element-plus";
-import {
-  qualityTestStandardAdd, qualityTestStandardDel,
-  qualityTestStandardListPage,
-  qualityTestStandardUpdate
-} from "@/api/qualityManagement/metricMaintenance.js";
-const { proxy } = getCurrentInstance();
-// 鏍�
-const search = ref("");
-const treeLoad = ref(false);
-const list = ref([]);
-const expandedKeys = ref([]);
-const currentId = ref("");
-const currentParentId = ref("");
-// 鎸囨爣琛ㄦ牸
-const tableData = ref([]);
-const tableLoading = ref(false);
-const page = reactive({
-  current: 1,
-  size: 10,
-});
-const tableColumn = ref([
-  {
-    label: "鎸囨爣",
-    prop: "parameterItem",
-  },
-  {
-    label: "鍗曚綅",
-    prop: "unit",
-  },
-  {
-    label: "鏍囧噯鍊�",
-    prop: "standardValue",
-  },
-  {
-    label: "鍐呮帶鍊�",
-    prop: "controlValue",
-  },
-  {
-    dataType: "action",
-    label: "鎿嶄綔",
-    align: "center",
-    operation: [
-      {
-        name: "缂栬緫",
-        type: "text",
-        clickFun: (row) => {
-          openModelDia("edit", row);
+  import { Search } from "@element-plus/icons-vue";
+  import {
+    ref,
+    reactive,
+    toRefs,
+    onMounted,
+    getCurrentInstance,
+    computed,
+  } from "vue";
+  import { ElMessageBox } from "element-plus";
+  import {
+    qualityTestStandardListPage,
+    qualityTestStandardAdd,
+    qualityTestStandardUpdate,
+    qualityTestStandardDel,
+    qualityTestStandardCopyParam,
+    qualityTestStandardAudit,
+    qualityTestStandardParamList,
+    qualityTestStandardParamAdd,
+    qualityTestStandardParamUpdate,
+    qualityTestStandardParamDel,
+  } from "@/api/qualityManagement/metricMaintenance.js";
+  import { productProcessListPage } from "@/api/basicData/productProcess.js";
+  import StandardFormDialog from "./StandardFormDialog.vue";
+  import ParamFormDialog from "./ParamFormDialog.vue";
+
+  const { proxy } = getCurrentInstance();
+
+  // 绫诲埆 Tab锛�0=鍘熸潗鏂欙紝1=杩囩▼锛�2=鍑哄巶锛�
+  const activeTab = ref("0");
+
+  // 宸︿晶鏍囧噯鍒楄〃锛氭暣琛屽唴瀹瑰眳涓紙閰嶅悎鏍峰紡锛�
+  const rowClassNameCenter = () => "row-center";
+
+  // 鏍囧噯鐘舵�佷负鈥滈�氳繃(1)鈥濇椂锛屽彸渚у弬鏁扮姝㈠鍒犳敼
+  const isStandardReadonly = computed(() => {
+    const state = currentStandard.value?.state;
+    return state === 1 || state === "1";
+  });
+
+  // 鎼滅储鏉′欢
+  const data = reactive({
+    searchForm: {
+      standardNo: "",
+      standardName: "",
+      remark: "",
+      state: "",
+      inspectType: "",
+      processId: "",
+    },
+    standardForm: {
+      id: undefined,
+      standardNo: "",
+      standardName: "",
+      remark: "",
+      state: "0",
+      inspectType: "",
+      processId: "",
+    },
+    standardRules: {
+      standardNo: [
+        { required: true, message: "璇疯緭鍏ユ爣鍑嗙紪鍙�", trigger: "blur" },
+      ],
+      standardName: [
+        { required: true, message: "璇疯緭鍏ユ爣鍑嗗悕绉�", trigger: "blur" },
+      ],
+      processId: [
+        {
+          validator: (_rule, value, callback) => {
+            const inspectType = String(
+              standardForm.value.inspectType ?? activeTab.value ?? ""
+            );
+            if (
+              (inspectType === "1" || inspectType === "2") &&
+              (value === "" || value === null || value === undefined)
+            ) {
+              callback(new Error("璇烽�夋嫨宸ュ簭"));
+              return;
+            }
+            callback();
+          },
+          trigger: "change",
         },
-      },
-    ],
-  },
-]);
-const selectedRows = ref([]);
-// 鎸囨爣寮规
-const modelDia = ref(false);
-const modelOperationType = ref("");
-const data = reactive({
-  modelForm: {
+      ],
+    },
+  });
+
+  const { searchForm, standardForm, standardRules } = toRefs(data);
+
+  // 宸︿晶琛ㄦ牸
+  const standardTableData = ref([]);
+  const selectedRows = ref([]);
+  const tableLoading = ref(false);
+  const page = reactive({
+    current: 1,
+    size: 10,
+    total: 0,
+  });
+
+  // 宸ュ簭涓嬫媺
+  const processOptions = ref([]);
+
+  // 鑾峰彇宸ュ簭鍒楄〃
+  const getProcessList = async () => {
+    try {
+      const res = await productProcessListPage({ current: 1, size: 1000 });
+      if (res?.code === 200) {
+        const records = res?.data?.records || [];
+        processOptions.value = records.map(item => ({
+          label: item.processName || item.name || item.label,
+          value: item.id || item.processId || item.value,
+        }));
+      }
+    } catch (error) {
+      console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触:", error);
+    }
+  };
+
+  // 褰撳墠閫変腑鐨勬爣鍑� & 鍙充晶璇︽儏
+  const currentStandard = ref(null);
+  const detailTableData = ref([]);
+  const detailLoading = ref(false);
+  const paramSelectedRows = ref([]);
+  const paramDialogVisible = ref(false);
+  const paramOperationType = ref("add"); // add | edit
+  const paramFormDialogRef = ref(null);
+  const paramForm = reactive({
+    id: undefined,
     parameterItem: "",
     unit: "",
     standardValue: "",
     controlValue: "",
-  },
-  modelRules: {
-    parameterItem: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    standardValue: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    controlValue: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-  },
-});
-const { modelForm, modelRules } = toRefs(data);
+    defaultValue: "",
+  });
 
-// 鏌ヨ浜у搧鏍�
-const getProductTreeList = () => {
-  treeLoad.value = true;
-  productTreeList().then((res) => {
-    list.value = res;
-    list.value.forEach((a) => {
-      expandedKeys.value.push(a.label);
-    });
-    treeLoad.value = false;
-  }).catch((err) => {
-    treeLoad.value = false;
-  });
-};
-// 杩囨护浜у搧鏍�
-const searchFilter = () => {
-  proxy.$refs.tree.filter(search.value);
-};
-// 閫夋嫨浜у搧
-const handleNodeClick = (val, node, el) => {
-  // 鍙湁鍙跺瓙鑺傜偣鎵嶆墽琛屼互涓嬮�昏緫
-  currentId.value = val.id;
-  currentParentId.value = val.parentId;
-  getModelList();
-};
-// 琛ㄦ牸閫夋嫨鏁版嵁
-const handleSelectionChange = (selection) => {
-  selectedRows.value = selection;
-};
-// 鏌ヨ鎸囨爣鏁版嵁
-const pagination = (obj) => {
-  page.current = obj.page;
-  page.size = obj.limit;
-  getModelList();
-};
-const getModelList = () => {
-  tableLoading.value = true;
-  qualityTestStandardListPage({
-    productId: currentId.value,
-    current: page.current,
-    size: page.size,
-  }).then((res) => {
-    tableData.value = res.data.records;
-    page.total = res.data.total;
-    tableLoading.value = false;
-  });
-};
-// 璋冪敤tree杩囨护鏂规硶 涓枃鑻辫繃婊�
-const filterNode = (value, data, node) => {
-  if (!value) {
-    //濡傛灉鏁版嵁涓虹┖锛屽垯杩斿洖true,鏄剧ず鎵�鏈夌殑鏁版嵁椤�
-    return true;
-  }
-  // 鏌ヨ鍒楄〃鏄惁鏈夊尮閰嶆暟鎹紝灏嗗�煎皬鍐欙紝鍖归厤鑻辨枃鏁版嵁
-  let val = value.toLowerCase();
-  return chooseNode(val, data, node); // 璋冪敤杩囨护浜屽眰鏂规硶
-};
-// 杩囨护鐖惰妭鐐� / 瀛愯妭鐐� (濡傛灉杈撳叆鐨勫弬鏁版槸鐖惰妭鐐逛笖鑳藉尮閰嶏紝鍒欒繑鍥炶鑺傜偣浠ュ強鍏朵笅鐨勬墍鏈夊瓙鑺傜偣锛涘鏋滃弬鏁版槸瀛愯妭鐐癸紝鍒欒繑鍥炶鑺傜偣鐨勭埗鑺傜偣銆俷ame鏄腑鏂囧瓧绗︼紝enName鏄嫳鏂囧瓧绗�.
-const chooseNode = (value, data, node) => {
-  if (data.label.indexOf(value) !== -1) {
-    return true;
-  }
-  const level = node.level;
-  // 濡傛灉浼犲叆鐨勮妭鐐规湰韬氨鏄竴绾ц妭鐐瑰氨涓嶇敤鏍¢獙浜�
-  if (level === 1) {
-    return false;
-  }
-  // 鍏堝彇褰撳墠鑺傜偣鐨勭埗鑺傜偣
-  let parentData = node.parent;
-  // 閬嶅巻褰撳墠鑺傜偣鐨勭埗鑺傜偣
-  let index = 0;
-  while (index < level - 1) {
-    // 濡傛灉鍖归厤鍒扮洿鎺ヨ繑鍥烇紝姝ゅname鍊兼槸涓枃瀛楃锛宔nName鏄嫳鏂囧瓧绗︺�傚垽鏂尮閰嶄腑鑻辨枃杩囨护
-    if (parentData.data.label.indexOf(value) !== -1) {
-      return true;
-    }
-    // 鍚﹀垯鐨勮瘽鍐嶅線涓婁竴灞傚仛鍖归厤
-    parentData = parentData.parent;
-    index++;
-  }
-  // 娌″尮閰嶅埌杩斿洖false
-  return false;
-};
-// 鎵撳紑鎸囨爣寮规
-const openModelDia = (type, data) => {
-  modelOperationType.value = type;
-  modelDia.value = true;
-  modelForm.value.model = "";
-  modelForm.value.model = "";
-  modelForm.value.id = "";
-  if (type === "edit") {
-    modelForm.value = { ...data };
-  }
-};
-// 瀵煎嚭
-const handleOut = () => {
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  }).then(() => {
-    proxy.download("/quality/qualityTestStandard/export", {}, "妫�娴嬫寚鏍�.xlsx");
-  }).catch(() => {
-    proxy.$modal.msg("宸插彇娑�");
-  });
-};
+  // 寮圭獥
+  const standardDialogVisible = ref(false);
+  const standardOperationType = ref("add"); // add | edit | copy
+  const standardFormDialogRef = ref(null);
 
-// 鍒犻櫎鎸囨爣
-const handleDelete = () => {
-  let ids = [];
-  if (selectedRows.value.length > 0) {
-    ids = selectedRows.value.map((item) => item.id);
-  } else {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
-    return;
-  }
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  }).then(() => {
+  // 鍒楀畾涔�
+  const standardColumns = ref([
+    {
+      label: "鏍囧噯缂栧彿",
+      prop: "standardNo",
+      dataType: "slot",
+      slot: "standardNoCell",
+      minWidth: 160,
+      align: "center",
+      headerSlot: "standardNoHeader",
+    },
+    {
+      label: "鏍囧噯鍚嶇О",
+      prop: "standardName",
+      minWidth: 180,
+      align: "center",
+      headerSlot: "standardNameHeader",
+    },
+    {
+      label: "绫诲埆",
+      prop: "inspectType",
+      align: "center",
+      dataType: "tag",
+      minWidth: 120,
+      formatData: val => {
+        const map = {
+          0: "鍘熸潗鏂欐楠�",
+          1: "杩囩▼妫�楠�",
+          2: "鍑哄巶妫�楠�",
+        };
+        return map[val] || val;
+      },
+    },
+    {
+      label: "宸ュ簭",
+      prop: "processId",
+      align: "center",
+      dataType: "tag",
+      visible: visible => ["1", "2"].includes(String(activeTab.value)),
+      formatData: val => {
+        const target = processOptions.value.find(
+          item => String(item.value) === String(val)
+        );
+        return target?.label || val;
+      },
+    },
+    {
+      label: "鐘舵��",
+      prop: "state",
+      headerSlot: "stateHeader",
+      align: "center",
+      dataType: "tag",
+      formatData: val => {
+        const map = {
+          0: "鑽夌",
+          1: "閫氳繃",
+          2: "鎾ら攢",
+        };
+        return map[val] || val;
+      },
+      formatType: val => {
+        if (val === "1" || val === 1) return "success";
+        if (val === "2" || val === 2) return "warning";
+        return "info";
+      },
+    },
+    {
+      label: "澶囨敞",
+      prop: "remark",
+      minWidth: 160,
+      align: "center",
+    },
+    {
+      dataType: "action",
+      label: "鎿嶄綔",
+      align: "center",
+      fixed: "right",
+      width: 220,
+      operation: [
+        {
+          name: "缂栬緫",
+          type: "text",
+          clickFun: row => {
+            openStandardDialog("edit", row);
+          },
+        },
+        {
+          name: "澶嶅埗",
+          type: "text",
+          clickFun: async row => {
+            if (!row?.id) return;
+            try {
+              await ElMessageBox.confirm("纭澶嶅埗璇ユ爣鍑嗗弬鏁帮紵", "鎻愮ず", {
+                type: "warning",
+              });
+            } catch {
+              return;
+            }
+            await qualityTestStandardCopyParam(row.id);
+            proxy.$message.success("澶嶅埗鎴愬姛");
+            getStandardList();
+            if (currentStandard.value?.id === row.id) {
+              loadDetail(row.id);
+            }
+          },
+        },
+        {
+          name: "鍒犻櫎",
+          type: "text",
+          clickFun: row => {
+            handleDelete(row);
+          },
+        },
+      ],
+    },
+  ]);
+  const handleTabChange = () => {
+    searchForm.value.standardNo = "";
+    searchForm.value.standardName = "";
+    searchForm.value.remark = "";
+    searchForm.value.state = "";
+    searchForm.value.processId = "";
+    searchForm.value.inspectType = activeTab.value;
+    page.current = 1;
+    currentStandard.value = null;
+    detailTableData.value = [];
+    paramSelectedRows.value = [];
+    getStandardList();
+  };
+
+  // 鏌ヨ鍒楄〃
+  const getStandardList = () => {
     tableLoading.value = true;
-    qualityTestStandardDel(ids).then((res) => {
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-      getModelList();
-    }).finally(() => {
-      tableLoading.value = false;
-    });
-  }).catch(() => {
-    proxy.$modal.msg("宸插彇娑�");
-  });
-};
+    const params = {
+      ...searchForm.value,
+      current: page.current,
+      size: page.size,
+    };
+    qualityTestStandardListPage(params)
+      .then(res => {
+        const records = res?.data?.records || [];
+        standardTableData.value = records;
+        page.total = res?.data?.total || records.length;
+      })
+      .finally(() => {
+        tableLoading.value = false;
+      });
+  };
 
-// 鎻愪氦瑙勬牸鍨嬪彿淇敼
-const submitModelForm = () => {
-  proxy.$refs.modelFormRef.validate((valid) => {
-    if (valid) {
-      modelForm.value.productId = Number(currentId.value);
-      if(modelOperationType.value === 'add') {
-        qualityTestStandardAdd(modelForm.value).then((res) => {
-          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-          closeModelDia();
-          getModelList();
-        });
-      } else {
-        qualityTestStandardUpdate(modelForm.value).then((res) => {
-          proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-          closeModelDia();
-          getModelList();
-        });
-      }
+  const handleQuery = () => {
+    page.current = 1;
+    getStandardList();
+  };
+
+  const resetQuery = () => {
+    searchForm.value.standardNo = "";
+    searchForm.value.standardName = "";
+    searchForm.value.remark = "";
+    searchForm.value.state = "";
+    searchForm.value.inspectType = "";
+    searchForm.value.processId = "";
+    handleQuery();
+  };
+
+  const handlePagination = obj => {
+    page.current = obj.page;
+    page.size = obj.limit;
+    getStandardList();
+  };
+
+  const handleSelectionChange = selection => {
+    selectedRows.value = selection;
+  };
+
+  // 鎵归噺瀹℃牳锛氱姸鎬� 1=鎵瑰噯锛�2=鎾ら攢
+  const handleBatchAudit = async state => {
+    if (!selectedRows.value.length) {
+      proxy.$message.warning("璇烽�夋嫨鏁版嵁");
+      return;
     }
+    const text = state === 1 ? "鎵瑰噯" : "鎾ら攢";
+    const payload = selectedRows.value
+      .filter(i => i?.id)
+      .map(item => ({ id: item.id, state }));
+
+    if (!payload.length) {
+      proxy.$message.warning("璇烽�夋嫨鏈夋晥鏁版嵁");
+      return;
+    }
+
+    try {
+      await ElMessageBox.confirm(`纭${text}閫変腑鐨勬爣鍑嗭紵`, "鎻愮ず", {
+        type: "warning",
+      });
+    } catch {
+      return;
+    }
+    await qualityTestStandardAudit(payload);
+    proxy.$message.success(`${text}鎴愬姛`);
+    getStandardList();
+  };
+
+  // 琛ㄦ牸琛岀偣鍑伙紝鍔犺浇鍙充晶鍙傛暟
+  const handleTableRowClick = row => {
+    currentStandard.value = row;
+    loadDetail(row.id);
+  };
+
+  // 宸︿晶琛岀偣鍑伙紝鍔犺浇鍙充晶鍙傛暟锛堜繚鐣欑敤浜庢爣鍑嗙紪鍙峰垪鐨勭偣鍑伙級
+  const handleStandardRowClick = row => {
+    currentStandard.value = row;
+    loadDetail(row.id);
+  };
+
+  const loadDetail = standardId => {
+    if (!standardId) {
+      detailTableData.value = [];
+      return;
+    }
+    detailLoading.value = true;
+    qualityTestStandardParamList({ testStandardId: standardId })
+      .then(res => {
+        detailTableData.value = res?.data || [];
+      })
+      .finally(() => {
+        detailLoading.value = false;
+      });
+  };
+
+  const handleParamSelectionChange = selection => {
+    paramSelectedRows.value = selection;
+  };
+
+  const openParamDialog = (type, row) => {
+    if (!currentStandard.value?.id) return;
+    if (isStandardReadonly.value) {
+      proxy.$message.warning("璇ユ爣鍑嗗凡閫氳繃锛屽弬鏁颁笉鍙紪杈�");
+      return;
+    }
+    paramOperationType.value = type;
+    if (type === "add") {
+      Object.assign(paramForm, {
+        id: undefined,
+        parameterItem: "",
+        unit: "",
+        standardValue: "",
+        controlValue: "",
+        defaultValue: "",
+      });
+    } else if (type === "edit" && row) {
+      Object.assign(paramForm, row);
+    }
+    paramDialogVisible.value = true;
+  };
+
+  const closeParamDialog = () => {
+    paramDialogVisible.value = false;
+    paramFormDialogRef.value?.resetFields?.();
+  };
+
+  const submitParamForm = async () => {
+    const testStandardId = currentStandard.value?.id;
+    if (!testStandardId) return;
+    if (isStandardReadonly.value) {
+      proxy.$message.warning("璇ユ爣鍑嗗凡閫氳繃锛屽弬鏁颁笉鍙紪杈�");
+      return;
+    }
+    const payload = { ...paramForm, testStandardId };
+    if (paramOperationType.value === "edit") {
+      await qualityTestStandardParamUpdate(payload);
+      proxy.$message.success("鎻愪氦鎴愬姛");
+    } else {
+      await qualityTestStandardParamAdd(payload);
+      proxy.$message.success("鎻愪氦鎴愬姛");
+    }
+    closeParamDialog();
+    loadDetail(testStandardId);
+  };
+
+  const handleParamDelete = async row => {
+    if (!row?.id) return;
+    if (isStandardReadonly.value) {
+      proxy.$message.warning("璇ユ爣鍑嗗凡閫氳繃锛屽弬鏁颁笉鍙紪杈�");
+      return;
+    }
+    try {
+      await ElMessageBox.confirm("纭鍒犻櫎璇ュ弬鏁帮紵", "鎻愮ず", { type: "warning" });
+    } catch {
+      return;
+    }
+    await qualityTestStandardParamDel([row.id]);
+    proxy.$message.success("鍒犻櫎鎴愬姛");
+    loadDetail(currentStandard.value?.id);
+  };
+
+  const handleParamBatchDelete = async () => {
+    if (isStandardReadonly.value) {
+      proxy.$message.warning("璇ユ爣鍑嗗凡閫氳繃锛屽弬鏁颁笉鍙紪杈�");
+      return;
+    }
+    if (!paramSelectedRows.value.length) {
+      proxy.$message.warning("璇烽�夋嫨鏁版嵁");
+      return;
+    }
+    const ids = paramSelectedRows.value.map(i => i.id);
+    try {
+      await ElMessageBox.confirm(
+        "閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�",
+        "鍒犻櫎鎻愮ず",
+        { type: "warning" }
+      );
+    } catch {
+      return;
+    }
+    await qualityTestStandardParamDel(ids);
+    proxy.$message.success("鍒犻櫎鎴愬姛");
+    loadDetail(currentStandard.value?.id);
+  };
+
+  // 鏂板 / 缂栬緫 / 澶嶅埗
+  const openStandardDialog = (type, row) => {
+    standardOperationType.value = type;
+    if (type === "add") {
+      Object.assign(standardForm.value, {
+        id: undefined,
+        standardNo: "",
+        standardName: "",
+        remark: "",
+        state: "0",
+        inspectType: activeTab.value,
+        processId: ["1", "2"].includes(String(activeTab.value)) ? "" : null,
+      });
+    } else if (type === "edit" && row) {
+      Object.assign(standardForm.value, {
+        ...row,
+        // 纭繚 inspectType 鍜� state 杞崲涓哄瓧绗︿覆锛屼互鍖归厤 el-select 鐨� value 绫诲瀷
+        inspectType:
+          row.inspectType !== null && row.inspectType !== undefined
+            ? String(row.inspectType)
+            : "",
+        state:
+          row.state !== null && row.state !== undefined ? String(row.state) : "0",
+        // 纭繚 processId 杞崲涓哄瓧绗︿覆鎴栨暟瀛楋紙鏍规嵁瀹為檯闇�瑕侊級
+        processId:
+          ["1", "2"].includes(String(row.inspectType)) &&
+          row.processId !== null &&
+          row.processId !== undefined
+            ? row.processId
+            : null,
+      });
+    } else if (type === "copy" && row) {
+      const { id, ...rest } = row;
+      Object.assign(standardForm.value, {
+        ...rest,
+        id: undefined,
+        standardNo: "",
+        state: "0",
+        // 纭繚 inspectType 杞崲涓哄瓧绗︿覆
+        inspectType: activeTab.value,
+        processId: ["1", "2"].includes(String(activeTab.value))
+          ? rest.processId ?? ""
+          : null,
+      });
+    }
+    standardDialogVisible.value = true;
+  };
+
+  const closeStandardDialog = () => {
+    standardDialogVisible.value = false;
+    standardFormDialogRef.value?.resetFields?.();
+  };
+
+  const submitStandardForm = () => {
+    const payload = { ...standardForm.value };
+    payload.inspectType = activeTab.value;
+    if (!["1", "2"].includes(String(payload.inspectType))) {
+      payload.processId = null;
+    }
+    const isEdit = standardOperationType.value === "edit";
+    if (isEdit) {
+      qualityTestStandardUpdate(payload).then(() => {
+        proxy.$message.success("鎻愪氦鎴愬姛");
+        standardDialogVisible.value = false;
+        getStandardList();
+      });
+    } else {
+      qualityTestStandardAdd(payload).then(() => {
+        proxy.$message.success("鎻愪氦鎴愬姛");
+        standardDialogVisible.value = false;
+        getStandardList();
+      });
+    }
+  };
+
+  // 鍒犻櫎锛堝崟鏉★級
+  const handleDelete = row => {
+    const ids = [row.id];
+    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        tableLoading.value = true;
+        qualityTestStandardDel(ids)
+          .then(() => {
+            proxy.$message.success("鍒犻櫎鎴愬姛");
+            getStandardList();
+            if (currentStandard.value && currentStandard.value.id === row.id) {
+              currentStandard.value = null;
+              detailTableData.value = [];
+            }
+          })
+          .finally(() => {
+            tableLoading.value = false;
+          });
+      })
+      .catch(() => {
+        proxy.$modal?.msg("宸插彇娑�");
+      });
+  };
+
+  // 鎵归噺鍒犻櫎
+  const handleBatchDelete = () => {
+    if (!selectedRows.value.length) {
+      proxy.$message.warning("璇烽�夋嫨鏁版嵁");
+      return;
+    }
+    const ids = selectedRows.value.map(item => item.id);
+    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        tableLoading.value = true;
+        qualityTestStandardDel(ids)
+          .then(() => {
+            proxy.$message.success("鍒犻櫎鎴愬姛");
+            getStandardList();
+            if (currentStandard.value && ids.includes(currentStandard.value.id)) {
+              currentStandard.value = null;
+              detailTableData.value = [];
+            }
+          })
+          .finally(() => {
+            tableLoading.value = false;
+          });
+      })
+      .catch(() => {
+        proxy.$modal?.msg("宸插彇娑�");
+      });
+  };
+
+  onMounted(() => {
+    searchForm.value.inspectType = activeTab.value;
+    getProcessList();
+    getStandardList();
   });
-};
-// 鍏抽棴鍨嬪彿寮规
-const closeModelDia = () => {
-  proxy.$refs.modelFormRef.resetFields();
-  modelDia.value = false;
-};
-getProductTreeList();
 </script>
 
 <style scoped>
-.product-view {
-  display: flex;
-}
-.left {
-  width: 380px;
-  padding: 16px;
-  background: #ffffff;
-}
-.right {
-  width: calc(100% - 380px);
-  padding: 16px;
-  margin-left: 20px;
-  background: #ffffff;
-}
-.custom-tree-node {
-  flex: 1;
-  display: flex;
-  align-items: center;
-  justify-content: space-between;
-  font-size: 14px;
-  padding-right: 8px;
-}
-.tree-node-content {
-  display: flex;
-  align-items: center; /* 鍨傜洿灞呬腑 */
-  height: 100%;
-}
-.orange-icon {
-  color: orange;
-  font-size: 18px;
-  margin-right: 8px; /* 鍥炬爣涓庢枃瀛椾箣闂村姞鐐归棿璺� */
-}
-</style>
\ No newline at end of file
+  .metric-maintenance {
+    padding: 0;
+    min-width: 0;
+  }
+
+  .metric-tabs {
+    margin: 10px;
+  }
+
+  .metric-maintenance-row {
+    width: 100%;
+  }
+
+  .metric-maintenance-row .left-col,
+  .metric-maintenance-row .right-col {
+    margin-bottom: 16px;
+  }
+
+  .left-panel,
+  .right-panel {
+    min-width: 0;
+    background: #ffffff;
+    padding: 16px;
+    box-sizing: border-box;
+    overflow: hidden;
+    height: 100%;
+    min-height: 400px;
+  }
+
+  @media (max-width: 768px) {
+    .left-panel,
+    .right-panel {
+      padding: 12px;
+    }
+  }
+
+  .toolbar {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 12px;
+    flex-wrap: wrap;
+    gap: 8px;
+  }
+
+  .toolbar-left {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    gap: 4px;
+  }
+
+  .toolbar-right {
+    flex-shrink: 0;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+  }
+
+  .search-label {
+    margin: 0 4px 0 12px;
+  }
+
+  .search-label:first-of-type {
+    margin-left: 0;
+  }
+
+  .right-header {
+    display: flex;
+    align-items: baseline;
+    justify-content: space-between;
+    margin-bottom: 10px;
+  }
+
+  .right-header .title {
+    font-size: 16px;
+    font-weight: 600;
+  }
+
+  .right-header .desc {
+    font-size: 13px;
+    color: #666;
+  }
+
+  .right-toolbar {
+    display: flex;
+    justify-content: flex-end;
+    gap: 10px;
+    margin-bottom: 10px;
+  }
+
+  .link-text {
+    color: #409eff;
+    cursor: default;
+  }
+
+  .clickable-link {
+    color: #409eff;
+    cursor: pointer;
+  }
+
+  .clickable-link:hover {
+    text-decoration: underline;
+  }
+
+  :deep(.row-center td) {
+    text-align: center !important;
+  }
+
+  /* el-table 琛ㄥご/鍐呭缁熶竴灞呬腑锛坮ow-class-name 涓嶄綔鐢ㄤ簬琛ㄥご锛� */
+  :deep(.center-table .el-table__header-wrapper th .cell) {
+    text-align: center !important;
+  }
+  :deep(.center-table .el-table__body-wrapper td .cell) {
+    text-align: center !important;
+  }
+
+  /* PIMTable 琛ㄥご灞呬腑 */
+  :deep(.lims-table .pim-table-header-cell) {
+    text-align: center;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+  }
+
+  :deep(.lims-table .pim-table-header-title) {
+    text-align: center;
+    width: 100%;
+  }
+
+  :deep(.lims-table .pim-table-header-extra) {
+    width: 100%;
+    margin-top: 4px;
+  }
+</style>

--
Gitblit v1.9.3