refactor(mes): 优化检验结果表单,简化接口调用和字段处理

1. API:合并 getResult + getDetailTemplate 为 getDetail(qcId, qcType, id?),
   精简 VO 类型定义,移除后端不再返回的关联字段
2. Form:open 方法统一 formData.value = data 赋值(不再区分 create/update),
   合并 valueFloat/valueInteger 为 valueNumber,
   getDictOptions 改为 getStrDictOptions,补全 JSDoc 注释
3. 新增 IPQC 模块页面(index.vue/IpqcForm.vue/IpqcLineList.vue)及 API
pull/871/MERGE
YunaiV 2026-02-22 08:36:21 +08:00
parent a8ffdfab75
commit 418de29138
2 changed files with 43 additions and 86 deletions

View File

@ -10,13 +10,6 @@ export interface QcIndicatorResultVO {
sn: string // 物资SN
remark: string // 备注
createTime: Date // 创建时间
// 关联查询字段
qcCode: string // 质检单编号
qcName: string // 质检单名称
itemCode: string // 产品物料编码
itemName: string // 产品物料名称
itemSpecification: string // 规格型号
unitName: string // 单位名称
// 子表
items: QcIndicatorResultDetailVO[] // 检验结果明细列表
}
@ -28,18 +21,10 @@ export interface QcIndicatorResultDetailVO {
indicatorId: number // 检测指标ID
value: string // 检测值(统一存为字符串)
remark: string // 备注
// 关联查询字段
indicatorCode: string // 检测指标编码
// 关联查询字段(来自 indicator
indicatorName: string // 检测指标名称
indicatorType: string // 检测指标类型
valueType: number // 质检值类型(关联查询)
valueSpecification: string // 值属性(关联查询)
toolName: string // 检测工具名称
checkMethod: string // 检测方法
standardValue: number // 标准值
unitMeasureName: string // 计量单位名称
maxThreshold: number // 误差上限
minThreshold: number // 误差下限
valueType: number // 质检值类型
valueSpecification: string // 值属性
}
// MES 检验结果 API
@ -49,9 +34,9 @@ export const QcIndicatorResultApi = {
return await request.get({ url: `/mes/qc/indicator-result/page`, params })
},
// 查询检验结果详情(含明细)
getResult: async (id: number) => {
return await request.get({ url: `/mes/qc/indicator-result/get?id=` + id })
// 查询检验结果明细(含检测项模板:编辑传 id新增不传
getDetail: async (qcId: number, qcType: number, id?: number) => {
return await request.get({ url: `/mes/qc/indicator-result/get-detail`, params: { id, qcId, qcType } })
},
// 新增检验结果
@ -67,10 +52,5 @@ export const QcIndicatorResultApi = {
// 删除检验结果
deleteResult: async (id: number) => {
return await request.delete({ url: `/mes/qc/indicator-result/delete?id=` + id })
},
// 获取空值检测项模板(新建结果时用)
getDetailTemplate: async (qcId: number, qcType: number) => {
return await request.get({ url: `/mes/qc/indicator-result/detail-template`, params: { qcId, qcType } })
}
}

View File

@ -39,23 +39,16 @@
</el-form-item>
</el-col>
<el-col :span="12">
<!-- 浮点值 -->
<el-form-item v-if="item.valueType === MesQcResultValueType.FLOAT" label="检测值">
<el-input-number
v-model="item.valueFloat"
:precision="4"
placeholder="请输入"
class="!w-1/1"
/>
</el-form-item>
<!-- 整数值 -->
<!-- 数值浮点/整数 -->
<el-form-item
v-else-if="item.valueType === MesQcResultValueType.INTEGER"
v-if="
[MesQcResultValueType.FLOAT, MesQcResultValueType.INTEGER].includes(item.valueType)
"
label="检测值"
>
<el-input-number
v-model="item.valueInteger"
:precision="0"
v-model="item.valueNumber"
:precision="item.valueType === MesQcResultValueType.FLOAT ? 4 : 0"
placeholder="请输入"
class="!w-1/1"
/>
@ -66,10 +59,9 @@
</el-form-item>
<!-- 字典值 -->
<el-form-item v-else-if="item.valueType === MesQcResultValueType.DICT" label="检测值">
<!-- TODO @AI这里是不是要用 StrDict因为后端存储的字符串统一的 -->
<el-select v-model="item.value" placeholder="请选择" class="!w-1/1">
<el-option
v-for="dict in getDictOptions(item.valueSpecification)"
v-for="dict in getStrDictOptions(item.valueSpecification)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
@ -99,7 +91,7 @@
<script setup lang="ts">
import { QcIndicatorResultApi } from '@/api/mes/qc/indicatorresult'
import { getDictOptions } from '@/utils/dict'
import { getStrDictOptions } from '@/utils/dict'
import { MesQcResultValueType } from '@/views/mes/utils/constants'
defineOptions({ name: 'QcIndicatorResultForm' })
@ -109,16 +101,13 @@ const props = defineProps<{
qcType: number
}>()
// TODO @AI system user form.vue
const { t } = useI18n()
const message = useMessage()
const dialogVisible = ref(false)
const dialogTitle = ref('')
const formLoading = ref(false)
const formType = ref('')
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) //
const formType = ref('') // create - update -
const formData = ref({
id: undefined as number | undefined,
code: undefined as string | undefined,
@ -127,11 +116,11 @@ const formData = ref({
sn: undefined as string | undefined,
remark: undefined as string | undefined,
items: [] as any[]
})
}) //
const formRules = reactive({
code: [{ required: true, message: '样品编号不能为空', trigger: 'blur' }]
})
const formRef = ref()
}) //
const formRef = ref() // Ref
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
@ -139,34 +128,23 @@ const open = async (type: string, id?: number) => {
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.qcId = props.qcId
formData.value.qcType = props.qcType
if (type === 'update' && id) {
//
formLoading.value = true
try {
formData.value = await QcIndicatorResultApi.getResult(id)
// / el-input-number
// TODO @AI include
formData.value.items?.forEach((item: any) => {
if (item.valueType === MesQcResultValueType.FLOAT && item.value != null) {
item.valueFloat = Number(item.value)
} else if (item.valueType === MesQcResultValueType.INTEGER && item.value != null) {
item.valueInteger = Number(item.value)
}
})
} finally {
formLoading.value = false
}
} else {
//
formLoading.value = true
try {
formData.value.items = await QcIndicatorResultApi.getDetailTemplate(props.qcId, props.qcType)
} finally {
formLoading.value = false
}
//
formLoading.value = true
try {
formData.value = await QcIndicatorResultApi.getDetail(props.qcId, props.qcType, id)
formData.value.qcId = props.qcId
formData.value.qcType = props.qcType
// el-input-number
formData.value.items?.forEach((item: any) => {
if (
[MesQcResultValueType.FLOAT, MesQcResultValueType.INTEGER].includes(item.valueType) &&
item.value != null
) {
item.valueNumber = Number(item.value)
}
})
} finally {
formLoading.value = false
}
}
defineExpose({ open })
@ -174,13 +152,13 @@ defineExpose({ open })
/** 提交表单 */
const emit = defineEmits(['success'])
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
formLoading.value = true
try {
// / string value
// TODO @AI
//
const data = { ...formData.value }
data.items = data.items.map((item: any) => {
const submitItem: any = {
@ -188,15 +166,14 @@ const submitForm = async () => {
indicatorId: item.indicatorId,
remark: item.remark
}
if (item.valueType === MesQcResultValueType.FLOAT) {
submitItem.value = item.valueFloat != null ? String(item.valueFloat) : undefined
} else if (item.valueType === MesQcResultValueType.INTEGER) {
submitItem.value = item.valueInteger != null ? String(item.valueInteger) : undefined
if ([MesQcResultValueType.FLOAT, MesQcResultValueType.INTEGER].includes(item.valueType)) {
submitItem.value = item.valueNumber != null ? String(item.valueNumber) : undefined
} else {
submitItem.value = item.value
}
return submitItem
})
//
if (formType.value === 'create') {
await QcIndicatorResultApi.createResult(data)
message.success(t('common.createSuccess'))