zory 1 ماه پیش
والد
کامیت
6c224f38c3

+ 12 - 0
src/api/model/serHeart.js

@@ -0,0 +1,12 @@
+import config from "@/config";
+import http from "@/utils/request";
+
+export default {
+    beat: {
+        url: `${config.API_URL}/service/heart/beat`,
+        name: "-",
+        get: async function (params) {
+            return await http.get(this.url, params);
+        },
+    },
+}

+ 1 - 1
src/components/imFloat/im.vue

@@ -2,7 +2,7 @@
   <div class="global-im">
     <!-- 悬浮按钮与角标 -->
     <div class="im-trigger" :class="{ active: visible }" @click="toggleChat">
-        <el-icon><el-icon-chat-round /></el-icon>
+        <el-icon :size="18"><el-icon-chat-round /></el-icon>
       <el-badge :value="unreadCount" :hidden="unreadCount === 0" :max="99">
         <i class="el-icon-chat-dot-round" style="font-size: 24px"></i>
       </el-badge>

+ 178 - 0
src/components/imFloat/imFloat.vue

@@ -0,0 +1,178 @@
+<template>
+    <div class="global-im">
+        <!-- 悬浮按钮与角标 -->
+        <div class="im-trigger" :class="{ active: visible }" @click="toggleChat">
+            <el-icon :size="18"><el-icon-chat-round /></el-icon>
+            <el-badge :value="unreadCount" :hidden="unreadCount === 0" :max="99">
+                <i class="el-icon-chat-dot-round" style="font-size: 24px"></i>
+            </el-badge>
+        </div>
+    </div>
+    <el-drawer v-model="visible" title="在线客服" size="100%" destroy-on-close :close-on-click-modal="false" :with-header="false">
+        <el-container class="flex-column" v-loading="loading">
+            <div class="drawer-detail-main">
+                <div class="drawer-detail-header">
+                    <div class="drawer-detail-header-body">
+                        <div class="drawer-detail-header-left">在线客服</div>
+                        <div class="drawer-detail-header-left">
+                            <el-button type="default" icon="el-icon-close" @click="visible=false">隐藏窗口</el-button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <el-main class="nopadding">
+                <el-container>
+                    <el-aside width="200px" v-loading="menuloading">
+                        
+                    </el-aside>
+                    <el-container>
+                        <el-header><div class="msg-title">与xxx的对话</div></el-header>
+                        <el-main class="nopadding" ref="main">
+                            <div class="chat-container">
+                                <div class="message-list" ref="messageListRef">
+                                </div>
+                                <div class="input-area">
+                                    <el-input
+                                        type="textarea"
+                                        :rows="3"
+                                        v-model="inputMessage"
+                                        placeholder="请输入消息..."
+                                    ></el-input>
+                                    <el-button type="primary" style="margin-top: 10px;" @click="sendMessage">发送</el-button>
+                                </div>
+                            </div>
+                        </el-main>
+                    </el-container>
+                    <el-aside width="400px">
+                        <el-container>
+                            <el-header><div class="msg-title">个人资料</div></el-header>
+                        </el-container>
+                    </el-aside>
+                </el-container>
+            </el-main>
+        </el-container>
+    </el-drawer>
+</template>
+
+<script>
+import { Push } from "@/utils/push";
+var pushObj = null;
+export default {
+    name: 'GlobalIM',
+    data() {
+        return {
+            loading:false,
+            visible: false,           // 聊天窗口可见性
+            unreadCount: 0,          // 未读消息数量
+            inputMessage: '',        // 输入的消息
+            timer: null,             // 定时器
+            messages: [              // 消息列表
+                { id: 1, name: '系统助手', avatar: '', text: '欢迎使用 SCUI!', time: '10:00', self: false },
+                { id: 2, name: '我', avatar: '', text: '你好,这个全局IM功能不错', time: '10:01', self: true },
+            ]
+        }
+    },
+    mounted() {
+        console.log("pushObj")
+        // this.simulateNewMessage()
+    },
+    beforeDestroy() {
+        // if (this.timer) {
+        //     clearInterval(this.timer)
+        // }
+    },
+    methods: {
+        // 切换聊天窗口
+        toggleChat() {
+            this.visible = !this.visible
+            if (this.visible) {
+                // 打开窗口时清除未读角标
+                this.unreadCount = 0
+            }
+        }
+    }
+}
+</script>
+
+<style scoped lang="scss">
+.msg-title{font-size: 18px;font-weight: bold;}
+.global-im {
+  .im-trigger {
+    position: fixed;
+    right: 24px;
+    bottom: 24px;
+    width: 48px;
+    height: 48px;
+    background: #409eff;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
+    z-index: 2000;
+    transition: all 0.3s;
+    color: white;
+    &:hover {
+      transform: scale(1.05);
+      background: #66b1ff;
+    }
+    &.active {
+      background: #909399;
+    }
+  }
+}
+.chat-container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+  .message-list {
+    flex: 1;
+    overflow-y: auto;
+    .message-item {
+      display: flex;
+      margin-bottom: 16px;
+      &.self {
+        flex-direction: row-reverse;
+        .content {
+          margin-right: 12px;
+          align-items: flex-end;
+          .text {
+            background: #95ec69;
+          }
+        }
+      }
+      &.other {
+        .content {
+          margin-left: 12px;
+        }
+      }
+      .content {
+        display: flex;
+        flex-direction: column;
+        max-width: 70%;
+        .name {
+          font-size: 12px;
+          color: #999;
+          margin-bottom: 4px;
+        }
+        .text {
+          padding: 8px 12px;
+          background: #f0f0f0;
+          border-radius: 12px;
+          word-break: break-all;
+        }
+        .time {
+          font-size: 10px;
+          color: #ccc;
+          margin-top: 4px;
+        }
+      }
+    }
+  }
+  .input-area {
+    padding: 16px;
+    border-top: 1px solid #eee;
+  }
+}
+</style>

+ 24 - 9
src/layout/index.vue

@@ -203,11 +203,6 @@
 
 	<div class="main-maximize-exit" @click="exitMaximize"><el-icon><el-icon-close /></el-icon></div>
 
-	<div class="layout-setting" @click="sendTestNotification" v-if="userInfo.type==3">
-		<el-icon><el-icon-chat-round /></el-icon>
-		<span>99</span>
-	</div>
-
 	<el-drawer title="布局实时演示" v-model="settingDialog" :size="400" append-to-body destroy-on-close>
 		<setting></setting>
 	</el-drawer>
@@ -227,9 +222,7 @@ import userbar from './components/userbar.vue';
 import setting from './components/setting.vue';
 import iframeView from './components/iframeView.vue';
 import autoExit from './other/autoExit.js';
-import imFloat from '@/components/imFloat/index';
-import { Push } from "@/utils/push";
-
+import imFloat from '@/components/imFloat/imFloat';
 export default {
 	name: 'index',
 	components: {
@@ -253,7 +246,8 @@ export default {
 			active: '',
 			baseData: {},
 			userInfo:{},
-			notificationPermission: 'default'
+			notificationPermission: 'default',
+			heartbeatTimer: null
 		}
 	},
 	computed: {
@@ -286,6 +280,9 @@ export default {
 		if (window.Notification && Notification.permission !== 'denied') {
 			this.requestPermission()
 		}
+		if (this.userInfo.type == 3) {
+			this.startHeartbeat()
+		}
 	},
 	watch: {
 		$route() {
@@ -298,7 +295,25 @@ export default {
 			immediate: true,
 		}
 	},
+	beforeDestroy() {
+		this.stopHeartbeat()
+	},
 	methods: {
+		startHeartbeat() {
+			this.sendHeartbeat() // 立即发送一次
+			this.heartbeatTimer = setInterval(() => {
+				this.sendHeartbeat()
+			}, 45 * 1000)
+		},
+		stopHeartbeat() {
+			if (this.heartbeatTimer) {
+				clearInterval(this.heartbeatTimer)
+				this.heartbeatTimer = null
+			}
+		},
+		async sendHeartbeat(){
+			await this.$API.serHeart.beat.get();
+		},
 		async requestPermission() {
 			if (!("Notification" in window)) {
 				alert("当前浏览器不支持通知功能")

+ 1 - 1
src/views/login/components/mobile.vue

@@ -188,7 +188,7 @@ export default {
 			} else if (userType == 2) {
 				dashboard = "/merchant/dashboard";
 			} else if (userType == 3) {
-				dashboard = "/store/dashboard";
+				dashboard = "/service/dashboard";
 			} else if (userType == 4) {
 				dashboard = "/factory/dashboard";
 			}

+ 1 - 1
src/views/login/components/passwd.vue

@@ -133,7 +133,7 @@ export default {
 			} else if (userType == 2) {
 				dashboard = "/merchant/dashboard";
 			} else if (userType == 3) {
-				dashboard = "/store/dashboard";
+				dashboard = "/service/dashboard";
 			}
 			this.$emit("success");
 			this.$message.success(user.msg)

+ 6 - 0
src/views/merchant/service/index/components/table.vue

@@ -19,6 +19,12 @@
                 <span class="status-danger" v-else>未设置</span>
             </template>
         </el-table-column>
+        <el-table-column label="在线" prop="type" width="120" align="left">
+            <template #default="scope">
+                <div class="status-success" v-if="scope.row.is_line==1"><sc-status-indicator type="success"></sc-status-indicator> 在线</div>
+                <div class="status-danger" v-else><sc-status-indicator type="danger"></sc-status-indicator> 离线</div>
+            </template>
+        </el-table-column>
         <el-table-column label="账户类型" prop="type" width="120" align="left">
             <template #default="scope">
                 <div class="status-success" v-if="scope.row.type==1"><sc-status-indicator type="success"></sc-status-indicator> 系统管理员</div>