From 04477a62f8966e9aabc31421bab138960eff323e Mon Sep 17 00:00:00 2001
From: hejianhao <15708179461@qq.com>
Date: 星期三, 26 三月 2025 15:57:29 +0800
Subject: [PATCH] 除地图外所有接口对接、样式调整

---
 src/components/LeftPanel.vue |  268 +++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 187 insertions(+), 81 deletions(-)

diff --git a/src/components/LeftPanel.vue b/src/components/LeftPanel.vue
index e75b923..edc191b 100644
--- a/src/components/LeftPanel.vue
+++ b/src/components/LeftPanel.vue
@@ -9,13 +9,13 @@
         <div class="stat-item">
           <div class="stat-info">
             <div class="stat-label"> <i class="icon-area"></i> 房屋总面积</div>
-            <div class="stat-value">{{ totalArea }}<span class="unit">m²</span></div>
+            <div class="stat-value">{{ staticsData.houseTotalArea }}<span class="unit">m²</span></div>
           </div>
         </div>
         <div class="stat-item">
           <div class="stat-info">
             <div class="stat-label"> <i class="icon-area"></i>已出租面积</div>
-            <div class="stat-value">{{ rentedArea }}<span class="unit">m²</span></div>
+            <div class="stat-value">{{ staticsData.houseRentedArea }}<span class="unit">m²</span></div>
           </div>
         </div>
       </div>
@@ -23,107 +23,147 @@
         <div class="stat-group">
           <div class="stat-item mt-10">
             <div class="stat-info">
-              <div class="stat-label"> <i class="icon-money"></i>今日已收租金</div>
-              <div class="stat-value">{{ todayRent }}<span class="unit">万元</span></div>
+              <div class="stat-label"> <i class="icon-money"></i>总计应收租金</div>
+              <div class="stat-value">{{ staticsData.totalReceivableRent }}<span class="unit">万元</span></div>
             </div>
           </div>
           <div class="stat-item mt-10">
             <div class="stat-info">
-              <div class="stat-label"><i class="icon-money"></i>今日已收租金</div>
-              <div class="stat-value">{{ todayIncome }}<span class="unit">万元</span></div>
+              <div class="stat-label"><i class="icon-money"></i>总计已收租金</div>
+              <div class="stat-value">{{ staticsData.totalReceivedRent }}<span class="unit">万元</span></div>
             </div>
           </div>
         </div>
       </div>
     </div>
     <div class="chart-card" style="width: 350px;">
-      <div class="chart-title">区域租金分析</div>
-      <div class="area-chart" ref="areaRentChart"></div>
+      <div class="chart-title">区域租金排名</div>
+      <div class="chart-unit">单位(万元)</div>
+      <div class="rent-rank-list" ref="scrollContainer" @mouseenter="stopScroll" @mouseleave="startScroll">
+        <div class="rank-list-content" ref="scrollContent">
+          <div class="rank-list-group">
+            <div v-for="(item, index) in displayRank" :key="index" class="rent-rank-item">
+              <div class="rank-name">{{ item.streetName }}</div>
+              <div class="rank-progress">
+                <div class="rank-bar">
+                  <div class="rank-bar-inner" :style="{
+                    width: (item.rentAmount / Math.max(...rentRank.map(i => i.rentAmount)) * 100) + '%',
+                    background: getBarColor(item.rentAmount)
+                  }"></div>
+                </div>
+                <div class="rank-value">{{ item.rentAmount }}</div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
     </div>
   </div>
 </template>
 
 <script>
-import * as echarts from 'echarts'
-
 export default {
   name: 'LeftPanel',
+  props: {
+    staticsData: {
+      type: Object,
+      default: () => { }
+    },
+    rentRank: {
+      type: Array,
+      default: () => []
+    }
+  },
   data() {
     return {
-      totalArea: '386.5',
-      rentedArea: '316.5',
-      todayRent: '316.5',
-      todayIncome: '124.5',
-      charts: {
-        areaRent: null
+      scrollTimer: null,
+      isScrolling: true,
+      currentTranslate: 0,
+      firstItemHeight: 0,
+      animationFrameId: null,
+      lastTimestamp: 0,
+      displayRank: []
+    }
+  },
+  watch: {
+    rentRank: {
+      immediate: true,
+      handler(newVal) {
+        if (newVal && newVal.length) {
+          // 复制两组数据用于无缝滚动
+          this.displayRank = [...newVal, ...newVal];
+        }
       }
     }
   },
   mounted() {
     this.$nextTick(() => {
-      this.initCharts()
-    })
+      const firstItem = this.$el.querySelector('.rent-rank-item');
+      if (firstItem) {
+        this.firstItemHeight = firstItem.offsetHeight + 8;
+      }
+      this.startScroll();
+    });
+  },
+  beforeDestroy() {
+    this.clearScrollTimer();
+    if (this.animationFrameId) {
+      cancelAnimationFrame(this.animationFrameId);
+    }
   },
   methods: {
-    initCharts() {
-      this.charts.areaRent = echarts.init(this.$refs.areaRentChart)
-      this.charts.areaRent.setOption({
-        grid: {
-          left: '20%',
-          right: '5%',
-          top: '10%',
-          bottom: '10%'
-        },
-        xAxis: {
-          type: 'value',
-          axisLine: {
-            show: false
-          },
-          splitLine: {
-            show: false
-          },
-          axisLabel: {
-            color: '#fff'
-          }
-        },
-        yAxis: {
-          type: 'category',
-          data: ['新城大道', '拉萨路', '新城大道', '拉萨路', '新城大道', '新城大道', '拉萨路', '新城大道', '拉萨路', '新城大道'],
-          axisLine: {
-            lineStyle: {
-              color: '#fff'
-            }
-          },
-          axisLabel: {
-            color: '#fff'
-          }
-        },
-        series: [{
-          type: 'bar',
-          data: [1900, 1850, 1800, 1750, 1700, 1600, 1500, 1400, 1300, 1200],
-          barWidth: '30%',
-          itemStyle: {
-            color: {
-              type: 'linear',
-              x: 0,
-              y: 0,
-              x2: 1,
-              y2: 0,
-              colorStops: [{
-                offset: 0,
-                color: '#0ff'
-              }, {
-                offset: 1,
-                color: '#0ff'
-              }]
-            }
-          }
-        }]
-      })
+    startScroll() {
+      this.isScrolling = true;
+      if (!this.animationFrameId) {
+        this.lastTimestamp = performance.now();
+        this.startAutoScroll();
+      }
+    },
+    stopScroll() {
+      this.isScrolling = false;
+    },
+    clearScrollTimer() {
+      if (this.animationFrameId) {
+        cancelAnimationFrame(this.animationFrameId);
+        this.animationFrameId = null;
+      }
+    },
+    startAutoScroll() {
+      const animate = (timestamp) => {
+        if (!this.isScrolling) {
+          this.lastTimestamp = timestamp;
+          this.animationFrameId = requestAnimationFrame(animate);
+          return;
+        }
 
-      window.addEventListener('resize', () => {
-        this.charts.areaRent && this.charts.areaRent.resize()
-      })
+        const deltaTime = timestamp - this.lastTimestamp;
+        const speed = 0.03;
+        const step = speed * deltaTime;
+
+        const content = this.$refs.scrollContent;
+        if (!content || !this.firstItemHeight) {
+          this.animationFrameId = requestAnimationFrame(animate);
+          return;
+        }
+
+        this.currentTranslate -= step;
+
+        // 当滚动到第一组数据的末尾时,重置位置到第二组数据的开始
+        const halfHeight = this.firstItemHeight * this.rentRank.length;
+        if (Math.abs(this.currentTranslate) >= halfHeight) {
+          this.currentTranslate = 0;
+        }
+
+        content.style.transform = `translateY(${this.currentTranslate}px)`;
+        this.lastTimestamp = timestamp;
+        this.animationFrameId = requestAnimationFrame(animate);
+      };
+
+      this.animationFrameId = requestAnimationFrame(animate);
+    },
+    getBarColor(value) {
+      if (value == 0) return 'transparent';
+      return '#87F7C7';
     }
   }
 }
@@ -136,7 +176,7 @@
   position: fixed;
   top: 0;
   left: 0;
-  height: calc(100vh);
+  height: 100%;
   background: linear-gradient(to right, rgba(1, 85, 121, 0.8) 0%, rgba(1, 85, 121, 0.8) 20%, rgba(151, 190, 192, 0));
   z-index: 1002;
   flex-direction: column;
@@ -177,6 +217,7 @@
   display: flex;
   align-items: center;
   gap: 10px;
+  min-width: 0;
 }
 
 .icon-area,
@@ -205,6 +246,10 @@
   font-size: 24px;
   font-weight: bold;
   color: #0ff;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  width: 100%;
 }
 
 .unit {
@@ -219,15 +264,76 @@
   border-radius: 8px;
   padding: 15px;
   min-height: 300px;
+  max-height: calc(100vh - 600px);
+  overflow: hidden;
+  margin-bottom: 20px;
 }
 
 .chart-title {
   font-size: 16px;
-  margin-bottom: 15px;
   color: #fff;
 }
 
-.area-chart {
-  height: calc(100% - 30px);
+.chart-unit {
+  font-size: 12px;
+  margin-bottom: 15px;
 }
-</style> 
\ No newline at end of file
+
+.rent-rank-list {
+  height: calc(100% - 60px);
+  overflow: hidden;
+  padding: 10px 0;
+  position: relative;
+  max-height: calc(100% - 60px);
+}
+
+.rank-list-content {
+  position: relative;
+  transition: none;
+  transform: translateY(0);
+  will-change: transform;
+}
+
+.rank-list-group {
+  position: relative;
+}
+
+.rent-rank-item {
+  display: flex;
+  flex-direction: column;
+  padding: 8px 0;
+}
+
+.rank-name {
+  color: #fff;
+  font-size: 14px;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.rank-progress {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.rank-bar {
+  flex: 1;
+  height: 8px;
+  background: rgba(255, 255, 255, 0.1);
+  overflow: hidden;
+}
+
+.rank-bar-inner {
+  height: 100%;
+  transition: all 0.3s ease;
+}
+
+.rank-value {
+  color: #fff;
+  font-size: 14px;
+  min-width: 45px;
+  text-align: right;
+}
+</style>
\ No newline at end of file

--
Gitblit v1.7.1