<template>
|
<div class="carbon-management">
|
<!-- 页面头部 -->
|
<div class="page-header">
|
<div class="header-content">
|
<h1 class="page-title">碳排放管理系统</h1>
|
<p class="page-subtitle">基于ISO 14064标准 · GHG Protocol核算标准</p>
|
</div>
|
<div class="header-stats">
|
<div class="stat-item">
|
<span class="stat-label">总碳排放量</span>
|
<span class="stat-value">{{totalEmissions}} tCO₂e</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-label">本月减排</span>
|
<span class="stat-value reduction">-{{monthlyReduction}}%</span>
|
</div>
|
<div class="stat-item">
|
<span class="stat-label">碳中和进度</span>
|
<span class="stat-value">{{neutralProgress}}%</span>
|
</div>
|
</div>
|
</div>
|
|
<!-- 主要内容区域 -->
|
<div class="dashboard-content">
|
<!-- 顶部数据面板 -->
|
<div class="top-panels">
|
<div class="data-panel top-left">
|
<div class="panel-title">当前碳排放</div>
|
<div class="panel-value">{{carbonData.scope1}} <span class="unit">tCO₂e</span></div>
|
<div class="panel-subtitle">范围1直接排放</div>
|
</div>
|
<div class="data-panel top-center">
|
<div class="panel-title">能耗监测</div>
|
<div class="panel-value">{{carbonData.scope2}} <span class="unit">tCO₂e</span></div>
|
<div class="panel-subtitle">范围2间接排放</div>
|
</div>
|
<div class="data-panel top-right">
|
<div class="panel-title">供应链排放</div>
|
<div class="panel-value">{{carbonData.scope3}} <span class="unit">tCO₂e</span></div>
|
<div class="panel-subtitle">范围3供应链排放</div>
|
</div>
|
<div class="data-panel top-far-right">
|
<div class="panel-title">减排进度</div>
|
<div class="panel-value">{{neutralProgress}} <span class="unit">%</span></div>
|
<div class="panel-subtitle">碳中和目标</div>
|
</div>
|
</div>
|
|
<!-- 中心主视图区域 -->
|
<div class="center-main-view">
|
<!-- 左侧控制面板 -->
|
<div class="left-control-panel">
|
<div class="control-section">
|
<div class="section-title">碳排放范围</div>
|
<el-radio-group v-model="selectedScope" @change="updateScopeData" class="vertical-radio">
|
<el-radio-button :value="'all'">全部范围</el-radio-button>
|
<el-radio-button :value="'scope1'">范围1</el-radio-button>
|
<el-radio-button :value="'scope2'">范围2</el-radio-button>
|
<el-radio-button :value="'scope3'">范围3</el-radio-button>
|
</el-radio-group>
|
</div>
|
<div class="control-section">
|
<div class="section-title">监测层级</div>
|
<el-radio-group v-model="heatmapLevel" @change="updateHeatmapLevel" class="vertical-radio">
|
<el-radio-button :value="'device'">设备级</el-radio-button>
|
<el-radio-button :value="'line'">产线级</el-radio-button>
|
<el-radio-button :value="'enterprise'">企业级</el-radio-button>
|
</el-radio-group>
|
</div>
|
</div>
|
|
<!-- 中心热力图 -->
|
<div class="main-heatmap">
|
<div class="heatmap-header">
|
<h2 class="main-title">碳足迹热力图分析</h2>
|
<div class="date-selector">
|
<el-date-picker
|
v-model="selectedDate"
|
type="date"
|
placeholder="选择日期"
|
size="small"
|
@change="updateHeatmapData"
|
/>
|
</div>
|
</div>
|
<div class="heatmap-view">
|
<Echarts ref="heatmapChart"
|
:series="heatmapSeries"
|
:xAxis="heatmapXAxis"
|
:yAxis="heatmapYAxis"
|
:tooltip="heatmapTooltip"
|
:visualMap="heatmapVisualMap"
|
:options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
|
style="height: 450px"></Echarts>
|
</div>
|
</div>
|
|
<!-- 右侧数据面板 -->
|
<div class="right-data-panel">
|
<div class="data-section">
|
<div class="section-title">实时监控</div>
|
<div class="mini-chart">
|
<Echarts ref="realtimeChart"
|
:series="realtimeSeries"
|
:xAxis="realtimeXAxis"
|
:chartStyle="chartStyle"
|
:yAxis="realtimeYAxis"
|
:tooltip="realtimeTooltip"
|
:options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
|
style="height: 300px"></Echarts>
|
</div>
|
</div>
|
<div class="data-section">
|
<div class="section-title">趋势分析</div>
|
<div class="trend-controls">
|
<el-radio-group v-model="trendPeriod" size="small" @change="updateTrendData">
|
<el-radio-button :value="'week'">周</el-radio-button>
|
<el-radio-button :value="'month'">月</el-radio-button>
|
<el-radio-button :value="'year'">年</el-radio-button>
|
</el-radio-group>
|
</div>
|
<div class="mini-chart">
|
<Echarts ref="trendChart"
|
:series="trendSeries"
|
:xAxis="trendXAxis"
|
:yAxis="trendYAxis"
|
:tooltip="trendTooltip"
|
:chartStyle="chartStyle"
|
:legend="trendLegend"
|
:options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}"
|
style="height: 200px"></Echarts>
|
</div>
|
</div>
|
</div>
|
</div>
|
|
<!-- 底部进度面板 -->
|
<div class="bottom-progress-panel">
|
<div class="progress-section">
|
<div class="progress-title">2024年减排目标</div>
|
<div class="progress-data">
|
<span class="current">{{reductionTarget.current}}</span>
|
<span class="separator">/</span>
|
<span class="target">{{reductionTarget.target}} tCO₂e</span>
|
</div>
|
<el-progress :percentage="reductionTarget.percentage" :stroke-width="6" color="#00E676"/>
|
</div>
|
<div class="progress-section">
|
<div class="progress-title">碳中和进度</div>
|
<div class="progress-data">
|
<span class="current">{{neutralTarget.current}}</span>
|
<span class="separator">/</span>
|
<span class="target">{{neutralTarget.target}} tCO₂e</span>
|
</div>
|
<el-progress :percentage="neutralTarget.percentage" :stroke-width="6" color="#00D4FF"/>
|
</div>
|
</div>
|
|
<!-- 底部数据表格 -->
|
<div class="bottom-data-table">
|
<div class="table-panel">
|
<div class="table-header">
|
<h3 class="table-title">碳排放详细数据</h3>
|
<div class="table-controls">
|
<el-input
|
v-model="searchKeyword"
|
placeholder="搜索设备或产线"
|
size="small"
|
style="width: 200px; margin-right: 10px;"
|
/>
|
<el-button type="primary" size="small" @click="exportData">导出数据</el-button>
|
</div>
|
</div>
|
<el-table :data="filteredTableData" style="width: 100%" height="180">
|
<el-table-column prop="name" label="设备/产线" width="150"/>
|
<el-table-column prop="type" label="类型" width="100"/>
|
<el-table-column prop="scope1" label="范围1排放" width="120"/>
|
<el-table-column prop="scope2" label="范围2排放" width="120"/>
|
<el-table-column prop="scope3" label="范围3排放" width="120"/>
|
<el-table-column prop="total" label="总排放量" width="120"/>
|
<el-table-column prop="efficiency" label="碳效率" width="100"/>
|
<el-table-column prop="status" label="状态" width="100">
|
<template #default="scope">
|
<el-tag :type="getStatusType(scope.row.status)">{{scope.row.status}}</el-tag>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted, onBeforeUnmount, computed } from 'vue'
|
import * as echarts from 'echarts'
|
import Echarts from '@/components/Echarts/echarts.vue'
|
|
// 响应式数据
|
const selectedScope = ref('all')
|
const heatmapLevel = ref('device')
|
const selectedDate = ref(new Date())
|
const trendPeriod = ref('week')
|
const searchKeyword = ref('')
|
|
// 碳排放数据
|
const carbonData = ref({
|
scope1: 125.6,
|
scope2: 89.3,
|
scope3: 234.7
|
})
|
const chartStyle = {
|
width: '96%',
|
height: '110%' // 设置图表容器的高度
|
}
|
// 计算属性
|
const totalEmissions = computed(() => {
|
return (carbonData.value.scope1 + carbonData.value.scope2 + carbonData.value.scope3).toFixed(1)
|
})
|
|
const monthlyReduction = ref(8.5)
|
|
// 计算碳中和进度百分比
|
const neutralProgress = computed(() => {
|
return Math.round(neutralTarget.value.percentage)
|
})
|
|
// 减排目标数据
|
const reductionTarget = ref({
|
current: 320.5,
|
target: 500,
|
percentage: 64.1
|
})
|
|
const neutralTarget = ref({
|
current: 1250,
|
target: 3800,
|
percentage: 32.9
|
})
|
|
// 实时监控图表配置
|
const realtimeSeries = ref([
|
{
|
name: '实时碳排放',
|
type: 'line',
|
smooth: true,
|
data: generateRealtimeData(),
|
itemStyle: {
|
color: '#FF6B6B'
|
},
|
areaStyle: {
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
{ offset: 0, color: 'rgba(255, 107, 107, 0.3)' },
|
{ offset: 1, color: 'rgba(255, 107, 107, 0.1)' }
|
])
|
}
|
}
|
])
|
|
const realtimeXAxis = [{
|
type: 'category',
|
data: Array.from({length: 24}, (_, i) => `${i.toString().padStart(2, '0')}:00`),
|
axisLabel: { color: '#B8C8E0' }
|
}]
|
|
const realtimeYAxis = [{
|
type: 'value',
|
name: 'tCO₂e/h',
|
axisLabel: { color: '#B8C8E0' },
|
nameTextStyle: { color: '#B8C8E0' }
|
}]
|
|
const realtimeTooltip = {
|
trigger: 'axis',
|
formatter: '{b}: {c} tCO₂e/h'
|
}
|
|
// 热力图配置
|
const heatmapSeries = ref([
|
{
|
name: '碳排放量',
|
type: 'heatmap',
|
data: generateHeatmapData(),
|
label: {
|
show: false
|
},
|
emphasis: {
|
itemStyle: {
|
shadowBlur: 10,
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
}
|
}
|
}
|
])
|
|
const heatmapXAxis = [{
|
type: 'category',
|
data: Array.from({length: 24}, (_, i) => `${i}:00`),
|
splitArea: { show: true },
|
axisLabel: { color: '#B8C8E0' }
|
}]
|
|
const heatmapYAxis = [{
|
type: 'category',
|
data: ['设备A', '设备B', '设备C', '设备D', '设备E', '设备F', '设备G'],
|
splitArea: { show: true },
|
axisLabel: { color: '#B8C8E0' }
|
}]
|
|
const heatmapTooltip = {
|
trigger: 'item',
|
formatter: function (params) {
|
const [hour, device] = params.data
|
const value = params.value[2]
|
return `设备: ${heatmapYAxis[0].data[device]}<br/>时间: ${hour}:00<br/>碳排放量: ${value} tCO₂e`
|
}
|
}
|
|
const heatmapVisualMap = ref({
|
min: 0,
|
max: 50,
|
calculable: true,
|
orient: 'horizontal',
|
left: 'center',
|
bottom: '5%',
|
inRange: {
|
color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
|
},
|
textStyle: { color: '#B8C8E0' }
|
})
|
|
// 趋势分析图表配置
|
const trendSeries = ref([
|
{
|
name: '范围1',
|
type: 'line',
|
data: [120, 132, 101, 134, 90, 230, 210],
|
itemStyle: { color: '#FF6B6B' }
|
},
|
{
|
name: '范围2',
|
type: 'line',
|
data: [220, 182, 191, 234, 290, 330, 310],
|
itemStyle: { color: '#4ECDC4' }
|
},
|
{
|
name: '范围3',
|
type: 'line',
|
data: [150, 232, 201, 154, 190, 330, 410],
|
itemStyle: { color: '#45B7D1' }
|
}
|
])
|
|
const trendXAxis = [{
|
type: 'category',
|
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
axisLabel: { color: '#B8C8E0' }
|
}]
|
|
const trendYAxis = [{
|
type: 'value',
|
name: 'tCO₂e',
|
axisLabel: { color: '#B8C8E0' },
|
nameTextStyle: { color: '#B8C8E0' }
|
}]
|
|
const trendTooltip = {
|
trigger: 'axis'
|
}
|
|
const trendLegend = {
|
data: ['范围1', '范围2', '范围3'],
|
textStyle: { color: '#B8C8E0' }
|
}
|
|
// 表格数据
|
const carbonTableData = ref([
|
{ name: '生产线A', type: '产线', scope1: 45.2, scope2: 32.1, scope3: 18.7, total: 96.0, efficiency: '良好', status: '正常' },
|
{ name: '设备B-01', type: '设备', scope1: 12.5, scope2: 8.3, scope3: 5.2, total: 26.0, efficiency: '优秀', status: '正常' },
|
{ name: '生产线C', type: '产线', scope1: 38.7, scope2: 28.9, scope3: 15.4, total: 83.0, efficiency: '良好', status: '告警' },
|
{ name: '设备D-02', type: '设备', scope1: 15.8, scope2: 11.2, scope3: 7.1, total: 34.1, efficiency: '一般', status: '正常' },
|
{ name: '生产线E', type: '产线', scope1: 52.3, scope2: 39.6, scope3: 22.8, total: 114.7, efficiency: '待优化', status: '告警' }
|
])
|
|
// 生成实时数据
|
function generateRealtimeData() {
|
return Array.from({length: 24}, () => (Math.random() * 20 + 10).toFixed(1))
|
}
|
|
// 生成热力图数据
|
function generateHeatmapData() {
|
const data = []
|
let yAxisLength = 7 // 默认设备级
|
let baseMultiplier = 1 // 基础倍数
|
|
// 根据层级确定Y轴长度和数据范围
|
if (heatmapLevel.value === 'line') {
|
yAxisLength = 5
|
baseMultiplier = 2 // 产线级数据更大
|
} else if (heatmapLevel.value === 'enterprise') {
|
yAxisLength = 3
|
baseMultiplier = 4 // 企业级数据最大
|
}
|
|
for (let i = 0; i < yAxisLength; i++) {
|
for (let j = 0; j < 24; j++) {
|
let value
|
// 简化的时间段逻辑
|
if (j >= 8 && j <= 18) {
|
// 工作时间排放量较高
|
value = Math.random() * 30 + 20
|
} else if (j >= 19 && j <= 22) {
|
// 晚间排放量中等
|
value = Math.random() * 20 + 10
|
} else {
|
// 深夜和凌晨排放量较低
|
value = Math.random() * 10 + 2
|
}
|
|
// 添加设备差异和层级倍数
|
value *= (0.8 + i * 0.1) * baseMultiplier
|
|
data.push([j, i, Math.round(value * 10) / 10])
|
}
|
}
|
return data
|
}
|
|
// 更新范围数据
|
function updateScopeData() {
|
// 根据选择的范围更新所有相关图表数据
|
const scopeMultiplier = {
|
'all': 1,
|
'scope1': 0.3,
|
'scope2': 0.4,
|
'scope3': 0.3
|
}
|
|
const multiplier = scopeMultiplier[selectedScope.value] || 1
|
|
// 更新碳排放数据显示
|
if (selectedScope.value === 'all') {
|
carbonData.value = {
|
scope1: 125.6,
|
scope2: 89.3,
|
scope3: 234.7
|
}
|
} else {
|
const baseTotal = 125.6 + 89.3 + 234.7
|
carbonData.value = {
|
scope1: selectedScope.value === 'scope1' ? 125.6 : 0,
|
scope2: selectedScope.value === 'scope2' ? 89.3 : 0,
|
scope3: selectedScope.value === 'scope3' ? 234.7 : 0
|
}
|
}
|
|
// 更新热力图数据
|
heatmapSeries.value[0].data = generateHeatmapData().map(item => [
|
item[0], item[1], Math.round(item[2] * multiplier * 10) / 10
|
])
|
|
// 更新实时监控数据
|
realtimeSeries.value[0].data = generateRealtimeData().map(val =>
|
Math.round(parseFloat(val) * multiplier * 10) / 10
|
)
|
}
|
|
// 更新热力图层级
|
function updateHeatmapLevel() {
|
// 根据层级更新Y轴数据和visualMap范围
|
if (heatmapLevel.value === 'device') {
|
heatmapYAxis[0].data = ['锅炉A', '压缩机B', '冷却塔C', '风机D', '泵E', '变压器F', '电机G']
|
heatmapVisualMap.value.max = 50
|
} else if (heatmapLevel.value === 'line') {
|
heatmapYAxis[0].data = ['生产线1', '生产线2', '生产线3', '生产线4', '生产线5']
|
heatmapVisualMap.value.max = 100
|
} else {
|
heatmapYAxis[0].data = ['厂区A', '厂区B', '厂区C']
|
heatmapVisualMap.value.max = 200
|
}
|
|
// 更新热力图数据
|
heatmapSeries.value[0].data = generateHeatmapData()
|
|
// 更新表格数据以匹配当前层级
|
updateTableDataForLevel()
|
}
|
|
// 根据层级更新表格数据
|
function updateTableDataForLevel() {
|
const levelConfigs = {
|
device: [
|
{ name: '锅炉A', type: '设备', scope1: 45.2, scope2: 32.1, scope3: 18.7, total: 96.0, efficiency: '良好', status: '正常' },
|
{ name: '压缩机B', type: '设备', scope1: 38.5, scope2: 28.3, scope3: 15.2, total: 82.0, efficiency: '优秀', status: '正常' },
|
{ name: '冷却塔C', type: '设备', scope1: 22.8, scope2: 18.9, scope3: 12.3, total: 54.0, efficiency: '良好', status: '告警' },
|
{ name: '风机D', type: '设备', scope1: 15.6, scope2: 12.4, scope3: 8.1, total: 36.1, efficiency: '一般', status: '正常' },
|
{ name: '泵E', type: '设备', scope1: 12.3, scope2: 9.8, scope3: 6.4, total: 28.5, efficiency: '优秀', status: '正常' }
|
],
|
line: [
|
{ name: '生产线1', type: '产线', scope1: 125.6, scope2: 89.3, scope3: 56.8, total: 271.7, efficiency: '良好', status: '正常' },
|
{ name: '生产线2', type: '产线', scope1: 98.4, scope2: 72.1, scope3: 45.2, total: 215.7, efficiency: '优秀', status: '正常' },
|
{ name: '生产线3', type: '产线', scope1: 87.2, scope2: 65.8, scope3: 41.6, total: 194.6, efficiency: '良好', status: '告警' },
|
{ name: '生产线4', type: '产线', scope1: 76.9, scope2: 58.3, scope3: 37.1, total: 172.3, efficiency: '一般', status: '正常' },
|
{ name: '生产线5', type: '产线', scope1: 65.7, scope2: 49.2, scope3: 31.8, total: 146.7, efficiency: '待优化', status: '告警' }
|
],
|
enterprise: [
|
{ name: '厂区A', type: '厂区', scope1: 456.8, scope2: 334.7, scope3: 212.5, total: 1004.0, efficiency: '良好', status: '正常' },
|
{ name: '厂区B', type: '厂区', scope1: 387.2, scope2: 289.6, scope3: 184.3, total: 861.1, efficiency: '优秀', status: '正常' },
|
{ name: '厂区C', type: '厂区', scope1: 298.5, scope2: 223.8, scope3: 142.7, total: 665.0, efficiency: '良好', status: '告警' }
|
]
|
}
|
|
carbonTableData.value = levelConfigs[heatmapLevel.value] || levelConfigs.device
|
}
|
|
// 更新热力图数据(日期变化时)
|
function updateHeatmapData() {
|
heatmapSeries.value[0].data = generateHeatmapData()
|
|
// 同时更新其他相关数据
|
updateScopeData()
|
}
|
|
// 更新趋势数据
|
function updateTrendData() {
|
const trendDataConfigs = {
|
week: {
|
xAxisData: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
scope1Data: [120, 132, 101, 134, 90, 80, 75],
|
scope2Data: [220, 182, 191, 234, 190, 150, 140],
|
scope3Data: [150, 232, 201, 154, 190, 120, 110]
|
},
|
month: {
|
xAxisData: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
scope1Data: [1200, 1150, 1300, 1250, 1180, 1320, 1280, 1350, 1220, 1290, 1160, 1100],
|
scope2Data: [2200, 2100, 2350, 2280, 2150, 2400, 2320, 2450, 2180, 2380, 2120, 2050],
|
scope3Data: [1800, 1750, 1950, 1880, 1820, 2000, 1920, 2100, 1850, 1980, 1780, 1720]
|
},
|
year: {
|
xAxisData: ['2019', '2020', '2021', '2022', '2023', '2024'],
|
scope1Data: [14500, 14200, 13800, 13500, 13100, 12800],
|
scope2Data: [26800, 26200, 25600, 25000, 24400, 23800],
|
scope3Data: [22400, 21800, 21200, 20600, 20000, 19400]
|
}
|
}
|
|
const config = trendDataConfigs[trendPeriod.value] || trendDataConfigs.week
|
|
// 更新X轴数据
|
trendXAxis[0].data = config.xAxisData
|
|
// 更新系列数据
|
trendSeries.value = [
|
{
|
name: '范围1',
|
type: 'line',
|
data: config.scope1Data,
|
itemStyle: { color: '#FF6B6B' },
|
smooth: true
|
},
|
{
|
name: '范围2',
|
type: 'line',
|
data: config.scope2Data,
|
itemStyle: { color: '#4ECDC4' },
|
smooth: true
|
},
|
{
|
name: '范围3',
|
type: 'line',
|
data: config.scope3Data,
|
itemStyle: { color: '#45B7D1' },
|
smooth: true
|
}
|
]
|
}
|
|
// 获取状态类型
|
function getStatusType(status) {
|
switch (status) {
|
case '正常': return 'success'
|
case '告警': return 'warning'
|
case '异常': return 'danger'
|
default: return 'info'
|
}
|
}
|
|
// 导出数据
|
function exportData() {
|
// 准备导出数据
|
const exportDataSet = {
|
基本信息: {
|
导出时间: new Date().toLocaleString('zh-CN'),
|
数据层级: heatmapLevel.value === 'device' ? '设备级' : heatmapLevel.value === 'line' ? '产线级' : '企业级',
|
选择范围: selectedScope.value === 'all' ? '全部范围' : `范围${selectedScope.value.slice(-1)}`,
|
选择日期: selectedDate.value ? selectedDate.value.toLocaleDateString('zh-CN') : '今日'
|
},
|
碳排放统计: {
|
范围1直接排放: carbonData.value.scope1 + ' tCO₂e',
|
范围2间接排放: carbonData.value.scope2 + ' tCO₂e',
|
范围3供应链排放: carbonData.value.scope3 + ' tCO₂e',
|
总排放量: totalEmissions.value + ' tCO₂e'
|
},
|
详细数据: carbonTableData.value,
|
热力图数据: heatmapSeries.value[0].data.map(item => ({
|
时间: `${item[0]}:00`,
|
设备序号: item[1],
|
设备名称: heatmapYAxis.data[item[1]],
|
碳排放量: item[2] + ' tCO₂e'
|
}))
|
}
|
|
// 创建CSV内容
|
let csvContent = '\uFEFF' // BOM for UTF-8
|
|
// 基本信息
|
csvContent += '基本信息\n'
|
Object.entries(exportDataSet.基本信息).forEach(([key, value]) => {
|
csvContent += `${key},${value}\n`
|
})
|
csvContent += '\n'
|
|
// 碳排放统计
|
csvContent += '碳排放统计\n'
|
Object.entries(exportDataSet.碳排放统计).forEach(([key, value]) => {
|
csvContent += `${key},${value}\n`
|
})
|
csvContent += '\n'
|
|
// 详细数据表格
|
csvContent += '详细数据\n'
|
csvContent += '名称,类型,范围1排放,范围2排放,范围3排放,总排放量,碳效率,状态\n'
|
exportDataSet.详细数据.forEach(row => {
|
csvContent += `${row.name},${row.type},${row.scope1},${row.scope2},${row.scope3},${row.total},${row.efficiency},${row.status}\n`
|
})
|
csvContent += '\n'
|
|
// 热力图数据(前50条)
|
csvContent += '热力图数据(前50条)\n'
|
csvContent += '时间,设备名称,碳排放量\n'
|
exportDataSet.热力图数据.slice(0, 50).forEach(row => {
|
csvContent += `${row.时间},${row.设备名称},${row.碳排放量}\n`
|
})
|
|
// 创建下载链接
|
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
|
const link = document.createElement('a')
|
const url = URL.createObjectURL(blob)
|
link.setAttribute('href', url)
|
link.setAttribute('download', `碳排放数据_${new Date().toISOString().slice(0, 10)}.csv`)
|
link.style.visibility = 'hidden'
|
document.body.appendChild(link)
|
link.click()
|
document.body.removeChild(link)
|
|
// 显示成功消息
|
console.log('碳排放数据导出成功')
|
}
|
|
// 搜索过滤功能
|
const filteredTableData = computed(() => {
|
if (!searchKeyword.value) {
|
return carbonTableData.value
|
}
|
return carbonTableData.value.filter(item =>
|
item.name.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
|
item.type.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
)
|
})
|
|
// 热力图点击事件处理
|
function handleHeatmapClick(params) {
|
if (params.componentType === 'series') {
|
const [hour, deviceIndex, value] = params.data
|
const deviceName = heatmapYAxis.data[deviceIndex]
|
console.log(`点击了设备: ${deviceName}, 时间: ${hour}:00, 排放量: ${value} tCO₂e`)
|
|
// 可以在这里添加详细信息弹窗或跳转到详细页面
|
}
|
}
|
|
onMounted(() => {
|
// 页面加载完成后的初始化操作
|
console.log('碳管理页面已加载')
|
|
// 初始化热力图数据
|
updateHeatmapLevel()
|
|
// 初始化趋势数据
|
updateTrendData()
|
|
// 初始化范围数据
|
updateScopeData()
|
|
// 设置定时器,每30秒更新一次实时数据
|
const timer = setInterval(() => {
|
realtimeSeries.value[0].data = generateRealtimeData()
|
}, 30000)
|
|
// 清理定时器
|
onBeforeUnmount(() => {
|
clearInterval(timer)
|
})
|
})
|
|
// 添加热力图点击事件绑定
|
function bindHeatmapEvents() {
|
// 这个函数可以用来绑定热力图的点击事件
|
// 在实际使用中,可以通过ECharts的事件系统来实现
|
}
|
</script>
|
|
<style scoped>
|
.carbon-management {
|
min-height: 100vh;
|
background:
|
radial-gradient(ellipse at top, rgba(29, 78, 216, 0.15), transparent 50%),
|
radial-gradient(ellipse at bottom, rgba(139, 92, 246, 0.15), transparent 50%),
|
linear-gradient(135deg, #0a0f1c 0%, #1e293b 25%, #0f172a 50%, #1e293b 75%, #0a0f1c 100%);
|
padding: 20px;
|
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
|
overflow: hidden;
|
position: relative;
|
}
|
|
.carbon-management::before {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background:
|
radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.1) 0%, transparent 50%),
|
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.1) 0%, transparent 50%),
|
radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.05) 0%, transparent 50%);
|
pointer-events: none;
|
|
}
|
|
|
|
.page-header {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.95) 0%, rgba(30, 41, 59, 0.9) 100%),
|
radial-gradient(circle at top right, rgba(59, 130, 246, 0.1), transparent 50%);
|
border: 1px solid rgba(148, 163, 184, 0.2);
|
border-radius: 20px;
|
padding: 40px;
|
margin-bottom: 30px;
|
box-shadow:
|
0 25px 50px -12px rgba(0, 0, 0, 0.4),
|
0 0 0 1px rgba(255, 255, 255, 0.05),
|
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
position: relative;
|
overflow: hidden;
|
backdrop-filter: blur(20px);
|
|
}
|
|
.page-header:hover {
|
transform: translateY(-2px);
|
box-shadow:
|
0 32px 64px -12px rgba(0, 0, 0, 0.5),
|
0 0 0 1px rgba(255, 255, 255, 0.1),
|
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
}
|
|
.page-header::before {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background:
|
linear-gradient(45deg, rgba(59, 130, 246, 0.08) 0%, rgba(147, 51, 234, 0.08) 50%, rgba(236, 72, 153, 0.08) 100%);
|
pointer-events: none;
|
|
}
|
|
|
|
.header-content {
|
flex: 1;
|
position: relative;
|
z-index: 1;
|
}
|
|
.page-title {
|
font-size: 28px;
|
font-weight: bold;
|
color: #ffffff;
|
margin: 0 0 8px 0;
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
}
|
|
.page-subtitle {
|
font-size: 14px;
|
color: #B8C8E0;
|
margin: 0;
|
}
|
|
.header-stats {
|
display: flex;
|
gap: 40px;
|
position: relative;
|
z-index: 1;
|
}
|
|
.stat-item {
|
text-align: center;
|
padding: 20px;
|
background:
|
linear-gradient(135deg, rgba(59, 130, 246, 0.15) 0%, rgba(147, 51, 234, 0.15) 100%),
|
radial-gradient(circle at center, rgba(255, 255, 255, 0.05), transparent 70%);
|
border-radius: 12px;
|
border: 1px solid rgba(148, 163, 184, 0.2);
|
position: relative;
|
overflow: hidden;
|
|
backdrop-filter: blur(10px);
|
}
|
|
.stat-item:hover {
|
transform: translateY(-2px) scale(1.05);
|
box-shadow:
|
0 20px 25px -5px rgba(59, 130, 246, 0.3),
|
0 10px 10px -5px rgba(59, 130, 246, 0.2);
|
}
|
|
.stat-item::before {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: -100%;
|
width: 100%;
|
height: 100%;
|
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);
|
|
}
|
|
.stat-item:hover::before {
|
left: 100%;
|
}
|
|
.stat-label {
|
display: block;
|
font-size: 12px;
|
color: #94A3B8;
|
margin-bottom: 8px;
|
font-weight: 500;
|
letter-spacing: 0.5px;
|
text-transform: uppercase;
|
}
|
|
.stat-value {
|
display: block;
|
font-size: 28px;
|
font-weight: 700;
|
color: #00D4FF;
|
text-shadow:
|
0 0 20px rgba(0, 212, 255, 0.6),
|
0 0 40px rgba(0, 212, 255, 0.3);
|
position: relative;
|
z-index: 1;
|
}
|
|
.stat-value.reduction {
|
color: #00E676;
|
text-shadow:
|
0 0 20px rgba(0, 230, 118, 0.6),
|
0 0 40px rgba(0, 230, 118, 0.3);
|
}
|
|
.dashboard-content {
|
display: flex;
|
flex-direction: column;
|
gap: 20px;
|
min-height: calc(100vh - 200px);
|
}
|
|
.top-panels {
|
display: grid;
|
grid-template-columns: 1fr 1fr 1fr 1fr;
|
gap: 20px;
|
height: 120px;
|
}
|
|
.data-panel {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%),
|
radial-gradient(circle at bottom left, rgba(59, 130, 246, 0.08), transparent 50%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 20px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 10px 10px -5px rgba(0, 0, 0, 0.2),
|
0 0 0 1px rgba(255, 255, 255, 0.05);
|
backdrop-filter: blur(16px);
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
text-align: center;
|
}
|
|
.panel-title {
|
font-size: 12px;
|
color: #94A3B8;
|
margin-bottom: 8px;
|
font-weight: 500;
|
letter-spacing: 0.5px;
|
text-transform: uppercase;
|
}
|
|
.panel-value {
|
font-size: 24px;
|
font-weight: 700;
|
color: #00D4FF;
|
text-shadow:
|
0 0 20px rgba(0, 212, 255, 0.6),
|
0 0 40px rgba(0, 212, 255, 0.3);
|
margin-bottom: 4px;
|
}
|
|
.panel-subtitle {
|
font-size: 11px;
|
color: #B8C8E0;
|
font-weight: 400;
|
}
|
|
.unit {
|
font-size: 16px;
|
color: #94A3B8;
|
}
|
|
.center-main-view {
|
display: grid;
|
grid-template-columns: 200px 1fr 300px;
|
gap: 20px;
|
flex: 1;
|
}
|
|
.left-control-panel {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 20px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 0 0 1px rgba(255, 255, 255, 0.05);
|
backdrop-filter: blur(16px);
|
display: flex;
|
flex-direction: column;
|
gap: 20px;
|
}
|
|
.control-section {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.section-title {
|
font-size: 14px;
|
font-weight: 600;
|
color: #ffffff;
|
margin-bottom: 8px;
|
}
|
|
.vertical-radio {
|
display: flex;
|
flex-direction: column;
|
gap: 8px;
|
}
|
|
.main-heatmap {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 20px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 0 0 1px rgba(255, 255, 255, 0.05);
|
backdrop-filter: blur(16px);
|
display: flex;
|
flex-direction: column;
|
}
|
|
.heatmap-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
padding-bottom: 15px;
|
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
}
|
|
.main-title {
|
font-size: 18px;
|
font-weight: bold;
|
color: #ffffff;
|
margin: 0;
|
}
|
|
.date-selector {
|
display: flex;
|
align-items: center;
|
}
|
|
.heatmap-view {
|
flex: 1;
|
}
|
|
.right-data-panel {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 20px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 0 0 1px rgba(255, 255, 255, 0.05);
|
backdrop-filter: blur(16px);
|
display: flex;
|
flex-direction: column;
|
gap: 20px;
|
}
|
|
.data-section {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.mini-chart {
|
width: 100%;
|
}
|
|
.trend-controls {
|
margin-bottom: 10px;
|
}
|
|
.bottom-progress-panel {
|
display: grid;
|
grid-template-columns: 1fr 1fr;
|
gap: 40px;
|
height: 100px;
|
}
|
|
.progress-section {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 20px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 0 0 1px rgba(255, 255, 255, 0.05);
|
backdrop-filter: blur(16px);
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
}
|
|
.progress-title {
|
font-size: 14px;
|
font-weight: 600;
|
color: #ffffff;
|
margin-bottom: 8px;
|
}
|
|
.progress-data {
|
display: flex;
|
align-items: baseline;
|
gap: 4px;
|
margin-bottom: 12px;
|
}
|
|
.progress-data .current {
|
font-size: 20px;
|
font-weight: 700;
|
color: #00D4FF;
|
}
|
|
.progress-data .separator {
|
font-size: 16px;
|
color: #94A3B8;
|
}
|
|
.progress-data .target {
|
font-size: 14px;
|
color: #B8C8E0;
|
}
|
|
.bottom-data-table {
|
margin-top: 20px;
|
}
|
|
.table-panel {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%),
|
radial-gradient(circle at bottom left, rgba(59, 130, 246, 0.08), transparent 50%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 20px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 10px 10px -5px rgba(0, 0, 0, 0.2),
|
0 0 0 1px rgba(255, 255, 255, 0.05),
|
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
backdrop-filter: blur(16px);
|
}
|
|
.table-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 15px;
|
padding-bottom: 10px;
|
border-bottom: 1px solid rgba(148, 163, 184, 0.2);
|
}
|
|
.table-title {
|
font-size: 16px;
|
font-weight: 600;
|
color: #ffffff;
|
margin: 0;
|
}
|
|
.table-controls {
|
display: flex;
|
align-items: center;
|
gap: 10px;
|
}
|
|
.panel-card {
|
background:
|
linear-gradient(135deg, rgba(15, 27, 46, 0.9) 0%, rgba(30, 41, 59, 0.85) 100%),
|
radial-gradient(circle at bottom left, rgba(59, 130, 246, 0.08), transparent 50%);
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
border-radius: 16px;
|
padding: 24px;
|
box-shadow:
|
0 20px 25px -5px rgba(0, 0, 0, 0.3),
|
0 10px 10px -5px rgba(0, 0, 0, 0.2),
|
0 0 0 1px rgba(255, 255, 255, 0.05),
|
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
position: relative;
|
overflow: hidden;
|
backdrop-filter: blur(16px);
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
}
|
|
|
|
.heatmap-card {
|
height: 500px;
|
}
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
padding-bottom: 15px;
|
border-bottom: 1px solid rgba(81, 129, 219, 0.3);
|
position: relative;
|
z-index: 1;
|
}
|
|
.card-title {
|
font-size: 18px;
|
font-weight: bold;
|
color: #ffffff;
|
margin: 0;
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
}
|
|
.heatmap-controls {
|
display: flex;
|
align-items: center;
|
}
|
|
.scope-stats {
|
display: flex;
|
flex-direction: column;
|
gap: 15px;
|
position: relative;
|
z-index: 1;
|
}
|
|
.scope-item {
|
display: flex;
|
align-items: center;
|
padding: 20px;
|
border-radius: 12px;
|
background:
|
linear-gradient(135deg, rgba(59, 130, 246, 0.12) 0%, rgba(147, 51, 234, 0.12) 100%),
|
radial-gradient(circle at top, rgba(255, 255, 255, 0.05), transparent 60%);
|
border-left: 4px solid #00D4FF;
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
position: relative;
|
overflow: hidden;
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
backdrop-filter: blur(8px);
|
}
|
|
.scope-item:hover {
|
transform: translateY(-3px);
|
box-shadow:
|
0 15px 30px -5px rgba(59, 130, 246, 0.25),
|
0 0 0 1px rgba(255, 255, 255, 0.1);
|
}
|
|
.scope-item::after {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
height: 2px;
|
background: linear-gradient(90deg, #3B82F6, #8B5CF6, #EC4899);
|
opacity: 0;
|
transition: opacity 0.3s ease;
|
}
|
|
.scope-item:hover::after {
|
opacity: 1;
|
}
|
|
/* 碳排放统计样式 */
|
.carbon-stats {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 20px;
|
gap: 15px;
|
}
|
|
.carbon-stat-item {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
gap: 12px;
|
padding: 20px;
|
background:
|
linear-gradient(135deg, rgba(59, 130, 246, 0.12) 0%, rgba(147, 51, 234, 0.12) 100%),
|
radial-gradient(circle at top, rgba(255, 255, 255, 0.05), transparent 60%);
|
border-radius: 12px;
|
border: 1px solid rgba(148, 163, 184, 0.15);
|
flex: 1;
|
position: relative;
|
overflow: hidden;
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
backdrop-filter: blur(8px);
|
}
|
|
.carbon-stat-item:hover {
|
transform: translateY(-3px);
|
box-shadow:
|
0 15px 30px -5px rgba(59, 130, 246, 0.25),
|
0 0 0 1px rgba(255, 255, 255, 0.1);
|
}
|
|
.carbon-stat-item::after {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
height: 2px;
|
background: linear-gradient(90deg, #3B82F6, #8B5CF6, #EC4899);
|
opacity: 0;
|
transition: opacity 0.3s ease;
|
}
|
|
.carbon-stat-item:hover::after {
|
opacity: 1;
|
}
|
|
.carbon-label {
|
color: #94A3B8;
|
font-size: 11px;
|
text-align: center;
|
font-weight: 500;
|
letter-spacing: 0.5px;
|
text-transform: uppercase;
|
}
|
|
.carbon-value {
|
color: #00D4FF;
|
font-size: 18px;
|
font-weight: 700;
|
text-shadow:
|
0 0 15px rgba(0, 212, 255, 0.6),
|
0 0 30px rgba(0, 212, 255, 0.3);
|
position: relative;
|
}
|
|
.scope-item.scope1 {
|
border-left-color: #FF6B6B;
|
}
|
|
.scope-item.scope2 {
|
border-left-color: #FFD93D;
|
}
|
|
.scope-item.scope3 {
|
border-left-color: #6BCF7F;
|
}
|
|
.scope-icon {
|
font-size: 24px;
|
margin-right: 15px;
|
}
|
|
.scope-info {
|
flex: 1;
|
}
|
|
.scope-name {
|
display: block;
|
font-weight: bold;
|
color: #ffffff;
|
margin-bottom: 5px;
|
}
|
|
.scope-value {
|
display: block;
|
font-size: 20px;
|
font-weight: bold;
|
color: #00D4FF;
|
margin-bottom: 3px;
|
text-shadow: 0 0 8px rgba(0, 212, 255, 0.5);
|
}
|
|
.scope-desc {
|
display: block;
|
font-size: 12px;
|
color: #B8C8E0;
|
}
|
|
.target-progress {
|
display: flex;
|
flex-direction: column;
|
gap: 20px;
|
position: relative;
|
z-index: 1;
|
}
|
|
.progress-item {
|
padding: 15px;
|
background: rgba(81, 129, 219, 0.1);
|
border-radius: 8px;
|
border: 1px solid rgba(81, 129, 219, 0.2);
|
}
|
|
.progress-info {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10px;
|
}
|
|
.progress-label {
|
font-weight: bold;
|
color: #ffffff;
|
}
|
|
.progress-value {
|
color: #B8C8E0;
|
font-size: 14px;
|
}
|
|
.bottom-panel {
|
margin-top: 20px;
|
}
|
|
.table-controls {
|
display: flex;
|
align-items: center;
|
}
|
|
/* Element Plus 组件深色主题样式 */
|
:deep(.el-table) {
|
background: transparent !important;
|
color: #ffffff !important;
|
}
|
|
:deep(.el-table th) {
|
background: rgba(81, 129, 219, 0.2) !important;
|
color: #ffffff !important;
|
border-bottom: 1px solid rgba(81, 129, 219, 0.3) !important;
|
}
|
|
:deep(.el-table td) {
|
background: transparent !important;
|
color: #B8C8E0 !important;
|
border-bottom: 1px solid rgba(81, 129, 219, 0.1) !important;
|
}
|
|
:deep(.el-table tr:hover > td) {
|
background: rgba(81, 129, 219, 0.1) !important;
|
}
|
|
:deep(.el-input__wrapper) {
|
background: rgba(15, 27, 46, 0.8) !important;
|
border: 1px solid rgba(81, 129, 219, 0.3) !important;
|
color: #ffffff !important;
|
}
|
|
:deep(.el-input__inner) {
|
color: #ffffff !important;
|
}
|
|
:deep(.el-button--primary) {
|
background: linear-gradient(135deg, #5181DB, #D369E0) !important;
|
border: none !important;
|
box-shadow: 0 0 10px rgba(81, 129, 219, 0.5) !important;
|
}
|
|
/* 垂直单选按钮组样式 */
|
:deep(.vertical-radio) {
|
display: flex !important;
|
flex-direction: column !important;
|
gap: 6px !important;
|
}
|
|
:deep(.vertical-radio .el-radio-button) {
|
margin: 0 !important;
|
width: 100% !important;
|
}
|
|
:deep(.vertical-radio .el-radio-button__inner) {
|
background: rgba(59, 130, 246, 0.1) !important;
|
border: 1px solid rgba(148, 163, 184, 0.2) !important;
|
color: #B8C8E0 !important;
|
border-radius: 8px !important;
|
padding: 10px 16px !important;
|
width: 100% !important;
|
text-align: center !important;
|
font-size: 12px !important;
|
font-weight: 500 !important;
|
}
|
|
:deep(.vertical-radio .el-radio-button__inner:hover) {
|
background: rgba(59, 130, 246, 0.2) !important;
|
border-color: rgba(59, 130, 246, 0.4) !important;
|
color: #ffffff !important;
|
}
|
|
:deep(.vertical-radio .el-radio-button.is-active .el-radio-button__inner) {
|
background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important;
|
border-color: #3B82F6 !important;
|
color: #ffffff !important;
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3) !important;
|
}
|
|
:deep(.vertical-radio .el-radio-button:first-child .el-radio-button__inner) {
|
border-left: 1px solid rgba(148, 163, 184, 0.2) !important;
|
}
|
|
:deep(.el-radio-group .el-radio-button__inner) {
|
background: rgba(59, 130, 246, 0.1) !important;
|
border: 1px solid rgba(148, 163, 184, 0.2) !important;
|
color: #B8C8E0 !important;
|
border-radius: 6px !important;
|
padding: 6px 12px !important;
|
margin: 0 2px !important;
|
font-size: 12px !important;
|
}
|
|
:deep(.el-radio-group .el-radio-button__inner:hover) {
|
background: rgba(59, 130, 246, 0.2) !important;
|
border-color: rgba(59, 130, 246, 0.4) !important;
|
color: #ffffff !important;
|
}
|
|
:deep(.el-radio-group .el-radio-button.is-active .el-radio-button__inner) {
|
background: linear-gradient(135deg, #3B82F6, #8B5CF6) !important;
|
border-color: #3B82F6 !important;
|
color: #ffffff !important;
|
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3) !important;
|
}
|
|
:deep(.el-date-editor .el-input__wrapper) {
|
background: rgba(15, 27, 46, 0.8) !important;
|
border: 1px solid rgba(81, 129, 219, 0.3) !important;
|
}
|
|
:deep(.el-progress-bar__outer) {
|
background: rgba(81, 129, 219, 0.2) !important;
|
}
|
|
:deep(.el-tag) {
|
background: rgba(81, 129, 219, 0.2) !important;
|
border: 1px solid rgba(81, 129, 219, 0.3) !important;
|
color: #ffffff !important;
|
}
|
|
:deep(.el-tag.el-tag--success) {
|
background: rgba(0, 230, 118, 0.2) !important;
|
border-color: rgba(0, 230, 118, 0.3) !important;
|
color: #00E676 !important;
|
}
|
|
:deep(.el-tag.el-tag--warning) {
|
background: rgba(255, 193, 7, 0.2) !important;
|
border-color: rgba(255, 193, 7, 0.3) !important;
|
color: #FFC107 !important;
|
}
|
|
:deep(.el-tag.el-tag--danger) {
|
background: rgba(244, 67, 54, 0.2) !important;
|
border-color: rgba(244, 67, 54, 0.3) !important;
|
color: #F44336 !important;
|
}
|
|
/* 响应式设计 */
|
@media (max-width: 1200px) {
|
.main-content {
|
flex-direction: column;
|
}
|
|
.header-stats {
|
gap: 20px;
|
}
|
}
|
|
@media (max-width: 768px) {
|
.page-header {
|
flex-direction: column;
|
text-align: center;
|
gap: 20px;
|
}
|
|
.header-stats {
|
justify-content: center;
|
}
|
|
.carbon-management {
|
padding: 10px;
|
}
|
}
|
</style>
|