feat(mes): 添加定时同步可生产数量到WMS及BOM项相关标准字段
- 在main.go中添加定时任务每10分钟同步可生产数量到WMS系统 - 为BomItem实体添加relatedStandard字段及相关CRUD方法 - 为InspectionRecord实体添加reportNo、materialCode、materialName等字段 - 更新ent schema确保新字段的验证和默认值设置 - 添加必要的数据库迁移和字段映射逻辑
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<script setup>
|
||||
defineOptions({ name: 'Inspection' })
|
||||
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import request from '../utils/request'
|
||||
import { getRealName } from '../utils/auth'
|
||||
import { fmtTime } from '../utils/format'
|
||||
@@ -17,6 +17,7 @@ const activeTab = ref('entry') // entry=质量检验(录入) / records=检验记
|
||||
|
||||
// 菜单按业务分开(来料/过程/完工检验):从路由 meta 锁定检验类型,同表同接口按类别过滤
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageType = String(route.meta.inspectionType || '')
|
||||
|
||||
/* ===================== Tab1 质量检验(录入,默认打开) ===================== */
|
||||
@@ -31,10 +32,14 @@ const passQty = ref(0)
|
||||
const checkDesc = ref('')
|
||||
const inspectionNo = ref('')
|
||||
const reportNo = ref('')
|
||||
// 新增字段(客户诉求 L107/L150/L494)
|
||||
const ownershipType = ref('none')
|
||||
const ownershipNo = ref('')
|
||||
const relatedStandard = ref('')
|
||||
const manufacturer = ref('')
|
||||
|
||||
// 不合格品处置(客户诉求 问题记录 L137-145:退货 / 报废 / 部分入库)
|
||||
const disposalType = ref('NONE')
|
||||
const disposalRemark = ref('')
|
||||
const returnTrackingNo = ref('')
|
||||
|
||||
// 待检编号列表(合并单/批量,统一一次提交)
|
||||
@@ -102,7 +107,7 @@ async function submitInspection() {
|
||||
return
|
||||
}
|
||||
if (!inspector.value.trim()) {
|
||||
ElMessage.warning('请填写检验员')
|
||||
ElMessage.warning('请填写记录人')
|
||||
return
|
||||
}
|
||||
// 判定不合格必须选择处置方式(不合格不入库、不上产线)
|
||||
@@ -131,21 +136,38 @@ async function submitInspection() {
|
||||
inspector: inspector.value.trim(),
|
||||
inspectionNo: inspectionNo.value.trim(),
|
||||
disposalType: status.value === '不合格' ? disposalType.value : 'NONE',
|
||||
disposalRemark: disposalRemark.value.trim(),
|
||||
returnTrackingNo: returnTrackingNo.value.trim(),
|
||||
ownershipType: ownershipType.value,
|
||||
ownershipNo: ownershipNo.value.trim(),
|
||||
relatedStandard: relatedStandard.value.trim(),
|
||||
manufacturer: manufacturer.value.trim(),
|
||||
})
|
||||
const n = data?.flipped ?? targetList.value.length
|
||||
ElMessage.success(`检验已记录:共 ${n} 条 → ${status.value}`)
|
||||
// 检验合格后引导去入库(方案 C / P1-6):携检测单号跳转,入库页自动回填免手抄
|
||||
const passedNo = inspectionNo.value.trim()
|
||||
const goInbound = status.value === '合格'
|
||||
clearAll()
|
||||
inspectQty.value = 0
|
||||
passQty.value = 0
|
||||
checkDesc.value = ''
|
||||
reportNo.value = ''
|
||||
disposalType.value = 'NONE'
|
||||
disposalRemark.value = ''
|
||||
returnTrackingNo.value = ''
|
||||
ownershipType.value = 'none'
|
||||
ownershipNo.value = ''
|
||||
relatedStandard.value = ''
|
||||
manufacturer.value = ''
|
||||
// 提交成功后主动刷新记录 Tab(用户切过去即可见最新)
|
||||
await loadRecords()
|
||||
if (goInbound) {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
passedNo ? `检验合格,是否携检测单号 ${passedNo} 前往入库?` : '检验合格,是否前往入库?',
|
||||
'前往入库', { type: 'success', confirmButtonText: '去入库', cancelButtonText: '留在本页' })
|
||||
router.push({ path: '/inbound', query: passedNo ? { inspectionNo: passedNo } : {} })
|
||||
} catch { /* 用户选择留在本页 */ }
|
||||
}
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
@@ -193,9 +215,11 @@ function defaultStart() {
|
||||
return `${y}-${m}-${day}`
|
||||
}
|
||||
|
||||
// 筛选独立条件(不再笼统关键字);默认近3个月
|
||||
// 筛选独立条件(客户诉求 L507-510:三框模糊查询 图号/名称/型号,框内模糊、框间取交集);默认近3个月
|
||||
const filters = reactive({
|
||||
targetId: '', materialCode: '', inspectionType: pageType, status: '', inspector: '',
|
||||
targetId: '', materialCode: '', materialName: '', spec: '',
|
||||
inspectionType: pageType, status: '', inspector: '',
|
||||
ownershipNo: '',
|
||||
startDate: defaultStart(), endDate: ''
|
||||
})
|
||||
const loading = ref(false)
|
||||
@@ -236,6 +260,9 @@ async function loadRecords() {
|
||||
params: {
|
||||
targetId: filters.targetId.trim(),
|
||||
materialCode: filters.materialCode.trim(),
|
||||
materialName: filters.materialName.trim(),
|
||||
spec: filters.spec.trim(),
|
||||
ownershipNo: filters.ownershipNo.trim(),
|
||||
inspectionType: filters.inspectionType,
|
||||
status: filters.status,
|
||||
inspector: filters.inspector.trim(),
|
||||
@@ -263,6 +290,9 @@ async function exportCsv() {
|
||||
await exportXlsxFetch('/api/inspection/export', {
|
||||
targetId: filters.targetId.trim(),
|
||||
materialCode: filters.materialCode.trim(),
|
||||
materialName: filters.materialName.trim(),
|
||||
spec: filters.spec.trim(),
|
||||
ownershipNo: filters.ownershipNo.trim(),
|
||||
inspectionType: filters.inspectionType,
|
||||
status: filters.status,
|
||||
inspector: filters.inspector.trim(),
|
||||
@@ -318,17 +348,31 @@ onMounted(() => {
|
||||
<el-form-item v-if="disposalType === 'RETURN'" label="货运单号">
|
||||
<el-input v-model="returnTrackingNo" placeholder="退货运单号(必填)" clearable style="width:280px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="处置说明">
|
||||
<el-input v-model="disposalRemark" placeholder="报废 / 退货原因(可空)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
<el-form-item label=" ">
|
||||
<el-alert type="warning" :closable="false" style="max-width:560px"
|
||||
title="不合格品自动隔离:库存质量状态置「不合格/待退」,禁止领料上线;退货必填货运单号。" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="检验员">
|
||||
<el-input v-model="inspector" placeholder="检验员姓名" clearable style="width:260px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="记录人">
|
||||
<el-input v-model="inspector" placeholder="记录人姓名" clearable style="width:260px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="归属">
|
||||
<div style="display:flex;gap:8px;width:100%;max-width:560px">
|
||||
<el-select v-model="ownershipType" style="width:150px">
|
||||
<el-option label="无" value="none" />
|
||||
<el-option label="工单号" value="workorder" />
|
||||
<el-option label="科技项目号" value="project" />
|
||||
</el-select>
|
||||
<el-input v-if="ownershipType !== 'none'" v-model="ownershipNo"
|
||||
placeholder="归属编号" clearable />
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="相关标准">
|
||||
<el-input v-model="relatedStandard" placeholder="检验细则/试验方案号(可空)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="生产厂家">
|
||||
<el-input v-model="manufacturer" placeholder="生产厂家(可空)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检测单号">
|
||||
<el-input v-model="inspectionNo" placeholder="检验报告单号(可空,与入库单关联)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
@@ -343,7 +387,7 @@ onMounted(() => {
|
||||
<el-form-item label="合格数量">
|
||||
<el-input-number v-model="passQty" :min="0" :max="999999" placeholder="合格件数(≤检验数量)" style="width:160px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检测说明">
|
||||
<el-form-item label="相关标准">
|
||||
<el-input v-model="checkDesc" placeholder="检验项目/方法/标准(可空)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
<el-divider content-position="left">待检编号(可扫/选多条,统一提交)</el-divider>
|
||||
@@ -357,7 +401,7 @@ onMounted(() => {
|
||||
clearable
|
||||
:remote-method="loadPicker"
|
||||
:loading="pickerLoading"
|
||||
:placeholder="`输入批次号/SN/物料编码搜索(最近100条)`"
|
||||
:placeholder="`输入批次号/SN/图号搜索(最近100条)`"
|
||||
style="width:100%"
|
||||
@change="addFromPicker"
|
||||
>
|
||||
@@ -400,11 +444,23 @@ onMounted(() => {
|
||||
<el-card shadow="never" class="mb12">
|
||||
<el-form inline @submit.prevent="search">
|
||||
<el-form-item label="批次/SN">
|
||||
<el-input v-model="filters.targetId" placeholder="批次号或 SN" clearable style="width:160px"
|
||||
<el-input v-model="filters.targetId" placeholder="批次号或 SN" clearable style="width:150px"
|
||||
@keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料编码">
|
||||
<el-input v-model="filters.materialCode" placeholder="物料编码" clearable style="width:150px"
|
||||
<el-form-item label="图号">
|
||||
<el-input v-model="filters.materialCode" placeholder="图号(模糊)" clearable style="width:140px"
|
||||
@keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="filters.materialName" placeholder="物料名称(模糊)" clearable style="width:140px"
|
||||
@keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="型号">
|
||||
<el-input v-model="filters.spec" placeholder="规格型号(模糊)" clearable style="width:140px"
|
||||
@keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="归属单号">
|
||||
<el-input v-model="filters.ownershipNo" placeholder="工单号/科技项目号" clearable style="width:150px"
|
||||
@keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="!pageType" label="检验类型">
|
||||
@@ -421,11 +477,11 @@ onMounted(() => {
|
||||
<el-option label="未检" value="未检" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="检验员">
|
||||
<el-input v-model="filters.inspector" placeholder="检验员" clearable style="width:120px"
|
||||
<el-form-item label="记录人">
|
||||
<el-input v-model="filters.inspector" placeholder="记录人" clearable style="width:120px"
|
||||
@keyup.enter="search" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验时间">
|
||||
<el-form-item label="记录日期">
|
||||
<el-date-picker v-model="filters.startDate" type="date" value-format="YYYY-MM-DD" placeholder="开始"
|
||||
style="width:130px" @change="search" />
|
||||
<span style="margin:0 6px">至</span>
|
||||
@@ -446,7 +502,10 @@ onMounted(() => {
|
||||
<template #default="{ row }">{{ targetTypeLabel(row.targetType) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="targetId" label="批次/SN" min-width="150" />
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="130" />
|
||||
<el-table-column prop="materialCode" label="图号" min-width="130" />
|
||||
<el-table-column prop="materialName" label="名称" min-width="120">
|
||||
<template #default="{ row }">{{ row.materialName || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检验类型" width="90" align="center">
|
||||
<template #default="{ row }">{{ typeLabel(row.inspectionType) }}</template>
|
||||
</el-table-column>
|
||||
@@ -468,10 +527,10 @@ onMounted(() => {
|
||||
<el-table-column prop="passQty" label="合格数" width="80" align="center">
|
||||
<template #default="{ row }">{{ row.passQty || 0 }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检测说明" min-width="140">
|
||||
<el-table-column label="相关标准" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip v-if="row.checkDesc" :content="row.checkDesc" placement="top">
|
||||
<span>{{ row.checkDesc }}</span>
|
||||
<el-tooltip v-if="row.checkDesc || row.relatedStandard" :content="row.relatedStandard || row.checkDesc" placement="top">
|
||||
<span>{{ row.relatedStandard || row.checkDesc }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
@@ -479,13 +538,19 @@ onMounted(() => {
|
||||
<el-table-column prop="reportNo" label="报检单号" min-width="130" align="center">
|
||||
<template #default="{ row }">{{ row.reportNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inspector" label="检验员" width="90" align="center">
|
||||
<el-table-column label="归属单号" min-width="130" align="center">
|
||||
<template #default="{ row }">{{ row.ownershipNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inspector" label="记录人" width="90" align="center">
|
||||
<template #default="{ row }">{{ row.inspector || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inspectionNo" label="检测单号" min-width="130" align="center">
|
||||
<template #default="{ row }">{{ row.inspectionNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="检验时间" width="155" align="center">
|
||||
<el-table-column prop="manufacturer" label="生产厂家" min-width="120" align="center">
|
||||
<template #default="{ row }">{{ row.manufacturer || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="记录日期" width="155" align="center">
|
||||
<template #default="{ row }">{{ fmtTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="130" align="center" fixed="right">
|
||||
@@ -514,7 +579,7 @@ onMounted(() => {
|
||||
<span style="margin-left:8px;color:#909399;font-size:12px">按当前时间区间与检验类别统计;每次检验独立计数,不合并记录</span>
|
||||
</div>
|
||||
<el-table :data="statsList" border size="small" v-loading="statsLoading" empty-text="点「统计」查看结果">
|
||||
<el-table-column prop="materialCode" label="物料编码" min-width="160" />
|
||||
<el-table-column prop="materialCode" label="图号" min-width="160" />
|
||||
<el-table-column prop="total" label="检验次数" width="110" align="center" />
|
||||
<el-table-column prop="pass" label="合格次数" width="110" align="center" />
|
||||
<el-table-column prop="fail" label="不合格次数" width="120" align="center" />
|
||||
@@ -534,7 +599,7 @@ onMounted(() => {
|
||||
<el-form-item label="批次/SN">
|
||||
<el-input :model-value="disposeDialog.row?.targetId || ''" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="物料编码">
|
||||
<el-form-item label="图号">
|
||||
<el-input :model-value="disposeDialog.row?.materialCode || ''" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="检验数 / 合格数">
|
||||
@@ -551,9 +616,6 @@ onMounted(() => {
|
||||
<el-form-item v-if="disposeDialog.type === 'RETURN'" label="货运单号" required>
|
||||
<el-input v-model="disposeDialog.trackingNo" placeholder="退货运单号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="处置说明">
|
||||
<el-input v-model="disposeDialog.remark" type="textarea" :rows="2" placeholder="原因(可空)" />
|
||||
</el-form-item>
|
||||
<el-alert v-if="disposeDialog.type === 'PARTIAL'" type="info" :closable="false"
|
||||
title="部分入库:按「合格数」拆分批次,合格部分入库、差额部分隔离待处置。" />
|
||||
</el-form>
|
||||
|
||||
Reference in New Issue
Block a user