酸轧数据同步,轧辊新增产线新增各种产线

This commit is contained in:
2026-05-14 15:12:30 +08:00
parent 4a5b9544a4
commit 49561a125e
41 changed files with 2054 additions and 319 deletions

View File

@@ -0,0 +1,188 @@
<template>
<div class="l2-panel">
<!-- 最佳匹配 -->
<div class="panel-block">
<div class="pb-header">
<span class="pb-title">最佳匹配</span>
<el-tag v-if="bestMatch" size="mini" type="success" style="margin-left:6px">热卷号已找到</el-tag>
<el-tag v-else-if="matchLoading" size="mini" type="info" style="margin-left:6px">查询中</el-tag>
<el-tag v-else-if="hotCoilId" size="mini" type="warning" style="margin-left:6px">未找到</el-tag>
<el-tag v-else size="mini" style="margin-left:6px">待输入</el-tag>
</div>
<template v-if="bestMatch">
<div class="match-grid">
<div class="mg-item" v-for="f in PLAN_FIELDS" :key="f.key">
<span class="mg-label">{{ f.label }}</span>
<span class="mg-value">{{ formatPlanField(f.key, bestMatch[f.key]) }}</span>
</div>
</div>
<el-button type="primary" size="small" style="width:100%;margin-top:10px"
icon="el-icon-download" @click="$emit('fill', bestMatch)">
写入表单
</el-button>
</template>
<div v-else-if="matchLoading" class="pb-empty"><i class="el-icon-loading" /></div>
<div v-else class="pb-empty">{{ hotCoilId ? '未找到匹配的 L2 计划记录' : '输入入场钢卷号后自动查询' }}</div>
</div>
<!-- 最近20条 -->
<div class="panel-block" style="margin-top:12px">
<div class="pb-header">
<span class="pb-title">最近 20 条生产记录</span>
<el-button type="text" size="mini" icon="el-icon-refresh"
style="margin-left:auto" :loading="recentLoading" @click="loadRecentList">刷新</el-button>
</div>
<el-table :data="recentList" size="mini" v-loading="recentLoading"
max-height="400" border style="width:100%">
<el-table-column label="热卷号" min-width="110" show-overflow-tooltip>
<template slot-scope="{ row }">
<span :class="(row.hot_coilid || row.encoilid) === hotCoilId ? 'hot-match' : ''">
{{ row.hot_coilid || row.encoilid || '—' }}
</span>
</template>
</el-table-column>
<el-table-column label="出口厚" width="72" align="right">
<template slot-scope="{ row }">{{ row.exit_thick != null ? row.exit_thick : '—' }}</template>
</el-table-column>
<el-table-column label="出口宽" width="72" align="right">
<template slot-scope="{ row }">{{ row.exit_width != null ? row.exit_width : '—' }}</template>
</el-table-column>
<el-table-column label="长度(m)" width="76" align="right">
<template slot-scope="{ row }">{{ row.exit_length != null ? row.exit_length : '—' }}</template>
</el-table-column>
<el-table-column label="重量(t)" width="72" align="right">
<template slot-scope="{ row }">{{ row.entry_weight != null ? row.entry_weight : '—' }}</template>
</el-table-column>
<el-table-column label="" width="52" fixed="right" align="center">
<template slot-scope="{ row }">
<el-button type="text" size="mini" @click="$emit('fill', row)">写入</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</template>
<script>
import { getTimingPlanDetailByHotcoilId, getExcoilList } from '@/api/l2/timing'
const PLAN_FIELDS = [
{ key: 'hot_coilid', label: '热卷号' },
{ key: 'status', label: '状态' },
{ key: 'process_code', label: '工艺编码' },
{ key: 'entry_thick', label: '入口厚(mm)' },
{ key: 'entry_width', label: '入口宽(mm)' },
{ key: 'entry_weight', label: '入口重量(t)' },
{ key: 'exit_thick', label: '出口厚(mm)' },
{ key: 'exit_width', label: '出口宽(mm)' },
{ key: 'exit_length', label: '出口长度(m)' },
{ key: 'park_type', label: '包装要求' },
{ key: 'trimming', label: '切边要求' },
]
export default {
name: 'L2MatchPanel',
props: {
hotCoilId: { type: String, default: '' }
},
data() {
return {
PLAN_FIELDS,
bestMatch: null,
matchLoading: false,
recentList: [],
recentLoading: false,
}
},
watch: {
hotCoilId(val) {
if (val) this.loadBestMatch(val)
else this.bestMatch = null
}
},
created() {
this.loadRecentList()
if (this.hotCoilId) this.loadBestMatch(this.hotCoilId)
},
methods: {
loadBestMatch(hotCoilId) {
this.bestMatch = null
this.matchLoading = true
getTimingPlanDetailByHotcoilId(hotCoilId).then(res => {
const fr = res?.data?.firstRow
this.bestMatch = (fr && Object.keys(fr).length > 0) ? fr : null
}).catch(() => {}).finally(() => { this.matchLoading = false })
},
loadRecentList() {
this.recentLoading = true
getExcoilList(1, 20).then(res => {
const rows = res?.data?.rows || []
this.recentList = rows.map(row => this.normalizeExcoilRow(row))
}).catch(() => {}).finally(() => { this.recentLoading = false })
},
formatPlanField(key, val) {
if (val == null) return '—'
if (key === 'trimming') {
if (val === 1 || val === '1') return '净边料'
if (val === 0 || val === '0') return '毛边料'
}
return val
},
normalizeExcoilRow(row) {
const g = k => row[k] != null ? row[k] : (row[k.toUpperCase()] != null ? row[k.toUpperCase()] : null)
return {
hot_coilid: g('hot_coilid'),
encoilid: g('encoilid'),
excoilid: g('excoilid'),
exit_thick: g('exit_thick'),
exit_width: g('exit_width'),
exit_length: g('exit_length'),
entry_weight: g('used_entry_weight') != null ? g('used_entry_weight')
: (g('meas_exit_weight') != null ? g('meas_exit_weight') : g('entry_weight')),
}
}
}
}
</script>
<style scoped>
.l2-panel { font-size: 13px; }
.panel-block {
background: #fff;
border: 1px solid #e4e7ed;
border-radius: 4px;
padding: 12px;
}
.pb-header {
display: flex;
align-items: center;
margin-bottom: 10px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f2f5;
}
.pb-title { font-weight: 600; color: #303133; font-size: 13px; }
.match-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 6px 12px;
}
.mg-item { display: flex; flex-direction: column; }
.mg-label { font-size: 11px; color: #909399; }
.mg-value { font-size: 13px; color: #303133; font-weight: 500; }
.pb-empty {
text-align: center;
color: #c0c4cc;
padding: 20px 0;
font-size: 12px;
}
.hot-match { color: #67c23a; font-weight: 600; }
</style>