简易聊天室代码分享 js+socket.io

news2024/11/25 0:29:14

先言

这我以前写的,这里就是单纯分享下代码,不算正经文章。效果如下,前端用一个单html文件。然后后端用node.js和socket.io,也是只用一个单js文件就好。这里可以看下代码的实现逻辑就好,因为来连数据库才能运行的。有需要的话告诉我,我也可以把存取数据库代码逻辑和接口逻辑删了,改成时时存时时失效的,这样就能直接打开html文件直接随意运行了。
在这里插入图片描述

在这里插入图片描述

代码

前端
html:

<!DOCTYPE html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <link rel="stylesheet" href="./chat.css" />
  </head>

  <body>
    <img class="bg" src="../bg.webp" alt="" />
    <div class="chat">
      <div class="left">
        <div class="title">
          <h3>聊天室</h3>
        </div>
        <div class="content" id="content">
          <div class="history" id="history">
            <button>查看最近的聊天</button>
          </div>
          <ul id="messages">
            <!--             <li class="data">
              <div class="img">
                <img
                  src="https://bbs-img.huaweicloud.com/user/img/head/1617968414164_1201_6320.jpg"
                  alt=""
                />
              </div>
              <p><span>小杰(老师):</span> 【摘要】</p>
            </li>
            <li class="data2">
              <p>
                <span>我:</span> 【摘要】
                首先,强类型不允许随意的隐式类型转换,而弱类型是允许的。JavaScript就是经典的弱类型语言。而Typescript可以说是JavaScript的超集,在js的基础上新增了许多语法特性,使得类型不再可以随意转换,能大大减少开发阶段的错误。
              </p>
              <div class="img">
                <img
                  src="https://bbs-img.huaweicloud.com/user/img/head/1617968414164_1201_6320.jpg"
                  alt=""
                />
              </div>
            </li> -->
          </ul>
        </div>
        <div class="shuru">
          <textarea
            id="m"
            type="text"
            autocomplete="off"
            autofocus=""
          ></textarea>
          <button id="btn">
            发送
          </button>
          <div class="emoji" id="emoji">
            😊
            <div id="ej" style="display: none;">
              <span>😂</span>
              <span>😐</span>
              <span>😤</span>
              <span>😴</span>
              <span>😫</span>
              <span>😧</span>
              <span>🤪</span>
              <span>😛</span>
              <span>😭</span>
              <span>😡</span>
              <span>👹</span>
              <span>🤢</span>
              <span>❤️</span>
              <span>💔</span>
              <span>👄</span>
              <span>🧝</span>
              <span>💇‍♀️</span>
              <span>💘</span>
              <span>👻</span>
              <span>☠️</span>
              <span>😱</span>
              <span>🌬️</span>
              <span>👌</span>
              <span>🤝</span>
            </div>
          </div>
        </div>
      </div>
      <div class="right">
        <div class="title">
          <h3>当前在线成员<span id="people">(0)</span></h3>
        </div>
        <div class="list" id="list">
          <!--      <div class="item">
            <img
              src="https://bbs-img.huaweicloud.com/user/img/head/1617968414164_1201_6320.jpg"
              alt=""
            />
            <p>小杰(学生)33333330000</p>
          </div> -->
        </div>
      </div>
    </div>
  </body>
  <!-- <script src="https://unpkg.com/axios/dist/axios.min.js"></script> -->
  <script>
    // 封装的ajax请求
    function ajax(url, params) {
      return new Promise((resolve, reject) => {
        //要发个get请求知道是你来了,后端解析你的信息

        let xhr = new XMLHttpRequest();

        // 设置属性
        xhr.open("post", url);

        // 如果想要使用post提交数据,必须添加此行
        xhr.setRequestHeader(
          "Content-type",
          "application/x-www-form-urlencoded"
        );
        // 将数据通过send方法传递
        xhr.send(params);
        // 发送并接受返回值
        xhr.onreadystatechange = function() {
          // 这步为判断服务器是否正确响应
          if (xhr.readyState == 4 && xhr.status == 200) {
            resolve(xhr.responseText);
          }
        };
      });
    }
  </script>
  <script src="./static/dist/socket.io.js"></script>
  <script>
    //要发个请求知道是你来了,后端解析你的信息
    /*    axios
      .post("http://localhost:8849/", {
        username: "787",
      })
      .then(function(response) {
        console.log(response);
      }); */

    let net_name = window.sessionStorage.getItem("net_name");
    let icon = window.sessionStorage.getItem("icon");
    let role = window.sessionStorage.getItem("role");
    let uid = window.sessionStorage.getItem("uid");
    if (role == "1") {
      role = "学生";
    } else if (role == "2") {
      role = "老师";
    } else {
      role = "管理员";
    }
    /*     let uid = Number(
      Math.random()
        .toString()
        .substr(3, 10) + Date.now()
    ).toString(36); */
    ajax(
      "http://localhost:8849/",
      `net_name=${net_name}&icon=${icon}&role=${role}&uid=${uid}`
    ).then(function(response) {
      console.log(response);
    });

    // 做个判断

    var socket = io("http://localhost:8849/");
    var btn = document.getElementById("btn");
    var ul = document.getElementById("messages");
    let cxt = document.getElementById("m");
    let people = document.getElementById("people");
    let content = document.getElementById("content");
    let list = document.getElementById("list");
    let history = document.getElementById("history");
    let emoji = document.getElementById("emoji");
    let ej = document.getElementById("ej");

    //选表情
    emoji.onclick = function(e) {
      if (ej.style.display == "block") {
        ej.style.display = "none";
      } else {
        ej.style.display = "block";
      }
    };
    ej.onclick = function(e) {
      // console.log(e.target.innerText);
      if (e.target.nodeName.toLowerCase() == "span") {
        cxt.value += e.target.innerText;
      }
    };

    history.onclick = function() {
      //查看历史记录
      history.style.display = "none";
      ajax("http://localhost:8849/query", "").then(function(response) {
        let data = JSON.parse(response).data;
        //先看下有几个小li了
        lis = document.getElementById("messages").getElementsByTagName("li")
          .length;
        console.log(lis);
        for (let i = lis; i < data.length - 1; i++) {
          let newli = document.createElement("li");
          if (data[i].uid == uid) {
            newli.setAttribute("class", "data2");
            newli.innerHTML = `
             <p>
                <span>${data[i].net_name}(${data[i].role}):</span> ${data[i].content}
              </p>
           <div class="img">
                <img
                  src="http://localhost:8848/${data[i].icon}"
                  alt=""
                />
              </div>
             `;
          } else {
            newli.setAttribute("class", "data");
            newli.innerHTML = `
           <div class="img">
                <img
                  src="http://localhost:8848/${data[i].icon}"
                  alt=""
                />
              </div>
              <p>
                <span>${data[i].net_name}(${data[i].role}):</span> ${data[i].content}
              </p>`;
          }
          ul.insertBefore(newli, ul.childNodes[0]);
        }
        //滚动到底部
        content.scrollTo({
          top: content.scrollHeight,
          behavior: "smooth",
        });
      });
    };

    // 点击send按钮,把消息发送给服务器
    btn.onclick = function() {
      if (cxt.value == "") return;
      // 把登录的用户名和输入框内容全部发送给服务器,让服务器做一次广播,才能同步用户信息。
      //把自己名字传给服务器,其实也不用,我在那局部变量保存了
      socket.emit("message", { net_name, role, uid, icon, inpval: cxt.value });

      //数据库添加数据
      ajax(
        "http://localhost:8849/add",
        `net_name=${net_name}&icon=${icon}&role=${role}&content=${cxt.value}&uid=${uid}`
      ).then(function(response) {
        console.log(response);
      });
      return false;
    };
    //监听服务器的广播消息,同步用户信息,msg就是点击发送按钮发送的用户信息
    socket.on("message", function(msg) {
      //在这可以通过名字判断是自己就放右边,别人就放左边

      // 每个客户端将用户的消息渲染
      var newli = document.createElement("li");
      // newli.innerHTML = msg.net_name + "(" + msg.role + ")" + ":" + msg.inpval;
      if (msg.uid == uid) {
        newli.setAttribute("class", "data2");
        newli.innerHTML = `
              <p>
                <span>${msg.net_name}(${msg.role}):</span> ${msg.inpval}
              </p>
               <div class="img">
                <img
                  src="http://localhost:8848/${msg.icon}"
                  alt=""
                />
              </div>`;
      } else {
        newli.setAttribute("class", "data");
        newli.innerHTML = `
           <div class="img">
                <img
                  src="http://localhost:8848/${msg.icon}"
                  alt=""
                />
              </div>
              <p>
                <span>${msg.net_name}(${msg.role}):</span> ${msg.inpval}
              </p>`;
      }
      ul.appendChild(newli);
      //滚动到底部
      content.scrollTo({
        top: content.scrollHeight,
        behavior: "smooth",
      });

      cxt.value = "";
    });
    // 服务器端监听服务端建立连接发来的信息,用于渲染温馨提示信息,msg是服务器返回广播的用户对象数据
    socket.on("loginin", function(msg) {
      // 生成用户进入房间提示信息标签
      let tip = document.createElement("p");
      console.log(msg.userList);
      tip.innerHTML = msg.des;
      // 设置样式
      tip.className = "tips";
      ul.appendChild(tip);
      // people是显示当前聊天室人数
      people.innerHTML = "( " + msg.count + "人 )";
      //更新在线用户列表
      list.innerHTML = " ";
      for (let i = 0; i < msg.userList.length; i++) {
        list.innerHTML += `
          <div class="item">
            <img
              src="http://localhost:8848/${msg.userList[i].icon}"
              alt=""
            />
            <p>${msg.userList[i].net_name}${msg.userList[i].role})</p>
          </div>
         `;
      }
    });
    //服务器端监听服务端建立连接发来的信息,msg是服务器返回广播的用户对象数据
    //关掉浏览器会执行下面这个函数
    socket.on("loginout", function(msg) {
      // 生成用户退出提示信息
      let tip = document.createElement("p");
      console.log(msg.userList);
      tip.innerHTML = msg.des;
      tip.className = "tips";
      ul.appendChild(tip);
      people.innerHTML = "( " + msg.count + "人 )";
      //更新在线用户列表
      list.innerHTML = " ";
      for (let i = 0; i < msg.userList.length; i++) {
        list.innerHTML += `
          <div class="item">
            <img
              src="http://localhost:8848/${msg.userList[i].icon}"
              alt=""
            />
            <p>${msg.userList[i].net_name}${msg.userList[i].role})</p>
          </div>
         `;
      }
    });
  </script>
</html>

css:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  height: 600px;
  display: flex;
  justify-content: center;
}
.bg {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  object-fit: cover;
  z-index: -1000;
}
.history {
  width: 100%;
  text-align: center;
}
.history button {
  border: none;
  height: 30px;
  width: 120px;
  cursor: pointer;
  background-color: rgb(88, 180, 230);
  border-radius: 2px;
  color: white;
}
.history button:hover {
  background-color: rgb(125, 195, 236);
}
.history button:active {
  background-color: rgb(88, 180, 230);
}
.chat {
  width: 1100px;
  height: 596px;
  margin: 20px auto;
}
.left {
  width: 800px;
  height: 100%;
  float: left;
  background-color: rgba(223, 241, 251, 0.8);
  border-radius: 10px;
  box-shadow: 0 0 5px rgb(153, 153, 153);
}
.left .emoji {
  position: absolute;
  width: 30px;
  height: 30px;
  background-color: rgb(88, 180, 230);
  right: 90px;
  line-height: 30px;
  text-align: center;
  border-radius: 2px;
  cursor: pointer;
}
.left .emoji div {
  width: 200px;
  height: 100px;
  background-color: #fff;
  position: absolute;
  top: -110px;
  left: -50%;
  display: flex;
  justify-content: space-evenly;
  flex-wrap: wrap;
  border-radius: 3px;
  align-items: center;
}
.left .emoji div::after {
  content: "";
  position: absolute;
  bottom: -9px;
  left: 25px;
  width: 10px;
  height: 10px;
  background-color: rgb(255, 255, 255);
  -webkit-clip-path: polygon(53% 100%, 0 0, 100% 0);
  clip-path: polygon(53% 100%, 0 0, 100% 0);
}
.left .emoji div span {
  line-height: 25px;
  text-align: center;
  font-size: 15px;
  width: 25px;
  height: 25px;
}
.right {
  width: 290px;
  float: right;
  height: 100%;
  border-radius: 10px;
  background-color: rgba(223, 241, 251, 0.8);
  box-shadow: 0 0 5px rgb(153, 153, 153);
}
.right .list {
  padding: 10px;
  width: 100%;
  height: 520px;
  display: flex;
  flex-wrap: wrap;
  align-content: start;
  overflow: auto;
}
.right .list .item {
  margin-top: 6px;
  width: 100%;
  height: 50px;
  background-color: red;
}
.right .list .item img {
  width: 50px;
  height: 50px;
  object-fit: cover;
  float: left;
}
.right .list .item p {
  line-height: 50px;
  background-color: #fff;
  text-indent: 1em;
  font-family: "fangsong";
}
.title {
  border-radius: 10px 10px 0 0;
  line-height: 60px;
  color: black;
  border-bottom: 1px solid #999;
  text-align: center;
  background-color: rgb(128, 199, 237);
}

.content {
  padding: 10px;
  width: 100%;
  overflow: auto;
  height: 400px;
}

#messages li {
  list-style: none;
  padding: 5px;
}

.shuru {
  border-top: solid 2px rgb(143, 143, 143);
  height: 130px;
  position: relative;
}
#m {
  width: 100%;
  height: 83px;
  outline: none;
  color: #666;
  overflow: auto;
  font-size: 16px;
  line-height: 25px;
  padding: 5px 10px;
  border: none;
  background-color: transparent;
  text-indent: 0;
}

#btn {
  border: none;
  height: 30px;
  width: 80px;
  cursor: pointer;
  position: absolute;
  right: 6px;
  bottom: 10px;
  background-color: rgb(88, 180, 230);
  border-radius: 2px;
}
#btn:hover {
  background-color: rgb(125, 195, 236);
}
#btn:active {
  background-color: rgb(88, 180, 230);
}
.tips {
  width: 50%;
  margin: 4px auto;
  padding: 2px 5px;
  text-align: center;
  font-size: 8px;
  border-radius: 10px;
  background-color: #cfcfcf;
  color: #fff;
}

.title #people {
  font-size: 8px;
  color: rgb(250, 27, 27);
}

.data {
  width: 100%;
  display: flex;
  justify-content: flex-start;
  min-height: 60px;
}
.data .img {
  width: 60px;
}
.data img {
  flex: 1;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 3px rgb(153, 153, 153);
}
.data p {
  font-size: 14px;
  line-height: 20px;
  margin-left: 10px;
  background-color: rgb(18, 183, 245);
  color: white;
  border-radius: 5px;
  padding: 10px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.data p span {
  width: 120px;
  overflow: hidden;
  color: rgb(255, 123, 0);
  background-color: rgb(223, 241, 251);
  border-radius: 2px;
  padding: 0 5px;
  font-size: 14px;
  margin-bottom: 5px;
}
.data2 p span {
  width: 120px;
  overflow: hidden;
  color: rgb(255, 123, 0);
  background-color: rgb(223, 241, 251);
  border-radius: 2px;
  padding: 0 5px;
  font-size: 14px;
  margin-bottom: 5px;
}
.data p::after {
  position: absolute;
  content: "";
  top: 10px;
  left: -9px;
  width: 10px;
  height: 10px;
  background-color: rgb(18, 183, 245);
  -webkit-clip-path: polygon(100% 100%, 100% 0, 0 51%);
  clip-path: polygon(100% 100%, 100% 0, 0 51%);
}
/*  */
.data2 {
  width: 100%;
  display: flex;
  justify-content: flex-end;
  min-height: 60px;
}
.data2 .img {
  width: 60px;
}
.data2 img {
  flex: 1;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 0 3px rgb(153, 153, 153);
}
.data2 p {
  line-height: 20px;
  margin-right: 10px;
  font-size: 14px;
  background-color: rgb(18, 183, 245);
  color: white;
  border-radius: 5px;
  padding: 10px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.data2 p::after {
  position: absolute;
  content: "";
  top: 10px;
  right: -9px;
  width: 10px;
  height: 10px;
  background-color: rgb(18, 183, 245);
  -webkit-clip-path: polygon(100% 50%, 0 0, 0 100%);
  clip-path: polygon(100% 50%, 0 0, 0 100%);
}

后端js文件:

/*
 * @Author: yournet_name
 * @Date: 2022-03-10 21:39:37
 * @LastEditTime: 2022-03-13 11:50:33
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \onlinechat-main\app.js
 */
const express = require('express')
const app = express()
var http = require('http').Server(app)
var io = require('socket.io')(http, { cors: true })



// 使得能接收post请求参数
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended:false }))
//使得express接收json格式数据
app.use(express.json());
// 解决跨域 
const cors = require('cors')
app.use(cors({credentials:true,origin:true}))
 // knex插件,连接数据库
const knex = require('knex')({
    client: 'mysql',
    connection: {
        hhost     : 'localhost',    //   
        user     : '',
        password : '',
        database : ''
    }
})


//时间格式转换
Date.prototype.Format = function (fmt) { // author: meizz
    var o = {
        "M+": this.getMonth() + 1, // 月份
        "d+": this.getDate(), // 日
        "h+": this.getHours(), // 小时
        "m+": this.getMinutes(), // 分
        "s+": this.getSeconds(), // 秒
        "q+": Math.floor((this.getMonth() + 3) / 3), // 季度
        "S": this.getMilliseconds() // 毫秒
    };
    if (/(y+)/.test(fmt))
        fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            return fmt;
} 

/* / 使用
var date = new Date();
date.format("yyyy-MM-dd"); */








/* 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();  
});  */ 


//meoji表情转义
function utf16toEntities(str) {
    var patt=/[\ud800-\udbff][\udc00-\udfff]/g; // 检测utf16字符正则
    str = str.replace(patt, function(char){
            var H, L, code;
            if (char.length===2) {
                H = char.charCodeAt(0); // 取出高位
                L = char.charCodeAt(1); // 取出低位
                code = (H - 0xD800) * 0x400 + 0x10000 + L - 0xDC00; // 转换算法
                return "&#" + code + ";";
            } else {
                return char;
            }
        });
    return str;
}




var userList = [] //当前在线用户数组
var user = {
  net_name:"",
  role:"",
  uid:"",
  icon:""
} //新进入用户 , 要公告推送消息

var count = 0

//通用接口,通过接口获取是谁进来了 ,要公告推送消息
app.post('/',(req,res)=>{

  let {net_name,role,uid,icon} = req.body; 
  user.net_name = net_name;
  user.role = role;
  user.uid = uid;
  user.icon = icon;
  userList.push({
      net_name,
      role,
      uid,
      icon
  })

  // 保存用户的名称
  
  // 返回状态码,通过状态码执行客户端页面跳转
  res.send({state:net_name})
  // res.sendFile(__dirname + '/index.html')
})
//新增聊天数据 用户点击发送应该也触发这个接口  到达50条后应该删除以前的
app.post('/add',(req,res)=>{
        
        // req.file得到文件信息,req.body的到文件文本信息
       let {net_name,icon,role,content,uid} = req.body  
        content = utf16toEntities(content)
        let create_time = new Date();
        create_time.Format("yyyy-MM-dd-hh:mm");  

           knex('chat').insert({net_name,icon,role,create_time,content,uid}).then(value=>{
             //   res.send({msg:'新增成功'})
            }).catch(value=>{
                    res.send({code:'400',msg:'发生错误'})  
                    console.log(value);
                })   
    }) 
//查询历史聊天记录   直接只取20条把
app.post('/query',(req,res)=>{
       knex.schema.raw(`select * from chat order by id  desc  limit 20`).then(value=>{
            if(res.length === 0){
              res.send({code:200,msg:'无结果'})
            }else{
              res.send({code:200,msg:'查询成功',data:value[0]})
            }
        }).catch(value=>{
            console.log(value);
        })
    })






//入口函数,连接进程 每一个用户(连接状态)都有一个下面这个函数,独立的
io.on('connection', function (socket) {


/*     let userSelf = {
      net_name:"",
      role:"",
      uid:""};
    userSelf.net_name = user.net_name;
    userSelf.role = user.role;
    userSelf.uid = user.uid;  */



    let net_name =user.net_name;   //局部变量,保存当前连接的是谁
    let icon =user.icon;   //局部变量,保存当前连接的是谁
    let uid =user.uid;   //局部变量,保存当前连接的是谁
    let role =user.role;   //局部变量,保存当前连接的是谁




    // console.log('有人连接');
  // 每建立连接一次,在线人数加一
  count++
  //这里是发送消息
  // on用来监听客户端message事件,回调函数处理。
  socket.on('message', function (msg) {
 
    // 如果在这里通过url解析的username来改变下面33行即将渲染的name,会出现异步问题。name还没有赋值就被传到客户端
    // 所以通过ajax请求,先让后端拿到username,然后再做提示信息的渲染
   // console.log(msg.net_name+'('+msg.role+')'+':'+ msg.inpval);
    // 将客户端发送来的消息中转给所有客户端
    io.emit('message', msg)
  });
  // loginin是自定义事件,第二个参数返回数据对象用于渲染,用于登陆后向客户端发送用户登录信息
  io.emit('loginin',{count,des:`温馨提示:${net_name}(${role})进入聊天室 ${new Date().Format("yyyy-MM-dd-hh:mm")}`,userList:userList})
  //io.emit('loginin',{count,des:{a:'哈哈哈'}})
  //登陆后向客户端发送用户退出信息
  //当断开连接disconnect,前端会执行下面这个loginout函数
  socket.on('disconnect', function (value) {
    //console.log(value);
    // loginout是自定义事件,第二个参数返回数据对象用于渲染
    count--
    //在线用户数组减去一个
    for(let i=0;i<=userList.length-1;i++){
      if(userList[i].uid == uid){
        userList.splice(i,1)
      }
    }


   io.emit('loginout',{count,des:`温馨提示:${net_name}(${role})退出聊天室  ${new Date().Format("yyyy-MM-dd-hh:mm")}`,userList:userList})

    // 连接每断开一次,在线人数减一
  })
});
http.listen(8849, function () {
  console.log('websocket连接成功!')
})

结语

我的哔哩哔哩空间
Gitee仓库地址:全部css、js特效源码
其它文章:
~关注我看更多简单创意特效:
文字烟雾效果 html+css+js
环绕倒影加载特效 html+css
气泡浮动背景特效 html+css
简约时钟特效 html+css+js
赛博朋克风格按钮 html+css
仿网易云官网轮播图 html+css+js
水波加载动画 html+css
导航栏滚动渐变效果 html+css+js
书本翻页 html+css
3D立体相册 html+css
霓虹灯绘画板效果 html+css+js
记一些css属性总结(一)
Sass总结笔记
…等等
进我主页看更多~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/90760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML网页设计制作大作业 基于HTML+CSS+JavaScript实现炫丽口红网化妆品网站(10页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

《天天学敏捷:Scrum团队转型记》读书笔记

读书给人以快乐、给人以光彩、给人以才干。 —— 培根 基本信息 作者&#xff1a;杨蕾&#xff0c;郑江著推荐值&#xff1a;76.7%微信读书&#xff1a;天天学敏捷&#xff1a;Scrum团队转型记 收获 & 思考 阅读目标&#xff1a;提前明确目标&#xff0c;有助于提升阅读效…

营销新赛道:虚拟数字人

2021年10月Facebook改名Meta&#xff0c;引爆全球范围的元宇宙热&#xff0c;和Web 3.0相比较&#xff0c;元宇宙是一个完整的生态&#xff0c;而Web 3.0特指一种交互方式和实现方法&#xff0c;两者之间的关系类似于移动互联网与HTML 5。在元宇宙生态下&#xff0c;营销的3要素…

[附源码]Python计算机毕业设计-高校人事管理系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Vue--》路由vue-router的使用讲解

目录 路由简述 vue-router vue-router的安装配置与使用 路由重定向 嵌套路由 嵌套路由重定向 命名路由 动态路由 路由简述 路由&#xff08;英文&#xff1a;router&#xff09;就是对应关系。单页面应用程序&#xff08;SPA&#xff09;指的是一个web网站只有唯一一个…

故障分析 | MySQL死锁案例分析

作者&#xff1a;杨奇龙 网名“北在南方”&#xff0c;资深 DBA&#xff0c;主要负责数据库架构设计和运维平台开发工作&#xff0c;擅长数据库性能调优、故障诊断。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转…

[附源码]Python计算机毕业设计高校教材网上征订系统Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

密码改造技术路径大比拼--“免”改造太理想,“重”改造太复杂,“易”改造是王道

随着《密码法》的颁布施行&#xff0c;密码产业进入爆发式增长期。市场用户侧、供给侧、监管侧对于“密评密改”的标准路径和部署方式共识度低&#xff0c;有唱专业的&#xff0c;有唱商业的&#xff0c;有唱便捷的&#xff0c;有唱可持续发展的&#xff0c;有唱单品的&#xf…

ANSYS Mechanical 2020 R1 版本新特性-CABLE 280单元分析索结构

导读&#xff1a;3D 缆索单元&#xff0c;可用的产品&#xff1a;Pro | Premium | Enterprise | PrepPost | Solver | AS add-on 一、CABLE 280 单元概述 CABLE280适用于分析中等至极细的缆索结构(如海底电缆)。该单元是三维三节点二次线单元。每个节点有x , y , z三个平动自…

【Anime.js】——JavaScript动画库:Anime.js

官方文档 官网定义&#xff1a; anime.js 是一个简便的JS动画库&#xff0c;用法简单而且适用范围广&#xff0c;涵盖CSS&#xff0c;DOM&#xff0c;SVG还有JS的对象&#xff0c;各种带数值属性的东西都可以动起来。 一、搭建开发环境 1、新建一个文件夹 &#xff0c;用vs c…

CpG ODN丨艾美捷ODN 1982 (synthetic)参数说明

艾美捷CpG ODN系列——ODN 1982 (synthetic)&#xff1a;具有硫代磷酸酯骨架的GpC寡脱氧核苷酸。 艾美捷CpG ODN丨ODN 1982 (synthetic)化学性质&#xff1a; 序列&#xff1a;5-tccatgagcttcctgagct-3&#xff08;小写字母表示硫代磷酸酯键&#xff09;。 MW&#xff1a;638…

Java-1214

Spring5总体学习内容 Spring基本概念IOC容器AopJdbcTemplate事务管理Spring5新特性 框架概述 Spring是轻量级的开源的JavaEE框架Spring可以解决企业应用开发的复杂性Spring有两个核心部分&#xff1a;IOC、Aop IOC&#xff1a;控制反转&#xff0c;把创建对象的过程交给Spri…

【ant-design】生态介绍和表单设计器 汇总

▒ 目录 ▒&#x1f6eb; 导读需求开发环境1️⃣ ant-design生态ant-designant-design-vueant-design-pro2️⃣ 表单设计器form-render - 阿里团队开源表单设计器&#xff0c;自家 Antd UI 框架友好form-create - 支持Vue3 及 ElementPlusUI、AntDesign、iview 框架Form Genera…

如何建立好客户信任关系?

2022年9月8日&#xff0c; 一个秋高气爽阳光明媚的日子。 正当我优雅的端起coffee&#xff0c; 专注投入早A晚C的重要一环时&#xff0c; 光头老邱按下一沓资料&#xff0c; 一并丢下经典语录&#xff1a; 这个客户对我们很重要&#xff01; emmm...... 重要的客户托付给…

Centos实现软路由

因公司需求,需要一台Centos主机,既需要做服务器,又要做路由器,要求能够对外提供有线和WIFI,还要求在学校复杂的局域网环境中,能够通过IP直接访问。带着需求去华强北找符合这样设备,华强北给的方案是爱快软路由+centos虚拟机,满足了服务器和路由器功能,但是没法使用学校…

理解频域、时域、FFT和加窗 加深对信号的认识

学习信号时域和频域、快速傅立叶变换(FFT)、加窗&#xff0c;以及如何通过这些操作来加深对信号的认识。 理解时域、频域、FFT傅立叶变换有助于理解常见的信号&#xff0c;以及如何辨别信号中的错误。尽管傅立叶变换是一个复杂的数学函数&#xff0c;但是通过一个测量信号来理…

[附源码]Nodejs计算机毕业设计基于的二手车商城Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

java计算机毕业设计springboot+vue小区防疫健康信息管理及出入登记平台

项目介绍 通篇文章的撰写基础是实际的应用需要,然后在架构系统之前全面复习大学所修习的相关知识以及网络提供的技术应用教程,以小区防疫健康信息管理及出入登记平台的实际应用需要出发,架构系统来改善现小区防疫健康信息管理及出入登记平台工作流程繁琐等问题。不仅如此以操作…

浅析即时通讯音视频开发多人实时音视频聊天架构

移动互联网发展迅猛&#xff0c;目前实时音视频技术已被广泛地应用在了实时在线教育、智能家居、在线直播、安防监控等领域。这之中&#xff0c;诸如多人视频会议、在线实时视频教育等场景&#xff0c;跟传统的一对一实时音视频聊天&#xff0c;在技术架构的实现上有很大不同。…

Java+mysql基于JSP的家教兼职网站

随着家教兼职网站需求和在线家教兼职网站渗透率的提升,中国家教兼职网站在线市场将释放巨大潜力,家教兼职网站系统的建设和发展成为业界广泛关注的重点,本文将对此进行分析,以期为我国家教兼职网站电子商务的发展提供参考。目前对于国内外知名兼职平台,各媒体都已经宣传的比较到…