简单聊天室的实现 需要自己安装模块以及配置数据库

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="/public/css/bootstrap-3.4.1-dist/css/bootstrap.min.css">
  <style>
    /* 初始化 */
    * {
      padding: 0px;
      margin: 0px;
      list-style: none;
      box-sizing: border-box;
    }

    /* 背景宽高和颜色 */
    html,
    body {
      width: 100%;
      height: 100vh;
      /* background-color: aqua; */
    }

    /* 页面 */
    .room {
      width: 78%;
      height: 78%;
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      margin: auto;
      border: 1px solid #cccecf;
      /* border-radius: 10px; */
      /* overflow: hidden; */
    }

    /* 左侧样式 */
    .left {
      width: 12%;
      height: 100%;
      /* line-height: middle; */
      background-color: #badef1;
      border-right: 1px solid #cccecf;
      /* position: relative; */
      position: absolute;
      left: 0;
      top: 0;
    }

    /* 图片 */
    .left img {
      width: 50px;
      height: 50px;
      position: absolute;
      left: 45px;
      top: 20px;
    }

    .left span {
      text-align: center;
      font-size: 20px;
      display: block;
      position: absolute;
      left: 48px;
      top: 70px;
    }

    /* 右侧样式 */
    .right {
      width: 88%;
      height: 100%;
      background-color: #f6f9fa;
      position: absolute;
      right: 0;
      top: 0;
    }

    /* 右侧上盒样式 */
    .right .r-top {
      width: 100%;
      height: 10%;
      /* background-color: rgb(26, 72, 222); */
      border-bottom: 1px solid #cccecf;
      position: relative;
    }

    /* 关闭按钮 */
    .close {
      width: 72px;
      height: 24px;
      text-align: center;
      line-height: 24px;
      border-radius: 5px;
      background-color: #d88080;
      font-size: 14px;
      color: #fff;
      position: absolute;
      right: 14px;
      top: 10px;
      transition: 0.5s ease;
    }

    .close:hover {
      cursor: pointer;
      background-color: rgb(223, 5, 5);
    }

    /* 右侧下盒样式 */
    .right .r-bom {
      width: 100%;
      height: 90%;
      /* display: flex; */
      position: relative;
    }

    /* 聊天框 */
    .r-left {
      width: 76%;
      height: 100%;
      border-right: 1px solid #cccecf;
      position: absolute;
      left: 0;
    }

    /* 显示区 */
    .r-l-top {
      width: 100%;
      height: 75%;
      border-bottom: 1px solid #cccecf;
      overflow-x: hidden;
      overflow-y: scroll;
      padding: 5px;
    }

    .r-l-top img {
      width: 24px;
      height: 24px;
      margin-top: 4px;
    }

    /* 左文字框 */
    .show-l {
      width: 100%;
      height: 32px;
      line-height: 32px;
      /* background-color: aqua; */
      padding-left: 4px;
      margin: 5px 0;
    }

    .show-l img {
      float: left;
      margin-right: 4px;
    }

    .show-l span {
      float: left;
      margin: 0 4px;
      display: block;
      padding: 0 4px;
    }

    .l-yu {
      background-color: #bababa;
      border-radius: 4px;
    }

    /* 右文字框 */
    .show-r {
      width: 100%;
      height: 32px;
      line-height: 32px;
      /* background-color: lawngreen; */
      padding-right: 4px;
      margin: 5px 0;
    }

    .show-r img {
      float: right;
      margin-left: 4px;
    }

    .show-r span {
      float: right;
      margin: 0 4px;
      display: block;
      padding: 0 4px;
    }

    .r-yu {
      background-color: greenyellow;
      border-radius: 4px;
    }



    /* 输入区 */
    .r-l-bom {
      width: 100%;
      height: 25%;
      position: relative;
    }

    /* 工具 */
    .gongju {
      width: 100%;
      height: 22px;
      position: relative;
    }

    /* 聊天记录按钮 */
    .record {
      width: 60px;
      height: 20px;
      font-size: 12px;
      line-height: 20px;
      text-align: center;
      position: absolute;
      top: 2px;
      right: 5px;
      border: 1px solid transparent;
    }

    .record:hover {
      cursor: pointer;
      border-color: #cccecf;
    }

    /* 输入框 */
    .kuang .shuru {
      width: 100%;
      height: 9vh;
      resize: none;
      outline: none;
      border: none;
      background-color: #f6f9fa;
      padding: 4px;
    }

    /* 发送按钮 */
    .send {
      width: 72px;
      height: 24px;
      text-align: center;
      line-height: 24px;
      border-radius: 12px;
      background-color: #80bdde;
      font-size: 14px;
      color: #fff;
      position: absolute;
      right: 10px;
      bottom: 4px;
      transition: 0.5s ease;
    }

    .send:hover {
      cursor: pointer;
      background-color: #137bff;
    }

    /* 成员信息 */
    .r-right {
      width: 24%;
      height: 100%;
      position: absolute;
      right: 0;
    }

    /* 公告 */
    .r-r-top {
      width: 100%;
      height: 20%;
      border-bottom: 1px solid #cccecf;
    }

    /* 成员列表 */
    .r-r-bom {
      width: 100%;
      height: 80%;
    }

    /* 人数 */
    .r-r-bom .msg {
      width: 100%;
      height: 8%;
      line-height: 32px;
      border-bottom: 1px solid #cccecf;
      background-color: #f1f7fc;
      font-size: 14px;

    }

    .msg span {
      padding-left: 4px;
    }

    /* 详情 */
    .r-r-bom .list {
      width: 100%;
      height: 92%;
      overflow-x: hidden;
      overflow-y: scroll;
    }

    .list li {
      width: 100%;
      height: 24px;
      line-height: 24px;
      font-size: 12px;
      padding: 2px;
      /* display: flex; */
      position: relative;
    }

    .list li:hover {
      background-color: #badef1;
    }

    .list li img {
      width: 20px;
      height: 20px;
      margin-left: 5px;
    }

    .list li span {
      display: block;
      position: absolute;
      left: 34px;
      bottom: 1px;
    }

    /* 聊天记录 */
    .modal-body {
      height: 45vh;
      overflow-x: hidden;
      overflow-y: scroll;
    }

    .chat-l {
      margin: 8px;
    }

    .chat-l img {
      width: 30px;
      height: 30px;
    }


    .mebred {
      color: red;
      /* display: none; */
    }
  </style>
</head>

<body>


  <div class="room">
    <!-- 左侧 -->
    <div class="left">
      <img src="<%= userInfo.pic %>" alt=""><span>
        <%= userInfo.user %>
      </span>
    </div>
    <!-- 右侧 -->
    <div class="right">
      <!-- 头部 -->
      <div class="r-top">
        群名
        <!-- 关闭按钮 -->
        <div class="close" onclick="close()">
          关闭
        </div>
      </div>
      <!-- 底部 -->
      <div class="r-bom">
        <!-- 聊天 -->
        <div class="r-left">
          <!-- 显示聊天 -->
          <div class="r-l-top">

            <!-- <div class="show-l">
              <img src="/public/img/default.webp" alt=""><span class="l-name"><b>刘备</b>:</span><span
                class="l-yu">宝贝~~想你了</span>
            </div>

            <div class="show-r">
              <img src="<%= userInfo.pic %>" alt=""><span class="r-name"><b>:<%= userInfo.user %></b></span><span
                class="r-yu">讨厌~死鬼!</span>
            </div> -->


          </div>

          <!-- 功能区 -->
          <div class="r-l-bom">
            <!-- 工具 -->
            <div class="gongju">
              <button type="button" class="record" data-toggle="modal" data-target="#myModal">聊天记录</button>
            </div>
            <!-- 输入框 -->
            <div class="kuang">
              <textarea name="" class="shuru"></textarea>
            </div>
            <!-- 发送按钮 -->
            <div class="send">
              发送
            </div>
          </div>
        </div>
        <!-- 公告和成员 -->
        <div class="r-right">
          <!-- 公告 -->
          <div class="r-r-top">
            公告:
          </div>
          <!-- 成员 -->
          <div class="r-r-bom">
            <!-- 人数 -->
            <div class="msg">
              <span>成员信息(/<%= result.length %>)</span>
            </div>
            <!-- 详情 -->
            <ul class="list">
              <% for(var i=0; i<result.length;i++){ %>
                <li id="<%= result[i].user%>">
                  <img src="<%= result[i].pic%>" alt=""><span>
                    <%= result[i].user%>
                  </span>
                </li>
                <% } %>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>


  <!-- 聊天记录模态框 -->
  <div class="modal" id="myModal">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">聊天记录</h5>
          <button type="button" class="close" data-dismiss="modal">&times;</button>
        </div>
        <div class="modal-body">



        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-success clear" data-dismiss="modal">关闭</button>
        </div>
      </div>
    </div>
  </div>

</body>
<script src="/public/js/jquery.1.11.1.min.js"></script>
<script src="/public/css/bootstrap-3.4.1-dist/js/bootstrap.min.js"></script>
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect("http://localhost:3000");
  var name = "<%= userInfo.user %>";
  // 点击发送
  $(".send").click(function () {
    var now = new Date();

    var year = now.getFullYear(); // 年份,如 2022
    var month = now.getMonth() + 1; // 月份,注意月份是从 0 开始计数的,所以要加 1  
    var day = now.getDate(); // 当月的日期,如 25
    var hour = now.getHours(); // 小时,24 小时制,如 10
    var minute = now.getMinutes(); // 分钟,如 30
    var second = now.getSeconds(); // 秒钟,如 45
    var datetime = `${year}-${month}-${day} ${hour}:${minute}:${second}`;


    var val = $(".shuru").val().trim();
    $(".r-l-top").append(`
              <div class="show-r">
                  <img src="<%= userInfo.pic %>" alt=""><span class="r-name"><b>:<%= userInfo.user %></b></span><span
                    class="r-yu">${val}</span>
                </div>
              </div> 
    `);

    $.ajax({
      url: "/data",
      type: "post",
      data: {
        user: "<%= userInfo.user %>",
        chat: val,
        time: datetime,
        pic: "<%= userInfo.pic %>",
      },
      success(res) {
        // console.log(res.msg);
      }
    })

    socket.emit('liao', { "user": "<%= userInfo.user %>", val, "pic": "<%= userInfo.pic %>" });
    $(".shuru").val("");
  })

  // 回车
  $(".shuru").keydown(function (e) {
    if (e.keyCode != 13) return;
    $(".send").trigger("click");
  })

  // 接收
  socket.on("liao", (res) => {
    console.log(res);
    $(".r-l-top").append(`
    <div class="show-l">
              <img src="${res.pic}" alt=""><span class="l-name"><b>${res.user}</b>:</span><span
                class="l-yu">${res.val}</span>
            </div>
    `);
  })

  // 关闭
  $(".close").click(function () {
    $.ajax({
      url: "/out",
      type: "get",
      success(res) {
        alert(res.msg);
        location.href = "/login";
      }
    });
    // $("#" + name).hide();
    socket.emit("down", name);
    socket.emit("black", name);

  })


  // 聊天记录
  $(".record").click(function () {
    $.ajax({
      url: "/gain",
      type: "get",
      success(res) {
        console.log(res);
        var s = res.res1
        for (var i = 0; i < s.length; i++) {
          $(".modal-body").append(`
          <div class="chat-l">
            <img src="${s[i].pic}" alt="">
            <span>用户: ${s[i].user}</span>
            <span>信息: ${s[i].chat}</span>
            <span>时间: ${s[i].time}</span>
          </div>
          `)
        }
      }
    })
  })

  // 关闭删除
  $(".clear").click(function () {
    $(".clear").parent().siblings().empty();
  })


  // 上线
  socket.emit("on", name);

  socket.on("on", (res) => {
    alert(res + "上线了")
  });

  // 下线
  socket.on("down", (res) => {
    alert(res + '下线了');
  })

  $.ajax({
    url: "/true",
    type: "post",
    data: {
      name
    },
    success(res) {
      console.log(res.res1);
      var a = res.res1[0];
      console.log(a);
      var {user,flag} = a;
      console.log(flag, user);
      if (flag == 1) {
        socket.emit("red", user);
        socket.on("red", (msg) => {
          // console.log(msg);
          $("#" + msg + " span").addClass("mebred");
        })
      }
    }
  })




  //在线列表 


  socket.emit("red", name);

  socket.on("red", (res) => {
    $("#" + res + " span").addClass("mebred");
    socket.emit("red", res);
  })

  socket.on("black", (res) => {
    $("#" + res + " span").removeClass("mebred");
  })

  socket.on('connect', () => {
    // 发送上线事件
    socket.emit('online');
    // socket.emit('red');
  });

  // 监听上线提醒事件
  socket.on('online', (message) => {
    // console.log(message);
    // $("#"+message).addClass("mebred");
    alert(message + "上线");

  });

  // 监听下线提醒事件
  socket.on('offline', (message) => {
    // $("#"+message).removeClass("mebred");
    alert(message + "下线");
  });

  // 监听连接断开事件
  socket.on('disconnect', () => {
  });

  socket.on('red', (message) => {
    // console.log(message);
    $(".list").append(`
                <li id="${message.user}">
                  <img src="${message.pic}" alt=""><span>
                    ${message.user}
                  </span>
                </li>
    `);

  });

  socket.on('black', (message) => {
    // console.log(message);
    // $("#" + message).hide();
    $(`#${message.user}`).remove();
  });

  socket.on('connect', () => {
    // 发送上线事件
  
  });

  


</script>

</html>

以上为主页

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    form {

      /* 设置透明度 */
      opacity: 80%;

      text-align: center;
      /* 再设置内边距 使得内容更偏向于中央位置 */
      /* 上方,下方内边距为120px 与 左边与右边均为100px 按照逆时针 */
      /* 但是会撑大盒子 */
      padding: 0px 100px;

      /* 设置文本文字的大小 */
      font-size: 18px;

      /* 添加圆角边框 */
      border-radius: 10px;

      /* 增加外边距 */
      /* 上下120px 然后左右居中 */
      margin: 120px auto;
    }

    .textinput {
      /* 设置宽高 */
      height: 40px;
      width: 100px;

      /* 设置内边距 */
      padding: 0 35px;

      /* 去除边框 */
      border: none;

      /* 设置背景颜色 */
      background: #F8F9F9;

      /* 设置字体大小 */
      font-size: 15px;

      /* 给文本框加上阴影 */
      box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.7), inset 0px 2px 5px #aaaaaa;

      /* 给文本框加上圆角边框 */
      border-radius: 5px;

      /* 给文本框中输入文字加上颜色 */
      color: saddlebrown;
    }

    /* 筛选input标签中 type为"submit"的 进行渲染*/
    input[type="submit"] {
      width: 110px;
      height: 40px;
      text-align: center;
      outline-style: none;
      border-style: none;
      border-radius: 50px;
      background: rgb(31, 209, 218);
      -webkit-text-stroke: 0px;
      box-shadow: inset 4px 4px 10px rgba(160, 162, 158, 0.814), 4px 4px 10px rgba(117, 117, 117, 0.3), 15px 15px 30px rgba(72, 70, 70, 0.193), inset -2px -2px 10px rgba(255, 254, 254, 0.873);
      transition: background-color 1s ease;
    }


    .nbclas:hover {
      background-color: #ff6a00;
      cursor: pointer;
    }

    a {
      /* 去除下划线 */
      text-decoration: none;
    }

    a:hover {
      /* 悬空的时候有被选中的样子 出现下划线*/
      text-decoration: underline;
    }

    * {
      margin: 0;
      padding: 0;
    }

    body {
      background: skyblue;
    }

    .main {
      /* 设置为绝对定位 */
      position: absolute;
      /* 设置盒子放在中间的位置 */
      left: 50%;
      top: 50%;
      /* 设置动态效果 */
      transform: translate(-50%, -50%);
      /* 设置盒子大小 */
      width: 400px;
      height: 400px;
      /* 把边框算入盒子大小 */
      box-sizing: border-box;
      border-radius: 50%;
      /* 背景透明 */
      background: transparent;
      /* 设置阴影边框 */
      box-shadow: inset 10px 20px 30px rgba(0, 0, 0, 0.5), 10px 10px 20px rgba(0, 0, 0, 0.3), 15px 15px 30px rgba(0, 0, 0, 0.05), inset -10px -10px 15px rgba(255, 255, 255, 0.8);
      /* 设置动画效果 */
      /* animation: move 6s linear infinite; */
    }

    .main::after {
      position: absolute;
      content: "";
      width: 40px;
      height: 40px;
      background: rgba(255, 255, 255, 0.5);
      left: 80px;
      top: 80px;
      border-radius: 50%;
      animation: move2 6s linear infinite;
      filter: blur(1px);
    }

    .main::before {
      position: absolute;
      content: "";
      width: 20px;
      height: 20px;
      background: rgba(255, 255, 255, 0.5);
      left: 130px;
      top: 70px;
      border-radius: 50%;
      animation: move3 6s linear infinite;
      filter: blur(1px);
    }

    /* 设置移动方位 */
    @keyframes move {
      50% {
        border-radius: 50% 50% 66% 34% / 26% 62% 38% 74%;
      }

      75% {
        border-radius: 750% 50% 49% 51% / 26% 62% 38% 74%;
      }

      25% {
        border-radius: 50% 50% 49% 51% / 52% 62% 38% 48%;
      }
    }

    @keyframes move2 {
      50% {
        left: 60px;
        top: 80px;
      }

      75% {
        left: 80px;
        top: 120px;
      }

      25% {
        left: 50px;
        top: 120px;
      }
    }

    @keyframes move3 {
      50% {
        left: 110px;
        top: 75px;
      }

      75% {
        left: 130px;
        top: 100px;
      }

      25% {
        left: 100px;
        top: 90px;
      }
    }
  </style>
</head>

<body>
  <div class="main">
    <form action="/doLogin" method="post">
      <p>用户名<br />
        <input type="text" class="textinput" placeholder="请输入用户名" name="user" />
      </p>
      <p>密码<br />
        <input type="password" class="textinput" placeholder="请输入密码" name="pass" />
      </p>
      <br>
      <p>
        <input type="submit" class="nbclas" value="登录" />
      </p>
      <p class="smtxt">还没有账户?<a href="/reg">注册</a></a>
    </form>
  </div>
</body>
</html>

以上为登录界面

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <!DOCTYPE html>
  <html lang="en">

  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
      form {

        /* 设置透明度 */
        opacity: 80%;

        text-align: center;
        /* 再设置内边距 使得内容更偏向于中央位置 */
        /* 上方,下方内边距为120px 与 左边与右边均为100px 按照逆时针 */
        /* 但是会撑大盒子 */
        padding: 0px 100px;

        /* 设置文本文字的大小 */
        font-size: 18px;

        /* 添加圆角边框 */
        border-radius: 10px;

        /* 增加外边距 */
        /* 上下120px 然后左右居中 */
        margin: 120px auto;
      }

      .textinput {
        /* 设置宽高 */
        height: 40px;
        width: 100px;

        /* 设置内边距 */
        padding: 0 35px;

        /* 去除边框 */
        border: none;

        /* 设置背景颜色 */
        background: #F8F9F9;

        /* 设置字体大小 */
        font-size: 15px;

        /* 给文本框加上阴影 */
        box-shadow: 0px 1px 1px rgba(255, 255, 255, 0.7), inset 0px 2px 5px #aaaaaa;

        /* 给文本框加上圆角边框 */
        border-radius: 5px;

        /* 给文本框中输入文字加上颜色 */
        color: saddlebrown;
      }

      /* 筛选input标签中 type为"submit"的 进行渲染*/
      input[type="submit"] {
        width: 110px;
        height: 40px;
        text-align: center;
        outline-style: none;
        border-style: none;
        border-radius: 50px;
        background: rgb(31, 209, 218);
        -webkit-text-stroke: 0px;
        box-shadow: inset 4px 4px 10px rgba(160, 162, 158, 0.814), 4px 4px 10px rgba(117, 117, 117, 0.3), 15px 15px 30px rgba(72, 70, 70, 0.193), inset -2px -2px 10px rgba(255, 254, 254, 0.873);
        transition: background-color 1s ease;
      }


      .nbclas:hover {
        background-color: #ff6a00;
        cursor: pointer;
      }

      a {
        /* 去除下划线 */
        text-decoration: none;
      }

      a:hover {
        /* 悬空的时候有被选中的样子 出现下划线*/
        text-decoration: underline;
      }

      * {
        margin: 0;
        padding: 0;
      }

      body {
        background: skyblue;
      }

      .main {
        /* 设置为绝对定位 */
        position: absolute;
        /* 设置盒子放在中间的位置 */
        left: 50%;
        top: 50%;
        /* 设置动态效果 */
        transform: translate(-50%, -50%);
        /* 设置盒子大小 */
        width: 400px;
        height: 400px;
        /* 把边框算入盒子大小 */
        box-sizing: border-box;
        border-radius: 50%;
        /* 背景透明 */
        background: transparent;
        /* 设置阴影边框 */
        box-shadow: inset 10px 20px 30px rgba(0, 0, 0, 0.5), 10px 10px 20px rgba(0, 0, 0, 0.3), 15px 15px 30px rgba(0, 0, 0, 0.05), inset -10px -10px 15px rgba(255, 255, 255, 0.8);
        /* 设置动画效果 */
        /* animation: move 6s linear infinite; */
      }

      .main::after {
        position: absolute;
        content: "";
        width: 40px;
        height: 40px;
        background: rgba(255, 255, 255, 0.5);
        left: 80px;
        top: 80px;
        border-radius: 50%;
        animation: move2 6s linear infinite;
        filter: blur(1px);
      }

      .main::before {
        position: absolute;
        content: "";
        width: 20px;
        height: 20px;
        background: rgba(255, 255, 255, 0.5);
        left: 130px;
        top: 70px;
        border-radius: 50%;
        animation: move3 6s linear infinite;
        filter: blur(1px);
      }

      /* 设置移动方位 */
      @keyframes move {
        50% {
          border-radius: 50% 50% 66% 34% / 26% 62% 38% 74%;
        }

        75% {
          border-radius: 750% 50% 49% 51% / 26% 62% 38% 74%;
        }

        25% {
          border-radius: 50% 50% 49% 51% / 52% 62% 38% 48%;
        }
      }

      @keyframes move2 {
        50% {
          left: 60px;
          top: 80px;
        }

        75% {
          left: 80px;
          top: 120px;
        }

        25% {
          left: 50px;
          top: 120px;
        }
      }

      @keyframes move3 {
        50% {
          left: 110px;
          top: 75px;
        }

        75% {
          left: 130px;
          top: 100px;
        }

        25% {
          left: 100px;
          top: 90px;
        }
      }
    </style>
  </head>

  <body>
    <div class="main">
      <form action="/doReg" method="post" enctype="multipart/form-data">
        <p>用户名<br />
          <input type="text" class="textinput" placeholder="请输入用户名" name="user" />
        </p>
        <p>密码<br />
          <input type="password" class="textinput" placeholder="请输入密码" name="pass" />
        </p>
        <br>
        <p>
          <input type="file" name="pic">
        </p>
        <br>
        <p>
          <input type="submit" class="nbclas" value="注册" />
        </p>
      </form>
    </div>
  </body>
  </html>
</body>
</html>

以上为注册页面 

注:以上均为ejs文件 需要下载ejs模块        

// 1.引入express模块
var express = require("express");
var app = express();
var server = require("http").createServer(app);
server.listen(3000);

// 7.引入socket.io模块
var io = require("socket.io")(server);
io.on("connection", (socket) => {
  // console.log("已经握手");
  socket.on("liao", (res) => {
    // console.log(res);
    socket.broadcast.emit("liao", res);
  });
});

// 静态路径
app.use("/public", express.static("./public"));
app.use("/uploads", express.static("./uploads"));
app.set("views", "./views");

// 2.引入ejs模块
app.set("view engine", "ejs");

// 3.引入mysql模块
var mysql = require("mysql");
var db = mysql.createConnection({
  host: "localhost",
  user: "root",
  password: "root",
  database: "chatroom",
});
db.connect();

// 4.引入body-parser模块
var bodyParser = require("body-parser");
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

// 5.引入formidable模块
var formidable = require("formidable");

// 6.引入fs模块
var fs = require("fs");

// 8.cookie模块
var cookieParser = require("cookie-parser");
app.use(cookieParser());

// 1.渲染登录页面
app.get("/", (req, res) => {
  res.redirect("/login");
});
app.get("/login", (req, res) => {
  res.render("login");
});

// 2.执行登录功能
app.post("/doLogin", (req, res) => {
  var { user, pass } = req.body;
  // console.log(req.body);
  if (!user.trim() || !pass.trim()) {
    res.send(`
      <script>alert("账号和密码不能为空");location.href="/login";</script>
    `);
  } else {
    var sql = "select * from member where user=?";
    db.query(sql, user, (err1, res1) => {
      if (res1.length <= 0) {
        res.send(`
        <script>alert("账号未注册,请完成注册");location.href="/reg";</script>
      `);
      } else {
        var sql1 = "select * from member where user=? and pass=?";
        db.query(sql1, [user, pass], (err2, res2) => {
          // console.log(res1);
          if (res2.length <= 0) {
            res.send(`
      <script>alert("账号或密码不正确,请重新登陆");location.href="/login";</script>
    `);
          } else {
            res.cookie("token", true, {
              maxAge: 1000 * 60 * 60,
            });
            res.cookie("userInfo", res2[0], {
              maxAge: 1000 * 60 * 60,
            });

            // 上下线
            io.on("connection", (socket) => {
              // 新的客户端连接
              // console.log('新成员上线了');

              // 监听客户端上线事件
              socket.on("online", () => {
                // 发送上线提醒给其他客户端
                socket.broadcast.emit("online", user);
              });

              // 监听客户端下线事件
              socket.on("disconnect", () => {
                // 发送下线提醒给其他客户端
                socket.broadcast.emit("offline", user);
              });
            });

            res.send(`
      <script>alert("登录成功");location.href="/index";</script>
    `);
          }
        });
      }
    });
  }
});

// 3.渲染注册页面
app.get("/reg", (req, res) => {
  res.render("reg");
});

// 4.实现注册功能
app.post("/doReg", (req, res) => {
  var form = formidable({
    uploadDir: "./uploads",
    keepExtensions: true,
  });
  form.parse(req, (err, fields, files) => {
    // console.log(err);
    // console.log(fields);
    console.log(files);
    var { user, pass } = fields;
    var flag = false;
    if (!user.trim() || !pass.trim) {
      fs.unlink("./uploads/" + files.pic.newFilename, () => {});
      res.send(`
      <script>alert("账号和密码不能为空");location.href="/reg";</script>
    `);
    } else {
      var pic;
      if (files.pic.size <= 0) {
        pic = "/public/img/default.webp";
      } else {
        pic = "/uploads/" + files.pic.newFilename;
      }
      var sql = "select * from member where user=?";
      db.query(sql, user, (err1, res1) => {
        // console.log(res1);
        if (res1.length > 0) {
          fs.unlink("./uploads/" + files.pic.newFilename, () => {});
          res.send(`
      <script>alert("账号已注册");location.href="/login";</script>
    `);
        } else {
          var sql1 = "insert into member(user,pass,pic,flag) values(?,?,?,?)";
          db.query(sql1, [user, pass, pic, flag], (err2, res2) => {
            // console.log(res2);
            if (res2.affectedRows >= 1) {
              res.send(`
              <script>alert("注册成功,请完成登录");location.href="/login";</script>
            `);
            } else {
              fs.unlink("./uploads/" + files.pic.newFilename, () => {});
              res.send(`
              <script>alert("网络异常");location.href="/reg";</script>
            `);
            }
          });
        }
      });
    }
  });
});

// 5.渲染聊天页面
app.get("/index", (req, res) => {
  var sql = "select * from member";
  db.query(sql, (err, result) => {
    var token = req.cookies.token || false;
    var userInfo = req.cookies.userInfo || null;
    var sql1 = "select * from history";
    isLogin(req, res) && res.render("index", { result, token, userInfo });
  });
});

// 6.关闭
app.get("/out", (req, res) => {
  res.clearCookie("token");
  res.clearCookie("userInfo");
  res.send({
    code: 200,
    msg: "退出成功",
  });
});

// 存储聊天
app.post("/data", (req, res) => {
  var { user, chat, time, pic } = req.body;
  // console.log(req.body);
  // console.log(user,chat);
  var sql = "insert into history(user,chat,time,pic) values(?,?,?,?)";
  db.query(sql, [user, chat, time, pic], (err, res1) => {
    // console.log(res1);
    if (res1.affectedRows >= 1) {
      res.send({
        code: 200,
        msg: "添加成功",
      });
    }
  });
});

// 权限
function isLogin(req, res) {
  var token = req.cookies.token || false;
  if (!token) {
    res.send(`
    <script>alert("未登录");location.href="/login";</script>
  `);
    return false;
  } else {
    return true;
  }
}

// 获取聊天
app.get("/gain", (req, res) => {
  var sql = "select * from history";
  db.query(sql, (err, res1) => {
    res.send({
      res1,
    });
  });
});

 js文件express框架实现关联功能 也需要下载安装express模块

  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值