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 sn: string // 物资SN
remark: string // 备注 remark: string // 备注
createTime: Date // 创建时间 createTime: Date // 创建时间
// 关联查询字段
qcCode: string // 质检单编号
qcName: string // 质检单名称
itemCode: string // 产品物料编码
itemName: string // 产品物料名称
itemSpecification: string // 规格型号
unitName: string // 单位名称
// 子表 // 子表
items: QcIndicatorResultDetailVO[] // 检验结果明细列表 items: QcIndicatorResultDetailVO[] // 检验结果明细列表
} }
@ -28,18 +21,10 @@ export interface QcIndicatorResultDetailVO {
indicatorId: number // 检测指标ID indicatorId: number // 检测指标ID
value: string // 检测值(统一存为字符串) value: string // 检测值(统一存为字符串)
remark: string // 备注 remark: string // 备注
// 关联查询字段 // 关联查询字段(来自 indicator
indicatorCode: string // 检测指标编码
indicatorName: string // 检测指标名称 indicatorName: string // 检测指标名称
indicatorType: string // 检测指标类型 valueType: number // 质检值类型
valueType: number // 质检值类型(关联查询) valueSpecification: string // 值属性
valueSpecification: string // 值属性(关联查询)
toolName: string // 检测工具名称
checkMethod: string // 检测方法
standardValue: number // 标准值
unitMeasureName: string // 计量单位名称
maxThreshold: number // 误差上限
minThreshold: number // 误差下限
} }
// MES 检验结果 API // MES 检验结果 API
@ -49,9 +34,9 @@ export const QcIndicatorResultApi = {
return await request.get({ url: `/mes/qc/indicator-result/page`, params }) return await request.get({ url: `/mes/qc/indicator-result/page`, params })
}, },
// 查询检验结果详情(含明细) // 查询检验结果明细(含检测项模板:编辑传 id新增不传
getResult: async (id: number) => { getDetail: async (qcId: number, qcType: number, id?: number) => {
return await request.get({ url: `/mes/qc/indicator-result/get?id=` + id }) 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) => { deleteResult: async (id: number) => {
return await request.delete({ url: `/mes/qc/indicator-result/delete?id=` + id }) 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-form-item>
</el-col> </el-col>
<el-col :span="12"> <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 <el-form-item
v-else-if="item.valueType === MesQcResultValueType.INTEGER" v-if="
[MesQcResultValueType.FLOAT, MesQcResultValueType.INTEGER].includes(item.valueType)
"
label="检测值" label="检测值"
> >
<el-input-number <el-input-number
v-model="item.valueInteger" v-model="item.valueNumber"
:precision="0" :precision="item.valueType === MesQcResultValueType.FLOAT ? 4 : 0"
placeholder="请输入" placeholder="请输入"
class="!w-1/1" class="!w-1/1"
/> />
@ -66,10 +59,9 @@
</el-form-item> </el-form-item>
<!-- 字典值 --> <!-- 字典值 -->
<el-form-item v-else-if="item.valueType === MesQcResultValueType.DICT" label="检测值"> <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-select v-model="item.value" placeholder="请选择" class="!w-1/1">
<el-option <el-option
v-for="dict in getDictOptions(item.valueSpecification)" v-for="dict in getStrDictOptions(item.valueSpecification)"
:key="dict.value" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="dict.value" :value="dict.value"
@ -99,7 +91,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { QcIndicatorResultApi } from '@/api/mes/qc/indicatorresult' import { QcIndicatorResultApi } from '@/api/mes/qc/indicatorresult'
import { getDictOptions } from '@/utils/dict' import { getStrDictOptions } from '@/utils/dict'
import { MesQcResultValueType } from '@/views/mes/utils/constants' import { MesQcResultValueType } from '@/views/mes/utils/constants'
defineOptions({ name: 'QcIndicatorResultForm' }) defineOptions({ name: 'QcIndicatorResultForm' })
@ -109,16 +101,13 @@ const props = defineProps<{
qcType: number qcType: number
}>() }>()
// TODO @AI system user form.vue
const { t } = useI18n() const { t } = useI18n()
const message = useMessage() const message = useMessage()
const dialogVisible = ref(false) const dialogVisible = ref(false) //
const dialogTitle = ref('') const dialogTitle = ref('') //
const formLoading = ref(false) const formLoading = ref(false) //
const formType = ref('') const formType = ref('') // create - update -
const formData = ref({ const formData = ref({
id: undefined as number | undefined, id: undefined as number | undefined,
code: undefined as string | undefined, code: undefined as string | undefined,
@ -127,11 +116,11 @@ const formData = ref({
sn: undefined as string | undefined, sn: undefined as string | undefined,
remark: undefined as string | undefined, remark: undefined as string | undefined,
items: [] as any[] items: [] as any[]
}) }) //
const formRules = reactive({ const formRules = reactive({
code: [{ required: true, message: '样品编号不能为空', trigger: 'blur' }] code: [{ required: true, message: '样品编号不能为空', trigger: 'blur' }]
}) }) //
const formRef = ref() const formRef = ref() // Ref
/** 打开弹窗 */ /** 打开弹窗 */
const open = async (type: string, id?: number) => { const open = async (type: string, id?: number) => {
@ -139,34 +128,23 @@ const open = async (type: string, id?: number) => {
dialogTitle.value = t('action.' + type) dialogTitle.value = t('action.' + type)
formType.value = type formType.value = type
resetForm() resetForm()
formData.value.qcId = props.qcId //
formData.value.qcType = props.qcType formLoading.value = true
try {
if (type === 'update' && id) { formData.value = await QcIndicatorResultApi.getDetail(props.qcId, props.qcType, id)
// formData.value.qcId = props.qcId
formLoading.value = true formData.value.qcType = props.qcType
try { // el-input-number
formData.value = await QcIndicatorResultApi.getResult(id) formData.value.items?.forEach((item: any) => {
// / el-input-number if (
// TODO @AI include [MesQcResultValueType.FLOAT, MesQcResultValueType.INTEGER].includes(item.valueType) &&
formData.value.items?.forEach((item: any) => { item.value != null
if (item.valueType === MesQcResultValueType.FLOAT && item.value != null) { ) {
item.valueFloat = Number(item.value) item.valueNumber = Number(item.value)
} else if (item.valueType === MesQcResultValueType.INTEGER && item.value != null) { }
item.valueInteger = Number(item.value) })
} } finally {
}) formLoading.value = false
} finally {
formLoading.value = false
}
} else {
//
formLoading.value = true
try {
formData.value.items = await QcIndicatorResultApi.getDetailTemplate(props.qcId, props.qcType)
} finally {
formLoading.value = false
}
} }
} }
defineExpose({ open }) defineExpose({ open })
@ -174,13 +152,13 @@ defineExpose({ open })
/** 提交表单 */ /** 提交表单 */
const emit = defineEmits(['success']) const emit = defineEmits(['success'])
const submitForm = async () => { const submitForm = async () => {
//
if (!formRef) return if (!formRef) return
const valid = await formRef.value.validate() const valid = await formRef.value.validate()
if (!valid) return if (!valid) return
formLoading.value = true formLoading.value = true
try { try {
// / string value //
// TODO @AI
const data = { ...formData.value } const data = { ...formData.value }
data.items = data.items.map((item: any) => { data.items = data.items.map((item: any) => {
const submitItem: any = { const submitItem: any = {
@ -188,15 +166,14 @@ const submitForm = async () => {
indicatorId: item.indicatorId, indicatorId: item.indicatorId,
remark: item.remark remark: item.remark
} }
if (item.valueType === MesQcResultValueType.FLOAT) { if ([MesQcResultValueType.FLOAT, MesQcResultValueType.INTEGER].includes(item.valueType)) {
submitItem.value = item.valueFloat != null ? String(item.valueFloat) : undefined submitItem.value = item.valueNumber != null ? String(item.valueNumber) : undefined
} else if (item.valueType === MesQcResultValueType.INTEGER) {
submitItem.value = item.valueInteger != null ? String(item.valueInteger) : undefined
} else { } else {
submitItem.value = item.value submitItem.value = item.value
} }
return submitItem return submitItem
}) })
//
if (formType.value === 'create') { if (formType.value === 'create') {
await QcIndicatorResultApi.createResult(data) await QcIndicatorResultApi.createResult(data)
message.success(t('common.createSuccess')) message.success(t('common.createSuccess'))