VUE3+NODE开发一个简易的聊天室(3)

682 阅读4分钟

后端部分

由于本人后端开发经验较少,本项目也是本着学习的态度简单实现了一下,应该会有不少不合理之处,请指教。

建表

1.room表,用于存放用户新建的房间信息,字段为

  • id:主键。
  • name:房间名称。
  • introduce:房间简介
  • manageId:房主id
  • password:房间密码
  • code:随机生成的房间号
  • isDelete:房间是否被删除,假删标识

2.user表,用于存放用户信息,字段为

  • id:主键
  • username:用户名
  • password:密码

3.user_room中间表,用于关联房间与用户的关系,字段为

  • id:主键
  • roomId:房间id
  • userId:用户id
  • isDelete:是否删除

4.histroy历史记录表,存放聊天记录,字段为

  • id:主键
  • message:消息内容(此处有坑,下面详细介绍)
  • sendUser:发送人id
  • sendusername:发送人姓名(这里偷个懒,直接前端传姓名,合理的做法应该是后端自己查)
  • time:发送时间,查询历史记录时根据时间排序

搭建node服务

结构目录

image.png

初始化package.json

node init -y

安装必要的插件

yarn add express --save    //用于创建创建Web服务器
yarn add cors --save    //cors跨域
yarn add body-parser --save    //解析post请求
yarn add mysql --save    //连接数据库

创建server.js

const express = require("express")
const app = express()
const cors = require("cors")
const bodyParser = require("body-parser")
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}));
app.use(cors());
const mysql = require("mysql")

连接数据库

const connection = mysql.createConnection({ 
    host:'你的服务器地址', 
    user:"一般为root",
    password:"你的mysql密码",
    database:"你的数据库",
    charset:'utf8mb4' //注意连接池字符集
})
connection.connect()

头部信息

app.all('*', function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",'3.2.1');
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

做完以上部分就可愉快的写接口啦!例如登录:

app.post('/user/login',function(req,res){
    let username = req.body.username
    let password = req.body.password
    const sql = "select * from user where username ='"+username+"' and password ='"+password+"'"
    connection.query(sql,function(err,result){
        if(err){ 
            console.log('/user/login:',err)
            return;
        }
        if(result.length > 0){
            res.send({
                data:result[0],
                status:0
            })
        }else{
            res.send({
                status:1,
                message:"The username or password is incorrect"
            })
        }
    }); 
})   

socket部分

创建websocket.js

const ws = require("nodejs-websocket")
const createServer = ()=>{
    let server = ws.createServer(connection=>{
        connection.on('text', (result)=> {
            //这里处理客户端发送的消息,例如心跳
            connection.sendText(JSON.stringify({type:null,remark:"接收心跳"}))
        })
        connection.on('connect', function(code) {
            // console.log('开启连接', code)
        })
        connection.on('close', function(code) {
            // console.log('关闭连接', code)
        })
        connection.on('error', function(code) {
            // console.log('异常关闭', code)
        })
    }).listen(8012) 
    return server
}
module.exports = createServer()  

主要的接口以及逻辑

  • 用户登录、注册

    用户提交用户名、密码,接口校验数据库是否存在用户名,如果没有,进行注册;如果有,校验密码是否正确。登录或注册成功进入聊天室。这里只是简单实现了一下,正确用户体系应该更为复杂,密码也应该加密。

  • 获取用户已进入的聊天室

    通过中间表查询,通过inner join查询出房间的对应信息,接口判断房间是否需要密码,返回添加字段isPassword。

  • 房间验证、详情

    选择房间后,通过isPassword判断房间是否需要密码,如果需要,用户提交密码验证是否正确。进入房间后获取房间详情。

  • 创建房间

    用户提交表单,生成数字、字符、英文组成的18位房间号,插入数据库。

  • 删除房间

    只有管理员可以删除房间,前端通过房间详情的manageId和用户的id控制删除按钮的显隐,同时接口校验是否是管理员,将room的isDelete改为1

  • 退出房间

    将中间表的isDelete改为1,如果用户是管理员,删除房间。

  • 保存消息

    将用户发送的信息保存到history表,同时通过socket推送给当前房间的用户。

字符集

实现前期只考虑了文字消息,被帮忙测试的朋友吐槽了一番后,加上了表情功能,发现insert语句报错了,上网一查发现,emjio表情是4个字节,如果数据库或表为utf8编码,只能存储3字节,会导致插入报错,于是修改数据库、表的字符集为utf8mb4。

ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

但是依然插入失败,检查后发现,还需要修改连接池的charset,修改后插入成功,其实也称不上是坑,怪自己太嫩。

结尾

暂时先写到这儿吧,后面有优化或新功能会持续更新。应该有很多不合理的地方,有些功能甚至只是为了实现而实现,还得去多学习一些服务器、后端相关的知识。