docs(deployment): 更新部署手册和业务架构说明
- 更新MES和WMS服务端口配置说明 - 详细说明产线工位设备配置(扫码枪+拧紧枪) - 明确AGV配送和接驳台的模拟模式与真实对接方案 - 更新WMS中AGV配送默认模拟模式说明 - 完善厂内物流(AGV/接驳台)的业务架构约束 - 修订临时文档为详细的项目问题和解决方案规划
This commit is contained in:
@@ -10,6 +10,7 @@ import { exportXlsxFetch } from '../utils/export'
|
||||
import { can } from '../utils/perm'
|
||||
import PageHelp from '../components/PageHelp.vue'
|
||||
import AttachmentPanel from '../components/AttachmentPanel.vue'
|
||||
import MaterialSelect from '../components/MaterialSelect.vue'
|
||||
import { helpInspection } from '../help'
|
||||
|
||||
// ===== 多 Tab:录入在前默认打开,记录在后点击才见(参照出库管理) =====
|
||||
@@ -19,9 +20,13 @@ const activeTab = ref('entry') // entry=质量检验(录入) / records=检验记
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const pageType = String(route.meta.inspectionType || '')
|
||||
// 三检边界(需求23/30):来料检=入库物料验收;过程检=产线在制巡检;完工检=成品 SN 终检。
|
||||
const isFinal = pageType === 'finished'
|
||||
const isIncoming = pageType === 'incoming'
|
||||
|
||||
/* ===================== Tab1 质量检验(录入,默认打开) ===================== */
|
||||
const targetType = ref('BATCH')
|
||||
// 完工检对象一定是成品 SN,无「批次」选项(临时.md L101)
|
||||
const targetType = ref(isFinal ? 'SN' : 'BATCH')
|
||||
const status = ref('合格')
|
||||
const inspector = ref(getRealName())
|
||||
const submitting = ref(false)
|
||||
@@ -32,8 +37,8 @@ const passQty = ref(0)
|
||||
const checkDesc = ref('')
|
||||
const inspectionNo = ref('')
|
||||
const reportNo = ref('')
|
||||
// 新增字段(客户诉求 L107/L150/L494)
|
||||
const ownershipType = ref('none')
|
||||
// 新增字段(客户诉求 L107/L150/L494;需求22:归属默认「其他」)
|
||||
const ownershipType = ref('other')
|
||||
const ownershipNo = ref('')
|
||||
const relatedStandard = ref('')
|
||||
const manufacturer = ref('')
|
||||
@@ -63,9 +68,10 @@ async function loadPicker(kw = '') {
|
||||
pickerLoading.value = true
|
||||
try {
|
||||
const mm = targetType.value === 'BATCH' ? 1 : 2
|
||||
const data = await request.get('/stock/query', {
|
||||
params: { manageMode: mm, keyword: kw || '', page: 1, pageSize: 100 }
|
||||
})
|
||||
const params = { manageMode: mm, keyword: kw || '', page: 1, pageSize: 100 }
|
||||
// 完工检只从成品库存(category=3)拾取 SN
|
||||
if (isFinal) params.category = 3
|
||||
const data = await request.get('/stock/query', { params })
|
||||
pickerOptions.value = data?.list || []
|
||||
} catch (e) {
|
||||
pickerOptions.value = []
|
||||
@@ -112,7 +118,7 @@ async function submitInspection() {
|
||||
}
|
||||
// 判定不合格必须选择处置方式(不合格不入库、不上产线)
|
||||
if (status.value === '不合格' && disposalType.value === 'NONE') {
|
||||
ElMessage.warning('判定不合格时必须选择处置方式(退货 / 报废 / 部分入库)')
|
||||
ElMessage.warning('判定不合格时必须选择处置方式(退货 / 换修 / 让步接收 / 报废 / 部分入库)')
|
||||
return
|
||||
}
|
||||
if (status.value === '不合格' && disposalType.value === 'RETURN' && !returnTrackingNo.value.trim()) {
|
||||
@@ -123,6 +129,17 @@ async function submitInspection() {
|
||||
ElMessage.warning('「部分入库」一次只能处理 1 个批次,请分开提交')
|
||||
return
|
||||
}
|
||||
// 报检数守恒校验(临时.md §六:报检数 = 合格数 + 不合格数)
|
||||
const iq = Number(inspectQty.value) || 0
|
||||
const pq = Number(passQty.value) || 0
|
||||
if (iq > 0 && pq > iq) {
|
||||
ElMessage.warning('合格数不能大于报检数(报检数 = 合格数 + 不合格数)')
|
||||
return
|
||||
}
|
||||
if (status.value === '合格' && iq > 0 && pq !== iq) {
|
||||
ElMessage.warning('判定合格时,合格数应等于报检数(否则请改判不合格并选处置方式)')
|
||||
return
|
||||
}
|
||||
submitting.value = true
|
||||
try {
|
||||
const data = await request.post('/inspection/batch-flip', {
|
||||
@@ -154,7 +171,7 @@ async function submitInspection() {
|
||||
reportNo.value = ''
|
||||
disposalType.value = 'NONE'
|
||||
returnTrackingNo.value = ''
|
||||
ownershipType.value = 'none'
|
||||
ownershipType.value = 'other'
|
||||
ownershipNo.value = ''
|
||||
relatedStandard.value = ''
|
||||
manufacturer.value = ''
|
||||
@@ -225,13 +242,26 @@ const filters = reactive({
|
||||
const loading = ref(false)
|
||||
const statsList = ref([])
|
||||
const statsLoading = ref(false)
|
||||
// 需求13/58:统计必须先选物料再点「统计」,不做全表实时聚合
|
||||
const statsMaterialCode = ref('')
|
||||
const statsQueried = ref(false)
|
||||
async function loadStats() {
|
||||
if (!statsMaterialCode.value) {
|
||||
ElMessage.warning('请先选择物料再统计')
|
||||
return
|
||||
}
|
||||
statsLoading.value = true
|
||||
try {
|
||||
const data = await request.get('/inspection/stats', {
|
||||
params: { inspectionType: filters.inspectionType, startDate: filters.startDate, endDate: filters.endDate }
|
||||
params: {
|
||||
inspectionType: filters.inspectionType,
|
||||
materialCode: statsMaterialCode.value,
|
||||
startDate: filters.startDate,
|
||||
endDate: filters.endDate
|
||||
}
|
||||
})
|
||||
statsList.value = data?.list || []
|
||||
statsQueried.value = true
|
||||
} finally {
|
||||
statsLoading.value = false
|
||||
}
|
||||
@@ -249,9 +279,14 @@ function targetTypeLabel(t) {
|
||||
}
|
||||
// 不合格处置方式显示(NONE=未处置)
|
||||
function disposalLabel(t) {
|
||||
const m = { RETURN: '退货', SCRAP: '报废', PARTIAL: '部分入库' }
|
||||
const m = { RETURN: '退货', SCRAP: '报废', PARTIAL: '部分入库', REWORK: '换修', CONCESSION: '让步接收' }
|
||||
return m[t] || '未处置'
|
||||
}
|
||||
// 归属类型显示(需求22:工单编号/科技项目号/其他;旧 none/空 → 其他)
|
||||
function ownershipTypeLabel(t) {
|
||||
const m = { workorder: '工单编号', project: '科技项目号' }
|
||||
return m[t] || '其他'
|
||||
}
|
||||
|
||||
async function loadRecords() {
|
||||
loading.value = true
|
||||
@@ -321,9 +356,16 @@ onMounted(() => {
|
||||
<!-- ============ 质量检验(录入,默认打开) ============ -->
|
||||
<el-tab-pane label="质量检验录入" name="entry">
|
||||
<el-card shadow="never" style="max-width:860px;margin:0 auto">
|
||||
<el-alert :closable="false" show-icon class="mb12" :type="isFinal ? 'success' : 'info'">
|
||||
<template #title>
|
||||
<span v-if="isIncoming">来料检验:对入库物料验收(按入库批次/SN),合格才能入库上架,不合格隔离退货。</span>
|
||||
<span v-else-if="isFinal">完工检验:对 MES 回流的成品 SN 做终检(对象固定为 SN),合格后成品方可发货;不合格可返修/让步接收。</span>
|
||||
<span v-else>过程检验:对产线在制物料/半成品巡检,判定质量状态。</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
<el-form label-width="96px">
|
||||
<!-- 目标类型直接改变输入框标题与占位,直观体现当前录入对象 -->
|
||||
<el-form-item label="目标类型">
|
||||
<!-- 目标类型直接改变输入框标题与占位;完工检对象固定为成品 SN,不展示切换 -->
|
||||
<el-form-item v-if="!isFinal" label="目标类型">
|
||||
<el-radio-group v-model="targetType" @change="() => loadPicker()">
|
||||
<el-radio-button value="BATCH">批次 (结构件)</el-radio-button>
|
||||
<el-radio-button value="SN">序列号 SN (电气件)</el-radio-button>
|
||||
@@ -336,11 +378,13 @@ onMounted(() => {
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 不合格品处置(判定不合格时才出现):退货/报废/部分入库 -->
|
||||
<!-- 不合格品处置(判定不合格时才出现):退货/换修/让步接收/报废/部分入库 -->
|
||||
<template v-if="status === '不合格'">
|
||||
<el-form-item label="处置方式">
|
||||
<el-radio-group v-model="disposalType">
|
||||
<el-radio-button value="RETURN">退货</el-radio-button>
|
||||
<el-radio-button value="REWORK">换修</el-radio-button>
|
||||
<el-radio-button value="CONCESSION">让步接收</el-radio-button>
|
||||
<el-radio-button value="SCRAP">报废</el-radio-button>
|
||||
<el-radio-button value="PARTIAL">部分入库</el-radio-button>
|
||||
</el-radio-group>
|
||||
@@ -350,33 +394,33 @@ onMounted(() => {
|
||||
</el-form-item>
|
||||
<el-form-item label=" ">
|
||||
<el-alert type="warning" :closable="false" style="max-width:560px"
|
||||
title="不合格品自动隔离:库存质量状态置「不合格/待退」,禁止领料上线;退货必填货运单号。" />
|
||||
title="退货/换修/报废:库存隔离(待退/不合格),禁止领料上线,退货必填货运单号;让步接收:审批后放行,质量状态置合格。" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
<el-form-item label="记录人">
|
||||
<el-input v-model="inspector" placeholder="记录人姓名" clearable style="width:260px" />
|
||||
<el-form-item :label="isFinal ? '审核人' : '记录人'">
|
||||
<el-input v-model="inspector" :placeholder="isFinal ? '完工检审核人姓名' : '记录人姓名'" 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="workorder" />
|
||||
<el-option label="科技项目号" value="project" />
|
||||
<el-option label="其他" value="other" />
|
||||
</el-select>
|
||||
<el-input v-if="ownershipType !== 'none'" v-model="ownershipNo"
|
||||
placeholder="归属编号" clearable />
|
||||
<el-input v-model="ownershipNo" maxlength="64" show-word-limit
|
||||
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-form-item v-if="!isFinal" label="生产厂家">
|
||||
<el-input v-model="manufacturer" placeholder="生产厂家(可空)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="检测单号">
|
||||
<el-form-item v-if="!isFinal" label="检测单号">
|
||||
<el-input v-model="inspectionNo" placeholder="检验报告单号(可空,与入库单关联)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="报检单号">
|
||||
<el-form-item v-if="!isFinal" label="报检单号">
|
||||
<el-input v-model="reportNo" placeholder="生产报检单号(可空,与报检流程关联)" clearable style="width:420px" />
|
||||
</el-form-item>
|
||||
|
||||
@@ -538,8 +582,11 @@ onMounted(() => {
|
||||
<el-table-column prop="reportNo" label="报检单号" min-width="130" align="center">
|
||||
<template #default="{ row }">{{ row.reportNo || '-' }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="归属单号" min-width="130" align="center">
|
||||
<template #default="{ row }">{{ row.ownershipNo || '-' }}</template>
|
||||
<el-table-column label="归属" min-width="160" align="center">
|
||||
<template #default="{ row }">
|
||||
<span>{{ ownershipTypeLabel(row.ownershipType) }}</span>
|
||||
<span v-if="row.ownershipNo">:{{ row.ownershipNo }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="inspector" label="记录人" width="90" align="center">
|
||||
<template #default="{ row }">{{ row.inspector || '-' }}</template>
|
||||
@@ -574,11 +621,12 @@ onMounted(() => {
|
||||
<!-- ============ 按物料统计(点击才加载) ============ -->
|
||||
<el-tab-pane label="按物料统计" name="stats">
|
||||
<el-card shadow="never" header="检验次数 / 合格率(按物料)">
|
||||
<div style="margin-bottom:10px">
|
||||
<el-button type="primary" :loading="statsLoading" @click="loadStats">统计</el-button>
|
||||
<span style="margin-left:8px;color:#909399;font-size:12px">按当前时间区间与检验类别统计;每次检验独立计数,不合并记录</span>
|
||||
<div style="margin-bottom:10px;display:flex;gap:10px;align-items:center;flex-wrap:wrap">
|
||||
<MaterialSelect v-model="statsMaterialCode" placeholder="先选择物料(必填)" style="width:280px" />
|
||||
<el-button type="primary" :loading="statsLoading" :disabled="!statsMaterialCode" @click="loadStats">统计</el-button>
|
||||
<span style="color:#909399;font-size:12px">需先选物料再统计(按当前时间区间与检验类别,每次检验独立计数,不合并记录)</span>
|
||||
</div>
|
||||
<el-table :data="statsList" border size="small" v-loading="statsLoading" empty-text="点「统计」查看结果">
|
||||
<el-table :data="statsList" border size="small" v-loading="statsLoading" :empty-text="statsQueried ? '该物料区间内无检验记录' : '请先选择物料再点「统计」'">
|
||||
<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" />
|
||||
@@ -609,6 +657,8 @@ onMounted(() => {
|
||||
<el-form-item label="处置方式" required>
|
||||
<el-radio-group v-model="disposeDialog.type">
|
||||
<el-radio-button value="RETURN">退货</el-radio-button>
|
||||
<el-radio-button value="REWORK">换修</el-radio-button>
|
||||
<el-radio-button value="CONCESSION">让步接收</el-radio-button>
|
||||
<el-radio-button value="SCRAP">报废</el-radio-button>
|
||||
<el-radio-button value="PARTIAL">部分入库</el-radio-button>
|
||||
</el-radio-group>
|
||||
|
||||
Reference in New Issue
Block a user