feat: 生产指挥中心大屏分表率调整(6656*1872 -> 4096*2160)

This commit is contained in:
wangjr 2025-09-07 22:59:47 +08:00
parent 710c385bdd
commit 720ab40f9c
17 changed files with 2794 additions and 1 deletions

View File

@ -19,6 +19,7 @@
"core-js": "^3.1.2",
"crypto-js": "^4.0.0",
"default-passive-events": "^1.0.10",
"echarts": "^6.0.0",
"enquire.js": "^2.1.6",
"font-awesome": "^4.7.0",
"jquery": "^3.5.1",

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -85,7 +85,7 @@ export const constantRouterMap = [
{
path: 'productionCommandCenter',
name: 'productionCommandCenter',
component: () => import(/* webpackChunkName: "largeScreen" */ '@/views/largeScreen/productionCommandCenter')
component: () => import(/* webpackChunkName: "largeScreen" */ '@/views/largeScreen/ProductionCommandCenter1')
}
]
},

View File

@ -0,0 +1,377 @@
<script>
import ProductData from './components/ProductData.vue'
import Production from './components/Production.vue'
import PowerConsumption from './components/PowerConsumption.vue'
import ProductOutput from './components/ProductOutput.vue'
import ProductQualityRate from './components/ProductQualityRate.vue'
import ProductQualificationRate from './components/ProductQualificationRate.vue'
import FurnaceProductionContribution from './components/FurnaceProductionContribution.vue'
import SafetyEvents from './components/SafetyEvents.vue'
import ElectrodeConsumption from './components/ElectrodeConsumption.vue'
import UnitPowerConsumption from './components/UnitPowerConsumption.vue'
import FurnaceTemperatureStability from './components/FurnaceTemperatureStability.vue'
import PowerUsage from './components/PowerUsage.vue'
import ReactiveCompensationEfficiency from './components/ReactiveCompensationEfficiency.vue'
export default {
components: {
ProductData,
Production,
PowerConsumption,
ProductOutput,
ProductQualityRate,
ProductQualificationRate,
FurnaceProductionContribution,
SafetyEvents,
FurnaceTemperatureStability,
ElectrodeConsumption,
PowerUsage,
UnitPowerConsumption,
ReactiveCompensationEfficiency
}
}
</script>
<template>
<div class="main">
<div id="middleTitle" class="middleTitle">
<!-- <div class="cockpit"><div class="cockpitFont">驾驶舱</div></div>
<div class="branchPlantProCap"><div class="branchPlantProCapFont">分厂产能</div></div> -->
<div class="middleTitleFont"><img src="@/assets/title.png" alt="" /></div>
<!-- <div class="productionEfficiency"><div class="productionEfficiencyFont">生产效能</div></div>
<div class="safetyManagement"><div class="safetyManagementFont">安全管理</div></div> -->
</div>
<div class="operatingStatusBox">
<div class="operatingStatus">
<div class="operatingStatusFont">工厂整体运行状态</div>
<div class="operatingStatusContent">
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 1.svg" alt="" />
</div>
<div class="contentBoxCont">
<product-data></product-data>
</div>
</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 6.svg" alt="" />
<span>单位t</span>
</div>
<div class="contentBoxCont">
<production></production>
</div>
</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 7.svg" alt="" />
<span>单位kWh/t</span>
</div>
<div class="contentBoxCont">
<power-consumption></power-consumption>
</div>
</div>
</div>
</div>
<div class="operatingStatus">
<div class="operatingStatusFont">产能与产品结构</div>
<div class="operatingStatusContent">
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 2.svg" alt="" />
<span>单位t</span>
</div>
<div class="contentBoxCont">
<product-output></product-output>
</div>
</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 8.svg" alt="" />
<span>百分比</span>
</div>
<div class="contentBoxCont">
<div class="contentBoxCont">
<product-quality-rate></product-quality-rate>
</div>
</div>
</div>
<div class="contentBox contentBox1">
<div>
<div class="contentBoxFont">
<img src="@/assets/Component 10.svg" alt="" />
</div>
<div class="contentBoxCont">
<product-qualification-rate></product-qualification-rate>
</div>
</div>
<div>
<div class="contentBoxFont">
<img src="@/assets/Component 9.svg" alt="" />
<span class="half">单位t</span>
</div>
<div class="contentBoxCont">
<FurnaceProductionContribution />
</div>
</div>
</div>
</div>
</div>
<div class="operatingStatus1">
<iframe width="1000" height="1480" src="https://www.baidu.com"></iframe>
</div>
<div class="operatingStatus">
<div class="operatingStatusFont">安全监测</div>
<div class="operatingStatusContent">
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 11.svg" alt="" />
</div>
<div class="contentBoxCont">
<safety-events></safety-events>
</div>
</div>
<div class="operatingStatusFont">炉况与电极运行统计</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 5.svg" alt="" />
</div>
<div class="contentBoxCont">
<div class="contentBoxCont">
<furnace-temperature-stability></furnace-temperature-stability>
</div>
</div>
</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 15.svg" alt="" />
<span>单位kg/炉次</span>
</div>
<div class="contentBoxCont">
<ElectrodeConsumption />
</div>
</div>
</div>
</div>
<div class="operatingStatus">
<div class="operatingStatusFont">能耗与电耗分析</div>
<div class="operatingStatusContent">
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 12.svg" alt="" />
</div>
<div class="contentBoxCont">
<PowerUsage />
</div>
</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 13.svg" alt="" />
<span>单位kWh/t</span>
</div>
<div class="contentBoxCont">
<div class="contentBoxCont">
<UnitPowerConsumption />
</div>
</div>
</div>
<div class="contentBox">
<div class="contentBoxFont">
<img src="@/assets/Component 14.svg" alt="" />
<span>单位kvar</span>
</div>
<div class="contentBoxCont">
<ReactiveCompensationEfficiency />
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped lang="less">
.main {
width: 256rem; // 416 * 0.615
height: 135rem; // 114.1875 * 1.154
background: radial-gradient(50% 50% at 50% 50%, #0f3b8c 0%, #0e357e 33.17%, #041026 100%);
}
.middleTitle {
width: 256rem; // 415.8125 * 0.615
height: 11.77rem; // 10.19919 * 1.154
flex-shrink: 0;
padding-top: 16px; // 33.81 * 1.154
display: inline-block;
background-image: url('~@/assets/title1.svg');
background-size: auto 72%;
background-repeat: no-repeat;
background-position: top center;
}
.middleTitleFont {
text-align: center;
text-shadow: 0 3.47px 8.68px #010a14; // 3.008 * 1.154, 7.519 * 1.154
font-family: 'DingTalk JinBuTi';
font-size: 4.33rem; // 3.75 * 1.154
font-style: normal;
font-weight: 400;
line-height: 4.33rem; // 3.75 * 1.154
letter-spacing: 0.87rem; // 0.75 * 1.154
background: linear-gradient(180deg, #fff 0%, #96dbf2 66.32%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.cockpit {
width: 15.97rem; // 25.96338 * 0.615
height: 5.55rem; // 4.8125 * 1.154
flex-shrink: 0;
margin-left: 41.77rem; // 67.92 * 0.615
background-image: url('~@/assets/Group 2785.svg');
}
.cockpitFont {
text-align: center;
text-shadow: 0 3.47px 8.68px #010a14;
font-family: 'DingTalk JinBuTi';
font-size: 3.25rem; // 2.8125 * 1.154
font-style: normal;
font-weight: 400;
letter-spacing: 0.87rem;
background: linear-gradient(180deg, #fff 0%, #dff7ff 66.32%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.branchPlantProCap {
width: 15.97rem;
height: 5.55rem;
flex-shrink: 0;
margin-left: 57.84rem; // 94.04 * 0.615
background-image: url('~@/assets/Group 2789.png');
}
.branchPlantProCapFont {
text-align: center;
text-shadow: 0 3.47px 8.68px #010a14;
font-family: 'DingTalk JinBuTi';
font-size: 3.25rem;
font-style: normal;
font-weight: 400;
letter-spacing: 0.87rem;
background: linear-gradient(180deg, rgba(177, 245, 255, 0.8) 0%, rgba(150, 219, 242, 0.8) 66.32%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.productionEfficiency {
width: 16.03rem; // 26.0625 * 0.615
height: 5.55rem;
flex-shrink: 0;
margin-left: 182.04rem; // 296 * 0.615
background-image: url('~@/assets/Group 2790.svg');
}
.productionEfficiencyFont {
text-align: center;
text-shadow: 0 3.47px 8.68px #010a14;
font-family: 'DingTalk JinBuTi';
font-size: 3.25rem;
font-style: normal;
font-weight: 400;
letter-spacing: 0.87rem;
background: linear-gradient(180deg, rgba(177, 245, 255, 0.8) 0%, rgba(150, 219, 242, 0.8) 66.32%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.safetyManagement {
width: 16.03rem;
height: 5.55rem;
flex-shrink: 0;
margin-left: 198.03rem; // 322 * 0.615
background-image: url('~@/assets/Group 2791.svg');
}
.safetyManagementFont {
text-align: center;
text-shadow: 0 3.47px 8.68px #010a14;
font-family: 'DingTalk JinBuTi';
font-size: 3.25rem;
font-style: normal;
font-weight: 400;
letter-spacing: 0.87rem;
background: linear-gradient(180deg, rgba(177, 245, 255, 0.8) 0%, rgba(150, 219, 242, 0.8) 66.32%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.operatingStatus1 {
width: 1000px; // 2236 * 0.615
height: 1480px; // 1217 * 1.154
}
.operatingStatusFont {
color: #fff;
font-family: 'DingTalk JinBuTi';
font-size: 2.16rem; // 1.8745 * 1.154
font-style: normal;
font-weight: 400;
line-height: 180%;
letter-spacing: 0.43rem; // 0.37488 * 1.154
height: 4.04rem; // 3.5 * 1.154
flex-shrink: 0;
background-image: url('~@/assets/Group 1142814701.svg');
}
.operatingStatusBox {
display: flex;
justify-content: space-between;
margin: 0px 100px; // 215 * 0.615
}
.operatingStatus {
width: 700px; // 941 * 0.615
}
.operatingStatusContent {
display: flex;
flex-direction: column;
height: 1500px; // 1300 * 1.154
justify-content: space-around;
.contentBox {
width: 700px; // 936 * 0.615
height: 410px; // 343 * 1.154
flex-shrink: 0;
.contentBoxFont {
overflow: hidden;
position: relative;
span {
position: absolute;
z-index: 99;
right: 0; // 335 * 0.615
top: 10px; // 9 * 1.154
font-family: 'DingTalk JinBuTi';
font-style: italic;
font-weight: 400;
font-size: 17px; // 15 * 1.154
line-height: 150%;
text-align: center;
letter-spacing: 0.2em;
color: #60f2ff;
&.half {
right: 0;
}
}
}
.contentBoxCont {
background: linear-gradient(126.97deg, rgba(6, 11, 40, 0.74) 28.26%, rgba(10, 14, 35, 0.71) 91.2%);
border: 0.94px solid #3675c9;
height: 344px; // 298 * 1.154
}
}
.contentBox1{
display: flex;
justify-content: space-between;
> div {
width: 49%;
}
}
}
</style>

View File

@ -0,0 +1,206 @@
<template>
<div class="electrode-consumption">
<div class="chart-container" ref="chartContainer"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'ElectrodeConsumption',
data() {
return {
chart: null,
chartData: {
dates: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31'],
dailyMax: [13.2, 12.8, 11.5, 12.1, 12.5, 13.1, 12.9, 12.3, 12.7, 13.0, 12.4, 11.8, 12.2, 12.6, 13.3, 12.1, 11.9, 12.8, 13.1, 12.5, 12.0, 11.7, 12.4, 12.9, 13.2, 12.3, 11.6, 12.7, 13.0, 12.2, 11.8],
dailyAvg: [9.8, 9.5, 8.2, 8.8, 9.2, 9.7, 9.4, 8.9, 9.3, 9.6, 9.0, 8.4, 8.7, 9.1, 9.8, 8.6, 8.3, 9.4, 9.7, 9.1, 8.6, 8.1, 8.9, 9.4, 9.8, 8.8, 8.0, 9.3, 9.6, 8.7, 8.2],
dailyMin: [6.2, 5.8, 4.5, 5.1, 5.5, 6.1, 5.9, 5.3, 5.7, 6.0, 5.4, 4.8, 5.2, 5.6, 6.3, 5.1, 4.9, 5.8, 6.1, 5.5, 5.0, 4.7, 5.4, 5.9, 6.2, 5.3, 4.6, 5.7, 6.0, 5.2, 4.8]
}
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
}
window.removeEventListener('resize', this.handleResize)
},
methods: {
initChart() {
this.chart = echarts.init(this.$refs.chartContainer)
const option = {
grid: {
top: '15%',
left: '8%',
right: '5%',
bottom: '15%',
containLabel: true
},
xAxis: {
type: 'category',
data: this.chartData.dates,
axisLine: {
lineStyle: {
color: '#4a90e2'
}
},
axisLabel: {
color: '#ffffff',
fontSize: 10
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(74, 144, 226, 0.2)',
type: 'dashed'
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 15,
axisLine: {
lineStyle: {
color: '#4a90e2'
}
},
axisLabel: {
color: '#ffffff',
fontSize: 10
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(74, 144, 226, 0.2)',
type: 'dashed'
}
}
},
legend: {
data: ['日最高', '日平均', '日最低'],
bottom: '5%',
textStyle: {
color: '#ffffff',
fontSize: 12
},
itemWidth: 12,
itemHeight: 8
},
series: [
{
name: '日最高',
type: 'line',
data: this.chartData.dailyMax,
smooth: true,
symbol: 'circle',
symbolSize: 4,
lineStyle: {
color: '#00d4aa',
width: 2
},
itemStyle: {
color: '#00d4aa'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(0, 212, 170, 0.3)' },
{ offset: 1, color: 'rgba(0, 212, 170, 0.05)' }
]
}
}
},
{
name: '日平均',
type: 'line',
data: this.chartData.dailyAvg,
smooth: true,
symbol: 'circle',
symbolSize: 4,
lineStyle: {
color: '#9c27b0',
width: 2
},
itemStyle: {
color: '#9c27b0'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(156, 39, 176, 0.3)' },
{ offset: 1, color: 'rgba(156, 39, 176, 0.05)' }
]
}
}
},
{
name: '日最低',
type: 'line',
data: this.chartData.dailyMin,
smooth: true,
symbol: 'circle',
symbolSize: 4,
lineStyle: {
color: '#ff9800',
width: 2
},
itemStyle: {
color: '#ff9800'
},
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(255, 152, 0, 0.3)' },
{ offset: 1, color: 'rgba(255, 152, 0, 0.05)' }
]
}
}
}
]
}
this.chart.setOption(option)
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style scoped>
.electrode-consumption {
width: 100%;
height: 100%;
background: transparent;
}
.chart-container {
width: 100%;
height: 100%;
}
</style>

View File

@ -0,0 +1,155 @@
<template>
<div class="furnace-production-contribution">
<div class="chart-container">
<div id="furnaceChart" class="chart"></div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'FurnaceProductionContribution',
data() {
return {
furnaceData: [
{ name: '1#炉', value: 780 },
{ name: '2#炉', value: 950 },
{ name: '3#炉', value: 820 },
{ name: '4#炉', value: 580 },
{ name: '5#炉', value: 1200 },
{ name: '6#炉', value: 890 },
{ name: '7#炉', value: 720 },
{ name: '8#炉', value: 760 }
]
}
},
mounted() {
this.initChart()
},
methods: {
initChart() {
const chartDom = document.getElementById('furnaceChart')
const myChart = echarts.init(chartDom)
const option = {
backgroundColor: 'transparent',
grid: {
left: '8%',
right: '8%',
bottom: '15%',
top: '10%',
containLabel: true
},
xAxis: {
type: 'category',
data: this.furnaceData.map(item => item.name),
axisLine: {
lineStyle: {
color: '#1e3a8a'
}
},
axisLabel: {
color: '#60a5fa',
fontSize: 12
},
axisTick: {
show: false
}
},
yAxis: {
type: 'value',
max: 1600,
interval: 400,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#60a5fa',
fontSize: 12
},
splitLine: {
lineStyle: {
color: '#1e3a8a',
type: 'dashed'
}
}
},
series: [{
type: 'bar',
data: this.furnaceData.map(item => item.value),
barWidth: '60%',
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: '#3b82f6'
}, {
offset: 1,
color: '#1e40af'
}]
},
borderRadius: [2, 2, 0, 0]
},
emphasis: {
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: '#60a5fa'
}, {
offset: 1,
color: '#2563eb'
}]
}
}
}
}]
}
myChart.setOption(option)
//
window.addEventListener('resize', () => {
myChart.resize()
})
}
}
}
</script>
<style lang="less" scoped>
.furnace-production-contribution {
width: 100%;
height: 100%;
background: rgba(15, 23, 42, 0.8);
border: 1px solid #1e3a8a;
border-radius: 8px;
padding: 16px;
.chart-container {
width: 100%;
height: 100%;
.chart {
width: 100%;
height: 100%;
min-height: 300px;
}
}
}
</style>

View File

@ -0,0 +1,146 @@
<template>
<div class="furnace-temperature-stability">
<div ref="chart" class="chart-container"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'FurnaceTemperatureStability',
data() {
return {
chartData: {
categories: ['7.1-7.2', '3-4', '5-6', '7-8', '9-10', '11-12', '13-14', '15-16', '17-18', '19-20', '21-22', '23-24', '25-26', '27-28', '29-30', '29-30'],
abnormal: [25, 25, 25, 25, 0, 0, 0, 25, 25, 25, 0, 0, 0, 0, 0, 0],
fluctuation: [25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0],
stable: [50, 50, 50, 50, 75, 75, 75, 50, 50, 50, 100, 100, 100, 100, 100, 100]
}
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
}
window.removeEventListener('resize', this.handleResize)
},
methods: {
initChart() {
this.chart = echarts.init(this.$refs.chart)
const option = {
grid: {
top: '15%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: this.chartData.categories,
axisLine: {
lineStyle: {
color: '#3675c9'
}
},
axisLabel: {
color: '#fff',
fontSize: 12,
rotate: 0
},
axisTick: {
show: false
}
},
yAxis: {
type: 'value',
max: 100,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#fff',
fontSize: 12
},
splitLine: {
lineStyle: {
color: 'rgba(54, 117, 201, 0.3)',
type: 'dashed'
}
}
},
legend: {
data: ['异常', '波动', '稳定'],
top: '5%',
right: '10%',
textStyle: {
color: '#fff',
fontSize: 12
},
itemWidth: 12,
itemHeight: 8
},
series: [
{
name: '稳定',
type: 'bar',
stack: 'total',
data: this.chartData.stable,
itemStyle: {
color: '#00bfff'
},
barWidth: '60%'
},
{
name: '波动',
type: 'bar',
stack: 'total',
data: this.chartData.fluctuation,
itemStyle: {
color: '#ffa500'
}
},
{
name: '异常',
type: 'bar',
stack: 'total',
data: this.chartData.abnormal,
itemStyle: {
color: '#ff6b6b'
}
}
]
}
this.chart.setOption(option)
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style lang="less" scoped>
.furnace-temperature-stability {
width: 100%;
height: 100%;
background: transparent;
.chart-container {
width: 100%;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,238 @@
<template>
<div class="power-consumption">
<div class="chart-container" ref="chartContainer"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'PowerConsumption',
data() {
return {
powerData: {
days: Array.from({ length: 31 }, (_, i) => i + 1),
dailyMax: [52, 48, 53, 45, 49, 47, 51, 39, 46, 50, 48, 52, 44, 53, 47, 49, 46, 38, 51, 47, 50, 49, 52, 45, 47, 51, 39, 46, 50, 48, 52],
dailyAvg: [42, 38, 43, 35, 39, 37, 41, 29, 36, 40, 38, 42, 34, 43, 37, 39, 36, 28, 41, 37, 40, 39, 42, 35, 37, 41, 29, 36, 40, 38, 42],
dailyMin: [32, 28, 33, 25, 29, 27, 31, 19, 26, 30, 28, 32, 24, 33, 27, 29, 26, 18, 31, 27, 30, 29, 32, 25, 27, 31, 19, 26, 30, 28, 32]
}
}
},
mounted() {
this.initChart()
},
methods: {
initChart() {
const chart = echarts.init(this.$refs.chartContainer)
const option = {
backgroundColor: 'transparent',
grid: {
left: '5%',
right: '5%',
top: '15%',
bottom: '15%',
containLabel: true
},
legend: {
data: ['日最高', '日平均', '日最低'],
textStyle: {
color: '#ffffff',
fontSize: 12
},
top: '5%',
right: '10%'
},
xAxis: {
type: 'category',
data: this.powerData.days,
axisLine: {
lineStyle: {
color: '#1e3a8a'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#60a5fa',
fontSize: 10,
interval: 4
},
splitLine: {
show: true,
lineStyle: {
color: '#1e3a8a',
type: 'dashed',
opacity: 0.3
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 60,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#60a5fa',
fontSize: 10
},
splitLine: {
show: true,
lineStyle: {
color: '#1e3a8a',
type: 'dashed',
opacity: 0.3
}
}
},
series: [
{
name: '日最高',
type: 'line',
data: this.powerData.dailyMax,
lineStyle: {
color: '#fbbf24',
width: 2
},
itemStyle: {
color: '#fbbf24'
},
symbol: 'circle',
symbolSize: 4,
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(251, 191, 36, 0.3)'
},
{
offset: 1,
color: 'rgba(251, 191, 36, 0.05)'
}
]
}
}
},
{
name: '日平均',
type: 'line',
data: this.powerData.dailyAvg,
lineStyle: {
color: '#3b82f6',
width: 2
},
itemStyle: {
color: '#3b82f6'
},
symbol: 'circle',
symbolSize: 4,
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(59, 130, 246, 0.3)'
},
{
offset: 1,
color: 'rgba(59, 130, 246, 0.05)'
}
]
}
}
},
{
name: '日最低',
type: 'line',
data: this.powerData.dailyMin,
lineStyle: {
color: '#10b981',
width: 2
},
itemStyle: {
color: '#10b981'
},
symbol: 'circle',
symbolSize: 4,
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: 'rgba(16, 185, 129, 0.3)'
},
{
offset: 1,
color: 'rgba(16, 185, 129, 0.05)'
}
]
}
}
}
],
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0, 0, 0, 0.8)',
borderColor: '#3675c9',
textStyle: {
color: '#ffffff'
},
formatter: function(params) {
let result = `${params[0].axisValue}天<br/>`
params.forEach(param => {
result += `${param.seriesName}: ${param.value}<br/>`
})
return result
}
}
}
chart.setOption(option)
//
window.addEventListener('resize', () => {
chart.resize()
})
}
}
}
</script>
<style lang="less" scoped>
.power-consumption {
width: 100%;
height: 100%;
background: linear-gradient(180deg, #0f172a 0%, #1e293b 100%);
border-radius: 8px;
padding: 20px;
.chart-container {
width: 100%;
height: 280px;
}
}
</style>

View File

@ -0,0 +1,161 @@
<template>
<div class="power-usage">
<div class="usage-cards">
<div class="usage-card">
<div class="card-icon">
<div class="icon-wrapper">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#00d4aa"/>
</svg>
</div>
</div>
<div class="card-content">
<div class="card-title">总用电量</div>
<div class="card-value">{{ totalPowerUsage.value }}<span class="unit">{{ totalPowerUsage.unit }}</span></div>
</div>
</div>
<div class="usage-card">
<div class="card-icon">
<div class="icon-wrapper">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#00d4aa"/>
</svg>
</div>
</div>
<div class="card-content">
<div class="card-title">单位电耗</div>
<div class="card-value">{{ unitPowerConsumption.value }}<span class="unit">{{ unitPowerConsumption.unit }}</span></div>
</div>
</div>
<div class="usage-card">
<div class="card-icon">
<div class="icon-wrapper">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill="#00d4aa"/>
</svg>
</div>
</div>
<div class="card-content">
<div class="card-title">峰谷时段电量占比</div>
<div class="card-value">{{ peakValleyRatio.value }}<span class="unit">{{ peakValleyRatio.unit }}</span></div>
<div class="progress-bar">
<div class="progress-fill" :style="{ width: peakValleyRatio.value + '%' }"></div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'PowerUsage',
data() {
return {
totalPowerUsage: {
value: '32,984',
unit: 'kWh'
},
unitPowerConsumption: {
value: '2.42',
unit: 'mkWh/t'
},
peakValleyRatio: {
value: '40',
unit: '%'
}
}
}
}
</script>
<style scoped>
.power-usage {
width: 100%;
height: 100%;
padding: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.usage-cards {
display: flex;
gap: 40px;
align-items: center;
justify-content: space-between;
width: 100%;
}
.usage-card {
display: flex;
align-items: center;
gap: 15px;
flex: 1;
}
.card-icon {
display: flex;
align-items: center;
justify-content: center;
}
.icon-wrapper {
width: 48px;
height: 48px;
background: rgba(0, 212, 170, 0.2);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid rgba(0, 212, 170, 0.3);
}
.card-content {
flex: 1;
}
.card-title {
color: #60f2ff;
font-family: 'DingTalk JinBuTi';
font-size: 14px;
font-weight: 400;
line-height: 1.4;
margin-bottom: 8px;
}
.card-value {
color: #ffffff;
font-family: 'DingTalk JinBuTi';
font-size: 28px;
font-weight: 600;
line-height: 1.2;
display: flex;
align-items: baseline;
gap: 4px;
}
.unit {
color: #60f2ff;
font-size: 14px;
font-weight: 400;
}
.progress-bar {
width: 100%;
height: 4px;
background: rgba(96, 242, 255, 0.2);
border-radius: 2px;
margin-top: 8px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #00d4aa 0%, #60f2ff 100%);
border-radius: 2px;
transition: width 0.3s ease;
}
</style>

View File

@ -0,0 +1,217 @@
<template>
<div class="product-data">
<div class="data-item monthly-production">
<div class="title">本月累计产量</div>
<div class="value">{{ productionData.monthlyProduction }}</div>
<div class="unit">(t)</div>
<div class="date">截止到{{ productionData.date }}</div>
</div>
<div class="data-item">
<div class="title">产品合格率</div>
<div class="chart-container" ref="qualifiedRateChart"></div>
</div>
<div class="data-item">
<div class="title">炉温稳定率</div>
<div class="chart-container" ref="temperatureStabilityChart"></div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'ProductData',
data() {
return {
productionData: {
monthlyProduction: '432,928',
date: '8-20',
qualifiedRate: 95,
temperatureStability: 92
},
qualifiedRateChart: null,
temperatureStabilityChart: null
}
},
mounted() {
this.initQualifiedRateChart()
this.initTemperatureStabilityChart()
},
methods: {
initQualifiedRateChart() {
this.qualifiedRateChart = echarts.init(this.$refs.qualifiedRateChart)
const option = {
series: [{
type: 'gauge',
startAngle: 180,
endAngle: 0,
min: 0,
max: 100,
radius: '100%',
itemStyle: {
color: '#42d3a5'
},
progress: {
show: true,
width: 18
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 18,
color: [
[1, '#E3E3E3']
]
}
},
axisTick: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
title: {
show: true,
offsetCenter: [0, '30%'],
fontSize: 20,
fontWeight: 'bold',
color: '#fff',
fontFamily: 'DingTalk JinBuTi'
},
detail: {
valueAnimation: true,
fontSize: 25,
offsetCenter: [0, '20%'],
formatter: '{value}%',
color: '#fff',
fontFamily: 'DingTalk JinBuTi'
},
data: [{
value: this.productionData.qualifiedRate,
name: ''
}]
}]
}
this.qualifiedRateChart.setOption(option)
},
initTemperatureStabilityChart() {
this.temperatureStabilityChart = echarts.init(this.$refs.temperatureStabilityChart)
const option = {
series: [{
type: 'gauge',
startAngle: 180,
endAngle: 0,
min: 0,
max: 100,
radius: '100%',
itemStyle: {
color: '#a66cff'
},
progress: {
show: true,
width: 18
},
pointer: {
show: false
},
axisLine: {
lineStyle: {
width: 18,
color: [
[1, '#E3E3E3']
]
}
},
axisTick: {
show: false
},
splitLine: {
show: false
},
axisLabel: {
show: false
},
title: {
show: true,
offsetCenter: [0, '30%'],
fontSize: 20,
fontWeight: 'bold',
color: '#fff',
fontFamily: 'DingTalk JinBuTi'
},
detail: {
valueAnimation: true,
fontSize: 25,
offsetCenter: [0, '20%'],
formatter: '{value}%',
color: '#fff',
fontFamily: 'DingTalk JinBuTi'
},
data: [{
value: this.productionData.temperatureStability,
name: ''
}]
}]
}
this.temperatureStabilityChart.setOption(option)
}
}
}
</script>
<style scoped lang="less">
.product-data {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 100%;
color: #fff;
font-family: 'DingTalk JinBuTi';
.data-item {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
.title {
font-size: 1.8rem;
margin-bottom: 1rem;
color: #fff;
}
.chart-container {
width: 100%;
height: 150px;
}
}
.monthly-production {
.value {
font-size: 3.5rem;
font-weight: bold;
color: #60f2ff;
}
.unit {
font-size: 1.2rem;
color: #60f2ff;
}
.date {
font-size: 1rem;
color: #999;
margin-top: 0.5rem;
}
}
}
</style>

View File

@ -0,0 +1,176 @@
<template>
<div class="product-output">
<div class="product-data">
<div class="product-item" v-for="item in productData" :key="item.name">
<div class="product-label">
<div class="product-icon">{{ item.symbol }}</div>
<div class="product-name">{{ item.name }}</div>
</div>
<div class="product-value">{{ item.value.toLocaleString() }}</div>
</div>
</div>
<div class="chart-container">
<div ref="pieChart" class="pie-chart"></div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'ProductOutput',
data() {
return {
productData: [
{ name: '中锰', symbol: 'FeMn', value: 1692 },
{ name: '硅锰', symbol: 'SiMn', value: 722 },
{ name: '碳铬', symbol: 'FeCr', value: 3898 },
{ name: '硅铁', symbol: 'FeSi', value: 2618 }
]
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
if (this.chart) {
this.chart.dispose()
}
},
methods: {
initChart() {
const chart = echarts.init(this.$refs.pieChart)
this.chart = chart
const total = this.productData.reduce((sum, item) => sum + item.value, 0)
const chartData = this.productData.map(item => ({
name: item.name,
value: item.value,
percentage: ((item.value / total) * 100).toFixed(2)
}))
const option = {
backgroundColor: 'transparent',
title: {
text: '产量比',
left: 'center',
top: 'center',
textStyle: {
color: '#ffffff',
fontSize: 18,
fontWeight: 'normal'
}
},
legend: {
orient: 'vertical',
right: '10%',
top: 'center',
textStyle: {
color: '#ffffff',
fontSize: 12
},
formatter: function(name) {
const item = chartData.find(d => d.name === name)
return `${name} ${item.percentage}%`
}
},
series: [
{
type: 'pie',
radius: ['40%', '70%'],
center: ['35%', '50%'],
avoidLabelOverlap: false,
label: {
show: false
},
labelLine: {
show: false
},
data: chartData,
itemStyle: {
borderRadius: 5,
borderColor: 'rgba(0,0,0,0.1)',
borderWidth: 1
},
color: ['#FF6B9D', '#4ECDC4', '#45B7D1', '#96CEB4']
}
]
}
chart.setOption(option)
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style scoped lang="less">
.product-output {
display: flex;
width: 100%;
height: 100%;
padding: 20px;
.product-data {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-around;
padding-right: 20px;
.product-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
.product-label {
display: flex;
align-items: center;
.product-icon {
width: 40px;
height: 30px;
background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
border: 1px solid #4ECDC4;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
color: #4ECDC4;
font-size: 12px;
font-weight: bold;
margin-right: 10px;
}
.product-name {
color: #ffffff;
font-size: 14px;
}
}
.product-value {
color: #4ECDC4;
font-size: 18px;
font-weight: bold;
}
}
}
.chart-container {
flex: 1;
.pie-chart {
width: 100%;
height: 250px;
}
}
}
</style>

View File

@ -0,0 +1,135 @@
<template>
<div class="product-qualification-rate">
<div class="qualification-table">
<div
v-for="product in productQualificationData"
:key="product.symbol"
class="qualification-row"
>
<div class="product-info">
<span class="product-symbol">{{ product.symbol }}</span>
<span class="product-name">{{ product.name }}</span>
</div>
<div class="progress-container">
<div class="progress-bar">
<div
class="progress-fill"
:style="{ width: product.rate + '%' }"
></div>
</div>
</div>
<div class="rate-value">{{ product.rate }}%</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'ProductQualificationRate',
data() {
return {
productQualificationData: [
{
symbol: 'FeMn',
name: '中锰',
rate: 100.0
},
{
symbol: 'SiMn',
name: '硅锰',
rate: 92.4
},
{
symbol: 'FeSi',
name: '硅铁',
rate: 98.4
},
{
symbol: 'FeCr',
name: '碳铬',
rate: 97.1
}
]
}
}
}
</script>
<style scoped lang="less">
.product-qualification-rate {
width: 100%;
height: 100%;
padding: 20px;
.qualification-table {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
.qualification-row {
display: flex;
align-items: center;
height: 60px;
border-bottom: 1px solid rgba(54, 117, 201, 0.3);
&:last-child {
border-bottom: none;
}
.product-info {
width: 120px;
display: flex;
flex-direction: column;
align-items: flex-start;
.product-symbol {
font-family: 'DingTalk JinBuTi';
font-size: 18px;
font-weight: 600;
color: #ffffff;
line-height: 1.2;
}
.product-name {
font-family: 'DingTalk JinBuTi';
font-size: 14px;
color: #96dbf2;
line-height: 1.2;
}
}
.progress-container {
flex: 1;
margin: 0 20px;
.progress-bar {
width: 100%;
height: 8px;
background: rgba(54, 117, 201, 0.2);
border-radius: 4px;
overflow: hidden;
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #00ff88 0%, #00cc6a 100%);
border-radius: 4px;
transition: width 0.3s ease;
}
}
}
.rate-value {
width: 80px;
text-align: right;
font-family: 'DingTalk JinBuTi';
font-size: 20px;
font-weight: 600;
color: #ffffff;
}
}
}
}
</style>

View File

@ -0,0 +1,207 @@
<template>
<div class="product-quality-rate">
<div ref="lineChart" class="line-chart"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'ProductQualityRate',
data() {
return {
chartData: {
days: Array.from({ length: 31 }, (_, i) => i + 1),
cr: [72, 85, 88, 75, 68, 78, 82, 79, 85, 83, 87, 74, 86, 89, 72, 68, 78, 85, 79, 83, 87, 85, 74, 68, 78, 85, 79, 83, 87, 85, 74],
si: [45, 68, 72, 45, 55, 62, 58, 65, 70, 62, 68, 45, 72, 68, 45, 55, 62, 58, 65, 70, 62, 68, 45, 55, 62, 58, 65, 70, 62, 68, 58],
c: [32, 55, 38, 35, 12, 8, 35, 38, 32, 28, 35, 32, 38, 35, 12, 8, 35, 38, 32, 28, 35, 32, 38, 35, 12, 8, 35, 38, 32, 28, 45]
}
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
if (this.chart) {
this.chart.dispose()
}
},
methods: {
initChart() {
const chart = echarts.init(this.$refs.lineChart)
this.chart = chart
const option = {
backgroundColor: 'transparent',
grid: {
left: '5%',
right: '5%',
bottom: '15%',
top: '10%',
containLabel: true
},
xAxis: {
type: 'category',
data: this.chartData.days,
axisLine: {
lineStyle: {
color: '#1e3c72'
}
},
axisLabel: {
color: '#4ECDC4',
fontSize: 10
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(78, 205, 196, 0.1)',
type: 'dashed'
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 100,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
color: '#4ECDC4',
fontSize: 10
},
splitLine: {
lineStyle: {
color: 'rgba(78, 205, 196, 0.1)',
type: 'dashed'
}
}
},
legend: {
data: ['Cr', 'Si', 'C'],
bottom: '5%',
textStyle: {
color: '#ffffff',
fontSize: 12
},
itemWidth: 20,
itemHeight: 2
},
series: [
{
name: 'Cr',
type: 'line',
data: this.chartData.cr,
smooth: true,
lineStyle: {
color: '#9B59B6',
width: 2
},
itemStyle: {
color: '#9B59B6'
},
symbol: 'circle',
symbolSize: 4,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(155, 89, 182, 0.3)' },
{ offset: 1, color: 'rgba(155, 89, 182, 0.05)' }
]
}
}
},
{
name: 'Si',
type: 'line',
data: this.chartData.si,
smooth: true,
lineStyle: {
color: '#2ECC71',
width: 2
},
itemStyle: {
color: '#2ECC71'
},
symbol: 'circle',
symbolSize: 4,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(46, 204, 113, 0.3)' },
{ offset: 1, color: 'rgba(46, 204, 113, 0.05)' }
]
}
}
},
{
name: 'C',
type: 'line',
data: this.chartData.c,
smooth: true,
lineStyle: {
color: '#3498DB',
width: 2
},
itemStyle: {
color: '#3498DB'
},
symbol: 'circle',
symbolSize: 4,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(52, 152, 219, 0.3)' },
{ offset: 1, color: 'rgba(52, 152, 219, 0.05)' }
]
}
}
}
]
}
chart.setOption(option)
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style scoped lang="less">
.product-quality-rate {
width: 100%;
height: 100%;
padding: 20px;
.line-chart {
width: 100%;
height: 250px;
}
}
</style>

View File

@ -0,0 +1,110 @@
<template>
<div class="production-chart">
<div class="chart-container" ref="productionChart"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'Production',
data() {
return {
productionChart: null,
productionData: {
dates: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31'],
values: [7000, 5000, 6000, 4500, 3000, 5000, 9000, 4500, 6000, 3500, 2000, 6500, 4500, 7500, 5000, 5000, 4500, 6000, 3000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
}
},
mounted() {
this.initProductionChart()
//
window.addEventListener('resize', this.resizeChart)
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeChart)
if (this.productionChart) {
this.productionChart.dispose()
}
},
methods: {
initProductionChart() {
this.productionChart = echarts.init(this.$refs.productionChart)
const option = {
grid: {
left: '3%',
right: '4%',
bottom: '3%',
top: '5%',
containLabel: true
},
xAxis: {
type: 'category',
data: this.productionData.dates,
axisLine: {
lineStyle: {
color: '#60f2ff'
}
},
axisLabel: {
color: '#fff',
fontFamily: 'DingTalk JinBuTi',
fontSize: 10
},
axisTick: {
show: false
}
},
yAxis: {
type: 'value',
max: 10000,
splitLine: {
lineStyle: {
color: 'rgba(96, 242, 255, 0.1)'
}
},
axisLine: {
show: true,
lineStyle: {
color: '#60f2ff'
}
},
axisLabel: {
color: '#fff',
fontFamily: 'DingTalk JinBuTi',
fontSize: 10
}
},
series: [{
data: this.productionData.values,
type: 'bar',
barWidth: '40%',
itemStyle: {
color: '#60f2ff'
}
}]
}
this.productionChart.setOption(option)
},
resizeChart() {
if (this.productionChart) {
this.productionChart.resize()
}
}
}
}
</script>
<style scoped lang="less">
.production-chart {
width: 100%;
height: 100%;
.chart-container {
width: 100%;
height: 100%;
}
}
</style>

View File

@ -0,0 +1,215 @@
<template>
<div class="reactive-compensation-efficiency">
<div class="chart-header">
<h3>无功补偿效率</h3>
</div>
<div ref="chart" class="chart-container"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'ReactiveCompensationEfficiency',
data() {
return {
chartData: {
dates: Array.from({ length: 31 }, (_, i) => i + 1),
dailyMax: [85, 78, 82, 75, 80, 88, 92, 85, 78, 82, 90, 85, 88, 92, 85, 78, 82, 75, 80, 88, 92, 85, 78, 82, 90, 85, 88, 92, 85, 78, 82],
dailyAvg: [65, 58, 62, 55, 60, 68, 72, 65, 58, 62, 70, 65, 68, 72, 65, 58, 62, 55, 60, 68, 72, 65, 58, 62, 70, 65, 68, 72, 65, 58, 62],
dailyMin: [45, 38, 42, 35, 40, 48, 52, 45, 38, 42, 50, 45, 48, 52, 45, 38, 42, 35, 40, 48, 52, 45, 38, 42, 50, 45, 48, 52, 45, 38, 42]
},
chart: null
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
}
window.removeEventListener('resize', this.handleResize)
},
methods: {
initChart() {
this.chart = echarts.init(this.$refs.chart)
const option = {
backgroundColor: 'transparent',
grid: {
top: '15%',
left: '8%',
right: '8%',
bottom: '15%',
containLabel: true
},
legend: {
data: ['日最高', '日平均', '日最低'],
top: '5%',
right: '10%',
textStyle: {
color: '#ffffff',
fontSize: 12
},
itemWidth: 20,
itemHeight: 2
},
xAxis: {
type: 'category',
data: this.chartData.dates,
axisLine: {
lineStyle: {
color: '#2a4a6b'
}
},
axisLabel: {
color: '#7ec7ff',
fontSize: 10
},
axisTick: {
show: false
},
splitLine: {
show: true,
lineStyle: {
color: '#1e3a5f',
type: 'dashed'
}
}
},
yAxis: {
type: 'value',
min: 0,
max: 100,
axisLine: {
lineStyle: {
color: '#2a4a6b'
}
},
axisLabel: {
color: '#7ec7ff',
fontSize: 10,
formatter: '{value}%'
},
axisTick: {
show: false
},
splitLine: {
show: true,
lineStyle: {
color: '#1e3a5f',
type: 'dashed'
}
}
},
tooltip: {
trigger: 'axis',
backgroundColor: 'rgba(0, 20, 40, 0.8)',
borderColor: '#00d4ff',
borderWidth: 1,
textStyle: {
color: '#ffffff'
},
formatter: function(params) {
let result = `${params[0].axisValue}日<br/>`
params.forEach(param => {
result += `${param.seriesName}: ${param.value}%<br/>`
})
return result
}
},
series: [
{
name: '日最高',
type: 'line',
data: this.chartData.dailyMax,
smooth: true,
lineStyle: {
color: '#00d4ff',
width: 2
},
itemStyle: {
color: '#00d4ff'
},
symbol: 'circle',
symbolSize: 4,
showSymbol: false
},
{
name: '日平均',
type: 'line',
data: this.chartData.dailyAvg,
smooth: true,
lineStyle: {
color: '#00ff88',
width: 2
},
itemStyle: {
color: '#00ff88'
},
symbol: 'circle',
symbolSize: 4,
showSymbol: false
},
{
name: '日最低',
type: 'line',
data: this.chartData.dailyMin,
smooth: true,
lineStyle: {
color: '#ff6b9d',
width: 2
},
itemStyle: {
color: '#ff6b9d'
},
symbol: 'circle',
symbolSize: 4,
showSymbol: false
}
]
}
this.chart.setOption(option)
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style scoped>
.reactive-compensation-efficiency {
width: 100%;
height: 100%;
background: linear-gradient(135deg, rgba(0, 20, 40, 0.8) 0%, rgba(0, 40, 80, 0.6) 100%);
border: 1px solid rgba(0, 212, 255, 0.3);
border-radius: 8px;
padding: 16px;
box-sizing: border-box;
}
.chart-header {
margin-bottom: 10px;
}
.chart-header h3 {
color: #ffffff;
font-size: 16px;
font-weight: 500;
margin: 0;
text-align: center;
}
.chart-container {
width: 100%;
height: calc(100% - 40px);
min-height: 200px;
}
</style>

View File

@ -0,0 +1,228 @@
<template>
<div class="safety-events">
<div class="events-container">
<!-- 左侧事件列表 -->
<div class="events-left">
<div
v-for="event in leftEvents"
:key="event.id"
class="event-item"
:class="`level-${event.level}`"
>
<div class="event-time">{{ event.time }}</div>
<div class="event-content">
<div class="event-level">
<span class="level-icon"></span>
<span class="level-text">{{ event.levelText }}</span>
</div>
<div class="event-description">{{ event.description }}</div>
</div>
</div>
</div>
<!-- 右侧状态统计 -->
<div class="events-right">
<div class="status-item">
<div class="status-count processed">{{ processedCount }}</div>
<div class="status-label">已处理</div>
</div>
<div class="status-item">
<div class="status-count pending">{{ pendingCount }}</div>
<div class="status-label">待处理</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SafetyEvents',
data() {
return {
safetyEventsData: [
{
id: 1,
time: '2022-11-23 11:37:25',
level: 1,
levelText: 'I级',
description: 'xxxx段发生严重xx请立即前往处理',
status: 'processed'
},
{
id: 2,
time: '2022-11-23 09:37:25',
level: 2,
levelText: 'II级',
description: 'xxxx发生xxx请立即前往处理',
status: 'pending'
}
]
}
},
computed: {
leftEvents() {
return this.safetyEventsData
},
processedCount() {
return this.safetyEventsData.filter(event => event.status === 'processed').length
},
pendingCount() {
return this.safetyEventsData.filter(event => event.status === 'pending').length
}
}
}
</script>
<style lang="less" scoped>
.safety-events {
width: 100%;
height: 100%;
background: rgba(15, 23, 42, 0.8);
border: 1px solid #1e3a8a;
border-radius: 8px;
padding: 16px;
overflow: hidden; /* 不显示滚动条 */
.events-container {
display: flex;
height: 100%;
gap: 20px;
.events-left {
flex: 1;
display: flex;
flex-direction: column;
gap: 12px;
overflow: hidden; /* 不显示滚动条 */
.event-item {
background: linear-gradient(126.97deg, rgba(6, 11, 40, 0.74) 28.26%, rgba(10, 14, 35, 0.71) 91.2%);
border: 1px solid #3675c9;
border-radius: 6px;
padding: 12px;
display: flex;
flex-direction: column;
gap: 8px;
&.level-1 {
border-left: 4px solid #ef4444;
.level-icon {
color: #ef4444;
}
.event-description {
background: linear-gradient(90deg, rgba(239, 68, 68, 0.2) 0%, rgba(239, 68, 68, 0.05) 100%);
}
}
&.level-2 {
border-left: 4px solid #f59e0b;
.level-icon {
color: #f59e0b;
}
.event-description {
background: linear-gradient(90deg, rgba(245, 158, 11, 0.2) 0%, rgba(245, 158, 11, 0.05) 100%);
}
}
.event-time {
color: #60a5fa;
font-family: 'DingTalk JinBuTi';
font-size: 14px;
font-weight: 400;
text-align: center;
margin-bottom: 4px;
}
.event-content {
display: flex;
flex-direction: column;
gap: 8px;
.event-level {
display: flex;
align-items: center;
gap: 6px;
justify-content: center;
.level-icon {
font-size: 16px;
font-weight: bold;
}
.level-text {
color: #ffffff;
font-family: 'DingTalk JinBuTi';
font-size: 14px;
font-weight: 500;
background: rgba(255, 255, 255, 0.1);
padding: 2px 8px;
border-radius: 4px;
}
}
.event-description {
color: #e2e8f0;
font-family: 'DingTalk JinBuTi';
font-size: 14px;
font-weight: 400;
line-height: 1.4;
padding: 8px 12px;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
}
}
}
}
.events-right {
width: 120px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 30px;
.status-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
.status-count {
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-family: 'DingTalk JinBuTi';
font-size: 24px;
font-weight: 600;
color: #ffffff;
&.processed {
background: #10b981;
}
&.pending {
background: #f59e0b;
}
}
.status-label {
color: #60a5fa;
font-family: 'DingTalk JinBuTi';
font-size: 14px;
font-weight: 400;
text-align: center;
}
}
}
}
}
</style>

View File

@ -0,0 +1,216 @@
<template>
<div class="unit-power-consumption">
<div ref="chart" class="chart-container"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
export default {
name: 'UnitPowerConsumption',
data() {
return {
chartData: {
dates: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31'],
// 线
dailyMax: [520, 530, 480, 470, 490, 510, 500, 520, 480, 490, 510, 520, 430, 420, 440, 480, 470, 490, 510, 500, 520, 480, 490, 510, 520, 430, 420, 440, 480, 470, 490],
dailyAvg: [420, 430, 380, 370, 390, 410, 400, 420, 380, 390, 410, 420, 330, 320, 340, 380, 370, 390, 410, 400, 420, 380, 390, 410, 420, 330, 320, 340, 380, 370, 390],
dailyMin: [320, 330, 280, 270, 290, 310, 300, 320, 280, 290, 310, 320, 230, 220, 240, 280, 270, 290, 310, 300, 320, 280, 290, 310, 320, 230, 220, 240, 280, 270, 290]
},
chart: null
}
},
mounted() {
this.initChart()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
if (this.chart) {
this.chart.dispose()
}
window.removeEventListener('resize', this.handleResize)
},
methods: {
initChart() {
this.chart = echarts.init(this.$refs.chart)
const option = {
grid: {
top: '15%',
left: '8%',
right: '8%',
bottom: '15%',
containLabel: true
},
legend: {
data: ['日最高', '日平均', '日最低'],
textStyle: {
color: '#FFFFFF',
fontSize: 12
},
bottom: '5%',
itemWidth: 12,
itemHeight: 12
},
xAxis: {
type: 'category',
data: this.chartData.dates,
axisLine: {
lineStyle: {
color: '#3675C9'
}
},
axisLabel: {
color: '#FFFFFF',
fontSize: 12
},
axisTick: {
show: false
}
},
yAxis: {
type: 'value',
min: 0,
max: 600,
interval: 100,
axisLine: {
lineStyle: {
color: '#3675C9'
}
},
axisLabel: {
color: '#FFFFFF',
fontSize: 12,
formatter: '{value}'
},
splitLine: {
lineStyle: {
color: 'rgba(54, 117, 201, 0.3)',
type: 'dashed'
}
}
},
series: [
{
name: '日最高',
type: 'line',
data: this.chartData.dailyMax,
smooth: true,
lineStyle: {
color: '#4ECDC4',
width: 2
},
itemStyle: {
color: '#4ECDC4'
},
symbol: 'circle',
symbolSize: 4,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(78, 205, 196, 0.6)'
}, {
offset: 1,
color: 'rgba(78, 205, 196, 0.1)'
}]
}
},
stack: 'total'
},
{
name: '日平均',
type: 'line',
data: this.chartData.dailyAvg,
smooth: true,
lineStyle: {
color: '#E91E63',
width: 2
},
itemStyle: {
color: '#E91E63'
},
symbol: 'circle',
symbolSize: 4,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(233, 30, 99, 0.6)'
}, {
offset: 1,
color: 'rgba(233, 30, 99, 0.1)'
}]
}
},
stack: 'total'
},
{
name: '日最低',
type: 'line',
data: this.chartData.dailyMin,
smooth: true,
lineStyle: {
color: '#2196F3',
width: 2
},
itemStyle: {
color: '#2196F3'
},
symbol: 'circle',
symbolSize: 4,
areaStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [{
offset: 0,
color: 'rgba(33, 150, 243, 0.6)'
}, {
offset: 1,
color: 'rgba(33, 150, 243, 0.1)'
}]
}
},
stack: 'total'
}
]
}
this.chart.setOption(option)
},
handleResize() {
if (this.chart) {
this.chart.resize()
}
}
}
}
</script>
<style scoped>
.unit-power-consumption {
width: 100%;
height: 100%;
background: transparent;
}
.chart-container {
width: 100%;
height: 298px;
}
</style>