From 4c9fdc87987140e8b2c3f0dfc2f6608cdb6be774 Mon Sep 17 00:00:00 2001
From: WXL <wl_5969728@163.com>
Date: 星期三, 21 十月 2026 17:39:24 +0800
Subject: [PATCH] 青岛维护

---
 src/views/home/index.vue | 2904 ++++++++++++++++------------------------------------------
 1 files changed, 801 insertions(+), 2,103 deletions(-)

diff --git a/src/views/home/index.vue b/src/views/home/index.vue
index 4fab88a..e1721b8 100644
--- a/src/views/home/index.vue
+++ b/src/views/home/index.vue
@@ -1,2162 +1,860 @@
 <template>
-  <div>
-    <div v-loading="isloading" style="padding: 10px">
-      <div>
-        <el-image
-          style="width: 100%; height: 72px"
-          :src="img.head"
-          fit="contain"
-        ></el-image>
+  <div v-loading="loading" class="cockpit">
+    <!-- 椤堕儴鏍囬鏍� -->
+    <header class="cockpit-header">
+      <div class="header-left">
+        <span class="header-logo"></span>
+        <h1 class="header-title">闈掑矝澶у闄勫睘鍖婚櫌 路 OPO 鍣ㄥ畼鎹愮尞绠$悊椹鹃┒鑸�</h1>
       </div>
+      <div class="header-right">
+        <span class="header-clock">{{ now }}</span>
+        <el-button type="text" class="header-logout" @click="handleLogout"
+          >閫�鍑�</el-button
+        >
+      </div>
+    </header>
 
-      <el-row :gutter="20">
-        <el-col :span="6">
-          <div class="iwc-dv-box" style="margin-bottom: 0.5rem">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">鍗犳瘮缁熻</div>
-
-              <div style="padding: 0 2rem">
-                <div class="iwc-box-a" :style="'height:' + heightA + 'px'">
-                  <div class="iwc-box-a-1">
-                    <span
-                      class="iwc-before-o"
-                      style="border-color: #38a5f8"
-                    ></span
-                    >鎬у埆鍗犳瘮锛歿{
-                      currentZb.sex == -1 ? "" : arrZb.sex[currentZb.sex].label
-                    }}
-                  </div>
-                  <el-progress
-                    :text-inside="true"
-                    :stroke-width="15"
-                    :percentage="
-                      currentZb.sex == -1
-                        ? 0
-                        : Number(
-                            (arrZb.sex[currentZb.sex].value * 100).toFixed(0)
-                          )
-                    "
-                    :color="'#38a5f8'"
-                  ></el-progress>
-                </div>
-                <div class="iwc-box-a" :style="'height:' + heightA + 'px'">
-                  <div class="iwc-box-a-1">
-                    <span
-                      class="iwc-before-o"
-                      style="border-color: #9078e5"
-                    ></span
-                    >骞撮緞鍗犳瘮锛歿{
-                      currentZb.age == -1 ? "" : arrZb.age[currentZb.age].label
-                    }}
-                  </div>
-                  <el-progress
-                    :text-inside="true"
-                    :stroke-width="15"
-                    :percentage="
-                      currentZb.age == -1
-                        ? 0
-                        : Number(
-                            (arrZb.age[currentZb.age].value * 100).toFixed(0)
-                          )
-                    "
-                    :color="'#9078e5'"
-                  ></el-progress>
-                </div>
-                <div class="iwc-box-a" :style="'height:' + heightA + 'px'">
-                  <div class="iwc-box-a-1">
-                    <span
-                      class="iwc-before-o"
-                      style="border-color: #3fc529"
-                    ></span
-                    >鎹愮尞鍒嗙被鍗犳瘮锛歿{
-                      currentZb.type == -1
-                        ? ""
-                        : arrZb.type[currentZb.type].label
-                    }}
-                  </div>
-                  <el-progress
-                    :text-inside="true"
-                    :stroke-width="15"
-                    :percentage="
-                      currentZb.type == -1
-                        ? 0
-                        : Number(
-                            (arrZb.type[currentZb.type].value * 100).toFixed(0)
-                          )
-                    "
-                    :color="'#3fc529'"
-                  ></el-progress>
-                </div>
-                <div class="iwc-box-a" :style="'height:' + heightA + 'px'">
-                  <div class="iwc-box-a-1">
-                    <span
-                      class="iwc-before-o"
-                      style="border-color: #2a65b5"
-                    ></span
-                    >鐤剧梾鍗犳瘮锛歿{
-                      currentZb.d == -1 ? "" : arrZb.d[currentZb.d].label
-                    }}
-                  </div>
-                  <el-progress
-                    :text-inside="true"
-                    :stroke-width="15"
-                    :percentage="
-                      currentZb.d == -1
-                        ? 0
-                        : Number((arrZb.d[currentZb.d].value * 100).toFixed(0))
-                    "
-                    :color="'#2a65b5'"
-                  ></el-progress>
-                </div>
-                <div class="iwc-box-a" :style="'height:' + heightA + 'px'">
-                  <div class="iwc-box-a-1">
-                    <span
-                      class="iwc-before-o"
-                      style="border-color: #fbc329"
-                    ></span
-                    >琛�鍨嬪崰姣旓細{{
-                      currentZb.x == -1 ? "" : arrZb.x[currentZb.x].label
-                    }}
-                  </div>
-                  <el-progress
-                    :text-inside="true"
-                    :stroke-width="15"
-                    :percentage="
-                      currentZb.x == -1
-                        ? 0
-                        : Number((arrZb.x[currentZb.x].value * 100).toFixed(0))
-                    "
-                    :color="'#fbc329'"
-                  ></el-progress>
-                </div>
-              </div>
-            </dv-border-box-7>
+    <!-- KPI 鎸囨爣鍗� -->
+    <section class="kpi-row">
+      <div v-for="kpi in kpiCards" :key="kpi.label" class="kpi-card">
+        <div class="kpi-icon" :style="{ background: kpi.gradient }">
+          <i :class="kpi.icon"></i>
+        </div>
+        <div class="kpi-body">
+          <div class="kpi-label">{{ kpi.label }}</div>
+          <div class="kpi-value">
+            <count-to
+              :start-val="0"
+              :end-val="kpi.value"
+              :duration="1400"
+              :decimals="kpi.decimals || 0"
+              separator=","
+            />
+            <span class="kpi-unit">{{ kpi.unit }}</span>
           </div>
+        </div>
+      </div>
+    </section>
 
-          <div class="iwc-dv-box" style="margin-bottom: 0.5rem">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">鏈烘瀯鎹愮尞缁熻</div>
+    <!-- 浠〃鐩樻寚鏍� -->
+    <section class="gauge-row">
+      <div v-for="g in gaugeCharts" :key="g.name" class="panel">
+        <div class="panel-title">{{ g.name }}</div>
+        <G2PlotChart type="gauge" :options="g.options" :height="150" />
+      </div>
+    </section>
 
-              <div
-                style="padding: 0 2rem"
-                :style="'height:' + (height * 0.35 - 54) + 'px'"
-              >
-                <dv-scroll-board
-                  :config="tableConfig"
-                  style="width: 100%"
-                  class="iwc-h-rb-table"
-                  :style="'height:' + (height * 0.35 - 54) + 'px'"
+    <!-- 涓诲尯锛氬湴鍥惧眳涓紝鍏朵粬鍥剧幆缁� -->
+    <el-row :gutter="16">
+      <el-col :span="6">
+        <div class="col-stack">
+          <div class="panel">
+            <div class="panel-title">妗堜緥鏈堝害瓒嬪娍</div>
+            <G2PlotChart type="area" :options="trendOptions" :height="205" />
+          </div>
+          <div class="panel">
+            <div class="panel-title">鍣ㄥ畼鑾峰彇 / 绉绘瓒嬪娍</div>
+            <G2PlotChart type="line" :options="organMoonOptions" :height="205" />
+          </div>
+        </div>
+      </el-col>
+      <el-col :span="12">
+        <div class="panel panel--map">
+          <div class="panel-title">鍦板尯鍒嗗竷</div>
+          <MapChart
+            :cdata="raw.mapData"
+            :height="'480px'"
+            :zoom="1.4"
+            left="center"
+            top="middle"
+            label-mode="name"
+            dark
+            :roam="true"
+            @click="mapClick"
+          />
+        </div>
+      </el-col>
+      <el-col :span="6">
+        <div class="col-stack">
+          <div class="panel">
+            <div class="panel-title">鍦板尯鎹愮尞瀵规瘮</div>
+            <G2PlotChart type="column" :options="areaOptions" :height="205" />
+          </div>
+          <div class="panel panel--carousel">
+            <div class="panel-title">{{ currentCarousel.title }}</div>
+            <transition name="fade" mode="out-in">
+              <div :key="carouselIndex" class="carousel-body">
+                <G2PlotChart
+                  :type="currentCarousel.type"
+                  :options="currentCarousel.options"
+                  :height="205"
                 />
               </div>
-            </dv-border-box-7>
-          </div>
-        </el-col>
-        <el-col :span="12">
-          <div class="iwc-box-d" style="height: 125px">
-            <div class="iwc-box-d-1">
-              <div class="iwc-box-d-img">
-                <el-image
-                  style="width: 100%; height: 100%"
-                  :src="img.btn1"
-                  fit="cover"
-                ></el-image>
-              </div>
-              <div class="iwc-box-d-f">
-                <div class="iwc-box-d-f1">{{ leijishuju.processOrgans }}</div>
-                <div class="iwc-box-d-f2">鎹愮尞妗堜緥绱</div>
-              </div>
-            </div>
-            <div class="iwc-box-d-1">
-              <div class="iwc-box-d-img">
-                <el-image
-                  style="width: 100%; height: 100%"
-                  :src="img.btn2"
-                  fit="cover"
-                ></el-image>
-              </div>
-              <div class="iwc-box-d-f">
-                <div class="iwc-box-d-f1">{{ leijishuju.finishedOrgans }}</div>
-                <div class="iwc-box-d-f2">鎹愮尞瀹屾垚绱</div>
-              </div>
-            </div>
-            <div class="iwc-box-d-1">
-              <div class="iwc-box-d-img">
-                <el-image
-                  style="width: 100%; height: 100%"
-                  :src="img.btn3"
-                  fit="cover"
-                ></el-image>
-              </div>
-              <div class="iwc-box-d-f">
-                <div class="iwc-box-d-f1">{{ leijishuju.Organsnum }}</div>
-                <div class="iwc-box-d-f2">鎹愮尞鍣ㄥ畼绱</div>
-              </div>
-            </div>
-            <div class="iwc-box-d-1" style="flex: 1.4">
-              <div class="iwc-box-d-img">
-                <el-image
-                  style="width: 100%; height: 100%"
-                  :src="img.btn4"
-                  fit="cover"
-                ></el-image>
-              </div>
-              <div class="iwc-box-d-f">
-                <div class="iwc-box-d-f1">{{ leijishuju.PMP }}</div>
-                <div class="iwc-box-d-f2">姣忕櫨涓囦汉鍙e櫒瀹樻崘鐚巼(PMP)</div>
-              </div>
+            </transition>
+            <div class="carousel-dots">
+              <span
+                v-for="(item, i) in carouselItems"
+                :key="i"
+                class="dot"
+                :class="{ active: i === carouselIndex }"
+                @click="carouselIndex = i"
+              ></span>
             </div>
           </div>
+        </div>
+      </el-col>
+    </el-row>
 
-          <div class="iwc-box-e" style="margin-bottom: 10px; padding-left: 12%">
-            <el-col :span="17">
-              <MapChart
-                :cdata="cdata"
-                :height="height * 0.72 - 128 + 'px'"
-                @click="mapClick"
-                :chartType="chartType"
-              />
-            </el-col>
-            <el-col :span="7">
-              <div
-                style="backgroun-color:black; margin-bottom:5px;height:100%;padding-top:50px;"
-              >
-                <el-row>
-                  <div style="color:white;font-size:15px;text-align:center">
-                    褰撳墠鍚勫湴甯傛綔鍦ㄦ崘鐚渚�
-                  </div>
-                </el-row>
-                <el-row>
-                  <el-col
-                    :span="12"
-                    style="color:white;font-size:14px;text-align:center;margin-top:10px"
-                    v-for="(item, index) in cityDonoateCaseArr"
-                    :key="index"
-                  >
-                    {{ item.cityName }}<br />
-                    <span style="color:#ffd200">{{ item.donoateNum }}</span
-                    >渚�
-                  </el-col>
-                </el-row>
-              </div>
-            </el-col>
-          </div>
-        </el-col>
-        <el-col :span="6">
-          <div class="iwc-dv-box" style="margin-bottom: 0.5rem">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">鍣ㄥ畼鑾峰彇缁熻</div>
-
-              <el-row
-                style="padding: 0 2rem"
-                :style="'height:' + (height * 0.35 - 54) + 'px'"
-              >
-                <el-col
-                  :span="8"
-                  v-for="(item, index) in organSumData"
-                  :key="index"
-                >
-                  <div
-                    style="
-                      color: #fff;
-                      padding-bottom: 10px;
-                    "
-                  >
-                    {{ item.name }}锛�<span style="font-size: 18px">{{
-                      item.value
-                    }}</span>
-                  </div>
-                </el-col>
-              </el-row>
-            </dv-border-box-7>
-          </div>
-          <div class="iwc-dv-box" style="margin-bottom: 0.5rem">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">鏈烘瀯鎺ュ彈鍣ㄥ畼缁熻</div>
-
-              <el-row
-                style="padding: 0 1rem"
-                :style="'height:' + (height * 0.35 - 54) + 'px'"
-              >
-                <dv-scroll-board
-                  v-if="configHosOrgan.data.length > 0"
-                  :config="configHosOrgan"
-                  class="iwc-box-b-table"
-                  style="width: 100%"
-                  :style="'height:' + (height * 0.35 - 54) + 'px'"
-                />
-              </el-row>
-            </dv-border-box-7>
-          </div>
-        </el-col>
-      </el-row>
-
-      <el-row :gutter="20">
-        <el-col :span="6">
-          <div class="iwc-dv-box" style="margin-bottom: 0.5rem">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">鍘嗗勾鎹愮尞鏁版嵁</div>
-
-              <el-row
-                style="padding: 0 1rem"
-                :style="'height:' + (height * 0.28 - 80) + 'px'"
-              >
-                <BarChartH
-                  :cdata="cdataYear"
-                  :organData="organYearData"
-                  :height="height * 0.28 - 80 + 'px'"
-                />
-              </el-row>
-            </dv-border-box-7>
-          </div>
-        </el-col>
-
-        <el-col :span="12">
-          <div class="iwc-dv-box" style="margin-bottom: 0.5rem">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">鎹愮尞妗堜緥鏈堝害缁熻</div>
-
-              <div style="padding: 0 2rem">
-                <LineChart
-                  :cdata="anlidata"
-                  :height="height * 0.28 - 80 + 'px'"
-                />
-              </div>
-            </dv-border-box-7>
-          </div>
-        </el-col>
-        <el-col :span="6">
-          <div class="iwc-dv-box">
-            <dv-border-box-7
-              :color="['#0a336e', '#1a7ade']"
-              :backgroundColor="'#030e40'"
-            >
-              <div class="iwc-box-head">璐ㄦ帶鎸囨爣</div>
-
-              <div
-                style="padding: 0 2rem"
-                :style="'height:' + (height * 0.28 - 80) + 'px'"
-              >
-                <div class="iwc-box-c">
-                  <div class="iwc-box-c1" style="color: #fac738">
-                    <div class="iwc-box-c1-o">
-                      {{
-                        leijishuju.donateTransferRate
-                          ? leijishuju.donateTransferRate.toFixed(2)
-                          : ""
-                      }}
-                    </div>
-                    <div class="iwc-box-c1-l" style="font-size:0.8rem">
-                      鍣ㄥ畼鎹愮尞杞寲鐜�
-                    </div>
-                  </div>
-                  <div class="iwc-box-c1" style="color: #34bc1d">
-                    <div class="iwc-box-c1-o">
-                      {{
-                        leijishuju.organProductionRate
-                          ? leijishuju.organProductionRate.toFixed(2)
-                          : ""
-                      }}
-                    </div>
-                    <div class="iwc-box-c1-l" style="font-size:0.8rem">
-                      骞冲潎鍣ㄥ畼浜у嚭鐜�
-                    </div>
-                  </div>
-                  <div class="iwc-box-c1" style="color: #2f9ef4">
-                    <div class="iwc-box-c1-o">
-                      {{
-                        leijishuju.organUsedRate
-                          ? leijishuju.organUsedRate.toFixed(2)
-                          : ""
-                      }}
-                    </div>
-                    <div class="iwc-box-c1-l" style="font-size:0.8rem">
-                      鑾峰彇鍣ㄥ畼鍒╃敤鐜�
-                    </div>
-                  </div>
-                </div>
-              </div>
-            </dv-border-box-7>
-          </div>
-        </el-col>
-      </el-row>
-
-      <!-- <el-row v-if="0" class="c-home" :gutter="10">
-        <el-col :span="8">
-          <div style="padding-top: 25px; padding-bottom: 10px">
-            <dv-border-box-2 :color="['#1b88a3']">
-              <div class="box-title" style="position: absolute; top: -8px">
-                <span><b>瀵规瘮鍒嗘瀽</b></span>
-              </div>
-              <div style="padding: 40px 10px">
-                <div
-                  class="c-table-title light"
-                  v-if="0"
-                  style="height: 50px; line-height: 50px"
-                >
-                  鍣ㄥ畼缁熻
-                </div>
-                <LineChart :cdata="anlidata" :height="height / 7 + 'px'" />
-                <Line2Chart :cdata="yiyuan" :height="height / 7 + 'px'" />
-                <Line1Chart :cdata="organsum" :height="height / 7 + 'px'" />
-                <BarChart :cdata="organData" :height="height / 7 + 'px'" />
-
-                <BarChart2
-                  :cdata="hosGetData"
-                  :height="(height / 7) * 2 + 'px'"
-                />
-
-                <BarChart3
-                  :cdata="organSumData"
-                  :height="(height - 10) / 7 + 'px'"
-                />
-              </div>
-            </dv-border-box-2>
-          </div>
-        </el-col>
-        <el-col :span="8" style="margin-top: 28px">
-          <dv-border-box-12 :color="['#1b88a3']" style="padding: -20px">
-            <div class="box-title" style="position: absolute; top: -8px">
-              <span><b>鍏ㄧ渷姒傚喌</b></span>
-            </div>
-            <div style="padding: 30px 20px 30px; margin: 0 auto">
-              <el-row>
-                <el-col :span="8" class="box-num">
-                  <div class="box-num-main" style="text-align: center">
-                    <p>娼滃湪鎹愮尞绱</p>
-                    <span class="box-num-main-n">{{
-                      leijishuju.processOrgans
-                    }}</span>
-                  </div>
-                  <div class="box-num-ex">
-                    <span></span>
-                  </div>
-                </el-col>
-                <el-col :span="8" class="box-num">
-                  <div class="box-num-main" style="text-align: center">
-                    <p>鎹愮尞瀹屾垚绱</p>
-                    <span class="box-num-main-n">{{
-                      leijishuju.finishedOrgans
-                    }}</span>
-                  </div>
-                  <div style="height: 20px"></div>
-                  <div class="box-num-ex">
-                    <span></span>
-                  </div>
-                </el-col>
-
-                <el-col :span="8" class="box-num">
-                  <div class="box-num-main" style="text-align: center">
-                    <p>鎹愮尞鍣ㄥ畼绱</p>
-                    <span class="box-num-main-n">{{
-                      leijishuju.Organsnum
-                    }}</span>
-                  </div>
-                  <div class="box-num-ex">
-                    <span></span>
-                  </div>
-                </el-col>
-              </el-row>
-              <el-row style="margin-bottom: 10px">
-                <el-col :span="12" class="box-num">
-                  <div class="box-num-main" style="text-align: center">
-                    <p>姣忕櫨涓囦汉鍙e櫒瀹樻崘鐚巼(PMP)</p>
-                    <span class="box-num-main-n">{{ leijishuju.PMP }}</span>
-                  </div>
-                  <div class="box-num-ex">
-                    <span></span>
-                  </div>
-                </el-col>
-                <el-col :span="12" class="box-num">
-                  <div class="box-num-main" style="text-align: center">
-                    <p>娼滅尞杞寲鐜�/鍣ㄥ畼浜у嚭鐜�/鍣ㄥ畼鍒╃敤鐜�</p>
-                    <span class="box-num-main-n">
-                      {{ leijishuju.donateTransferRate.toFixed(2) }}/{{
-                        leijishuju.organProductionRate.toFixed(2)
-                      }}/{{ leijishuju.organUsedRate.toFixed(2) }}</span
-                    >
-                  </div>
-                  <div class="box-num-ex">
-                    <span></span>
-                  </div>
-                </el-col>
-              </el-row>
-            </div>
-          </dv-border-box-12>
-          <dv-border-box-7 :color="['#fff']">
-            <dv-border-box-8>
-              <div style="padding: 40px 20px">
-                <div style="padding-top: 12px"></div>
-                <MapChart
-                  :cdata="cdata"
-                  :height="height - 220 + 'px'"
-                  @click="mapClick"
-                  :chartType="chartType"
-                /></div></dv-border-box-8
-          ></dv-border-box-7>
-        </el-col>
-        <el-col :span="8" v-loading="tableLoading" style="padding-top: 28px">
-          <dv-border-box-6 :color="['#1b88a3']">
-            <div class="box-title" style="position: absolute; top: -8px">
-              <span><b>鍗犳瘮缁熻</b></span>
-            </div>
-            <div
-              class="iwc-ring"
-              v-if="1"
-              style="
-                padding: 30px 10px 20px;
-                min-height: 280px;
-                text-align: center;
-              "
-            >
-              <el-row
-                ><el-col :span="8">
-                  <dv-active-ring-chart
-                    v-if="configSex.data.length > 0"
-                    :config="configSex"
-                    style="width: 100%; height: 100px"
-                  />
-                  <div>鎬у埆鍗犳瘮</div></el-col
-                ><el-col :span="8">
-                  <dv-active-ring-chart
-                    v-if="configAge.data.length > 0"
-                    :config="configAge"
-                    style="width: 100%; height: 100px"
-                  />
-                  <div>骞撮緞鍗犳瘮</div></el-col
-                ><el-col :span="8">
-                  <dv-active-ring-chart
-                    v-if="configDd.data.length > 0"
-                    :config="configDd"
-                    style="width: 100%; height: 100px"
-                  />
-                  <div>鎹愮尞鍒嗙被鍗犳瘮</div></el-col
-                ></el-row
-              >
-              <el-row
-                ><el-col :span="12">
-                  <dv-active-ring-chart
-                    v-if="configD.data.length > 0"
-                    :config="configD"
-                    style="width: 100%; height: 100px"
-                  />
-                  <div>鐤剧梾鍗犳瘮</div></el-col
-                ><el-col :span="12">
-                  <dv-active-ring-chart
-                    v-if="configX.data.length > 0"
-                    :config="configX"
-                    style="width: 100%; height: 100px"
-                  />
-                  琛�鍨嬪崰姣�</el-col
-                ></el-row
-              >
-            </div>
-            <div v-if="0" style="padding: 30px 10px 20px; min-height: 280px">
-              <el-row style="margin-bottom: 10px">
-                <el-col :span="7" style="text-align: right">鐢峰コ鍗犳瘮</el-col>
-                <el-col :span="17">
-                  <div style="display: flex; text-align: center">
-                    <div style="flex: 1">
-                      <span class="fc-white">鐢�</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.manRate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">濂�</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.womanRate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                  </div>
-                </el-col>
-              </el-row>
-              <el-row style="margin-bottom: 10px">
-                <el-col :span="7" style="text-align: right"
-                  >鎹愮尞鍒嗙被鍗犳瘮</el-col
-                >
-                <el-col :span="17">
-                  <div style="display: flex; text-align: center">
-                    <div style="flex: 1">
-                      <span class="fc-white">DBD</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.dbdrate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">DCD</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.dcdrate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">DBCD</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.dbcdrate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                  </div>
-                </el-col>
-              </el-row>
-
-              <el-row style="margin-bottom: 10px">
-                <el-col :span="7" style="text-align: right">骞撮緞鍗犳瘮</el-col>
-                <el-col :span="17">
-                  <div style="display: flex; text-align: center">
-                    <div style="flex: 1">
-                      <span class="fc-white">1-17宀�</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.a1Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">18-49宀�</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.a2Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">49-69宀�</span>&nbsp;<span
-                        class="fc-sp"
-                        >{{ (objZb.a3Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                  </div>
-                </el-col>
-              </el-row>
-              <el-row style="margin-bottom: 10px">
-                <el-col
-                  :span="24"
-                  style="margin-bottom: 10px; text-align: center"
-                  >琛�鍨嬪崰姣�</el-col
-                >
-                <el-col :span="24">
-                  <div style="display: flex; text-align: center">
-                    <div style="flex: 1">
-                      <span class="fc-white">A鍨�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.xarate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">B鍨�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.xbrate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">AB鍨�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.xabrate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">O鍨�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.xorate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                  </div>
-                </el-col>
-              </el-row>
-              <el-row>
-                <el-col
-                  :span="24"
-                  style="margin-bottom: 10px; text-align: center"
-                  >鐥呭洜鍗犳瘮</el-col
-                >
-                <el-col :span="24">
-                  <div style="display: flex; text-align: center">
-                    <div style="flex: 1">
-                      <span class="fc-white">鑴戣绠℃剰澶�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.d0Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">鑴戝浼�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.d1Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">缂鸿缂烘哀鎬ц剳鐥�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.d2Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">鑴戣偪鐦�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.d3Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                    <div style="flex: 1">
-                      <span class="fc-white">蹇冭绠$柧鐥�</span><br /><span
-                        class="fc-sp"
-                        >{{ (objZb.d4Rate * 100).toFixed(2) + "%" }}</span
-                      >
-                    </div>
-                  </div>
-                </el-col>
-              </el-row>
-            </div>
-          </dv-border-box-6>
-
-          <dv-border-box-6 :color="['#1b88a3']" style="margin-top: 30px">
-            <div class="box-title" style="position: absolute; top: -8px">
-              <span><b>鏈烘瀯缁熻</b></span>
-            </div>
-            <div style="padding: 20px">
-              <el-row class="c-table-title">
-                <el-col :span="18" :class="isAll ? 'active' : ''">
-                  <el-divider content-position="left"
-                    ><span>娴欐睙鐪�</span></el-divider
-                  ></el-col
-                >
-                <el-col :span="6"><el-divider></el-divider></el-col>
-              </el-row>
-              <dv-scroll-board
-                :config="tableConfig"
-                style="width: 100%; border: 1px solid #142984"
-                class="iwc-h-rb-table"
-                :style="{ height: height - 310 + 'px' }"
-              />
-            </div>
-          </dv-border-box-6>
-        </el-col>
-      </el-row> -->
-      <el-dialog title="鐧婚檰" :visible.sync="dialogVisible" width="30%">
-        <el-form :model="form">
-          <el-form-item label="璐﹀彿" label-width="80px">
-            <el-input
-              v-model="defaultAccount"
-              autocomplete="off"
-              @keyup.enter.native="loginFn"
-            ></el-input>
-          </el-form-item>
-          <el-form-item
-            label="瀵嗙爜"
-            label-width="80px"
+    <!-- 鐧诲綍寮圭獥 -->
+    <el-dialog
+      title="鐧诲綍"
+      :visible.sync="dialogVisible"
+      width="380px"
+      :close-on-click-modal="false"
+      :show-close="false"
+      append-to-body
+      custom-class="login-dialog"
+    >
+      <el-form :model="form" @submit.native.prevent>
+        <el-form-item label="璐﹀彿" label-width="60px">
+          <el-input
+            v-model="defaultAccount"
+            autocomplete="off"
+            placeholder="璇疯緭鍏ヨ处鍙�"
             @keyup.enter.native="loginFn"
-          >
-            <el-input
-              v-model="defaultPassword"
-              show-password
-              autocomplete="off"
-            ></el-input>
-          </el-form-item>
-          <el-form-item prop="code" label-width="80px">
-            <el-input
-              v-model="code"
-              auto-complete="off"
-              placeholder="楠岃瘉鐮�"
-              style="width: 63%"
-              @keyup.enter.native="loginFn"
-            >
-              <svg-icon
-                slot="prefix"
-                icon-class="validCode"
-                class="el-input__icon input-icon"
-              />
-            </el-input>
-            <div class="login-code">
-              <img :src="codeUrl" @click="getCode" class="login-code-img" />
-            </div>
-          </el-form-item>
-        </el-form>
-        <span slot="footer" class="dialog-footer">
-          <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
-          <el-button type="primary" @click="loginFn">纭� 瀹�</el-button>
-        </span>
-      </el-dialog>
-    </div>
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="瀵嗙爜" label-width="60px">
+          <el-input
+            v-model="defaultPassword"
+            show-password
+            autocomplete="off"
+            placeholder="璇疯緭鍏ュ瘑鐮�"
+            @keyup.enter.native="loginFn"
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍙� 娑�</el-button>
+        <el-button type="primary" :loading="loginLoading" @click="loginFn"
+          >鐧� 褰�</el-button
+        >
+      </span>
+    </el-dialog>
   </div>
 </template>
-<script>
-import {
-  getNumberOfOrgan,
-  getOrgansOfHospital,
-  getAllOrganInfo,
-  countDonateorgan,
-  countDonateHostipal,
-  countorganHostipal,
-  getDonateNumber,
-  getdonateBaseInfoByMonth,
-  getdonatePeopleByMonth,
-  getdonateNumberByMonth,
-  getdonateHospitalByMonth,
-  getacceptHospitalByMonths,
-  getOrgansOfHospitalByMonth,
-  getDonateorganPMP,
-  getDonateorganQuality,
-  getDonationwitnessStats,
-  getTransplantHospitalNum,
-  getDonateorganSum,
-  getDonateorganDistrictDonateCalculate
-} from "@/api/project/donateorgan";
-import { listData } from "@/api/system/dict/data";
-import { login, logout, getInfo, getCodeImg } from "@/api/login";
-import { listDonatebaseinfo } from "@/api/project/donatebaseinfo";
-import { getToken, setToken, removeToken } from "@/utils/auth";
-import MapChart from "./components/MapChart";
-import BarChart from "./components/BarChart";
-import BarChart2 from "./components/BarChart2";
-import BarChart3 from "./components/BarChart3";
-import BarChartH from "./components/BarChartH";
-import LineChart from "./components/lineChart";
-import Line1Chart from "./components/line1Chart";
-import Line2Chart from "./components/line2Chart";
 
-const DEF_TABLE_CONFIG = {
-  header: ["鍖哄煙", "鏈烘瀯", "鎹愮尞鐧昏", "鎹愮尞瀹屾垚"],
-  data: [],
-  headerBGC: "#0a3073",
-  oddRowBGC: "",
-  evenRowBGC: "",
-  rowNum: 6
+<script>
+import CountTo from 'vue-count-to';
+import G2PlotChart from '@/components/charts/G2PlotChart.vue';
+import MapChart from './components/MapChart';
+import { login } from '@/api/login';
+import { encrypts } from '@/utils/crypto';
+import { setToken, removeToken } from '@/utils/auth';
+import { xAxis, yAxis, legend, tooltip } from '@/utils/g2Dark';
+import { toMonth, toNum } from '@/utils/totals';
+import { mockCockpitData } from './cockpitMock';
+
+const AGE_LABELS = {
+  '1': '鈮�17宀�',
+  '2': '18-49宀�',
+  '3': '50-69宀�',
+  '4': '鈮�70宀�',
+  '0-17': '鈮�17宀�',
+  '18-49': '18-49宀�',
+  '50-69': '50-69宀�',
+  '70-100': '鈮�70宀�'
 };
 
 export default {
-  name: "home",
-  props: {},
-  components: {
-    MapChart,
-    BarChart,
-    BarChart2,
-    BarChart3,
-    BarChartH,
-    LineChart,
-    Line1Chart,
-    Line2Chart
-  },
+  name: 'home',
+  components: { CountTo, G2PlotChart, MapChart },
   data() {
     return {
-      img: {
-        head: require("../../assets/images/dv-head.png"),
-        btn1: require("../../assets/images/dv-btn-1.png"),
-        btn2: require("../../assets/images/dv-btn-2.png"),
-        btn3: require("../../assets/images/dv-btn-3.png"),
-        btn4: require("../../assets/images/dv-btn-4.png")
-      },
-      leijishuju: {},
-      arrrrr: [],
-      captchaOnOff: true,
-      uuid: "",
-      form: {},
-      hospitallist: [],
-      year: "",
-      code: "",
-      codeUrl: "",
+      now: '',
+      clockTimer: null,
+      carouselTimer: null,
+      loading: false,
+      loginLoading: false,
       dialogVisible: true,
-      isloading: false,
-      tableLoading: false,
-      showTable: false,
-      currentArea: null,
-      tableList: [],
-      defaultAccount: "",
-      defaultPassword: "",
-      pageData: {
-        pageNum: 1,
-        pageSize: 10
-      },
-      total: 0,
-      height: 1080,
-      width: 1920,
-      isAll: true,
-      chartType: "map",
-      tableConfig: { ...DEF_TABLE_CONFIG },
-      totalCount: 0,
-      allInfo: {
-        finishedOrgans: 0,
-        processOrgans: 4,
-        Organsnum: 0
-      },
-      anlidata: [
-        {
-          name: "1鏈�",
-          value: 0
-        },
-        {
-          name: "2鏈�",
-          value: 0
-        },
-        {
-          name: "3鏈�",
-          value: 0
-        },
-        {
-          name: "4鏈�",
-          value: 0
-        },
-        {
-          name: "5鏈�",
-          value: 0
-        },
-        {
-          name: "6鏈�",
-          value: 0
-        },
-        {
-          name: "7鏈�",
-          value: 0
-        },
-        {
-          name: "8鏈�",
-          value: 0
-        },
-        {
-          name: "9鏈�",
-          value: 0
-        },
-        {
-          name: "10鏈�",
-          value: 0
-        },
-        {
-          name: "11鏈�",
-          value: 0
-        },
-        {
-          name: "12鏈�",
-          value: 0
-        }
-      ],
-
-      organsum: [
-        {
-          name: "涓�鏈�",
-          value: 0
-        },
-        {
-          name: "浜屾湀",
-          value: 0
-        },
-        {
-          name: "涓夋湀",
-          value: 0
-        },
-        {
-          name: "鍥涙湀",
-          value: 0
-        },
-        {
-          name: "浜旀湀",
-          value: 0
-        },
-        {
-          name: "鍏湀",
-          value: 0
-        },
-        {
-          name: "涓冩湀",
-          value: 0
-        },
-        {
-          name: "鍏湀",
-          value: 0
-        },
-        {
-          name: "涔濇湀",
-          value: 0
-        },
-        {
-          name: "鍗佹湀",
-          value: 0
-        },
-        {
-          name: "鍗佷竴鏈�",
-          value: 0
-        },
-        {
-          name: "鍗佷簩鏈�",
-          value: 0
-        }
-      ],
-
-      yiyuan: [
-        {
-          name: "涓�鏈�",
-          value: 0
-        },
-        {
-          name: "浜屾湀",
-          value: 0
-        },
-        {
-          name: "涓夋湀",
-          value: 0
-        },
-        {
-          name: "鍥涙湀",
-          value: 0
-        },
-        {
-          name: "浜旀湀",
-          value: 0
-        },
-        {
-          name: "鍏湀",
-          value: 0
-        },
-        {
-          name: "涓冩湀",
-          value: 0
-        },
-        {
-          name: "鍏湀",
-          value: 0
-        },
-        {
-          name: "涔濇湀",
-          value: 0
-        },
-        {
-          name: "鍗佹湀",
-          value: 0
-        },
-        {
-          name: "鍗佷竴鏈�",
-          value: 0
-        },
-        {
-          name: "鍗佷簩鏈�",
-          value: 0
-        }
-      ],
-      organData: [
-        {
-          key: "heart",
-          name: "蹇冭剰",
-          value: 0
-        },
-        {
-          key: "fullLiver",
-          name: "鑲濊剰",
-          value: 0
-        },
-
-
-        {
-          key: "leftRenal",
-          name: "宸﹁偩",
-          value: 0
-        },
-        {
-          key: "rightRenal",
-          name: "鍙宠偩",
-          value: 0
-        },
-        {
-          key: "fullLung",
-          name: "鍏ㄨ偤",
-          value: 0
-        },
-        {
-          key: "leftLung",
-          name: "宸﹁偤",
-          value: 0
-        },
-        {
-          key: "rightLung",
-          name: "鍙宠偤",
-          value: 0
-        },
-        {
-          key: "leftEye",
-          name: "宸︾溂鑶�",
-          value: 0
-        },
-        {
-          key: "rightEye",
-          name: "鍙崇溂鑶�",
-          value: 0
-        }
-        //  閬椾綋鎹㈡垚鍏ㄨ倽浜�
-      ],
-
-      hosGetData: [],
-      configHosOrgan: {
-        data: [],
-        oddRowBGC: "",
-        evenRowBGC: "",
-        rowNum: 6
-      },
-      organSumData: [],
-      cdata: [
-        {
-          // 鍚嶅瓧闇�瑕佷笌 鈥渃ommon/map/zhejiang.js鈥� 鍦板浘鏁版嵁鏂囦欢閲岄潰瀹氫箟鐨勪竴涓�瀵瑰簲锛屼笉鑳芥槸 鈥滅宸炩�� 鎴栬�� 鈥滈椊鈥� 涔嬬被鐨勭缉鍐�
-          name: "鏉窞甯�",
-          district: "1",
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          district: "2",
-          name: "瀹佹尝甯�",
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          district: "3",
-          name: "娓╁窞甯�",
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "鍢夊叴甯�",
-          district: "4",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "婀栧窞甯�",
-          district: "5",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "缁嶅叴甯�",
-          district: "6",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "閲戝崕甯�",
-          district: "7",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "琛㈠窞甯�",
-          district: "8",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "鑸熷北甯�",
-          district: "9",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "鍙板窞甯�",
-          district: "A",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        },
-        {
-          name: "涓芥按甯�",
-          district: "B",
-
-          value: 0,
-          elseData: {
-            value2: 0,
-            value3: 0
-          }
-        }
-      ],
-      hospitalarr: [],
-      objZb: {}, //鍗犳瘮
-      arrZb: {},
-      currentZb: {
-        sex: -1,
-        age: -1,
-        type: -1,
-        d: -1,
-        x: -1
-      },
-      loopShowZb: null,
-      cdataYear: [],
-      organYearData: [],
-      configSex: {
-        data: [],
-        lineWidth: 6,
-        digitalFlopStyle: {
-          fontSize: 14
-        }
-      },
-      configAge: {
-        data: [],
-        lineWidth: 6,
-        digitalFlopStyle: {
-          fontSize: 14
-        }
-      },
-      configDd: {
-        data: [],
-        lineWidth: 6,
-        digitalFlopStyle: {
-          fontSize: 14
-        }
-      },
-      configD: {
-        data: [],
-        lineWidth: 6,
-        digitalFlopStyle: {
-          fontSize: 14
-        }
-      },
-      configX: {
-        data: [],
-        lineWidth: 6,
-        digitalFlopStyle: {
-          fontSize: 14
-        }
-      },
-      cityDonoateCaseArr: []
+      defaultAccount: '',
+      defaultPassword: '',
+      form: {},
+      carouselIndex: 0,
+      raw: {
+        mapData: [],
+        gauges: [],
+        caseTrend: [],
+        organMoon: [],
+        caseBloodType: [],
+        caseSex: [],
+        organType: [],
+        organDiscard: [],
+        caseTrendArea: [],
+        totals: [],
+        caseAvgAge: []
+      }
     };
   },
+  computed: {
+    kpiCards() {
+      const t = this.raw.totals[0] || {};
+      const potential = toNum(t.totalPotential);
+      const completed = toNum(t.totalCompletion);
+      const age = toNum((this.raw.caseAvgAge[0] || {}).avgAge);
+      const getTotal = this.raw.organMoon.reduce(
+        (s, i) => s + toNum(i.getCount),
+        0
+      );
+      const useTotal = this.raw.organMoon.reduce(
+        (s, i) => s + toNum(i.useCount),
+        0
+      );
+      return [
+        {
+          label: '鎬绘綔鍦ㄦ崘鐚渚�',
+          value: potential,
+          unit: '渚�',
+          icon: 'el-icon-s-flag',
+          gradient: 'linear-gradient(135deg,#1d4ed8,#38bdf8)'
+        },
+        {
+          label: '鎬诲畬鎴愭崘鐚�',
+          value: completed,
+          unit: '渚�',
+          icon: 'el-icon-circle-check',
+          gradient: 'linear-gradient(135deg,#059669,#34d399)'
+        },
+        {
+          label: '骞冲潎骞撮緞',
+          value: age,
+          unit: '宀�',
+          icon: 'el-icon-user',
+          decimals: 1,
+          gradient: 'linear-gradient(135deg,#7c3aed,#a78bfa)'
+        },
+        {
+          label: '鍣ㄥ畼鑾峰彇鎬绘暟',
+          value: getTotal,
+          unit: '涓�',
+          icon: 'el-icon-box',
+          gradient: 'linear-gradient(135deg,#0e7490,#22d3ee)'
+        },
+        {
+          label: '鍣ㄥ畼绉绘鎬绘暟',
+          value: useTotal,
+          unit: '涓�',
+          icon: 'el-icon-s-help',
+          gradient: 'linear-gradient(135deg,#d97706,#fbbf24)'
+        }
+      ];
+    },
+    gaugeCharts() {
+      return this.raw.gauges.map(g => ({ name: g.name, options: this.buildGauge(g) }));
+    },
+    trendOptions() {
+      const data = [];
+      this.raw.caseTrend.forEach(d => {
+        data.push({
+          time: this.fmtMonth(d.donateTime),
+          type: '娼滃湪鎹愮尞',
+          value: toNum(d.potentialCount)
+        });
+        data.push({
+          time: this.fmtMonth(d.donateTime),
+          type: '瀹屾垚鎹愮尞',
+          value: toNum(d.completeCount)
+        });
+      });
+      return {
+        data,
+        xField: 'time',
+        yField: 'value',
+        seriesField: 'type',
+        smooth: true,
+        color: ['#38a5f8', '#34d399'],
+        legend: legend(),
+        xAxis: xAxis(),
+        yAxis: yAxis(),
+        tooltip: tooltip(),
+        line: { size: 3 },
+        areaStyle: { fillOpacity: 0.16 }
+      };
+    },
+    organMoonOptions() {
+      const data = [];
+      this.raw.organMoon.forEach(d => {
+        data.push({
+          time: this.fmtMonth(d.donateTime),
+          type: '鑾峰彇',
+          value: toNum(d.getCount)
+        });
+        data.push({
+          time: this.fmtMonth(d.donateTime),
+          type: '绉绘',
+          value: toNum(d.useCount)
+        });
+      });
+      return {
+        data,
+        xField: 'time',
+        yField: 'value',
+        seriesField: 'type',
+        smooth: true,
+        color: ['#22d3ee', '#fbbf24'],
+        lineStyle: { lineWidth: 3 },
+        point: { size: 4, shape: 'circle' },
+        legend: legend(),
+        xAxis: xAxis(),
+        yAxis: yAxis(),
+        tooltip: tooltip()
+      };
+    },
+    // 鐢峰コ姣斾緥锛堟寜骞撮緞娈垫眹鎬讳负鎬讳綋鐢峰コ锛�
+    sexRatioOptions() {
+      let man = 0;
+      let woman = 0;
+      this.raw.caseSex.forEach(d => {
+        man += toNum(d.manCount);
+        woman += toNum(d.womanCount);
+      });
+      const data = [
+        { type: '鐢�', value: man },
+        { type: '濂�', value: woman }
+      ];
+      return {
+        data,
+        angleField: 'value',
+        colorField: 'type',
+        radius: 0.85,
+        innerRadius: 0.62,
+        color: ['#38a5f8', '#fb7185'],
+        label: {
+          type: 'spider',
+          content: '{percentage}',
+          style: { fill: '#c3cde4' }
+        },
+        legend: legend({ position: 'bottom' }),
+        tooltip: tooltip({ showTitle: false })
+      };
+    },
+    // 骞撮緞涓庢�у埆鍒嗗竷
+    ageSexOptions() {
+      const data = [];
+      this.raw.caseSex.forEach(d => {
+        const g = AGE_LABELS[d.ageGroup] || d.ageGroup;
+        data.push({ age: g, type: '鐢�', value: toNum(d.manCount) });
+        data.push({ age: g, type: '濂�', value: toNum(d.womanCount) });
+      });
+      return {
+        data,
+        xField: 'age',
+        yField: 'value',
+        seriesField: 'type',
+        isGroup: true,
+        columnWidthRatio: 0.4,
+        color: ['#38a5f8', '#fb7185'],
+        legend: legend(),
+        xAxis: xAxis(),
+        yAxis: yAxis(),
+        tooltip: tooltip()
+      };
+    },
+    organTypeOptions() {
+      const data = [];
+      this.raw.organType.forEach(d => {
+        data.push({ organ: d.organName, type: '鑾峰彇', value: toNum(d.getCount) });
+        data.push({ organ: d.organName, type: '绉绘', value: toNum(d.useCount) });
+      });
+      return {
+        data,
+        xField: 'value',
+        yField: 'organ',
+        seriesField: 'type',
+        isGroup: true,
+        barWidthRatio: 0.6,
+        color: ['#22d3ee', '#fbbf24'],
+        legend: legend(),
+        xAxis: yAxis(),
+        yAxis: xAxis(),
+        tooltip: tooltip()
+      };
+    },
+    // 鍣ㄥ畼寮冪敤鎯呭喌
+    discardOptions() {
+      const data = this.raw.organDiscard.map(d => ({
+        organ: d.organName,
+        value: toNum(d.discardCount)
+      }));
+      return {
+        data,
+        xField: 'organ',
+        yField: 'value',
+        columnWidthRatio: 0.5,
+        color: '#fb7185',
+        legend: false,
+        xAxis: xAxis({ label: { autoRotate: true } }),
+        yAxis: yAxis(),
+        tooltip: tooltip()
+      };
+    },
+    areaOptions() {
+      const data = [];
+      this.raw.caseTrendArea.forEach(d => {
+        const name = String(d.area || '').replace('鍦板尯', '');
+        data.push({
+          area: name,
+          type: '娼滃湪鎹愮尞',
+          value: toNum(d.potentialCount)
+        });
+        data.push({
+          area: name,
+          type: '瀹屾垚鎹愮尞',
+          value: toNum(d.completeCount)
+        });
+      });
+      return {
+        data,
+        xField: 'area',
+        yField: 'value',
+        seriesField: 'type',
+        isGroup: true,
+        columnWidthRatio: 0.45,
+        color: ['#38a5f8', '#34d399'],
+        legend: legend(),
+        xAxis: xAxis({ label: { autoRotate: true } }),
+        yAxis: yAxis(),
+        tooltip: tooltip()
+      };
+    },
+    carouselItems() {
+      return [
+        { title: '鐢峰コ姣斾緥', type: 'ring', options: this.sexRatioOptions },
+        { title: '鍣ㄥ畼绫诲瀷鍒嗗竷', type: 'bar', options: this.organTypeOptions },
+        { title: '鍣ㄥ畼寮冪敤鎯呭喌', type: 'column', options: this.discardOptions },
+        { title: '骞撮緞涓庢�у埆鍒嗗竷', type: 'column', options: this.ageSexOptions }
+      ];
+    },
+    currentCarousel() {
+      return this.carouselItems[this.carouselIndex] || this.carouselItems[0];
+    }
+  },
   created() {
-    this.height = window.innerHeight - 72;
-    this.getCode();
-    //this.getinfos();
-    //this.getOrgansOfHospitalByMonthss();
+    this.startClock();
   },
   mounted() {
     removeToken();
-    // let defaultAccount = "cockpit";
-    // let defaultPassword = "Admin@123";
+  },
+  beforeDestroy() {
+    if (this.clockTimer) clearInterval(this.clockTimer);
+    if (this.carouselTimer) clearInterval(this.carouselTimer);
   },
   methods: {
-    getCode() {
-      getCodeImg().then(res => {
-        this.captchaOnOff =
-          res.captchaOnOff === undefined ? true : res.captchaOnOff;
-        if (this.captchaOnOff) {
-          this.codeUrl = "data:image/gif;base64," + res.img;
-          this.uuid = res.uuid;
+    fmtMonth(value) {
+      const m = toMonth(value);
+      if (!m) return '';
+      const mm = Number(m.split('-')[1]);
+      return mm ? `${mm}鏈坄 : m;
+    },
+    buildGauge(g) {
+      const pct = g.max ? Math.min(Math.max(g.value / g.max, 0), 1) : 0;
+      const suffix = g.max === 100 ? '%' : '';
+      return {
+        percent: pct,
+        startAngle: Math.PI,
+        endAngle: Math.PI * 2,
+        radius: 0.85,
+        innerRadius: 0.72,
+        range: { color: [g.color, '#1c2a4d'], width: 10 },
+        axis: {
+          label: null,
+          tickLine: { style: { stroke: '#2a3a63' } }
+        },
+        indicator: {
+          pointer: { style: { stroke: '#e6edff', lineWidth: 2 } },
+          pin: { style: { stroke: '#e6edff', lineWidth: 2, r: 4 } }
+        },
+        statistic: {
+          content: {
+            content: `${g.value}${suffix}`,
+            style: {
+              color: '#ffffff',
+              fontSize: 30,
+              fontWeight: 700,
+              lineHeight: 1,
+              opacity: 1
+            }
+          }
         }
-      });
+      };
+    },
+    startClock() {
+      const tick = () => {
+        this.now = this.$moment().format('YYYY-MM-DD HH:mm:ss');
+      };
+      tick();
+      this.clockTimer = setInterval(tick, 1000);
+    },
+    startCarousel() {
+      if (this.carouselTimer) clearInterval(this.carouselTimer);
+      this.carouselTimer = setInterval(() => {
+        this.carouselIndex =
+          (this.carouselIndex + 1) % this.carouselItems.length;
+      }, 5000);
     },
     loginFn() {
-      login(this.defaultAccount, this.defaultPassword, this.code, this.uuid)
-        .then(async res => {
-          if (res.code == 200) {
+      if (!this.defaultAccount || !this.defaultPassword) {
+        this.$message.warning('璇疯緭鍏ヨ处鍙峰拰瀵嗙爜');
+        return;
+      }
+      this.loginLoading = true;
+      login(encrypts(this.defaultAccount), encrypts(this.defaultPassword))
+        .then(res => {
+          if (res.code === 200) {
             setToken(res.token);
             this.dialogVisible = false;
-            this.$message.success("鐧婚檰鎴愬姛");
-            const loading = this.$loading({
-              lock: true,
-              text: "Loading",
-              spinner: "el-icon-loading",
-              background: "rgba(0, 0, 0, 0.7)"
-            });
-            setTimeout(() => {
-              loading.close();
-            }, 2000);
-            await this.getDictData();
-            this.getinfos();
-            this.getData();
-            // this.getList();
-            this.getAllInfo();
-            this.getdonatecount();
-            this.getorgancount();
-            this.getDonateNumbers();
-            this.get();
-            this.getcountDonateHostipal();
-            //鎸夋湀搴︾粺璁$殑鍣ㄥ畼鏁�  鎶樼嚎鍥�
-            //this.getcurrentmonthorgan();
-            // this.getcurrentPeopleBymonth();
-            this.getOrgansOfHospitalByMonths();
-            //this.getOrgansOfHospitalByMonthss();
-            //resolve()
+            this.$message.success('鐧诲綍鎴愬姛');
+            this.loadData();
           } else {
-            this.$message.error(res.msg);
+            this.$message.error(res.msg || '鐧诲綍澶辫触');
           }
         })
-        .catch(error => {
-          // this.$message.error(error);
-          console.log(error);
-        });
-    },
-    getOrgansOfHospitalByMonthss() {
-      var date = new Date();
-      var year = date.getFullYear();
-      var month = date.getMonth();
-      month = Number(month) + 1;
-      if (month < 10) {
-        month = "0" + month;
-      }
-      var data = date.getDate();
-      if (data < 10) {
-        data = "0" + data;
-      }
-      var hours = date.getHours();
-      var minute = date.getMinutes();
-      var second = date.getSeconds();
-      var time =
-        year +
-        "-" +
-        month +
-        "-" +
-        data +
-        " " +
-        hours +
-        ":" +
-        minute +
-        ":" +
-        second;
-      let params = {
-        starttime: "1998-01-01 00:00:00",
-        endtime: time
-      };
-      getOrgansOfHospitalByMonth(params).then(res => {
-        let hospitalarr = res.data;
-        // this.hospitalarr = hospitalarr
-        let shi = [
-          { name: "鐪佹湰绾�", value: "0" },
-          { name: "鏉窞甯�", value: "1" },
-          { name: "瀹佹尝甯�", value: "2" },
-          { name: "娓╁窞甯�", value: "3" },
-          { name: "鍢夊叴甯�", value: "4" },
-          { name: "婀栧窞甯�", value: "5" },
-          { name: "缁嶅叴甯�", value: "6" },
-          { name: "閲戝崕甯�", value: "7" },
-          { name: "琛㈠窞甯�", value: "8" },
-          { name: "鑸熷北甯�", value: "9" },
-          { name: "鍙板窞甯�", value: "A" },
-          { name: "涓芥按甯�", value: "B" }
-        ];
-
-        for (let i = 0; i < hospitalarr.length; i++) {
-          for (let j = 0; j < shi.length; j++) {
-            if (hospitalarr[i].regionLevel == shi[j].value) {
-              hospitalarr[i].regionLevel = shi[j].name;
-            }
-          }
-        }
-      });
-    },
-
-    getOrgansOfHospitalByMonths() {
-      let curYear = this.$moment().year();
-      let params = {
-        starttime: this.$moment().format(curYear + "-01-01 00:00:00"),
-        endtime: this.$moment().format("YYYY-MM-DD 00:00:00")
-      };
-      getOrgansOfHospitalByMonth(params).then(res => {
-        let arr = [];
-        arr = res.data;
-        let shi = [
-          { name: "鐪佹湰绾�", value: "0" },
-          { name: "鏉窞甯�", value: "1" },
-          { name: "瀹佹尝甯�", value: "2" },
-          { name: "娓╁窞甯�", value: "3" },
-          { name: "鍢夊叴甯�", value: "4" },
-          { name: "婀栧窞甯�", value: "5" },
-          { name: "缁嶅叴甯�", value: "6" },
-          { name: "閲戝崕甯�", value: "7" },
-          { name: "琛㈠窞甯�", value: "8" },
-          { name: "鑸熷北甯�", value: "9" },
-          { name: "鍙板窞甯�", value: "A" },
-          { name: "涓芥按甯�", value: "B" }
-        ];
-        let newConfig = {
-          ...DEF_TABLE_CONFIG
-        };
-        let arrr = [];
-        for (let i = 0; i < arr.length; i++) {
-          for (let j = 0; j < shi.length; j++) {
-            if (arr[i].regionLevel == shi[j].value) {
-              arr[i].regionLevel = shi[j].name;
-            }
-          }
-          arrr.push({
-            regionLevel: arr[i].regionLevel,
-            hospitalName: arr[i].hospitalName,
-            donateNumber: arr[i].baseInfoCount,
-            acceptNumber: arr[i].completionCount
-          });
-        }
-        this.arrrrr = arrr;
-        newConfig.data = arrr;
-        this.tableConfig = newConfig;
-      });
-    },
-    refresh() {
-      if (this.showTable) {
-        this.getList();
-      } else {
-        this.getData();
-      }
-    },
-    //鏌辩姸鍥炬暟鎹�
-    getinfos() {},
-
-    //褰撳墠骞翠唤鎸夋湀搴︾粺璁$殑鎹愮尞鍣ㄥ畼鏁�
-    getcurrentmonthorgan() {
-      let nowYear = this.$moment().year();
-      let params = {
-        starttime: this.$moment(nowYear + "-01-01").format(
-          "YYYY-01-01 00:00:00"
-        ),
-        endtime: this.$moment().format("YYYY-MM-DD 00:00:00")
-      };
-      getdonateNumberByMonth(params).then(res => {
-        let donateorgans = res.data;
-        let arr1 = [];
-        let num = 0;
-        for (let i = 0; i < donateorgans.length; i++) {
-          num = donateorgans[i].donatemonth.substring(0, 4);
-          // if (this.year == num) {
-          arr1.push(donateorgans[i]);
-          for (let i = 0; i < arr1.length; i++) {
-            let month = arr1[i].donatemonth;
-            month = month.substring(month.length - 2, month.length);
-            let donatecount = arr1[i].donatecount;
-            this.organsum[month - 1].value = donatecount;
-          }
-          // }
-        }
-      });
-    },
-
-    getcountDonateHostipal() {
-      let nowYear = this.$moment().year();
-      let a = {
-        // starttime: "2020-01-01 00:00:00",
-        // endtime: "2022-02-01 00:00:00", //????
-        starttime: this.$moment(nowYear + "-01-01").format(
-          "YYYY-01-01 00:00:00"
-        ),
-        endtime: this.$moment().format("YYYY-MM-DD 00:00:00")
-      };
-      countDonateHostipal(a).then(res => {
-        let donateorgans = res.data;
-        let arr3 = [];
-        let num = 0;
-        for (let i = 0; i < donateorgans.length; i++) {
-          num = donateorgans[i].donatemonth.substring(0, 4);
-          arr3.push(donateorgans[i]);
-          for (let i = 0; i < arr3.length; i++) {
-            let month = arr3[i].donatemonth;
-            month = month.substring(month.length - 2, month.length);
-            let donatecount = arr3[i].donatecount;
-            this.yiyuan[month - 1].value = donatecount;
-          }
-        }
-      });
-    },
-
-    get() {},
-    //鎹愮尞绱淇℃伅
-    getDonateNumbers() {
-      let paramStartTime = null;
-      let nowDateYear = this.$moment().year();
-      paramStartTime = this.$moment(nowDateYear + "-01-01").format(
-        "YYYY-MM-DD HH:mm:ss"
-      );
-      let a = {
-        starttime: paramStartTime,
-        endtime: this.$moment().format("YYYY-MM-DD HH:mm:ss")
-      };
-
-      getDonateorganDistrictDonateCalculate(a).then(res => {
-        let cityCaseArr = [];
-        let data = res.data;
-        for (let i = 0; i < data.length; i++) {
-          let ii = this.cdata.findIndex(
-            item => item.district == data[i].district
-          );
-          if (ii > -1) {
-            this.cdata[ii].value = data[i].donateCount;
-            this.cdata[ii].elseData.value2 = data[i].completeCount;
-            this.cdata[ii].elseData.value3 = data[i].totalOrganCount;
-            cityCaseArr.push({
-              cityName: this.cdata[ii].name,
-              donoateNum: data[i].donateCount
-            });
-          }
-        }
-        this.cityDonoateCaseArr = cityCaseArr;
-      });
-      getDonateNumber(a).then(res => {
-        console.log("鎹愮尞绱淇℃伅", res);
-        this.leijishuju.processOrgans = res.data.numberOfDonate;
-        this.leijishuju.finishedOrgans = res.data.numberOfCompletion;
-        this.leijishuju.Organsnum = res.data.numberOfOrgans;
-      });
-
-      getDonateorganPMP(a).then(res => {
-        console.log("PMP", res);
-        let data = res.data;
-        this.leijishuju.PMP = ((data.pmprate * 100) / 64).toFixed(2);
-      });
-
-      getDonateorganQuality(a).then(res => {
-        let data = res.data;
-        this.leijishuju.donateTransferRate = data.donateTransferRate;
-        this.leijishuju.organProductionRate = data.organProductionRate;
-        this.leijishuju.organUsedRate = data.organUsedRate;
-        this.$forceUpdate();
-      });
-      getDonationwitnessStats(a).then(res => {
-        console.log("鍚勭鍗犳瘮", res);
-        let data = res.data;
-
-        this.objZb = { ...data };
-        this.arrZb = {
-          sex: [
-            { label: "鐢�", value: data.manRate },
-            { label: "濂�", value: data.womanRate }
-          ],
-          age: [
-            { label: "1-17宀�", value: data.a1Rate },
-            { label: "18-48宀�", value: data.a2Rate },
-            { label: "49-69宀�", value: data.a2Rate }
-          ],
-          type: [
-            { label: "DBD", value: data.dbdrate },
-            { label: "DCD", value: data.dcdrate },
-            { label: "DBCD", value: data.dbcdrate }
-          ],
-          d: [
-            { label: "鑴戣绠℃剰澶�", value: data.d0Rate },
-            { label: "鑴戝浼�", value: data.d1Rate },
-            { label: "缂鸿缂烘哀鎬ц剳鐥�", value: data.d2Rate },
-            { label: "鑴戣偪鐦�", value: data.d3Rate },
-            { label: "蹇冭绠$柧鐥�", value: data.d4Rate }
-          ],
-          x: [
-            { label: "A鍨�", value: data.xarate },
-            { label: "B鍨�", value: data.xbrate },
-            { label: "AB鍨�", value: data.xabrate },
-            { label: "O鍨�", value: data.xorate }
-          ]
-        };
-
-        window.clearInterval(this.loopShowZb);
-        this.loopShowZb = setInterval(() => {
-          if (this.currentZb.sex < this.arrZb.sex.length - 1) {
-            this.currentZb.sex += 1;
-          } else {
-            this.currentZb.sex = 0;
-          }
-          if (this.currentZb.age < this.arrZb.age.length - 1) {
-            this.currentZb.age += 1;
-          } else {
-            this.currentZb.age = 0;
-          }
-          if (this.currentZb.type < this.arrZb.type.length - 1) {
-            this.currentZb.type += 1;
-          } else {
-            this.currentZb.type = 0;
-          }
-          if (this.currentZb.d < this.arrZb.d.length - 1) {
-            this.currentZb.d += 1;
-          } else {
-            this.currentZb.d = 0;
-          }
-          if (this.currentZb.x < this.arrZb.x.length - 1) {
-            this.currentZb.x += 1;
-          } else {
-            this.currentZb.x = 0;
-          }
-        }, 3000);
-      });
-
-      getTransplantHospitalNum(a).then(res => {
-        console.log("姣忓绉绘鍖婚櫌鑾峰彇鐨勫櫒瀹樻�绘暟", res);
-        let data = res.data;
-        let list = data.map(item => {
-          return [item.orgName, item.organCount];
-        });
-        list = list.filter(item => !item[0].includes("鐪�"));
-        this.configHosOrgan.data = list;
-        this.hosGetData = data.map(item => {
-          return {
-            name: item.orgName,
-            value: item.organCount
-          };
-        });
-      });
-
-      getDonateorganSum(a).then(res => {
-        console.log("鍚勭鍣ㄥ畼鐨勮幏鍙栨�绘暟", res);
-        let data = res.data;
-        let list = this.organSumData.map(item => item);
-        for (let i = 0; i < data.length; i++) {
-          let k = data[i].organNo;
-          let ii = this.organSumData.findIndex(item => item.key == k);
-          if (ii > -1) {
-            this.organSumData[ii].value = data[i].count;
-          }
-        }
-      });
-
-      //鍘嗗勾鏁版嵁
-      let startTime = "2019-01-01 00:00:00";
-      let endTime = this.$moment().format("YYYY-01-01 00:00:00");
-      endTime = this.$moment(endTime)
-        .add(1, "years")
-        .format("YYYY-01-01 00:00:00");
-      let dYear = this.$moment(endTime).diff(this.$moment(startTime), "years");
-
-      if (dYear > 5) {
-        startTime ==
-          this.$moment(endtime)
-            .add(-5, "year")
-            .format("YYYY-01-01 00:00:00");
-      }
-
-      let arrYear = [];
-      for (let i = 0; i < 6; i++) {
-        let year = this.$moment(startTime)
-          .add(i, "year")
-          .format("YYYY");
-        if (i >= dYear) {
-          year = "";
-          continue;
-        }
-        arrYear.push({
-          year: year,
-          num: year ? 0 : ""
-        });
-      }
-      let params = {
-        starttime: startTime,
-        endtime: endTime
-      };
-      // getdonateNumberByMonth ???//甯︽敞閲�
-      getdonatePeopleByMonth(params).then(res => {
-        let data = res.data;
-        for (let i = 0; i < data.length; i++) {
-          let year = this.$moment(data[i].donatemonth).format("YYYY");
-
-          let ii = arrYear.findIndex(item => item.year == year);
-          if (ii > -1) {
-            arrYear[ii].num += data[i].donatecount;
-          }
-        }
-        this.cdataYear = arrYear;
-        console.log("cdataYear:" + JSON.stringify(this.cdataYear));
-      });
-    },
-
-    async getDictData() {
-      try {
-        let res = await listData({
-          pageNum: 1,
-          pageSize: 20,
-          dictType: "sys_Organ"
-        });
-        let list = res.rows.map(item => {
-          return {
-            key: item.dictValue,
-            name: item.dictLabel,
-            value: 0
-          };
-        });
-        this.organSumData = list.filter(it => it.key != "C00");
-      } catch (e) {}
-    },
-
-    async getdonatecount() {
-      let nowDateYear = this.$moment().year();
-      let nowDateMonth = this.$moment().month() + 1;
-      let startTime;
-      let endTime = this.$moment()
-        .add(1, "month")
-        .format("YYYY-MM-01");
-      if (nowDateMonth <= 5) {
-        startTime = this.$moment()
-          .add(-6, "month")
-          .format("YYYY-MM-01");
-      } else {
-        startTime = this.$moment().format(nowDateYear + "-01-01");
-      }
-
-      let donateorgans = [];
-      let organList = [];
-
-      let params = {
-        starttime: startTime,
-        endtime: endTime
-      };
-
-      try {
-        let res = await countDonateorgan(params);
-        donateorgans = res.data;
-        console.log("donateorgans:" + JSON.stringify(donateorgans));
-      } catch (e) {}
-      //debugger
-      try {
-        let res = await getdonateNumberByMonth(params);
-        organList = res.data;
-        console.log("organList:" + JSON.stringify(organList));
-      } catch (e) {}
-      //debugger
-      console.log(donateorgans);
-      let arr = [];
-      for (let i = 0; i < 12; i++) {
-        //缁熻鎹愮尞妗堜緥鏈堝害缁熻鏁版嵁
-        let mm = this.$moment(startTime)
-          .add(i, "month")
-          .format("YYYY-MM");
-        let num = "";
-        let num2 = "";
-        let ii = donateorgans.findIndex(item => item.donatemonth == mm);
-        if (ii > -1) {
-          num = donateorgans[ii].donatecount;
-        }
-        let oi = organList.findIndex(item => item.donatemonth == mm);
-        if (oi > -1) {
-          num2 = organList[oi].donatecount;
-        }
-        arr.push({
-          name: this.$moment(mm).format("M鏈�"),
-          value: num,
-          value2: num2
-        });
-      }
-
-      let organYearArr = [];
-      this.anlidata = arr;
-
-      for (let k = 0; k < organList.length; k++) {
-        let yearNo = this.$moment(organList[k].donatemonth + "-01").format(
-          "YYYY"
-        );
-        let organNum = organList[k].donatecount;
-        //鍒ゆ柇褰撳墠骞翠唤鏄惁鍦ㄦ暟缁勪腑
-        let yearIndex = organYearArr.findIndex(item => item.year == yearNo);
-        if (yearIndex > -1) {
-          organYearArr[yearIndex].num += organNum;
-        } else {
-          organYearArr.push({ year: yearNo, num: organNum });
-        }
-      }
-      this.organYearData = organYearArr;
-    },
-    getorgancount() {},
-
-    getData() {},
-
-    getAllInfo() {
-      let params = {
-        starttime: "2022-01-01 00:00:00",
-        endtime: this.$moment().format("YYYY-MM-DD HH:mm:ss")
-      };
-      getAllOrganInfo(params)
-        .then(response => {
-          if (response.data) {
-            this.allInfo = response.data;
-            let list = this.organData.map(item => item);
-            for (let i = 0; i < list.length; i++) {
-              let k = list[i].key;
-              if (this.allInfo[k]) {
-                list.value = this.allInfo[k];
-                this.organData[i].value = list.value;
-              }
-            }
-            this.organData = list;
-            let organsums = 0;
-          }
+        .catch(() => {
+          // 璇锋眰澶辫触鐢� request 鎷︽埅鍣ㄧ粺涓�鎻愮ず
         })
-        .catch(erroe => {})
-        .finally(() => {});
+        .finally(() => {
+          this.loginLoading = false;
+        });
     },
-    async getTempList() {
-      let total = 0;
-      let pageIndex = 1;
-      let list = [];
+    handleLogout() {
+      removeToken();
+      this.dialogVisible = true;
+      this.$message.info('宸查��鍑虹櫥褰�');
+    },
+    mapClick() {
+      // 鍖哄幙鐐瑰嚮鍙湪姝ゆ墿灞曚笅閽�
+    },
+    async loadData() {
+      this.loading = true;
       try {
-        let searchInfo = {
-          pageNum: 1,
-          pageSize: 1
-        };
-        let response = await listDonatebaseinfo(searchInfo);
-        this.totalCount = response.total;
-      } catch (error) {}
-    },
-    mapClick(data) {
-      let newConfig = {
-        ...DEF_TABLE_CONFIG
-      };
-      let arr = [];
-      for (let i = 0; i < this.arrrrr.length; i++) {
-        if (data.name == this.arrrrr[i].regionLevel) {
-          arr.push(this.arrrrr[i]);
-        }
+        // 鍚庣鎺ュ彛灏辩华鍚庯紝灏嗕笅闈㈡ā鎷熸暟鎹浛鎹负鐪熷疄鎺ュ彛锛�
+        // 瓒嬪娍/鎬у埆/鍣ㄥ畼/鍦板尯/KPI 鈫� /opo/totals/*锛園/api/businessApi/statistics.js锛�
+        // 鍖哄幙鍦板浘 鈫� getDonateorganDistrictDonateCalculate锛�
+        // 浠〃鐩� 鈫� getDonateorganQuality / getDonateorganPMP锛�
+        // 鍣ㄥ畼寮冪敤 鈫� 缁熻妯″潡鍣ㄥ畼寮冪敤鐩稿叧鎺ュ彛锛園/api/businessApi/statistics.js锛�
+        const m = mockCockpitData();
+        this.raw.mapData = m.mapData;
+        this.raw.gauges = m.gauges;
+        this.raw.caseTrend = m.caseTrend;
+        this.raw.organMoon = m.organMoon;
+        this.raw.caseBloodType = m.caseBloodType;
+        this.raw.caseSex = m.caseSex;
+        this.raw.organType = m.organType;
+        this.raw.organDiscard = m.organDiscard;
+        this.raw.caseTrendArea = m.caseTrendArea;
+        this.raw.totals = m.totals;
+        this.raw.caseAvgAge = m.caseAvgAge;
+        this.startCarousel();
+      } catch (e) {
+        console.error('椹鹃┒鑸辨暟鎹姞杞藉け璐�', e);
+      } finally {
+        this.loading = false;
       }
-      newConfig.data = arr;
-      this.tableConfig = newConfig;
-      // let name = data.name;
-      // let arr = [];
-
-      // for(let i=0;i<this.arrrrr.length;i++){
-      //   if(this.arrrr[i].regionLevel == name){
-      //     arr.push({
-      //      regionLevel   : this.arrrrr[i].regionLevel,
-      //       hospitalName  : this.arrrrr[i].hospitalName,
-      //      donateNumber  : this.arrrrr[i].baseInfoCount,
-      //      acceptNumber  : this.arrrrr[i].completionCount
-      //     })
-      //   }
-      // }
-      //   this.arrrr = arr;
-      // this.currentArea = { ...data };
-      // this.tableList = [];
-      // this.total = 0;
-      // this.pageData.pageNum = 1;
-      // this.showTable = true;
-      // this.getList(data.name);
-    },
-    getRanNum() {
-      return Math.round(Math.random() * 40);
-    }
-  },
-  computed: {
-    heightA() {
-      let h = (this.height * 0.36 - 54) / 5;
-      return h;
-    },
-    totalValue() {
-      let sum = 0;
-      for (let i = 0; i < this.cdata.length; i++) {
-        sum += this.cdata[i].value;
-      }
-      return sum;
-    },
-    totalValue2() {
-      let sum = 0;
-      for (let i = 0; i < this.cdata.length; i++) {
-        sum += this.cdata[i].elseData.value2;
-      }
-      return sum;
-    },
-    totalValue3() {
-      let sum = 0;
-      for (let i = 0; i < this.cdata.length; i++) {
-        sum += this.cdata[i].elseData.value3;
-      }
-      return sum;
     }
   }
 };
 </script>
 
 <style lang="scss" scoped>
-#app {
-  overflow: hidden;
+.cockpit {
+  min-height: 100vh;
+  padding: 14px 16px 20px;
+  box-sizing: border-box;
+  color: #e6edff;
+  background: radial-gradient(
+      1200px 640px at 18% -10%,
+      #12275a 0%,
+      rgba(18, 39, 90, 0) 60%
+    ),
+    radial-gradient(1000px 600px at 110% 10%, #0c2a52 0%, rgba(12, 42, 82, 0) 55%),
+    linear-gradient(180deg, #0a1226 0%, #070c1c 60%, #050812 100%);
 }
-.iwc-dv-box {
-  .iwc-box-head {
-    text-align: center;
-    font-size: 18px;
-    padding: 7px 0 25px;
-    color: #fff;
-    background-image: url("../../assets/images/dv-box-title.png");
-    background-size: 100% 150%;
-    height: 54px;
-  }
-  .iwc-box-a {
-    font-size: 13px;
-    .iwc-box-a-1 {
-      color: #5ba2ff;
-      margin-bottom: 5px;
-    }
-  }
-  .iwc-before-o {
-    display: inline-block;
-    width: 11px;
-    height: 10px;
-    border-radius: 50%;
-    border: 0.15rem solid;
-    margin-right: 0.5rem;
-  }
-  .iwc-box-c {
-    display: flex;
-    padding: 1rem 0;
-    .iwc-box-c1 {
-      flex: 1;
-      font-size: 1rem;
-      text-align: center;
-      .iwc-box-c1-o {
-        display: inline-block;
-        width: 3.6rem;
-        height: 3.6rem;
-        line-height: 3.6rem;
-        margin: 0 auto;
-        border: 0.2rem solid;
-        border-radius: 50%;
-      }
-      .iwc-box-c1-l {
-        padding: 1rem 0;
-      }
-    }
-  }
+::v-deep .el-loading-mask {
+  background-color: rgba(5, 8, 18, 0.75);
 }
-.iwc-box-d {
-  display: flex;
-  padding-top: 2rem;
-  .iwc-box-d-1 {
-    flex: 1;
-    position: relative;
-    .iwc-box-d-img {
-      width: 3.6rem;
-      height: 3.6rem;
-      position: absolute;
-    }
-  }
-  .iwc-box-d-f {
-    padding-left: 4rem;
-    padding-top: 0.5rem;
-    .iwc-box-d-f1 {
-      font-size: 1.4rem;
-      color: #07dbff;
-      height: 2rem;
-    }
-    .iwc-box-d-f2 {
-      color: #fff;
-      font-size: 0.75rem;
-    }
-  }
-}
-.c-home {
-  .fc-white {
-    color: #fff;
-  }
-  .fc-sp {
-    color: #409eff;
-  }
-  .box-title {
-    width: 100%;
-    span {
-      display: block;
-      width: 130px;
-      height: 25px;
-      -webkit-transform: skew(20deg);
-      -moz-transform: skew(20deg);
-      -o-transform: skew(20deg);
-      background: #1356a1;
-      line-height: 25px;
-      align-self: center;
-      border: 1px transparent solid;
-      border-image: linear-gradient(#070a17, #7be6fc) 10 10;
-      border-image: linear-gradient(#070a17, #7be6fc) 10 10;
-      border-image: linear-gradient(#070a17, #7be6fc) 10 10;
-      margin: 0 auto;
-    }
-    b {
-      display: block;
-      color: #fff;
-      text-align: center;
-      transform: skewY(-20deg);
-      transform: skewX(-20deg);
-    }
-  }
-  .box-num {
-    position: relative;
-    .box-num-main {
-      p {
-        margin: 0 0 10px;
-      }
-      text-align: right;
-      .box-num-main-n {
-        color: #409eff;
-        font-size: 25px;
-      }
-    }
-    .box-num-ex {
-      position: absolute;
-      bottom: 5px;
-      right: 10px;
-      width: 45px;
 
-      span {
-        color: #409eff;
-        font-size: 12px;
-      }
-    }
+/* 椤堕儴鏍囬鏍� */
+.cockpit-header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 6px 4px 14px;
+  .header-left {
+    display: flex;
+    align-items: center;
   }
-}
-::v-deep .c-table-title {
-  .el-divider.el-divider--horizontal {
-    background-color: #95a1ec;
-    .el-divider__text.is-left {
-      color: #303133;
-      background: #fafafa;
-    }
+  .header-logo {
+    width: 10px;
+    height: 26px;
+    border-radius: 3px;
+    margin-right: 12px;
+    background: linear-gradient(180deg, #38a5f8, #22d3ee);
+    box-shadow: 0 0 12px rgba(56, 165, 248, 0.7);
   }
-  .active {
-    .el-divider.el-divider--horizontal {
-      .el-divider__text.is-left {
-        color: #409eff;
-      }
-    }
+  .header-title {
+    margin: 0;
+    font-size: 22px;
+    font-weight: 700;
+    letter-spacing: 2px;
+    background: linear-gradient(90deg, #eaf2ff, #6db8ff);
+    -webkit-background-clip: text;
+    background-clip: text;
+    -webkit-text-fill-color: transparent;
   }
-}
-::v-deep .iwc-ring {
-  .dv-active-ring-chart .active-ring-info .active-ring-name {
-    position: absolute;
-    top: 82px;
+  .header-right {
+    display: flex;
+    align-items: center;
   }
-}
-::v-deep .iwc-box-b-table.dv-scroll-board {
-  .rows {
-    .row-item:nth-child(2) {
-      border: 1px solid #02406e;
-      background-color: rgba(19, 187, 206, 0.13);
-      background-blend-mode: multiply;
-      //filter: drop-shadow(3px 3px 4px #07dbff);
-      box-shadow: 0 0 10px rgb(0, 153, 184) inset;
-    }
-    .ceil:nth-child(1) {
-      flex: 1;
-    }
-    .ceil:nth-child(2) {
-      width: 70px !important;
-    }
-  }
-}
-::v-deep .iwc-h-rb-table.dv-scroll-board {
-  .header {
-    color: #07dbff;
-    .header-item:nth-child(1) {
-      width: 70px !important;
-    }
-    .header-item:nth-child(2) {
-      flex: 1;
-    }
-    .header-item:nth-child(3) {
-      width: 80px !important;
-    }
-    .header-item:nth-child(4) {
-      width: 80px !important;
-    }
-  }
-  .rows {
-    .row-item {
-      border-bottom: 1px solid #036492;
-    }
-    .row-item:nth-child(2) {
-      border: 1px solid #07dbff;
-      background-color: rgba(19, 187, 206, 0.13);
-      background-blend-mode: multiply;
-      box-shadow: 0 0 10px rgb(0, 153, 184) inset;
-      //filter: drop-shadow(3px 3px 4px #07dbff);
-    }
-    .ceil:nth-child(1) {
-      width: 70px;
-    }
-    .ceil:nth-child(2) {
-      flex: 1;
-      padding-left: 0;
-      padding-right: 0;
-    }
-    .ceil:nth-child(3) {
-      width: 80px;
-      text-align: center;
-      padding-left: 0;
-      padding-right: 0;
-    }
-    .ceil:nth-child(4) {
-      width: 80px;
-      text-align: center;
-      padding-left: 0;
-      padding-right: 0;
-    }
-  }
-}
-::v-deep .el-dialog {
-  -webkit-transform: none;
-  transform: none;
-  background-color: rgb(3, 14, 64);
-  box-shadow: rgb(10, 51, 110) 0px 0px 40px inset;
-  border: 1px solid rgb(10, 51, 110);
-  color: #fff !important;
-  left: 0;
-  position: relative;
-  margin: 0 auto;
-  .el-dialog__title {
-    color: #fff;
-  }
-  .el-form-item__label {
-    text-align: right;
-    vertical-align: middle;
-    float: left;
+  .header-clock {
+    color: #9aa7c7;
     font-size: 14px;
+    font-variant-numeric: tabular-nums;
+    letter-spacing: 1px;
+    margin-right: 16px;
+  }
+  .header-logout {
+    color: #9aa7c7;
+    &:hover {
+      color: #38a5f8;
+    }
+  }
+}
+
+/* KPI 鎸囨爣鍗� */
+.kpi-row {
+  display: grid;
+  grid-template-columns: repeat(5, 1fr);
+  gap: 16px;
+  margin-bottom: 16px;
+}
+.kpi-card {
+  display: flex;
+  align-items: center;
+  padding: 12px 16px;
+  border-radius: 12px;
+  border: 1px solid rgba(90, 120, 190, 0.28);
+  background: linear-gradient(
+    135deg,
+    rgba(40, 52, 96, 0.72),
+    rgba(16, 24, 52, 0.9)
+  );
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
+}
+.kpi-icon {
+  width: 44px;
+  height: 44px;
+  flex-shrink: 0;
+  border-radius: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 22px;
+  color: #fff;
+  margin-right: 12px;
+  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
+}
+.kpi-body {
+  min-width: 0;
+}
+.kpi-label {
+  font-size: 13px;
+  color: #8aa0c8;
+  margin-bottom: 2px;
+}
+.kpi-value {
+  font-size: 24px;
+  font-weight: 700;
+  color: #fff;
+  line-height: 1.2;
+}
+.kpi-unit {
+  font-size: 13px;
+  font-weight: 400;
+  color: #8aa0c8;
+  margin-left: 4px;
+}
+
+/* 浠〃鐩樿 */
+.gauge-row {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: 16px;
+  margin-bottom: 16px;
+}
+
+/* 闈㈡澘 */
+.panel {
+  height: 100%;
+  padding: 14px 16px;
+  border-radius: 12px;
+  border: 1px solid rgba(80, 110, 180, 0.25);
+  background: linear-gradient(
+    180deg,
+    rgba(25, 35, 70, 0.82),
+    rgba(13, 20, 43, 0.82)
+  );
+  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
+  box-sizing: border-box;
+}
+.panel-title {
+  position: relative;
+  font-size: 15px;
+  font-weight: 600;
+  color: #dbe4ff;
+  margin-bottom: 10px;
+  padding-left: 12px;
+  &::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 2px;
+    bottom: 2px;
+    width: 4px;
+    border-radius: 2px;
+    background: linear-gradient(180deg, #38a5f8, #22d3ee);
+  }
+}
+
+/* 宸﹀彸涓ゅ垪鍫嗗彔 */
+.col-stack {
+  display: flex;
+  flex-direction: column;
+  gap: 16px;
+  height: 100%;
+  .panel {
+    flex: 1;
+  }
+}
+
+/* 杞挱 */
+.panel--carousel {
+  position: relative;
+}
+.carousel-body {
+  height: 205px;
+}
+.carousel-dots {
+  position: absolute;
+  right: 16px;
+  top: 16px;
+  display: flex;
+  gap: 6px;
+}
+.dot {
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  background: rgba(120, 140, 190, 0.35);
+  cursor: pointer;
+  transition: all 0.3s;
+  &.active {
+    width: 20px;
+    border-radius: 4px;
+    background: #38a5f8;
+  }
+}
+.fade-enter-active,
+.fade-leave-active {
+  transition: opacity 0.4s;
+}
+.fade-enter,
+.fade-leave-to {
+  opacity: 0;
+}
+</style>
+
+<!-- 鐧诲綍寮圭獥閫氳繃 append-to-body 鎸傚埌 body 涓嬶紝scoped 鏍峰紡鏃犳硶鍛戒腑锛屾晠鐢ㄥ叏灞�鏍峰紡 -->
+<style lang="scss">
+.el-dialog.login-dialog {
+  background: linear-gradient(180deg, rgba(28, 40, 78, 0.97), rgba(13, 20, 43, 0.99));
+  border: 1px solid rgba(74, 120, 200, 0.45);
+  border-radius: 14px;
+  box-shadow: 0 0 0 1px rgba(56, 165, 248, 0.12), 0 0 44px rgba(56, 165, 248, 0.28),
+    0 24px 60px rgba(0, 0, 0, 0.55);
+  overflow: hidden;
+
+  .el-dialog__header {
+    padding: 22px 26px 14px;
+    border-bottom: 1px solid rgba(74, 120, 200, 0.22);
+  }
+  .el-dialog__title {
+    color: #eaf2ff;
+    font-size: 18px;
+    font-weight: 600;
+    letter-spacing: 2px;
+    &::before {
+      content: '';
+      display: inline-block;
+      width: 4px;
+      height: 16px;
+      margin-right: 10px;
+      border-radius: 2px;
+      background: linear-gradient(180deg, #38a5f8, #22d3ee);
+      box-shadow: 0 0 8px rgba(56, 165, 248, 0.8);
+      vertical-align: -2px;
+    }
+  }
+  .el-dialog__body {
+    padding: 26px 26px 8px;
+    color: #c3cde4;
+  }
+  .el-dialog__footer {
+    padding: 8px 26px 24px;
+    text-align: right;
+  }
+
+  .el-form-item__label {
+    color: #aab6d4;
+    font-weight: 500;
+    letter-spacing: 1px;
+  }
+  .el-input__inner {
+    background: rgba(8, 15, 34, 0.9);
+    border: 1px solid rgba(90, 124, 200, 0.35);
+    border-radius: 6px;
+    color: #e6edff;
+    transition: border-color 0.25s, box-shadow 0.25s;
+    &::placeholder {
+      color: rgba(154, 167, 199, 0.6);
+    }
+    &:hover {
+      border-color: rgba(90, 124, 200, 0.55);
+    }
+    &:focus {
+      border-color: #38a5f8;
+      box-shadow: 0 0 0 3px rgba(56, 165, 248, 0.18);
+    }
+  }
+
+  .el-button {
+    background: rgba(24, 36, 68, 0.9);
+    border: 1px solid rgba(90, 124, 200, 0.4);
+    color: #c3cde4;
+    &:hover {
+      border-color: #38a5f8;
+      color: #eaf2ff;
+    }
+  }
+  .el-button--primary {
+    background: linear-gradient(135deg, #2563eb, #22d3ee);
+    border: none;
     color: #fff;
-    line-height: 40px;
-    padding: 0 12px 0 0;
-    -webkit-box-sizing: border-box;
-    box-sizing: border-box;
+    box-shadow: 0 4px 14px rgba(56, 165, 248, 0.4);
+    &:hover,
+    &:focus {
+      background: linear-gradient(135deg, #2f6ff0, #2fd8f2);
+      color: #fff;
+    }
   }
-}
-::v-deep .iwc-box-a {
-  .el-progress-bar__outer {
-    background-color: #29345c;
-  }
-  .el-progress-bar__innerText {
-    margin-right: -27px;
-  }
-}
-.login-code {
-  width: 33%;
-  height: 38px;
-  float: right;
-  img {
-    cursor: pointer;
-    vertical-align: middle;
-  }
-}
-.login-code-img {
-  height: 38px;
 }
 </style>

--
Gitblit v1.9.3