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

智慧社区构建——2

1.实现Token校验

## Token校验URL```json
GET /checkToken
```参数```json
HttpServletRequest request
```返回```json
{"msg": "操作成功","code": 200,"status": "ok"
}{"msg": "操作成功","code": 200,"status": "error"
}

 在LoginController中实现下面得方法

/*** Token校验* @param request HTTP请求* @return 校验结果*/@RequestMapping("/checkToken")public Result checkToken(HttpServletRequest request) {//1.从请求头中获取tokenString token = request.getHeader("token");System.out.println("从请求头获取到的token:" + token);//2.判断token是否为空或空字符串,如果是则返回错误信息if (token == null || token.isEmpty()) {System.out.println("token为空或空字符串,验证失败");return Result.ok().put("status", "error").put("msg", "token不能为空");}//3.声明变量用于标记JWT格式是否有效boolean isJwtValid;//4.声明变量用于存储从token中解析出的userIdString userId = null;try {//5.使用JWT工具类解析token,获取负载信息Claims claims = Jwts.parser().setSigningKey(jwtUtil.getSecret()).parseClaimsJws(token).getBody();//6.从负载中获取userIduserId = claims.get("userId", String.class);System.out.println("从token中解析出的userId:" + userId);//7.如果解析成功,标记JWT格式有效isJwtValid = true;System.out.println("JWT格式验证通过");} catch (Exception e) {//8.如果解析失败,标记JWT格式无效isJwtValid = false;System.out.println("JWT格式验证失败,异常信息:" + e.getMessage());}//9.如果JWT格式无效,返回错误信息if (!isJwtValid) {System.out.println("JWT格式无效,返回错误响应");return Result.ok().put("status", "error").put("msg", "token格式无效");}//10.根据userId拼接Redis中存储token的keyString redisKey = "communityuser-" + userId;System.out.println("Redis中存储token的key:" + redisKey);//11.从Redis中获取存储的tokenString redisToken = (String) redisTemplate.opsForValue().get(redisKey);System.out.println("从Redis中获取到的token:" + redisToken);//12.判断Redis中是否存在token且与请求中的token一致boolean isTokenValid = redisToken != null && redisToken.equals(token);System.out.println("Redis中token与请求token是否一致:" + isTokenValid);//13.根据双重验证结果返回对应的响应信息if (isTokenValid) {System.out.println("token双重验证通过,返回成功响应");return Result.ok().put("status", "ok").put("msg", "token验证通过");} else {System.out.println("token双重验证失败,返回错误响应");return Result.ok().put("status", "error").put("msg", "token已失效或不匹配");}}

利用上面得Token校验实现动态路由

加载动态路由

实现思路

1.通过session获取用户信息

2.根据userId获取角色名称,需要在user_role表和role表中联表查询

3.根据userId获取用户的权限菜单:

第一步:根据用户的id查询该用户所对应的角色以及该角色所对应的菜单,需要user_role、user_menu、menu三个表联表查询;

第二步:按照查询出来的菜单进行封装,一个一级菜单的信息封装进一个列表,此菜单下的二级菜单的信息封装进此列表的子列表中,若有三级菜单以此类推进行封装

④返回用户信息、角色名称和用户的权限菜单信息,格式如

```json
{"msg": "操作成功","code": 200,"data": {"userId": 1,"username": "admin", "password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92","realName": "管理员", "contact": "", "mobile": "15679711120", "status": 1},"roles": "超级管理员","routers": [{"name": "系统管理","path": "/sys","hidden": "false","redirect": "noRedirect","component": "Layout","alwaysShow": true,"meta": {"title": "系统管理","icon": "system"},"children": [{"name": "管理员管理","path": "/user","hidden": "false","component": "sys/user/index","meta": {"title": "管理员管理","icon": "user"}}]}]
}

封装返回的routers信息MenuRouterVO、ChildMenuRouterVO、MenuRouterVO

package com.qcby.vo;import lombok.Data;import java.util.List;@Data
public class MenuRouterVO {private String name;private String path;private String component;private String hidden;private String redirect = "noRedirect";private Boolean alwaysShow = true;private MetaVO meta;private List<ChildMenuRouterVO> children;}
package com.qcby.vo;import lombok.Data;@Data
public class ChildMenuRouterVO {private String name;private String path;private String component;private String hidden;private MetaVO meta;}
package com.qcby.vo;import lombok.Data;@Data
public class MetaVO {private String title;private String icon;
}

加载动态路由controller请求

/*** 通过登录的用于加载动态路由* 显示该用户能访问的菜单* @param session* @return*/@RequestMapping("/getRouters")public Result getRouters(HttpSession session){//获取用户名称User user = (User)session.getAttribute("user");//获取用户的角色名称String roles = roleMapper.getRoleNameByUserId(user.getUserId());//获取用户的权限菜单List<MenuRouterVO> routers = this.menuService.getMenuRouterByUserId(user.getUserId());return Result.ok().put("data", user).put("roles", roles).put("routers",routers);}

获取用户的角色名称的mapper

@Select("SELECT role_name FROM role, user_role where user_role.role_id=role.role_id and user_role.user_id=#{userId}")public String getRoleNameByUserId(Integer userId);

获取用户的菜单信息service

 /*** 重写接口方法,根据用户ID获取菜单路由信息* @param userId 用户ID* @return 菜单路由信息列表*/@Overridepublic List<MenuRouterVO> getMenuRouterByUserId(Integer userId) {// 1. 根据用户ID查询该用户拥有的角色及对应的所有菜单列表List<Menu> menuList = this.menuMapper.getMenusByUserId(userId);// 2. 创建最终要返回的菜单路由VO集合(VO用于前端展示的数据模型)List<MenuRouterVO> list = new ArrayList<>();// 3. 遍历所有菜单,筛选出一级菜单(父菜单ID为0)并封装成MenuRouterVOfor (Menu menu : menuList) {// 筛选一级菜单(parentId为0表示是顶级菜单)if (menu.getParentId() == 0) {// 创建一级菜单路由VO对象MenuRouterVO menuRouterVO = new MenuRouterVO();// 复制Menu对象的属性到MenuRouterVO(使用框架提供的属性拷贝工具类)BeanUtils.copyProperties(menu, menuRouterVO);// 封装Meta信息(前端显示需要的标题和图标)MetaVO metaVO = new MetaVO();metaVO.setTitle(menu.getName()); // 设置菜单标题metaVO.setIcon(menu.getIcon()); // 设置菜单图标menuRouterVO.setMeta(metaVO); // 将meta信息设置到路由对象// 获取当前一级菜单的ID,用于匹配其子菜单Integer menuId = menu.getMenuId();// 4. 创建子菜单集合,用于存储当前一级菜单下的所有子菜单List<ChildMenuRouterVO> children = new ArrayList<>();// 遍历所有菜单,筛选出属于当前一级菜单的子菜单for (Menu child : menuList) {// 判断当前菜单是否为当前一级菜单的子菜单(子菜单的parentId等于父菜单的menuId)if(child.getParentId() == menuId){// 5. 创建子菜单路由VO对象并封装数据ChildMenuRouterVO childVO = new ChildMenuRouterVO();BeanUtils.copyProperties(child, childVO); // 复制基本属性// 封装子菜单的Meta信息MetaVO childMetaVO = new MetaVO();childMetaVO.setTitle(child.getName()); // 子菜单标题childMetaVO.setIcon(child.getIcon()); // 子菜单图标childVO.setMeta(childMetaVO); // 设置子菜单的meta信息// 将子菜单添加到子菜单集合children.add(childVO);}}// 6. 将子菜单集合设置到当前一级菜单路由对象中menuRouterVO.setChildren(children);// 7. 将封装好的一级菜单路由对象添加到最终返回的集合中list.add(menuRouterVO);}}// 返回整理好的菜单路由列表(包含一级菜单和对应的子菜单)return list;}

获取用户的菜单信息mapper

    @Select({"select m.menu_id,m.parent_id,m.name,m.path,m.component," +"m.menu_type,m.status,m.icon,m.sort,m.hidden from " +"user_role ur,role_menu rm,menu m where ur.role_id = rm.role_id" +" and rm.menu_id = m.menu_id " +"and ur.user_id = #{userId} order by m.sort"})public List<Menu> getMenusByUserId(Integer userId);

结果图

登录进去之后就能够看到一级目录

每个目录下面有对应得子目录

2.修改密码

实现思路

①发送更新密码请求,弹出更新密码弹出层

②前端密码格式验证,新旧密码是否一致验证

③修改密码:第一步获取session中的用户信息;第二步将根据用户查询的密码和前端传来的旧密码进行比较,如果相等,将新密码加密后在数据库中更新密码字段信息,密码更新成功,返回。

修改密码请求处理

/*** 修改用户密码的控制器方法* @return 返回操作结果*/@PutMapping("/updatePassword")  // 使用PUT映射处理/updatePassword请求public Result updatePassword(@RequestBody UpdatePasswordFrom updatePasswordFrom, HttpSession session){// 从session中获取当前登录的用户信息User user = (User)session.getAttribute("user");// 获取用户当前存储的密码String pwd = user.getPassword();// 使用SHA-256算法对用户输入的原密码进行加密String password = SecureUtil.sha256(updatePasswordFrom.getPassword());// 比较数据库中的密码和用户输入的原密码是否一致if(pwd.equals(password)){String newpassword = SecureUtil.sha256(updatePasswordFrom.getNewPassword());user.setPassword(newpassword);if(userService.updateById(user)){return Result.ok().put("status","success");}return Result.error("修改失败");}
// 原密码验证失败return Result.ok().put("status","passwordError");}

密码修改表单实体类UpdatePasswordFrom

package com.qcby.DTO;import lombok.Data;/*** 密码修改表单实体类* 用于接收前端传递的旧密码修改相关参数*/
@Data
public class UpdatePasswordFrom {/*** 当前密码(旧密码)*/private String password;/*** 新密码*/private String newPassword;/*** 确认新密码(可选,用于前端二次验证)*/private String confirmPassword;
}

 结果

3.退出登录模块

实现思路

①登出请求:将当前session设置为无效

②将token设置为空

③将router设置为空

④将cookie里面的token信息清空

⑤返回登录页面

登出请求处理

 /*** 用户退出* @param session* @return*/@RequestMapping("/logout")public Result logOut(HttpSession session){session.invalidate();return Result.ok();}

结果图

4.小区的增删改查

对应的实体类

package com.qcby.entity;import lombok.Data;import java.util.Date;@Data
public class Community {private Integer communityId;private String communityName;private Integer termCount;private Integer seq;private String creater;private Date createTime;private Float lng;private Float lat;
}

服务层

package com.qcby.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.DTO.CommunityListFrom;
import com.qcby.entity.Community;
import com.qcby.vo.PageVO;public interface ICommunityService extends IService<Community> {PageVO communityList(CommunityListFrom communityListForm);
}

增删改查的实现思路 

对于传入参数,如果有,但是参数不多,只有一个,直接接收;如果参数较多,应将其传入字段封装在一个实体类中。对于get请求,用@PathVariable接收,对于非get请求,用@RequestBody接收。

对于返回参数,如果与数据单表中的字段可以进行一一映射,不需要考虑封装,直接返回;如果无法在单表中进行一一映射,则需要根据返回参数进行实体类封装。

对于单表的增删改查,mybatiaPlus提供了相应的操作,对于多表则需要手写sql语句

4.1小区搜索和查询

传入参数

{"page": 1,"limit": 10,"communityId": "","communityName": ""
}

返回参数

{"msg": "操作成功","code": 200,"data": {"totalCount": 8,"pageSize": 10,"totalPage": 1,"currPage": 1,"list": [{"communityId": 19,"communityName": "北清云际","termCount": 33,"seq": 190,"creater": "admin","createTime": "2023-07-18 00:41:20","lng": 116.298904,"lat": 40.091644,"personCnt": 1},{"communityId": 17,"communityName": "天龙苑","termCount": 10,"seq": 170,"creater": "admin","createTime": "2023-07-18 00:38:06","lng": 116.36206,"lat": 40.088108,"personCnt": 0}]}
} 

 实现思路:由于返回list中在community表中没有personCnt字段,因此需要封装一个CommunityVO类用于数据的返回。同时由于mybtisPlus中并没有现成的sql用于根据community_id查询相应的居民人数,因此需要编写sql用来查询每个community对于的人数personCnt

CommunityVO类

package com.qcby.vo;import lombok.Data;import java.util.Date;@Data
public class CommunityVO {private Integer communityId;private String communityName;private Integer termCount;private Integer seq;private String creater;private Date createTime;private Float lng;private Float lat;private Integer personCnt;
}

 controller

/*** 获取小区的所有信息,分页条件查询* @return*/@GetMapping("/list")public Result getList(CommunityListFrom communityListFrom){PageVO pageVO = this.communityService.communityList(communityListFrom);return Result.ok().put("data",pageVO);}

service 

// CommunityServiceImpl.java
package com.qcby.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcby.DTO.CommunityListFrom;
import com.qcby.entity.Community;
import com.qcby.mapper.CommunityMapper;
import com.qcby.service.ICommunityService;
import com.qcby.vo.CommunityVO;
import com.qcby.vo.PageVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;@Service
public class CommunityServiceImpl extends ServiceImpl<CommunityMapper, Community> implements ICommunityService {@Autowiredprivate CommunityMapper communityMapper;@Overridepublic PageVO communityList(CommunityListFrom communityListForm) {Page<Community> page = new Page<>(communityListForm.getPage(), communityListForm.getLimit());QueryWrapper<Community> queryWrapper = new QueryWrapper<>();queryWrapper.like(StringUtils.isNotBlank(communityListForm.getCommunityName()), "community_name", communityListForm.getCommunityName());Page<Community> resultPage = this.communityMapper.selectPage(page, queryWrapper);PageVO pageVO = new PageVO();List<CommunityVO> list = new ArrayList<>();for (Community record : resultPage.getRecords()) {CommunityVO communityVO = new CommunityVO();BeanUtils.copyProperties(record, communityVO);Integer personCount = communityMapper.getCountByCommunityId(record.getCommunityId());communityVO.setPersonCnt(personCount);list.add(communityVO);}pageVO.setList(list);pageVO.setTotalCount(resultPage.getTotal());pageVO.setPageSize(resultPage.getSize());pageVO.setCurrPage(resultPage.getCurrent());pageVO.setTotalPage(resultPage.getPages());return pageVO;}
}

 根据communityId查询居民人数的mapper

@Select({"select count(*) from person where community_id = #{communityId} "})Integer getCountByCommunityId(Integer communityId);

分页 

用于分页封装的实体类
package com.qcby.vo;import lombok.Data;import java.util.List;@Data
public class PageVO {private Long totalCount;private Long totalPage;private Long pageSize;private Long currPage;private List list;
}
分页的相关配置 
package com.qcby.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {/*** 配置分页插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 添加分页拦截器(支持MySQL、PostgreSQL等主流数据库)interceptor.addInnerInterceptor(new PaginationInnerInterceptor());//添加乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

结果图

4.2添加小区

传入参数

{"communityName": "test""lat": "1""lng": "1""seq": 1"termCount": "1"
}

返回参数

 {"msg": "操作成功","code": 200
}

controller

 /*** 添加小区* @param community* @param session* @return*/@RequestMapping("/add")public Result add(@RequestBody Community community, HttpSession session){User user = (User) session.getAttribute("user");community.setCreater(user.getUsername());boolean save = this.communityService.save(community);if(!save) return Result.error("添加失败");return Result.ok();}

界面

4.3通过id查询小区

传入参数

1

返回参数

{"msg": "操作成功","code": 200,"data": {"communityId": 19,"communityName": "北清云际","termCount": 33,"seq": 190,"lng": 116.298904,"lat": 40.091644}
}

controller

 /*** 修改的回显操作* @param id* @return*/@RequestMapping("/info/{id}")public Result info(@PathVariable("id") Integer id){Community community = this.communityService.getById(id);if(community == null){return Result.error("没有此小区");}return Result.ok().put("data",community);}

界面

 4.4修改小区

传入参数

{"communityId": 21,"communityName": "1","termCount": "12","lng": "12","lat": "12","seq": 210
}

返回参数

{"msg": "操作成功","code": 200
}

controller

/*** 修改小区信息* @param community* @return*/@RequestMapping("/edit")public Result edit(@RequestBody Community community){boolean updateById = this.communityService.updateById(community);if(!updateById) return Result.error("修改失败");return Result.ok();}

界面

4.5删除小区

传入参数

[21,20
]

返回参数

{"msg": "操作成功","code": 200
}

controller

   /*** 仅删除小区信息,不删除关联表数据(不使用try-catch)* @param ids 小区ID数组* @return 操作结果*/@RequestMapping("/del")@Transactionalpublic Result del(@RequestBody Integer[] ids) {// 删除小区数据boolean remove = this.communityService.removeByIds(Arrays.asList(ids));if (!remove) {return Result.error("小区删除失败");}return Result.ok();}

界面

注意:在删除小区的同时也会删除掉这个小区对应的摄像头、访客记录、小区出入记录、小区居民,如果数据库中没有则会个小区对应的内容则会删除失败

5.摄像头的增删改查

和上面的小区的实现基本一致

对应的Controller

package com.qcby.controller;import com.qcby.entity.Camera;
import com.qcby.entity.User;
import com.qcby.service.ICameraService;
import com.qcby.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.List;@RestController
@RequestMapping("/sys/camera")
public class CameraController {@Autowiredprivate ICameraService cameraService;/*** 查询摄像头列表*/@GetMapping("/list/{communityId}")public Result getCameraList(@PathVariable Integer communityId) {try {// 调用关联查询方法,获取包含小区名称的摄像头列表List<Camera> cameraList = cameraService.getCameraListWithCommunityName(communityId);return Result.ok().put("data", cameraList);} catch (Exception e) {return Result.error("查询失败:" + e.getMessage());}}/*** 添加摄像头*/@RequestMapping("/add")public Result add(@RequestBody Camera camera, HttpSession session){User user = (User) session.getAttribute("user");camera.setCreater(user.getUsername());boolean save = cameraService.save(camera);if(!save) return Result.error("添加失败");return Result.ok();}/*** 修改的回显操作* @param id* @return*/@RequestMapping("/info/{id}")public Result info(@PathVariable("id") Integer id){Camera camera = cameraService.getById(id);if(camera == null){return Result.error("没有此摄像头");}return Result.ok().put("data",camera);}/*** 修改摄像头信息* @param camera* @return*/@RequestMapping("/edit")public Result edit(@RequestBody Camera camera){boolean updateById = cameraService.updateById(camera);if(!updateById) return Result.error("修改失败");return Result.ok();}/*** 删除摄像头信息* @param ids 摄像头ID数组* @return 操作结果*/@RequestMapping("/del")public Result del(@RequestBody Integer[] ids){boolean remove = cameraService.removeByIds(Arrays.asList(ids));if(!remove) return Result.error("删除失败");return Result.ok();}
}

对应的实体类

package com.qcby.entity;import lombok.Data;@Data
public class Person {private Integer personId;private Integer communityId;private String termName;private String houseNo;private String userName;private String sex;private String mobile;private String faceUrl;private String personType;private Integer state;private String creater;private String createTime;private String remark;private String faceBase;
}

对应的Mapper.java

package com.qcby.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qcby.entity.Camera;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Param;
import java.util.List;public interface CameraMapper extends BaseMapper<Camera> {// 联表查询,通过 camera 的 community_id 关联 community 表,获取小区名称@Select("SELECT c.*, com.community_name as communityName " +"FROM camera c " +"LEFT JOIN community com ON c.community_id = com.community_id " +"WHERE c.community_id = #{communityId}")List<Camera> selectCameraWithCommunityName(@Param("communityId") Integer communityId);
}

应的Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.mapper.CameraMapper"><!-- 与数据库表字段严格映射 --><resultMap id="BaseResultMap" type="com.qcby.entity.Camera"><id column="camera_id" property="cameraId" /><result column="community_id" property="communityId" /><result column="camera_name" property="cameraName" /><result column="mac_id" property="macId" /><result column="direction" property="direction" /><result column="state" property="state" /><result column="seq" property="seq" /><result column="creater" property="creater" /><result column="create_time" property="createTime" /><result column="remark" property="remark" /></resultMap><!-- 完整查询字段列表 --><sql id="Base_Column_List">camera_id,community_id,camera_name,mac_id,direction,state,seq,creater,create_time,remark</sql><!-- selectById 实现(MyBatis-Plus 基础方法) --><select id="selectById" resultMap="BaseResultMap">SELECT<include refid="Base_Column_List" />FROM cameraWHERE camera_id = #{id}</select><!--修改摄像头信息--><update id="updateById" parameterType="com.qcby.entity.Camera">UPDATE camera<set><if test="et.cameraName != null">camera_name = #{et.cameraName},</if><if test="et.macId != null"> mac_id = #{et.macId},</if><if test="et.direction != null"> direction = #{et.direction},</if><if test="et.state != null"> state = #{et.state},</if><if test="et.seq != null"> seq = #{et.seq},</if><if test="et.remark != null"> remark = #{et.remark},</if></set>WHERE camera_id = #{et.cameraId}</update><!--删除摄像头--><delete id="deleteBatchIds" parameterType="java.util.Collection">DELETE FROM cameraWHERE camera_id IN<foreach item="id" collection="coll" separator="," open="(" close=")">#{id}</foreach></delete>
</mapper>

对应的ICameraService

package com.qcby.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.qcby.entity.Camera;import java.util.List;public interface ICameraService extends IService<Camera> {List<Camera> getCameraListWithCommunityName(Integer communityId);
}

对应的CameraServiceImpl

package com.qcby.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcby.entity.Camera;
import com.qcby.mapper.CameraMapper;
import com.qcby.service.ICameraService;
import org.springframework.stereotype.Service;import java.util.List;@Service
public class CameraServiceImpl extends ServiceImpl<CameraMapper, Camera> implements ICameraService {@Overridepublic List<Camera> getCameraListWithCommunityName(Integer communityId) {return baseMapper.selectCameraWithCommunityName(communityId);}
}

http://www.lryc.cn/news/607477.html

相关文章:

  • C语言(02)——标准库函数大全(持续更新)
  • AI Agent 视角:可执行程序的二进制格式,是一场「结构化语言」与「智能解析」的双向奔赴
  • 一套视频快速入门并精通PostgreSQL
  • 03 Broker主从架构和集群模式
  • (二)LoRA微调BERT:为何在单分类任务中表现优异,而在多分类任务中效果不佳?
  • Hutool 的完整 JSON 工具类示例
  • 使用社区 EE 镜像运行 Ansible
  • Redis的ZipList、SkipList和ListPack之间的区别
  • 在Alpine Linux上配置Redis使用NFS存储的完整指南
  • 李宏毅深度学习教程 第4-5章 CNN卷积神经网络+RNN循环神经网络
  • 每天一点跑步运动小知识
  • 逻辑回归算法 银行贷款资格判断案例,介绍混淆矩阵与正则化惩罚
  • AG-UI 协议全面解析--下一代 AI Agent 交互框架医疗应用分析(下)
  • Python 项目路径配置完全指南
  • 51单片机入门:模块化编程
  • C#常见的转义字符
  • 智能Agent场景实战指南 Day 29:Agent市场趋势与前沿技术
  • 31. 伪类和伪元素区别
  • 板卡型授时设备的优势总结.北斗pcie对时装置,北斗双模pcie授时板卡,双模pcie授时板卡
  • 二建机电工程专业都考哪些知识点?
  • WordPress 前端显示英文,后台显示中文的设置
  • 前端SWR策略:优化数据请求
  • 电商项目_性能优化_数据同步
  • Altium 移除在原理图之外的元器件
  • Linux权限提升
  • 【CDH × Docker】一次测试部署,N 次复用的环境镜像方案
  • Qt结合ffmpeg实现图片参数调节/明亮度对比度饱和度设置/滤镜的使用
  • 菜鸟教程Shell笔记 数组 运算符 echo命令
  • 一文了解 `package.json` 和 `package-lock.json`文件
  • vscode cursor配置php的debug,docker里面debug