本次重构删除原有BOM物料清单表,改用工单工艺组合×工艺物料清单作为唯一用料来源;新增系统基础设置表支持WMS地址、日志保留天数等配置,新增虚拟工位作业管理后台接口与前端页签控制功能,同时优化工位号校验逻辑、事件日志自动清理与工单用料查询能力。
128 lines
5.4 KiB
Vue
128 lines
5.4 KiB
Vue
<script setup>
|
||
defineOptions({ name: 'ProducibleSupport' })
|
||
import { computed, reactive, ref, onMounted } from 'vue'
|
||
import request from '../utils/request'
|
||
import { fmtTime } from '../utils/format'
|
||
import PageHelp from '../components/PageHelp.vue'
|
||
import { helpProducible } from '../help'
|
||
|
||
// 排产支撑:逐成品可生产套数 + 整体还能满产多少天/支撑到哪天/最先告罄短板物料
|
||
const loading = ref(false)
|
||
const items = ref([])
|
||
const supportDays = ref(0)
|
||
const supportUntil = ref('')
|
||
const shortBoardMaterial = ref('')
|
||
const computedAt = ref(0)
|
||
|
||
// 成品分页(§A2:只算启用成品、按需分页,不再全量无分页)
|
||
const page = reactive({ current: 1, size: 20 })
|
||
const pagedItems = computed(() => {
|
||
const start = (page.current - 1) * page.size
|
||
return items.value.slice(start, start + page.size)
|
||
})
|
||
function onSizeChange(s) {
|
||
page.size = s
|
||
page.current = 1
|
||
}
|
||
|
||
async function load() {
|
||
loading.value = true
|
||
try {
|
||
const data = await request.get('/production/producible-support')
|
||
items.value = data?.items || []
|
||
supportDays.value = data?.supportDays || 0
|
||
supportUntil.value = data?.supportUntil || ''
|
||
shortBoardMaterial.value = data?.shortBoardMaterial || ''
|
||
computedAt.value = data?.computedAt || 0
|
||
page.current = 1
|
||
} catch {
|
||
// 拦截器已提示
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
onMounted(load)
|
||
</script>
|
||
|
||
<template>
|
||
<div>
|
||
<el-card shadow="never" class="mb12">
|
||
<el-alert type="info" :closable="false" show-icon>
|
||
<template #title>
|
||
<div style="font-size:12px;line-height:1.7">
|
||
本页基于日排产与库存可用量推算(物料需求跟着工单工艺组合走,一律按日排产口径计算):<b>可生产套数</b> = 按工单工艺组合的物料单台含损耗用量 ÷ WMS 可用量取最小;
|
||
<b>支撑天数</b> = 用可用量对日排产做逐日消耗模拟,直到某物料不足(排产排满后,第 N+1 天起按近3天平均日需求外推,封顶365天)。
|
||
若无排产计划或排产日全部满足,短板物料栏显示「无排产计划 / 充足」。
|
||
</div>
|
||
</template>
|
||
</el-alert>
|
||
<el-row :gutter="12" style="margin-top:12px">
|
||
<el-col :span="6">
|
||
<el-card shadow="never" class="stat">
|
||
<div class="stat-num" :class="supportDays > 0 ? 'ok' : 'warn'">{{ supportDays }}</div>
|
||
<div class="stat-label">还能满产(天)</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :span="6">
|
||
<el-card shadow="never" class="stat">
|
||
<div class="stat-num">{{ supportUntil || '-' }}</div>
|
||
<div class="stat-label">库存可支撑到</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :span="6">
|
||
<el-card shadow="never" class="stat">
|
||
<div class="stat-num short" :title="shortBoardMaterial">{{ shortBoardMaterial || '充足' }}</div>
|
||
<div class="stat-label">最先告罄短板物料</div>
|
||
</el-card>
|
||
</el-col>
|
||
<el-col :span="6">
|
||
<el-card shadow="never" class="stat">
|
||
<div class="stat-num">{{ computedAt ? fmtTime(computedAt) : '-' }}</div>
|
||
<div class="stat-label">计算时间</div>
|
||
</el-card>
|
||
</el-col>
|
||
</el-row>
|
||
</el-card>
|
||
|
||
<el-card shadow="never" header="各工单可生产套数(只算有未取消日排产的工单;按工艺组合单台含损耗用量 ÷ 库存可用量取最小,短板物料见说明列)" v-loading="loading">
|
||
<el-table :data="pagedItems" border size="small" empty-text="暂无工单(无日排产或工艺未配置物料清单)">
|
||
<el-table-column prop="productCode" label="成品编码" min-width="150" />
|
||
<el-table-column prop="productName" label="成品名称" min-width="150">
|
||
<template #default="{ row }">{{ row.productName || '-' }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="可生产套数" width="120" align="center" sortable prop="producibleQty">
|
||
<template #default="{ row }">
|
||
<span :class="row.producibleQty > 0 ? 'ok' : 'warn'" class="qty">{{ row.producibleQty }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="短板说明" min-width="320">
|
||
<template #default="{ row }">
|
||
<span class="muted">{{ row.shortText || '-' }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div class="pager">
|
||
<el-pagination background layout="total, sizes, prev, pager, next" :total="items.length"
|
||
:current-page="page.current" :page-size="page.size" :page-sizes="[10, 20, 50, 100]"
|
||
@current-change="(p) => (page.current = p)" @size-change="onSizeChange" />
|
||
</div>
|
||
</el-card>
|
||
|
||
<PageHelp :data="helpProducible" page="ProducibleSupport" />
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.mb12 { margin-bottom: 12px; }
|
||
.pager { display: flex; justify-content: flex-end; margin-top: 12px; }
|
||
.stat { text-align: center; }
|
||
.stat-num { font-size: 26px; font-weight: 700; color: #303133; word-break: break-all; line-height: 1.3; }
|
||
.stat-num.short { font-size: 18px; color: #e6a23c; }
|
||
.stat-num.ok { color: #67c23a; }
|
||
.stat-num.warn { color: #e6a23c; }
|
||
.stat-label { font-size: 12px; color: #909399; margin-top: 6px; }
|
||
.qty { font-size: 18px; font-weight: 700; }
|
||
.muted { color: #909399; }
|
||
</style>
|