初始化2

This commit is contained in:
SunYF
2026-08-28 15:06:01 +08:00
parent b34325a16f
commit a9c3fbeb41
537 changed files with 176215 additions and 17 deletions
@@ -0,0 +1,154 @@
<script setup>
import { computed, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '../utils/request'
import { getRealName } from '../utils/auth'
const queryForm = reactive({ orderNo: '' })
const operator = getRealName()
const targetDock = ref('')
const loading = ref(false)
const queried = ref(false)
const rows = ref([])
const pendingRows = computed(() => rows.value.filter(r => r.status !== '领料完结'))
function gapOf(row) {
return Math.max((row.totalQty || 0) - (row.outQty || 0), 0)
}
// 一键自动分配批次:合格区 Z02,batchNo 正序 FIFO 凑够缺口
async function autoAllocate(row) {
const gap = gapOf(row)
if (gap <= 0) return
const stock = await request.get('/stock/query', { params: { type: 'batch', materialCode: row.materialCode, page: 1, pageSize: 200 } })
const batches = (stock?.batch || [])
.filter(b => b.qualityStatus === '合格' && b.zoneCode === 'Z02')
.sort((a, b) => String(a.batchNo).localeCompare(String(b.batchNo)))
const plan = []
let remain = gap
for (const b of batches) {
if (remain <= 0) break
const avail = (b.quantity || 0) - (b.lockedQty || 0)
if (avail <= 0) continue
const take = Math.min(avail, remain)
plan.push({ batchNo: b.batchNo, qty: take, zoneCode: b.zoneCode })
remain -= take
}
if (!plan.length) {
ElMessage.warning(`物料 ${row.materialCode} 在合格区(Z02)无可用批次库存`)
return
}
if (remain > 0) {
ElMessage.error(`可用量不足:缺口 ${gap}Z02 仅可凑 ${gap - remain},还差 ${remain}`)
return
}
const lines = plan.map(p => `· 批次 ${p.batchNo} 出库 ${p.qty}`).join('\n')
await ElMessageBox.confirm(
`工单 ${row.orderNo} 物料 ${row.materialCode}\n缺口 ${gap},按 FIFO 分配如下:\n${lines}\n\n操作人:${operator}${targetDock.value ? `\n目标口:${targetDock.value}` : ''}`,
'确认自动分配出库',
{ type: 'warning', confirmButtonText: '确认出库', cancelButtonText: '取消' }
)
const outboundNos = []
let lastStatus = ''
for (const p of plan) {
const res = await request.post('/outbound/create', {
orderNo: row.orderNo,
materialCode: row.materialCode,
batchNo: p.batchNo,
qty: p.qty,
operator,
targetDock: targetDock.value.trim() || undefined
})
if (res?.outboundNo) outboundNos.push(res.outboundNo)
lastStatus = res?.status || lastStatus
}
const done = lastStatus === '领料完结'
ElMessage.success(`出库完成:出库单号 ${outboundNos.join('、')};该物料${done ? '已' : '未'}领料完结`)
await query()
}
function statusTag(s) {
return s === '领料完结' ? 'success' : s === '进行中' ? 'primary' : 'info'
}
async function query() {
if (!queryForm.orderNo.trim()) {
ElMessage.warning('请输入工单号')
return
}
loading.value = true
try {
const data = await request.get('/ledger/query', { params: { orderNo: queryForm.orderNo.trim(), page: 1, pageSize: 100 } })
rows.value = data?.list || []
queried.value = true
if (!rows.value.length) ElMessage.info('该工单暂无台账记录')
} finally {
loading.value = false
}
}
</script>
<template>
<div>
<el-card shadow="never" class="mb12">
<el-form inline label-width="90px" @submit.prevent>
<el-form-item label="工单号">
<el-input v-model="queryForm.orderNo" placeholder="输入工单号回车查询" clearable autofocus
style="width:260px" @keyup.enter="query" />
</el-form-item>
<el-form-item label="操作人">
<el-input :model-value="operator" disabled style="width:160px" />
</el-form-item>
<el-form-item label="目标工位">
<el-input v-model="targetDock" placeholder="可选,如 DOCK-A" clearable style="width:180px" />
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="loading" @click="query">查询台账</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card v-if="queried" shadow="never">
<template #header>
台账明细 {{ rows.length }} 待补 {{ pendingRows.length }}
</template>
<el-table :data="rows" border v-loading="loading">
<el-table-column prop="orderNo" label="工单号" min-width="140" />
<el-table-column prop="materialCode" label="物料编码" min-width="150" />
<el-table-column prop="materialName" label="物料名称" min-width="140">
<template #default="{ row }">{{ row.materialName || '-' }}</template>
</el-table-column>
<el-table-column prop="totalQty" label="需求总量" width="100" align="center" />
<el-table-column prop="outQty" label="已出库" width="90" align="center" />
<el-table-column label="缺口" width="90" align="center">
<template #default="{ row }">
<span :class="{ gap: gapOf(row) > 0 }">{{ gapOf(row) }}</span>
</template>
</el-table-column>
<el-table-column label="状态" width="110" align="center">
<template #default="{ row }">
<el-tag :type="statusTag(row.status)" size="small">{{ row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="140" align="center">
<template #default="{ row }">
<el-button v-if="row.status !== '领料完结'" type="primary" size="small"
@click="autoAllocate(row)">一键分配出库</el-button>
<span v-else style="color:#67c23a">已完结</span>
</template>
</el-table-column>
</el-table>
</el-card>
<el-empty v-else description="请先按工单号查询物料台账" />
</div>
</template>
<style scoped>
.mb12 { margin-bottom: 12px; }
.gap { color: #f56c6c; font-weight: 700; }
</style>