469 lines
15 KiB
Vue
469 lines
15 KiB
Vue
<template>
|
|
<div class="actual-page">
|
|
<div class="body-wrap">
|
|
|
|
<!-- 实绩表格 -->
|
|
<div class="table-card">
|
|
<div class="card-header">
|
|
<span class="card-title">双机架实绩</span>
|
|
<el-radio-group v-model="query.planStatus" size="mini" @change="onStatusChange">
|
|
<el-radio-button label="">全部</el-radio-button>
|
|
<el-radio-button label="0">准备</el-radio-button>
|
|
<el-radio-button label="1">上线</el-radio-button>
|
|
<el-radio-button label="2">生产中</el-radio-button>
|
|
<el-radio-button label="3">生产完成</el-radio-button>
|
|
</el-radio-group>
|
|
<el-button size="mini" icon="el-icon-refresh" style="margin-left:8px" @click="loadList">刷新</el-button>
|
|
</div>
|
|
|
|
<el-table
|
|
v-loading="loading"
|
|
:data="list"
|
|
size="mini"
|
|
border
|
|
highlight-current-row
|
|
:height="tableHeight"
|
|
style="width:100%"
|
|
@row-click="handleRowClick"
|
|
>
|
|
<el-table-column type="index" width="40" align="center" />
|
|
<el-table-column label="计划号" prop="planNo" width="150" show-overflow-tooltip />
|
|
<el-table-column label="入场钢卷号" prop="enterCoilNo" min-width="120" show-overflow-tooltip>
|
|
<template slot-scope="{ row }">{{ row.enterCoilNo || row.inMatNo || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="出口钢卷号" prop="currentCoilNo" min-width="120" show-overflow-tooltip>
|
|
<template slot-scope="{ row }">{{ row.currentCoilNo || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="合金牌号" prop="alloyNo" width="100" show-overflow-tooltip>
|
|
<template slot-scope="{ row }">{{ row.alloyNo || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="计划状态" width="80" align="center">
|
|
<template slot-scope="{ row }">
|
|
<el-tag :type="planStatusType(row.planStatus)" size="mini">
|
|
{{ planStatusLabel(row.planStatus) }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="生产状态" width="80" align="center">
|
|
<template slot-scope="{ row }">
|
|
<el-tag :type="prodStatusType(row.prodStatus)" size="mini" effect="plain">
|
|
{{ row.prodStatus || '—' }}
|
|
</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="来料厚(mm)" width="82" align="right">
|
|
<template slot-scope="{ row }">{{ row.inMatThick || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="来料宽(mm)" width="82" align="right">
|
|
<template slot-scope="{ row }">{{ row.inMatWidth || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="来料重(t)" width="76" align="right">
|
|
<template slot-scope="{ row }">{{ row.inMatWeight || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="成品厚(mm)" width="82" align="right">
|
|
<template slot-scope="{ row }">
|
|
<span class="accent-val">{{ row.outThick || '—' }}</span>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column label="道次数" prop="passCount" width="60" align="center">
|
|
<template slot-scope="{ row }">{{ row.passCount || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="工艺方案" prop="recipeNo" width="110" show-overflow-tooltip>
|
|
<template slot-scope="{ row }">{{ row.recipeNo || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="创建时间" width="148">
|
|
<template slot-scope="{ row }">{{ formatDate(row.createTime) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="创建人" prop="createBy" width="80" align="center">
|
|
<template slot-scope="{ row }">{{ row.createBy || '—' }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="备注" prop="remark" min-width="100" show-overflow-tooltip>
|
|
<template slot-scope="{ row }">{{ row.remark || '—' }}</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<div class="table-footer">
|
|
<el-pagination
|
|
small
|
|
layout="total, sizes, prev, pager, next"
|
|
:page-sizes="[20, 50, 100]"
|
|
:total="total"
|
|
:page-size="query.pageSize"
|
|
:current-page="query.pageNum"
|
|
@size-change="handleSizeChange"
|
|
@current-change="handlePageChange"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧面板 -->
|
|
<div class="side-panel">
|
|
|
|
<!-- 查找 -->
|
|
<div class="panel-block">
|
|
<div class="panel-title">查找</div>
|
|
|
|
<div class="filter-item">
|
|
<span class="filter-label">钢卷号</span>
|
|
<el-input
|
|
v-model="query.inMatNo"
|
|
size="mini" clearable
|
|
placeholder="入场/出口钢卷号"
|
|
style="width:100%"
|
|
/>
|
|
</div>
|
|
|
|
<div class="filter-item">
|
|
<span class="filter-label">开始时间</span>
|
|
<el-date-picker
|
|
v-model="query.createStartTime"
|
|
type="datetime"
|
|
size="mini"
|
|
style="width:100%"
|
|
value-format="yyyy-MM-dd HH:mm:ss"
|
|
placeholder="创建开始时间"
|
|
/>
|
|
</div>
|
|
|
|
<div class="filter-item">
|
|
<span class="filter-label">结束时间</span>
|
|
<el-date-picker
|
|
v-model="query.createEndTime"
|
|
type="datetime"
|
|
size="mini"
|
|
style="width:100%"
|
|
value-format="yyyy-MM-dd HH:mm:ss"
|
|
placeholder="创建结束时间"
|
|
/>
|
|
</div>
|
|
|
|
<div class="filter-actions">
|
|
<el-button type="primary" size="mini" :loading="loading" @click="handleSearch">查找</el-button>
|
|
<el-button size="mini" @click="handleReset">重置</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 选中行详情 -->
|
|
<div v-if="selectedRow" class="panel-block detail-block">
|
|
<div class="panel-title">计划详情</div>
|
|
<div class="detail-grid">
|
|
<div class="detail-row">
|
|
<span class="detail-key">计划号</span>
|
|
<span class="detail-val">{{ selectedRow.planNo }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">入场卷号</span>
|
|
<span class="detail-val">{{ selectedRow.enterCoilNo || selectedRow.inMatNo || '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">出口卷号</span>
|
|
<span class="detail-val">{{ selectedRow.currentCoilNo || '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">合金牌号</span>
|
|
<span class="detail-val">{{ selectedRow.alloyNo || '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">来料厚</span>
|
|
<span class="detail-val accent">{{ selectedRow.inMatThick ? selectedRow.inMatThick + ' mm' : '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">来料宽</span>
|
|
<span class="detail-val accent">{{ selectedRow.inMatWidth ? selectedRow.inMatWidth + ' mm' : '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">来料重</span>
|
|
<span class="detail-val accent">{{ selectedRow.inMatWeight ? selectedRow.inMatWeight + ' t' : '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">来料长</span>
|
|
<span class="detail-val">{{ selectedRow.inMatLength ? selectedRow.inMatLength + ' m' : '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">成品厚</span>
|
|
<span class="detail-val accent">{{ selectedRow.outThick ? selectedRow.outThick + ' mm' : '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">道次数</span>
|
|
<span class="detail-val">{{ selectedRow.passCount || '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">工艺方案</span>
|
|
<span class="detail-val">{{ selectedRow.recipeNo || '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">计划状态</span>
|
|
<span class="detail-val">
|
|
<el-tag :type="planStatusType(selectedRow.planStatus)" size="mini">
|
|
{{ planStatusLabel(selectedRow.planStatus) }}
|
|
</el-tag>
|
|
</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">生产状态</span>
|
|
<span class="detail-val">
|
|
<el-tag :type="prodStatusType(selectedRow.prodStatus)" size="mini" effect="plain">
|
|
{{ selectedRow.prodStatus || '—' }}
|
|
</el-tag>
|
|
</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">创建人</span>
|
|
<span class="detail-val">{{ selectedRow.createBy || '—' }}</span>
|
|
</div>
|
|
<div class="detail-row">
|
|
<span class="detail-key">创建时间</span>
|
|
<span class="detail-val">{{ formatDate(selectedRow.createTime) }}</span>
|
|
</div>
|
|
<div v-if="selectedRow.remark" class="detail-row">
|
|
<span class="detail-key">备注</span>
|
|
<span class="detail-val">{{ selectedRow.remark }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { listDrActualPage } from '@/api/wms/drMill'
|
|
|
|
const PLAN_STATUS = {
|
|
'0': { label: '准备', type: 'info' },
|
|
'1': { label: '上线', type: 'primary' },
|
|
'2': { label: '生产中', type: 'warning' },
|
|
'3': { label: '生产完成', type: 'success' },
|
|
}
|
|
|
|
const PROD_STATUS_TYPE = {
|
|
Idle: 'info',
|
|
Rolling: 'warning',
|
|
NextCoil: 'primary',
|
|
Done: 'success',
|
|
Error: 'danger',
|
|
}
|
|
|
|
export default {
|
|
name: 'DrActual',
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
list: [],
|
|
total: 0,
|
|
selectedRow: null,
|
|
query: {
|
|
pageNum: 1,
|
|
pageSize: 50,
|
|
planStatus: '',
|
|
inMatNo: '',
|
|
createStartTime: '',
|
|
createEndTime: '',
|
|
},
|
|
}
|
|
},
|
|
computed: {
|
|
tableHeight() { return 'calc(100vh - 210px)' }
|
|
},
|
|
created() { this.loadList() },
|
|
methods: {
|
|
loadList() {
|
|
this.loading = true
|
|
const params = {
|
|
...this.query,
|
|
planStatus: this.query.planStatus || undefined,
|
|
inMatNo: this.query.inMatNo || undefined,
|
|
createStartTime: this.query.createStartTime || undefined,
|
|
createEndTime: this.query.createEndTime || undefined,
|
|
}
|
|
listDrActualPage(params)
|
|
.then(res => {
|
|
this.list = res.rows || []
|
|
this.total = res.total || 0
|
|
})
|
|
.finally(() => { this.loading = false })
|
|
},
|
|
handlePageChange(page) {
|
|
this.query.pageNum = page
|
|
this.loadList()
|
|
},
|
|
handleSizeChange(size) {
|
|
this.query.pageSize = size
|
|
this.query.pageNum = 1
|
|
this.loadList()
|
|
},
|
|
onStatusChange() {
|
|
this.query.pageNum = 1
|
|
this.loadList()
|
|
},
|
|
handleRowClick(row) {
|
|
this.selectedRow = (this.selectedRow && this.selectedRow.planId === row.planId) ? null : row
|
|
},
|
|
handleSearch() {
|
|
this.query.pageNum = 1
|
|
this.loadList()
|
|
},
|
|
handleReset() {
|
|
this.query.planStatus = ''
|
|
this.query.inMatNo = ''
|
|
this.query.createStartTime = ''
|
|
this.query.createEndTime = ''
|
|
this.query.pageNum = 1
|
|
this.selectedRow = null
|
|
this.loadList()
|
|
},
|
|
planStatusLabel(s) { return (PLAN_STATUS[s] || { label: s || '—' }).label },
|
|
planStatusType(s) { return (PLAN_STATUS[s] || { type: '' }).type },
|
|
prodStatusType(s) { return PROD_STATUS_TYPE[s] || 'info' },
|
|
formatDate(v) {
|
|
if (!v) return '—'
|
|
return String(v).replace('T', ' ').substring(0, 19)
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.actual-page {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 100%;
|
|
background: #f5f7fa;
|
|
padding: 10px 12px;
|
|
box-sizing: border-box;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.body-wrap {
|
|
flex: 1;
|
|
min-height: 0;
|
|
display: flex;
|
|
gap: 8px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* ── 表格卡片 ── */
|
|
.table-card {
|
|
flex: 1;
|
|
min-width: 0;
|
|
background: #fff;
|
|
border: 1px solid #e4e7ed;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
box-shadow: 0 1px 4px rgba(0,0,0,.04);
|
|
}
|
|
|
|
.card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 10px 14px;
|
|
border-bottom: 1px solid #e4e7ed;
|
|
flex-shrink: 0;
|
|
gap: 8px;
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: #303133;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.table-footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
padding: 6px 10px;
|
|
border-top: 1px solid #e4e7ed;
|
|
background: #fafafa;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.accent-val {
|
|
font-family: 'Courier New', monospace;
|
|
font-weight: 600;
|
|
color: #409eff;
|
|
}
|
|
|
|
/* ── 侧边面板 ── */
|
|
.side-panel {
|
|
width: 220px;
|
|
flex-shrink: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
overflow-y: auto;
|
|
|
|
&::-webkit-scrollbar { width: 4px; }
|
|
&::-webkit-scrollbar-thumb { background: #dcdfe6; border-radius: 2px; }
|
|
}
|
|
|
|
.panel-block {
|
|
background: #fff;
|
|
border: 1px solid #e4e7ed;
|
|
border-radius: 4px;
|
|
padding: 12px;
|
|
box-shadow: 0 1px 4px rgba(0,0,0,.04);
|
|
}
|
|
|
|
.panel-title {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: #303133;
|
|
padding-bottom: 8px;
|
|
border-bottom: 1px solid #ebeef5;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.filter-item { margin-bottom: 10px; }
|
|
|
|
.filter-label {
|
|
display: block;
|
|
font-size: 11px;
|
|
color: #909399;
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.filter-actions {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-top: 4px;
|
|
}
|
|
|
|
/* ── 详情 ── */
|
|
.detail-grid {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
|
|
.detail-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
gap: 4px;
|
|
}
|
|
|
|
.detail-key {
|
|
font-size: 11px;
|
|
color: #909399;
|
|
flex-shrink: 0;
|
|
padding-top: 2px;
|
|
}
|
|
|
|
.detail-val {
|
|
font-size: 12px;
|
|
color: #303133;
|
|
text-align: right;
|
|
word-break: break-all;
|
|
|
|
&.accent {
|
|
color: #409eff;
|
|
font-weight: 600;
|
|
font-family: 'Courier New', monospace;
|
|
}
|
|
}
|
|
</style>
|