feat(mes): 添加工单、工作站、任务和客户信息字段

pull/871/MERGE
YunaiV 2026-03-25 21:04:24 +08:00
parent d79d6084c3
commit 7736768a3e
12 changed files with 153 additions and 53 deletions

View File

@ -7,7 +7,6 @@ export interface QcPendingInspectVO {
sourceDocCode: string
sourceLineId: number
qcType: number
qcTypeName: string
itemId: number
itemCode: string
itemName: string
@ -16,6 +15,15 @@ export interface QcPendingInspectVO {
quantity: number
vendorId: number
vendorName: string
// 工单/工作站/任务IPQC/RQC 场景)
workOrderId: number
workstationId: number
workstationName: string
taskId: number
taskCode: string
// 客户OQC/RQC 场景)
clientId: number
clientName: string
recordTime: string
}

View File

@ -11,9 +11,7 @@
<el-form-item label="缺陷编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入缺陷编码">
<template #append>
<el-button @click="generateCode" :disabled="formType === 'update'">
生成
</el-button>
<el-button @click="generateCode" :disabled="formType === 'update'"> 生成 </el-button>
</template>
</el-input>
</el-form-item>
@ -21,12 +19,7 @@
<el-input type="textarea" v-model="formData.name" placeholder="请输入缺陷描述" />
</el-form-item>
<el-form-item label="检测项类型" prop="type">
<el-select
v-model="formData.type"
placeholder="请选择检测项类型"
clearable
class="!w-1/1"
>
<el-select v-model="formData.type" placeholder="请选择检测项类型" clearable class="!w-1/1">
<el-option
v-for="dict in getStrDictOptions(DICT_TYPE.MES_INDICATOR_TYPE)"
:key="dict.value"
@ -36,12 +29,7 @@
</el-select>
</el-form-item>
<el-form-item label="缺陷等级" prop="level">
<el-select
v-model="formData.level"
placeholder="请选择缺陷等级"
clearable
class="!w-1/1"
>
<el-select v-model="formData.level" placeholder="请选择缺陷等级" clearable class="!w-1/1">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_DEFECT_LEVEL)"
:key="dict.value"

View File

@ -3,12 +3,7 @@
<Dialog title="缺陷记录" v-model="dialogVisible" width="900px">
<!-- 新增按钮 -->
<el-row class="mb-10px">
<el-button
type="primary"
plain
@click="handleAdd"
v-hasPermi="['mes:qc-defect:create']"
>
<el-button type="primary" plain @click="handleAdd" v-hasPermi="['mes:qc-defect:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增缺陷
</el-button>
</el-row>
@ -27,11 +22,7 @@
</el-table-column>
<el-table-column label="缺陷等级" align="center" width="140">
<template #default="scope">
<el-select
v-if="scope.row.editing"
v-model="scope.row.level"
placeholder="请选择"
>
<el-select v-if="scope.row.editing" v-model="scope.row.level" placeholder="请选择">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.MES_DEFECT_LEVEL)"
:key="dict.value"
@ -56,11 +47,7 @@
</el-table-column>
<el-table-column label="备注" align="center" min-width="150">
<template #default="scope">
<el-input
v-if="scope.row.editing"
v-model="scope.row.remark"
placeholder="请输入备注"
/>
<el-input v-if="scope.row.editing" v-model="scope.row.remark" placeholder="请输入备注" />
<span v-else>{{ scope.row.remark || '-' }}</span>
</template>
</el-table-column>

View File

@ -48,7 +48,11 @@
</el-select>
</el-form-item>
<!-- 动态显示FILE 类型 -->
<el-form-item v-if="formData.resultType === MesQcResultValueType.FILE" label="文件类型" prop="resultSpecification">
<el-form-item
v-if="formData.resultType === MesQcResultValueType.FILE"
label="文件类型"
prop="resultSpecification"
>
<el-radio-group v-model="formData.resultSpecification">
<el-radio label="IMG">图片/照片</el-radio>
<el-radio label="FILE">文件</el-radio>

View File

@ -62,8 +62,7 @@ const handleFilter = (query: string) => {
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
item.name?.toLowerCase().includes(keyword) || item.code?.toLowerCase().includes(keyword)
)
}

View File

@ -49,6 +49,8 @@
v-model="formData.workOrderId"
placeholder="请选择生产工单"
class="!w-1/1"
:disabled="isFromPendingTask"
@change="handleWorkOrderChange"
/>
</el-form-item>
</el-col>
@ -58,12 +60,19 @@
v-model="formData.workstationId"
placeholder="请选择工位"
class="!w-1/1"
:disabled="isFromPendingTask"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="生产任务" prop="taskId">
<ProTaskSelect v-model="formData.taskId" placeholder="请选择生产任务" class="!w-1/1" />
<ProTaskSelect
v-model="formData.taskId"
:workOrderId="formData.workOrderId"
placeholder="请选择生产任务"
class="!w-1/1"
:disabled="isFromPendingTask || (!isFromPendingTask && !formData.workOrderId)"
/>
</el-form-item>
</el-col>
</el-row>
@ -78,6 +87,7 @@
:precision="2"
placeholder="请输入检测数量"
class="!w-1/1"
:disabled="isFromPendingTask"
/>
</el-form-item>
</el-col>
@ -280,6 +290,9 @@ const dialogTitle = computed(() => {
return titles[formType.value] || t('action.' + formType.value)
}) // formType
const isDetail = computed(() => formType.value === 'detail') //
const isFromPendingTask = computed(
() => formType.value === 'create' && formData.value.sourceDocId != null
) //
const formData = ref({
id: undefined as number | undefined,
@ -343,8 +356,13 @@ const handleScrapChanged = () => {
(formData.value.otherScrapQuantity || 0)
}
/** 生产工单变更:清空关联的任务等信息 */
const handleWorkOrderChange = () => {
formData.value.taskId = undefined
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
const open = async (type: string, id?: number, data?: QcIpqcVO) => {
dialogVisible.value = true
formType.value = type
activeTab.value = 'line'
@ -357,6 +375,9 @@ const open = async (type: string, id?: number) => {
} finally {
formLoading.value = false
}
} else if (data) {
// pending inspect
Object.assign(formData.value, data)
}
}
defineExpose({ open }) // open

View File

@ -32,12 +32,22 @@
<el-row :gutter="16">
<el-col :span="8">
<el-form-item label="产品物料" prop="itemId">
<MdItemSelect v-model="formData.itemId" placeholder="请选择产品物料" class="!w-1/1" />
<MdItemSelect
v-model="formData.itemId"
placeholder="请选择产品物料"
class="!w-1/1"
:disabled="isFromPendingTask"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="客户" prop="clientId">
<MdClientSelect v-model="formData.clientId" placeholder="请选择客户" class="!w-1/1" />
<MdClientSelect
v-model="formData.clientId"
placeholder="请选择客户"
class="!w-1/1"
:disabled="isFromPendingTask"
/>
</el-form-item>
</el-col>
<el-col :span="8">
@ -57,6 +67,7 @@
:precision="2"
placeholder="请输入发货数量"
class="!w-1/1"
:disabled="isFromPendingTask"
/>
</el-form-item>
</el-col>
@ -235,6 +246,9 @@ const dialogTitle = computed(() => {
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const activeTab = ref('line') //
const isFromPendingTask = computed(
() => formType.value === 'create' && formData.value.sourceDocId != null
) //
const formData = ref({
id: undefined as number | undefined,
@ -284,7 +298,7 @@ const generateCode = () => {
}
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
const open = async (type: string, id?: number, data?: QcOqcVO) => {
dialogVisible.value = true
formType.value = type
activeTab.value = 'line'
@ -297,6 +311,9 @@ const open = async (type: string, id?: number) => {
} finally {
formLoading.value = false
}
} else if (data) {
// pending inspect
Object.assign(formData.value, data)
}
}
defineExpose({ open }) // open

View File

@ -57,7 +57,6 @@
<dict-tag :type="DICT_TYPE.MES_QC_TYPE" :value="scope.row.qcType" />
</template>
</el-table-column>
<el-table-column label="检验类型名称" align="center" prop="qcTypeName" width="120" />
<el-table-column label="物料编码" align="center" prop="itemCode" width="130" />
<el-table-column label="物料名称" align="center" prop="itemName" min-width="150" />
<el-table-column label="规格型号" align="center" prop="specification" width="130" />
@ -72,7 +71,34 @@
v-if="scope.row.qcType === MesQcTypeEnum.IQC"
v-hasPermi="['mes:qc-iqc:create']"
>
创建检验单
来料检验
</el-button>
<el-button
link
type="primary"
@click="handleCreateIpqc(scope.row)"
v-if="scope.row.qcType === MesQcTypeEnum.IPQC"
v-hasPermi="['mes:qc-ipqc:create']"
>
过程检验
</el-button>
<el-button
link
type="primary"
@click="handleCreateRqc(scope.row)"
v-if="scope.row.qcType === MesQcTypeEnum.RQC"
v-hasPermi="['mes:qc-rqc:create']"
>
退货检验
</el-button>
<el-button
link
type="primary"
@click="handleCreateOqc(scope.row)"
v-if="scope.row.qcType === MesQcTypeEnum.OQC"
v-hasPermi="['mes:qc-oqc:create']"
>
出货检验
</el-button>
</template>
</el-table-column>
@ -85,8 +111,11 @@
/>
</ContentWrap>
<!-- IQC 表单弹窗 -->
<!-- 表单弹窗 -->
<IqcForm ref="iqcFormRef" @success="getList" />
<IpqcForm ref="ipqcFormRef" @success="getList" />
<RqcForm ref="rqcFormRef" @success="getList" />
<OqcForm ref="oqcFormRef" @success="getList" />
</template>
<script setup lang="ts">
@ -95,6 +124,9 @@ import { QcPendingInspectApi, QcPendingInspectVO } from '@/api/mes/qc/pendingins
import { MesQcTypeEnum } from '@/views/mes/utils/constants'
import MdItemSelect from '@/views/mes/md/item/components/MdItemSelect.vue'
import IqcForm from '@/views/mes/qc/iqc/IqcForm.vue'
import IpqcForm from '@/views/mes/qc/ipqc/IpqcForm.vue'
import RqcForm from '@/views/mes/qc/rqc/RqcForm.vue'
import OqcForm from '@/views/mes/qc/oqc/OqcForm.vue'
defineOptions({ name: 'MesQcPendingInspect' })
@ -134,7 +166,7 @@ const resetQuery = () => {
handleQuery()
}
/** 创建 IQC 检验单 */
/** 创建 IQC 来料检验单 */
const iqcFormRef = ref()
const handleCreateIqc = (row: QcPendingInspectVO) => {
iqcFormRef.value.open('create', undefined, {
@ -149,6 +181,52 @@ const handleCreateIqc = (row: QcPendingInspectVO) => {
})
}
/** 创建 IPQC 过程检验单 */
const ipqcFormRef = ref()
const handleCreateIpqc = (row: QcPendingInspectVO) => {
ipqcFormRef.value.open('create', undefined, {
sourceDocId: row.sourceDocId,
sourceDocType: row.sourceDocType,
sourceLineId: row.sourceLineId,
itemId: row.itemId,
workOrderId: row.workOrderId,
workstationId: row.workstationId,
taskId: row.taskId,
checkQuantity: row.quantity,
inspectDate: row.recordTime,
name: row.sourceDocCode + ' 过程检验单'
})
}
/** 创建 RQC 退货检验单 */
const rqcFormRef = ref()
const handleCreateRqc = (row: QcPendingInspectVO) => {
rqcFormRef.value.open('create', undefined, {
sourceDocId: row.sourceDocId,
sourceDocType: row.sourceDocType,
sourceLineId: row.sourceLineId,
itemId: row.itemId,
checkQuantity: row.quantity,
inspectDate: row.recordTime,
name: row.sourceDocCode + ' 退货检验单'
})
}
/** 创建 OQC 出货检验单 */
const oqcFormRef = ref()
const handleCreateOqc = (row: QcPendingInspectVO) => {
oqcFormRef.value.open('create', undefined, {
sourceDocId: row.sourceDocId,
sourceDocType: row.sourceDocType,
sourceLineId: row.sourceLineId,
clientId: row.clientId,
itemId: row.itemId,
outQuantity: row.quantity,
outDate: row.recordTime,
name: row.sourceDocCode + ' 出货检验单'
})
}
/** 初始化 **/
onMounted(() => {
getList()

View File

@ -77,6 +77,7 @@
:precision="2"
placeholder="请输入"
class="!w-1/1"
:disabled="isFromPendingTask"
/>
</el-form-item>
</el-col>

View File

@ -150,7 +150,10 @@
<script setup lang="ts">
import { DICT_TYPE } from '@/utils/dict'
import { QcTemplateIndicatorApi, QcTemplateIndicatorVO } from '@/api/mes/qc/template/indicator/index'
import {
QcTemplateIndicatorApi,
QcTemplateIndicatorVO
} from '@/api/mes/qc/template/indicator/index'
import QcIndicatorSelect from '@/views/mes/qc/indicator/components/QcIndicatorSelect.vue'
import MdUnitMeasureSelect from '@/views/mes/md/unitmeasure/components/MdUnitMeasureSelect.vue'

View File

@ -62,8 +62,7 @@ const handleFilter = (query: string) => {
const keyword = query.toLowerCase()
filteredList.value = allList.value.filter(
(item) =>
item.name?.toLowerCase().includes(keyword) ||
item.code?.toLowerCase().includes(keyword)
item.name?.toLowerCase().includes(keyword) || item.code?.toLowerCase().includes(keyword)
)
}

View File

@ -43,12 +43,7 @@
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
clearable
class="!w-240px"
>
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"