src/views/qualityManagement/metricMaintenance/index.vue
@@ -1,860 +1,938 @@
<template>
  <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 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-row :gutter="16"
            class="metric-maintenance-row">
      <!-- 左侧:检测标准列表 -->
      <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="left-col">
      <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>
      </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 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"
                    :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>
      </el-col>
      <!-- 右侧:标准参数列表 -->
      <el-col :xs="24" :sm="24" :md="12" :lg="12" :xl="12" class="right-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)">
              编辑
          <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 link type="danger" size="small" :disabled="isStandardReadonly" @click="handleParamDelete(row)">
            <el-button type="danger"
                       plain
                       :disabled="!currentStandard || isStandardReadonly"
                       @click="handleParamBatchDelete">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
          </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"
    />
    <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 { 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'
  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()
  const { proxy } = getCurrentInstance();
// 类别 Tab(0=原材料,1=过程,2=出厂)
const activeTab = ref('0')
  // 类别 Tab(0=原材料,1=过程,2=出厂)
  const activeTab = ref("0");
// 左侧标准列表:整行内容居中(配合样式)
const rowClassNameCenter = () => 'row-center'
  // 左侧标准列表:整行内容居中(配合样式)
  const rowClassNameCenter = () => "row-center";
// 标准状态为“通过(1)”时,右侧参数禁止增删改
const isStandardReadonly = computed(() => {
  const state = currentStandard.value?.state
  return state === 1 || state === '1'
})
  // 标准状态为“通过(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' && (value === '' || value === null || value === undefined)) {
          callback(new Error('请选择工序'))
          return
        }
        callback()
      },
      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,
  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: '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 => activeTab.value === '1',
    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
  // 搜索条件
  const data = reactive({
    searchForm: {
      standardNo: "",
      standardName: "",
      remark: "",
      state: "",
      inspectType: "",
      processId: "",
    },
    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)
        }
    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 { 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,
        }));
      }
    ]
  }
])
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()
}
    } catch (error) {
      console.error("获取工序列表失败:", error);
    }
  };
// 查询列表
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
  // 当前选中的标准 & 右侧详情
  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: "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;
    }
    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",
    })
    .finally(() => {
      tableLoading.value = false
      .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("已取消");
      });
  };
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: activeTab.value === '1' ? '' : 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: String(row.inspectType) === '1' && 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: activeTab.value === '1' ? (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 (String(payload.inspectType) !== '1') {
    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()
})
  onMounted(() => {
    searchForm.value.inspectType = activeTab.value;
    getProcessList();
    getStandardList();
  });
</script>
<style scoped>
.metric-maintenance {
  padding: 0;
  min-width: 0;
}
  .metric-maintenance {
    padding: 0;
    min-width: 0;
  }
.metric-tabs {
  margin: 10px;
}
  .metric-tabs {
    margin: 10px;
  }
.metric-maintenance-row {
  width: 100%;
}
  .metric-maintenance-row {
    width: 100%;
  }
.metric-maintenance-row .left-col,
.metric-maintenance-row .right-col {
  margin-bottom: 16px;
}
  .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;
    min-width: 0;
    background: #ffffff;
    padding: 16px;
    box-sizing: border-box;
    overflow: hidden;
    height: 100%;
    min-height: 400px;
  }
}
.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  flex-wrap: wrap;
  gap: 8px;
}
  @media (max-width: 768px) {
    .left-panel,
    .right-panel {
      padding: 12px;
    }
  }
.toolbar-left {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px;
}
  .toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
    flex-wrap: wrap;
    gap: 8px;
  }
.toolbar-right {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
  .toolbar-left {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
  }
.search-label {
  margin: 0 4px 0 12px;
}
  .toolbar-right {
    flex-shrink: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
  }
.search-label:first-of-type {
  margin-left: 0;
}
  .search-label {
    margin: 0 4px 0 12px;
  }
.right-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}
  .search-label:first-of-type {
    margin-left: 0;
  }
.right-header .title {
  font-size: 16px;
  font-weight: 600;
}
  .right-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-bottom: 10px;
  }
.right-header .desc {
  font-size: 13px;
  color: #666;
}
  .right-header .title {
    font-size: 16px;
    font-weight: 600;
  }
.right-toolbar {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-bottom: 10px;
}
  .right-header .desc {
    font-size: 13px;
    color: #666;
  }
.link-text {
  color: #409eff;
  cursor: default;
}
  .right-toolbar {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    margin-bottom: 10px;
  }
.clickable-link {
  color: #409eff;
  cursor: pointer;
}
  .link-text {
    color: #409eff;
    cursor: default;
  }
.clickable-link:hover {
  text-decoration: underline;
}
  .clickable-link {
    color: #409eff;
    cursor: pointer;
  }
:deep(.row-center td) {
  text-align: center !important;
}
  .clickable-link:hover {
    text-decoration: underline;
  }
/* 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;
}
  :deep(.row-center td) {
    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;
}
  /* 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;
  }
:deep(.lims-table .pim-table-header-title) {
  text-align: center;
  width: 100%;
}
  /* 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-extra) {
  width: 100%;
  margin-top: 4px;
}
  :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>