Files
klp-oa/klp-ui/src/views/timing/stoppage/index.vue
2026-05-09 17:22:28 +08:00

238 lines
7.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="stoppage-view">
<el-form :inline="true" :model="query" size="small" class="filter-bar">
<el-form-item label="区域">
<el-input v-model="query.area" placeholder="区域" clearable style="width: 120px" />
</el-form-item>
<el-form-item label="停机类型">
<el-input v-model="query.stopType" placeholder="停机类型" clearable style="width: 140px" />
</el-form-item>
<el-form-item label="开始日期">
<el-date-picker
v-model="query.startDate"
type="date"
placeholder="起"
value-format="yyyy-MM-dd"
style="width: 136px"
/>
</el-form-item>
<el-form-item label="—">
<el-date-picker
v-model="query.endDate"
type="date"
placeholder="止"
value-format="yyyy-MM-dd"
style="width: 136px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" :loading="loading" @click="handleSearch">查询</el-button>
<el-button icon="el-icon-refresh" @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<el-table
:data="rows"
size="mini"
border
stripe
:height="tableHeight"
v-loading="loading"
highlight-current-row
>
<el-table-column type="index" width="50" label="序" fixed />
<el-table-column prop="encoilid" label="钢卷号" width="130" show-overflow-tooltip fixed />
<el-table-column prop="area" label="区域" width="90" show-overflow-tooltip />
<el-table-column prop="unit" label="机组" width="90" show-overflow-tooltip />
<el-table-column prop="stop_type" label="停机类型" width="120" show-overflow-tooltip>
<template slot-scope="{ row }">
<el-tag :type="stopTypeTag(row.stop_type)" size="mini" disable-transitions>
{{ row.stop_type || '—' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="开始时间" width="148">
<template slot-scope="{ row }">{{ fmtDate(row.start_date) }}</template>
</el-table-column>
<el-table-column label="结束时间" width="148">
<template slot-scope="{ row }">{{ fmtDate(row.end_date) }}</template>
</el-table-column>
<el-table-column label="时长" width="80">
<template slot-scope="{ row }">
<span :class="durationCls(row.duration)">{{ fmtDuration(row.duration) }}</span>
</template>
</el-table-column>
<el-table-column prop="shift" label="班次" width="56" />
<el-table-column prop="crew" label="班组" width="56" />
<el-table-column prop="seton" label="SETON" width="90" show-overflow-tooltip />
<el-table-column prop="remark" label="备注" min-width="200" show-overflow-tooltip />
</el-table>
<div class="pagination-bar">
<span class="total-duration" v-if="rows.length">
本页合计时长<b>{{ pageTotalDuration }}</b>
</span>
<el-pagination
small
layout="total, sizes, prev, pager, next, jumper"
:total="pagination.total"
:page-size="pagination.pageSize"
:page-sizes="[50, 100, 200]"
:current-page="pagination.page"
@size-change="handleSizeChange"
@current-change="handlePageChange"
/>
</div>
</div>
</template>
<script>
import { getStoppageList, getStoppageCount } from '@/api/l2/timing'
function fmtDateStr(val) {
if (!val) return '—'
const s = String(val)
const m = s.match(/(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})/)
if (m) return `${m[1]}-${m[2]}-${m[3]} ${m[4]}:${m[5]}:${m[6]}`
const d = new Date(val)
if (isNaN(d.getTime())) return s
const pad = n => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}
// duration 单位为秒,格式化为 Xh Ym 或 Ym
function fmtDurationStr(val) {
if (val == null || val === '') return '—'
const secs = parseFloat(val)
if (isNaN(secs)) return String(val)
const mins = Math.round(secs / 60)
if (mins < 60) return `${mins}m`
const h = Math.floor(mins / 60)
const m = mins % 60
return m === 0 ? `${h}h` : `${h}h ${m}m`
}
export default {
name: 'TimingStoppagePage',
data() {
return {
loading: false,
query: { area: '', stopType: '', startDate: '', endDate: '' },
rows: [],
pagination: { page: 1, pageSize: 50, total: 0 },
tableHeight: 'calc(100vh - 200px)'
}
},
computed: {
pageTotalDuration() {
const total = this.rows.reduce((sum, r) => {
const v = parseFloat(r.duration)
return sum + (isNaN(v) ? 0 : v)
}, 0)
return fmtDurationStr(total)
}
},
created() {
this.loadCount()
this.loadRows()
},
methods: {
buildFilter() {
const { area, stopType, startDate, endDate } = this.query
return {
area: area || undefined,
stopType: stopType || undefined,
startDate: startDate || undefined,
endDate: endDate || undefined
}
},
async loadCount() {
try {
const res = await getStoppageCount(this.buildFilter())
this.pagination.total = res?.data?.total ?? 0
} catch (_) {}
},
async loadRows() {
this.loading = true
try {
const { page, pageSize } = this.pagination
const res = await getStoppageList(page, pageSize, this.buildFilter())
this.rows = res?.data?.rows || []
} finally {
this.loading = false
}
},
handleSearch() {
this.pagination.page = 1
this.loadCount()
this.loadRows()
},
handleReset() {
this.query = { area: '', stopType: '', startDate: '', endDate: '' }
this.pagination.page = 1
this.loadCount()
this.loadRows()
},
handlePageChange(page) {
this.pagination.page = page
this.loadRows()
},
handleSizeChange(size) {
this.pagination.pageSize = size
this.pagination.page = 1
this.loadCount()
this.loadRows()
},
fmtDate(val) { return fmtDateStr(val) },
fmtDuration(val) { return fmtDurationStr(val) },
durationCls(val) {
const secs = parseFloat(val)
if (isNaN(secs)) return ''
if (secs >= 3600) return 'dur-high' // >= 1 小时
if (secs >= 900) return 'dur-mid' // >= 15 分钟
return ''
},
stopTypeTag(type) {
if (!type) return 'info'
const t = String(type).toUpperCase()
if (t.includes('故障') || t.includes('FAULT') || t.includes('BREAK')) return 'danger'
if (t.includes('计划') || t.includes('PLAN')) return 'primary'
if (t.includes('换辊') || t.includes('ROLL')) return 'warning'
return 'info'
}
}
}
</script>
<style scoped>
.stoppage-view {
padding: 12px;
background: #fff;
height: 100%;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.filter-bar {
margin-bottom: 8px;
flex-shrink: 0;
}
.pagination-bar {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 16px;
padding: 8px 0 0;
flex-shrink: 0;
}
.total-duration {
font-size: 12px;
color: #606266;
}
.total-duration b {
color: #303133;
}
.dur-high { color: #f56c6c; font-weight: 600; }
.dur-mid { color: #e6a23c; }
</style>