项目9-网页聊天室1(注册+Bycrpt加密)

1.准备工作

1.1.前端页面展示 

1.2 数据库的建立 

我们通过注册页面,考虑如何设计用户表数据库。

  1. 用户id,userId
  2. 用户名,唯一,username
  3. 用户密码,password(包括密码和确认密码ensurePssword【数据库没有该字段】)
  4. 同时还需要考虑是否需要将图片和用户进行分离

                //我考虑的是将其合并在一起

                //这样做的好处是直接和userId相对应

                //省去了其余的操作

      5.需要存储图片名字(picname)

      6.需要存储图片地址(path)

-- 数据库
drop database if exists `chatroom`;
create database if not exists `chatroom` character set utf8;
-- 使用数据库
use `chatroom`;

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`userId` INT PRIMARY KEY AUTO_INCREMENT,
`username` varchar(200) NOT NULL,
`password` varchar(200) NOT NULL,
`picname` varchar(200) NOT NULL,
`path` varchar(255) NOT NULL
);

2.前端代码 

2.1 model

@Data
public class User {
    private Integer userId;
    private String username;
    private String password;
    private String picname;
    private String path;
}

2.2 service

package com.example.demo.service;

import com.example.demo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;


@org.springframework.stereotype.Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public Boolean insertUserInfo(String username,String password,String picname,String path){
        Integer influncefactor=userMapper.insertUserInfo(username,password,picname,path);
        if(influncefactor>0){
            return true;
        }
        return false;
    }

}

2.3 controller

package com.example.demo.controller;

import com.example.demo.config.AppConfig;
import com.example.demo.config.Result;
import com.example.demo.constant.Constant;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @RequestMapping("/register")
    public Result registerUser(@RequestParam MultipartFile file,String username,String password,String ensurePassword){
        //当旧密码与新密码所输入的一样,且都不为空才会进行后续操作
        if(!StringUtils.hasLength(username)||!StringUtils.hasLength(password)||!StringUtils.hasLength(ensurePassword)){
            return Result.fail(Constant.RESULT_CODE_MESSAGENULL,"你所输入的信息为空,违规");
        }
        //两个密码必须一致才可以进行后续操作
        if(!password.equals(ensurePassword)){
            return Result.fail(Constant.RESULT_CODE_NOTSAMEPASSWORD,"两次密码输入不一致,违规");
        }
        String fileName=file.getOriginalFilename();
        String path = Constant.SAVE_PATH +fileName;
        File dest=new File(path);
        //图片可以是同一张图片
        //直接上传图片
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail(Constant.RESULT_CODE_UPLOADPICFAIL,"图片上传失败");
        }
        //同时要将密码进行加密BCrypt
        String newpassword=bCryptPasswordEncoder.encode(password);
        //将所输入的数据存入数据库中
        if(userService.insertUserInfo(username,newpassword,fileName,path)){
            return Result.success(true);
        }
        return Result.fail(Constant.RESULT_CODE_FAIL,"上传数据库失败");
    }
}

3.前端接口测试

每个if语句都需要判断一次

3.1 成功情况

3.2 用户名相同情况

 3.3 有一个输入为空的情况

3.4 两次输入的密码不同 

4.考虑的问题,图像为空

我们允许图像为空,故需要考虑将本地的文件转为MultipartFile。

数据库存入默认头像

根据文件路径获取 MultipartFile 文件_multipartfile他通过路径获取-CSDN博客

4.1 Controller更改

 

package com.example.demo.controller;

import com.example.demo.config.Method;
import com.example.demo.config.Result;
import com.example.demo.constant.Constant;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
    @RequestMapping("/register")
    public Result registerUser(@RequestParam(required = false) MultipartFile file, String username, String password, String ensurePassword) {
        //当旧密码与新密码所输入的一样,且都不为空才会进行后续操作
        if (!StringUtils.hasLength(username) || !StringUtils.hasLength(password) || !StringUtils.hasLength(ensurePassword)) {
            return Result.fail(Constant.RESULT_CODE_MESSAGENULL, "你所输入的信息为空,违规");
        }
        //两个密码必须一致才可以进行后续操作
        if (!password.equals(ensurePassword)) {
            return Result.fail(Constant.RESULT_CODE_NOTSAMEPASSWORD, "两次密码输入不一致,违规");
        }
        //需要查询是否存在相同的username,若否则不能注册,让用户重命名
        if (!userService.selectByUsername(username)) {
            return Result.fail(Constant.RESULT_CODE_SAMEUSERNAME, "用户名不能相同,违规");
        }
        String fileName;
        MultipartFile mfile;
        String path;
        //如果图片为空,则保存默认的图片
        if (file == null) {
            fileName = Constant.PIC;
            path = Constant.SAVE_PATH +fileName;
            mfile = Method.getMulFileByPath(path);
        } else {
            fileName = file.getOriginalFilename();
            path = Constant.SAVE_PATH +fileName;
            mfile=file;
        }
        File dest=new File(path);
        try {
            mfile.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail(Constant.RESULT_CODE_UPLOADPICFAIL,"图片上传失败");
        }

        //同时要将密码进行加密BCrypt
        String newpassword=bCryptPasswordEncoder.encode(password);

        //将所输入的数据存入数据库中
        if(userService.insertUserInfo(username,newpassword,fileName,path)){
            return Result.success(true);
        }
        return Result.fail(Constant.RESULT_CODE_FAIL,"上传数据库失败");
    }
}

4.2 Method类

 

package com.example.demo.config;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Method {
    public static MultipartFile getMulFileByPath(String picPath) {
        FileItem fileItem = createFileItem(picPath);
        MultipartFile mfile = new CommonsMultipartFile(fileItem);
        return mfile;
    }

    public static FileItem createFileItem(String filePath) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "textField";
        int num = filePath.lastIndexOf(".");
        String extFile = filePath.substring(num);
        FileItem item = factory.createItem(textFieldName, "text/plain", true,
                "MyFileName" + extFile);
        File newfile = new File(filePath);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try
        {
            FileInputStream fis = new FileInputStream(newfile);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192))
                    != -1)
            {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return item;
    }

}

4.3 前端测试 

5.前后端交互

5.1 register.html

</head>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>用户注册界面</title>
  <link rel="stylesheet" href="css/common.css">
  <link rel="stylesheet" href="css/register.css">
  <link rel="stylesheet" href="css/upload.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav">
        网页聊天
    </div>
    <div class="container">
        <h1>新用户注册</h1>
        <br>
        <form enctype="multipart/form-data" id="file_upload" class="headForm" onsubmit="return false" action="##"> 
            <div id="test-image-preview" class="iconfont icon-bianjitouxiang">
                <input type="file" name="test" id="test-image-file" class="fileHead" accept="image/gif, image/jpeg, image/png, image/jpg" multiple="multiple">
            </div>
            <div class="headMain">
                <span class="file">上传头像</span>
                <p id="test-file-info" class="fileName"></p>
            </div>
            <br>       
            <div>
            <span class="p">*</span>
            <label for="username">用户名</label>
            <input type="text" name="" id="username" placeholder="" class="register"><br><br>
            
            <span class="q">*</span>
            <label for="pwd">登录密码</label>
            <input type="password" name="" id="pwd" class="register"><br><br>
            <span class="q">*</span>
            <label for="c_pwd">确认密码</label>
            <input type="password" name="" id="c_pwd" class="register"><br><br>
            <input type="checkbox" class="checkbox" name="">
            <span style="font-size:15px">我已阅读并同意《用户注册协议》</span>
            <br><br>
            <input type="submit" name="" value="同意以上协议并注册" class="submit" onclick="register(this)"><br>
            <a href="login.html" class="left">返回首页</a>
            <a href="login.html" class="right">开始登录</a>
            </form>
            </div>
    </div>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script type="text/javascript" src="js/register.js"></script>
<script type="text/javascript" src="js/upload.js"></script>
<script>
    
</script>
</body>
</html>

5.2 register.js

var checkbox=document.getElementsByClassName('checkbox');
function register(btn){
    if(checkbox[0].checked==true){
        submitmessage();
    }else{
        alert("请先阅读并同意《用户注册协议》!")
    }
}


function submitmessage(){
    var formData = new FormData();
    formData.append('file', $('.fileHead')[0].files[0]);
    formData.append('username', $("#username").val());
    formData.append('password', $("#pwd").val());
    formData.append('ensurePassword', $("#c_pwd").val());
    var name11 = formData.get("#username");
    $.ajax({
        type: 'post',
        url: '/user/register',
        processData: false,
        async: false,
        contentType: false,
        cache: false,// 使用同步操作
        timeout: 50000, //超时时间:50秒
        data: formData,
        success: function (result) {    // 返回成功
            // console.log(result);
            console.log(name11);
            if(result!=null&&result.status==200){
                alert("注册账号成功,跳转到登陆页面,开始进行聊天吧!")
                location.href="login.html"
                return;
            }else if(result!=null&&result.status==-10){
                alert("用户名不能相同,违规");
            }else if(result!=null&&result.status==-8){
                alert("两次密码输入不一致,违规");
            }else if(result!=null&&result.status==-6){
                alert("你所输入的信息为空,违规");
            }else{
                alert("注册错误,请联系工作人员")
            }
            
        },
        error: function () {
            alert("接口错误");       // 返回失败
        }
    })
}

5.3 upload.js

var fileInput = document.getElementById('test-image-file'),//文件框,里面存的是文件,fileHead
    info = document.getElementById('test-file-info'),//文件名
    preview = document.getElementById('test-image-preview');//文件框,头像显示界面
    dataBase64 = '',
    preview.style.backgroundImage = 'url(../img/个人头像.png)';    //默认显示的图片

    // 监听change事件:
    fileInput.addEventListener('change', upImg);

// 头像上传逻辑函数
function upImg() {
    preview.style.backgroundImage = '';       // 清除背景图片
    if (!fileInput.value) {     // 检查文件是否选择:(此时文件中什么都没选择)
        $('#test-image-preview').addClass('icon-bianjitouxiang');
        info.innerHTML = '没有选择文件';
    } else {
        $('#test-image-preview').removeClass('icon-bianjitouxiang');
        info.innerHTML = '';//此时上传文件成功
    }

    var file = fileInput.files[0];    // 获取File引用
    var size = file.size;
    if (size >= 100 * 1024 * 1024) {     //判断文件大小
        info.innerHTML = '文件大于100兆不行!';
        preview.style.backgroundImage = '';
        $('#test-image-preview').addClass('icon-bianjitouxiang');
        return false;
    }

    if (file.type !== 'image/jpeg' && file.type !== 'image/png' && file.type !== 'image/gif') {    // 获取File信息:
        info.innerHTML = '不是有效的图片文件!';
        preview.style.backgroundImage = '';
        $('#test-image-preview').addClass('icon-bianjitouxiang');
        return;
    }

    // 读取文件:
    var reader = new FileReader();
    reader.onload = function (e) {
        dataBase64 = e.target.result;     // 'data:image/jpeg;base64,/9j/4AAQSk...(base64编码)...}'        
        preview.style.backgroundImage = 'url(' + dataBase64 + ') ';
        preview.style.backgroundRepeat = 'no-repeat';
        preview.style.backgroundSize = ' 100% 100%';
    };
    // 以DataURL的形式读取文件:
    reader.readAsDataURL(file);
    // console.log(file);
}

5.4 upload.css

.reHead{
    margin: 15px 4%; 
}
.headForm{
    text-align: center;
    padding: 40px 0 70px 0;
}
#test-image-preview {
    position: relative;
    display: inline-block;
    width: 100px;
    height: 100px;
    border-radius: 50px;
    background: #F5F5F5;
    color: #fff;
    font-size: 60px;
    text-align: center;
    line-height: 100px;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center center;
    margin-bottom: 26px;
}
.fileHead{
    position: absolute;
    width: 100px;
    height: 100px;
    right: 0;
    top: 0;
    opacity: 0;
}
.content-format {
    font-size: 12px;
    font-weight: 400;
    color: rgba(153, 153, 153, 1);
}
.headMain{
    height: 40px;
}
.file {
    position: relative;
    background: #fff;
    color: #F39800;
    font-weight:800;
}
.file input {
    position: absolute;
    font-size: 12px;
    right: 0;
    top: 0;
    opacity: 0;
}
.fileName {
    line-height: 28px;
    font-size: 12px;
    font-weight: 400;
    color: rgba(51, 51, 51, 1);
}
.but{
    text-align: center;
}
.orangeHead{
    width: 40%;
    height: 40px;
    background: #f60;
    border: none;
}
.orangeHead a{
    color: #fff;
}

5.5 register.css

body{
  background: url("../img/coolgirl.jpg");
  background-size:100% 100%;
  background-attachment: fixed;
}
  .container{
    position: absolute;
             top: 50%;
             left: 50%;
             transform: translate(-50%,-50%);
  }
  img{
		width: 4rem;
		height: 4rem;
		margin-left: 50%;
		transform: translateX(-50%);
		margin-top: 0.853rem;
		border-radius: 50%;
	}
	#js_logo_img{
		width: 4rem;
		height: 4rem;
		position: absolute;
		left: 50%;
		transform: translateX(-50%);
		top: 30%;
		opacity: 0;
	}
  h2{
		color: #000066;
		font-size: 0.853rem;
		text-align: center;
		margin: 0;
	}
  form{
    width: 450px;
    margin: 0 auto;
    background: #FFF;
    border-radius: 15px;
    position: relative;
  }
  h1{
    font-size: 28px;
    text-align: center;
    color: #FFF;
  }
  .p{
    color: red;
    margin-left: 33px;
    display: inline-block;
    /* 不占单独一行的块级元素 */
  }
  label{
    font-size: 18px;
    font-weight: bold;
  }
  .register{
    height: 35px;
    width: 300px;
  }
  .q{
    color:red;
    margin-left:17px;
    display:inline-block;
  }
  .checkbox{
    margin-left: 100px;
    display: inline-block;
    width: 15px;
    height: 15px;
  }
  .submit{
    border-radius: 7px;
    margin-left: 150px;
    height: 35px;
    width: 150px;
    background-color: #000;
    border: none;
    display: block;
    padding: 0;
    color: #FFF;
    font-weight: bold;
    cursor: pointer;
  }
  a{
    text-decoration: none;
    font-weight: bold;
  }
  .left,.right{
    position: absolute;
    bottom: 20px;
  }
  .left{
    left: 20px;
  }
  .right{
    right: 20px;
  }

5.6 common.css

/* 放置页面的公共样式 */

/* 去除浏览器默认样式 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 设定页面高度 */
html, body {
    height: 100%;
}

/* 设定导航栏的样式 */
.nav {
    height: 50px;
    background-color: black;
    color: rgb(255, 255, 255);

    /* 使用弹性布局, 让导航栏内部的元素, 垂直方向居中 */
    display: flex;
    align-items: center;
    /* 让里面的元素距离左侧边框, 有点间隙 */
    padding-left: 20px;
}

5.7 测试

注册成功!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PXI/PXIe规格 A429/717 航电总线适配卡

A429是一款标准的PXI/PXIe1规格的多协议总线适配卡。该产品最多支持36个A429通道&#xff0c;或32个A429通道加4个A717通道&#xff0c;每个A429和A717通道可由软件配置成接收或发送&#xff0c;可满足A429总线和A717总线的通讯、测试和数据分析等应用需求。 该产品的每个A429通…

儿童身高成长:关注每一厘米的成长

引言&#xff1a; 儿童的身高发育是家长和教育者普遍关注的问题&#xff0c;它不仅关乎孩子的外貌形象&#xff0c;更与孩子的健康成长密切相关。本文将深入探讨儿童身高的注意事项&#xff0c;为家长和教育者提供科学的指导&#xff0c;帮助孩子健康成长。 1. 身高发育的基本知…

BM11 链表相加(二)

描述 假设链表中每一个节点的值都在 0 - 9 之间&#xff0c;那么链表整体就可以代表一个整数。 给定两个这种链表&#xff0c;请生成代表两个整数相加值的结果链表。 数据范围&#xff1a;0≤&#x1d45b;,&#x1d45a;≤10000000≤n,m≤1000000&#xff0c;链表任意值 0≤…

前端面试:项目细节|项目重难点|已工作|做分享

面试官提问&#xff1a;分享一个项目中记忆比较深刻的需求&#xff1f;说说你是怎么解决的&#xff1f;解决过程有没有遇到什么困难&#xff1f; 答&#xff1a;我的回答&#xff08;我分点写思路&#xff0c;便于大家观看&#xff09;&#xff1a; &#xff08;1&#xff09…

C语言例题41、八进制转换为十进制

#include<stdio.h>void main() {int x;printf("请输入一个8进制整数&#xff1a;");scanf("%o", &x);printf("转换成十进制后的整数为%d\n", x); }运行结果&#xff1a; 本章C语言经典例题合集&#xff1a;http://t.csdnimg.cn/FK0Qg…

Web3时代的技术革新:区块链与人工智能的融合

随着科技的飞速发展&#xff0c;区块链和人工智能作为两大颠覆性技术正呈现出日益紧密的融合趋势。在Web3时代&#xff0c;这种融合将推动技术革新&#xff0c;引领着我们进入全新的数字时代。本文将深入探讨区块链与人工智能的融合&#xff0c;探索其在各个领域的应用前景和挑…

美国多IP服务器为企业的数据分析提供了强大的技术支持

美国多IP服务器为企业的数据分析提供了强大的技术支持 在当今数字化时代&#xff0c;数据分析已经成为企业决策和战略规划的核心。而美国多IP服务器则为企业提供了强大的技术支持&#xff0c;帮助它们有效地进行数据分析&#xff0c;从而更好地理解市场、优化运营&#xff0c;…

常见物联网面试题详解

物联网一直是非常火热的行业&#xff0c;G端如智慧城市、智慧工厂、智慧园区、智慧水利、智慧矿山等行业&#xff0c;都会涉及到物联网&#xff0c;基本都是软硬一体&#xff0c;因此当面试相关企业时&#xff0c;物联网平台是面试企业重点考察的项&#xff0c;小伙伴如果从事相…

十一、 进行个人信息保护认证的流程是怎样的?

2022 年 11 月 18 日&#xff0c;国家市场监督管理总局和国家网信办发布的《认证公告》以及附件《认证规则》&#xff0c;对开展个人信息保护认证的流程进行了细节说明&#xff0c;包括认证委托、技术验证、现场审核、认证结果评价和批准等环节。《认证公告》指出“从事个人信息…

软件测试之【软件测试初级工程师技能点全解】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f525; 欢迎来到我的博客 &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️寻至善的主页 文章目录 &#x1f525;前言&#x1f680;初级测试工程师技能点&#x1f449;测试理论基…

【数据结构】线性表----链表详解

数据结构—-链表详解 目录 文章目录 链表的定义链表的构成链表的分类双向和单向带头和不带头循环和不循环 链表的命名基本操作的实现初始化打印取值查找插入指定位置插入删除删除销毁 部分其他链表的代码实现循环链表双向链表 优点/缺点&#xff08;对比顺序表&#xff09;优点…

SQL Server (MSSQLSERVER) 服务无法启动

解决方法&#xff1a; 打开服务&#xff0c;右键SQL Server (MSSQLSERVER) ->属性->登录&#xff0c;改为本地系统用户

OpenGL入门第四步:摄像机视角变换与交互

OpenGL入门第一步:创建窗口、重写虚函数-CSDN博客 OpenGL入门第二步:颜色、纹理设置(解析)-CSDN博客 OpenGL入门第三步:矩阵变换、坐标系统-CSDN博客 目录 函数解析 具体代码 函数解析 相机视角变换需要与鼠标键盘进行交互,需要重写鼠标和键盘响应函数。 初始化 …

如何安装在系统中安装make命令

文章目录 WindowsMacUbuntuCentOS/Red Hat make是系统比较基础的命令&#xff0c;一般会自己携带&#xff0c;如果没有就手动安装一下吧。 Windows 从官网下载 make.exe Make for Windows 官网首页&#xff1a;https://www.gnu.org/software/make/ 下载地址&#xff1a;htt…

mac安装禅道(局域网访问、远程访问)

前提已安装&#xff1a;phpapacheMySQL macOS12 安装 php8.1/apache-CSDN博客 安装MySQL 一、禅道下载 安装官方文档 源码包下载地址&#xff1a;禅道 18.10 从下图可看出&#xff1a;windows和linux一键安装&#xff0c;方便很多 1. 解压禅道源码包 2. 将解压后的文件复制到…

C++基础——继承(上)

一、继承的概念 继承 (inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许实现者保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称之为派生类&#xff1b; 继承呈现了面向对象程序设计的层次结构…

升级Microsoft 365后,SAP GUI中无法打开Excel的解决方案

最近&#xff0c;我们遇到了一个棘手的问题&#xff0c;一位客户在升级到Microsoft 365后&#xff0c;无法在SAP GUI中打开Excel。这个问题不仅影响了工作效率&#xff0c;也给用户的日常操作带来了不便。在本文中&#xff0c;我们将探讨问题的成因&#xff0c;并提供一种解决方…

2024年【河北省安全员B证】考试及河北省安全员B证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 河北省安全员B证考试参考答案及河北省安全员B证考试试题解析是安全生产模拟考试一点通题库老师及河北省安全员B证操作证已考过的学员汇总&#xff0c;相对有效帮助河北省安全员B证复审模拟考试学员顺利通过考试。 1、…

[vue] nvm

nvm ls // 看安装的所有node.js的版本nvm list available // 查显示可以安装的所有node.js的版本可以在可选列表里。选择任意版本安装&#xff0c;比如安装16.15.0 执行&#xff1a; nvm install 16.15.0安装好了之后。可以执行&#xff1a; …

【2024】最新快手小游戏项目,边玩游戏边赚钱,周赚4000+!快手怎么赚钱,快手干货分享!

大家好&#xff0c;我是一个99年互联网创业者。 相信老朋友对我也不陌生啦&#xff01; 但还是有一些新朋友&#xff0c;在这里我再做个简单的自我介绍吧。 我是做网赚出身的&#xff0c;大大小小的项目都接触过&#xff0c;后面转型做互联网开发程序这块&#xff0c;到现在…