Browse Source

在线会话

rkljw 2 days ago
parent
commit
f9128eba0b

+ 30 - 2
src/App.vue

@@ -1,11 +1,12 @@
 <template>
   <div id="app">
     <router-view />
-    <ChatFloatButton ref="chatFloatButton" v-show="!showChat && $store.state.user.name" @open="showChat = true" />
+    <ChatFloatButton ref="chatFloatButton" @showDataList="handleShowChatPanelDataList" v-show="!showChat && $store.state.user.name" @open="showChat = true" />
     <ChatPanel
       ref="chatPanel"
       v-show="showChat && $store.state.user.name"
       @close="showChat = false"
+      @showChatPanel="handleShowChatPanel"
     />
   </div>
 </template>
@@ -14,7 +15,7 @@
 import ChatFloatButton from './layout/components/Chat/ChatFloatButton.vue'
 import ChatPanel from './layout/components/Chat/ChatPanel.vue'
 import emitter from '@/eventBus';
-
+import wsService from '@/utils/websocketService';
 export default {
   name: 'App',
   components: { ChatFloatButton, ChatPanel },
@@ -25,8 +26,20 @@ export default {
   },
   mounted() {
     emitter.on('view-group-chat', this.handleViewGroupChat);
+    const token = this.$store.state.user.token; // 或从 cookie/localStorage 获取
+    wsService.connect(token);
+    console.log('#############websocket connected:', wsService.getReadyState());
+    // 你可以在这里全局监听消息
+    wsService.addMessageListener(this.handleWsMessage);
+    setInterval(() => {
+        if (wsService.getReadyState() === 1) {
+          wsService.send({ type: 'ping' });
+        }
+    }, 10000); // 每10秒
+
   },
   beforeDestroy() {
+    console.log("FFFFFFFFFFFFFFFFFFFFFFFFFF");
     emitter.off('view-group-chat', this.handleViewGroupChat);
   },
   methods: {
@@ -37,7 +50,22 @@ export default {
           this.$refs.chatPanel.viewGroupChat(val);// 这里调用 selectGroup 或其它弹窗方法
         }
       });
+    },
+    handleShowChatPanel(callback,msg) {
+    this.showChat = true;
+    this.$nextTick(() => {
+      if (typeof callback === 'function') callback(msg);
+    });
+  },
+  handleShowChatPanelDataList(data) {
+    // console.log('handleShowChatPanelDataList::::::::::::', data);
+      this.$nextTick(() => {
+          if (this.$refs.chatPanel) {
+            this.$refs.chatPanel.handleShowChatPanelDataList(data);// 这里调用 selectGroup 或其它弹窗方法
+          }
+      });
     }
   }
+  
 }
 </script>

+ 3 - 0
src/layout/components/Chat/ChatFloatButton.vue

@@ -24,11 +24,14 @@ export default {
     onLabelClick(e) {
       if (!dragSuppressClick) {
         this.$emit('open');
+        //给父级提交一个方法,这个方法去调用ChatPannel的open方法
+        this.$emit('showDataList');
       }
     },
     onButtonClick(e) {
       if (dragSuppressClick) {
         dragSuppressClick = false;
+        
         e.stopImmediatePropagation && e.stopImmediatePropagation();
         e.stopPropagation();
         e.preventDefault();

+ 90 - 67
src/layout/components/Chat/ChatPanel.vue

@@ -4,7 +4,7 @@
 
       <div class="chat-header">
         <img class="chat-icon" :src=avatar alt="在线会话" />
-        <span @click="clickShowMessage">{{ this.$store.state.user.name }}</span>
+        <span>{{ this.$store.state.user.name }}</span>
         <span class="chat-status online"></span>
         <span class="chat-close" @click="$emit('close')">×</span>
       </div>
@@ -928,7 +928,7 @@
                         <div class="fileWindowMessageItemName">用户名称</div>
                         <div class="fileWindowMessageItemTime">12:40</div>
                       </div>
-                      <div class="fileWindowMessageItemText">用用户消息用户消息用户消息用户消息用户消息用户消息用户消息用户消息用户消息用户消息用户消息</div>
+                      <div class="fileWindowMessageItemText">用用户消息用户消息用户消息用户消息用户消息用户消息用户消息用户消息</div>
                     </div>
                   </div>
                 </div>
@@ -1255,7 +1255,6 @@
               </div>
             </div>
       </el-dialog>
-      <!-- <el-button class="top-button" type="primary" @click="viewGroupChat">查看群聊</el-button> -->
     </div>
    
   </template>
@@ -1265,6 +1264,7 @@
   import hallTitle from './components/hallTitle.vue';
   import contactsTitle from './components/contactsTitle.vue';
   import baseUrl from '@/utils/baseUrl';
+  import wsService from '@/utils/websocketService';
   export default {
     components: {
       hallTitle,
@@ -1273,6 +1273,7 @@
     name: "ChatPanel",
     data() {
       return {
+        newMessage: {},
         token:'',
         ones:0,
         messageContent:{},
@@ -1446,7 +1447,8 @@
       }
     },
     methods: {
-      clickShowMessage() {
+      clickShowMessage(item) {
+        // this.newMessage = item;
         // 先关闭所有旧消息
         this.$message.closeAll();
         this.$message({
@@ -1459,7 +1461,7 @@
               <span>收到新消息</span>
             </div>
           `,
-          duration: 300000,
+          duration: 3000,
           customClass:'message-new'
         });
 
@@ -1467,18 +1469,25 @@
           const el = document.querySelector('.my-custom-message');
           if (el) {
             el.onclick = () => {
-              this.onCustomMessageClick();
+              this.onCustomMessageClick(item);
             };
           }
         }, 50);
       },
-      onCustomMessageClick() {
-        if(this.messageContent.receiver_id && this.messageContent.receiver_id.length==18){
-          this.selectGroup(this.messageContent);
-        }else{
-          this.selectConversation(this.messageContent);
-        }
-        console.log('自定义消息弹窗被点击了');
+      onCustomMessageClick(item) {
+
+        // 通知父组件显示ChatPanel,并把 item 作为参数传递
+        this.$emit('showChatPanel', (msg) => {
+          console.log('回调点击消息体内容:', msg);
+          // 这里写后续逻辑
+          if (msg && msg.receiver_id && msg.receiver_id.length == 18) {
+            this.selectGroup(msg);
+          } else {
+            msg.receiver_id = item.user_id;
+            this.selectConversation(msg);
+          }
+        }, item);
+
       },
       //1.会话列表 start---------------------------------------->
       //1.1获取会话列表
@@ -1521,6 +1530,7 @@
           }
         });
         //console.log(this.conversationList)
+        console.log("LLLLL选择会话:",item.receiver_id)
         this.getchatrecords(item.receiver_id);
         //关闭没有选择任何聊天的界面
         this.ifNoMessage = false;
@@ -1642,10 +1652,10 @@
         //console.log(message)
         //发送消息
         let that = this;
-        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
+        if (this.ws && wsService.getReadyState === WebSocket.OPEN) {
           //打开左侧loading防止重复点击
           this.hallLeftLoading = true;
-          this.ws.send(JSON.stringify(message));
+          wsService.send(JSON.stringify(message));
   
           //bug
           //如果双方不是好友,此处可以弹出错误
@@ -2263,8 +2273,8 @@
   
           console.log(message)
           //发送消息
-          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
-            this.ws.send(JSON.stringify(message));
+          if (this.ws && wsService.getReadyState === WebSocket.OPEN) {
+            wsService.send(message);
           }
           //关闭分享弹出框
           this.shareGroupWindowStatus = false;
@@ -2418,20 +2428,17 @@
       //5.websocket会话 start---------------------------------------->
       //5.1 接受消息
       handleIncomingMessage(event) {
-        const message = JSON.parse(event.data);
-        // this.clickShowMessage();
-        console.log("监听消息1:",message.user_id,"===",this.myUserId,"##",this.user_id)
-        // if(this.ones==0){
-        //   this.ones = 1
-        //   this.getConversationList();          
-        // }
-        // console.log(message.receiver_id)
-        // this.conversationList.forEach(item => {
-        //   if(item.receiver_id==message.receiver_id){
-        //     console.log("当前消息属于当前的聊天窗口!")
-        //     this.messageContent = message;
-        //   }
-        // });
+        if(event.event=="connect"){
+          console.log("websocket连接成功!")
+          return;
+        }
+        const message = event;
+        this.conversationList.forEach(item => {
+          if(item.receiver_id==message.receiver_id){
+            console.log("当前消息属于当前的聊天窗口!")
+            this.newMessage = message;
+          }
+        });
         // console.log(message.receiver_id.length == 18)
         if(message.user_id && (message.user_id !=this.user_id)){
           this.clickShowMessage(message);
@@ -2442,6 +2449,7 @@
           if(Number(this.receiverId)==Number(message.receiver_id)){
             console.log("当前消息为群消息,并且可以显示到当前的会话框中!")
             //18位就是群聊
+            console.log("18888888888888:",Number(this.myUserId) ,"====", Number(message.user_id))
             if(Number(this.myUserId) == Number(message.user_id)){
               //如果message的receiverId和会话的receiverId一致,说明这条信息是自己发的回显
               let receiveMessage = {
@@ -2558,9 +2566,11 @@
             content:this.userMessage,//用户发发送的消息
             msg_type:1,//消息类型 1:文本 2:图片 3:文件 4:好友卡片 5:系统消息;6:加群卡片
           };
+          // console.log("websocket发送消息:",wsService.getReadyState,WebSocket.OPEN)
           //发送消息
-          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
-            this.ws.send(JSON.stringify(message));
+          console.log("发送消息前的状态:",wsService.getReadyState() ,"==========" ,WebSocket.OPEN)
+          if (wsService.getReadyState() === WebSocket.OPEN) {
+            wsService.send(message);
           }
           this.userMessage = '';
         }else{
@@ -2577,7 +2587,7 @@
             content:this.sendMessage.img.imgUrl,//用户发发送的消息
             msg_type:2,//消息类型 1:文本 2:图片 3:文件 4:好友卡片 5:系统消息;6:加群卡片
           };
-          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
+          if (this.ws && wsService.getReadyState === WebSocket.OPEN) {
             this.ws.send(JSON.stringify(message));
             //发送完毕清除选择的图片
             this.sendMessage.img.imgUrl='';
@@ -2601,7 +2611,7 @@
             content:fileInfoString,//用户发发送的消息
             msg_type:3,//消息类型 1:文本 2:图片 3:文件 4:好友卡片 5:系统消息;6:加群卡片
           };
-          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
+          if (this.ws && wsService.getReadyState === WebSocket.OPEN) {
             this.ws.send(JSON.stringify(message));
             //发送完毕清除选择的文件
             this.sendMessage.file.fileUrl='';
@@ -2666,7 +2676,7 @@
   
           console.log(message)
           //发送消息
-          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
+          if (this.ws && wsService.getReadyState === WebSocket.OPEN) {
             this.ws.send(JSON.stringify(message));
           }
           //关闭分享弹出框
@@ -3070,6 +3080,10 @@
           document.addEventListener('mouseup', onMouseUp);
         });
       },
+      handleShowChatPanelDataList(){
+        this.getConversationList();
+        this.getUserFriendList();
+      },
       viewGroupChat(info) {
         // 这里可以添加查看群聊的逻辑
         console.log('查看群聊',info);
@@ -3092,50 +3106,56 @@
         // 你的逻辑,比如显示面板、加载群聊数据等
         // this.showPanel = true;
         // this.loadGroupChat(id);
+      },
+      handleShowChatPanel(callback) {
+        this.showChat = true;
+        this.$nextTick(() => {
+          if (typeof callback === 'function') callback();
+        });
       }
     },
     mounted() {
-      console.log("用户头像信息:",this.$store.state.user.avatar)
-      //开启websocket连接 start---------------------------------------->
-      //1.获取admin-token
-      const adminToken = this.token;
-      console.log("Admin-Token:", adminToken);
+      // console.log("用户头像信息:",this.$store.state.user.avatar)
+      // //开启websocket连接 start---------------------------------------->
+      // //1.获取admin-token
+      // const adminToken = this.token;
+      // console.log("Admin-Token:", adminToken);
   
-      //2.连接websocket 
-      let websocketNewUrl = baseUrl.WebsocketUrl +"?token=" + adminToken;
-      //let websocketNewUrl = URL.WebsocketUrl +"?token=" + adminToken;
-      this.ws = new WebSocket(websocketNewUrl);
-      this.ws.addEventListener('message', this.handleIncomingMessage);
+      // //2.连接websocket 
+      // let websocketNewUrl = baseUrl.WebsocketUrl +"?token=" + adminToken;
+      // //let websocketNewUrl = URL.WebsocketUrl +"?token=" + adminToken;
+      // this.ws = new WebSocket(websocketNewUrl);
+      wsService.addMessageListener(this.handleIncomingMessage);
   
       //3.当连接中断时提供一个方法重新连接
       let that = this;
   
       //当连接关闭的时候关闭websocket
-      this.ws.addEventListener('close', function (event) {
-        // 连接关闭时执行的操作
-        console.log("关闭链接",event);
-        // 弹窗询问用户是否手动刷新
-        // that.getWebsocket();
-      });
+      // wsService.addEventListener('close', function (event) {
+      //   // 连接关闭时执行的操作
+      //   console.log("关闭链接",event);
+      //   // 弹窗询问用户是否手动刷新
+      //   // that.getWebsocket();
+      // });
       
       //开启websocket连接 end---------------------------------------->
   
       //从通讯录创建单聊 start---------------------------------------->
       //当ws创建成功以后再执行,防止数据未加载
-      this.ws.onopen = () => {
-        console.log("ws创建成功!");
-        console.log(this.$route.query.friend_id)
-        //判断当前路由是否携带friend_id
-        if(this.$route.query.friend_id){
-          console.log("从通讯录进入,开始创建会话!")
-          //1.从通讯录进入会话大厅
-          this.retrieveSession();
-          //2.获取我的用户id
-          this.myUserId = this.$store.state.user.userid;
-          //把这个id存一下
-          this.createMessageId = this.$route.query.friend_id;
+      // this.ws.onopen = () => {
+      //   console.log("ws创建成功!");
+      //   console.log(this.$route.query.friend_id)
+      //   //判断当前路由是否携带friend_id
+      //   if(this.$route.query.friend_id){
+      //     console.log("从通讯录进入,开始创建会话!")
+      //     //1.从通讯录进入会话大厅
+      //     this.retrieveSession();
+      //     //2.获取我的用户id
+      //     this.myUserId = this.$store.state.user.userid;
+      //     //把这个id存一下
+      //     this.createMessageId = this.$route.query.friend_id;
           
-        }else{
+      //   }else{
           console.log("直接进入,无需创建会话!")
           //直接进入会话大厅
           //1.获取会话列表
@@ -3144,12 +3164,13 @@
           this.getFriendApplyList();
           //2.获取我的用户id
           this.myUserId = this.$store.state.user.userid;
+          console.log("isME:", this.myUserId);
           //3.循环获取会话列表
           //开启loading
           this.hallLeftLoading = true;
           this.forSearchConversationList();
-        }
-      };
+      //   }
+      // };
       //从通讯录创建单聊 end---------------------------------------->
       this.initDrag();
     },
@@ -3162,6 +3183,7 @@
         this.ws.close();
       }
       clearInterval(this.getFriendApplyListStatus);
+      wsService.removeMessageListener(this.handleIncomingMessage);
     },
     watch: {
       // 监听 user.avatar 的变化
@@ -3177,6 +3199,7 @@
         if (newVal) {
           // 这里可以安全地使用 avatar
           this.user_id = newVal
+          this.myUserId = newVal
           console.log('user_id 变化了:', newVal);
           // 你的逻辑...
         }

+ 59 - 0
src/utils/websocketService.js

@@ -0,0 +1,59 @@
+// src/services/websocketService.js
+import baseUrl from '@/utils/baseUrl';
+class WebSocketService {
+  constructor() {
+    this.ws = null;
+    this.isConnected = false;
+    this.messageListeners = [];
+  }
+
+  connect(token) {
+    if (this.ws) {
+      this.ws.close();
+    }
+    const baseUrls = baseUrl.WebsocketUrl; // 替换为你的 ws 地址
+    const url = `${baseUrls}?token=${token}`;
+    this.ws = new window.WebSocket(url);
+
+    this.ws.onopen = () => {
+      this.isConnected = true;
+      console.log('[WebSocket] 连接成功');
+    };
+
+    this.ws.onmessage = (event) => {
+      const message = JSON.parse(event.data);
+      this.messageListeners.forEach(cb => {
+        if (typeof cb === 'function') {
+          cb(message);
+        }
+      });
+    };
+
+    this.ws.onclose = (event) => {
+      this.isConnected = false;
+      console.log('[WebSocket] 连接关闭', event);
+    };
+  }
+
+  send(data) {
+    if (this.ws && this.isConnected) {
+      this.ws.send(JSON.stringify(data));
+    }
+  }
+
+  addMessageListener(cb) {
+    this.messageListeners.push(cb);
+  }
+
+  removeMessageListener(cb) {
+    this.messageListeners = this.messageListeners.filter(fn => fn !== cb);
+  }
+
+  getReadyState() {
+    // 0: CONNECTING, 1: OPEN, 2: CLOSING, 3: CLOSED
+    return this.ws ? this.ws.readyState : null;
+  }
+}
+
+const wsService = new WebSocketService();
+export default wsService;

+ 22 - 6
src/views/chat/businessDistrictDetail.vue

@@ -28,12 +28,12 @@
                         </div>
                         <span
                           class="article_panel_btn"
-                          v-if="!isExpanded"
+                          v-if="showReadMoreBtn && !isExpanded"
                           @click="toggleExpand"
-                        >阅读全文
-                        <i class="el-icon-arrow-down" ></i>
-                            
-                      </span>
+                        >
+                          阅读全文
+                          <i class="el-icon-arrow-down"></i>
+                        </span>
                     </div>
                   </div>
                 </div>
@@ -98,6 +98,7 @@
         id:'',
         dataInfo:{},
         isExpanded: false, // btn添加展开状态
+        showReadMoreBtn: false,
         //1.列表和分页相关 start ------------------------------------------------------------>
         tableDivTitle: "商圈详情",
         getApiData: {
@@ -125,6 +126,14 @@
             
            this.isExpanded = true;
         },
+        checkPanelHeight() {
+          this.$nextTick(() => {
+            const panel = this.$el.querySelector('.article_panel');
+            if (panel) {
+              this.showReadMoreBtn = panel.scrollHeight > 270;
+            }
+          });
+        },
         getDataINfo(){
           getTopicDataInfo({
                 id:self.id
@@ -164,11 +173,17 @@
       self.id = this.$route.query.id+'';
       this.getDataINfo();
       this.getTopicReplyList();
+      this.checkPanelHeight();
       // 可选:如果你需要监听(一般只在调试时用)
       emitter.on('view-group-chat', this.handleViewGroupChat);
     },
     beforeDestroy() {
       emitter.off('view-group-chat', this.handleViewGroupChat);
+    },
+    watch: {
+      'dataInfo.content': function() {
+        this.checkPanelHeight();
+      }
     }
   }
   </script>
@@ -271,7 +286,8 @@
         .comment_li{background:#FAFAFA;border:solid 1px #E1E1E1;overflow:hidden;margin-bottom:20px;}
         .comment_li_img{float:left;width:52px;height:52px;border-radius:50%;margin:30px 0px 30px 30px;}
         .comment_li_name{float:left;margin:44px 0px 44px 20px;color:#333;font-size:16px;line-height:24px;}
-        .comment_li_text{float:left;margin:45px 0px 11px 20px;color:#333;font-size:16px;line-height:24px;                   font-weight:bold;width:1000px; }
+        .comment_li_text{float:left;margin:45px 0px 11px 20px;color:#333;font-size:16px;line-height:24px; 
+                          font-weight:bold;max-width: 1000px; }
         .comment_li_time{float:right;margin:44px 30px 44px 0px;color:#999;font-size:16px;line-height:24px; }
       margin-bottom: 16px;
       .comment-item {

+ 4 - 1
src/views/login/index.vue

@@ -98,7 +98,7 @@ import axios from 'axios'
 import BASEURL from '@/utils/baseUrl'
 import { getToken, getTokenTest, removeToken,setLoginStatus,setUserUrl } from '@/utils/auth'
 import router from '@/router'//引入路由
-
+import wsService from '@/utils/websocketService';
 
 export default {
     name: 'Login',
@@ -379,6 +379,9 @@ export default {
                                 console.log("登录成功,将跳转至详情页面222!")
                                 console.log(res)
                                 this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
+                                // 手动初始化 WebSocket
+                                const token = this.$store.state.user.token;
+                                wsService.connect(token);
                                 console.log("当前路由个数:" + router.options.routes.length)
                             } else if (res.code != 0 && res.code != 200) {
                                 this.$message({