From 0878762ff3d0796e5fcb22fc38103a3079d6ca24 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 18 三月 2026 15:06:40 +0800
Subject: [PATCH] 1

---
 src/views/costAccounting/energyCosts/index.vue | 4755 ++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 2,419 insertions(+), 2,336 deletions(-)

diff --git a/src/views/costAccounting/energyCosts/index.vue b/src/views/costAccounting/energyCosts/index.vue
index 5488bcc..655e145 100644
--- a/src/views/costAccounting/energyCosts/index.vue
+++ b/src/views/costAccounting/energyCosts/index.vue
@@ -2,8 +2,7 @@
 <template>
   <div class="energy-cost-page">
     <!-- 绛涢�夊尯鍩� -->
-    <el-card class="filter-card"
-             shadow="never">
+    <el-card class="filter-card" shadow="never">
       <template #header>
         <div class="card-head">
           <div class="card-head-left">
@@ -13,9 +12,11 @@
             <span class="card-title">鏌ヨ鏉′欢</span>
           </div>
           <div class="card-head-right">
-            <el-radio-group v-model="statisticsType"
-                            size="small"
-                            @change="handleTypeChange">
+            <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>
@@ -24,9 +25,7 @@
       </template>
 
       <div class="filter-layout">
-        <el-form :model="searchForm"
-                 :inline="true"
-                 class="filter-form">
+        <el-form :model="searchForm" :inline="true" class="filter-form">
           <!-- <el-form-item label="鑳借�楃被鍨�">
             <el-select v-model="searchForm.energyType"
                        placeholder="鍏ㄩ儴"
@@ -44,80 +43,94 @@
             </el-select>
           </el-form-item> -->
           <el-form-item label="鑳借�楃敤閫�">
-            <el-select v-model="searchForm.type"
-                       placeholder=""
-                       clearable
-                       class="w-140"
-                       @change="handleQuery">
-              <el-option label="鐢熶骇"
-                         value="鐢熶骇" />
-              <el-option label="鍔炲叕"
-                         value="鍔炲叕" />
+            <el-select
+              v-model="searchForm.type"
+              placeholder=""
+              clearable
+              class="w-140"
+              @change="handleQuery"
+            >
+              <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-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>
+          <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>
     </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')">
+      <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-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" />
+                <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>
@@ -126,36 +139,51 @@
                 <Money />
               </el-icon>
             </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 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>
           </button>
-          <button class="kpi-item kpi-production"
-                  type="button"
-                  :class="{ selected: selectedKpi === 'production' }"
-                  @click="handleKpiClick('production')">
+          <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-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" />
+                <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>
@@ -164,36 +192,51 @@
                 <DataLine />
               </el-icon>
             </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 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>
           </button>
-          <button class="kpi-item kpi-office"
-                  type="button"
-                  :class="{ selected: selectedKpi === 'office' }"
-                  @click="handleKpiClick('office')">
+          <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-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" />
+                <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>
@@ -202,22 +245,36 @@
                 <TrendCharts />
               </el-icon>
             </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 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>
           </button>
-          <button class="kpi-item kpi-avg"
-                  type="button"
-                  @click="handleKpiClick('all')">
+          <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-value">
+                楼{{ formatMoney(animatedOverview.avgCost) }}
+                <span class="kpi-unit"
+                  >/{{ statisticsType === "day" ? "鏃�" : "鏈�" }}</span
+                >
+              </div>
               <div class="kpi-meta muted">鍩轰簬褰撳墠绛涢�変笌鏄庣粏缁熻</div>
             </div>
             <div class="kpi-icon">
@@ -225,41 +282,56 @@
                 <Histogram />
               </el-icon>
             </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 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')">
+          <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')">
+            <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>
@@ -267,66 +339,81 @@
         </div>
 
         <transition name="lux-collapse">
-          <div v-show="chartPanel === 'core'"
-               class="panel-body">
+          <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">
+              <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 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">
+                  <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">
+              <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 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">
+                  <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>
@@ -337,67 +424,81 @@
         </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">
+          <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 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">
+                  <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">
+              <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 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">
+                  <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>
@@ -409,30 +510,36 @@
       </el-card>
     </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>
+    <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>
+          <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>
 
     <!-- 鏁版嵁琛ㄦ牸 -->
-    <el-card class="table-card"
-             shadow="never">
+    <el-card class="table-card" shadow="never">
       <div ref="tableAnchor"></div>
       <template #header>
         <div class="card-head">
@@ -448,2214 +555,2190 @@
         </div>
       </template>
 
-      <el-table :data="displayTableData"
-                v-loading="tableLoading"
-                stripe
-                :header-cell-style="{ height: '44px' }"
-                class="data-table lux-table"
-                @sort-change="handleSortChange">
+      <el-table
+        :data="displayTableData"
+        v-loading="tableLoading"
+        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"
-                         sortable="custom" />
-        <el-table-column prop="energyType"
-                         label="鑳借�楃被鍨�"
-                         width="100"
-                         align="center"
-                         :filters="energyTypeFilters"
-                         :filter-method="filterEnergyType"
-                         filter-placement="bottom-end">
+        <el-table-column type="index" label="搴忓彿" width="60" align="center" />
+        <el-table-column
+          prop="timePeriod"
+          :label="timeColumnLabel"
+          align="center"
+          sortable="custom"
+        />
+        <el-table-column
+          prop="energyType"
+          label="鑳借�楃被鍨�"
+          width="100"
+          align="center"
+          :filters="energyTypeFilters"
+          :filter-method="filterEnergyType"
+          filter-placement="bottom-end"
+        >
           <template #default="scope">
             <el-tag :type="getEnergyTypeType(scope.row.energyType)">
               {{ scope.row.energyType }}
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="type"
-                         label="鑳借�楃敤閫�"
-                         width="100"
-                         align="center"
-                         :filters="energyPurposeFilters"
-                         :filter-method="filterEnergyPurpose"
-                         filter-placement="bottom-end">
+        <el-table-column
+          prop="type"
+          label="鑳借�楃敤閫�"
+          width="100"
+          align="center"
+          :filters="energyPurposeFilters"
+          :filter-method="filterEnergyPurpose"
+          filter-placement="bottom-end"
+        >
           <template #default="scope">
             <el-tag :type="scope.row.type === '鐢熶骇' ? 'primary' : 'info'">
               {{ scope.row.type }}
             </el-tag>
           </template>
         </el-table-column>
-        <el-table-column prop="consumption"
-                         label="鐢ㄩ噺"
-                         align="right">
+        <el-table-column prop="consumption" label="鐢ㄩ噺" align="right">
           <template #default="scope">
-            <span class="consumption-value">{{ formatNumber(scope.row.consumption, 2) }}</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"
-                         sortable="custom">
+        <el-table-column
+          prop="price"
+          label="鍗曚环(鍏�)"
+          align="right"
+          sortable="custom"
+        >
           <template #default="scope">
-            <span class="price-value">{{ formatNumber(scope.row.price, 2) }}</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">
+        <el-table-column
+          prop="cost"
+          label="鎴愭湰(鍏�)"
+          align="right"
+          sortable="custom"
+          fixed="right"
+        >
           <template #default="scope">
-            <span class="cost-value">楼{{ formatNumber(scope.row.cost, 2) }}</span>
+            <span class="cost-value"
+              >楼{{ formatNumber(scope.row.cost, 2) }}</span
+            >
           </template>
         </el-table-column>
       </el-table>
 
       <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" />
+        <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, onUnmounted, computed, nextTick, watch } from "vue";
-  import { ElMessage } from "element-plus";
-  import {
-    Money,
-    DataLine,
-    TrendCharts,
-    Histogram,
-    List,
-    ArrowDown,
-  } from "@element-plus/icons-vue";
-  import * as echarts from "echarts";
-  // import { energyCostStatistics } from "@/api/costAccounting/energyCosts";
-  import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
-  // 缁熻缁村害锛歞ay-鎸夋棩锛宮onth-鎸夋湀
-  const statisticsType = ref("day");
+import {
+  ref,
+  reactive,
+  onMounted,
+  onUnmounted,
+  computed,
+  nextTick,
+  watch,
+} from "vue";
+import { ElMessage } from "element-plus";
+import {
+  Money,
+  DataLine,
+  TrendCharts,
+  Histogram,
+  List,
+  ArrowDown,
+} from "@element-plus/icons-vue";
+import * as echarts from "echarts";
+// import { energyCostStatistics } from "@/api/costAccounting/energyCosts";
+import { energyConsumptionDetailStatistics } from "@/api/energyManagement/energyType";
+// 缁熻缁村害锛歞ay-鎸夋棩锛宮onth-鎸夋湀
+const statisticsType = ref("day");
 
-  // 鎼滅储琛ㄥ崟
-  const searchForm = reactive({
-    // energyType: "",
-    type: "",
-    dateRange: (() => {
-      // 榛樿鏈�杩�7澶�
-      const end = new Date();
-      const start = new Date();
-      start.setDate(start.getDate() - 6);
-      return [start.toISOString().split("T")[0], end.toISOString().split("T")[0]];
-    })(),
-    monthRange: (() => {
-      // 榛樿鏈�杩�3涓湀
-      const end = new Date();
-      const start = new Date();
-      start.setMonth(start.getMonth() - 2);
-      return [start.toISOString().slice(0, 7), end.toISOString().slice(0, 7)];
-    })(),
+// 鎼滅储琛ㄥ崟
+const searchForm = reactive({
+  // energyType: "",
+  type: "",
+  dateRange: (() => {
+    // 榛樿鏈�杩�7澶�
+    const end = new Date();
+    const start = new Date();
+    start.setDate(start.getDate() - 6);
+    return [start.toISOString().split("T")[0], end.toISOString().split("T")[0]];
+  })(),
+  monthRange: (() => {
+    // 榛樿鏈�杩�3涓湀
+    const end = new Date();
+    const start = new Date();
+    start.setMonth(start.getMonth() - 2);
+    return [start.toISOString().slice(0, 7), end.toISOString().slice(0, 7)];
+  })(),
+});
+
+// 鏃堕棿鍒楁爣绛�
+const timeColumnLabel = computed(() => {
+  return statisticsType.value === "day" ? "鏃ユ湡" : "鏈堜唤";
+});
+
+// 缁熻姒傝
+const overview = reactive({
+  totalCost: "0.00",
+  productionCost: "0.00",
+  officeCost: "0.00",
+  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 timeColumnLabel = computed(() => {
-    return statisticsType.value === "day" ? "鏃ユ湡" : "鏈堜唤";
+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 overview = reactive({
-    totalCost: "0.00",
-    productionCost: "0.00",
-    officeCost: "0.00",
-    avgCost: "0.00",
-  });
+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 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 tick = (now) => {
+    const p = Math.min(1, (now - start) / duration);
+    animatedOverview[key] = from + (to - from) * easeOut(p);
+    if (p < 1) requestAnimationFrame(tick);
   };
+  requestAnimationFrame(tick);
+};
 
-  const formatNumber = (v, digits = 2) => {
-    const n = Number.parseFloat(v);
-    if (!Number.isFinite(n)) return "--";
-    return n.toLocaleString("zh-CN", { minimumFractionDigits: digits, maximumFractionDigits: digits });
-  };
+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 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 tableData = ref([]);
+const tableLoading = ref(false);
+const hasTableData = computed(
+  () => Array.isArray(tableData.value) && tableData.value.length > 0
+);
+const queryPulse = ref(false);
 
-    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 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?.type === "鐢熶骇") bucket.production += cost;
+    if (r?.type === "鍔炲叕") 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 tableData = ref([]);
-  const tableLoading = ref(false);
-  const hasTableData = computed(() => Array.isArray(tableData.value) && tableData.value.length > 0);
-  const queryPulse = ref(false);
+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 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?.type === "鐢熶骇") bucket.production += cost;
-      if (r?.type === "鍔炲叕") 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 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.type = "";
+  if (key === "production") searchForm.type = "鐢熶骇";
+  if (key === "office") searchForm.type = "鍔炲叕";
+  page.current = 1;
+  handleQuery();
+};
+
+const viewKpiDetails = (key) => {
+  handleKpiClick(key);
+  nextTick(() => {
+    const el = tableAnchor.value;
+    if (el?.scrollIntoView)
+      el.scrollIntoView({ behavior: "smooth", block: "start" });
   });
+};
 
-  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 copyKpi = async (field) => {
+  const map = {
+    totalCost: animatedOverview.totalCost,
+    productionCost: animatedOverview.productionCost,
+    officeCost: animatedOverview.officeCost,
+    avgCost: animatedOverview.avgCost,
   };
-
-  const handleKpiClick = key => {
-    selectedKpi.value = key;
-    if (key === "all") searchForm.type = "";
-    if (key === "production") searchForm.type = "鐢熶骇";
-    if (key === "office") searchForm.type = "鍔炲叕";
-    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 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 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 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.type ? `_${searchForm.type}` : "";
-      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 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.type ? `_${searchForm.type}` : "";
+    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 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;
+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;
-  };
+    bigChartInstance = echarts.init(el);
+    const opt = src.getOption();
+    bigChartInstance.setOption(opt, true);
+    bigChartInstance.resize();
+  });
+};
 
-  const handleBigChartResize = () => {
-    try {
-      bigChartInstance?.resize?.();
-    } catch (e) {
-      // ignore
+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;
     }
-  };
-  // 琛ㄦ牸鎺掑簭锛堝墠绔帓搴忥細浠呭奖鍝嶅綋鍓嶉〉鏁版嵁锛岄伩鍏嶇牬鍧忓悗绔垎椤靛崗璁級
-  const sortState = reactive({
-    prop: "",
-    order: "",
+
+    return (
+      String(av ?? "").localeCompare(String(bv ?? ""), "zh-Hans-CN") * direction
+    );
   });
+});
 
-  const handleSortChange = ({ prop, order }) => {
-    sortState.prop = prop || "";
-    sortState.order = order || "";
-  };
+const energyTypeFilters = [
+  { text: "姘�", value: "姘�" },
+  { text: "鐢�", value: "鐢�" },
+  { text: "姘�", value: "姘�" },
+];
+const energyPurposeFilters = [
+  { text: "鐢熶骇", value: "鐢熶骇" },
+  { text: "鍔炲叕", value: "鍔炲叕" },
+];
 
-  const displayTableData = computed(() => {
-    const data = Array.isArray(tableData.value) ? [...tableData.value] : [];
-    if (!sortState.prop || !sortState.order) return data;
+const filterEnergyType = (value, row) => row.energyType === value;
+const filterEnergyPurpose = (value, row) => row.type === value;
 
-    const prop = sortState.prop;
-    const direction = sortState.order === "ascending" ? 1 : -1;
-    const numFields = new Set(["price", "cost", "consumption"]);
+// 鍒嗛〉
+const page = reactive({
+  current: 1,
+  size: 10,
+  total: 0,
+});
 
-    return data.sort((a, b) => {
-      const av = a?.[prop];
-      const bv = b?.[prop];
+// 鍥捐〃寮曠敤
+const costChart = ref(null);
+const typeChart = ref(null);
+const purposeChart = ref(null);
+const priceChart = ref(null);
 
-      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;
-      }
+const costChartWrap = ref(null);
+const typeChartWrap = ref(null);
+const purposeChartWrap = ref(null);
+const priceChartWrap = ref(null);
 
-      return String(av ?? "").localeCompare(String(bv ?? ""), "zh-Hans-CN") * direction;
-    });
+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 energyTypeFilters = [
-    { text: "姘�", value: "姘�" },
-    { text: "鐢�", value: "鐢�" },
-    { text: "姘�", value: "姘�" },
-  ];
-  const energyPurposeFilters = [
-    { text: "鐢熶骇", value: "鐢熶骇" },
-    { text: "鍔炲叕", value: "鍔炲叕" },
-  ];
+const handleChartPanelClick = (key) => {
+  chartPanel.value = chartPanel.value === key ? "none" : key;
+};
 
-  const filterEnergyType = (value, row) => row.energyType === value;
-  const filterEnergyPurpose = (value, row) => row.type === value;
+const panelIndicatorStyle = computed(() => {
+  const x = chartPanel.value === "advanced" ? "calc(100% + 4px)" : "0";
+  return { transform: `translateX(${x})` };
+});
 
-  // 鍒嗛〉
-  const page = reactive({
-    current: 1,
-    size: 10,
-    total: 0,
-  });
+watch(chartPanel, (val) => {
+  if (val !== "none") resizeChartsAfterExpand();
+});
 
-  // 鍥捐〃寮曠敤
-  const costChart = ref(null);
-  const typeChart = ref(null);
-  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 getEnergyTypeType = (type) => {
+  const typeMap = {
+    姘�: "primary",
+    鐢�: "warning",
+    姘�: "success",
   };
+  return typeMap[type] || "info";
+};
 
-  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})` };
+// 鍒濆鍖栧浘琛�
+const initCharts = () => {
+  nextTick(() => {
+    // 鍙垵濮嬪寲鍙闈㈡澘锛岄伩鍏嶉殣钘忓鍣ㄥ垵濮嬪寲涓� 0 灏哄瀵艰嚧绌虹櫧
+    ensureChartsReady(chartPanel.value === "none" ? "core" : chartPanel.value);
   });
+};
 
-  watch(chartPanel, val => {
-    if (val !== "none") resizeChartsAfterExpand();
-  });
-
-  // 鑾峰彇鑳借�楃被鍨嬫爣绛剧被鍨�
-  const getEnergyTypeType = type => {
-    const typeMap = {
-      姘�: "primary",
-      鐢�: "warning",
-      姘�: "success",
-    };
-    return typeMap[type] || "info";
-  };
-
-  // 鍒濆鍖栧浘琛�
-  const initCharts = () => {
-    nextTick(() => {
-      // 鍙垵濮嬪寲鍙闈㈡澘锛岄伩鍏嶉殣钘忓鍣ㄥ垵濮嬪寲涓� 0 灏哄瀵艰嚧绌虹櫧
-      ensureChartsReady(chartPanel.value === "none" ? "core" : chartPanel.value);
-    });
-  };
-
-  // 鏇存柊鑳借�楁垚鏈秼鍔垮浘
-  const updateCostChart = () => {
-    const data = tableData.value;
-    const option = {
-      tooltip: {
-        trigger: "axis",
-        axisPointer: { type: "shadow" },
-        backgroundColor: "rgba(255, 255, 255, 0.96)",
-        borderColor: "#2f6fed",
-        borderWidth: 1,
-        textStyle: { color: "rgba(15, 23, 42, 0.92)" },
-        extraCssText: "box-shadow: 0 14px 40px rgba(15,23,42,.14); border-radius: 12px;",
+// 鏇存柊鑳借�楁垚鏈秼鍔垮浘
+const updateCostChart = () => {
+  const data = tableData.value;
+  const option = {
+    tooltip: {
+      trigger: "axis",
+      axisPointer: { type: "shadow" },
+      backgroundColor: "rgba(255, 255, 255, 0.96)",
+      borderColor: "#2f6fed",
+      borderWidth: 1,
+      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" },
+    },
+    grid: {
+      left: "3%",
+      right: "4%",
+      bottom: "10%",
+      top: "15%",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      data: data.map((item) => item.timePeriod),
+      axisLabel: {
+        rotate: statisticsType.value === "day" ? 45 : 0,
+        color: "rgba(15, 23, 42, 0.62)",
       },
-      legend: {
-        data: ["鐢熶骇鑳借�楁垚鏈�", "鍔炲叕鑳借�楁垚鏈�"],
-        top: 0,
-        right: 10,
-        textStyle: { color: "#606266" },
+      axisLine: { lineStyle: { color: "rgba(15, 23, 42, 0.08)" } },
+      splitLine: { show: false },
+    },
+    yAxis: {
+      type: "value",
+      name: "鎴愭湰(鍏�)",
+      nameTextStyle: { color: "rgba(15, 23, 42, 0.58)" },
+      axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
+      axisLine: { show: false },
+      splitLine: { lineStyle: { color: "rgba(15, 23, 42, 0.06)" } },
+    },
+    series: [
+      {
+        name: "鐢熶骇鑳借�楁垚鏈�",
+        type: "bar",
+        data: data.map((item) => (item.type === "鐢熶骇" ? item.cost : 0)),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: "#409EFF" },
+            { offset: 1, color: "#66b1ff" },
+          ]),
+          borderRadius: [4, 4, 0, 0],
+        },
+        animationDelay: function (idx) {
+          return idx * 100;
+        },
       },
-      grid: {
-        left: "3%",
-        right: "4%",
-        bottom: "10%",
-        top: "15%",
-        containLabel: true,
+      {
+        name: "鍔炲叕鑳借�楁垚鏈�",
+        type: "bar",
+        data: data.map((item) => (item.type === "鍔炲叕" ? item.cost : 0)),
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: "#67C23A" },
+            { offset: 1, color: "#85ce61" },
+          ]),
+          borderRadius: [4, 4, 0, 0],
+        },
+        animationDelay: function (idx) {
+          return idx * 100 + 100;
+        },
       },
-      xAxis: {
-        type: "category",
-        data: data.map(item => item.timePeriod),
-        axisLabel: {
-          rotate: statisticsType.value === "day" ? 45 : 0,
+    ],
+    animationEasing: "elasticOut",
+    animationDelayUpdate: function (idx) {
+      return idx * 5;
+    },
+  };
+  costChartInstance.setOption(option);
+};
+
+// 鏇存柊鑳借�楃被鍨嬫垚鏈崰姣斿浘
+const updateTypeChart = () => {
+  const data = tableData.value;
+  const typeCosts = {};
+
+  data.forEach((item) => {
+    if (!typeCosts[item.energyType]) {
+      typeCosts[item.energyType] = 0;
+    }
+    typeCosts[item.energyType] += parseFloat(item.cost);
+  });
+
+  const chartData = Object.entries(typeCosts).map(([name, value]) => ({
+    name,
+    value: value.toFixed(2),
+  }));
+
+  const option = {
+    tooltip: {
+      trigger: "item",
+      formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
+      backgroundColor: "rgba(255, 255, 255, 0.96)",
+      borderColor: "#2f6fed",
+      borderWidth: 1,
+      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: "rgba(15, 23, 42, 0.62)" },
+    },
+    series: [
+      {
+        name: "鑳借�楃被鍨嬫垚鏈�",
+        type: "pie",
+        radius: ["40%", "70%"],
+        center: ["50%", "40%"],
+        avoidLabelOverlap: false,
+        itemStyle: {
+          borderRadius: 4,
+          borderColor: "#fff",
+          borderWidth: 2,
+        },
+        label: {
+          show: false,
+          position: "center",
+        },
+        emphasis: {
+          label: {
+            show: true,
+            fontSize: "18",
+            fontWeight: "bold",
+            color: "#303133",
+          },
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: "rgba(0, 0, 0, 0.3)",
+          },
+        },
+        labelLine: {
+          show: false,
+        },
+        data: chartData,
+      },
+    ],
+    color: ["#2f6fed", "#16a34a", "#f59e0b"],
+  };
+  typeChartInstance.setOption(option);
+};
+
+// 鏇存柊鑳借�楃敤閫旀垚鏈崰姣斿浘
+const updatePurposeChart = () => {
+  const data = tableData.value;
+  const purposeCosts = {
+    鐢熶骇: 0,
+    鍔炲叕: 0,
+  };
+
+  data.forEach((item) => {
+    if (purposeCosts.hasOwnProperty(item.type)) {
+      purposeCosts[item.type] += parseFloat(item.cost);
+    }
+  });
+
+  const chartData = Object.entries(purposeCosts).map(([name, value]) => ({
+    name,
+    value: value.toFixed(2),
+  }));
+
+  const option = {
+    tooltip: {
+      trigger: "item",
+      formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
+      backgroundColor: "rgba(255, 255, 255, 0.96)",
+      borderColor: "#2f6fed",
+      borderWidth: 1,
+      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: "rgba(15, 23, 42, 0.62)" },
+    },
+    series: [
+      {
+        name: "鑳借�楃敤閫旀垚鏈�",
+        type: "pie",
+        radius: "60%",
+        center: ["50%", "40%"],
+        data: chartData,
+        emphasis: {
+          itemStyle: {
+            shadowBlur: 10,
+            shadowOffsetX: 0,
+            shadowColor: "rgba(0, 0, 0, 0.3)",
+          },
+        },
+        label: {
+          show: true,
+          formatter: "{b}: {d}%",
           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: "rgba(15, 23, 42, 0.58)" },
-        axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
-        axisLine: { show: false },
-        splitLine: { lineStyle: { color: "rgba(15, 23, 42, 0.06)" } },
-      },
-      series: [
-        {
-          name: "鐢熶骇鑳借�楁垚鏈�",
-          type: "bar",
-          data: data.map(item => (item.type === "鐢熶骇" ? item.cost : 0)),
-          itemStyle: {
-            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-              { offset: 0, color: "#409EFF" },
-              { offset: 1, color: "#66b1ff" },
-            ]),
-            borderRadius: [4, 4, 0, 0],
-          },
-          animationDelay: function (idx) {
-            return idx * 100;
-          },
+        labelLine: {
+          show: true,
+          lineStyle: { color: "rgba(15, 23, 42, 0.10)" },
         },
-        {
-          name: "鍔炲叕鑳借�楁垚鏈�",
-          type: "bar",
-          data: data.map(item => (item.type === "鍔炲叕" ? item.cost : 0)),
-          itemStyle: {
-            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-              { offset: 0, color: "#67C23A" },
-              { offset: 1, color: "#85ce61" },
-            ]),
-            borderRadius: [4, 4, 0, 0],
-          },
-          animationDelay: function (idx) {
-            return idx * 100 + 100;
-          },
-        },
-      ],
-      animationEasing: "elasticOut",
-      animationDelayUpdate: function (idx) {
-        return idx * 5;
       },
-    };
-    costChartInstance.setOption(option);
+    ],
+    color: ["#2f6fed", "#16a34a"],
   };
+  purposeChartInstance.setOption(option);
+};
 
-  // 鏇存柊鑳借�楃被鍨嬫垚鏈崰姣斿浘
-  const updateTypeChart = () => {
-    const data = tableData.value;
-    const typeCosts = {};
+// 鏇存柊鑳借�楀崟浠峰姣斿浘
+const updatePriceChart = () => {
+  const data = tableData.value;
+  const priceData = {};
 
-    data.forEach(item => {
-      if (!typeCosts[item.energyType]) {
-        typeCosts[item.energyType] = 0;
-      }
-      typeCosts[item.energyType] += parseFloat(item.cost);
-    });
-
-    const chartData = Object.entries(typeCosts).map(([name, value]) => ({
-      name,
-      value: value.toFixed(2),
-    }));
-
-    const option = {
-      tooltip: {
-        trigger: "item",
-        formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
-        backgroundColor: "rgba(255, 255, 255, 0.96)",
-        borderColor: "#2f6fed",
-        borderWidth: 1,
-        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: "rgba(15, 23, 42, 0.62)" },
-      },
-      series: [
-        {
-          name: "鑳借�楃被鍨嬫垚鏈�",
-          type: "pie",
-          radius: ["40%", "70%"],
-          center: ["50%", "40%"],
-          avoidLabelOverlap: false,
-          itemStyle: {
-            borderRadius: 4,
-            borderColor: "#fff",
-            borderWidth: 2,
-          },
-          label: {
-            show: false,
-            position: "center",
-          },
-          emphasis: {
-            label: {
-              show: true,
-              fontSize: "18",
-              fontWeight: "bold",
-              color: "#303133",
-            },
-            itemStyle: {
-              shadowBlur: 10,
-              shadowOffsetX: 0,
-              shadowColor: "rgba(0, 0, 0, 0.3)",
-            },
-          },
-          labelLine: {
-            show: false,
-          },
-          data: chartData,
-        },
-      ],
-      color: ["#2f6fed", "#16a34a", "#f59e0b"],
-    };
-    typeChartInstance.setOption(option);
-  };
-
-  // 鏇存柊鑳借�楃敤閫旀垚鏈崰姣斿浘
-  const updatePurposeChart = () => {
-    const data = tableData.value;
-    const purposeCosts = {
-      鐢熶骇: 0,
-      鍔炲叕: 0,
-    };
-
-    data.forEach(item => {
-      if (purposeCosts.hasOwnProperty(item.type)) {
-        purposeCosts[item.type] += parseFloat(item.cost);
-      }
-    });
-
-    const chartData = Object.entries(purposeCosts).map(([name, value]) => ({
-      name,
-      value: value.toFixed(2),
-    }));
-
-    const option = {
-      tooltip: {
-        trigger: "item",
-        formatter: "{a} <br/>{b}: 楼{c} ({d}%)",
-        backgroundColor: "rgba(255, 255, 255, 0.96)",
-        borderColor: "#2f6fed",
-        borderWidth: 1,
-        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: "rgba(15, 23, 42, 0.62)" },
-      },
-      series: [
-        {
-          name: "鑳借�楃敤閫旀垚鏈�",
-          type: "pie",
-          radius: "60%",
-          center: ["50%", "40%"],
-          data: chartData,
-          emphasis: {
-            itemStyle: {
-              shadowBlur: 10,
-              shadowOffsetX: 0,
-              shadowColor: "rgba(0, 0, 0, 0.3)",
-            },
-          },
-          label: {
-            show: true,
-            formatter: "{b}: {d}%",
-            color: "rgba(15, 23, 42, 0.62)",
-          },
-          labelLine: {
-            show: true,
-            lineStyle: { color: "rgba(15, 23, 42, 0.10)" },
-          },
-        },
-      ],
-      color: ["#2f6fed", "#16a34a"],
-    };
-    purposeChartInstance.setOption(option);
-  };
-
-  // 鏇存柊鑳借�楀崟浠峰姣斿浘
-  const updatePriceChart = () => {
-    const data = tableData.value;
-    const priceData = {};
-
-    data.forEach(item => {
-      if (!priceData[item.energyType]) {
-        priceData[item.energyType] = {
-          鐢熶骇: 0,
-          鍔炲叕: 0,
-        };
-      }
-      if (priceData[item.energyType].hasOwnProperty(item.type)) {
-        priceData[item.energyType][item.type] = parseFloat(item.price);
-      }
-    });
-
-    const energyTypes = Object.keys(priceData);
-    const productionPrices = energyTypes.map(type => priceData[type].鐢熶骇);
-    const officePrices = energyTypes.map(type => priceData[type].鍔炲叕);
-
-    const option = {
-      tooltip: {
-        trigger: "axis",
-        axisPointer: { type: "shadow" },
-        backgroundColor: "rgba(255, 255, 255, 0.96)",
-        borderColor: "#2f6fed",
-        borderWidth: 1,
-        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: "rgba(15, 23, 42, 0.62)" },
-      },
-      grid: {
-        left: "3%",
-        right: "4%",
-        bottom: "10%",
-        top: "15%",
-        containLabel: true,
-      },
-      xAxis: {
-        type: "category",
-        data: energyTypes,
-        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: "rgba(15, 23, 42, 0.58)" },
-        axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
-        axisLine: { show: false },
-        splitLine: { lineStyle: { color: "rgba(15, 23, 42, 0.06)" } },
-      },
-      series: [
-        {
-          name: "鐢熶骇鑳借�楀崟浠�",
-          type: "bar",
-          data: productionPrices,
-          itemStyle: {
-            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-              { offset: 0, color: "#2f6fed" },
-              { offset: 1, color: "#5b8cff" },
-            ]),
-            borderRadius: [4, 4, 0, 0],
-          },
-        },
-        {
-          name: "鍔炲叕鑳借�楀崟浠�",
-          type: "bar",
-          data: officePrices,
-          itemStyle: {
-            color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
-              { offset: 0, color: "#16a34a" },
-              { offset: 1, color: "rgba(22, 163, 74, 0.65)" },
-            ]),
-            borderRadius: [4, 4, 0, 0],
-          },
-        },
-      ],
-    };
-    priceChartInstance.setOption(option);
-  };
-
-  // 缁熻缁村害鍒囨崲
-  const handleTypeChange = () => {
-    // 閲嶇疆鏃堕棿鑼冨洿
-    if (statisticsType.value === "day") {
-      const end = new Date();
-      const start = new Date();
-      start.setDate(start.getDate() - 6);
-      searchForm.dateRange = [
-        start.toISOString().split("T")[0],
-        end.toISOString().split("T")[0],
-      ];
-    } else {
-      const end = new Date();
-      const start = new Date();
-      start.setMonth(start.getMonth() - 2);
-      searchForm.monthRange = [
-        start.toISOString().slice(0, 7),
-        end.toISOString().slice(0, 7),
-      ];
+  data.forEach((item) => {
+    if (!priceData[item.energyType]) {
+      priceData[item.energyType] = {
+        鐢熶骇: 0,
+        鍔炲叕: 0,
+      };
     }
-    page.current = 1;
-    handleQuery();
+    if (priceData[item.energyType].hasOwnProperty(item.type)) {
+      priceData[item.energyType][item.type] = parseFloat(item.price);
+    }
+  });
+
+  const energyTypes = Object.keys(priceData);
+  const productionPrices = energyTypes.map((type) => priceData[type].鐢熶骇);
+  const officePrices = energyTypes.map((type) => priceData[type].鍔炲叕);
+
+  const option = {
+    tooltip: {
+      trigger: "axis",
+      axisPointer: { type: "shadow" },
+      backgroundColor: "rgba(255, 255, 255, 0.96)",
+      borderColor: "#2f6fed",
+      borderWidth: 1,
+      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: "rgba(15, 23, 42, 0.62)" },
+    },
+    grid: {
+      left: "3%",
+      right: "4%",
+      bottom: "10%",
+      top: "15%",
+      containLabel: true,
+    },
+    xAxis: {
+      type: "category",
+      data: energyTypes,
+      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: "rgba(15, 23, 42, 0.58)" },
+      axisLabel: { color: "rgba(15, 23, 42, 0.58)" },
+      axisLine: { show: false },
+      splitLine: { lineStyle: { color: "rgba(15, 23, 42, 0.06)" } },
+    },
+    series: [
+      {
+        name: "鐢熶骇鑳借�楀崟浠�",
+        type: "bar",
+        data: productionPrices,
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: "#2f6fed" },
+            { offset: 1, color: "#5b8cff" },
+          ]),
+          borderRadius: [4, 4, 0, 0],
+        },
+      },
+      {
+        name: "鍔炲叕鑳借�楀崟浠�",
+        type: "bar",
+        data: officePrices,
+        itemStyle: {
+          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
+            { offset: 0, color: "#16a34a" },
+            { offset: 1, color: "rgba(22, 163, 74, 0.65)" },
+          ]),
+          borderRadius: [4, 4, 0, 0],
+        },
+      },
+    ],
+  };
+  priceChartInstance.setOption(option);
+};
+
+// 缁熻缁村害鍒囨崲
+const handleTypeChange = () => {
+  // 閲嶇疆鏃堕棿鑼冨洿
+  if (statisticsType.value === "day") {
+    const end = new Date();
+    const start = new Date();
+    start.setDate(start.getDate() - 6);
+    searchForm.dateRange = [
+      start.toISOString().split("T")[0],
+      end.toISOString().split("T")[0],
+    ];
+  } else {
+    const end = new Date();
+    const start = new Date();
+    start.setMonth(start.getMonth() - 2);
+    searchForm.monthRange = [
+      start.toISOString().slice(0, 7),
+      end.toISOString().slice(0, 7),
+    ];
+  }
+  page.current = 1;
+  handleQuery();
+};
+
+// 鏌ヨ
+const handleQuery = () => {
+  queryPulse.value = true;
+  window.setTimeout(() => {
+    queryPulse.value = false;
+  }, 520);
+  tableLoading.value = true;
+
+  // 鏋勯�犺姹傚弬鏁�
+  const params = {
+    days: 0,
+    // energyType: searchForm.energyType || undefined,
+    type: searchForm.type || undefined,
+    pageNum: page.current,
+    pageSize: page.size,
   };
 
-  // 鏌ヨ
-  const handleQuery = () => {
-    queryPulse.value = true;
-    window.setTimeout(() => {
-      queryPulse.value = false;
-    }, 520);
-    tableLoading.value = true;
+  if (statisticsType.value === "day") {
+    if (searchForm.dateRange && searchForm.dateRange.length === 2) {
+      params.startDate = searchForm.dateRange[0];
+      params.endDate = searchForm.dateRange[1];
+    }
+  } else {
+    if (searchForm.monthRange && searchForm.monthRange.length === 2) {
+      params.startDate = searchForm.monthRange[0] + "-01";
 
-    // 鏋勯�犺姹傚弬鏁�
-    const params = {
-      days: 0,
-      // energyType: searchForm.energyType || undefined,
-      type: searchForm.type || undefined,
-      // 椤圭洰鍐呭父鐢ㄥ垎椤靛弬鏁板懡鍚�
-      pageNum: page.current,
-      pageSize: page.size,
-    };
-
-    if (statisticsType.value === "day") {
-      if (searchForm.dateRange && searchForm.dateRange.length === 2) {
-        params.startDate = searchForm.dateRange[0];
-        params.endDate = searchForm.dateRange[1];
-      }
-    } else {
-      if (searchForm.monthRange && searchForm.monthRange.length === 2) {
-        params.startDate = searchForm.monthRange[0] + "-01";
-
-        // 缁撴潫鏃堕棿闇�瑕佸彇缁撴潫鏈堜唤鐨勬渶鍚庝竴澶╋紙渚嬪 2026-03 -> 2026-03-31锛�
-        const [endYearStr, endMonthStr] = String(searchForm.monthRange[1]).split("-");
-        const endYear = Number(endYearStr);
-        const endMonth = Number(endMonthStr); // 1-12
-        if (!Number.isNaN(endYear) && !Number.isNaN(endMonth) && endMonth >= 1 && endMonth <= 12) {
-          const lastDay = new Date(endYear, endMonth, 0).getDate(); // 涓嬩釜鏈堢0澶� = 鏈湀鏈�鍚庝竴澶�
-          params.endDate = `${endYearStr}-${endMonthStr}-${String(lastDay).padStart(2, "0")}`;
-        } else {
-          params.endDate = searchForm.monthRange[1] + "-01";
-        }
+      // 缁撴潫鏃堕棿闇�瑕佸彇缁撴潫鏈堜唤鐨勬渶鍚庝竴澶╋紙渚嬪 2026-03 -> 2026-03-31锛�
+      const [endYearStr, endMonthStr] = String(searchForm.monthRange[1]).split(
+        "-"
+      );
+      const endYear = Number(endYearStr);
+      const endMonth = Number(endMonthStr); // 1-12
+      if (
+        !Number.isNaN(endYear) &&
+        !Number.isNaN(endMonth) &&
+        endMonth >= 1 &&
+        endMonth <= 12
+      ) {
+        const lastDay = new Date(endYear, endMonth, 0).getDate(); // 涓嬩釜鏈堢0澶� = 鏈湀鏈�鍚庝竴澶�
+        params.endDate = `${endYearStr}-${endMonthStr}-${String(
+          lastDay
+        ).padStart(2, "0")}`;
+      } else {
+        params.endDate = searchForm.monthRange[1] + "-01";
       }
     }
+  }
 
-    // 璁$畻寮�濮嬪埌缁撴潫鐨勫ぉ鏁帮紙鍖呭惈璧锋涓ゅぉ锛�
-    if (params.startDate && params.endDate) {
-      const start = new Date(params.startDate);
-      const end = new Date(params.endDate);
-      if (!Number.isNaN(start.getTime()) && !Number.isNaN(end.getTime())) {
-        const diffTime = end.getTime() - start.getTime();
-        const diffDays = Math.floor(diffTime / (24 * 60 * 60 * 1000)) + 1;
-        params.days = diffDays > 0 ? diffDays : 0;
-      }
+  // 璁$畻寮�濮嬪埌缁撴潫鐨勫ぉ鏁帮紙鍖呭惈璧锋涓ゅぉ锛�
+  if (params.startDate && params.endDate) {
+    const start = new Date(params.startDate);
+    const end = new Date(params.endDate);
+    if (!Number.isNaN(start.getTime()) && !Number.isNaN(end.getTime())) {
+      const diffTime = end.getTime() - start.getTime();
+      const diffDays = Math.floor(diffTime / (24 * 60 * 60 * 1000)) + 1;
+      params.days = diffDays > 0 ? diffDays : 0;
     }
+  }
 
-    // 璋冪敤鎺ュ彛鑾峰彇鏁版嵁
-    energyConsumptionDetailStatistics(params)
-      .then(res => {
-        if (res.code === 200) {
-          tableData.value = res.data.records || [];
-          page.total = res.data.total || 0;
+  // 璋冪敤鎺ュ彛鑾峰彇鏁版嵁
+  energyConsumptionDetailStatistics(params)
+    .then((res) => {
+      if (res.code === 200) {
+        const data = res.data;
+        overview.totalConsumption = data.totalEnergyConsumption || "0";
+        overview.totalAmount = data.totalEnergyCost || "0";
+        overview.avgConsumption = data.averageConsumption || "0";
+        overview.compareRate = data.changeVite || 0;
 
-          // 鏇存柊缁熻姒傝鏁版嵁
-          if (res.data.overview) {
-            overview.totalCost = res.data.overview.totalCost || "0.00";
-            overview.productionCost = res.data.overview.productionCost || "0.00";
-            overview.officeCost = res.data.overview.officeCost || "0.00";
-            overview.avgCost = res.data.overview.avgCost || "0.00";
-          }
-        } else {
-          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);
-        // 銆愬亣鏁版嵁锛圡ock锛夊凡绂佺敤銆戞帴鍙e紓甯告椂涓嶅啀鐢熸垚闅忔満鍋囨暟鎹紝閬垮厤璇敤鍒扮敓浜ф暟鎹摼璺�
-        ElMessage.error("鑾峰彇鏁版嵁寮傚父");
+        // 澶勭悊琛ㄦ牸鏁版嵁
+        tableData.value = data.energyCostDtos || [];
+        page.total = tableData.value.length || 0;
+      } else {
+        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";
-      })
-      .finally(() => {
-        tableLoading.value = false;
-        updateCharts();
-      });
-  };
-
-  // 銆愬亣鏁版嵁锛圡ock锛夊凡绂佺敤銆戝巻鍙蹭笂鐢ㄤ簬鎺ュ彛寮傚父鍏滃簳鐨勯殢鏈烘暟鎹敓鎴愰�昏緫锛岀幇宸叉暣浣撴敞閲婏紝閬垮厤璇敤浜庣敓浜с��
-  /*
-  // 鐢熸垚鍋囨暟鎹�
-  const generateMockData = () => {
-    if (statisticsType.value === "day") {
-      // 鐢熸垚鏈�杩�7澶╃殑鍋囨暟鎹�
-      const mockData = [];
-      const today = new Date();
-
-      for (let i = 6; i >= 0; i--) {
-        const date = new Date(today);
-        date.setDate(date.getDate() - i);
-        const dateStr = date.toISOString().split("T")[0];
-
-        // 鐢熶骇鑳借�楁暟鎹�
-        mockData.push({
-          timePeriod: dateStr,
-          energyType: "鐢�",
-          type: "鐢熶骇",
-          consumption: (Math.random() * 1000 + 500).toFixed(2),
-          unit: "kWh",
-          price: "0.85",
-          cost: (Math.random() * 850 + 425).toFixed(2),
-        });
-        mockData.push({
-          timePeriod: dateStr,
-          energyType: "姘�",
-          type: "鐢熶骇",
-          consumption: (Math.random() * 500 + 200).toFixed(2),
-          unit: "m鲁",
-          price: "3.50",
-          cost: (Math.random() * 1750 + 700).toFixed(2),
-        });
-        mockData.push({
-          timePeriod: dateStr,
-          energyType: "姘�",
-          type: "鐢熶骇",
-          consumption: (Math.random() * 300 + 100).toFixed(2),
-          unit: "m鲁",
-          price: "2.80",
-          cost: (Math.random() * 840 + 280).toFixed(2),
-        });
-
-        // 鍔炲叕鑳借�楁暟鎹�
-        mockData.push({
-          timePeriod: dateStr,
-          energyType: "鐢�",
-          type: "鍔炲叕",
-          consumption: (Math.random() * 200 + 100).toFixed(2),
-          unit: "kWh",
-          price: "0.85",
-          cost: (Math.random() * 170 + 85).toFixed(2),
-        });
-        mockData.push({
-          timePeriod: dateStr,
-          energyType: "姘�",
-          type: "鍔炲叕",
-          consumption: (Math.random() * 50 + 20).toFixed(2),
-          unit: "m鲁",
-          price: "3.50",
-          cost: (Math.random() * 175 + 70).toFixed(2),
-        });
       }
-
-      tableData.value = mockData;
-      page.total = mockData.length;
-    } else {
-      // 鐢熸垚鏈�杩�3涓湀鐨勫亣鏁版嵁
-      const mockData = [];
-      const today = new Date();
-
-      for (let i = 2; i >= 0; i--) {
-        const date = new Date(today);
-        date.setMonth(date.getMonth() - i);
-        const monthStr = date.toISOString().slice(0, 7);
-
-        // 鐢熶骇鑳借�楁暟鎹�
-        mockData.push({
-          timePeriod: monthStr,
-          energyType: "鐢�",
-          type: "鐢熶骇",
-          consumption: (Math.random() * 30000 + 15000).toFixed(2),
-          unit: "kWh",
-          price: "0.85",
-          cost: (Math.random() * 25500 + 12750).toFixed(2),
-        });
-        mockData.push({
-          timePeriod: monthStr,
-          energyType: "姘�",
-          type: "鐢熶骇",
-          consumption: (Math.random() * 15000 + 6000).toFixed(2),
-          unit: "m鲁",
-          price: "3.50",
-          cost: (Math.random() * 52500 + 21000).toFixed(2),
-        });
-        mockData.push({
-          timePeriod: monthStr,
-          energyType: "姘�",
-          type: "鐢熶骇",
-          consumption: (Math.random() * 9000 + 3000).toFixed(2),
-          unit: "m鲁",
-          price: "2.80",
-          cost: (Math.random() * 25200 + 8400).toFixed(2),
-        });
-
-        // 鍔炲叕鑳借�楁暟鎹�
-        mockData.push({
-          timePeriod: monthStr,
-          energyType: "鐢�",
-          type: "鍔炲叕",
-          consumption: (Math.random() * 6000 + 3000).toFixed(2),
-          unit: "kWh",
-          price: "0.85",
-          cost: (Math.random() * 5100 + 2550).toFixed(2),
-        });
-        mockData.push({
-          timePeriod: monthStr,
-          energyType: "姘�",
-          type: "鍔炲叕",
-          consumption: (Math.random() * 1500 + 600).toFixed(2),
-          unit: "m鲁",
-          price: "3.50",
-          cost: (Math.random() * 5250 + 2100).toFixed(2),
-        });
-      }
-
-      tableData.value = mockData;
-      page.total = mockData.length;
-    }
-
-    // 鏇存柊缁熻姒傝鏁版嵁
-    calculateOverview();
-  };
-  */
-
-  // 銆愬亣鏁版嵁锛圡ock锛夊凡绂佺敤銆戜笌 generateMockData 閰嶅鐨勫墠绔眹鎬昏绠楋紙浠呬緵鍋囨暟鎹睍绀猴級锛岀幇宸叉敞閲�
-  /*
-  // 璁$畻缁熻姒傝鏁版嵁
-  const calculateOverview = () => {
-    let totalCost = 0;
-    let productionCost = 0;
-    let officeCost = 0;
-
-    tableData.value.forEach(item => {
-      const cost = parseFloat(item.cost);
-      totalCost += cost;
-      if (item.type === "鐢熶骇") {
-        productionCost += cost;
-      } else if (item.type === "鍔炲叕") {
-        officeCost += cost;
-      }
+    })
+    .catch((err) => {
+      console.error("鑾峰彇鏁版嵁寮傚父锛�", err);
+      // 銆愬亣鏁版嵁锛圡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;
+      updateCharts();
     });
+};
 
-    overview.totalCost = totalCost.toFixed(2);
-    overview.productionCost = productionCost.toFixed(2);
-    overview.officeCost = officeCost.toFixed(2);
-    overview.avgCost = (totalCost / tableData.value.length).toFixed(2);
-  };
-  */
-
-  // 鏇存柊鎵�鏈夊浘琛�
-  const updateCharts = () => {
-    nextTick(() => {
-      if (costChartInstance) updateCostChart();
-      if (typeChartInstance) updateTypeChart();
-      if (purposeChartInstance) updatePurposeChart();
-      if (priceChartInstance) updatePriceChart();
-    });
-  };
-
-  // 閲嶇疆
-  const handleReset = () => {
-    // searchForm.energyType = "";
-    searchForm.type = "";
-    if (statisticsType.value === "day") {
-      const end = new Date();
-      const start = new Date();
-      start.setDate(start.getDate() - 6);
-      searchForm.dateRange = [
-        start.toISOString().split("T")[0],
-        end.toISOString().split("T")[0],
-      ];
-    } else {
-      const end = new Date();
-      const start = new Date();
-      start.setMonth(start.getMonth() - 2);
-      searchForm.monthRange = [
-        start.toISOString().slice(0, 7),
-        end.toISOString().slice(0, 7),
-      ];
-    }
-    page.current = 1;
-    handleQuery();
-  };
-
-  // 瀵煎嚭
-  const handleExport = () => {
-    ElMessage.success("鎶ヨ〃瀵煎嚭鎴愬姛");
-  };
-
-  // 鍒嗛〉澶у皬鍙樺寲
-  const handleSizeChange = val => {
-    page.size = val;
-    page.current = 1;
-    handleQuery();
-  };
-
-  // 椤电爜鍙樺寲
-  const handleCurrentChange = val => {
-    page.current = val;
-    handleQuery();
-  };
-
-  // 绐楀彛澶у皬鍙樺寲鏃堕噸鏂版覆鏌撳浘琛�
-  const handleResize = () => {
-    costChartInstance && costChartInstance.resize();
-    typeChartInstance && typeChartInstance.resize();
-    purposeChartInstance && purposeChartInstance.resize();
-    priceChartInstance && priceChartInstance.resize();
-  };
-
-  onMounted(() => {
-    handleQuery();
-    initCharts();
-    window.addEventListener("resize", handleResize);
+// 鏇存柊鎵�鏈夊浘琛�
+const updateCharts = () => {
+  nextTick(() => {
+    if (costChartInstance) updateCostChart();
+    if (typeChartInstance) updateTypeChart();
+    if (purposeChartInstance) updatePurposeChart();
+    if (priceChartInstance) updatePriceChart();
   });
+};
 
-  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;
+// 閲嶇疆
+const handleReset = () => {
+  // searchForm.energyType = "";
+  searchForm.type = "";
+  if (statisticsType.value === "day") {
+    const end = new Date();
+    const start = new Date();
+    start.setDate(start.getDate() - 6);
+    searchForm.dateRange = [
+      start.toISOString().split("T")[0],
+      end.toISOString().split("T")[0],
+    ];
+  } else {
+    const end = new Date();
+    const start = new Date();
+    start.setMonth(start.getMonth() - 2);
+    searchForm.monthRange = [
+      start.toISOString().slice(0, 7),
+      end.toISOString().slice(0, 7),
+    ];
+  }
+  page.current = 1;
+  handleQuery();
+};
 
-    // Enter: 鍒锋柊鏌ヨ
-    if (e.key === "Enter") {
-      e.preventDefault();
-      handleQuery();
-      return;
-    }
+// 瀵煎嚭
+const handleExport = () => {
+  ElMessage.success("鎶ヨ〃瀵煎嚭鎴愬姛");
+};
 
-    // Esc: 閲嶇疆
-    if (e.key === "Escape") {
-      e.preventDefault();
-      handleReset();
-      return;
-    }
+// 鍒嗛〉澶у皬鍙樺寲
+const handleSizeChange = (val) => {
+  page.size = val;
+  page.current = 1;
+  handleQuery();
+};
 
-    // Alt+E: 瀵煎嚭
-    if (e.altKey && (e.key === "e" || e.key === "E")) {
-      e.preventDefault();
-      handleExport();
-    }
-  };
+// 椤电爜鍙樺寲
+const handleCurrentChange = (val) => {
+  page.current = val;
+  handleQuery();
+};
 
-  onMounted(() => {
-    window.addEventListener("keydown", handleGlobalHotkeys);
-  });
+// 绐楀彛澶у皬鍙樺寲鏃堕噸鏂版覆鏌撳浘琛�
+const handleResize = () => {
+  costChartInstance && costChartInstance.resize();
+  typeChartInstance && typeChartInstance.resize();
+  purposeChartInstance && purposeChartInstance.resize();
+  priceChartInstance && priceChartInstance.resize();
+};
 
-  onUnmounted(() => {
-    window.removeEventListener("keydown", handleGlobalHotkeys);
-  });
+onMounted(() => {
+  handleQuery();
+  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">
-  .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;
+.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%);
+  padding: 18px 22px 24px;
+  background: radial-gradient(
+      1200px 420px at 20% 0%,
+      rgba(47, 111, 237, 0.1),
+      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%);
+}
+
+.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;
+  gap: 14px;
+}
+
+.filter-form {
+  flex: 1 1 auto;
+  min-width: 0;
+}
+
+.w-260 {
+  width: 260px;
+  max-width: 100%;
+}
+
+.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.1);
+    filter: saturate(1.02);
+  }
+
+  &:active {
+    transform: translateY(0);
+    box-shadow: none;
+  }
+}
+
+.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.7);
+  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.1);
+  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.2);
+  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.3);
+  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.2s ease, transform 0.2s ease, border-color 0.2s 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.1);
+  }
+  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.1);
+  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.1),
+      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),
+    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.1),
+    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.1),
+    inset 0 0 0 1px rgba(47, 111, 237, 0.1);
+}
+
+.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: 850;
+  letter-spacing: 0.2px;
+  color: var(--lux-text);
+  line-height: 1.1;
+}
+
+.kpi-meta {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+  margin-top: 2px;
+  min-height: 22px;
+}
+
+.kpi-meta.muted {
+  font-size: 11px;
+  color: var(--lux-muted);
+}
+
+.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);
+}
+
+.kpi-chip.up {
+  border-color: rgba(22, 163, 74, 0.2);
+  color: rgba(22, 163, 74, 0.96);
+  background: rgba(22, 163, 74, 0.06);
+}
+
+.kpi-chip.down {
+  border-color: rgba(239, 68, 68, 0.2);
+  color: rgba(239, 68, 68, 0.96);
+  background: rgba(239, 68, 68, 0.06);
+}
+
+.kpi-spark {
+  width: 72px;
+  height: 22px;
+  opacity: 0.9;
+  filter: drop-shadow(0 8px 16px rgba(15, 23, 42, 0.1));
+}
+
+.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;
+}
+
+.kpi-item:hover .kpi-actions {
+  opacity: 1;
+  transform: translateY(0);
+  pointer-events: auto;
+}
+
+.kpi-action {
+  font-size: 11px;
+  font-weight: 650;
+  padding: 4px 8px;
+  border-radius: 999px;
+  border: 1px solid rgba(15, 23, 42, 0.1);
+  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;
+}
+
+.kpi-action:hover {
+  background: rgba(47, 111, 237, 0.08);
+  border-color: rgba(47, 111, 237, 0.22);
+  transform: translateY(-1px);
+}
+
+.kpi-action:active {
+  transform: translateY(0);
+}
+
+.chart-wrap {
+  border-radius: 12px;
+  overflow: hidden;
+  position: relative;
+}
+
+.chart-empty {
+  height: 240px;
+  display: grid;
+  place-items: center;
+  background: rgba(255, 255, 255, 0.7);
+  border-radius: 12px;
+  position: absolute;
+  inset: 0;
+}
+
+:deep(.big-chart-dialog .el-dialog) {
+  border-radius: 16px;
+  overflow: hidden;
+}
+
+:deep(.big-chart-dialog .el-dialog__header) {
+  padding: 14px 16px;
+  background: radial-gradient(
+      900px 240px at 10% 0%,
+      rgba(47, 111, 237, 0.1),
+      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;
+  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.1);
+  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.1),
+    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.1),
+    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.1),
+    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.1),
+    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.1);
+}
+
+.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.1),
+    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.1),
+    0 1px 0 rgba(255, 255, 255, 0.65) inset;
+  transition: transform 0.36s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.2s 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 {
+  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(-2px);
+    box-shadow: var(--lux-shadow);
+    border-color: rgba(47, 111, 237, 0.16);
+  }
+}
+
+.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.1);
+  }
+}
+
+.data-table {
+  width: 100%;
+}
+
+.consumption-value {
+  font-weight: bold;
+  color: var(--lux-primary);
+}
+
+.consumption-unit {
+  font-size: 12px;
+  color: var(--lux-muted);
+  margin-left: 2px;
+}
+
+.price-value {
+  font-weight: bold;
+  color: var(--lux-success);
+}
+
+.cost-value {
+  font-weight: bold;
+  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.3);
+}
+
+: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 {
-    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;
-    gap: 14px;
-  }
-
-  .filter-form {
-    flex: 1 1 auto;
-    min-width: 0;
-  }
-
-  .w-260 {
-    width: 260px;
-    max-width: 100%;
-  }
-
-  .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;
-    }
-  }
-
-  .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;
+    justify-content: flex-start;
   }
 
   .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: 850;
-    letter-spacing: 0.2px;
-    color: var(--lux-text);
-    line-height: 1.1;
-  }
-
-  .kpi-meta {
-    display: flex;
-    align-items: center;
-    gap: 8px;
-    margin-top: 2px;
-    min-height: 22px;
-  }
-
-  .kpi-meta.muted {
-    font-size: 11px;
-    color: var(--lux-muted);
-  }
-
-  .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);
-  }
-
-  .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);
-  }
-
-  .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);
-  }
-
-  .kpi-spark {
-    width: 72px;
-    height: 22px;
-    opacity: 0.9;
-    filter: drop-shadow(0 8px 16px rgba(15, 23, 42, 0.10));
-  }
-
-  .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;
-  }
-
-  .kpi-item:hover .kpi-actions {
-    opacity: 1;
-    transform: translateY(0);
-    pointer-events: auto;
-  }
-
-  .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;
-  }
-
-  .kpi-action:hover {
-    background: rgba(47, 111, 237, 0.08);
-    border-color: rgba(47, 111, 237, 0.22);
-    transform: translateY(-1px);
-  }
-
-  .kpi-action:active {
-    transform: translateY(0);
-  }
-
-  .chart-wrap {
-    border-radius: 12px;
-    overflow: hidden;
-    position: relative;
-  }
-
-  .chart-empty {
-    height: 240px;
-    display: grid;
-    place-items: center;
-    background: rgba(255, 255, 255, 0.70);
-    border-radius: 12px;
-    position: absolute;
-    inset: 0;
-  }
-
-  :deep(.big-chart-dialog .el-dialog) {
-    border-radius: 16px;
-    overflow: hidden;
-  }
-
-  :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;
+    grid-template-columns: repeat(2, minmax(0, 1fr));
   }
 
   .panel-head {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    gap: 12px;
-    padding: 8px 4px 6px;
+    flex-wrap: wrap;
   }
+}
 
-  .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;
-  }
+/* 鎶樺彔鍔ㄧ敾 */
+.lux-collapse-enter-active,
+.lux-collapse-leave-active {
+  transition: max-height 0.22s ease, opacity 0.18s ease;
+  overflow: hidden;
+}
 
-  .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;
-  }
+.lux-collapse-enter-from,
+.lux-collapse-leave-to {
+  max-height: 0;
+  opacity: 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 {
-    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(-2px);
-      box-shadow: var(--lux-shadow);
-      border-color: rgba(47, 111, 237, 0.16);
-    }
-  }
-
-  .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: var(--lux-primary);
-  }
-
-  .consumption-unit {
-    font-size: 12px;
-    color: var(--lux-muted);
-    margin-left: 2px;
-  }
-
-  .price-value {
-    font-weight: bold;
-    color: var(--lux-success);
-  }
-
-  .cost-value {
-    font-weight: bold;
-    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;
-  }
+.lux-collapse-enter-to,
+.lux-collapse-leave-from {
+  max-height: 600px;
+  opacity: 1;
+}
 </style>
\ No newline at end of file

--
Gitblit v1.9.3