From 3d17f7788b56ff5e601b069c6841ab723c20367d Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期四, 11 九月 2025 14:17:31 +0800 Subject: [PATCH] 碳排放热力图 --- src/components/Echarts/echarts.vue | 7 src/views/energyManagement/carbonManagement/index.vue | 1553 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1,559 insertions(+), 1 deletions(-) diff --git a/src/components/Echarts/echarts.vue b/src/components/Echarts/echarts.vue index 29abba8..a386bb7 100644 --- a/src/components/Echarts/echarts.vue +++ b/src/components/Echarts/echarts.vue @@ -76,6 +76,10 @@ type: Array, default: () => [] }, + visualMap: { + type: Object, + default: () => ({}) + }, option: { type: Object, default: () => ({}) @@ -121,6 +125,7 @@ grid: props.grid, legend: props.legend, tooltip: props.tooltip, + visualMap: Object.keys(props.visualMap).length ? props.visualMap : undefined, } chartInstance.clear() @@ -149,7 +154,7 @@ // Watch all reactive props that affect the chart watch( - () => [props.xAxis, props.series, props.legend, props.tooltip], + () => [props.xAxis, props.yAxis, props.series, props.legend, props.tooltip, props.visualMap], () => { if (chartInstance) { renderChart() diff --git a/src/views/energyManagement/carbonManagement/index.vue b/src/views/energyManagement/carbonManagement/index.vue new file mode 100644 index 0000000..5a4be25 --- /dev/null +++ b/src/views/energyManagement/carbonManagement/index.vue @@ -0,0 +1,1553 @@ +<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鈧俥</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鈧俥</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鈧俥</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鈧俥</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鈧俥</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鈧俥</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鈧俥/h', + axisLabel: { color: '#B8C8E0' }, + nameTextStyle: { color: '#B8C8E0' } +}] + +const realtimeTooltip = { + trigger: 'axis', + formatter: '{b}: {c} tCO鈧俥/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鈧俥` + } +} + +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鈧俥', + axisLabel: { color: '#B8C8E0' }, + nameTextStyle: { color: '#B8C8E0' } +}] + +const trendTooltip = { + trigger: 'axis' +} + +const trendLegend = { + data: ['鑼冨洿1', '鑼冨洿2', '鑼冨洿3'], + textStyle: { color: '#B8C8E0' } +} + +// 琛ㄦ牸鏁版嵁 +const carbonTableData = ref([ + { name: '鐢熶骇绾緼', type: '浜х嚎', scope1: 45.2, scope2: 32.1, scope3: 18.7, total: 96.0, efficiency: '鑹ソ', status: '姝e父' }, + { name: '璁惧B-01', type: '璁惧', scope1: 12.5, scope2: 8.3, scope3: 5.2, total: 26.0, efficiency: '浼樼', status: '姝e父' }, + { name: '鐢熶骇绾緾', 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: '姝e父' }, + { name: '鐢熶骇绾縀', 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', '鍘嬬缉鏈築', '鍐峰嵈濉擟', '椋庢満D', '娉礒', '鍙樺帇鍣‵', '鐢垫満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: '姝e父' }, + { name: '鍘嬬缉鏈築', type: '璁惧', scope1: 38.5, scope2: 28.3, scope3: 15.2, total: 82.0, efficiency: '浼樼', status: '姝e父' }, + { name: '鍐峰嵈濉擟', 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: '姝e父' }, + { name: '娉礒', type: '璁惧', scope1: 12.3, scope2: 9.8, scope3: 6.4, total: 28.5, efficiency: '浼樼', status: '姝e父' } + ], + line: [ + { name: '鐢熶骇绾�1', type: '浜х嚎', scope1: 125.6, scope2: 89.3, scope3: 56.8, total: 271.7, efficiency: '鑹ソ', status: '姝e父' }, + { name: '鐢熶骇绾�2', type: '浜х嚎', scope1: 98.4, scope2: 72.1, scope3: 45.2, total: 215.7, efficiency: '浼樼', status: '姝e父' }, + { 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: '姝e父' }, + { 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: '姝e父' }, + { name: '鍘傚尯B', type: '鍘傚尯', scope1: 387.2, scope2: 289.6, scope3: 184.3, total: 861.1, efficiency: '浼樼', status: '姝e父' }, + { 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 '姝e父': 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鈧俥', + 鑼冨洿2闂存帴鎺掓斁: carbonData.value.scope2 + ' tCO鈧俥', + 鑼冨洿3渚涘簲閾炬帓鏀�: carbonData.value.scope3 + ' tCO鈧俥', + 鎬绘帓鏀鹃噺: totalEmissions.value + ' tCO鈧俥' + }, + 璇︾粏鏁版嵁: carbonTableData.value, + 鐑姏鍥炬暟鎹�: heatmapSeries.value[0].data.map(item => ({ + 鏃堕棿: `${item[0]}:00`, + 璁惧搴忓彿: item[1], + 璁惧鍚嶇О: heatmapYAxis.data[item[1]], + 纰虫帓鏀鹃噺: item[2] + ' tCO鈧俥' + })) + } + + // 鍒涘缓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鈧俥`) + + // 鍙互鍦ㄨ繖閲屾坊鍔犺缁嗕俊鎭脊绐楁垨璺宠浆鍒拌缁嗛〉闈� + } +} + +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> \ No newline at end of file -- Gitblit v1.9.3