| | |
| | | <template> |
| | | <div class="app-container metric-maintenance"> |
| | | <!-- 左侧:检测标准列表 --> |
| | | <div class="left-panel"> |
| | | <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"> |
| | |
| | | :isSelection="true" |
| | | :tableLoading="tableLoading" |
| | | :rowClassName="rowClassNameCenter" |
| | | :rowClick="handleTableRowClick" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="handlePagination" |
| | | :total="page.total" |
| | |
| | | </el-select> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <!-- 右侧:标准参数列表 --> |
| | | <div class="right-panel"> |
| | | <!-- 右侧:标准参数列表 --> |
| | | <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"> |
| | |
| | | <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 link type="primary" :disabled="isStandardReadonly" @click="openParamDialog('edit', row)"> |
| | | 编辑 |
| | | </el-button> |
| | | <el-button link type="danger" size="small" :disabled="isStandardReadonly" @click="handleParamDelete(row)"> |
| | | <el-button link type="danger" :disabled="isStandardReadonly" @click="handleParamDelete(row)"> |
| | | 删除 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- 新增 / 编辑检测标准 --> |
| | | <StandardFormDialog |
| | |
| | | qualityTestStandardParamUpdate, |
| | | qualityTestStandardParamDel |
| | | } from '@/api/qualityManagement/metricMaintenance.js' |
| | | import { productProcessListPage } from '@/api/basicData/productProcess.js' |
| | | import StandardFormDialog from './StandardFormDialog.vue' |
| | | import ParamFormDialog from './ParamFormDialog.vue' |
| | | |
| | |
| | | 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' }] |
| | | } |
| | | }) |
| | | |
| | |
| | | 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) |
| | | } |
| | | } |
| | | // 工序下拉:来源于字典 product_process_type |
| | | const { product_process_type } = proxy.useDict('product_process_type') |
| | | const processOptions = computed(() => { |
| | | return (product_process_type?.value || []).map(item => ({ |
| | | label: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | | |
| | | // 当前选中的标准 & 右侧详情 |
| | | const currentStandard = ref(null) |
| | |
| | | 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 = { |
| | |
| | | }, |
| | | { |
| | | 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 = { |
| | |
| | | { |
| | | label: '备注', |
| | | prop: 'remark', |
| | | minWidth: 160 |
| | | minWidth: 160, |
| | | align: 'center' |
| | | }, |
| | | { |
| | | dataType: 'action', |
| | |
| | | current: page.current, |
| | | size: page.size |
| | | } |
| | | // processType:字典 product_process_type 的 value |
| | | // 兼容:如果后端仍接受 processId,这里两者都会带上 |
| | | params.processType = params.processId |
| | | qualityTestStandardListPage(params) |
| | | .then((res) => { |
| | | const records = res?.data?.records || [] |
| | |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection |
| | | |
| | | if (!selection.length) { |
| | | currentStandard.value = null |
| | | detailTableData.value = [] |
| | | return |
| | | } |
| | | |
| | | const nextStandard = selection[selection.length - 1] |
| | | if (currentStandard.value?.id === nextStandard.id) return |
| | | |
| | | currentStandard.value = nextStandard |
| | | loadDetail(nextStandard.id) |
| | | } |
| | | |
| | | // 批量审核:状态 1=批准,2=撤销 |
| | |
| | | getStandardList() |
| | | } |
| | | |
| | | // 左侧行点击,加载右侧参数 |
| | | // 表格行点击,加载右侧参数 |
| | | const handleTableRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadDetail(row.id) |
| | | } |
| | | |
| | | // 左侧行点击,加载右侧参数(保留用于标准编号列的点击) |
| | | const handleStandardRowClick = (row) => { |
| | | currentStandard.value = row |
| | | loadDetail(row.id) |
| | |
| | | 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 |
| | |
| | | |
| | | const submitStandardForm = () => { |
| | | const payload = { ...standardForm.value } |
| | | // processType:字典 product_process_type 的 value |
| | | payload.processType = payload.processId |
| | | const isEdit = standardOperationType.value === 'edit' |
| | | if (isEdit) { |
| | | qualityTestStandardUpdate(payload).then(() => { |
| | |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getProcessList() |
| | | getStandardList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .metric-maintenance { |
| | | display: flex; |
| | | gap: 16px; |
| | | .metric-maintenance-row { |
| | | width: 100%; |
| | | } |
| | | |
| | | .metric-maintenance-row .left-col, |
| | | .metric-maintenance-row .right-col { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | flex: 1; |
| | | 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 { |
| | |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 12px; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .toolbar-left { |
| | |
| | | |
| | | .toolbar-right { |
| | | flex-shrink: 0; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-label { |
| | |
| | | :deep(.center-table .el-table__body-wrapper td .cell) { |
| | | text-align: center !important; |
| | | } |
| | | </style> |
| | | |
| | | /* 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> |