From 767fe69bf69ceaeefa5458d231fd7f727cb40f2c Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 14 一月 2026 17:50:29 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_New' into dev_New

---
 src/views/qualityManagement/metricMaintenance/index.vue | 1081 +++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 710 insertions(+), 371 deletions(-)

diff --git a/src/views/qualityManagement/metricMaintenance/index.vue b/src/views/qualityManagement/metricMaintenance/index.vue
index 016a4c1..876d10f 100644
--- a/src/views/qualityManagement/metricMaintenance/index.vue
+++ b/src/views/qualityManagement/metricMaintenance/index.vue
@@ -1,415 +1,754 @@
 <template>
-  <div class="app-container product-view">
-    <div class="left">
-      <div>
-        <el-input
-            v-model="search"
-            style="width: 210px"
-            placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
-            @change="searchFilter"
-            @clear="searchFilter"
+  <div class="app-container metric-maintenance">
+    <!-- 宸︿晶锛氭娴嬫爣鍑嗗垪琛� -->
+    <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>
+      </div>
+      <PIMTable
+        rowKey="id"
+        :column="standardColumns"
+        :tableData="standardTableData"
+        :page="page"
+        :isSelection="true"
+        :tableLoading="tableLoading"
+        :rowClassName="rowClassNameCenter"
+        @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
-            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>
-          </template>
-        </el-tree>
-      </div>
+            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 #inspectTypeHeader>
+          <el-select
+            v-model="searchForm.inspectType"
+            placeholder="绫诲埆"
+            clearable
+            size="small"
+            style="width: 120px"
+            @change="handleQuery"
+            @clear="handleQuery"
+          >
+            <el-option label="鍘熸潗鏂欐楠�" value="0" />
+            <el-option label="杩囩▼妫�楠�" value="1" />
+            <el-option label="鍑哄巶妫�楠�" value="2" />
+          </el-select>
+        </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>
-    <div class="right">
-      <div style="margin-bottom: 10px">
-        <el-button type="primary" @click="openModelDia('add')">
-          鏂板妫�娴嬫寚鏍�
+
+    <!-- 鍙充晶锛氭爣鍑嗗弬鏁板垪琛� -->
+    <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 @click="handleOut">瀵煎嚭</el-button>
-        <el-button
-            type="danger"
-            @click="handleDelete"
-            style="margin-left: 10px"
-            plain
-        >
+        <el-button type="danger" plain :disabled="!currentStandard || isStandardReadonly" @click="handleParamBatchDelete">
           鍒犻櫎
         </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-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-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>
-      </template>
-    </el-dialog>
+        <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>
+
+    <!-- 鏂板 / 缂栬緫妫�娴嬫爣鍑� -->
+    <StandardFormDialog
+      ref="standardFormDialogRef"
+      v-model="standardDialogVisible"
+      :operation-type="standardOperationType"
+      :form="standardForm"
+      :rules="standardRules"
+      :process-options="processOptions"
+      @confirm="submitStandardForm"
+      @close="closeStandardDialog"
+      @cancel="closeStandardDialog"
+    />
+
+    <ParamFormDialog
+      ref="paramFormDialogRef"
+      v-model="paramDialogVisible"
+      :operation-type="paramOperationType"
+      :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 { Search } from '@element-plus/icons-vue'
+import { ref, reactive, toRefs, onMounted, getCurrentInstance, computed } from '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);
+  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()
+
+// 宸︿晶鏍囧噯鍒楄〃锛氭暣琛屽唴瀹瑰眳涓紙閰嶅悎鏍峰紡锛�
+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' }],
+    inspectType: [{ required: true, message: '璇烽�夋嫨妫�娴嬬被鍨�', trigger: 'change' }],
+    processId: [{ required: true, message: '璇烽�夋嫨宸ュ簭', trigger: 'change' }]
+  }
+})
+
+const { searchForm, standardForm, standardRules } = toRefs(data)
+
+// 宸︿晶琛ㄦ牸
+const standardTableData = ref([])
+const selectedRows = ref([])
+const tableLoading = ref(false)
 const page = reactive({
   current: 1,
   size: 10,
-});
-const tableColumn = ref([
+  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: '',
+  defaultValue: ''
+})
+
+// 寮圭獥
+const standardDialogVisible = ref(false)
+const standardOperationType = ref('add') // add | edit | copy
+const standardFormDialogRef = ref(null)
+
+// 鍒楀畾涔�
+const standardColumns = ref([
   {
-    label: "鎸囨爣",
-    prop: "parameterItem",
+    label: '鏍囧噯缂栧彿',
+    prop: 'standardNo',
+    dataType: 'slot',
+    slot: 'standardNoCell',
+    minWidth: 160,
+    headerSlot: 'standardNoHeader'
   },
   {
-    label: "鍗曚綅",
-    prop: "unit",
+    label: '鏍囧噯鍚嶇О',
+    prop: 'standardName',
+    minWidth: 180,
+    headerSlot: 'standardNameHeader'
   },
   {
-    label: "鏍囧噯鍊�",
-    prop: "standardValue",
+    label: '绫诲埆',
+    prop: 'inspectType',
+    headerSlot: 'inspectTypeHeader',
+    dataType: 'tag',
+    formatData: (val) => {
+      const map = {
+        0: '鍘熸潗鏂欐楠�',
+        1: '杩囩▼妫�楠�',
+        2: '鍑哄巶妫�楠�'
+      }
+      return map[val] || val
+    }
   },
   {
-    label: "鍐呮帶鍊�",
-    prop: "controlValue",
+    label: '宸ュ簭',
+    prop: 'processId'
   },
   {
-    dataType: "action",
-    label: "鎿嶄綔",
-    align: "center",
+    label: '鐘舵��',
+    prop: 'state',
+    headerSlot: 'stateHeader',
+    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
+  },
+  {
+    dataType: 'action',
+    label: '鎿嶄綔',
+    align: 'center',
+    fixed: 'right',
+    width: 220,
     operation: [
       {
-        name: "缂栬緫",
-        type: "text",
+        name: '缂栬緫',
+        type: 'text',
         clickFun: (row) => {
-          openModelDia("edit", row);
-        },
+          openStandardDialog('edit', row)
+        }
       },
-    ],
-  },
-]);
-const selectedRows = ref([]);
-// 鎸囨爣寮规
-const modelDia = ref(false);
-const modelOperationType = ref("");
-const data = reactive({
-  modelForm: {
-    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);
-
-// 鏌ヨ浜у搧鏍�
-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 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(() => {
-    tableLoading.value = true;
-    qualityTestStandardDel(ids).then((res) => {
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-      getModelList();
-    }).finally(() => {
-      tableLoading.value = false;
-    });
-  }).catch(() => {
-    proxy.$modal.msg("宸插彇娑�");
-  });
-};
-
-// 鎻愪氦瑙勬牸鍨嬪彿淇敼
-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();
-        });
+      {
+        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 closeModelDia = () => {
-  proxy.$refs.modelFormRef.resetFields();
-  modelDia.value = false;
-};
-getProductTreeList();
+    ]
+  }
+])
+
+// 鏌ヨ鍒楄〃
+const getStandardList = () => {
+  tableLoading.value = true
+  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 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 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: '',
+      processId: ''
+    })
+  } else if (type === 'edit' && row) {
+    Object.assign(standardForm.value, row)
+  } else if (type === 'copy' && row) {
+    const { id, ...rest } = row
+    Object.assign(standardForm.value, {
+      ...rest,
+      id: undefined,
+      standardNo: '',
+      state: '0'
+    })
+  }
+  standardDialogVisible.value = true
+}
+
+const closeStandardDialog = () => {
+  standardDialogVisible.value = false
+  standardFormDialogRef.value?.resetFields?.()
+}
+
+const submitStandardForm = () => {
+  const payload = { ...standardForm.value }
+  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(() => {
+  getProcessList()
+  getStandardList()
+})
 </script>
 
 <style scoped>
-.product-view {
+.metric-maintenance {
   display: flex;
+  gap: 16px;
 }
-.left {
-  width: 380px;
-  padding: 16px;
-  background: #ffffff;
-}
-.right {
-  width: calc(100% - 380px);
-  padding: 16px;
-  margin-left: 20px;
-  background: #ffffff;
-}
-.custom-tree-node {
+
+.left-panel,
+.right-panel {
   flex: 1;
+  background: #ffffff;
+  padding: 16px;
+  box-sizing: border-box;
+}
+
+.toolbar {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 12px;
+}
+
+.toolbar-left {
   display: flex;
   align-items: center;
-  justify-content: space-between;
-  font-size: 14px;
-  padding-right: 8px;
+  flex-wrap: wrap;
+  gap: 4px;
 }
-.tree-node-content {
+
+.toolbar-right {
+  flex-shrink: 0;
+}
+
+.search-label {
+  margin: 0 4px 0 12px;
+}
+
+.search-label:first-of-type {
+  margin-left: 0;
+}
+
+.right-header {
   display: flex;
-  align-items: center; /* 鍨傜洿灞呬腑 */
-  height: 100%;
+  align-items: baseline;
+  justify-content: space-between;
+  margin-bottom: 10px;
 }
-.orange-icon {
-  color: orange;
-  font-size: 18px;
-  margin-right: 8px; /* 鍥炬爣涓庢枃瀛椾箣闂村姞鐐归棿璺� */
+
+.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;
 }
 </style>
\ No newline at end of file

--
Gitblit v1.9.3