当前位置: 首页 > news >正文

web人脸登录

1,需要腾讯人脸第三方
腾讯人脸第三方申请步骤
2,相关表结构设计

create database faceDB;use faceDB;
-- 人脸表
create table face(
fid int primary key auto_increment COMMENT '主键',
face_base longtext COMMENT '图片数据 base_64编码',
create_time datetime COMMENT '插入时间',
vef_num int COMMENT '验证次数',
face_name varchar(100) COMMENT '人脸名称',
remark varchar(200) COMMENT '人脸备注',
face_status int COMMENT '人脸是否可用,(0==可用,1,不可用)',
update_extend1 varchar(300) COMMENT '扩展字段1',
update_extend2 varchar(300) COMMENT '扩展字段2',
update_extend3 varchar(300) COMMENT '扩展字段3'
);
-- 验证日志表
create table face_vef_log(
lid int primary key auto_increment COMMENT '主键',
vef_time datetime COMMENT '验证时间',
vef_code int COMMENT '返回code',
vef_msg varchar(200) COMMENT '返回的消息',
login_name varchar(100) COMMENT '验证人'
);

3,相关配置

tencentcloudapi:# 你的 secretIdsecretId: 你腾讯云的secretId# 你的 secretKeysecretKey: 你腾讯云的secretKey# 请求官方地址 不变endpoint: iai.tencentcloudapi.com#地域 可不变region: ap-shanghai
package com.face.config;import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.face.utils.JwtUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;/*** @author tanyongpeng* <p>des</p>**/
@Component
@Slf4j
public class FaceConfig implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String face_token = request.getHeader("face_token");Map<String,Object> infoMap = new HashMap<>();try{//token验证DecodedJWT tokenInfo = JwtUtils.getTokenInfo(face_token);//添加返回信息infoMap.put("msg","验证成功");return true;}catch (SignatureVerificationException e){e.printStackTrace();infoMap.put("msg","无效签名");}catch (TokenExpiredException e){infoMap.put("msg","token已过期");}catch (AlgorithmMismatchException e){infoMap.put("msg","算法不一致");}catch (Exception e){infoMap.put("msg","无效签名");}ObjectMapper objectMapper = new ObjectMapper();String mapInfoJson = objectMapper.writeValueAsString(infoMap);response.setContentType("application/json;charset=UTF-8");response.setCharacterEncoding("UTF-8");PrintWriter writer = response.getWriter();writer.write(mapInfoJson);return false;}
}
package com.face.server;import com.face.bean.result.FaceResult;
import com.face.utils.TimeUtils;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.CompareFaceRequest;
import com.tencentcloudapi.iai.v20180301.models.CompareFaceResponse;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;/*** @author tanyongpeng* <p>调用腾讯接口</p>**/
@Component
@Data
@Slf4j
public class FaceContrastServer {@Value("${tencentcloudapi.secretId}")private String secretId;@Value("${tencentcloudapi.secretKey}")private String secretKey;@Value("${tencentcloudapi.endpoint}")private String endpoint;@Value("${tencentcloudapi.region}")private String region;//第一张是数据库图片,第二张是登录时验证图片public FaceResult faceContrast(String imageA, String imageB){FaceResult faceResult = new FaceResult();try{Credential cred = new Credential(secretId, secretKey);HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint(endpoint);ClientProfile clientProfile = new ClientProfile();clientProfile.setHttpProfile(httpProfile);IaiClient client = new IaiClient(cred, region, clientProfile);CompareFaceRequest req = new CompareFaceRequest();req.setImageA(imageA);req.setImageB(imageB);CompareFaceResponse resp = client.CompareFace(req);faceResult.setScore(resp.getScore());faceResult.setCode(FaceResult.SUCCESS_CODE);} catch (TencentCloudSDKException e) {faceResult.setCode(FaceResult.FACE_ERROR);faceResult.setMsg(e.getMessage());}return faceResult;}
}

4,人脸注册,登录后端代码

package com.face.service.impl;import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.face.bean.Face;
import com.face.bean.result.FaceResult;
import com.face.mapper.FaceMapper;
import com.face.server.FaceContrastServer;
import com.face.service.FaceService;
import com.face.utils.JwtUtils;
import com.face.utils.TimeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/**
* @author typsusan
* @description 针对表【face】的数据库操作Service实现
* @createDate 2022-07-17 03:33:50
*/
@Service
public class FaceServiceImpl extends ServiceImpl<FaceMapper, Face>implements FaceService {@AutowiredFaceContrastServer faceContrastServer;@Overridepublic FaceResult vef(String imageBase) {imageBase = JSONUtil.parseObj(imageBase).getStr("imageBase");List<Face> faceList = lambdaQuery().orderByDesc(Face::getVefNum).list();FaceResult faceState = null;// 如果人脸库为空,则第一次登录为录入人脸if (faceList.size() == 0){return initFace(imageBase);}else {int faceLength = faceList.size();for (Face face : faceList) {FaceResult faceResult = faceContrastServer.faceContrast(face.getFaceBase(), imageBase);// 是否比对成功if (faceResult.getCode() == FaceResult.SUCCESS_CODE ){// 相似度是否大于80if (faceResult.getScore() > FaceResult.SATISFY_SCORE){if (face.getFaceStatus() == 0){// 成功lambdaUpdate().set(Face::getVefNum,face.getVefNum()+1).eq(Face::getFid,face.getFid()).update();faceResult.setMsg(TimeUtils.timeQuantum()+"好,"+face.getFaceName());faceResult.setName(face.getFaceName());Map<String,String> map = new HashMap<>();map.put("score",String.valueOf(faceResult.getScore()));map.put("faceName",faceResult.getName());faceResult.setToken(JwtUtils.genereteToken(map));return faceResult;}else {// 失败 人脸被禁用lambdaUpdate().set(Face::getVefNum,face.getVefNum()+1).eq(Face::getFid,face.getFid()).update();faceResult.setMsg(face.getFaceName()+",当前人脸被禁用");faceResult.setName(face.getFaceName());faceResult.setCode(FaceResult.FORBIDDEN_FACE);faceState = faceResult;// 就算上一张人脸被禁用还得往下执行// 可能当前用户存在多张人脸,if (faceLength == 1){return faceResult;}faceLength --;}}else {// 人脸库没有检测到人脸if (faceLength == 1){// 判断当前人脸是否被禁用,如被禁用,提示被禁用// 禁用优先级大于 没有检测到人脸return faceState != null?faceState:FaceResult.error(FaceResult.NOT_FOUND_FACE,"人脸库不存在该人脸",faceResult.getScore());}faceLength --;}}else {// 接口返回异常return faceResult;}}}// 空异常return FaceResult.error(FaceResult.NULL_ERROR,"空指针异常");}public FaceResult initFace(String imageBase){FaceResult faceResult = new FaceResult();Face face = new Face();face.setFaceBase(imageBase);face.setCreateTime(new Date());face.setVefNum(0);face.setFaceName("admin");face.setFaceStatus(0);boolean save = save(face);faceResult.setCode(FaceResult.INIT_FACE);faceResult.setMsg("人脸初始化"+(save?"成功":"失败")+","+(save?"请验证登录":"请稍后再试"));faceResult.setName(face.getFaceName());return faceResult;}
}

5,前端代码

/*** 获取 浏览器 拍照的权限*/
/*** 获取浏览器权限* @param option*/
function getCamera(option) {option.thisCancas = document.getElementById(option.canvasId);option.thisContext = option.thisCancas.getContext("2d");option.thisVideo = document.getElementById(option.videoId);option.thisVideo.style.display = "block";// 获取媒体属性,旧版本浏览器可能不支持mediaDevices,我们首先设置一个空对象if (navigator.mediaDevices === undefined) {navigator.mediaDevices = {};}// 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象// 使用getUserMedia,因为它会覆盖现有的属性。// 这里,如果缺少getUserMedia属性,就添加它。if (navigator.mediaDevices.getUserMedia === undefined) {navigator.mediaDevices.getUserMedia = function (constraints) {// 首先获取现存的getUserMedia(如果存在)var getUserMedia =navigator.webkitGetUserMedia ||navigator.mozGetUserMedia ||navigator.getUserMedia;// 有些浏览器不支持,会返回错误信息// 保持接口一致if (!getUserMedia) {//不存在则报错return Promise.reject(new Error("getUserMedia is not implemented in this browser"));}// 否则,使用Promise将调用包装到旧的navigator.getUserMediareturn new Promise(function (resolve, reject) {getUserMedia.call(navigator, constraints, resolve, reject);});};}var constraints = {audio: false,video: {width: option.videoWidth,height: option.videoHeight,transform: "scaleX(-1)",},};navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {// 旧的浏览器可能没有srcObjectif ("srcObject" in option.thisVideo) {option.thisVideo.srcObject = stream;} else {// 避免在新的浏览器中使用它,因为它正在被弃用。option.thisVideo.src = window.URL.createObjectURL(stream);}option.thisVideo.onloadedmetadata = function (e) {option.thisVideo.play();};}).catch((err) => {console.log(err);});return option
}/*** 绘制图片* 返回格式为base64* @param option*/
function draw(option){option.thisContext.drawImage(option.thisVideo,0,0,option.videoWidth,option.videoHeight);return option.thisCancas.toDataURL("image/png");
}export default {getCamera,draw
}
<template><div><div class="login"></div><!--登录中间块--><div class="login-mid"><div class="login-mid-top"><div class="shadow-top-left"></div><div class="shadow-top-right"></div></div><div class="login-mid-mid"><!--捕获人脸区域--><div class="videoCamera-canvasCamera"><videoid="videoCamera":width="videoWidth":height="videoHeight"autoplay></video><canvasstyle="display: none"id="canvasCamera":width="videoWidth":height="videoHeight"></canvas><!--人脸特效区域--><div v-if="faceImgState" class="face-special-effects-2"></div><div v-else class="face-special-effects"></div></div><!--按钮区域--><div class="face-btn"><button @click="faceVef()">{{faceImgState?'正在识别中...':'开始识别'}}</button></div><!--消息区域--><div class="msg"><div class="server-msg">{{msg}}</div><div class="welcome">Welcome to face recognition</div></div></div><div class="login-mid-bot"><div class="shadow-bot-left"></div><div class="shadow-bot-right"></div></div></div></div></template>
<script>
import $camera from '../../camera/index.js'
export default {data() {return {videoWidth: 200,videoHeight: 200,msg:'',faceImgState:false,faceOption:{}};},mounted() {//调用摄像头this.faceOption = $camera.getCamera({videoWidth: 200,videoHeight: 200,thisCancas: null,thisContext: null,thisVideo: null,canvasId:'canvasCamera',videoId:'videoCamera'});//this.getCompetence();},methods: {// 调用后台接口faceVef(){// 开始绘制图片let imageBase = $camera.draw(this.faceOption)if (this.faceImgState){return}this.faceImgState = trueif (imageBase === '' || imageBase === null || imageBase === undefined){this.$message.error("图片数据为空")}else {this.$http.post("/face/vef",{imageBase}).then(res =>{console.log(res)this.faceImgState = false// 跳转首页if (res.data.code === 200){// 关闭摄像头this.faceOption.thisVideo.srcObject.getTracks()[0].stop();localStorage.setItem("face_token",res.data.token);localStorage.setItem("username",res.data.name);this.$message.success(res.data.msg)this.$router.push("/home")}if (res.data.code === 201){this.$message.success(res.data.msg)}},onerror =>{this.faceImgState = false})}}},
};
</script>
<style>
@import "./index.css";
</style>

6,实现实例

参考:项目后端地址face-easy
参考:项目前端地址face-ui

相关文章:

web人脸登录

1&#xff0c;需要腾讯人脸第三方 腾讯人脸第三方申请步骤 2&#xff0c;相关表结构设计 create database faceDB;use faceDB; -- 人脸表 create table face( fid int primary key auto_increment COMMENT 主键, face_base longtext COMMENT 图片数据 base_64编码, create_tim…...

C++数字

目录 一、什么是数字 二、定义数字 三、数学运算 四、随机数 一、什么是数字 通常&#xff0c;当我们需要用到数字时&#xff0c;我们会使用原始的数据类型&#xff0c;如 int、short、long、float 和 double 等等。这些用于数字的数据类型&#xff0c;其可能的值和数值范围…...

【python】用plotly绘制正二十面体

文章目录顶点棱实现正二十面体plotly 的 Python 软件包是一个开源的代码库&#xff0c;它基于 plot.js&#xff0c;而后者基于 d3.js。我们实际使用的则是一个对 plotly 进行封装的库&#xff0c;名叫 cufflinks&#xff0c;能让你更方便地使用 plotly 和 Pandas 数据表协同工作…...

[Datawhale][CS224W]图机器学习(五)

这里写目录标题一、Deepwalk1.1 预备知识1.2 Deepwalk介绍1.3 Embedding1.4 word2Vec 词向量&#xff0c;词嵌入1.5 random Walk随机游走1.6 DeepWalk 核心代码Random WalkWord2vecDeepWalk应用1.7 DeepWalk优缺点二、Node2Vec2.1 图嵌入2.2 Node2Vec优化目标顶点序列采样策略2…...

Windows部署Jar包的三种方式

文章目录1、cmd命令启动2、bat脚本启动2.1 启动jar包2.2 关闭服务3、使用WinSW3.1 重命名3.2 xml配置3.3 安装服务3.4 卸载服务3.5 启动和停止服务1、cmd命令启动 这种方式比较简单&#xff0c;但是窗口关闭后服务也就被杀死了&#xff0c;命令如下 java -jar xxx.jar2、bat脚…...

【图像分类】卷积神经网络之AlexNet网络模型结构详解

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 1. 前言 LeNet5网络模型提出之后,卷积神经网络在很长一段时间都没有长足的发展,主要有以下两个原因: 1.1 训…...

学习动漫插画的网络班排行榜

很多小伙伴不知道动漫插画培训机构哪个好&#xff0c;找不到靠谱的插画班&#xff0c;今天给大家整理了国内动漫插画培训机构排名&#xff01; 一&#xff1a;动漫插画培训机构排名 1、轻微课&#xff08;五颗星&#xff09; 主打课程有日系插画、游戏原画、古风插画、动漫漫画…...

SpringCloud第五讲 Nacos注册中心-服务注册到Nacos

1.引入依赖&#xff1a; 在父工程中添加spring-cloud-alibaba的管理依赖 <!-- Nacos的管理依赖--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version…...

IP地理位置定位技术原理是什么

IP地理位置定位技术的原理是基于IP地址的网络通信原理和基础上的。它利用IP地址所包含的一些信息&#xff0c;如网络前缀和地址段&#xff0c;以及ISP的IP地址归属地数据库&#xff0c;来推测IP地址所对应的地理位置。具体来说&#xff0c;IP地址是由32位二进制数字组成的&…...

j-vxe-table 下拉搜索选择框数据加载过多导致前端崩溃问题

Jeeg-boot j-vxe-table 下拉搜索选择框数据加载过多导致前端崩溃问题 最近用到了Jeeg-boot j-vxe-table的组件&#xff0c;这组件时真J8难用&#xff0c;还好多BUG&#xff0c;想用个slot插槽也用不了&#xff0c;好像官方写了个基础就没怎么管了。&#x1f611; 问题&#xf…...

Java国际化ResourceBundle详解

在Java开发中&#xff0c;ResourceBundle是一种方便地管理本地化资源的机制。它可以使得程序能够根据当前系统环境的语言和国家/地区来自动加载相应的本地化资源文件&#xff0c;从而避免了硬编码和减少了重复的代码。以下是使用ResourceBundle的基本步骤&#xff1a; 1. 准备…...

一文高端Android性能优化-总结篇

以下从几个方面来总结一下Android的性能优化&#xff1a;1&#xff1a;界面卡顿优化2&#xff1a;内存优化3&#xff1a;App启动优化界面卡顿优化Android的界面为每秒60帧&#xff0c;即必须在16ms内完成1帧的绘制&#xff0c;如果某个方法耗时过程&#xff0c;导致16ms内无法完…...

深入讲解CFS组调度!(上)

注&#xff1a;本文缩写说明 一、CFS组调度简介 1.1. 存在的原因 总结来说是希望不同分组的任务在高负载下能分配可控比例的CPU资源。为什么会有这个需求呢&#xff0c;比如多用户计算机系统每个用户的所有任务划分到一个分组中&#xff0c;A用户90个相同任务&#xff0c;而B…...

大数据实操项目分享:餐饮智能推荐服务在线实习项目

项目背景&#xff1a;在“互联网"背景下&#xff0c;餐饮企业的经营方式发生了很大的变革&#xff1a;团购和020拓宽了销售 渠道&#xff0c;电子点餐、店内WIFI等信息技术提升了服务水平&#xff0c;大数据、私人定制更好地满足了细分市场的需求等。但是与此同时&#xf…...

代码随想录day38

动态规划五部曲 确定dp数组以及下标的含义确定递推公式dp数组如何初始化确定遍历顺序举例推导dp数组 509. 斐波那契数 https://leetcode.cn/problems/fibonacci-number/ class Solution {public int fib(int n) {if(n0) return 0;if(n<3) return 1;int[] dp new int[n]…...

《计算机网络:自顶向下方法》实验5:TCP

Q1 包含HTTP POST消息的TCP报文段的序号是多少?注意:为了发现POST 命令, 你需要在wireshark底部的报文内容域窗口中去查找,查找数据中包含 “POST”的段。 如图所示,由报文中的POST 和 HTTP/1.1可知,其包含HTTP POST消息; TCP报文段的序号可见TCP报文: Sequence Number:…...

【踩坑指南】Stable Diffusion 服务器端部署笔记

文章目录下载github文件配置环境ckpt文件权重下载生成图像NSFW检查&#xff08;瑟图过滤&#xff09;下载github文件 https://github.com/CompVis/stable-diffusion 这个网址&#xff0c;下载压缩包解压&#xff0c;也可以用git clone下载 配置环境 这一步坑最多&#xff0c…...

[qiankun]-多页签缓存

[qiankun]-多页签缓存环境功能需求多页签缓存方案方案1.主服务进行html替换方案2.微服务vnode 替换方案3.每个微服务都不卸载微服务加载方式的选择微服务的路由路径选择微服务的缓存工具微服务的容器使用tab作为微服务的挂载容器使用微服务路由作为微服务的挂载容器场景描述微服…...

2|电子技术|数字电子技术基础|雨课堂习题|考前回顾

A/DD/A转化横向与阵列 相乘&#xff0c;竖向为或阵列 相加&#xff01;功率放大电路克服交越失真&#xff0c;是在乙类的基础上增加两个二极管&#xff0c;使微导通&#xff0c;使三极管导通时间大于半个周期&#xff0c;小于一个周期&#xff0c;构成甲乙类工作状态。选择填空…...

vue+echarts:圆形柱状图设置角度和最大值

第020个点击查看专栏目录本示例是显示圆形的柱状图&#xff0c;angleAxis设置一个max&#xff0c; angleAxis上startAngle&#xff1a;90 &#xff0c; 将0点设置为最顶点。 文章目录示例效果示例源代码&#xff08;共100行&#xff09;相关资料参考专栏介绍示例效果 示例源代码…...

Linux系统安装Nginx常见报错问题

安装Nginx从nginx官网下载所需版本的nginx&#xff0c;http://nginx.org/下载之后&#xff0c;将安装包上传到linux系统指定路径解压文件&#xff0c;tar -zxvf nginx-1.22.1.tar.gz &#xff08;此处用1.22.1版本为例&#xff09;进入安装包目录&#xff0c;cd nginx-1.22.1执…...

按下按键之后,打印一句话------>三个按键需要实现

main.c: #include "key.h" extern void printf(const char *fmt, ...); void delay_ms(int ms){ int i,j; for(i 0; i < ms;i) for (j 0; j < 1800; j);} int main(){ //key1键盘 //EXIT控制器初始化 void PF9_exti_init(); //GICD控…...

Mac配置VScode

Mac配置VScode 常用技巧 命令调色板 根据您当前的上下文访问所有可用的命令。 键盘快捷键&#xff1a;⇧⌘P 快速打开 快速打开文件。 键盘快捷键&#xff1a;⌘P **提示&#xff1a;**类型&#xff1f;查看命令建议。 在最近打开的文件夹和工作区之间导航 最近打开 键盘快捷…...

MAC地址IP地址 端口

网络结构&#xff1a; 服务器-客户机&#xff08;C/S&#xff09;Client-Server结构&#xff0c;如QQ,LOL都拥有客户端 优点&#xff1a;响应速度快&#xff0c;形式多样&#xff0c;安全新较高缺点&#xff1a;安装软件和维护&#xff0c;不能跨平台LINUX/windows/MAC浏览器-…...

关于虚拟数字人你想知道的都在这里

2022年底&#xff0c;微软旗下的人工智能实验室Open AI发布的对话式大型语言模型ChatGPT聊天机器人一夜蹿红&#xff0c;5天用户量超百万&#xff0c;在各大中外媒体平台掀起了一阵热潮。也带火了人工智能相关产业&#xff0c;AI虚拟数字人就是其中之一&#xff0c;一个随着元宇…...

分布式任务调度处理方案(无代码)

业务涉及到&#xff0c;需要向数据库、redis、elasticsearch、MinIO写四份数据&#xff0c;这里存在分布式事务问题。如何解决问题&#xff0c;先分析cap&#xff0c;是要保证可用性&#xff0c;还是保证一致性。如何选择是CP还是AP&#xff1f;分析业务场景CP的场景&#xff1…...

2023年博管办香江学者计划、澳门青年学者开始申报

2023年2月20日&#xff0c;全国博士后管委会办公室官方网站发出了2023年香江学者计划、澳门青年学者计划和博士后国&#xff08;境&#xff09;外学术交流项目申报指南&#xff0c;以下知识人网小编仅转载香江学者计划和澳门青年学者计划申报指南并做重点解读。知识人网整理香江…...

(二十一)、实现评论功能(1)【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1&#xff0c;评论回复模块的样式布局 1.1 在detail页面添加uview中的 Empty 内容为空组件 <!-- 评论区 --><view class"comment"><u-empty mode"comment" icon"http://cdn.uviewui.com/uview/empty/comment.png"></u-emp…...

【Docker】初识Dcoker以及镜像操作(一)

目录 1.初识Docker 1.1.什么是Docker 1.1.1.应用部署的环境问题 1.1.2.Docker解决依赖兼容问题 1.1.3.Docker解决操作系统环境差异 1.1.4.小结 1.2.Docker和虚拟机的区别 1.3.Docker架构 1.3.1.镜像和容器 1.3.2.DockerHub 1.3.3.Docker架构 1.3.4.小结 1.4.安装D…...

(1)C#传智:在vs2022中基本了解(第一天)

开始vs2022中C#入门&#xff0c;就是一笔记&#xff0c;算不上原创&#xff0c;没办法得选啊。 一、vs中卸载项目和移除项目有什么区别&#xff1f; 1、卸载、移除都不会移除物理文件&#xff0c;只会删除关联 2、卸载删除关联的程度低&#xff0c;卸载后项目只是“变灰色…...