厦门市建设工程安全管理协会网站,海外服务器租赁,wordpress历史版本数据库,电脑技术学习网站文章目录 1. 登录校验1.1 需求说明1.2 实现思路1.3 ThreadLocal1.4 AuthContextUtil1.5 拦截器使用1.5.1 拦截器开发1.5.2 拦截器注册 1.6 代码优化1.6.1 配置优化1.6.2 代码优化1.6.3 前端修改 2. API接口文档2.1 Apifox接口管理平台2.1.1 接口管理平台简介2.1.2 Apifox简介2.… 文章目录 1. 登录校验1.1 需求说明1.2 实现思路1.3 ThreadLocal1.4 AuthContextUtil1.5 拦截器使用1.5.1 拦截器开发1.5.2 拦截器注册 1.6 代码优化1.6.1 配置优化1.6.2 代码优化1.6.3 前端修改 2. API接口文档2.1 Apifox接口管理平台2.1.1 接口管理平台简介2.1.2 Apifox简介2.1.3 Apifox使用 2.2 Api文档生成工具2.2.1 Swagger2.2.2 Knife4jKnife4j简介Knife4j使用配置抽取常见注解导出导入 3. 权限管理说明3.1 权限管理介绍3.2 表结构介绍 4. 角色管理4.1 菜单添加4.2 页面制作4.3 查询角色4.3.1 需求说明4.3.2 后端接口需求分析SysRoleSysRoleDtoSysRoleControllerSysRoleServiceSysRoleMapperSysRoleMapper.xml 4.3.3 前端对接实现思路sysRole.jssysRole.vue 4.4 添加角色4.4.1 需求说明4.4.2 页面制作4.4.3 后端接口SysRoleControllerSysRoleServiceSysRoleMapperSysRoleMapper.xml 4.4.4 前端对接实现思路sysRole.jssysRole.vue 4.5 修改角色4.5.1 需求说明4.5.2 数据回显4.5.3 提交修改后端接口SysRoleControllerSysRoleServiceSysRoleMapperSysRoleMapper.xml 前端对接sysRole.jssysRole.vue 4.6 删除角色4.6.1 需求说明4.6.2 后端接口SysRoleControllerSysRoleServiceSysRoleMapperSysRoleMapper.xml 4.6.3 前端对接sysRole.jssysRole.vue 4.6.3 前端对接sysRole.jssysRole.vue 1. 登录校验
1.1 需求说明
后台管理系统中除了登录接口、获取验证码的接口在访问的时候不需要验证用户的登录状态其余的接口在访问的时候都必须要求用户登录成功以后才可以进行访问。
1.2 实现思路
具体的实现流程如下所示 注意
1、请求url的判断可以通过拦截规则配置进行实现
2、更新Redis中数据的存活时间的主要目的就是为了保证用户在使用该系统的时候Redis中会一直保证用户的登录状态如果用户在30分钟之内没有使用该系统那么此时登录超时。此时用户就需要重新进行登录。
3、将从Redis中获取到的用户存储到ThreadLocal中这样在一次请求的中流可以在controller、service、mapper中获取用户数据
1.3 ThreadLocal
完成该功能需要使用到ThreadLocalThreadLocal是jdk所提供的一个线程工具类。使用该工具类可以实现在同一个线程进行数据的共享。
代码如下所示
public class ThreadLocalTest {// 创建一个ThreadLocal对象private static final ThreadLocalSysUser threadLocal new ThreadLocal() ;public static void main(String[] args){// 在主线程中创建SysUser对象SysUser sysUser new SysUser() ;sysUser.setUserName(admin);sysUser.setAvatar(https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg);sysUser.setId(1L);// 将数据存储到ThreadLocal中threadLocal.set(sysUser);// 调用show方法,由于show方法main方法使用的是同一个线程因此show方法中可以直接从ThreadLocal中获取数据show() ;}private static void show() {SysUser sysUser threadLocal.get();System.out.println(sysUser);}}1.4 AuthContextUtil
在common-util模块中中创建一个AuthContextUtil类对ThreadLocal进行封装代码如下所示
// com.atguigu.spzx.model.entity.system.SysUser
public class AuthContextUtil {// 创建一个ThreadLocal对象private static final ThreadLocalSysUser threadLocal new ThreadLocal() ;// 定义存储数据的静态方法public static void set(SysUser sysUser) {threadLocal.set(sysUser);}// 定义获取数据的方法public static SysUser get() {return threadLocal.get() ;}// 删除数据的方法public static void remove() {threadLocal.remove();}}1.5 拦截器使用
1.5.1 拦截器开发
在spzx-manager服务中创建一个拦截器代码如下
Component
public class LoginAuthInterceptor implements HandlerInterceptor {Autowiredprivate RedisTemplateString , String redisTemplate ;Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 获取请求方式String method request.getMethod();if(OPTIONS.equals(method)) { // 如果是跨域预检请求直接放行return true ;}// 获取tokenString token request.getHeader(token);if(StrUtil.isEmpty(token)) {responseNoLoginInfo(response) ;return false ;}// 如果token不为空那么此时验证token的合法性String sysUserInfoJson redisTemplate.opsForValue().get(user:login: token);if(StrUtil.isEmpty(sysUserInfoJson)) {responseNoLoginInfo(response) ;return false ;}// 将用户数据存储到ThreadLocal中SysUser sysUser JSON.parseObject(sysUserInfoJson, SysUser.class);AuthContextUtil.set(sysUser);// 重置Redis中的用户数据的有效时间redisTemplate.expire(user:login: token , 30 , TimeUnit.MINUTES) ;// 放行return true ;}//响应208状态码给前端private void responseNoLoginInfo(HttpServletResponse response) {ResultObject result Result.build(null, ResultCodeEnum.LOGIN_AUTH);PrintWriter writer null;response.setCharacterEncoding(UTF-8);//MediaType.APPLICATION_JSON_UTF8_VALUEresponse.setContentType(text/html; charsetutf-8);try {writer response.getWriter();writer.print(JSON.toJSONString(result));} catch (IOException e) {e.printStackTrace();} finally {if (writer ! null) writer.close();}}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {AuthContextUtil.remove(); // 移除threadLocal中的数据}
}1.5.2 拦截器注册
在spzx-manager服务中创建WebMvcConfiguration
想让拦截器生效那么此时就需要将拦截器注册到Spring MVC中具体的代码如下所示
Component
public class WebMvcConfiguration implements WebMvcConfigurer {Autowiredprivate LoginAuthInterceptor loginAuthInterceptor ;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginAuthInterceptor).excludePathPatterns(/admin/system/index/login , /admin/system/index/generateValidateCode).addPathPatterns(/**);}
}使用postman进行测试。
1.6 代码优化
1.6.1 配置优化
关于不需要验证登录的请求url 需要将其定义到对应的配置文件中以提高代码的维护性。
具体步骤
1、application-dev.yml添加如下自定义配置
# 自定义配置
spzx:auth:noAuthUrls:- /admin/system/index/login- /admin/system/index/generateValidateCode2、实体类定义
// com.atguigu.spzx.manager.properties;Data
ConfigurationProperties(prefix spzx.auth) // 前缀不能使用驼峰命名
public class UserAuthProperties {private ListString noAuthUrls ;
}3、启动类添加注解EnableConfigurationProperties
4、配置类代码修改
Component
public class WebMvcConfiguration implements WebMvcConfigurer {Autowiredprivate UserAuthProperties userAuthProperties ; // 注入实体类对象Autowiredprivate LoginAuthInterceptor loginAuthInterceptor ;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginAuthInterceptor).excludePathPatterns(userAuthProperties.getNoAuthUrls()).addPathPatterns(/**);}}注意封装配置文件内容的实体类此时会存在一个警告信息解决方案就是参考官网访问添加一个依赖 1.6.2 代码优化
后端获取用户信息的接口就无需获取token然后根据token从Redis中进行查询。可以直接从ThreadLocal中获取用户信息然后进行返回。
代码如下所示
// com.atguigu.spzx.manager.controller
GetMapping(value /getUserInfo)
public ResultSysUser getUserInfo() {return Result.build(AuthContextUtil.get() , ResultCodeEnum.SUCCESS) ;
}1.6.3 前端修改
更改axios响应拦截器代码如下所示utils\request.js
response { // service.interceptors.response.use第一个参数const res response.dataif (res.code 208) {const redirect encodeURIComponent(window.location.href) // 当前地址栏的urlrouter.push(/login?redirect${redirect})return Promise.reject(new Error(res.message || Error))}return res
}测试通过前端登录成功以后进入首页。删除Redis中的登录用户信息刷新页面此时会跳转到登录页面。
2. API接口文档
2.1 Apifox接口管理平台
2.1.1 接口管理平台简介
在前后端分离的开发模式前端和后端可以进行并行开发。前端不需要依赖于后端后端也不需要依赖前端。在进行并行开发的时候前端和后端都需要遵循接口规范。在进行开发之前需要进行接口设计的【设计接口的请求协议、请求方式、请求路径、请求参数、响应结果】此时就需要使用到接口管理平台进行设计。
常见的接口管理平台Apigee、Kong、YApi、 Apifox
2.1.2 Apifox简介
官网地址https://apifox.com/ Apifox是一款API 文档、API 调试、API Mock、API 自动化测试、API一体化协作平台
2.1.3 Apifox使用
具体步骤如下所示
1、从官网下载Apifox并进行安装 2、使用微信扫描登录
3、创建团队创建项目 4、选择项目定义接口 5、邀请团队成员 2.2 Api文档生成工具
刚才我们是直接在Yapi接口管理平台上进行接口的设计Yapi接口平台也支持导入我们事先生成好的接口文档。要生成接口文档就需要使用到一些接口文档生成工具。
2.2.1 Swagger
Swagger是一种基于OpenAPI规范的API文档生成工具它可以根据Java代码中的注解自动生成API接口文档并提供UI界面进行在线测试和调试。
Swagger为开发人员提供了更加方便、直观的API管理方式有助于提升API的可读性和可维护性。
Swagger的主要特点包括
1、自动生成API文档通过在Java代码中添加Swagger注解Swagger能够自动地解析API接口的参数、响应等信息并生成相应的API文档。
2、在线测试接口Swagger提供了UI界面可以方便地进行API接口的测试和调试无需单独使用HTTP客户端来测试接口。
3、支持多种语言和框架Swagger不仅支持Java语言和Spring框架还支持多种其他语言和框架如PHP、Python、Go等。
4、扩展性强Swagger提供了多种扩展机制和插件可以满足各种项目的需要如集成OAuth2、自定义UI等。
Swagger提欧共的UI界面相比于另外一款Api文档生成工具Knife4j较为简陋。
2.2.2 Knife4j
Knife4j简介
官方文档https://doc.xiaominfo.com/
Knife4j是一种基于Swagger构建的增强工具它在Swagger的基础上增加了更多的功能和扩展提供了更加丰富的API文档管理功能。相比于原版
SwaggerKnife4j的主要特点包括
1、更加美观的UI界面Knife4j通过对Swagger UI的修改和优化实现了更加美观、易用的UI界面提升了开发人员的体验感。
2、支持多种注解配置方式除了支持原版Swagger的注解配置方式外Knife4j还提供了其他几种注解配置方式如ApiIgnore、ApiOperationSupport等方便开发人员进行不同场景下的配置。
3、提供多种插件扩展Knife4j提供了多种插件扩展如knife4j-auth、knife4j-rate-limiter等可以满足不同项目的需求。
4、集成Spring Boot StarterKnife4j发布了spring-boot-starter-knife4j可以实现更加便捷的集成并支持配置文件中的动态属性调整。
Knife4j使用
官方文档使用地址https://doc.xiaominfo.com/docs/quick-start
具体的步骤
1、在spzx-parent项目的pom.xml文件中加入如下依赖
dependencygroupIdcom.github.xiaoymin/groupIdartifactIdknife4j-openapi3-jakarta-spring-boot-starter/artifactIdversion4.1.0/version
/dependencyspzx-model微服务中再次引入knife4j的坐标不需要加入版本号
2、在spzx-manager模块中添加knife4j所需要的配置类
Configuration
public class Knife4jConfig {Beanpublic GroupedOpenApi adminApi() { // 创建了一个api接口的分组return GroupedOpenApi.builder().group(admin-api) // 分组名称.pathsToMatch(/admin/**) // 接口请求路径规则.build();}/**** description 自定义接口信息*/Beanpublic OpenAPI customOpenAPI() {return new OpenAPI().info(new Info().title(尚品甑选API接口文档).version(1.0).description(尚品甑选API接口文档).contact(new Contact().name(atguigu))); // 设定作者}}3、在application.yml文件的spzx.auth.noAuthUrls配置项目中添加knife4j的资源访问地址
spzx:auth:noAuthUrls:- /doc.html- /webjars/css/**- /webjars/js/**- /v3/api-docs/**- /favicon.ico启动项目就可以访问到knife4j所生成的接口文档了。访问地址http://localhost:8501/doc.html 配置抽取
关于上述的Knife4j的配置类最好将其定义到一个公共的模块中【common-service】以实现复用。
步骤
1、将Knife4j的配置类抽取到common-service模块中
2、自定义一个注解封装Import导入的配置类
Retention(value RetentionPolicy.RUNTIME)
Target(value ElementType.TYPE)
Import(value Knife4jConfig.class)
public interface EnableKnife4j {}3、在spzx-manager的启动类上添加EnableKnife4j注解
常见注解
在Knife4j中也提供了一些注解让我们对接口加以说明常见的注解如下所示
Tag 用在controller类上对controller进行说明
Operation: 用在controller接口方法上对接口进行描述
Parameters用在controller接口方法上对单个参数进行描述
Schema 用在实体类和实体类属性上对实体类以及实体类属性进行描述举例说明
Tag(name 首页接口)
public class IndexController {Operation(summary 用户登录)public ResultLoginVo login(RequestBody LoginDto loginDto) {...}Operation(summary 用户退出)Parameters(value {Parameter(name 令牌参数 , required true)})GetMapping(value /logout)public Result logout(RequestHeader(value token) String token) {...}}Data
Schema(description 用户登录请求参数)
public class LoginDto {Schema(description 用户名)private String userName ;Schema(description 密码)private String password ;Schema(description 提交验证码)private String captcha ;Schema(description 验证码key)private String codeKey ;}再次启动服务访问接口文档就可以看到对接口的说明以及对参数的说明 导出导入
Knife4j生成的接口文档是一个在线的接口文档使用起来不是特别的方便当然Knife4j也支持离线接口文档并且支持导出json格式的数据如下所
示 点击OpenAPI那么此时就会将接口信息导出为一个json文件然后我们就可以把这个json文件导入进Apifox管理平台上如下所示 3. 权限管理说明
3.1 权限管理介绍
在后台管理系统中权限管理是指为了保证系统操作的安全性和可控性。对用户的操作权限进行限制和管理。简单的来说就是某一个用户可以使用我们系统的哪些功能。比如管理员可以使用后台管理系统中的所有功能普通业务人员只能使用系统中的一部分的功能(商品管理)。因此权限管理是后台管理系统中的一个重要功能模块。
3.2 表结构介绍
一般来说权限管理包括以下几个方面
1、用户管理通过对用户进行账号、密码、角色等信息的管理。
2、角色管理将多个用户分组并根据所属角色的权限区分用户的访问权限。
3、菜单管理对系统的菜单进行管理根据用户或角色的权限动态生成可访问的菜单列表。
4、日志管理记录系统的操作日志方便用户或管理员查看系统运行情况以及对不当操作进行追踪和处理。
尚品甄选项目后台管理系统的权限管理所涉及到数据库表以及其对应关系如下所示 sql演练
需求1查询id为1的用户所具有的角色数据
select sur.role_id , sr.role_code , sr.role_name from
sys_user_role sur
LEFT JOIN sys_role sr on sr.id sur.role_id
where sur.user_id 1 ;需求2查询id为1的用户所具有的菜单数据
select * from sys_menu sm where sm.id in
(select DISTINCT srm.menu_id from sys_user_role sur LEFT JOIN sys_role sr on sr.id sur.role_idLEFT JOIN sys_role_menu srm on srm.role_id sr.idwhere sur.user_id 1
)4. 角色管理
4.1 菜单添加
关于首页导航菜单我们先在前端页面写死等权限管理中的相关功能都开发完毕以后那么此时在将其更改为动态的。
具体步骤
1、在views目录下创建一个system文件夹
2、在该文件夹下创建3个.vue文件 3、在router/modules目录下创建system.js文件配置路由规则
// 导入组件
const Layout () import(/layout/index.vue)
const sysRole () import(/views/system/sysRole.vue)
const sysUser () import(/views/system/sysUser.vue)
const sysMenu () import(/views/system/sysMenu.vue)// 导出该组件
export default([{path: /system,component: Layout,name: system,meta: {title: 系统管理,},icon: Location,children: [{path: /sysRole,name: sysRole,component: sysRole,meta: {title: 角色管理,},hidden: false},{path: /sysUser,name: sysUser,component: sysUser,meta: {title: 用户管理,},hidden: false},{path: /menu,name: sysMenu,component: sysMenu,meta: {title: 菜单管理,},hidden: false}]}
])4、修改router的index.js导入路由配置
import system from ./modules/system
export const fixedRoutes [...home,...system]4.2 页面制作
对比如下页面结构使用Element Plus制作出对应的页面数据可以暂时使用假数据。 该页面可以将其分为4部分
1、搜索表单
2、添加按钮
3、数据展示表格
4、分页条组件
代码实现如下所示
templatediv classsearch-div!-- 搜索表单 --el-form label-width70px sizesmallel-form-item label角色名称el-inputstylewidth: 100%placeholder角色名称/el-input/el-form-itemel-row styledisplay:flexel-button typeprimary sizesmall搜索/el-buttonel-button sizesmall重置/el-button/el-row/el-form!-- 添加按钮 --div classtools-divel-button typesuccess sizesmall添 加/el-button/div!--- 角色表格数据 --el-table :datalist stylewidth: 100%el-table-column proproleName label角色名称 width180 /el-table-column proproleCode label角色code width180 /el-table-column propcreateTime label创建时间 /el-table-column label操作 aligncenter width280el-button typeprimary sizesmall修改/el-buttonel-button typedanger sizesmall删除/el-button/el-table-column/el-table!--分页条--el-pagination:page-sizes[10, 20, 50, 100]layouttotal, sizes, prev, pager, next:totaltotal//div/templatescript setup
import { ref } from vue;// 分页条总记录数
let total ref(0)// 定义表格数据模型
let list ref([{id:9 , roleName: 系统管理员 , roleCode:xtgly,createTime: 2023-05-09},{id:10 , roleName: 商品管理员 , roleCode:spgly,createTime: 2023-05-09}
])/scriptstyle scoped.search-div {margin-bottom: 10px;padding: 10px;border: 1px solid #ebeef5;border-radius: 3px;background-color: #fff;
}.tools-div {margin: 10px 0;padding: 10px;border: 1px solid #ebeef5;border-radius: 3px;background-color: #fff;
}/style4.3 查询角色
4.3.1 需求说明
需求说明
1、如果在搜索表单中输入和角色名称那么此时就需要按照角色名称进行模糊查询
2、搜索的时候需要进行分页搜索
4.3.2 后端接口
需求分析
1、前端提交请求参数的时候包含了两部分的参数搜索条件参数、分页参数。搜索条件参数可以通过?拼接到请求路径后面分页参数【当前页码、每页显示的数据条数】可以让前端通过请求路径传递过来
2、后端查询完毕以后需要给前端返回一个分页对象分页对象中就封装了分页相关的参数(当前页数据、总记录数、总页数…)
3、前端进行参数传递的时候不一定会传递搜索条件因此sql语句的编写需要使用到动态sql
SysRole
针对当前要操作的数据库表定义一个与之对应的实体类
Data
Schema(description SysRole)
public class SysRole extends BaseEntity {private static final long serialVersionUID 1L;Schema(description 角色名称)private String roleName;Schema(description 角色编码)private String roleCode;Schema(description 描述)private String description;}SysRoleDto
定义一个实体类封装前端传递给后端的条件查询参数
Data
public class SysRoleDto {private String roleName ;
}SysRoleController
表现层代码
RestController
RequestMapping(value /admin/system/sysRole)
public class SysRoleController {Autowiredprivate SysRoleService sysRoleService ;GetMapping(/findByPage/{pageNum}/{pageSize})public ResultPageInfoSysRole findByPage(SysRoleDto sysRoleDto ,PathVariable(value pageNum) Integer pageNum ,PathVariable(value pageSize) Integer pageSize) {PageInfoSysRole pageInfo sysRoleService.findByPage(sysRoleDto , pageNum , pageSize) ;return Result.build(pageInfo , ResultCodeEnum.SUCCESS) ;}}SysRoleService
业务层代码实现
// 业务接口
public interface SysRoleService {public abstract PageInfoSysRole findByPage(SysRoleDto sysRoleDto, Integer pageNum, Integer pageSize);
}// 接口实现类
Service
public class SysRoleServiceImpl implements SysRoleService {Autowiredprivate SysRoleMapper sysRoleMapper ;Overridepublic PageInfoSysRole findByPage(SysRoleDto sysRoleDto, Integer pageNum, Integer pageSize) {PageHelper.startPage(pageNum , pageSize) ;ListSysRole sysRoleList sysRoleMapper.findByPage(sysRoleDto) ;PageInfoSysRole pageInfo new PageInfo(sysRoleList) ;return pageInfo;}
}SysRoleMapper
持久层代码实现
Mapper
public interface SysRoleMapper {public abstract ListSysRole findByPage(SysRoleDto sysRoleDto);
}SysRoleMapper.xml
在映射文件中定义对应的sql语句
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.atguigu.spzx.manager.mapper.SysRoleMapper!-- 映射查询到的字段 --resultMap idsysRoleMap typecom.atguigu.spzx.model.entity.system.SysRole autoMappingtrue/resultMap!-- 用于select查询公用抽取的列 --sql idcolumnsid,role_name,role_code,description,create_time,update_time,is_deleted/sqlsql idfindPageWherewhereif testroleName ! null and roleName ! and role_name like CONCAT(%,#{roleName},%)/ifand is_deleted 0/where/sqlselect idfindByPage resultMapsysRoleMapselect include refidcolumns /from sys_roleinclude refidfindPageWhere/order by id desc/select/mapper注意在BaseEntity的实体类的createTime和updateTime属性上添加**JsonFormat**注解对日期数据进行格式化。
4.3.3 前端对接
实现思路
如下所示
1、定义发送请求方法
2、搜索表单绑定对应数据模型
3、onMounted钩子函数发送请求查询数据
4、分页条绑定数据模型以及对应事件
sysRole.js
在api目录下创建一个sysRole.js文件文件的内容如下所示
import request from /utils/request// 分页查询角色数据
export const GetSysRoleListByPage (pageNum , pageSize , queryDto) {return request({url: /admin/system/sysRole/findByPage/ pageNum / pageSize,method: get,params: queryDto})
}sysRole.vue
更改views/system/sysRole.vue文件
!-- template部分修改内容 --
!-- 搜索表单 --
el-form label-width70px sizesmallel-form-item label角色名称el-inputv-modelqueryDto.roleNamestylewidth: 100%placeholder角色名称/el-input/el-form-itemel-row styledisplay:flexel-button typeprimary sizesmall clicksearchSysRole搜索/el-buttonel-button sizesmall clickresetData重置/el-button/el-row
/el-form!--分页条--
el-paginationv-model:current-pagepageParams.pagev-model:page-sizepageParams.limit:page-sizes[10, 20, 50, 100]size-changefetchDatacurrent-changefetchDatalayouttotal, sizes, prev, pager, next:totaltotal
/!-- script部分修改内容 --
script setup
import { ref , onMounted } from vue;
import { GetSysRoleListByPage } from /api/sysRole;// 分页条总记录数
let total ref(0)// 定义表格数据模型
let list ref([])//分页数据
const pageParamsForm {page: 1, // 页码limit: 10, // 每页记录数
}
const pageParams ref(pageParamsForm) // 将pageParamsForm包装成支持响应式的对象// 搜索表单数据
const queryDto ref({roleName: })// 页面加载完毕以后请求后端接口获取数据
onMounted(() {fetchData() ;
})// 搜索按钮点击事件处理函数
const searchSysRole () {fetchData() ;
}// 搜索按钮点击事件处理函数
const searchSysRole () {queryDto.roleName fetchData() ;
}// 远程调用后端分页查询接口
const fetchData async () {const {data , code , message } await GetSysRoleListByPage(pageParams.value.page , pageParams.value.limit , queryDto) ;list.value data.list ;total.value data.total
}/script4.4 添加角色
4.4.1 需求说明
当用户点击添加按钮的时候那么此时就弹出对话框在该对话框中需要展示添加角色表单。当用户在该表单中点击提交按钮的时候那么此时就需要将表单进行提交在后端需要提交过来的表单数据保存到数据库中即可。页面效果如下所示 4.4.2 页面制作
页面代码如下所示
div classtools-divel-button typesuccess sizesmall clickaddShow添 加/el-button
/div!-- 添加角色表单对话框 --
el-dialog v-modeldialogVisible title添加或修改角色 width30%el-form label-width120pxel-form-item label角色名称el-input //el-form-itemel-form-item label角色Codeel-input //el-form-itemel-form-itemel-button typeprimary 提交/el-buttonel-button clickdialogVisible false取消/el-button/el-form-item/el-form
/el-dialogscript setup// 控制对话是否展示的变量
const dialogVisible ref(false)//进入添加
const addShow () {dialogVisible.value true
}
/script4.4.3 后端接口
后端接收到数据以后将数据保存到数据库中即可不要给前端返回业务数据只需要返回对应的业务状态码即可。
SysRoleController
表现层代码实现
// com.atguigu.spzx.manager.controller.SysRoleController
PostMapping(value /saveSysRole)
public Result saveSysRole(RequestBody SysRole SysRole) {sysRoleService.saveSysRole(SysRole) ;return Result.build(null , ResultCodeEnum.SUCCESS) ;
}SysRoleService
业务层代码实现
// com.atguigu.spzx.manager.service.impl.SysRoleServiceImpl
Override
public void saveSysRole(SysRole sysRole) {sysRoleMapper.saveSysRole(sysRole) ;
}SysRoleMapper
持久层代码实现
// com.atguigu.spzx.manager.mapper.SysRoleMapper
Mapper
public interface SysRoleMapper {public abstract void saveSysRole(SysRole sysRole);
}SysRoleMapper.xml
在映射文件中定义对应的sql语句
!-- 新增角色 --
insert idsaveSysRoleinsert into sys_role (id,role_name,role_code,description) values (#{id},#{roleName},#{roleCode},#{description})
/insert使用postman对后端接口进行测试。
4.4.4 前端对接
实现思路
1、给表单绑定数据模型
2、给提交按钮绑定点击事件
3、点击按钮请求后端地址
sysRole.js
在api目录下创建一个sysRole.js文件文件的内容如下所示
// 添加角色请求方法
export const SavaSysRole (data) {return request({url: /admin/system/sysRole/saveSysRole,method: post,data})
}sysRole.vue
更改views/system/sysRole.vue文件
!-- 页面表单 --
el-dialog v-modeldialogVisible title添加或修改角色 width30%el-form label-width120pxel-form-item label角色名称el-input v-modelsysRole.roleName//el-form-itemel-form-item label角色Codeel-input v-modelsysRole.roleCode//el-form-itemel-form-itemel-button typeprimary clicksubmit提交/el-buttonel-button clickdialogVisible false取消/el-button/el-form-item/el-form
/el-dialogscript setup
import { GetSysRoleListByPage , SaveSysRole} from /api/sysRole;
import { ElMessage } from element-plus// 表单数据模型
const defaultForm {id: ,roleCode: ,roleName:
}
const sysRole ref(defaultForm) // 使用ref包裹该对象使用reactive不方便进行重置// 添加角色
const submit async () {const { code } await SaveSysRole(sysRole.value) ;if(code 200) {dialogVisible.value falseElMessage.success(操作成功)fetchData()}
}
/script4.5 修改角色
4.5.1 需求说明
当用户点击修改按钮的时候那么此时就弹出对话框在该对话框中需要将当前行所对应的角色数据在该表单页面进行展示。当用户在该表单中点击提
交按钮的时候那么此时就需要将表单进行提交在后端需要提交过来的表单数据修改数据库中的即可。页面效果如下所示 4.5.2 数据回显
分析
1、使用添加数据的表单即可
2、要将当前操作行的数据展示在表单中那么此时需要用到插槽
代码如下所示
el-table-column label操作 aligncenter width280 #defaultscopeel-button typeprimary sizesmall clickeditShow(scope.row)修改/el-button
/el-table-columnscript setup// 修改按钮点击事件处理函数const editShow (row) {sysRole.value rowdialogVisible.value true}
/script4.5.3 提交修改
后端接口
SysRoleController
表现层代码实现
// com.atguigu.spzx.manager.controller.SysRoleController
PostMapping(value /updateSysRole)
public Result updateSysRole(RequestBody SysRole sysRole) {sysRoleService.updateSysRole(sysRole) ;return Result.build(null , ResultCodeEnum.SUCCESS) ;
}SysRoleService
业务层代码实现
// com.atguigu.spzx.manager.service.impl.SysRoleServiceImpl
Override
public void updateSysRole(SysRole sysRole) {sysRoleMapper.updateSysRole(sysRole) ;
}SysRoleMapper
持久层代码实现
// com.atguigu.spzx.manager.mapper.SysRoleMapper
Mapper
public interface SysRoleMapper {public abstract void updateSysRole(SysRole sysRole);
}SysRoleMapper.xml
在映射文件中定义对应的sql语句
!-- 修改角色 --
update idupdateSysRoleupdate sys_role setif testroleName ! null and roleName ! role_name #{roleName},/ifif testroleCode ! null and roleCode ! role_code #{roleCode},/ifif testdescription ! null and description ! description #{description},/ifupdate_time now()whereid #{id}
/update前端对接
sysRole.js
在api目录下创建一个sysRole.js文件文件的内容如下所示
// 保存修改
export const UpdateSysRole (data) {return request({url: /admin/system/sysRole/updateSysRole,method: put,data})
}sysRole.vue
更改views/system/sysRole.vue文件
script setup
import { GetSysRoleListByPage , SaveSysRole , UpdateSysRole} from /api/sysRole;// 添加角色
const submit async () {if(!sysRole.value.id) {const { code } await SaveSysRole(sysRole.value) ;if(code 200) {dialogVisible.value falseElMessage.success(操作成功)fetchData()}}else {const { code } await UpdateSysRole(sysRole.value) ;if(code 200) {dialogVisible.value falseElMessage.success(操作成功)fetchData()}}
}
/script4.6 删除角色
4.6.1 需求说明
当点击删除按钮的时候此时需要弹出一个提示框询问是否需要删除数据如果用户点击是那么此时向后端发送请求传递id参数后端接收id参数进
行逻辑删除。页面效果如下所示 4.6.2 后端接口
SysRoleController
表现层代码实现
// com.atguigu.spzx.manager.controller.SysRoleController
DeleteMapping(value /deleteById/{roleId})
public Result deleteById(PathVariable(value roleId) Long roleId) {sysRoleService.deleteById(roleId) ;return Result.build(null , ResultCodeEnum.SUCCESS) ;
}SysRoleService
业务层代码实现
// com.atguigu.spzx.manager.service.impl.SysRoleServiceImpl
Override
public void deleteById(Long roleId) {sysRoleMapper.deleteById(roleId) ;
}SysRoleMapper
持久层代码实现
// com.atguigu.spzx.manager.mapper.SysRoleMapper
Mapper
public interface SysRoleMapper {public abstract void deleteById(Long roleId);
}SysRoleMapper.xml
在映射文件中定义对应的sql语句
!-- 根据id删除角色数据 --
delete iddeleteByIdupdate sys_role set id_delete 0 where id #{value}
/delete4.6.3 前端对接
sysRole.js
在api目录下创建一个sysRole.js文件文件的内容如下所示
// 删除角色
export const DeleteSysRoleById (roleId) {return request({url: /admin/system/sysRole/deleteById/ roleId,method: delete})
}sysRole.vue
更改views/system/sysRole.vue文件
el-table-column label操作 aligncenter width280 #defaultscopeel-button typedanger sizesmall clickdeleteById(scope.row)删除/el-button
/el-table-columnscript setup
import { GetSysRoleListByPage , SaveSysRole , UpdateSysRole , DeleteSysRoleById } from /api/sysRole;
import { ElMessage, ElMessageBox } from element-plus// 删除数据
const deleteById (row) {ElMessageBox.confirm(此操作将永久删除该记录, 是否继续?, Warning, {confirmButtonText: 确定,cancelButtonText: 取消,type: warning,}).then(async () {const {code } await DeleteSysRoleById(row.id)if(code 200) {ElMessage.success(删除成功)fetchData()}}).catch(() {ElMessage.info(取消删除)})
}
/scriptinterface SysRoleMapper { public abstract void deleteById(Long roleId); } #### SysRoleMapper.xml在映射文件中定义对应的sql语句xml
!-- 根据id删除角色数据 --
delete iddeleteByIdupdate sys_role set id_delete 0 where id #{value}
/delete4.6.3 前端对接
sysRole.js
在api目录下创建一个sysRole.js文件文件的内容如下所示
// 删除角色
export const DeleteSysRoleById (roleId) {return request({url: /admin/system/sysRole/deleteById/ roleId,method: delete})
}sysRole.vue
更改views/system/sysRole.vue文件
el-table-column label操作 aligncenter width280 #defaultscopeel-button typedanger sizesmall clickdeleteById(scope.row)删除/el-button
/el-table-columnscript setup
import { GetSysRoleListByPage , SaveSysRole , UpdateSysRole , DeleteSysRoleById } from /api/sysRole;
import { ElMessage, ElMessageBox } from element-plus// 删除数据
const deleteById (row) {ElMessageBox.confirm(此操作将永久删除该记录, 是否继续?, Warning, {confirmButtonText: 确定,cancelButtonText: 取消,type: warning,}).then(async () {const {code } await DeleteSysRoleById(row.id)if(code 200) {ElMessage.success(删除成功)fetchData()}}).catch(() {ElMessage.info(取消删除)})
}
/script