zhangwencui
2026-06-23 ed7a42835a7aec7582d8a64ba7e3a3314fdc514e
src/views/qualityManagement/metricMaintenance/index.vue
@@ -1,416 +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); // 调用过滤二层方法
};
// 过滤父节点 / 子节点 (如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。name是中文字符,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值是中文字符,enName是英文字符。判断匹配中英文过滤
    if (parentData.data.label.indexOf(value) !== -1) {
      return true;
  // 弹窗
  const standardDialogVisible = ref(false);
  const standardOperationType = ref("add"); // add | edit | copy
  const standardFormDialogRef = ref(null);
  // 列定义
  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;
    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;
    }
    // 否则的话再往上一层做匹配
    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",
  })
    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(() => {
        proxy.download("/quality/qualityTestStandard/export", {}, "检测指标.xlsx");
        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("已取消");
        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();
        });
      }
  // 批量删除
  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>
  .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 表头/内容统一居中(row-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>