附录4-大事件项目后端-四个模块

news2024/12/23 9:39:44

目录

1  注册与登陆

1.1  代码

1.2  Bearer token

2  个人中心 

3  文章分类

3.1  代码

3.2  添加/更新文章分类确保名称唯一性

3.2.1  两条数据占用

3.2.2  被一条数据同时占用

3.2.3  只有名称被占用

3.2.4  只有别名被占用

4  文章列表

4.1  代码

4.2  筛选文章


1  注册与登陆

1.1  代码

const config = require('../config.js')
const login_register_router = express.Router()

// 登录与注册都在用下面这个验证机制
const check_username_password = {
    body:{
        username:userinfo_username_rule,
        password:userinfo_password_rule
    }
}

// 注册
login_register_router.post('/api/reguser',expressJoi(check_username_password),(req,res) => {
    // 检查用户名是否被占用
    db.query('select * from userinfo where username=?',req.body.username,function(err,results) {
        if (err) {
            return res.send({status:1,message:'注册失败,原因是'+err.message})
        }
        if (results.length > 0) {
            return res.send({status:1,message:'用户名被占用,请更换其他用户名'})
        }
        // 对密码进行加密
        req.body.password = bcryptjs.hashSync(req.body.password,10)

        // 插入新用户
        // 这里只希望插入用户名和密码,所以手动搞了一个对象
        db.query('insert into userinfo set ?',{username:req.body.username,password:req.body.password},(err,result) => {
            if (err) {
                return res.send({
                    "status":1,
                    "message":'注册失败,原因是'+err.message
                })
            }

            if (result.affectedRows === 1) {
                return res.send({
                    "status":0,
                    "message":"注册成功"
                })
            }
            else {
                return res.send({
                    "status":1,
                    "message":'注册失败'
                })
            }
        })
    })
})

// 登录
login_register_router.post('/api/login',expressJoi(check_username_password),(req,res) => {
    db.query('select * from userinfo where username=?',req.body.username,(err,result) => {
        if (err) {
            return res.send({
                status:1,
                message:'登录失败,原因是' + err.message
            })
        }
        else {
            if (result.length !== 1) {
                return res.send({
                    status:1,
                    message:'用户名或密码错误'
                })
            }
            const true_password = result[0].password
            // 由于注册的时候加密过,在登录的时候需要用bcryptjs.compareSync()校验一下,true表示一致,false表示不一致
            // 第一个参数是提交的密码,第二个是存储的密码,需要给存储的密码解密,所以顺序不能变
            if (bcryptjs.compareSync(req.body.password,true_password)) {
                return res.send({
                    "status":0,
                    "message":"登录成功",
                    "token":'Bearer ' + jsonwebtoken.sign({...result[0],password:'',user_pic:''},secretKey,{expiresIn:'24h'})
                })
            }
            else {
                return res.send({
                    status:1,
                    message:'用户名或密码错误'
                })
            }
        }
    })
}
)

module.exports = login_register_router

1.2  Bearer token

Bearer token是token的一种,在项目中登陆成功的时候会使用到

在你用Postman测试的时候,选择Authorization,然后选择Bearer Token,然后将不太Bearer前缀的内容粘贴到里面就可以发送了

他实际的请求头实际上是要带Bearer的

2  个人中心 

const config = require('../config.js')

const personal_center_router = express.Router()

// 查看个人除密码外的所有信息
personal_center_router.get('/my/userinfo',(req,res) => {
    db.query('select id,username,nickname,email,user_pic from userinfo where id=?',req.auth.id,(err,result) => {
        if (err) return res.send({status:1,message:'查询失败,原因是' + err.message})

        if (result.length !== 1) {
            return res.send({status:1,message:'查询失败'})
        }
        else {
            res.send({
                "status":0,
                "message":"获取用户基本信息成功",
                "data": result[0]
            })
        }
    })
})

// 更新用户昵称,邮箱
const check_id_nickname_email = {
    body:{
        id:id_rule,
        nickname:userinfo_nickname_rule,
        email:userinfo_email_rule
    }
}
personal_center_router.post('/my/userinfo',expressJoi(check_id_nickname_email),(req,res) => {
    db.query('update userinfo set ? where id=?',[req.body,req.body.id],(err,result) => {
        if (err) return res.send({"status":1,"message":"修改用户信息失败,原因是" + err.message,})

        if (result.affectedRows === 1) {
            res.send({
                "status":0,
                "message":"修改用户信息成功",
            })
        }
        else {
            res.send({
                "status":1,
                "message":"修改用户信息失败",
            })
        }
    })
})

// 更新用户个人密码
const check_new_old_password = {
    body:{
        oldPwd:userinfo_password_rule,
        // joi.ref('oldPwd')表示必须与oldPwd的值一致
        // joi.not(joi.ref('oldPwd'))表示必须与oldPwd的值不一致
        // joi.not(joi.ref('oldPwd')).concat(password_rule)表示必须与oldPwd的值不一致 且 验证规则使用password_rule,concat表示规则合并
        newPwd:joi.not(joi.ref('oldPwd')).concat(userinfo_password_rule)
    }
}
// 在下面的视图中实际上给了很多提示,在实际开发中可以不给这么多提示,因为这样可能会被别人试出来,就和你登录的时候一样,一般来讲只会告诉你用户名或密码不对,而不是告诉你哪个不对,这个最后也看实际需要
personal_center_router.post('/my/updatepwd',expressJoi(check_new_old_password),(req,res) => {
    // 检验用户是否存在
    db.query('select * from userinfo where id=?',req.auth.id,(err,result) => {
        if (err) {
            return res.send({
                "status":1,
                "message":"更新密码失败,原因是" + err.message
            })
        }
        else {
            if (result.length !== 1) {
                res.send({
                    "status":1,
                    // 这里一般就是用错了token
                    "message":"用户不存在!",
                })
            }
            // 检验旧密码是否与数据库中存的密码一致
            const true_password = result[0].password
            if (bcryptjs.compareSync(req.body.oldPwd,true_password)) {
                // 如果一致就更新一下,密码记得加密之后更新进去
                db.query('update userinfo set password=? where id=?',[bcryptjs.hashSync(req.body.newPwd,10),req.auth.id],(err,result) => {
                    if (err) return res.send({
                        "status":1,
                        "message":"更新密码失败,原因是" + err.message
                    })
            
                    if (result.affectedRows === 1) {
                        res.send({
                            "status":0,
                            "message":"更新密码成功!",
                        })
                    }
                    else {
                        res.send({
                            "status":1,
                            "message":"更新密码失败!",
                        })
                    }
                })
            }
            else {
                res.send({
                    "status":1,
                    "message":"给的密码与原来的密码不一致!",
                })
            }
        }
    })
})

// 更新用户个人头像
const check_avatar = {
    body:{
        avatar:userinfo_avatar_rule,
    }
}
personal_center_router.post('/my/update/avatar',expressJoi(check_avatar),(req,res) => {
    db.query('update userinfo set user_pic=? where id=?',[req.body.avatar,req.auth.id],(err,result) => {
        if (err) return res.send({
            "status":1,
            "message":"更新头像失败,原因是" + err.message,
        })

        if (result.affectedRows === 1) {
            res.send({
                "status":0,
                "message":"更新头像成功!",
            })
        }
        else {
            res.send({
                "status":1,
                "message":"更新头像失败!",
            })
        }
    })
})

module.exports = personal_center_router

在这个模块中加入了一个新的验证规则

更新密码的时候需要将新密码加密后在放入数据库

在更新用户数据中,讲道理id应该不能从req.body中拿,而是应该由token中拿,由于接口文档中写的要传入,这里是按照接口文档走的

3  文章分类

3.1  代码

const article_category_management_router = express.Router()

// 查看所有文章分类
article_category_management_router.get('/my/article/cates',(req,res) => {
    db.query('select * from article_category where is_delete=0 order by id asc',(err,result) => {
        if (err) {
            return res.send({"status":1,"message":'获取文章分类列表成功,原因是' + err.message,})
        }

        else {
            res.send({
                "status":0,
                "message":"获取文章分类列表成功!",
                "data": result
            })
        }
    })
})

// 添加文章分类
const check_category_name_alias = {
    body:{
        name:category_name_rule,
        alias:category_alias_rule
    }
}
article_category_management_router.post('/my/article/addcates',expressJoi(check_category_name_alias),(req,res) => {
    // 查看名称(name)或别名(alias)是否被占用
    db.query('select * from article_category where name=? or alias=?',[req.body.name,req.body.alias],(err,result) => {
        if (err) {
            return res.send({
                status:1,
                message:'添加失败,原因是' + err.message
            })
        }
        // 由于表中有唯一限制(UQ),所以如果查出了两个结果就表明 名称 与 别名 都不能用
        if (result.length === 2) {
            return res.send({
                status:1,
                message:'该名称与别名都被占用了,请更换后重试'
            })
        }
        // 由于表中有唯一限制,如果只查出来一条数据,那么不是名称被占用了就是别名被占用了(也有可能是名称和别名被同一条数据占用),我们这个做出判断然后给用户提示
        if (result.length === 1 && result[0].name === req.body.name) {
            return res.send({
                status:1,
                message:'该名称被占用了,请更换后重试'
            })
        }
        if (result.length === 1 && result[0].alias === req.body.alias) {
            return res.send({
                status:1,
                message:'该别名被占用了,请更换后重试'
            })
        }
        if (result.length === 1 && result[0].name === req.body.name && result[0].alias === req.body.alias) {
            return res.send({
                status:1,
                message:'该名称与别名都被占用了,请更换后重试'
            })
        }
        // 发现没有重复占用问题后进行添加
        db.query('insert into article_category set ?',req.body,(err,result) => {
            if (err) {
                return res.send({
                    status:1,
                    message:'添加失败,原因是' + err.message
                })
            }
    
            if (result.affectedRows === 1) {
                return res.send({
                    "status":0,
                    "message":"新增文章分类成功!"
                })
            }
            else {
                return res.send({
                    status:1,
                    message:'添加失败,原因是' + err.message
                })
            }
        })
    })
})

// 删除文章分类与获取文章分类数据都要验证id,且方式都是params
const check_category_id = {
    params:{
        id:id_rule
    }
}
// 删除文章分类
article_category_management_router.get('/my/article/deletecate/:id',expressJoi(check_category_id),(req,res) => {
    db.query('update article_category set is_delete=1 where id=?',req.params.id,(err,result) => {
        if (err) return res.send({"status":1,"message":"删除文章分类失败,原因是" + err.message})
        if (result.affectedRows === 1) {
            return res.send({
                "status":0,
                "message":"删除文章分类成功!",
            })
        }
        else {
            return res.send({
                "status":1,
                "message":"删除文章分类失败!",
            })
        }
    })
})
// 获取指定id的文章分类数据
article_category_management_router.get('/my/article/cates/:id',expressJoi(check_category_id),(req,res) => {
    db.query('select * from article_category where id=?',req.params.id,(err,result) => {
        if (err) return res.send({status:1,message:'获取文章分类数据失败,原因是' + err.message})

        if (result.length !== 1) {
            return res.send({status:1,message:'获取文章分类数据失败'})
        }
        else {
            return res.send({
                "status":0,
                "message":"获取文章分类列表成功!",
                "data": result[0]
            })
        }
    })
})

// 更新文章分类数据
const check_id_name_alias = {
    body:{
        id:id_rule,
        name:category_name_rule,
        alias:category_alias_rule
    }
}
article_category_management_router.post('/my/article/updatecate',expressJoi(check_id_name_alias),(req,res) => {
    // 与添加分类情况相同,先查一下名称与别名的占用问题
    // 与添加分类的区别的不能算自己要更新的那一条数据,因为我们有可能只改名称或只改别名,如果算上了自己要改的,那么变量和名称就必须同时修改
    db.query('select * from article_category where id!=? and (name=? or alias=?)',[req.body.id,req.body.name,req.body.alias],(err,result) => {
        if (err) {
            return res.send({
                status:1,
                message:'更新文章分类数据失败,原因是' + err.message
            })
        }
        if (result.length === 2) {
            return res.send({
                status:1,
                message:'该名称与别名都被占用了,请更换后重试'
            })
        }
        if (result.length === 1 && result[0].name === req.body.name) {
            return res.send({
                status:1,
                message:'该名称被占用了,请更换后重试'
            })
        }
        if (result.length === 1 && result[0].alias === req.body.alias) {
            return res.send({
                status:1,
                message:'该别名被占用了,请更换后重试'
            })
        }
        if (result.length === 1 && result[0].name === req.body.name && result[0].alias === req.body.alias) {
            return res.send({
                status:1,
                message:'该名称与别名都被占用了,请更换后重试'
            })
        }
        
        db.query('update article_category set ? where id=?',[req.body,req.body.id],(err,result) => {
            if (err) {
                return res.send({
                    "status":1,
                    "message":"更新文章分类数据失败,原因是" + err.message,
                })
            }
            
            if (result.affectedRows === 1) {
                return res.send({
                    "status":0,
                    "message":"更新文章分类数据成功!",
                })
            }
            else {
                return res.send({
                    "status":1,
                    "message":"更新文章分类数据失败!",
                })
            }
        })
    })
})

module.exports = article_category_management_router

3.2  添加/更新文章分类确保名称唯一性

添加文章分类的时候要保证 分类名称与分类别名 的唯一性,有下面四种情况

3.2.1  两条数据占用

3.2.2  被一条数据同时占用

3.2.3  只有名称被占用

3.2.4  只有别名被占用

4  文章列表

4.1  代码

const article_management_router = express.Router()

// 新增文章
const check_article_title_cateid_content_state = {
    body: {
        title: article_title_rule,
        cate_id: article_cate_id_rule.required(),
        content: article_content_rule,
        state: article_state_rule.required(),
    }
}
article_management_router.post('/my/article/add', uploads.single('cover_img'), expressJoi(check_article_title_cateid_content_state), (req, res) => {
    if (!req.file || req.file.fieldname !== 'cover_img') {
        return res.send({
            "status": 1,
            "message": "文章封面是必选参数!"
        })
    }
    const articleInfo = {
        ...req.body,
        cover_img: path.join('/uploads', req.file.filename),
        pub_date: new Date(),
        author_id: req.auth.id,
    }
    db.query('insert into article_list set ?', articleInfo, (err, result) => {
        if (err) {
            return res.send({
                "status": 1,
                "message": '新增文章失败,原因是' + err.message
            })
        }

        if (result.affectedRows === 1) {
            return res.send({
                "status": 0,
                "message": "新增文章成功!"
            })
        }
        else {
            return res.send({
                "status": 1,
                "message": '新增文章失败!'
            })
        }
    })
})

// 查看文章信息(可根据 文章分类id与文章状态 筛选)
const check_article_pagenum_pagesize_cate_id_state = {
    query: {
        pagenum: article_pagenum_rule,
        pagesize: article_pagesize_rule,
        cate_id: article_cate_id_rule,
        state: article_state_rule,
    }
}
article_management_router.get('/my/article/list', expressJoi(check_article_pagenum_pagesize_cate_id_state), (req, res) => {
    // 当前是哪页 一页有多少 是必选参数
    pagenum = req.query.pagenum
    pagesize = req.query.pagesize
    // 文章状态与分类id是可选参数,后面会通过有没有这两个参数,做使用哪个sql语句的判断
    state = req.query.state
    cate_id = req.query.cate_id

    sql = 'select * from article_list where is_delete=0 and author_id=' + req.auth.id
    if (state) {
        sql = sql + ' and state=' + "'" + state + "'"
    }
    if (cate_id) {
        sql = sql + ' and cate_id=' + cate_id
    }

    // 先获取符合条件的数据有多少个
    db.query(sql, (err, result) => {
        if (err) {
            return res.send({
                "status": 1,
                "message": "查询失败,原因是" + err.message,
            })
        }
        else {
            total = result.length

            // 如果没问题就进行第二次查询
            sql = sql + ' limit ' + (req.query.pagenum - 1) * req.query.pagesize + ',' + req.query.pagesize
            db.query(sql, (err, result) => {
                if (err) {
                    return res.send({
                        "status": 1,
                        "message": "查询失败,原因是" + err.message,
                    })
                }
                else {
                    res.send({
                        "status": 0,
                        "message": "获取文章列表成功!",
                        "data": result,
                        "total":total
                    })
                }
            })
        }
    })
})

// 删除文章
const check_article_id = {
    params: {
        id: id_rule
    }
}
article_management_router.get('/my/article/delete/:id', expressJoi(check_article_id), (req, res) => {
    db.query('update article_list set is_delete=1 where id=?', req.params.id, (err, result) => {
        if (err) {
            return res.send({
                "status": 1,
                "message": "删除失败,原因是" + err.message,
            })
        }

        if (result.affectedRows === 1) {
            res.send({
                "status": 0,
                "message": "删除成功!",
            })
        }
        else {
            res.send({
                "status": 1,
                "message": "删除失败!",
            })
        }
    })
})

// 获取指定id文章详情
article_management_router.get('/my/article/:id', expressJoi(check_article_id), (req, res) => {
    db.query('select * from article_list where id=?', req.params.id, (err, result) => {
        if (err) {
            return res.send({
                "status": 1,
                "message": "获取失败,原因是" + err.message,
            })
        }

        if (result.length === 1) {
            res.send({
                "status": 0,
                "message": "获取成功!",
                "data": result[0]
            })
        }
        else {
            res.send({
                "status": 1,
                "message": "获取失败!",
            })
        }
    })
})

// 更新文章信息
const check_article_id_title_cateid_content_state = {
    body: {
        id: id_rule,
        title: article_title_rule,
        cate_id: article_cate_id_rule.required(),
        content: article_content_rule,
        state: article_state_rule.required(),
    }
}
article_management_router.post('/my/article/edit', uploads.single('cover_img'), expressJoi(check_article_id_title_cateid_content_state), (req, res) => {
    if (!req.file || req.file.fieldname !== 'cover_img') {
        return res.send({
            "status": 1,
            "message": "文章封面是必选参数!"
        })
    }
    const articleInfo = {
        ...req.body,
        cover_img: path.join('/uploads', req.file.filename),
        pub_date: new Date(),
        author_id: req.auth.id
    }
    db.query('update article_list set ? where id=?', [articleInfo, req.body.id], (err, result) => {
        if (err) {
            return res.send({
                "status": 1,
                "message": '更新文章失败,原因是' + err.message
            })
        }

        if (result.affectedRows === 1) {
            return res.send({
                "status": 0,
                "message": "更新文章成功!"
            })
        }
        else {
            return res.send({
                "status": 1,
                "message": '更新文章失败!'
            })
        }
    })
})

module.exports = article_management_router

4.2  筛选文章

在筛选文章的时候有 状态(state)与分类id(cate_id) 这两个非必填参数,可以用拼接sql字符串的形式进行查询,先判断有没有,如果有就加上

由于要找到总数,所以要先查询一次全部的,之后对查询结果进行限制实现分页的功能 

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

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

相关文章

电子技术——CMOS反相器

电子技术——CMOS反相器 在本节,我们深入学习CMOS反相器。 电路原理 下图是我们要研究的CMOS反相器的原理图: 下图展示了当输入 vIVDDv_I V_{DD}vI​VDD​ 时的 iD−vDSi_D-v_{DS}iD​−vDS​ 曲线: 我们把 QNQ_NQN​ 当做是驱动源&#…

[AI助力] CS143学习笔记1

CS143, Compilers Lecture01 Course Overview notes 文章目录CS143, Compilers Lecture01 Course Overview notesAI summaryAI notes👇Introduction:Interpreters:Compilers:History:Conclusion:AI flowchart流程图AI flashcards抽认卡AI费曼学习法workflow 总结关于…

Linux 利用 qemu-system-aarch64 实现 x86 机器安装 arm64 的操作系统

文章目录[toc]遇到的问题安装 qemu-system-aarch64创建 aarch64 操作系统准备 aarch64 的 iso 镜像下载 aarch64 的 UEFI 固件创建虚拟磁盘创建虚拟机语言设置时区设置安装来源软件选择磁盘分区Kdump 配置网络配置root 用户密码创建用户安装操作系统遇到的问题 qemu-system-aar…

问题三十五:傅立叶变换——带通滤波

傅里叶变换(Fourier Transform)是一种用于分析信号的数学工具,它将信号分解成若干个不同频率的正弦和余弦函数。在图像处理中,傅里叶变换可以用来分析图像中各个频率的成分,从而进行滤波、增强等操作。 在傅里叶变换中…

电商项目后端框架SpringBoot、MybatisPlus

后端框架基础 1.代码自动生成工具 mybatis-plus &#xff08;1&#xff09;首先需要添加依赖文件 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.2</version></dependency><de…

【markdown】markdown语法

这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…

亿华通寻路:“氢”能之火,何以燎原?

氢&#xff0c;是能满足人类一切幻想的终极能源。以氢作为燃料的燃料电池&#xff0c;虽然还没有锂电池行业那样风光&#xff0c;但也在新能源战略布局中占有不可撼动的地位。近两年各界玩家跨界入局&#xff0c;更是掀起了持续的投资浪潮。在国内&#xff0c;政策依然是氢能发…

JAVA进阶--->JVM

文章目录JVM--java Virtual MachineJVM当时学习的存在位置JVM概述(什么是JVM)为什么学习JVM&#xff1f;虚拟机JVM作用JVM组成部分类加器作用类加载过程类什么时候会被加载&#xff08;初始化&#xff09;类加载器双亲委派机制打破双亲委派机制运行时数据区1.程序计数器2.本地方…

提取游戏《Limbus Company》(边狱公司)内素材

注意事项 相关工具会传到网盘。链接如下&#xff08;如果没链接那就是过期还没更新/文章没更新) BGM&#xff1a; 解包工具合集&#xff08;不包含uestdio&#xff0c;assetstdio)&#xff1a;点击此处 此文章主要是讲解如何提取游戏内的音频文件&#xff0c;所以默认各位会…

Spark性能优化四 内存

文章目录&#xff08;一&#xff09;性能优化分析内容怎么被消耗的如何预估程序会消耗多少内存呢(二&#xff09; 性能优化方案1)高性能序列化类库2)持久化或者checkpoint3)JVM 垃圾回收调优4)提高并行度5&#xff09;数据本地化&#xff08;一&#xff09;性能优化分析 一个计…

RocketMQ的基本概念与系统架构

RocketMQ安装与启动基础概念消息&#xff08;Message)主题&#xff08;Topic)标签&#xff08;Tag&#xff09;队列&#xff08;Queue)消息标识&#xff08;MessageId/Key)系统架构生产者 Producer消费者 Consumer名字服务器 NameServer功能介绍路由注册路由剔除路由发现客户端…

【Spark分布式内存计算框架——Structured Streaming】1. Structured Streaming 概述

前言 Apache Spark在2016年的时候启动了Structured Streaming项目&#xff0c;一个基于Spark SQL的全新流计算引擎Structured Streaming&#xff0c;让用户像编写批处理程序一样简单地编写高性能的流处理程序。 Structured Streaming并不是对Spark Streaming的简单改进&#xf…

Hypium框架使能ArkTS应用高效测试

HarmonyOS发布了声明式开发框架ArkUI&#xff0c;带来了极简高效的开发体验&#xff0c;备受广大开发者的青睐。那么&#xff0c;我们在开发过程中&#xff0c;如何确保ArkTS应用的功能和界面满足预期呢&#xff1f;ArkTS应用怎样高效进行专项测试&#xff1f;接下来&#xff0…

机器学习管道中的数据定价

机器学习管道中的数据定价 Data Pricing in Machine Learning 作者&#xff1a;Pipelines Zicun Cong Xuan Luo Pei Jian Feida Zhu Yong Zhang Abstract 机器学习具有破坏性。同时&#xff0c;机器学习只能通过多方协作&#xff0c;在多个步骤中取得成功&#xff0c;就…

Spark 性能调优

1常规性能调优 1.1常规性能调优一&#xff1a;最优资源配置 Spark性能调优的第一步&#xff0c;就是为任务分配更多的资源&#xff0c;在一定范围内&#xff0c;增加资源的分配与性能的提升是成正比的&#xff0c;实现了最优的资源配置后&#xff0c;在此基础上再考虑进行后面…

高研发投入成就产品力,蔚来财报透露重要信号

3月1日晚间&#xff0c;蔚来发布了2022年第四季度及全年财报。 财报显示&#xff0c;蔚来四季度营收160.6亿元&#xff0c;同比增长62.2%&#xff0c;连续11个季度正增长&#xff0c;同时全年总营收达492.7亿元&#xff0c;季度和年度营收均创新高。 尽管过去一年受到新冠疫情…

妇女节到了,祝福所有女神 Happy Women‘s Day!

在每年&#xff13;月&#xff18;日人们庆祝妇女节 &#xff37;omens Day is cllebrated on March 8 every year.国际妇女节(IWD)&#xff0c;中国内地称“三八”国际劳动妇女节或国际劳动妇女节。是在每年的3月8日为庆祝妇女在经济、政治和社会等领域作出的重要贡献和取得的…

5个商用字体网站分享

整理了5个免费、商用字体素材网站&#xff0c;对你有帮助记得点赞收藏。 更多设计素材免费下载&#xff1a; https://www.sucai999.com/?vNTYxMjky 1、FontSpace https://www.fontspace.com/ 这个网站提供了96000款免费字体&#xff0c;可商业用途的字体就有17000款&#xf…

RK3568-IOT核心板不同规格品牌TF卡读写速率测试

1. 测试对象HD-RK3568-IOT 底板基于HD-RK3568-CORE工业级核心板设计&#xff08;双网口、双CAN、 5路串口&#xff09;&#xff0c;接口丰富&#xff0c;适用于工业现场应用需求&#xff0c;亦方便用户评估核心板及CPU的性能。适用于工业自动化控制、人机界面、中小型医疗分析器…

VMworkstation centos虚拟机配置仅主机模式

首先是仅主机模式介绍&#xff0c;可以略过直接看下面具体配置过程。仅主机模式用于在宿主机和虚拟机之间建立局域网&#xff0c;宿主机和虚拟机之间可以互相访问&#xff0c;原理是建立虚拟交换机和宿主机虚拟网卡&#xff08;vmnet1&#xff09;&#xff0c;宿主机虚拟网卡和…