309 lines
7.6 KiB
Vue
309 lines
7.6 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="report-container">
|
|||
|
|
<div class="tabs-header">
|
|||
|
|
<el-tabs v-model="activeTab" type="card">
|
|||
|
|
<el-tab-pane label="日" name="day" />
|
|||
|
|
<el-tab-pane label="月" name="month" />
|
|||
|
|
<el-tab-pane label="年" name="year" />
|
|||
|
|
</el-tabs>
|
|||
|
|
<el-date-picker v-model="selectedDate" type="date" placeholder="选择日期" />
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="summary-section">
|
|||
|
|
<h3 class="section-title">停机汇总</h3>
|
|||
|
|
<div class="summary-cards">
|
|||
|
|
<div class="summary-card">
|
|||
|
|
<div class="card-icon">⏱️</div>
|
|||
|
|
<div class="card-content">
|
|||
|
|
<span class="card-label">停机时间</span>
|
|||
|
|
<span class="card-value highlight">{{ summaryData.stopTime }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="summary-card">
|
|||
|
|
<div class="card-icon">🔄</div>
|
|||
|
|
<div class="card-content">
|
|||
|
|
<span class="card-label">停机次数</span>
|
|||
|
|
<span class="card-value">{{ summaryData.stopCount }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="summary-card">
|
|||
|
|
<div class="card-icon">📊</div>
|
|||
|
|
<div class="card-content">
|
|||
|
|
<span class="card-label">作业率</span>
|
|||
|
|
<span class="card-value highlight">{{ summaryData.rate }}</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="charts-section">
|
|||
|
|
<div class="chart-panel">
|
|||
|
|
<h3 class="section-title">班组停机分布</h3>
|
|||
|
|
<div ref="teamChartRef" class="chart-content"></div>
|
|||
|
|
<div class="chart-legend">
|
|||
|
|
<span class="legend-item"><span class="legend-dot active"></span> 停机</span>
|
|||
|
|
<span class="legend-item"><span class="legend-dot inactive"></span> 正常</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="chart-panel">
|
|||
|
|
<h3 class="section-title">停机类型分布</h3>
|
|||
|
|
<div ref="typeChartRef" class="chart-content"></div>
|
|||
|
|
<div class="chart-legend">
|
|||
|
|
<span class="legend-item"><span class="legend-dot type1"></span> 来料缺陷</span>
|
|||
|
|
<span class="legend-item"><span class="legend-dot type2"></span> 机械故障</span>
|
|||
|
|
<span class="legend-item"><span class="legend-dot type3"></span> 换辊</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="table-section">
|
|||
|
|
<h3 class="section-title">停机详情</h3>
|
|||
|
|
<el-table :data="stopData" border :height="300">
|
|||
|
|
<el-table-column prop="timeRange" label="时间范围" width="200" />
|
|||
|
|
<el-table-column prop="duration" label="持续时间" width="120" />
|
|||
|
|
<el-table-column prop="team" label="机组" width="100" />
|
|||
|
|
<el-table-column prop="remark" label="备注" width="300" />
|
|||
|
|
</el-table>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { ref, onMounted, nextTick } from 'vue'
|
|||
|
|
import * as echarts from 'echarts'
|
|||
|
|
|
|||
|
|
const activeTab = ref('day')
|
|||
|
|
const selectedDate = ref('2026-05-14')
|
|||
|
|
|
|||
|
|
const summaryData = ref({
|
|||
|
|
stopTime: '60 min',
|
|||
|
|
stopCount: '4次',
|
|||
|
|
rate: '95.83%'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
const stopData = ref([
|
|||
|
|
{ timeRange: '2026-05-14 13:22 - 2026-05-14 13:34', duration: '12min', team: 'MLL', remark: '带尾夹送断带' },
|
|||
|
|
{ timeRange: '2026-05-14 12:47 - 2026-05-14 12:54', duration: '7min', team: 'MLL', remark: '处理表面缺陷' },
|
|||
|
|
{ timeRange: '2026-05-14 10:27 - 2026-05-14 12:54', duration: '33min', team: 'MLL', remark: '开卷机故障' },
|
|||
|
|
{ timeRange: '2026-05-14 10:27 - 2026-05-14 11:00', duration: '33min', team: 'MLL', remark: '换1-4机架辊,修4机架弯辊阀' },
|
|||
|
|
{ timeRange: '2026-05-14 04:03 - 2026-05-14 04:11', duration: '8min', team: 'MLL', remark: '换辊' }
|
|||
|
|
])
|
|||
|
|
|
|||
|
|
const teamChartRef = ref(null)
|
|||
|
|
const typeChartRef = ref(null)
|
|||
|
|
|
|||
|
|
const initCharts = () => {
|
|||
|
|
if (teamChartRef.value) {
|
|||
|
|
const chart = echarts.init(teamChartRef.value)
|
|||
|
|
chart.setOption({
|
|||
|
|
tooltip: { trigger: 'item' },
|
|||
|
|
series: [
|
|||
|
|
{
|
|||
|
|
name: '班组停机',
|
|||
|
|
type: 'pie',
|
|||
|
|
radius: ['50%', '75%'],
|
|||
|
|
center: ['50%', '50%'],
|
|||
|
|
data: [
|
|||
|
|
{ value: 1, name: '停机', itemStyle: { color: '#409eff' } },
|
|||
|
|
{ value: 0, name: '正常', itemStyle: { color: '#e4e7ed' } }
|
|||
|
|
],
|
|||
|
|
label: { show: false },
|
|||
|
|
emphasis: {
|
|||
|
|
label: { show: true, fontSize: 24, fontWeight: 'bold' }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (typeChartRef.value) {
|
|||
|
|
const chart = echarts.init(typeChartRef.value)
|
|||
|
|
chart.setOption({
|
|||
|
|
tooltip: { trigger: 'item' },
|
|||
|
|
series: [
|
|||
|
|
{
|
|||
|
|
name: '停机类型',
|
|||
|
|
type: 'pie',
|
|||
|
|
radius: ['50%', '75%'],
|
|||
|
|
center: ['50%', '50%'],
|
|||
|
|
data: [
|
|||
|
|
{ value: 45, name: '来料缺陷', itemStyle: { color: '#409eff' } },
|
|||
|
|
{ value: 35, name: '机械故障', itemStyle: { color: '#67c23a' } },
|
|||
|
|
{ value: 20, name: '换辊', itemStyle: { color: '#e6a23c' } }
|
|||
|
|
],
|
|||
|
|
label: { show: false },
|
|||
|
|
emphasis: {
|
|||
|
|
label: { show: true, fontSize: 18, fontWeight: 'bold' }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onMounted(() => {
|
|||
|
|
nextTick(() => {
|
|||
|
|
initCharts()
|
|||
|
|
window.addEventListener('resize', initCharts)
|
|||
|
|
})
|
|||
|
|
})
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.report-container {
|
|||
|
|
background: #fff;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 20px;
|
|||
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.tabs-header {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 20px;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
|
|||
|
|
:deep(.el-tabs) {
|
|||
|
|
flex: 1;
|
|||
|
|
|
|||
|
|
.el-tabs__header {
|
|||
|
|
margin: 0;
|
|||
|
|
border-bottom: 1px solid #e4e7ed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-tabs__item {
|
|||
|
|
padding: 0 20px;
|
|||
|
|
height: 40px;
|
|||
|
|
line-height: 40px;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-tabs__item.is-active {
|
|||
|
|
color: #409eff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.el-tabs__active-bar {
|
|||
|
|
background: #409eff;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-section {
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.section-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
padding-left: 12px;
|
|||
|
|
border-left: 3px solid #409eff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-cards {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-card {
|
|||
|
|
flex: 1;
|
|||
|
|
background: #fff;
|
|||
|
|
border: 1px solid #e4e7ed;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 20px;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 16px;
|
|||
|
|
|
|||
|
|
.card-icon {
|
|||
|
|
width: 48px;
|
|||
|
|
height: 48px;
|
|||
|
|
border-radius: 12px;
|
|||
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
font-size: 24px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-content {
|
|||
|
|
flex: 1;
|
|||
|
|
|
|||
|
|
.card-label {
|
|||
|
|
display: block;
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: #909399;
|
|||
|
|
margin-bottom: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-value {
|
|||
|
|
font-size: 24px;
|
|||
|
|
font-weight: bold;
|
|||
|
|
color: #303133;
|
|||
|
|
|
|||
|
|
&.highlight {
|
|||
|
|
color: #409eff;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.charts-section {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(2, 1fr);
|
|||
|
|
gap: 20px;
|
|||
|
|
margin-bottom: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.chart-panel {
|
|||
|
|
background: #fff;
|
|||
|
|
border: 1px solid #e4e7ed;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.chart-content {
|
|||
|
|
height: 200px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.chart-legend {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: center;
|
|||
|
|
gap: 24px;
|
|||
|
|
margin-top: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.legend-item {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 6px;
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: #606266;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.legend-dot {
|
|||
|
|
width: 12px;
|
|||
|
|
height: 12px;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
|
|||
|
|
&.active { background: #409eff; }
|
|||
|
|
&.inactive { background: #e4e7ed; }
|
|||
|
|
&.type1 { background: #409eff; }
|
|||
|
|
&.type2 { background: #67c23a; }
|
|||
|
|
&.type3 { background: #e6a23c; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.table-section {
|
|||
|
|
background: #fff;
|
|||
|
|
border: 1px solid #e4e7ed;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
padding: 20px;
|
|||
|
|
|
|||
|
|
:deep(.el-table) {
|
|||
|
|
--el-table-header-text-color: #606266;
|
|||
|
|
--el-table-row-hover-bg-color: #f5f7fa;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|