feat:智能制造产线任务大屏-能耗周趋势模块对接

main
黄伟杰 6 days ago
parent d4668912f8
commit 4ba8cc96bf

@ -7,35 +7,91 @@
</span>
<span>能耗周趋势</span>
</div>
<span class="tag">本周能耗对比</span>
<div class="card-toolbar">
<el-select
v-model="selectedEnergyTypeId" placeholder="请选择" class="energy-type-select" size="small"
@change="handleEnergyTypeChange">
<el-option v-for="item in energyTypes" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</div>
</div>
<div class="card-body">
<div id="chart-energy" class="chart"></div>
<div ref="chartRef" class="chart"></div>
</div>
</div>
</template>
<script setup lang="ts">
import { onMounted } from 'vue'
import { onMounted, onUnmounted, ref } from 'vue'
import * as echarts from 'echarts'
import { useChart, colors, style } from '../utils'
import { colors, style } from '../utils'
import { EnergyTypeApi, EnergyTypeVO } from '@/api/mes/energytype'
import { EnergyDeviceApi } from '@/api/mes/energydevice'
const { init } = useChart('chart-energy')
const energyTypes = ref<EnergyTypeVO[]>([])
const selectedEnergyTypeId = ref<number | undefined>(undefined)
const chartRef = ref<HTMLElement | null>(null)
let chart: echarts.ECharts | null = null
const energyDays = ['周一','周二','周三','周四','周五','周六','周日']
const energyUse = [520, 540, 580, 610, 640, 590, 560]
const energyStd = [500, 520, 540, 560, 580, 560, 540]
const getEnergyTypes = async () => {
try {
const res = await EnergyTypeApi.getEnergyTypeList()
const list = (res as any).data || (Array.isArray(res) ? res : [])
energyTypes.value = list
if (list.length > 0 && !selectedEnergyTypeId.value) {
selectedEnergyTypeId.value = list[0].id
await getChartData()
}
} catch (e) {
console.error('Failed to fetch energy types:', e)
}
}
onMounted(() => {
const chart = init()
const getChartData = async () => {
if (!selectedEnergyTypeId.value || !chart) return
try {
const res = await EnergyDeviceApi.getLastEnergyStatistics({
deviceTypeId: selectedEnergyTypeId.value,
orgId: 132
})
render(res)
} catch (e) {
console.error('Failed to fetch weekly energy data:', e)
}
}
const handleEnergyTypeChange = () => {
getChartData()
}
const render = (data: any = []) => {
if (!chart) return
const list = (data as any).data || (Array.isArray(data) ? data : [])
const x: string[] = []
const actual: number[] = []
const baseline: number[] = []
if (list && list.length > 0) {
list.forEach((item: any) => {
const label = item.hour || item.day || ''
x.push(label)
const v = Number(item.value ?? item.energy ?? item.consumption ?? 0)
actual.push(Number.isNaN(v) ? 0 : v)
})
}
chart.setOption({
backgroundColor: 'transparent',
tooltip: { trigger: 'axis' },
legend: { top: 0, right: 0, textStyle: style.legendText },
grid: { top: '20%', left: '6%', right: '6%', bottom: '10%', containLabel: true },
xAxis: { type: 'category', data: energyDays, axisLine: style.axisLine, axisLabel: style.axisLabel },
grid: { top: '20%', left: '6%', right: '6%', bottom: '14%', containLabel: true },
xAxis: {
type: 'category',
data: x,
axisLine: style.axisLine,
axisLabel: { ...style.axisLabel, fontSize: 10, rotate: 40 }
},
yAxis: { type: 'value', axisLine: { show: false }, axisLabel: style.axisLabel, splitLine: style.splitLine },
series: [
{
@ -49,7 +105,7 @@ onMounted(() => {
{ offset: 1, color: 'rgba(239,68,68,0.10)' }
])
},
data: energyUse
data: actual
},
{
name: '基准能耗(kWh)',
@ -57,10 +113,27 @@ onMounted(() => {
smooth: true,
showSymbol: false,
lineStyle: { width: 2, color: colors.green },
data: energyStd
data: baseline
}
]
})
}
const resize = () => {
chart?.resize()
}
onMounted(async () => {
if (!chartRef.value) return
chart = echarts.init(chartRef.value, 'dark', { renderer: 'canvas' })
render([])
await getEnergyTypes()
window.addEventListener('resize', resize)
})
onUnmounted(() => {
window.removeEventListener('resize', resize)
chart?.dispose()
})
</script>
@ -128,6 +201,12 @@ onMounted(() => {
color: #22d3ee;
}
.card-toolbar {
display: flex;
align-items: center;
gap: 6px;
}
.card-body {
flex: 1;
min-height: 0;
@ -150,7 +229,40 @@ onMounted(() => {
min-height: 180px;
}
.energy-type-select {
width: 140px;
}
:deep(.el-select__wrapper) {
background-color: transparent;
border: 1px solid rgba(56, 189, 248, 0.55);
box-shadow: 0 0 18px rgba(56, 189, 248, 0.35);
color: #94a3b8;
}
:deep(.el-select__placeholder) {
color: #94a3b8;
}
:deep(.energy-type-select .el-input__wrapper) {
border-radius: 999px;
border-color: rgba(56, 189, 248, 0.85);
background: radial-gradient(circle at 0 0, rgba(56, 189, 248, 0.22), transparent 70%);
box-shadow: 0 0 18px rgba(56, 189, 248, 0.45);
}
:deep(.energy-type-select .el-input__wrapper.is-focus) {
border-color: rgba(96, 165, 250, 0.95);
background: radial-gradient(circle at 0 0, rgba(59, 130, 246, 0.35), transparent 70%);
}
:deep(.energy-type-select .el-input__inner) {
color: #e0f2fe;
}
@media (max-width: 1600px) {
.chart { min-height: 160px; }
.chart {
min-height: 160px;
}
}
</style>

Loading…
Cancel
Save