张诺
10 小时以前 2b8c32366a2916dfbeac269eea94b2e6ef65f556
src/views/qualityManagement/metricMaintenance/index.vue
@@ -6,6 +6,8 @@
        <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>
@@ -16,6 +18,8 @@
        :page="page"
        :isSelection="true"
        :tableLoading="tableLoading"
        :rowClassName="rowClassNameCenter"
        :rowClick="handleTableRowClick"
        @selection-change="handleSelectionChange"
        @pagination="handlePagination"
        :total="page.total"
@@ -92,10 +96,10 @@
      </div>
      <div class="right-toolbar">
        <el-button type="primary" :disabled="!currentStandard" @click="openParamDialog('add')">
        <el-button type="primary" :disabled="!currentStandard || isStandardReadonly" @click="openParamDialog('add')">
          新增
        </el-button>
        <el-button type="danger" plain :disabled="!currentStandard" @click="handleParamBatchDelete">
        <el-button type="danger" plain :disabled="!currentStandard || isStandardReadonly" @click="handleParamBatchDelete">
          删除
        </el-button>
      </div>
@@ -104,6 +108,8 @@
        v-loading="detailLoading"
        :data="detailTableData"
        border
        :row-class-name="() => 'row-center'"
        class="center-table"
        style="width: 100%"
        height="calc(100vh - 220px)"
        @selection-change="handleParamSelectionChange"
@@ -117,10 +123,10 @@
        <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" @click="openParamDialog('edit', row)">
            <el-button link type="primary" size="small" :disabled="isStandardReadonly" @click="openParamDialog('edit', row)">
              编辑
            </el-button>
            <el-button link type="danger" size="small" @click="handleParamDelete(row)">
            <el-button link type="danger" size="small" :disabled="isStandardReadonly" @click="handleParamDelete(row)">
              删除
            </el-button>
          </template>
@@ -155,7 +161,7 @@
<script setup>
import { Search } from '@element-plus/icons-vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance } from 'vue'
import { ref, reactive, toRefs, onMounted, getCurrentInstance, computed } from 'vue'
import { ElMessageBox } from 'element-plus'
import {
  qualityTestStandardListPage,
@@ -163,6 +169,7 @@
  qualityTestStandardUpdate,
  qualityTestStandardDel,
  qualityTestStandardCopyParam,
  qualityTestStandardAudit,
  qualityTestStandardParamList,
  qualityTestStandardParamAdd,
  qualityTestStandardParamUpdate,
@@ -173,6 +180,15 @@
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({
@@ -197,7 +213,7 @@
    standardNo: [{ required: true, message: '请输入标准编号', trigger: 'blur' }],
    standardName: [{ required: true, message: '请输入标准名称', trigger: 'blur' }],
    inspectType: [{ required: true, message: '请选择检测类型', trigger: 'change' }],
    processId: [{ required: true, message: '请选择工序', trigger: 'change' }]
    processId: [{ required: false, message: '请选择工序', trigger: 'change' }]
  }
})
@@ -262,18 +278,21 @@
    dataType: 'slot',
    slot: 'standardNoCell',
    minWidth: 160,
    align: 'center',
    headerSlot: 'standardNoHeader'
  },
  {
    label: '标准名称',
    prop: 'standardName',
    minWidth: 180,
    align: 'center',
    headerSlot: 'standardNameHeader'
  },
  {
    label: '类别',
    prop: 'inspectType',
    headerSlot: 'inspectTypeHeader',
    align: 'center',
    dataType: 'tag',
    formatData: (val) => {
      const map = {
@@ -286,12 +305,21 @@
  },
  {
    label: '工序',
    prop: 'processId'
    prop: 'processId',
    align: 'center',
    dataType: 'tag',
    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 = {
@@ -310,7 +338,8 @@
  {
    label: '备注',
    prop: 'remark',
    minWidth: 160
    minWidth: 160,
    align: 'center'
  },
  {
    dataType: 'action',
@@ -399,7 +428,39 @@
  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)
@@ -425,6 +486,10 @@
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, {
@@ -449,6 +514,10 @@
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)
@@ -463,6 +532,10 @@
const handleParamDelete = async (row) => {
  if (!row?.id) return
  if (isStandardReadonly.value) {
    proxy.$message.warning('该标准已通过,参数不可编辑')
    return
  }
  try {
    await ElMessageBox.confirm('确认删除该参数?', '提示', { type: 'warning' })
  } catch {
@@ -474,6 +547,10 @@
}
const handleParamBatchDelete = async () => {
  if (isStandardReadonly.value) {
    proxy.$message.warning('该标准已通过,参数不可编辑')
    return
  }
  if (!paramSelectedRows.value.length) {
    proxy.$message.warning('请选择数据')
    return
@@ -503,14 +580,23 @@
      processId: ''
    })
  } else if (type === 'edit' && row) {
    Object.assign(standardForm.value, 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: row.processId !== null && row.processId !== undefined ? row.processId : ''
    })
  } else if (type === 'copy' && row) {
    const { id, ...rest } = row
    Object.assign(standardForm.value, {
      ...rest,
      id: undefined,
      standardNo: '',
      state: '0'
      state: '0',
      // 确保 inspectType 转换为字符串
      inspectType: rest.inspectType !== null && rest.inspectType !== undefined ? String(rest.inspectType) : ''
    })
  }
  standardDialogVisible.value = true
@@ -609,14 +695,41 @@
.metric-maintenance {
  display: flex;
  gap: 16px;
  min-width: 0; /* 允许 flex 子元素收缩 */
}
.left-panel,
.right-panel {
  flex: 1;
  min-width: 0; /* 允许 flex 子元素收缩 */
  background: #ffffff;
  padding: 16px;
  box-sizing: border-box;
  overflow: hidden; /* 防止内容溢出 */
}
/* 低分辨率适配 */
@media (max-width: 1400px) {
  .metric-maintenance {
    flex-direction: column;
  }
  .left-panel,
  .right-panel {
    width: 100%;
    min-width: 0;
  }
}
@media (max-width: 768px) {
  .metric-maintenance {
    gap: 12px;
  }
  .left-panel,
  .right-panel {
    padding: 12px;
  }
}
.toolbar {
@@ -624,6 +737,8 @@
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  flex-wrap: wrap;
  gap: 8px;
}
.toolbar-left {
@@ -635,6 +750,9 @@
.toolbar-right {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.search-label {
@@ -682,4 +800,35 @@
.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>