From 4d59bb7ee1f03ff16a5bc7f81db165ff68b6f665 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 17 三月 2026 18:01:16 +0800
Subject: [PATCH] Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management into dev_银川_中盛建材

---
 src/views/costAccounting/energyCosts/index.vue | 2207 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 1,857 insertions(+), 350 deletions(-)

diff --git a/src/views/costAccounting/energyCosts/index.vue b/src/views/costAccounting/energyCosts/index.vue
index e5d470a..957f66c 100644
--- a/src/views/costAccounting/energyCosts/index.vue
+++ b/src/views/costAccounting/energyCosts/index.vue
@@ -1,204 +1,479 @@
+// 鑳借�楁垚鏈牳绠�
 <template>
-  <div class="app-container">
-    <!-- 鎼滅储鍖哄煙 -->
-    <div class="search_form">
-      <el-form :model="searchForm"
-               :inline="true">
-        <el-form-item label="缁熻缁村害:">
-          <el-radio-group v-model="statisticsType"
-                          @change="handleTypeChange">
-            <el-radio-button label="day">鎸夋棩缁熻</el-radio-button>
-            <el-radio-button label="month">鎸夋湀缁熻</el-radio-button>
-          </el-radio-group>
-        </el-form-item>
-        <el-form-item label="鑳借�楃被鍨�:">
-          <el-select v-model="searchForm.energyType"
-                     placeholder="鍏ㄩ儴"
-                     clearable
-                     style="width: 140px;"
-                     @change="handleQuery">
-            <el-option label="鍏ㄩ儴"
-                       value="鍏ㄩ儴" />
-            <el-option label="姘�"
-                       value="姘�" />
-            <el-option label="鐢�"
-                       value="鐢�" />
-            <el-option label="姘�"
-                       value="姘�" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="鑳借�楃敤閫�:">
-          <el-select v-model="searchForm.energyPurpose"
-                     placeholder="鍏ㄩ儴"
-                     clearable
-                     style="width: 140px;"
-                     @change="handleQuery">
-            <el-option label="鍏ㄩ儴"
-                       value="鍏ㄩ儴" />
-            <el-option label="鐢熶骇"
-                       value="鐢熶骇" />
-            <el-option label="鍔炲叕"
-                       value="鍔炲叕" />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="鏃堕棿鑼冨洿:">
-          <el-date-picker v-if="statisticsType === 'day'"
-                          v-model="searchForm.dateRange"
-                          type="daterange"
-                          range-separator="鑷�"
-                          start-placeholder="寮�濮嬫棩鏈�"
-                          end-placeholder="缁撴潫鏃ユ湡"
-                          value-format="YYYY-MM-DD"
-                          style="width: 240px;"
-                          @change="handleQuery" />
-          <el-date-picker v-else
-                          v-model="searchForm.monthRange"
-                          type="monthrange"
-                          range-separator="鑷�"
-                          start-placeholder="寮�濮嬫湀浠�"
-                          end-placeholder="缁撴潫鏈堜唤"
-                          value-format="YYYY-MM"
-                          style="width: 240px;"
-                          @change="handleQuery" />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary"
-                     @click="handleQuery">鏌ヨ</el-button>
-          <el-button @click="handleReset">閲嶇疆</el-button>
-        </el-form-item>
-      </el-form>
-      <div>
-        <el-button type="success"
-                   @click="handleExport">瀵煎嚭鎶ヨ〃</el-button>
+  <div class="energy-cost-page">
+    <!-- 绛涢�夊尯鍩� -->
+    <el-card class="filter-card"
+             shadow="never">
+      <template #header>
+        <div class="card-head">
+          <div class="card-head-left">
+            <el-icon class="card-icon ui-icon">
+              <DataLine />
+            </el-icon>
+            <span class="card-title">鏌ヨ鏉′欢</span>
+          </div>
+          <div class="card-head-right">
+            <el-radio-group v-model="statisticsType"
+                            size="small"
+                            @change="handleTypeChange">
+              <el-radio-button label="day">鎸夋棩</el-radio-button>
+              <el-radio-button label="month">鎸夋湀</el-radio-button>
+            </el-radio-group>
+          </div>
+        </div>
+      </template>
+
+      <div class="filter-layout">
+        <el-form :model="searchForm"
+                 :inline="true"
+                 class="filter-form">
+          <el-form-item label="鑳借�楃被鍨�">
+            <el-select v-model="searchForm.energyType"
+                       placeholder="鍏ㄩ儴"
+                       clearable
+                       class="w-140"
+                       @change="handleQuery">
+              <el-option label="鍏ㄩ儴"
+                         value="鍏ㄩ儴" />
+              <el-option label="姘�"
+                         value="姘�" />
+              <el-option label="鐢�"
+                         value="鐢�" />
+              <el-option label="姘�"
+                         value="姘�" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="鑳借�楃敤閫�">
+            <el-select v-model="searchForm.energyPurpose"
+                       placeholder="鍏ㄩ儴"
+                       clearable
+                       class="w-140"
+                       @change="handleQuery">
+              <el-option label="鍏ㄩ儴"
+                         value="鍏ㄩ儴" />
+              <el-option label="鐢熶骇"
+                         value="鐢熶骇" />
+              <el-option label="鍔炲叕"
+                         value="鍔炲叕" />
+            </el-select>
+          </el-form-item>
+          <el-form-item label="鏃堕棿鑼冨洿">
+            <el-date-picker v-if="statisticsType === 'day'"
+                            v-model="searchForm.dateRange"
+                            type="daterange"
+                            range-separator="鑷�"
+                            start-placeholder="寮�濮嬫棩鏈�"
+                            end-placeholder="缁撴潫鏃ユ湡"
+                            value-format="YYYY-MM-DD"
+                            class="w-260"
+                            @change="handleQuery" />
+            <el-date-picker v-else
+                            v-model="searchForm.monthRange"
+                            type="monthrange"
+                            range-separator="鑷�"
+                            start-placeholder="寮�濮嬫湀浠�"
+                            end-placeholder="缁撴潫鏈堜唤"
+                            value-format="YYYY-MM"
+                            class="w-260"
+                            @change="handleQuery" />
+          </el-form-item>
+        </el-form>
+        <div class="filter-actions">
+          <el-button class="lux-btn"
+                     type="primary"
+                     :loading="tableLoading"
+                     @click="handleQuery">鍒锋柊</el-button>
+          <el-button class="lux-btn"
+                     @click="handleReset">閲嶇疆</el-button>
+          <el-button class="lux-btn"
+                     type="success"
+                     plain
+                     @click="handleExport">瀵煎嚭</el-button>
+        </div>
       </div>
-    </div>
-    <!-- 缁熻姒傝鍗$墖 -->
-    <div class="statistics-overview">
-      <h2 class="section-header">
-        <el-icon class="header-icon">
-          <DataLine />
-        </el-icon>
-        鑳借�楁垚鏈瑙�
-      </h2>
-      <el-row :gutter="20">
-        <el-col :span="6">
-          <div class="overview-card blue-card">
-            <div class="overview-icon blue-icon">
-              <el-icon>
+    </el-card>
+
+    <!-- 鍥捐〃鍖哄煙 -->
+    <div class="charts">
+      <el-card class="panel-card"
+               shadow="never">
+        <div class="kpi-strip"
+             :class="{ pulse: queryPulse }"
+             title="蹇嵎閿細Enter 鍒锋柊 / Esc 閲嶇疆 / Alt+E 瀵煎嚭">
+          <button class="kpi-item kpi-total"
+                  type="button"
+                  :class="{ selected: selectedKpi === 'all' }"
+                  @click="handleKpiClick('all')">
+            <div class="kpi-left">
+              <div class="kpi-label">鎬昏兘鑰楁垚鏈�</div>
+              <div class="kpi-value">楼{{ formatMoney(animatedOverview.totalCost) }}</div>
+              <div class="kpi-meta">
+                <span class="kpi-chip"
+                      :class="kpiDelta.total.pct >= 0 ? 'up' : 'down'"
+                      v-if="kpiDelta.total.valid">{{ kpiDelta.total.pct >= 0 ? '+' : '' }}{{ kpiDelta.total.pct.toFixed(1) }}%</span>
+                <svg class="kpi-spark"
+                     viewBox="0 0 72 22"
+                     aria-hidden="true">
+                  <polyline :points="sparklinePoints(kpiSeries.total)"
+                            fill="none"
+                            stroke="rgba(47, 111, 237, 0.85)"
+                            stroke-width="2"
+                            stroke-linecap="round"
+                            stroke-linejoin="round" />
+                </svg>
+              </div>
+            </div>
+            <div class="kpi-icon">
+              <el-icon class="ui-icon">
                 <Money />
               </el-icon>
             </div>
-            <div class="overview-info">
-              <div class="overview-label">鎬昏兘鑰楁垚鏈�</div>
-              <div class="overview-value">楼{{ overview.totalCost }}</div>
+            <div class="kpi-actions"
+                 @click.stop>
+              <button class="kpi-action"
+                      type="button"
+                      @click="copyKpi('totalCost')">澶嶅埗</button>
+              <button class="kpi-action"
+                      type="button"
+                      @click="viewKpiDetails('all')">鏄庣粏</button>
             </div>
-          </div>
-        </el-col>
-        <el-col :span="6">
-          <div class="overview-card green-card">
-            <div class="overview-icon green-icon">
-              <el-icon>
+          </button>
+          <button class="kpi-item kpi-production"
+                  type="button"
+                  :class="{ selected: selectedKpi === 'production' }"
+                  @click="handleKpiClick('production')">
+            <div class="kpi-left">
+              <div class="kpi-label">鐢熶骇鑳借�楁垚鏈�</div>
+              <div class="kpi-value">楼{{ formatMoney(animatedOverview.productionCost) }}</div>
+              <div class="kpi-meta">
+                <span class="kpi-chip"
+                      :class="kpiDelta.production.pct >= 0 ? 'up' : 'down'"
+                      v-if="kpiDelta.production.valid">{{ kpiDelta.production.pct >= 0 ? '+' : '' }}{{ kpiDelta.production.pct.toFixed(1) }}%</span>
+                <svg class="kpi-spark"
+                     viewBox="0 0 72 22"
+                     aria-hidden="true">
+                  <polyline :points="sparklinePoints(kpiSeries.production)"
+                            fill="none"
+                            stroke="rgba(22, 163, 74, 0.85)"
+                            stroke-width="2"
+                            stroke-linecap="round"
+                            stroke-linejoin="round" />
+                </svg>
+              </div>
+            </div>
+            <div class="kpi-icon">
+              <el-icon class="ui-icon">
                 <DataLine />
               </el-icon>
             </div>
-            <div class="overview-info">
-              <div class="overview-label">鐢熶骇鑳借�楁垚鏈�</div>
-              <div class="overview-value">楼{{ overview.productionCost }}</div>
+            <div class="kpi-actions"
+                 @click.stop>
+              <button class="kpi-action"
+                      type="button"
+                      @click="copyKpi('productionCost')">澶嶅埗</button>
+              <button class="kpi-action"
+                      type="button"
+                      @click="viewKpiDetails('production')">鏄庣粏</button>
             </div>
-          </div>
-        </el-col>
-        <el-col :span="6">
-          <div class="overview-card purple-card">
-            <div class="overview-icon purple-icon">
-              <el-icon>
+          </button>
+          <button class="kpi-item kpi-office"
+                  type="button"
+                  :class="{ selected: selectedKpi === 'office' }"
+                  @click="handleKpiClick('office')">
+            <div class="kpi-left">
+              <div class="kpi-label">鍔炲叕鑳借�楁垚鏈�</div>
+              <div class="kpi-value">楼{{ formatMoney(animatedOverview.officeCost) }}</div>
+              <div class="kpi-meta">
+                <span class="kpi-chip"
+                      :class="kpiDelta.office.pct >= 0 ? 'up' : 'down'"
+                      v-if="kpiDelta.office.valid">{{ kpiDelta.office.pct >= 0 ? '+' : '' }}{{ kpiDelta.office.pct.toFixed(1) }}%</span>
+                <svg class="kpi-spark"
+                     viewBox="0 0 72 22"
+                     aria-hidden="true">
+                  <polyline :points="sparklinePoints(kpiSeries.office)"
+                            fill="none"
+                            stroke="rgba(100, 116, 139, 0.90)"
+                            stroke-width="2"
+                            stroke-linecap="round"
+                            stroke-linejoin="round" />
+                </svg>
+              </div>
+            </div>
+            <div class="kpi-icon">
+              <el-icon class="ui-icon">
                 <TrendCharts />
               </el-icon>
             </div>
-            <div class="overview-info">
-              <div class="overview-label">鍔炲叕鑳借�楁垚鏈�</div>
-              <div class="overview-value">楼{{ overview.officeCost }}</div>
+            <div class="kpi-actions"
+                 @click.stop>
+              <button class="kpi-action"
+                      type="button"
+                      @click="copyKpi('officeCost')">澶嶅埗</button>
+              <button class="kpi-action"
+                      type="button"
+                      @click="viewKpiDetails('office')">鏄庣粏</button>
             </div>
-          </div>
-        </el-col>
-        <el-col :span="6">
-          <div class="overview-card gray-card">
-            <div class="overview-icon gray-icon">
-              <el-icon>
+          </button>
+          <button class="kpi-item kpi-avg"
+                  type="button"
+                  @click="handleKpiClick('all')">
+            <div class="kpi-left">
+              <div class="kpi-label">骞冲潎鎴愭湰</div>
+              <div class="kpi-value">楼{{ formatMoney(animatedOverview.avgCost) }} <span class="kpi-unit">/{{ statisticsType === 'day' ? '鏃�' : '鏈�' }}</span></div>
+              <div class="kpi-meta muted">鍩轰簬褰撳墠绛涢�変笌鏄庣粏缁熻</div>
+            </div>
+            <div class="kpi-icon">
+              <el-icon class="ui-icon">
                 <Histogram />
               </el-icon>
             </div>
-            <div class="overview-info">
-              <div class="overview-label">骞冲潎鑳借�楁垚鏈�</div>
-              <div class="overview-value">楼{{ overview.avgCost }} <span class="unit">/{{ statisticsType === 'day' ? '鏃�' : '鏈�' }}</span></div>
+            <div class="kpi-actions"
+                 @click.stop>
+              <button class="kpi-action"
+                      type="button"
+                      @click="copyKpi('avgCost')">澶嶅埗</button>
+              <button class="kpi-action"
+                      type="button"
+                      @click="viewKpiDetails('all')">鏄庣粏</button>
             </div>
+          </button>
+        </div>
+
+        <div class="panel-head">
+          <div class="segmented"
+               role="tablist"
+               aria-label="鍒嗘瀽闈㈡澘鍒囨崲"
+               :class="{ 'no-active': chartPanel === 'none' }">
+            <div class="segmented-indicator"
+                 :class="{ hidden: chartPanel === 'none' }"
+                 :style="panelIndicatorStyle"></div>
+            <button class="segmented-item"
+                    type="button"
+                    role="tab"
+                    :aria-selected="chartPanel === 'core'"
+                    :class="{ active: chartPanel === 'core' }"
+                    @click="handleChartPanelClick('core')">
+              <span class="seg-title">鏍稿績鍒嗘瀽</span>
+              <span class="seg-sub">瓒嬪娍 / 绫诲瀷鍗犳瘮</span>
+            </button>
+            <button class="segmented-item"
+                    type="button"
+                    role="tab"
+                    :aria-selected="chartPanel === 'advanced'"
+                    :class="{ active: chartPanel === 'advanced' }"
+                    @click="handleChartPanelClick('advanced')">
+              <span class="seg-title">楂樼骇鍒嗘瀽</span>
+              <span class="seg-sub">鐢ㄩ�斿崰姣� / 鍗曚环瀵规瘮</span>
+            </button>
           </div>
-        </el-col>
-      </el-row>
+        </div>
+
+        <transition name="lux-collapse">
+          <div v-show="chartPanel === 'core'"
+               class="panel-body">
+            <el-row :gutter="16">
+              <el-col :xs="24"
+                      :lg="12">
+                <el-card class="chart-card"
+                         shadow="never">
+                  <template #header>
+                    <div class="chart-head">
+                      <span class="chart-title">鑳借�楁垚鏈秼鍔�</span>
+                      <div class="chart-tools"
+                           @click.stop>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="downloadChart('cost', '鑳借�楁垚鏈秼鍔�')">涓嬭浇</button>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="openBigChart('cost', '鑳借�楁垚鏈秼鍔�')">澶у浘</button>
+                      </div>
+                    </div>
+                  </template>
+                  <div ref="costChartWrap"
+                       class="chart-wrap"
+                       v-loading="tableLoading">
+                    <div ref="costChart"
+                         class="chart-content"
+                         v-show="hasTableData"></div>
+                    <div class="chart-empty"
+                         v-show="!hasTableData">
+                      <el-empty description="鏆傛棤鏁版嵁" />
+                    </div>
+                  </div>
+                </el-card>
+              </el-col>
+              <el-col :xs="24"
+                      :lg="12">
+                <el-card class="chart-card"
+                         shadow="never">
+                  <template #header>
+                    <div class="chart-head">
+                      <span class="chart-title">鑳借�楃被鍨嬫垚鏈崰姣�</span>
+                      <div class="chart-tools"
+                           @click.stop>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="downloadChart('type', '鑳借�楃被鍨嬫垚鏈崰姣�')">涓嬭浇</button>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="openBigChart('type', '鑳借�楃被鍨嬫垚鏈崰姣�')">澶у浘</button>
+                      </div>
+                    </div>
+                  </template>
+                  <div ref="typeChartWrap"
+                       class="chart-wrap"
+                       v-loading="tableLoading">
+                    <div ref="typeChart"
+                         class="chart-content"
+                         v-show="hasTableData"></div>
+                    <div class="chart-empty"
+                         v-show="!hasTableData">
+                      <el-empty description="鏆傛棤鏁版嵁" />
+                    </div>
+                  </div>
+                </el-card>
+              </el-col>
+            </el-row>
+          </div>
+        </transition>
+
+        <transition name="lux-collapse">
+          <div v-show="chartPanel === 'advanced'"
+               class="panel-body">
+            <el-row :gutter="16"
+                    class="charts-row">
+              <el-col :xs="24"
+                      :lg="12">
+                <el-card class="chart-card"
+                         shadow="never">
+                  <template #header>
+                    <div class="chart-head">
+                      <span class="chart-title">鑳借�楃敤閫旀垚鏈崰姣�</span>
+                      <div class="chart-tools"
+                           @click.stop>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="downloadChart('purpose', '鑳借�楃敤閫旀垚鏈崰姣�')">涓嬭浇</button>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="openBigChart('purpose', '鑳借�楃敤閫旀垚鏈崰姣�')">澶у浘</button>
+                      </div>
+                    </div>
+                  </template>
+                  <div ref="purposeChartWrap"
+                       class="chart-wrap"
+                       v-loading="tableLoading">
+                    <div ref="purposeChart"
+                         class="chart-content"
+                         v-show="hasTableData"></div>
+                    <div class="chart-empty"
+                         v-show="!hasTableData">
+                      <el-empty description="鏆傛棤鏁版嵁" />
+                    </div>
+                  </div>
+                </el-card>
+              </el-col>
+              <el-col :xs="24"
+                      :lg="12">
+                <el-card class="chart-card"
+                         shadow="never">
+                  <template #header>
+                    <div class="chart-head">
+                      <span class="chart-title">鑳借�楀崟浠峰姣�</span>
+                      <div class="chart-tools"
+                           @click.stop>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="downloadChart('price', '鑳借�楀崟浠峰姣�')">涓嬭浇</button>
+                        <button class="chart-tool"
+                                type="button"
+                                @click="openBigChart('price', '鑳借�楀崟浠峰姣�')">澶у浘</button>
+                      </div>
+                    </div>
+                  </template>
+                  <div ref="priceChartWrap"
+                       class="chart-wrap"
+                       v-loading="tableLoading">
+                    <div ref="priceChart"
+                         class="chart-content"
+                         v-show="hasTableData"></div>
+                    <div class="chart-empty"
+                         v-show="!hasTableData">
+                      <el-empty description="鏆傛棤鏁版嵁" />
+                    </div>
+                  </div>
+                </el-card>
+              </el-col>
+            </el-row>
+          </div>
+        </transition>
+      </el-card>
     </div>
-    <!-- 鍥捐〃鍖哄煙 -->
-    <div class="charts-container">
-      <h2 class="section-header">
-        <el-icon class="header-icon">
-          <Histogram />
-        </el-icon>
-        鑳借�楁垚鏈垎鏋�
-      </h2>
-      <el-row :gutter="20">
-        <el-col :span="12">
-          <div class="chart-card">
-            <div class="chart-title">鑳借�楁垚鏈秼鍔�</div>
-            <div ref="costChart"
-                 class="chart-content"></div>
-          </div>
-        </el-col>
-        <el-col :span="12">
-          <div class="chart-card">
-            <div class="chart-title">鑳借�楃被鍨嬫垚鏈崰姣�</div>
-            <div ref="typeChart"
-                 class="chart-content"></div>
-          </div>
-        </el-col>
-      </el-row>
-      <el-row :gutter="20"
-              style="margin-top: 20px;">
-        <el-col :span="12">
-          <div class="chart-card">
-            <div class="chart-title">鑳借�楃敤閫旀垚鏈崰姣�</div>
-            <div ref="purposeChart"
-                 class="chart-content"></div>
-          </div>
-        </el-col>
-        <el-col :span="12">
-          <div class="chart-card">
-            <div class="chart-title">鑳借�楀崟浠峰姣�</div>
-            <div ref="priceChart"
-                 class="chart-content"></div>
-          </div>
-        </el-col>
-      </el-row>
-    </div>
+
+    <el-dialog v-model="bigChartVisible"
+               :title="bigChartTitle"
+               width="92%"
+               top="6vh"
+               class="big-chart-dialog"
+               destroy-on-close
+               @opened="handleBigChartOpened"
+               @closed="handleBigChartClosed">
+      <div ref="bigChartEl"
+           class="big-chart-canvas"></div>
+      <template #footer>
+        <div class="big-chart-footer">
+          <el-button class="lux-btn"
+                     @click="downloadChart(bigChartKey, bigChartTitle)">涓嬭浇鍥剧墖</el-button>
+          <el-button class="lux-btn"
+                     type="primary"
+                     @click="bigChartVisible = false">鍏抽棴</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
     <!-- 鏁版嵁琛ㄦ牸 -->
-    <div class="table-section">
-      <h2 class="section-header">
-        <el-icon class="header-icon">
-          <List />
-        </el-icon>
-        璇︾粏鏁版嵁
-      </h2>
-      <el-table :data="tableData"
+    <el-card class="table-card"
+             shadow="never">
+      <div ref="tableAnchor"></div>
+      <template #header>
+        <div class="card-head">
+          <div class="card-head-left">
+            <el-icon class="card-icon ui-icon">
+              <List />
+            </el-icon>
+            <span class="card-title">鏄庣粏鏁版嵁</span>
+          </div>
+          <div class="card-head-right subtle">
+            <span>鍏� {{ page.total }} 鏉�</span>
+          </div>
+        </div>
+      </template>
+
+      <el-table :data="displayTableData"
                 v-loading="tableLoading"
-                border>
+                stripe
+                :header-cell-style="{ height: '44px' }"
+                class="data-table lux-table"
+                @sort-change="handleSortChange">
+        <template #empty>
+          <el-empty description="鏆傛棤鏄庣粏鏁版嵁" />
+        </template>
         <el-table-column type="index"
                          label="搴忓彿"
                          width="60"
                          align="center" />
         <el-table-column prop="timePeriod"
                          :label="timeColumnLabel"
-                         align="center" />
+                         align="center"
+                         sortable="custom" />
         <el-table-column prop="energyType"
                          label="鑳借�楃被鍨�"
                          width="100"
-                         align="center">
+                         align="center"
+                         :filters="energyTypeFilters"
+                         :filter-method="filterEnergyType"
+                         filter-placement="bottom-end">
           <template #default="scope">
             <el-tag :type="getEnergyTypeType(scope.row.energyType)">
               {{ scope.row.energyType }}
@@ -208,7 +483,10 @@
         <el-table-column prop="energyPurpose"
                          label="鑳借�楃敤閫�"
                          width="100"
-                         align="center">
+                         align="center"
+                         :filters="energyPurposeFilters"
+                         :filter-method="filterEnergyPurpose"
+                         filter-placement="bottom-end">
           <template #default="scope">
             <el-tag :type="scope.row.energyPurpose === '鐢熶骇' ? 'primary' : 'info'">
               {{ scope.row.energyPurpose }}
@@ -219,42 +497,44 @@
                          label="鐢ㄩ噺"
                          align="right">
           <template #default="scope">
-            <span class="consumption-value">{{ scope.row.consumption }}</span>
+            <span class="consumption-value">{{ formatNumber(scope.row.consumption, 2) }}</span>
             <span class="consumption-unit">{{ scope.row.unit }}</span>
           </template>
         </el-table-column>
         <el-table-column prop="price"
                          label="鍗曚环(鍏�)"
-                         align="right">
+                         align="right"
+                         sortable="custom">
           <template #default="scope">
-            <span class="price-value">{{ scope.row.price }}</span>
+            <span class="price-value">{{ formatNumber(scope.row.price, 2) }}</span>
           </template>
         </el-table-column>
         <el-table-column prop="cost"
                          label="鎴愭湰(鍏�)"
                          align="right"
+                         sortable="custom"
                          fixed="right">
           <template #default="scope">
-            <span class="cost-value">楼{{ scope.row.cost }}</span>
+            <span class="cost-value">楼{{ formatNumber(scope.row.cost, 2) }}</span>
           </template>
         </el-table-column>
       </el-table>
-    </div>
-    <!-- 鍒嗛〉 -->
-    <div class="pagination-container">
-      <el-pagination v-model:current-page="page.current"
-                     v-model:page-size="page.size"
-                     :page-sizes="[10, 20, 50, 100]"
-                     :total="page.total"
-                     layout="total, sizes, prev, pager, next, jumper"
-                     @size-change="handleSizeChange"
-                     @current-change="handleCurrentChange" />
-    </div>
+
+      <div class="pagination-container">
+        <el-pagination v-model:current-page="page.current"
+                       v-model:page-size="page.size"
+                       :page-sizes="[10, 20, 50, 100]"
+                       :total="page.total"
+                       layout="total, sizes, prev, pager, next, jumper"
+                       @size-change="handleSizeChange"
+                       @current-change="handleCurrentChange" />
+      </div>
+    </el-card>
   </div>
 </template>
 
 <script setup>
-  import { ref, reactive, onMounted, computed, nextTick } from "vue";
+  import { ref, reactive, onMounted, onUnmounted, computed, nextTick, watch } from "vue";
   import { ElMessage } from "element-plus";
   import {
     Money,
@@ -262,10 +542,11 @@
     TrendCharts,
     Histogram,
     List,
+    ArrowDown,
   } from "@element-plus/icons-vue";
   import * as echarts from "echarts";
-  import { energyCostStatistics } from "@/api/costAccounting/energyCosts";
-
+  // import { energyCostStatistics } from "@/api/costAccounting/energyCosts";
+  import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
   // 缁熻缁村害锛歞ay-鎸夋棩锛宮onth-鎸夋湀
   const statisticsType = ref("day");
 
@@ -302,9 +583,279 @@
     avgCost: "0.00",
   });
 
+  const selectedKpi = ref("all"); // all | production | office
+  const animatedOverview = reactive({
+    totalCost: 0,
+    productionCost: 0,
+    officeCost: 0,
+    avgCost: 0,
+  });
+
+  const formatMoney = v => {
+    const n = Number.parseFloat(v);
+    const value = Number.isFinite(n) ? n : 0;
+    return value.toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
+  };
+
+  const formatNumber = (v, digits = 2) => {
+    const n = Number.parseFloat(v);
+    if (!Number.isFinite(n)) return "--";
+    return n.toLocaleString("zh-CN", { minimumFractionDigits: digits, maximumFractionDigits: digits });
+  };
+
+  const animateNumber = (key, toValue, duration = 420) => {
+    const from = animatedOverview[key] || 0;
+    const to = Number.isFinite(toValue) ? toValue : 0;
+    const start = performance.now();
+    const easeOut = t => 1 - Math.pow(1 - t, 3);
+
+    const tick = now => {
+      const p = Math.min(1, (now - start) / duration);
+      animatedOverview[key] = from + (to - from) * easeOut(p);
+      if (p < 1) requestAnimationFrame(tick);
+    };
+    requestAnimationFrame(tick);
+  };
+
+  watch(
+    () => ({ ...overview }),
+    val => {
+      animateNumber("totalCost", Number.parseFloat(val.totalCost));
+      animateNumber("productionCost", Number.parseFloat(val.productionCost));
+      animateNumber("officeCost", Number.parseFloat(val.officeCost));
+      animateNumber("avgCost", Number.parseFloat(val.avgCost));
+    },
+    { deep: true, immediate: true }
+  );
+
   // 琛ㄦ牸鏁版嵁
   const tableData = ref([]);
   const tableLoading = ref(false);
+  const hasTableData = computed(() => Array.isArray(tableData.value) && tableData.value.length > 0);
+  const queryPulse = ref(false);
+
+  const kpiSeries = computed(() => {
+    const rows = Array.isArray(tableData.value) ? tableData.value : [];
+    const byTime = new Map();
+    for (const r of rows) {
+      const t = r?.timePeriod ?? "";
+      if (!t) continue;
+      if (!byTime.has(t)) byTime.set(t, { total: 0, production: 0, office: 0 });
+      const bucket = byTime.get(t);
+      const c = Number.parseFloat(r?.cost);
+      const cost = Number.isFinite(c) ? c : 0;
+      bucket.total += cost;
+      if (r?.energyPurpose === "鐢熶骇") bucket.production += cost;
+      if (r?.energyPurpose === "鍔炲叕") bucket.office += cost;
+    }
+    const times = Array.from(byTime.keys()).sort((a, b) => String(a).localeCompare(String(b)));
+    const total = times.map(t => byTime.get(t).total);
+    const production = times.map(t => byTime.get(t).production);
+    const office = times.map(t => byTime.get(t).office);
+    return { times, total, production, office };
+  });
+
+  const kpiDelta = computed(() => {
+    const pick = arr => {
+      const a = Array.isArray(arr) ? arr : [];
+      if (a.length < 2) return { pct: 0, valid: false };
+      const prev = a[a.length - 2];
+      const cur = a[a.length - 1];
+      if (!Number.isFinite(prev) || prev === 0) return { pct: 0, valid: false };
+      return { pct: ((cur - prev) / prev) * 100, valid: true };
+    };
+    return {
+      total: pick(kpiSeries.value.total),
+      production: pick(kpiSeries.value.production),
+      office: pick(kpiSeries.value.office),
+    };
+  });
+
+  const sparklinePoints = values => {
+    const v = (Array.isArray(values) ? values : []).slice(-12);
+    if (v.length < 2) return "";
+    const min = Math.min(...v);
+    const max = Math.max(...v);
+    const range = max - min || 1;
+    const w = 72;
+    const h = 22;
+    return v
+      .map((n, i) => {
+        const x = (i / (v.length - 1)) * w;
+        const y = h - ((n - min) / range) * h;
+        return `${x.toFixed(2)},${y.toFixed(2)}`;
+      })
+      .join(" ");
+  };
+
+  const handleKpiClick = key => {
+    selectedKpi.value = key;
+    if (key === "all") searchForm.energyPurpose = "";
+    if (key === "production") searchForm.energyPurpose = "鐢熶骇";
+    if (key === "office") searchForm.energyPurpose = "鍔炲叕";
+    page.current = 1;
+    handleQuery();
+  };
+
+  const viewKpiDetails = key => {
+    handleKpiClick(key);
+    nextTick(() => {
+      const el = tableAnchor.value;
+      if (el?.scrollIntoView) el.scrollIntoView({ behavior: "smooth", block: "start" });
+    });
+  };
+
+  const copyKpi = async field => {
+    const map = {
+      totalCost: animatedOverview.totalCost,
+      productionCost: animatedOverview.productionCost,
+      officeCost: animatedOverview.officeCost,
+      avgCost: animatedOverview.avgCost,
+    };
+    const raw = map[field];
+    const text = `楼${formatMoney(raw)}`;
+    try {
+      if (navigator?.clipboard?.writeText) {
+        await navigator.clipboard.writeText(text);
+      } else {
+        const input = document.createElement("input");
+        input.value = text;
+        document.body.appendChild(input);
+        input.select();
+        document.execCommand("copy");
+        document.body.removeChild(input);
+      }
+      ElMessage.success("宸插鍒跺埌鍓创鏉�");
+    } catch (e) {
+      console.error(e);
+      ElMessage.error("澶嶅埗澶辫触");
+    }
+  };
+
+  const getChartByKey = key => {
+    if (key === "cost") return costChartInstance;
+    if (key === "type") return typeChartInstance;
+    if (key === "purpose") return purposeChartInstance;
+    if (key === "price") return priceChartInstance;
+    return null;
+  };
+
+  const ensurePanelForChart = key => {
+    if (key === "cost" || key === "type") chartPanel.value = "core";
+    if (key === "purpose" || key === "price") chartPanel.value = "advanced";
+  };
+
+  const downloadChart = (key, title) => {
+    ensurePanelForChart(key);
+    nextTick(() => {
+      ensureChartsReady(chartPanel.value === "none" ? "core" : chartPanel.value);
+      const ins = getChartByKey(key);
+      if (!ins) return;
+      const url = ins.getDataURL({ pixelRatio: 2, backgroundColor: "#ffffff" });
+      const a = document.createElement("a");
+      a.href = url;
+      const typePart = searchForm.energyType ? `_${searchForm.energyType}` : "";
+      const purposePart = searchForm.energyPurpose ? `_${searchForm.energyPurpose}` : "";
+      let rangePart = "";
+      if (statisticsType.value === "day") {
+        if (searchForm.dateRange?.length === 2) rangePart = `_${searchForm.dateRange[0]}~${searchForm.dateRange[1]}`;
+      } else {
+        if (searchForm.monthRange?.length === 2) rangePart = `_${searchForm.monthRange[0]}~${searchForm.monthRange[1]}`;
+      }
+      a.download = `${title || "chart"}${typePart}${purposePart}${rangePart}.png`;
+      a.click();
+    });
+  };
+
+  const openBigChart = (key, title) => {
+    bigChartKey.value = key;
+    bigChartTitle.value = title || "鍥捐〃";
+    bigChartVisible.value = true;
+  };
+
+  const handleBigChartOpened = () => {
+    nextTick(() => {
+      ensurePanelForChart(bigChartKey.value);
+      ensureChartsReady(chartPanel.value === "none" ? "core" : chartPanel.value);
+      const src = getChartByKey(bigChartKey.value);
+      const el = bigChartEl.value;
+      if (!src || !el) return;
+
+      try {
+        bigChartInstance?.dispose?.();
+      } catch (e) {
+        // ignore
+      }
+      bigChartInstance = echarts.init(el);
+      const opt = src.getOption();
+      bigChartInstance.setOption(opt, true);
+      bigChartInstance.resize();
+    });
+  };
+
+  const handleBigChartClosed = () => {
+    try {
+      bigChartInstance?.dispose?.();
+    } catch (e) {
+      // ignore
+    }
+    bigChartInstance = null;
+  };
+
+  const handleBigChartResize = () => {
+    try {
+      bigChartInstance?.resize?.();
+    } catch (e) {
+      // ignore
+    }
+  };
+  // 琛ㄦ牸鎺掑簭锛堝墠绔帓搴忥細浠呭奖鍝嶅綋鍓嶉〉鏁版嵁锛岄伩鍏嶇牬鍧忓悗绔垎椤靛崗璁級
+  const sortState = reactive({
+    prop: "",
+    order: "",
+  });
+
+  const handleSortChange = ({ prop, order }) => {
+    sortState.prop = prop || "";
+    sortState.order = order || "";
+  };
+
+  const displayTableData = computed(() => {
+    const data = Array.isArray(tableData.value) ? [...tableData.value] : [];
+    if (!sortState.prop || !sortState.order) return data;
+
+    const prop = sortState.prop;
+    const direction = sortState.order === "ascending" ? 1 : -1;
+    const numFields = new Set(["price", "cost", "consumption"]);
+
+    return data.sort((a, b) => {
+      const av = a?.[prop];
+      const bv = b?.[prop];
+
+      if (numFields.has(prop)) {
+        const an = Number.parseFloat(av);
+        const bn = Number.parseFloat(bv);
+        const aNum = Number.isFinite(an) ? an : -Infinity;
+        const bNum = Number.isFinite(bn) ? bn : -Infinity;
+        return (aNum - bNum) * direction;
+      }
+
+      return String(av ?? "").localeCompare(String(bv ?? ""), "zh-Hans-CN") * direction;
+    });
+  });
+
+  const energyTypeFilters = [
+    { text: "姘�", value: "姘�" },
+    { text: "鐢�", value: "鐢�" },
+    { text: "姘�", value: "姘�" },
+  ];
+  const energyPurposeFilters = [
+    { text: "鐢熶骇", value: "鐢熶骇" },
+    { text: "鍔炲叕", value: "鍔炲叕" },
+  ];
+
+  const filterEnergyType = (value, row) => row.energyType === value;
+  const filterEnergyPurpose = (value, row) => row.energyPurpose === value;
 
   // 鍒嗛〉
   const page = reactive({
@@ -319,11 +870,78 @@
   const purposeChart = ref(null);
   const priceChart = ref(null);
 
+  const costChartWrap = ref(null);
+  const typeChartWrap = ref(null);
+  const purposeChartWrap = ref(null);
+  const priceChartWrap = ref(null);
+
+  const tableAnchor = ref(null);
+
+  const bigChartVisible = ref(false);
+  const bigChartKey = ref("cost");
+  const bigChartTitle = ref("");
+  const bigChartEl = ref(null);
+  let bigChartInstance = null;
+
+  watch(bigChartVisible, v => {
+    if (v) window.addEventListener("resize", handleBigChartResize);
+    else window.removeEventListener("resize", handleBigChartResize);
+  });
+
+  onUnmounted(() => {
+    window.removeEventListener("resize", handleBigChartResize);
+    try {
+      bigChartInstance?.dispose?.();
+    } catch (e) {
+      // ignore
+    }
+  });
+
   // 鍥捐〃瀹炰緥
   let costChartInstance = null;
   let typeChartInstance = null;
   let purposeChartInstance = null;
   let priceChartInstance = null;
+
+  // 鍥捐〃鍖哄垏鎹細core | advanced | none锛堢偣鍑诲綋鍓嶉�変腑鍙敹璧凤級
+  const chartPanel = ref("core");
+
+  const ensureChartsReady = panel => {
+    if (panel === "core") {
+      if (costChart.value && !costChartInstance) costChartInstance = echarts.init(costChart.value);
+      if (typeChart.value && !typeChartInstance) typeChartInstance = echarts.init(typeChart.value);
+      if (costChartInstance) updateCostChart();
+      if (typeChartInstance) updateTypeChart();
+      return;
+    }
+    if (panel === "advanced") {
+      if (purposeChart.value && !purposeChartInstance) purposeChartInstance = echarts.init(purposeChart.value);
+      if (priceChart.value && !priceChartInstance) priceChartInstance = echarts.init(priceChart.value);
+      if (purposeChartInstance) updatePurposeChart();
+      if (priceChartInstance) updatePriceChart();
+    }
+  };
+
+  const resizeChartsAfterExpand = () => {
+    nextTick(() => {
+      ensureChartsReady(chartPanel.value === "none" ? "core" : chartPanel.value);
+      handleResize();
+      updateCharts();
+    });
+  };
+
+  const handleChartPanelClick = key => {
+    chartPanel.value = chartPanel.value === key ? "none" : key;
+  };
+
+  const panelIndicatorStyle = computed(() => {
+    const x = chartPanel.value === "advanced" ? "calc(100% + 4px)" : "0";
+    return { transform: `translateX(${x})` };
+  });
+
+  watch(chartPanel, val => {
+    if (val !== "none") resizeChartsAfterExpand();
+  });
 
   // 鑾峰彇鑳借�楃被鍨嬫爣绛剧被鍨�
   const getEnergyTypeType = type => {
@@ -338,26 +956,8 @@
   // 鍒濆鍖栧浘琛�
   const initCharts = () => {
     nextTick(() => {
-      // 鑳借�楁垚鏈秼鍔垮浘
-      if (costChart.value) {
-        costChartInstance = echarts.init(costChart.value);
-        updateCostChart();
-      }
-      // 鑳借�楃被鍨嬫垚鏈崰姣斿浘
-      if (typeChart.value) {
-        typeChartInstance = echarts.init(typeChart.value);
-        updateTypeChart();
-      }
-      // 鑳借�楃敤閫旀垚鏈崰姣斿浘
-      if (purposeChart.value) {
-        purposeChartInstance = echarts.init(purposeChart.value);
-        updatePurposeChart();
-      }
-      // 鑳借�楀崟浠峰姣斿浘
-      if (priceChart.value) {
-        priceChartInstance = echarts.init(priceChart.value);
-        updatePriceChart();
-      }
+      // 鍙垵濮嬪寲鍙闈㈡澘锛岄伩鍏嶉殣钘忓鍣ㄥ垵濮嬪寲涓� 0 灏哄瀵艰嚧绌虹櫧
+      ensureChartsReady(chartPanel.value === "none" ? "core" : chartPanel.value);
     });
   };
 
@@ -368,10 +968,11 @@
       tooltip: {
         trigger: "axis",
         axisPointer: { type: "shadow" },
-        backgroundColor: "rgba(255, 255, 255, 0.95)",
-        borderColor: "#409EFF",
+        backgroundColor: "rgba(255, 255, 255, 0.96)",
+        borderColor: "#2f6fed",
         borderWidth: 1,
-        textStyle: { color: "#303133" },
+        textStyle: { color: "rgba(15, 23, 42, 0.92)" },
+        extraCssText: "box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
       },
       legend: {
         data: ["鐢熶骇鑳借�楁垚鏈�", "鍔炲叕鑳借�楁垚鏈�"],
@@ -391,18 +992,18 @@
         data: data.map(item => item.timePeriod),
         axisLabel: {
           rotate: statisticsType.value === "day" ? 45 : 0,
-          color: "#606266",
+          color: "rgba(15, 23, 42, 0.62)",
         },
-        axisLine: { lineStyle: { color: "#ebeef5" } },
+        axisLine: { lineStyle: { color: "rgba(15, 23, 42, 0.08)" } },
         splitLine: { show: false },
       },
       yAxis: {
         type: "value",
         name: "鎴愭湰(鍏�)",
-        nameTextStyle: { color: "#606266" },
-        axisLabel: { color: "#606266" },
+        nameTextStyle: { color: "rgba(15, 23, 42, 0.58)" },
+        axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
         axisLine: { show: false },
-        splitLine: { lineStyle: { color: "#f0f2f5" } },
+        splitLine: { lineStyle: { color: "rgba(15, 23, 42, 0.06)" } },
       },
       series: [
         {
@@ -465,15 +1066,16 @@
       tooltip: {
         trigger: "item",
         formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
-        backgroundColor: "rgba(255, 255, 255, 0.95)",
-        borderColor: "#409EFF",
+        backgroundColor: "rgba(255, 255, 255, 0.96)",
+        borderColor: "#2f6fed",
         borderWidth: 1,
-        textStyle: { color: "#303133" },
+        textStyle: { color: "rgba(15, 23, 42, 0.92)" },
+        extraCssText: "box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
       },
       legend: {
         orient: "horizontal",
         bottom: 0,
-        textStyle: { color: "#606266" },
+        textStyle: { color: "rgba(15, 23, 42, 0.62)" },
       },
       series: [
         {
@@ -510,7 +1112,7 @@
           data: chartData,
         },
       ],
-      color: ["#409EFF", "#67C23A", "#E6A23C"],
+      color: ["#2f6fed", "#16a34a", "#f59e0b"],
     };
     typeChartInstance.setOption(option);
   };
@@ -538,15 +1140,16 @@
       tooltip: {
         trigger: "item",
         formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
-        backgroundColor: "rgba(255, 255, 255, 0.95)",
-        borderColor: "#409EFF",
+        backgroundColor: "rgba(255, 255, 255, 0.96)",
+        borderColor: "#2f6fed",
         borderWidth: 1,
-        textStyle: { color: "#303133" },
+        textStyle: { color: "rgba(15, 23, 42, 0.92)" },
+        extraCssText: "box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
       },
       legend: {
         orient: "horizontal",
         bottom: 0,
-        textStyle: { color: "#606266" },
+        textStyle: { color: "rgba(15, 23, 42, 0.62)" },
       },
       series: [
         {
@@ -565,15 +1168,15 @@
           label: {
             show: true,
             formatter: "{b}: {d}%",
-            color: "#606266",
+            color: "rgba(15, 23, 42, 0.62)",
           },
           labelLine: {
             show: true,
-            lineStyle: { color: "#dcdfe6" },
+            lineStyle: { color: "rgba(15, 23, 42, 0.10)" },
           },
         },
       ],
-      color: ["#409EFF", "#67C23A"],
+      color: ["#2f6fed", "#16a34a"],
     };
     purposeChartInstance.setOption(option);
   };
@@ -603,16 +1206,17 @@
       tooltip: {
         trigger: "axis",
         axisPointer: { type: "shadow" },
-        backgroundColor: "rgba(255, 255, 255, 0.95)",
-        borderColor: "#409EFF",
+        backgroundColor: "rgba(255, 255, 255, 0.96)",
+        borderColor: "#2f6fed",
         borderWidth: 1,
-        textStyle: { color: "#303133" },
+        textStyle: { color: "rgba(15, 23, 42, 0.92)" },
+        extraCssText: "box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
       },
       legend: {
         data: ["鐢熶骇鑳借�楀崟浠�", "鍔炲叕鑳借�楀崟浠�"],
         top: 0,
         right: 10,
-        textStyle: { color: "#606266" },
+        textStyle: { color: "rgba(15, 23, 42, 0.62)" },
       },
       grid: {
         left: "3%",
@@ -624,17 +1228,17 @@
       xAxis: {
         type: "category",
         data: energyTypes,
-        axisLabel: { color: "#606266" },
-        axisLine: { lineStyle: { color: "#ebeef5" } },
+        axisLabel: { color: "rgba(15, 23, 42, 0.62)" },
+        axisLine: { lineStyle: { color: "rgba(15, 23, 42, 0.08)" } },
         splitLine: { show: false },
       },
       yAxis: {
         type: "value",
         name: "鍗曚环(鍏�)",
-        nameTextStyle: { color: "#606266" },
-        axisLabel: { color: "#606266" },
+        nameTextStyle: { color: "rgba(15, 23, 42, 0.58)" },
+        axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
         axisLine: { show: false },
-        splitLine: { lineStyle: { color: "#f0f2f5" } },
+        splitLine: { lineStyle: { color: "rgba(15, 23, 42, 0.06)" } },
       },
       series: [
         {
@@ -643,8 +1247,8 @@
           data: productionPrices,
           itemStyle: {
             color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-              { offset: 0, color: "#409EFF" },
-              { offset: 1, color: "#66b1ff" },
+              { offset: 0, color: "#2f6fed" },
+              { offset: 1, color: "#5b8cff" },
             ]),
             borderRadius: [4, 4, 0, 0],
           },
@@ -655,8 +1259,8 @@
           data: officePrices,
           itemStyle: {
             color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-              { offset: 0, color: "#67C23A" },
-              { offset: 1, color: "#85ce61" },
+              { offset: 0, color: "#16a34a" },
+              { offset: 1, color: "rgba(22, 163, 74, 0.65)" },
             ]),
             borderRadius: [4, 4, 0, 0],
           },
@@ -692,6 +1296,10 @@
 
   // 鏌ヨ
   const handleQuery = () => {
+    queryPulse.value = true;
+    window.setTimeout(() => {
+      queryPulse.value = false;
+    }, 520);
     tableLoading.value = true;
 
     // 鏋勯�犺姹傚弬鏁�
@@ -699,6 +1307,9 @@
       type: statisticsType.value,
       energyType: searchForm.energyType || undefined,
       energyPurpose: searchForm.energyPurpose || undefined,
+      // 椤圭洰鍐呭父鐢ㄥ垎椤靛弬鏁板懡鍚�
+      pageNum: page.current,
+      pageSize: page.size,
     };
 
     if (statisticsType.value === "day") {
@@ -714,7 +1325,7 @@
     }
 
     // 璋冪敤鎺ュ彛鑾峰彇鏁版嵁
-    energyCostStatistics(params)
+    energyConsumptionDetailStatistics(params)
       .then(res => {
         if (res.code === 200) {
           tableData.value = res.data.records || [];
@@ -731,12 +1342,22 @@
           ElMessage.error(res.message || "鑾峰彇鏁版嵁澶辫触");
           tableData.value = [];
           page.total = 0;
+          overview.totalCost = "0.00";
+          overview.productionCost = "0.00";
+          overview.officeCost = "0.00";
+          overview.avgCost = "0.00";
         }
       })
       .catch(err => {
         console.error("鑾峰彇鏁版嵁寮傚父锛�", err);
-        // 鐢熸垚鍋囨暟鎹�
-        generateMockData();
+        // 銆愬亣鏁版嵁锛圡ock锛夊凡绂佺敤銆戞帴鍙e紓甯告椂涓嶅啀鐢熸垚闅忔満鍋囨暟鎹紝閬垮厤璇敤鍒扮敓浜ф暟鎹摼璺�
+        ElMessage.error("鑾峰彇鏁版嵁寮傚父");
+        tableData.value = [];
+        page.total = 0;
+        overview.totalCost = "0.00";
+        overview.productionCost = "0.00";
+        overview.officeCost = "0.00";
+        overview.avgCost = "0.00";
       })
       .finally(() => {
         tableLoading.value = false;
@@ -744,6 +1365,8 @@
       });
   };
 
+  // 銆愬亣鏁版嵁锛圡ock锛夊凡绂佺敤銆戝巻鍙蹭笂鐢ㄤ簬鎺ュ彛寮傚父鍏滃簳鐨勯殢鏈烘暟鎹敓鎴愰�昏緫锛岀幇宸叉暣浣撴敞閲婏紝閬垮厤璇敤浜庣敓浜с��
+  /*
   // 鐢熸垚鍋囨暟鎹�
   const generateMockData = () => {
     if (statisticsType.value === "day") {
@@ -875,7 +1498,10 @@
     // 鏇存柊缁熻姒傝鏁版嵁
     calculateOverview();
   };
+  */
 
+  // 銆愬亣鏁版嵁锛圡ock锛夊凡绂佺敤銆戜笌 generateMockData 閰嶅鐨勫墠绔眹鎬昏绠楋紙浠呬緵鍋囨暟鎹睍绀猴級锛岀幇宸叉敞閲�
+  /*
   // 璁$畻缁熻姒傝鏁版嵁
   const calculateOverview = () => {
     let totalCost = 0;
@@ -897,6 +1523,7 @@
     overview.officeCost = officeCost.toFixed(2);
     overview.avgCost = (totalCost / tableData.value.length).toFixed(2);
   };
+  */
 
   // 鏇存柊鎵�鏈夊浘琛�
   const updateCharts = () => {
@@ -941,11 +1568,14 @@
   // 鍒嗛〉澶у皬鍙樺寲
   const handleSizeChange = val => {
     page.size = val;
+    page.current = 1;
+    handleQuery();
   };
 
   // 椤电爜鍙樺寲
   const handleCurrentChange = val => {
     page.current = val;
+    handleQuery();
   };
 
   // 绐楀彛澶у皬鍙樺寲鏃堕噸鏂版覆鏌撳浘琛�
@@ -961,175 +1591,1052 @@
     initCharts();
     window.addEventListener("resize", handleResize);
   });
+
+  const handleGlobalHotkeys = e => {
+    // 閬垮厤鍦ㄨ緭鍏ユ鍐呰瑙�
+    const target = e?.target;
+    const tag = target?.tagName?.toLowerCase?.();
+    const isTyping =
+      tag === "input" ||
+      tag === "textarea" ||
+      target?.isContentEditable ||
+      target?.classList?.contains?.("el-input__inner");
+    if (isTyping) return;
+
+    // Enter: 鍒锋柊鏌ヨ
+    if (e.key === "Enter") {
+      e.preventDefault();
+      handleQuery();
+      return;
+    }
+
+    // Esc: 閲嶇疆
+    if (e.key === "Escape") {
+      e.preventDefault();
+      handleReset();
+      return;
+    }
+
+    // Alt+E: 瀵煎嚭
+    if (e.altKey && (e.key === "e" || e.key === "E")) {
+      e.preventDefault();
+      handleExport();
+    }
+  };
+
+  onMounted(() => {
+    window.addEventListener("keydown", handleGlobalHotkeys);
+  });
+
+  onUnmounted(() => {
+    window.removeEventListener("keydown", handleGlobalHotkeys);
+  });
 </script>
 
 <style scoped lang="scss">
-  .app-container {
-    padding: 20px;
+  .energy-cost-page {
+    --lux-bg: #f6f7fb;
+    --lux-card: rgba(255, 255, 255, 0.86);
+    --lux-card-solid: #ffffff;
+    --lux-border: rgba(15, 23, 42, 0.08);
+    --lux-text: rgba(15, 23, 42, 0.92);
+    --lux-subtle: rgba(15, 23, 42, 0.58);
+    --lux-muted: rgba(15, 23, 42, 0.38);
+    --lux-primary: #2f6fed;
+    --lux-primary-2: #5b8cff;
+    --lux-success: #16a34a;
+    --lux-warning: #f59e0b;
+    --lux-danger: #ef4444;
+    --lux-shadow: 0 18px 50px rgba(15, 23, 42, 0.08);
+    --lux-shadow-soft: 0 10px 28px rgba(15, 23, 42, 0.06);
+    --lux-radius: 14px;
+    --lux-radius-sm: 12px;
+
+    padding: 18px 22px 24px;
+    background:
+      radial-gradient(1200px 420px at 20% 0%, rgba(47, 111, 237, 0.10), transparent 55%),
+      radial-gradient(900px 380px at 90% 10%, rgba(22, 163, 74, 0.06), transparent 55%),
+      linear-gradient(180deg, var(--lux-bg) 0%, #ffffff 58%);
   }
 
-  .search_form {
+  .filter-actions {
     display: flex;
+    align-items: center;
+    gap: 10px;
+    flex-wrap: nowrap;
+    margin-top: 0;
+    padding-top: 0;
+    border-top: none;
+    justify-content: flex-end;
+    flex: 0 0 auto;
+    white-space: nowrap;
+    align-self: flex-start;
+    padding-bottom: 0;
+    width: 290px;
+  }
+
+  .filter-actions :deep(.el-button) {
+    min-width: 78px;
+  }
+
+  .filter-actions :deep(.el-button.is-loading) {
+    min-width: 90px;
+  }
+
+  .filter-layout {
+    display: flex;
+    align-items: flex-start;
     justify-content: space-between;
-    align-items: center;
-    margin-bottom: 20px;
-    padding: 15px;
-    background-color: #f5f7fa;
-    border-radius: 8px;
+    gap: 14px;
   }
 
-  .statistics-overview {
-    margin-bottom: 30px;
+  .filter-form {
+    flex: 1 1 auto;
+    min-width: 0;
   }
 
-  .charts-container {
-    margin-bottom: 30px;
+  .w-260 {
+    width: 260px;
+    max-width: 100%;
   }
 
-  .table-section {
-    margin-bottom: 20px;
+  .lux-btn {
+    transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
+
+    &:hover {
+      transform: translateY(-1px);
+      box-shadow: 0 10px 22px rgba(15, 23, 42, 0.10);
+      filter: saturate(1.02);
+    }
+
+    &:active {
+      transform: translateY(0);
+      box-shadow: none;
+    }
   }
 
-  .section-header {
+  .filter-card {
+    margin-bottom: 16px;
+    border-radius: var(--lux-radius);
+    border-color: var(--lux-border);
+    background: var(--lux-card);
+    backdrop-filter: blur(10px);
+    box-shadow: var(--lux-shadow-soft);
+  }
+
+  /* 鏌ヨ鍖烘帶浠剁粺涓�鐨偆 */
+  :deep(.filter-card .el-form-item__label) {
+    color: rgba(15, 23, 42, 0.70);
+    font-weight: 650;
+  }
+
+  :deep(.filter-card .el-input__wrapper),
+  :deep(.filter-card .el-select__wrapper) {
+    border-radius: 12px;
+    box-shadow: none;
+    border: 1px solid rgba(15, 23, 42, 0.10);
+    background: rgba(255, 255, 255, 0.82);
+    transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
+  }
+
+  :deep(.filter-card .el-input__wrapper:hover),
+  :deep(.filter-card .el-select__wrapper:hover) {
+    border-color: rgba(47, 111, 237, 0.20);
+    transform: translateY(-1px);
+  }
+
+  :deep(.filter-card .is-focus .el-input__wrapper),
+  :deep(.filter-card .is-focus .el-select__wrapper) {
+    border-color: rgba(47, 111, 237, 0.30);
+    box-shadow: 0 0 0 3px rgba(47, 111, 237, 0.14);
+  }
+
+  :deep(.filter-card .el-range-editor.el-input__wrapper) {
+    border-radius: 12px;
+  }
+
+  .card-head {
     display: flex;
     align-items: center;
+    justify-content: space-between;
+    gap: 12px;
+  }
+
+  .card-head-left {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    min-width: 200px;
+  }
+
+  .card-head-right {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+  }
+
+  .card-icon {
+    color: var(--lux-primary);
+  }
+
+  .card-title {
+    font-weight: 760;
+    color: var(--lux-text);
+  }
+
+  .subtle {
+    color: var(--lux-subtle);
+    font-size: 12px;
+  }
+
+  .filter-form {
+    display: flex;
+    flex-wrap: nowrap;
+    gap: 10px 14px;
+    align-items: flex-end;
+    min-width: 0;
+  }
+
+  .filter-form :deep(.el-form-item) {
+    margin-right: 0;
+    margin-bottom: 0;
+    flex: 0 0 auto;
+  }
+
+  .filter-form :deep(.el-form-item__content) {
+    min-width: 0;
+  }
+
+  .filter-form :deep(.el-form-item:last-child) {
+    flex: 1 1 auto;
+  }
+
+  .filter-form :deep(.el-form-item:last-child .el-form-item__content) {
+    width: 100%;
+  }
+
+  .w-140 {
+    width: 140px;
+  }
+
+  .w-260 {
+    width: 260px;
+    max-width: 100%;
+  }
+
+  @media (max-width: 1280px) {
+    .filter-form {
+      flex-wrap: wrap;
+      align-items: flex-start;
+    }
+  }
+
+  .section-title {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    margin: 10px 0 12px;
+    font-size: 14px;
+    font-weight: 700;
+    color: var(--lux-text);
+  }
+
+  .section-icon {
+    color: var(--lux-primary);
+  }
+
+  .metrics {
+    margin-bottom: 10px;
+  }
+
+  .ui-icon {
+    font-size: 16px;
+    transition: transform 0.18s ease, opacity 0.18s ease;
+  }
+
+  .card-head-left:hover .ui-icon,
+  .section-title:hover .ui-icon {
+    transform: translateY(-1px);
+  }
+
+  .metric-card {
+    border-radius: var(--lux-radius-sm);
+    padding: 14px 14px 14px 16px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    border: 1px solid var(--lux-border);
+    background: rgba(255, 255, 255, 0.9);
+    backdrop-filter: blur(10px);
+    min-height: 78px;
+    transition: box-shadow 0.20s ease, transform 0.20s ease, border-color 0.20s ease;
+
+    &:hover {
+      transform: translateY(-1px);
+      box-shadow: var(--lux-shadow);
+      border-color: rgba(47, 111, 237, 0.18);
+    }
+  }
+
+  .metric-left {
+    display: flex;
+    flex-direction: column;
+    gap: 6px;
+  }
+
+  .metric-label {
+    color: var(--lux-subtle);
+    font-size: 12px;
+  }
+
+  .metric-value {
+    color: var(--lux-text);
+    font-size: 20px;
+    font-weight: 800;
+    letter-spacing: 0.2px;
+  }
+
+  .metric-unit {
+    font-size: 12px;
+    font-weight: 500;
+    color: var(--lux-muted);
+    margin-left: 4px;
+  }
+
+  .metric-right {
+    width: 42px;
+    height: 42px;
+    border-radius: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .metric-icon {
+    font-size: 20px;
+    color: #fff;
+  }
+
+  .metric-total {
+    background: linear-gradient(135deg, rgba(47, 111, 237, 0.12), rgba(47, 111, 237, 0.02));
+
+    .metric-right {
+      background: linear-gradient(135deg, var(--lux-primary), var(--lux-primary-2));
+    }
+  }
+
+  .metric-production {
+    background: linear-gradient(135deg, rgba(22, 163, 74, 0.12), rgba(22, 163, 74, 0.02));
+
+    .metric-right {
+      background: linear-gradient(135deg, var(--lux-success), rgba(22, 163, 74, 0.65));
+    }
+  }
+
+  .metric-office {
+    background: linear-gradient(135deg, rgba(144, 147, 153, 0.14), rgba(144, 147, 153, 0.03));
+
+    .metric-right {
+      background: linear-gradient(135deg, #909399, #b1b3b8);
+    }
+  }
+
+  .metric-avg {
+    background: linear-gradient(135deg, rgba(245, 158, 11, 0.12), rgba(245, 158, 11, 0.02));
+
+    .metric-right {
+      background: linear-gradient(135deg, var(--lux-warning), rgba(245, 158, 11, 0.62));
+    }
+  }
+
+  .charts {
+    margin-top: 6px;
+    margin-bottom: 12px;
+  }
+
+  .charts-row {
+    margin-top: 16px;
+  }
+
+  .kpi-strip {
+    display: grid;
+    grid-template-columns: repeat(4, minmax(0, 1fr));
+    gap: 12px;
+    padding: 4px 4px 10px;
+  }
+
+  .kpi-strip.pulse {
+    animation: kpiPulse 520ms cubic-bezier(0.16, 1, 0.3, 1);
+  }
+
+  @keyframes kpiPulse {
+    0% {
+      filter: saturate(1.02);
+    }
+    35% {
+      filter: saturate(1.10);
+    }
+    100% {
+      filter: saturate(1.02);
+    }
+  }
+
+  .kpi-item {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 12px;
+    padding: 12px 12px 12px 14px;
+    border-radius: 14px;
+    border: 1px solid rgba(15, 23, 42, 0.08);
+    background: rgba(255, 255, 255, 0.86);
+    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
+    min-height: 68px;
+    text-align: left;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+    outline: none;
+    transform: translateZ(0);
+  }
+
+  .kpi-item:hover {
+    transform: translateY(-1px);
+    box-shadow: 0 16px 40px rgba(15, 23, 42, 0.10);
+    border-color: rgba(47, 111, 237, 0.18);
+  }
+
+  .kpi-item::before {
+    content: "";
+    position: absolute;
+    inset: 0;
+    background:
+      radial-gradient(520px 140px at 20% 0%, rgba(255, 255, 255, 0.65), transparent 60%),
+      radial-gradient(620px 180px at 90% 40%, rgba(47, 111, 237, 0.10), transparent 55%);
+    opacity: 0;
+    transform: translateX(-8%) translateY(-2%);
+    transition: opacity 0.22s ease, transform 0.42s cubic-bezier(0.16, 1, 0.3, 1);
+    pointer-events: none;
+  }
+
+  .kpi-item:hover::before {
+    opacity: 1;
+    transform: translateX(0) translateY(0);
+  }
+
+  .kpi-item::after {
+    content: "";
+    position: absolute;
+    inset: -1px;
+    border-radius: 15px;
+    background: linear-gradient(
+      135deg,
+      rgba(47, 111, 237, 0.18),
+      rgba(255, 255, 255, 0.0),
+      rgba(22, 163, 74, 0.14)
+    );
+    opacity: 0;
+    transition: opacity 0.22s ease;
+    pointer-events: none;
+  }
+
+  .kpi-item:hover::after {
+    opacity: 1;
+  }
+
+  .kpi-item:active {
+    transform: translateY(0);
+    box-shadow: 0 10px 22px rgba(15, 23, 42, 0.08);
+  }
+
+  .kpi-item:focus-visible {
+    box-shadow:
+      0 16px 44px rgba(15, 23, 42, 0.10),
+      0 0 0 3px rgba(47, 111, 237, 0.18);
+    border-color: rgba(47, 111, 237, 0.22);
+  }
+
+  .kpi-item.selected {
+    border-color: rgba(47, 111, 237, 0.22);
+    box-shadow:
+      0 16px 44px rgba(15, 23, 42, 0.10),
+      inset 0 0 0 1px rgba(47, 111, 237, 0.10);
+  }
+
+  .kpi-left {
+    display: flex;
+    flex-direction: column;
+    gap: 6px;
+    min-width: 0;
+    position: relative;
+    z-index: 1;
+  }
+
+  .kpi-label {
+    font-size: 12px;
+    color: var(--lux-subtle);
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+
+  .kpi-value {
     font-size: 18px;
-    font-weight: bold;
-    color: #303133;
-    margin-bottom: 15px;
-    padding-left: 10px;
-    border-left: 3px solid #409eff;
-
-    .header-icon {
-      margin-right: 8px;
-      color: #409eff;
-    }
+    font-weight: 850;
+    letter-spacing: 0.2px;
+    color: var(--lux-text);
+    line-height: 1.1;
   }
 
-  .overview-card {
+  .kpi-meta {
     display: flex;
     align-items: center;
-    padding: 20px;
-    border-radius: 4px;
-    background: #fff;
-    border: 1px solid #ebeef5;
+    gap: 8px;
+    margin-top: 2px;
+    min-height: 22px;
+  }
 
-    &.blue-card {
-      background-color: #ecf5ff;
-    }
+  .kpi-meta.muted {
+    font-size: 11px;
+    color: var(--lux-muted);
+  }
 
-    &.green-card {
-      background-color: #f0f9eb;
-    }
+  .kpi-chip {
+    font-size: 11px;
+    font-weight: 700;
+    padding: 2px 8px;
+    border-radius: 999px;
+    border: 1px solid rgba(15, 23, 42, 0.08);
+    background: rgba(255, 255, 255, 0.72);
+    color: rgba(15, 23, 42, 0.72);
+  }
 
-    &.purple-card {
-      background-color: #f3f0ff;
-    }
+  .kpi-chip.up {
+    border-color: rgba(22, 163, 74, 0.20);
+    color: rgba(22, 163, 74, 0.96);
+    background: rgba(22, 163, 74, 0.06);
+  }
 
-    &.gray-card {
-      background-color: #f5f7fa;
-    }
+  .kpi-chip.down {
+    border-color: rgba(239, 68, 68, 0.20);
+    color: rgba(239, 68, 68, 0.96);
+    background: rgba(239, 68, 68, 0.06);
+  }
 
-    .overview-icon {
-      width: 40px;
-      height: 40px;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      border-radius: 50%;
-      margin-right: 15px;
+  .kpi-spark {
+    width: 72px;
+    height: 22px;
+    opacity: 0.9;
+    filter: drop-shadow(0 8px 16px rgba(15, 23, 42, 0.10));
+  }
 
-      &.blue-icon {
-        background-color: #409eff;
-        color: #fff;
-      }
+  .kpi-actions {
+    position: absolute;
+    top: 10px;
+    right: 10px;
+    display: flex;
+    gap: 6px;
+    opacity: 0;
+    transform: translateY(-2px);
+    pointer-events: none;
+    transition: opacity 0.16s ease, transform 0.16s ease;
+    z-index: 2;
+  }
 
-      &.green-icon {
-        background-color: #67c23a;
-        color: #fff;
-      }
+  .kpi-item:hover .kpi-actions {
+    opacity: 1;
+    transform: translateY(0);
+    pointer-events: auto;
+  }
 
-      &.purple-icon {
-        background-color: #909399;
-        color: #fff;
-      }
+  .kpi-action {
+    font-size: 11px;
+    font-weight: 650;
+    padding: 4px 8px;
+    border-radius: 999px;
+    border: 1px solid rgba(15, 23, 42, 0.10);
+    background: rgba(255, 255, 255, 0.78);
+    color: rgba(15, 23, 42, 0.78);
+    cursor: pointer;
+    transition: background-color 0.16s ease, border-color 0.16s ease, transform 0.16s ease;
+  }
 
-      &.gray-icon {
-        background-color: #909399;
-        color: #fff;
-      }
+  .kpi-action:hover {
+    background: rgba(47, 111, 237, 0.08);
+    border-color: rgba(47, 111, 237, 0.22);
+    transform: translateY(-1px);
+  }
 
-      .el-icon {
-        font-size: 20px;
-      }
-    }
+  .kpi-action:active {
+    transform: translateY(0);
+  }
 
-    .overview-info {
-      flex: 1;
+  .chart-wrap {
+    border-radius: 12px;
+    overflow: hidden;
+    position: relative;
+  }
 
-      .overview-label {
-        font-size: 14px;
-        color: #606266;
-        margin-bottom: 5px;
-      }
+  .chart-empty {
+    height: 240px;
+    display: grid;
+    place-items: center;
+    background: rgba(255, 255, 255, 0.70);
+    border-radius: 12px;
+    position: absolute;
+    inset: 0;
+  }
 
-      .overview-value {
-        font-size: 20px;
-        font-weight: bold;
-        color: #303133;
+  :deep(.big-chart-dialog .el-dialog) {
+    border-radius: 16px;
+    overflow: hidden;
+  }
 
-        .unit {
-          font-size: 12px;
-          font-weight: normal;
-          color: #909399;
-        }
-      }
-    }
+  :deep(.big-chart-dialog .el-dialog__header) {
+    padding: 14px 16px;
+    background:
+      radial-gradient(900px 240px at 10% 0%, rgba(47, 111, 237, 0.10), transparent 55%),
+      rgba(255, 255, 255, 0.92);
+    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
+  }
+
+  :deep(.big-chart-dialog .el-dialog__body) {
+    padding: 14px 16px 8px;
+    background: rgba(255, 255, 255, 0.92);
+  }
+
+  :deep(.big-chart-dialog .el-dialog__footer) {
+    padding: 10px 16px 14px;
+    background: rgba(255, 255, 255, 0.92);
+    border-top: 1px solid rgba(15, 23, 42, 0.06);
+  }
+
+  .big-chart-canvas {
+    width: 100%;
+    height: min(74vh, 760px);
+    border-radius: 14px;
+    border: 1px solid rgba(15, 23, 42, 0.08);
+    background: #ffffff;
+  }
+
+  .big-chart-footer {
+    display: flex;
+    justify-content: flex-end;
+    gap: 10px;
+  }
+
+  .chart-tools {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    opacity: 0.0;
+    transform: translateY(-2px);
+    transition: opacity 0.16s ease, transform 0.16s ease;
+  }
+
+  .chart-card:hover .chart-tools {
+    opacity: 1;
+    transform: translateY(0);
+  }
+
+  .chart-card:focus-within .chart-tools {
+    opacity: 1;
+    transform: translateY(0);
+  }
+
+  :deep(.chart-wrap .el-loading-mask) {
+    border-radius: 12px;
+    backdrop-filter: blur(2px);
+    background-color: rgba(255, 255, 255, 0.55);
+  }
+
+  .chart-tool {
+    font-size: 11px;
+    font-weight: 650;
+    padding: 4px 8px;
+    border-radius: 10px;
+    border: 1px solid rgba(15, 23, 42, 0.10);
+    background: rgba(255, 255, 255, 0.78);
+    color: rgba(15, 23, 42, 0.78);
+    cursor: pointer;
+    transition: background-color 0.16s ease, border-color 0.16s ease, transform 0.16s ease;
+  }
+
+  .chart-tool:hover {
+    background: rgba(47, 111, 237, 0.08);
+    border-color: rgba(47, 111, 237, 0.22);
+    transform: translateY(-1px);
+  }
+
+  .kpi-unit {
+    font-size: 12px;
+    font-weight: 600;
+    color: var(--lux-muted);
+    margin-left: 4px;
+  }
+
+  .kpi-icon {
+    width: 38px;
+    height: 38px;
+    border-radius: 12px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #fff;
+    flex: 0 0 auto;
+    position: relative;
+    z-index: 1;
+    transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1), filter 0.28s ease;
+  }
+
+  .kpi-item:hover .kpi-icon {
+    transform: translateY(-1px) rotate(-2deg);
+    filter: saturate(1.06);
+  }
+
+  .kpi-total {
+    background: linear-gradient(135deg, rgba(47, 111, 237, 0.10), rgba(255, 255, 255, 0.86));
+  }
+  .kpi-total .kpi-icon {
+    background: linear-gradient(135deg, var(--lux-primary), var(--lux-primary-2));
+  }
+
+  .kpi-production {
+    background: linear-gradient(135deg, rgba(22, 163, 74, 0.10), rgba(255, 255, 255, 0.86));
+  }
+  .kpi-production .kpi-icon {
+    background: linear-gradient(135deg, var(--lux-success), rgba(22, 163, 74, 0.65));
+  }
+
+  .kpi-office {
+    background: linear-gradient(135deg, rgba(100, 116, 139, 0.10), rgba(255, 255, 255, 0.86));
+  }
+  .kpi-office .kpi-icon {
+    background: linear-gradient(135deg, #64748b, #94a3b8);
+  }
+
+  .kpi-avg {
+    background: linear-gradient(135deg, rgba(245, 158, 11, 0.10), rgba(255, 255, 255, 0.86));
+  }
+  .kpi-avg .kpi-icon {
+    background: linear-gradient(135deg, var(--lux-warning), rgba(245, 158, 11, 0.62));
+  }
+
+  .panel-card {
+    margin-top: 0;
+    border-radius: var(--lux-radius);
+    border-color: var(--lux-border);
+    background: var(--lux-card);
+    backdrop-filter: blur(10px);
+    box-shadow: var(--lux-shadow-soft);
+    padding-bottom: 8px;
+    overflow: hidden;
+  }
+
+  .panel-head {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 12px;
+    padding: 8px 4px 6px;
+  }
+
+  .segmented {
+    position: relative;
+    display: grid;
+    grid-template-columns: 1fr 1fr;
+    padding: 4px;
+    border-radius: 14px;
+    border: 1px solid rgba(15, 23, 42, 0.08);
+    background: rgba(15, 23, 42, 0.03);
+    overflow: hidden;
+    flex: 1 1 auto;
+    min-width: 0;
+  }
+
+  .segmented::after {
+    content: "";
+    position: absolute;
+    top: 10px;
+    bottom: 10px;
+    left: 50%;
+    width: 2px;
+    border-radius: 999px;
+    background: linear-gradient(
+      180deg,
+      rgba(15, 23, 42, 0.06),
+      rgba(15, 23, 42, 0.12),
+      rgba(15, 23, 42, 0.06)
+    );
+    transform: translateX(-0.5px);
+    pointer-events: none;
+    z-index: 0;
+  }
+
+  .segmented.no-active {
+    background:
+      radial-gradient(900px 220px at 20% 0%, rgba(47, 111, 237, 0.06), transparent 55%),
+      rgba(15, 23, 42, 0.03);
+    border-color: rgba(15, 23, 42, 0.10);
+  }
+
+  .segmented-indicator {
+    position: absolute;
+    top: 4px;
+    left: 4px;
+    width: calc(50% - 4px);
+    height: calc(100% - 8px);
+    border-radius: 13px;
+    background: linear-gradient(180deg, rgba(47, 111, 237, 0.10), rgba(255, 255, 255, 0.82));
+    border: 1px solid rgba(47, 111, 237, 0.18);
+    box-shadow:
+      0 14px 30px rgba(15, 23, 42, 0.10),
+      0 1px 0 rgba(255, 255, 255, 0.65) inset;
+    transition:
+      transform 0.36s cubic-bezier(0.16, 1, 0.3, 1),
+      opacity 0.20s ease;
+    pointer-events: none;
+    will-change: transform;
+    z-index: 1;
+  }
+
+  .segmented-indicator.hidden {
+    opacity: 0;
+  }
+
+  .segmented-item {
+    position: relative;
+    z-index: 2;
+    width: 100%;
+    display: flex;
+    flex-direction: column;
+    gap: 2px;
+    text-align: left;
+    padding: 10px 12px;
+    border-radius: 12px;
+    border: 1px solid transparent;
+    background: transparent;
+    cursor: pointer;
+    transition: transform 0.16s ease, color 0.16s ease, background-color 0.16s ease;
+  }
+
+  .segmented-item:hover {
+    transform: translateY(-1px);
+  }
+
+  .segmented-item:active {
+    transform: translateY(0);
+  }
+
+  .seg-title {
+    font-size: 13px;
+    font-weight: 780;
+    color: rgba(15, 23, 42, 0.86);
+    letter-spacing: 0.2px;
+  }
+
+  .seg-sub {
+    font-size: 11px;
+    color: rgba(15, 23, 42, 0.46);
+  }
+
+  .segmented-item.active .seg-title {
+    color: var(--lux-text);
+  }
+
+  .segmented-item.active .seg-sub {
+    color: rgba(15, 23, 42, 0.56);
+  }
+
+  .panel-body {
+    padding-top: 4px;
+  }
+
+  .core-kpi {
+    font-size: 12px;
+    font-weight: 650;
+    color: rgba(15, 23, 42, 0.78);
+    padding: 2px 10px;
+    border-radius: 999px;
+    background: rgba(15, 23, 42, 0.04);
+    border: 1px solid rgba(15, 23, 42, 0.06);
   }
 
   .chart-card {
-    background: #fff;
-    border-radius: 4px;
-    border: 1px solid #ebeef5;
-    padding: 20px;
+    border-radius: var(--lux-radius);
+    border-color: var(--lux-border);
+    background: var(--lux-card);
+    backdrop-filter: blur(10px);
+    box-shadow: var(--lux-shadow-soft);
+    transition: box-shadow 0.22s ease, transform 0.22s ease, border-color 0.22s ease;
 
-    .chart-title {
-      font-size: 14px;
-      font-weight: bold;
-      color: #303133;
-      margin-bottom: 15px;
-      padding-bottom: 10px;
-      border-bottom: 1px solid #ebeef5;
+    &:hover {
+      transform: translateY(-2px);
+      box-shadow: var(--lux-shadow);
+      border-color: rgba(47, 111, 237, 0.16);
     }
+  }
 
-    .chart-content {
-      height: 300px;
+  .chart-head {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    gap: 12px;
+  }
+
+  .chart-title {
+    font-weight: 700;
+    color: var(--lux-text);
+  }
+
+  .chart-content {
+    height: 240px;
+  }
+
+  .table-card {
+    border-radius: var(--lux-radius);
+    border-color: var(--lux-border);
+    background: var(--lux-card);
+    backdrop-filter: blur(10px);
+    box-shadow: var(--lux-shadow-soft);
+    transition: box-shadow 0.22s ease, transform 0.22s ease, border-color 0.22s ease;
+
+    &:hover {
+      transform: translateY(-1px);
+      box-shadow: var(--lux-shadow);
+      border-color: rgba(15, 23, 42, 0.10);
     }
+  }
+
+  .data-table {
+    width: 100%;
   }
 
   .consumption-value {
     font-weight: bold;
-    color: #409eff;
+    color: var(--lux-primary);
   }
 
   .consumption-unit {
     font-size: 12px;
-    color: #909399;
+    color: var(--lux-muted);
     margin-left: 2px;
   }
 
   .price-value {
     font-weight: bold;
-    color: #67c23a;
+    color: var(--lux-success);
   }
 
   .cost-value {
     font-weight: bold;
-    color: #f56c6c;
+    color: var(--lux-danger);
   }
 
   .pagination-container {
     display: flex;
     justify-content: flex-end;
+    padding-top: 12px;
+  }
+
+  /* Element Plus 娣卞害鏍峰紡锛氬崱鐗囧紡琛ㄦ牸璐ㄦ劅 */
+  :deep(.lux-table) {
+    border-radius: 12px;
+    overflow: hidden;
+    font-variant-numeric: tabular-nums;
+  }
+
+  :deep(.lux-table .el-table__inner-wrapper::before) {
+    height: 0;
+  }
+
+  :deep(.lux-table .el-table__header-wrapper) {
+    background:
+      linear-gradient(180deg, rgba(15, 23, 42, 0.04) 0%, rgba(15, 23, 42, 0.02) 100%);
+  }
+
+  :deep(.lux-table th.el-table__cell) {
+    background: transparent;
+    color: rgba(15, 23, 42, 0.78);
+    font-weight: 700;
+    letter-spacing: 0.2px;
+    border-bottom: 1px solid rgba(15, 23, 42, 0.08);
+  }
+
+  :deep(.lux-table td.el-table__cell) {
+    border-bottom: 1px solid rgba(15, 23, 42, 0.06);
+  }
+
+  :deep(.lux-table .el-table__row) {
+    transition: background-color 0.18s ease;
+  }
+
+  :deep(.lux-table .el-table__row:hover > td.el-table__cell) {
+    background-color: rgba(47, 111, 237, 0.06) !important;
+  }
+
+  :deep(.lux-table .el-table__row:hover) {
+    box-shadow: inset 3px 0 0 rgba(47, 111, 237, 0.30);
+  }
+
+  :deep(.lux-table .el-table__body tr.el-table__row--striped > td.el-table__cell) {
+    background: rgba(15, 23, 42, 0.018);
+  }
+
+  :deep(.el-pagination) {
+    --el-pagination-button-color: rgba(15, 23, 42, 0.72);
+    --el-pagination-button-bg-color: transparent;
+    --el-pagination-hover-color: var(--lux-primary);
+  }
+
+  :deep(.el-pagination .btn-next),
+  :deep(.el-pagination .btn-prev) {
+    border-radius: 10px;
+    transition: background-color 0.18s ease, transform 0.18s ease;
+  }
+
+  :deep(.el-pagination .btn-next:hover),
+  :deep(.el-pagination .btn-prev:hover) {
+    background-color: rgba(47, 111, 237, 0.06);
+    transform: translateY(-1px);
+  }
+
+  /* 鍝嶅簲寮� */
+  @media (max-width: 960px) {
+    .filter-form {
+      flex-direction: column;
+      align-items: flex-start;
+    }
+
+    .filter-actions {
+      justify-content: flex-start;
+    }
+
+    .kpi-strip {
+      grid-template-columns: repeat(2, minmax(0, 1fr));
+    }
+
+    .panel-head {
+      flex-wrap: wrap;
+    }
+  }
+
+  /* 鎶樺彔鍔ㄧ敾 */
+  .lux-collapse-enter-active,
+  .lux-collapse-leave-active {
+    transition: max-height 0.22s ease, opacity 0.18s ease;
+    overflow: hidden;
+  }
+
+  .lux-collapse-enter-from,
+  .lux-collapse-leave-to {
+    max-height: 0;
+    opacity: 0;
+  }
+
+  .lux-collapse-enter-to,
+  .lux-collapse-leave-from {
+    max-height: 600px;
+    opacity: 1;
   }
 </style>
\ No newline at end of file

--
Gitblit v1.9.3