vue和springboot使用websocket实现聊天

无敌的宇宙
无敌的宇宙
擅长邻域:Java,HTML,JavaScript,MySQL,支付,退款,图片上传

分类: springboot vue 专栏: springboot vue 常用功能 标签: 实现聊天

2025-02-19 21:47:58 254浏览

用2张表实现vue和springboot使用websocket实现聊天,可以是好朋友聊,也可以是固定客服人员聊天

旅游web——vue项目

 DROP TABLE IF EXISTS `lv_chatroom`;
CREATE TABLE `lv_chatroom`  (
  `cno` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `cts` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `cnos` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  PRIMARY KEY (`cno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;


DROP TABLE IF EXISTS `lv_chat`;
CREATE TABLE `lv_chat`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `uid` int(0) DEFAULT NULL,
  `cont` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `cts` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  `cno` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 473 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;


 

 pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>


   

后台xml  chat.xml

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.jf.s.dao.LvChatMapper">


  
	 

	
	
 	<select id="getlistByJoin" resultType="com.jf.s.bean.LvChat" parameterType="com.jf.s.bean.LvChat">
		select
		c.*,u.nickname,u.faceimg
		from lv_chat c
		left join lv_users u on u.id=c.uid
		 where 1=1
		<if test="cno != null and cno!='' ">
			and  c.cno=#{cno}
		</if>

	</select>
	 
	
	<select id="getByIdJoin" resultType="com.jf.s.bean.LvChat"
		parameterType="java.lang.Integer">
			select
		c.*,u.nickname,u.faceimg
		from lv_chat c
		left join lv_users u on u.id=c.uid
		where c.id=#{0}
	</select>





</mapper>

dao

 package com.jf.s.dao;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jf.s.bean.LvChat;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Mapper
public interface LvChatMapper extends BaseMapper<LvChat> {
    List<LvChat> getlistByJoin(LvChat o);

    LvChat getByIdJoin(Integer id);
}


package com.jf.s.dao;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jf.s.bean.LvChat;
import com.jf.s.bean.LvChatroom;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Mapper
public interface LvChatroomMapper extends BaseMapper<LvChatroom> {

}


service

 package com.jf.s.service;


import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jf.s.bean.LvChat;
import com.jf.s.dao.LvChatMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LvChatService extends ServiceImpl<LvChatMapper, LvChat> {

    @Autowired
    LvChatMapper chatMapper;

    public List<LvChat> getlistByJoin(LvChat o) {

        return  chatMapper.getlistByJoin(o);

    }
    public LvChat getByIdJoin(Integer id){
        return chatMapper.getByIdJoin(id);
    }




}
package com.jf.s.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jf.s.bean.LvChatroom;
import com.jf.s.bean.LvChatroom;
import com.jf.s.dao.LvChatroomMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class LvChatroomService extends ServiceImpl<LvChatroomMapper, LvChatroom> {

    @Autowired
    LvChatroomMapper chatroomMapper;

    public List<LvChatroom> getChatRooms(String cnos)  {
        LambdaQueryWrapper<LvChatroom> lambdaQueryWrapper = Wrappers.lambdaQuery();
        //条件查询

       lambdaQueryWrapper.like(LvChatroom::getCnos, cnos);


        List<LvChatroom> li = chatroomMapper.selectList(lambdaQueryWrapper);
        return li;
    }


}

bean

package com.jf.s.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("lv_chat")
public class LvChat {
	@TableId(type = IdType.AUTO)
	private Integer id;
	private Integer uid;
	private String cont;
	private String cts;
	private String cno;



	@TableField(exist = false)
	private String 	keywords;
	@TableField(exist = false)
	private String 	nickname;
	@TableField(exist = false)
	private String 	faceimg;
}

package com.jf.s.bean;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("lv_chatroom")
public class LvChatroom {
	@TableId(type = IdType.INPUT)
	private String cno;
	private String cts;
	private String cnos;
}

controller


 

package com.jf.s.control; import com.jf.s.bean.LvChat; import com.jf.s.bean.LvChatroom; import com.jf.s.bean.LvUsers; import com.jf.s.service.LvChatService; import com.jf.s.service.LvChatroomService; import com.jf.s.service.LvUsersService; import com.jf.s.util.DateUtil; import com.jf.s.util.MessUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; @CrossOrigin @RestController @RequestMapping("/chat") public class LvChatController { @Resource LvChatService chatService; @Resource LvChatroomService chatroomService; @Autowired LvUsersService usersService; @RequestMapping("/getChatRooms") public MessUtil getChatRooms(Integer uid ,String cno) { MessUtil mess=new MessUtil(); if(cno!=null&&cno.trim().length()>0){ LvChatroom r=chatroomService.getById(cno); if(r==null){ r=new LvChatroom(); r.setCno(cno); r.setCts(DateUtil.getNowTime()); Integer uid1=Integer.parseInt(r.getCno().split("_")[0]); Integer uid2=Integer.parseInt(r.getCno().split("_")[1]); r.setCnos("["+uid1+"]["+uid2+"]"); chatroomService.save(r); } } List<LvChatroom> li=chatroomService.getChatRooms("["+uid+"]"); List<LvChat> cli=new ArrayList<>(); for(LvChatroom r:li){ Integer uid1=Integer.parseInt(r.getCno().split("_")[0]); Integer uid2=Integer.parseInt(r.getCno().split("_")[1]); LvUsers u=null; if(uid.equals(uid1)){ u=usersService.getById(uid2); }else{ u=usersService.getById(uid1); } LvChat c=new LvChat(); c.setUid(u.getId()); c.setFaceimg(u.getFaceimg()); c.setNickname(u.getNickname()); c.setCno(r.getCno()); cli.add(c); } //对cli去重 String cnos=""; List<LvChat> cli2=new ArrayList<>(); for( LvChat c:cli){ if(cnos.indexOf("["+c.getCno()+"]")==-1 ){ cli2.add(c); cnos+="["+c.getCno()+"]"; } } return mess.succ(cli2); } @RequestMapping("/list") public MessUtil list( LvChat o) { MessUtil mess=new MessUtil(); LvChatroom r=chatroomService.getById(o.getCno()); if(r==null){ r=new LvChatroom(); r.setCno(o.getCno()); r.setCts(DateUtil.getNowTime()); Integer uid1=Integer.parseInt(r.getCno().split("_")[0]); Integer uid2=Integer.parseInt(r.getCno().split("_")[1]); r.setCnos("["+uid1+"]["+uid2+"]"); chatroomService.save(r); } List<LvChat> li=chatService.getlistByJoin(o); return mess.succ(li); } @RequestMapping("/save") public MessUtil save(LvChat o ) { MessUtil mess=new MessUtil(); if(o.getId()==null){ o.setCts(DateUtil.getNowTime()); chatService.save(o); }else{ chatService.updateById(o); } return mess.succ(o); } @RequestMapping("/info") public MessUtil info(Integer id ) { MessUtil mess=new MessUtil(); LvChat o=chatService.getByIdJoin(id); return mess.succ(o); } }


配置websocket,和application启动类同一目录

package com.jff.xinli;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}

websocket

package com.jff.xinli.websocket;


import com.alibaba.fastjson.JSONObject;
import com.jff.xinli.bean.XlChat;
import com.jff.xinli.service.XlChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;


/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 */
@ServerEndpoint(value = "/websocket/message/{cno}")
@Component
public class MessageWebSocket {


    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    private static CopyOnWriteArraySet<Map<String, MessageWebSocket>> webSocketSet = new CopyOnWriteArraySet<Map<String, MessageWebSocket>>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;


    /**
     * 连接建立成功调用的方法
     * @param session  可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
     * @throws EncodeException
     * @throws IOException
     */
    @OnOpen
    public void onOpen(@PathParam(value = "cno") String param, Session session) throws EncodeException, IOException{
        this.session = session;
        Map<String, MessageWebSocket> map = new HashMap<String, MessageWebSocket>();
        String name = param ;
        Map<String, List<String>> listMap = session.getRequestParameterMap();

        map.put(name,this);


        addSocket(map, name);
    }

    // 添加map 到 webSocketSet,
    public void addSocket(Map<String, MessageWebSocket> map, String name) {
        // 删除重复的连接
        for(Map<String, MessageWebSocket> item: webSocketSet){
            for(String key : item.keySet()){
                if (key.toString().equals(name)) {
                    webSocketSet.remove(item);


                }
            }
        }
        webSocketSet.add(map); //加入set中


    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(){
        for (Map<String, MessageWebSocket> item : webSocketSet) {
            for(String key : item.keySet()){
                if(item.get(key) == this){
                    // 删除关闭的连接
                    webSocketSet.remove(item);


                }
            }
        }
    }

    /**
     * 收到客户端消息后调用的方法
     * @param message 客户端发送过来的消息
     * @param session 可选的参数
     * @throws EncodeException
     */
    @OnMessage
    public void onMessage(String message, Session session) throws EncodeException {

        Map<String,Object> map = (Map<String, Object>) JSONObject.parse(message);
        System.out.println("socket=message=="+message );

        String cno= (String) map.get("cno");



        for(Map<String, MessageWebSocket> item: webSocketSet){
            for(String key : item.keySet()){
                System.out.println(key +"============key");

                if(key.equals(cno)){
                    MessageWebSocket webSocket = item.get(key);
                    try {

                        webSocket.sendMessage( message);
                    } catch (IOException e) {
                        e.printStackTrace();
                        continue;
                    }
                }



            }
        }



    }

    /**
     * 发生错误时调用
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error){

        error.printStackTrace();

    }

    /**
     * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
     * @param message
     * @throws IOException
     */
    public void sendMessage(String message) throws IOException{
        synchronized (this.session) {
            this.session.getBasicRemote().sendText(message);
        }
    }


}

vue


api/common.js配置路径

export const messageSocketUrl='ws://127.0.0.1:8099/websocket/message/'

api/messageSocket.js

export default {
    ws: {},
    setWs: function(newWs) {
        this.ws = newWs
    }

}

main.js配置全局

import Vue from 'vue'

 
import * as echarts from 'echarts'

import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

import messageSocket from './api/messageSocket'
Vue.prototype.$messageSocket = messageSocket

Vue.prototype.$echarts = echarts



Vue.use(ElementUI);


Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  router
}).$mount('#app')

import messageSocket from './api/messageSocket'
Vue.prototype.$messageSocket = messageSocket

关键的是上面2行


chat.vue可代入房间号cno或者不带

 <template>
    <div class="about ">

        <v-header />
        <v-sidebar />

        <div class="content-box " >

<br>
        <div  style="width: 95%">
            <el-row  >
                <el-col :span="4" class="  bkk" >
                    <div class="kfdiv">
                        <table  v-for="(t,i) in uli" :class="'bgg ' +(t.uid==chatuid?'selxian':'')">
                            <tr @click="chooseuser(t,i)">
                                <td class="kfw" valign="top"><img class="kffaceimg" :src="FILE_URL+t.faceimg"></td>
                                <td class="dibuxian"> <span class="kfname">{{t.nickname}}</span> </td>
                            </tr>
                        </table>


                    </div>
                </el-col>
                <el-col :span="20" class=" bkk">
                    <div class="chatdiv" id="chatgf">
                        <div v-for="(t,i) in cli">
                            <table v-if="lander.id!=t.uid" class="bgg">
                                <tr>
                                    <td class="ltr" valign="top"><img :src="FILE_URL+t.faceimg" class="faceimg"></td>
                                    <td class="lnr">
                                        <span class="huizi">{{t.nickname}}&nbsp;&nbsp;{{t.cts}}</span><br>
                                        <p class="lcnr">{{t.cont}}</p>
                                    </td>
                                </tr>
                            </table>
                            <table v-if="lander.id==t.uid" class="bgg">
                                <tr>

                                    <td class="rnr">
                                        <span class="huizi">{{t.nickname}}&nbsp;&nbsp;{{t.cts}}</span><br>
                                        <p class="rcnr">{{t.cont}}</p>
                                    </td>
                                    <td class="rtr" valign="top"><img :src="FILE_URL+t.faceimg" class="faceimg"></td>
                                </tr>
                            </table>
                        </div>

                    </div>

                    <el-row class="chatnr  "  >
                        <el-col :span="22"  >
                            <el-input    v-model="context"   placeholder="请输入您的内容"></el-input>
                        </el-col>

                        <el-col :span="2"  >
                            <el-button  :disabled=" chatuid?false:true"  @click="saveC" type="success">提交</el-button>
                        </el-col>
                    </el-row>
                </el-col>

            </el-row>
        </div>
        </div>
    </div>
</template>

<script>

    import vHeader from "./Header.vue";
    import vSidebar from "./Sidebar.vue";
    import { messageSocketUrl } from '../../api/common'
    import { chat_save, chat_list, chat_getChatRooms ,chat_info,users_list} from '../../api';
    export default {
        name: "NoticeDetail",
        components: {
            vHeader,vSidebar
        },
       
        data() {



            return {
                cno:'',

                FILE_URL:'',
                context:'',
                chatuid:'',



                lander:{},
                islogin:'',

                uli:[],
                cli:[],



                isfirst:true,


            }
        },
        methods:{
            getInfo(chatid){
                chat_info({id:chatid}).then((res) => {

                    if(res.data.status==1){
                        this.cli.push(res.data.obj);
                        this.gobottom();

                    }else{
                            this.$message.info('消息发送失败')
                    }
                })
            },
            sendMessage(msg) {
                let that = this;
                console.log(that.$messageSocket.ws);

                console.log("发送信息", msg);
                that.$messageSocket.ws.send(msg);

                // if (that.$messageSocket.ws && that.$messageSocket.ws.readyState == 1) {
                //     console.log("发送信息", msg);
                //     that.$messageSocket.ws.send(msg);
                // } else {
                //     that.ws = new WebSocket(messageSocketUrl + this.cno);
                //     that.$messageSocket.setWs(that.ws);
                //     setTimeout(() => {
                //         console.log("setTimeout发送信息", msg);
                //         that.$messageSocket.ws.send(msg);
                //     }, 2000)
                // }

            },
            saveC() {


                if ( this.context.trim().length==0) {
                    this.$message.error('请输入内容');
                    return  ;
                }

                chat_save({uid:this.lander.id, cont: this.context ,cno:this.cno}).then((res) => {

                    if(res.data.status==1){
                        this.context='';



                        this.sendMessage( JSON.stringify(res.data.obj));


                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },
            gobottom(){
                setTimeout(()=>{
                    let scrollTarget = document.getElementById("chatgf");
                    scrollTarget.scrollTop=scrollTarget.scrollHeight;
                },500)
            },
            getcli(){
                chat_list({cno: this.cno}).then((res) => {

                    if(res.data.status==1){
                        this.cli=res.data.obj;





                        if(this.isfirst){
                            this.gobottom();
                            this.isfirst=false;
                        }





                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },

            getuli(){
                chat_getChatRooms({ uid:this.lander.id,cno:this.cno}).then((res) => {

                    if(res.data.status==1){
                        this.uli=res.data.obj;

                        let  index = ( this.uli || []).findIndex((item) => item.cno === this.cno);
                        if(index>-1){
                            this.chooseuser(this.uli[index],index);
                        }


                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },
            chooseuser(t,i){


                this.chatuid=t.uid;
                this.cno=t.cno;

                let that=this;
                that.ws = new WebSocket(messageSocketUrl + this.cno);
                that.$messageSocket.setWs(that.ws);
                that.$messageSocket.ws.onmessage = function(msg) {
                    console.log(msg.data,"socket接收到的消息")
                    let m=JSON.parse(msg.data);
                    that.getInfo(m.id)

                };

                this. getcli();




            },
            getkfli(){
                users_list({role:'admin',state:1}).then((res) => {
                    this.uli=[];
                    if(res.data.status==1){
                        let li=res.data.obj;
                        for(let i=0;i<li.length;i++){
                            let o=li[i];

                            let cno=this.lander.id+'_'+o.id;
                            if(parseInt(this.lander.id)>parseInt(o.id))cno=o.id+'_'+this.lander.id;

                            o.uid=o.id;
                            o.cno=cno;
                            this.uli.push(o)
                        }
                        console.log(this.uli)



                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },



        },mounted() {
            this.FILE_URL=process.env.VUE_APP_API_ROOT;

            this.lander=JSON.parse(localStorage.loginUser);

            if( this.$route.query.cno) {
                this.cno = this.$route.query.cno;
                this.getuli();
            }

            if(this.$route.query.seltype=='qt'){
                this.getkfli();
            }

            if(this.$route.query.seltype=='kf'){
                this.getuli();
            }



        },
        watch:{
            $route:function(value){

                //已建立回话的前提,直接跳转回话
                if(value.query.cno){
                    this.cno =value.query.cno;
                    this.getuli();
                }


                //固定客服,前台咨询,查客服表
                if(value.query.seltype=='qt'){
                    this.getkfli();
                }
                //客服后台
                if(value.query.seltype=='kf'){
                    this.getuli();
                }

                //如果就是好盆友聊天请直接调用this.getuli();


            }

        },
        deactivated() {

        },destroyed() {

        }
    }


</script>
<style scoped>
    .bgg{width: 100%;margin-bottom: 10px;}
    .bkk{border: 1px solid #888;border-radius:10px;height:500px;}
    .chatdiv{height: 440px; overflow-y: auto;padding: 10px;}
    .chatnr{height: 50px;}
    .faceimg{width: 50px;height: 50px;border-radius: 50%; }
    .lnr{ text-align: left; }
    .huizi{color: #666;font-size: 13px;}
    .lcnr{background-color: #dddddd;padding: 10px;max-width: 80%;display: inline-block;border-radius: 10px;}
    .ltr{width: 60px}

    .rtr{width: 60px;text-align: right;}
    .rnr{text-align: right;}
    .rcnr{background-color: #2f7bbf;padding: 10px;max-width: 80%;color: #fff;display: inline-block;text-align: left;border-radius: 10px;}

    .kfdiv{overflow-y: auto;padding: 10px 0px;height: 100%;}

    .kffaceimg{width: 40px;height: 40px;border-radius: 50%; }
    .kfw{width: 50px;}
    .kfname{font-size: 13px;color:#333;}
    .dibuxian{border-bottom: 1px solid #8888;}

    .selxian{background-color:#ddd;}
</style>


谷歌部分功能受限,可以用国内两个浏览器测试


可以上传图片的vue

<template>
    <div class="  ">



        <div class="  " >

            <br>
            <div  style="width: 100%">
                <el-row  >
                    <el-col :span="4" class="  bkk" >
                        <div class="kfdiv">
                            <table  v-for="(t,i) in uli" :class="'bgg ' +(t.uid==chatuid?'selxian':'')">
                                <tr >
                                    <td class="kfw" valign="top"><img  @click="chooseuser(t,i)" class="kffaceimg" :src="FILE_URL+t.faceimg"></td>
                                    <td class="dibuxian"> <span class="kfname"  @click="chooseuser(t,i)">{{t.nickname}}</span><el-tag type="danger" size="mini" v-if="ctype=='hy' "  @click="delhandle(t)" >删除</el-tag> </td>
                                </tr>
                            </table>


                        </div>
                    </el-col>
                    <el-col :span="20" class=" bkk">
                        <div class="chatdiv" id="chatgf">
                            <div v-for="(t,i) in cli">
                                <table v-if="lander.id!=t.uid" class="bgg">
                                    <tr>
                                        <td class="ltr" valign="top"><img :src="FILE_URL+t.faceimg" class="faceimg"></td>
                                        <td class="lnr">
                                            <span class="huizi">{{t.nickname}}&nbsp;&nbsp;{{t.cts}}</span><br>
                                            <p class="lcnr" v-if="t.cctype=='text'">{{t.cont}}</p>
                                            <p class="lcnr" v-if="t.cctype=='img'"> <img :src="FILE_URL+t.cont" style="max-width: 100%;"></p>
                                        </td>
                                    </tr>
                                </table>
                                <table v-if="lander.id==t.uid" class="bgg">
                                    <tr>

                                        <td class="rnr">
                                            <span class="huizi">{{t.nickname}}&nbsp;&nbsp;{{t.cts}}</span><br>
                                            <p class="rcnr"  v-if="t.cctype=='text'">{{t.cont}}</p>
                                            <p class="rcnr"  v-if="t.cctype=='img'"> <img :src="FILE_URL+t.cont" style="max-width: 100%;"></p>
                                        </td>
                                        <td class="rtr" valign="top"><img :src="FILE_URL+t.faceimg" class="faceimg"></td>
                                    </tr>
                                </table>
                            </div>

                        </div>
                        <el-upload

                                v-show="false"
                                ref="uploadRef"
                                drag
                                :before-upload="beforeUploadFile"
                                :show-file-list="false"
                                :action=FILE_ACTION
                                :on-success="handleFileSuccess"
                                accept="image/*"
                                :multiple="true">

                        </el-upload>


                        <el-row class="chatnr  "  >
                            <el-col :span="20"  >
                                <el-input    v-model="context"   placeholder="请输入您的内容"></el-input>
                            </el-col>

                            <el-col :span="4"  >

                                <el-button   :disabled=" chatuid?false:true" @click="uploadC"  icon="el-icon-upload"  type="info"></el-button>

                                <el-button  :disabled=" chatuid?false:true"  @click="saveC" type="success">提交</el-button>
                            </el-col>
                        </el-row>
                    </el-col>

                </el-row>
            </div>
        </div>
    </div>
</template>

<script>
    import  PubSub from 'pubsub-js'

    import { messageSocketUrl } from '../../api/common'
    import {chat_save, chat_list, chat_getChatRooms, chat_info, chat_del} from '../../api';
    export default {
        name: "Chat",
        props:{
            cno:{
                type:String,
                default:'',
            },
            ctype:{
                type:String,
                default:'',
            },

        },
        components: {

        },

        data() {



            return {
                inv:null,



                context:'',
                chatuid:'',

                FILE_ACTION:'',
                FILE_URL:'',


                lander:{},
                islogin:'',

                uli:[],
                cli:[],



                isfirst:true,


            }
        },
        methods:{
            delhandle(row){
                this.$confirm('确定删除该好友?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                    chat_del({cno: row.cno}).then((res) => {
                        let data = res.data;
                        if(data.status==1){

                            this.getuli();

                        }else{
                            this.$message.error(data.msg);
                        }

                    })
                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消'
                    });
                });
            },
            uploadC(){
                // 通过 ref 获取 el-upload 组件实例
                const uploadInstance = this.$refs.uploadRef;
                if (uploadInstance) {
                    // 找到 el-upload 中的 input 元素
                    const inputElement = uploadInstance.$el.querySelector('input[type="file"]');
                    if (inputElement) {
                        // 触发 input 元素的点击事件
                        inputElement.click();
                    }
                }
              },
            beforeUploadFile(){

                this.loading = this.$loading({
                    lock: true,
                    text: "上传中,请稍等,,,,",
                    spinner: "el-icon-loading",
                    background: "rgba(0, 0, 0, 0.5)",
                });
            },
            handleFileSuccess(res) {
                this.loading.close();
                console.log(res)
                if( res.status==1){



                     let img=res.obj  ;

                    let o={uid:this.lander.id, cont: img ,cno:this.cno,cctype:'img'};

                    chat_save(o).then((res) => {

                        if(res.data.status==1){
                            this.isfirst=true;
                            this.sendMessage( JSON.stringify(res.data.obj));


                        }else{
                            this.$message.info(res.data.msg);
                        }
                    })


                }else{
                    this. $message.error( '上传失败' );
                }

            },

            getInfo(chatid){
                chat_info({id:chatid}).then((res) => {

                    if(res.data.status==1){
                        this.cli.push(res.data.obj);
                        this.gobottom();

                    }else{
                        this.$message.info('消息发送失败')
                    }
                })
            },
            sendMessage(msg) {
                let that = this;
                console.log(that.$messageSocket.ws);

                console.log("发送信息", msg);
                that.$messageSocket.ws.send(msg);

                // if (that.$messageSocket.ws && that.$messageSocket.ws.readyState == 1) {
                //     console.log("发送信息", msg);
                //     that.$messageSocket.ws.send(msg);
                // } else {
                //     that.ws = new WebSocket(messageSocketUrl + this.cno);
                //     that.$messageSocket.setWs(that.ws);
                //     setTimeout(() => {
                //         console.log("setTimeout发送信息", msg);
                //         that.$messageSocket.ws.send(msg);
                //     }, 2000)
                // }

            },
            saveC() {


                if ( this.context.trim().length==0) {
                    this.$message.error('请输入内容');
                    return  ;
                }
                let o={uid:this.lander.id, cont: this.context ,cno:this.cno,cctype:'text'};

                chat_save(o).then((res) => {

                    if(res.data.status==1){
                        this.context='';
                        this.isfirst=true;


                        this.sendMessage( JSON.stringify(res.data.obj));


                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },
            gobottom(){
                setTimeout(()=>{
                    let scrollTarget = document.getElementById("chatgf");
                    scrollTarget.scrollTop=scrollTarget.scrollHeight;
                },500)
            },
            getcli(){
                chat_list({cno: this.cno}).then((res) => {

                    if(res.data.status==1){
                        this.cli=res.data.obj;







                        if(this.isfirst){
                            this.gobottom();
                            this.isfirst=false;
                        }





                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },

            getuli(){
                let o={ uid:this.lander.id,cno:this.cno};
                if(this.ctype=='hy'){
                     o.isfriends=1;
                }
                chat_getChatRooms(o).then((res) => {

                    if(res.data.status==1){
                        this.uli=res.data.obj;

                        let  index = ( this.uli || []).findIndex((item) => item.cno === this.cno);
                        if(index>-1){
                            this.chooseuser(this.uli[index],index);
                        }

                        if(this.ctype=='one'){
                            let u=this.uli[index];
                            this.uli=[];
                            this.uli.push(u);
                        }


                    }else{
                        this.$message.info(res.data.msg);
                    }
                })
            },
            chooseuser(t,i){


                this.chatuid=t.uid;
                this.cno=t.cno;

                let that=this;
                that.ws = new WebSocket(messageSocketUrl + this.cno);
                that.$messageSocket.setWs(that.ws);
                that.$messageSocket.ws.onmessage = function(msg) {
                    console.log(msg.data,"socket接收到的消息")
                    let m=JSON.parse(msg.data);
                    that.getInfo(m.id)

                };

                this. getcli();




            },




        },mounted() {
            this.FILE_URL=process.env.VUE_APP_API_ROOT
            this.FILE_ACTION=process.env.VUE_APP_API_ROOT+'/common/upimg?type=chat' ;



            this.lander=JSON.parse(localStorage.loginUser);


            PubSub.subscribe('chat_cno_ctype',(msg,index)=>{
                if(index){
                    let arr=index.split('@#@')
                    this.cno=arr[0];
                    this.ctype=arr[1];

                    this.getuli();

                }
            });


            this.getuli();

            this.inv=setInterval(()=>{

                this. getcli();
            },1000*5 )



        },

        deactivated() {
           if(this.inv !=null) clearInterval(this.inv)
        },destroyed() {
            if(this.inv !=null) clearInterval(this.inv)
        }
    }


</script>
<style scoped>
    .bgg{width: 100%;margin-bottom: 10px;}
    .bkk{border: 1px solid #888;border-radius:10px;height:500px;}
    .chatdiv{height: 440px; overflow-y: auto;padding: 10px;}
    .chatnr{height: 50px;}
    .faceimg{width: 50px;height: 50px;border-radius: 50%; }
    .lnr{ text-align: left; }
    .huizi{color: #666;font-size: 13px;}
    .lcnr{background-color: #dddddd;padding: 10px;max-width: 80%;display: inline-block;border-radius: 10px;}
    .ltr{width: 60px}

    .rtr{width: 60px;text-align: right;}
    .rnr{text-align: right;}
    .rcnr{background-color: #2f7bbf;padding: 10px;max-width: 80%;color: #fff;display: inline-block;text-align: left;border-radius: 10px;}

    .kfdiv{overflow-y: auto;padding: 10px 0px;height: 100%;}

    .kffaceimg{width: 40px;height: 40px;border-radius: 50%; }
    .kfw{width: 50px;}
    .kfname{font-size: 13px;color:#333;}
    .dibuxian{border-bottom: 1px solid #8888;}

    .selxian{background-color:#ddd;}
</style>

好博客就要一起分享哦!分享海报

此处可发布评论

评论(0展开评论

暂无评论,快来写一下吧

展开评论

您可能感兴趣的博客

客服QQ 1913284695