pxb 2 недель назад
Родитель
Сommit
4ec25b89b0
1 измененных файлов с 65 добавлено и 2 удалено
  1. 65 2
      src/layout/components/Navbar.vue

+ 65 - 2
src/layout/components/Navbar.vue

@@ -11,6 +11,17 @@
           <el-switch v-model="isSoundOn" active-color="#13ce66" @change="handleSoundChange" />
         </div>
 
+        <!-- 在线用户统计 -->
+        <div class="online-stats-pill">
+          <span class="online-stats">在线用户:</span>
+          <div class="online-content">
+            <svg-icon icon-class="Iphone" class="stats-icon" />{{ onlineCounts.mobile }}
+            <svg-icon icon-class="Devices" class="stats-icon" />{{ onlineCounts.pc }}
+            <svg-icon icon-class="Android" class="stats-icon" />{{ onlineCounts.android }}
+            <svg-icon icon-class="Apple" class="stats-icon" />{{ onlineCounts.ios }}
+          </div>
+        </div>
+
         <el-popover placement="bottom" width="170" trigger="hover">
           <div style="padding: 10px 5px;">
             <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
@@ -81,7 +92,7 @@ import { mapGetters } from 'vuex'
 import Breadcrumb from '@/components/Breadcrumb'
 import Hamburger from '@/components/Hamburger'
 import setPassword from './setPassword.vue'
-import { getPaymentOrderUnProcessed } from '@/api/data'
+import { getPaymentOrderUnProcessed, getOnlineUsers } from '@/api/data'
 
 export default {
   components: {
@@ -105,7 +116,8 @@ export default {
       },
       intervalSeconds: 3, // 轮询秒数变量
       timer: null, // 定时器
-      audi: require('@/assets/masg.mp3')
+      audi: require('@/assets/masg.mp3'),
+      onlineCounts: { mobile: 0, pc: 0, ios: 0, android: 0 }
     }
   },
   computed: {
@@ -127,9 +139,11 @@ export default {
   created() {
     // 初始化调用一次
     this.fetchPendingData()
+    this.fetchOnlineCounts()
     // 开启定时器
     this.timer = setInterval(() => {
       this.fetchPendingData()
+      this.fetchOnlineCounts()
     }, this.intervalSeconds * 1000)
   },
   beforeDestroy() {
@@ -158,6 +172,23 @@ export default {
         }
       })
     },
+    // 拉取在线用户并按平台统计
+    fetchOnlineCounts() {
+      getOnlineUsers({ page: 1, limit: 200 })
+        .then(res => {
+          const counts = { mobile: 0, pc: 0, ios: 0, android: 0 }
+          const rows = (res.data && res.data.data) || []
+          rows.forEach(r => {
+            const p = String(r.platform || '').toLowerCase()
+            if (p === 'pc') counts.pc++
+            else if (p === 'ios') counts.ios++
+            else if (p === 'android') counts.android++
+            else counts.mobile++ // Mobile / WeChat 等归入移动
+          })
+          this.onlineCounts = counts
+        })
+        .catch(() => {})
+    },
     playSound() {
       const audio = new Audio(this.audi)
       audio.currentTime = 0 // 重置播放位置
@@ -258,6 +289,38 @@ export default {
       }
     }
 
+    .online-stats-pill {
+      display: flex;
+      align-items: center;
+      margin-top: 6px;
+      margin-right: 15px;
+      line-height: 1;
+      font-size: 13px;
+
+      .online-stats {
+        white-space: nowrap;
+        display: flex;
+        color: #fff;
+        align-items: center;
+      }
+      .online-content {
+        padding: 4px 6px;
+        background: #D7D8D3;
+        color: #666666;
+        border-radius: 10px;
+      }
+      .stats-icon {
+        width: 14px;
+        height: 14px;
+        margin: 0 3px 0 6px;
+        vertical-align: -0.15em;
+      }
+
+      .stats-icon:first-of-type {
+        margin-left: 4px;
+      }
+    }
+
     .avatar-container {
       margin-right: 30px;