This commit is contained in:
2023-05-19 17:38:09 +08:00
parent e41797c750
commit 3dc6fb7828
77 changed files with 1000 additions and 256 deletions

22
pom.xml
View File

@ -21,7 +21,7 @@
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.11</version>
<!-- 解决子模块继承不到父模块中dependencyManagement中包的version信息 -->
<relativePath />
<relativePath/>
</parent>
<properties>
@ -110,6 +110,16 @@
<artifactId>qiaoba-auth</artifactId>
<version>${qiaoba.version}</version>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-module-system</artifactId>
<version>${qiaoba.version}</version>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-module-file</artifactId>
<version>${qiaoba.version}</version>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-base</artifactId>
@ -130,11 +140,6 @@
<artifactId>qiaoba-api-system</artifactId>
<version>${qiaoba.version}</version>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-module-system</artifactId>
<version>${qiaoba.version}</version>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-doc</artifactId>
@ -150,6 +155,11 @@
<artifactId>qiaoba-common-redis</artifactId>
<version>${qiaoba.version}</version>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-file</artifactId>
<version>${qiaoba.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -14,28 +14,8 @@
<modules>
<module>qiaoba-api-system</module>
<module>qiaoba-api-job</module>
<module>qiaoba-api-file</module>
</modules>
<dependencies>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-datasource</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-doc</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-auth</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-poi</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qiaoba-apis</artifactId>
<groupId>com.qiaoba</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qiaoba-api-file</artifactId>
<dependencies>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-auth</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-doc</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,20 @@
package com.qiaoba.api.file.entity;
import lombok.Data;
import java.io.Serializable;
/**
* 文件
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:43
*/
@Data
public class File implements Serializable {
private static final long serialVersionUID = 1L;
private String url;
}

View File

@ -0,0 +1,29 @@
package com.qiaoba.api.file.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件对外暴露接口
*
* @author ailanyin
* @version 1.0
* @since 2023-04-23 20:33:43
*/
public interface FileApiService {
/**
* 上传文件
*
* @param file file
* @return url
*/
String upload(MultipartFile file);
/**
* 删除文件
*
* @param path 路径
* @return 结果
*/
boolean delete(String path);
}

View File

@ -0,0 +1 @@
null not found

View File

@ -11,5 +11,27 @@
<artifactId>qiaoba-api-system</artifactId>
<dependencies>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-datasource</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-doc</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-auth</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-common-poi</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -34,7 +34,7 @@ public class SysRole extends BaseEntity {
@Excel(name = "岗位序号", width = 20)
private Integer roleSort;
@Excel(name = "数据范围" , width = 20, replace = {"所有数据权限_1" , "自定义数据权限_2" , "本部门数据权限_3" , "本部门及以下数据权限_4" , "仅本人数据权限_5"})
@Excel(name = "数据范围", width = 20, replace = {"所有数据权限_1", "自定义数据权限_2", "本部门数据权限_3", "本部门及以下数据权限_4", "仅本人数据权限_5"})
private String dataScope;
@Excel(name = "状态", width = 20, replace = {"正常_1", "禁用_0"})

View File

@ -1,7 +1,6 @@
package com.qiaoba.api.system.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

View File

@ -2,6 +2,8 @@ package com.qiaoba.api.system.entity.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 用户登录对象
*
@ -10,7 +12,9 @@ import lombok.Data;
* @since 2021/10/15 0015 上午 10:05
*/
@Data
public class LoginDto {
public class LoginDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户名
@ -30,6 +34,6 @@ public class LoginDto {
/**
* 唯一标识
*/
private String uuid = "";
private String uuid;
}

View File

@ -6,17 +6,25 @@ import lombok.Setter;
import java.io.Serializable;
/**
* 更改密码
*
* @author ailanyin
* @version 1.0
* @since 2023/5/10 14:03
*/
@Getter
@Setter
public class ResetPwdDto implements Serializable {
public class ResetPasswordDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private String userId;
/**
* 新密码
*/
private String password;
}

View File

@ -0,0 +1,41 @@
package com.qiaoba.api.system.entity.dto;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
/**
* 更改用户基础信息
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 13:46
*/
@Getter
@Setter
public class ResetUserBasicInfoDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 姓名
*/
private String nickname;
/**
* 手机号
*/
private String phone;
/**
* 邮箱号
*/
private String email;
/**
* 性别
*/
private String gender;
}

View File

@ -6,6 +6,8 @@ import lombok.Setter;
import java.io.Serializable;
/**
* 更改用户状态
*
* @author ailanyin
* @version 1.0
* @since 2023/5/10 14:03
@ -16,7 +18,13 @@ public class ResetUserStatusDto implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private String userId;
/**
* 状态
*/
private String status;
}

View File

@ -1,6 +1,5 @@
package com.qiaoba.api.system.service;
import cn.hutool.core.lang.tree.Tree;
import com.qiaoba.api.system.entity.SysDept;
import com.qiaoba.api.system.entity.param.SysDeptParam;

View File

@ -5,7 +5,6 @@ import com.qiaoba.api.system.entity.param.SysMenuParam;
import com.qiaoba.api.system.entity.vo.SysMenuVo;
import java.util.List;
import java.util.Set;
/**
* 菜单对外暴露接口

View File

@ -1,11 +1,7 @@
package com.qiaoba.api.system.service;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.dto.ResetUserStatusDto;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.api.system.entity.param.SysUserParam;
import com.qiaoba.api.system.entity.vo.SysUserVo;
import java.util.List;
import java.util.Set;
@ -28,6 +24,13 @@ public interface SysUserApiService {
*/
int saveOrUpdate(SysUserDto dto, Boolean isUpdate);
/**
* 检查是否允许新增或修改
*
* @param sysUser sysUser
*/
void checkAddOrUpdate(SysUser sysUser);
/**
* 查询用户
*
@ -45,22 +48,6 @@ public interface SysUserApiService {
*/
SysUser selectByUsername(String username);
/**
* 重置密码
*
* @param dto dto
* @return 结果
*/
int resetPwd(ResetPwdDto dto);
/**
* 更改用户状态
*
* @param dto dto
* @return 结果
*/
int updateUserStatus(ResetUserStatusDto dto);
/**
* 批量删除
*
@ -78,5 +65,11 @@ public interface SysUserApiService {
*/
void handleUserRole(String userId, Set<String> roleIds, boolean isUpdate);
/**
* 用户更改
*
* @param sysUser sysUser
* @return 结果
*/
int updateById(SysUser sysUser);
}

View File

@ -0,0 +1,20 @@
package com.qiaoba.api.system.service;
import org.springframework.security.core.userdetails.UserDetails;
/**
* SysUserDetails 暴露接口
* @author ailanyin
* @version 1.0
* @since 2023/5/19 17:17
*/
public interface SysUserDetailsApiService {
/**
* 查询UserDetails 并缓存到Redis中
*
* @param username username
* @return UserDetails
*/
UserDetails toCache(String username);
}

View File

@ -16,6 +16,10 @@
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-module-system</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-module-file</artifactId>
</dependency>
</dependencies>
<build>

View File

@ -1,11 +1,8 @@
package com.qiaoba.application;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysMenu;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;

View File

@ -1,4 +1,5 @@
qiaoba:
file-upload-path: C:/${spring.application.name}/uploadPath/
datasource:
master:
driver: com.mysql.cj.jdbc.Driver

View File

@ -0,0 +1,44 @@
qiaoba:
file-upload-path: /opt/${spring.application.name}/uploadPath/
datasource:
master:
driver: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root
password: root
pool:
init: 5 #连接池初始化大小
min: 10 #最小空闲连接数
max: 20 #最大连接数
slaves:
- driver: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://121.5.136.69:3306/qiaoba-boot-1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root
password: LpYN7LUoL?l0OSpR2
pool:
init: 5
min: 10
max: 20
weight: 2 #权重 默认 1
is-use: true #是否使用 默认 true
- driver: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/qiaoba-boot?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&allowMultiQueries=true
username: root
password: root
pool:
init: 5
min: 10
max: 20
is-use: false # 不使用该库
mybatis-plus:
configuration:
# 自动驼峰命名规则camel case映射
mapUnderscoreToCamelCase: true
# MyBatis 自动映射策略
# NONE不启用 PARTIAL只对非嵌套 resultMap 自动映射 FULL对所有 resultMap 自动映射
autoMappingBehavior: PARTIAL
# MyBatis 自动映射时未知列或未知属性处理策
# NONE不做处理 WARNING打印相关警告 FAILING抛出异常和详细信息
autoMappingUnknownColumnBehavior: NONE

View File

@ -44,6 +44,9 @@ springdoc:
- group: '系统管理'
paths-to-match: '/**'
packages-to-scan: com.qiaoba.module.system.controller
- group: '文件管理'
paths-to-match: '/**'
packages-to-scan: com.qiaoba.module.file.controller
# knife4j的增强配置不需要增强可以不配
knife4j:
@ -54,7 +57,7 @@ knife4j:
enable-footer-custom: true
footer-custom-content: create by ailanyin
# mybatis-plus:
# mybatis-plus:
# 对应的 XML 文件位置
# mapperLocations: classpath*:mapper/**/*Mapper.xml
# 实体扫描多个package用逗号或者分号分隔

View File

@ -8,6 +8,7 @@ import com.qiaoba.auth.handler.AccessDeniedHandler;
import com.qiaoba.auth.handler.LogoutHandler;
import com.qiaoba.auth.properties.AuthConfigProperties;
import com.qiaoba.auth.utils.TokenUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.redis.service.RedisService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -21,6 +22,7 @@ import org.springframework.security.config.annotation.web.configurers.Expression
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import javax.annotation.PostConstruct;
@ -40,9 +42,9 @@ public class SpringSecurityConfig {
private final AuthConfigProperties authConfigProperties;
private final AccessDeniedHandler accessDeniedHandler;
private final LogoutHandler logoutHandler;
private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
private final RedisService redisService;
private final LogoutHandler logoutHandler;
/**
* 创建Token秘钥
@ -65,7 +67,8 @@ public class SpringSecurityConfig {
for (String url : authConfigProperties.getWhitelist()) {
registry.antMatchers(url).permitAll();
}
// 文件资源 无需鉴权
registry.antMatchers(BaseConstant.RESOURCE_PREFIX + "/**").permitAll();
// 由于使用的是JWT我们这里不需要csrf
httpSecurity.csrf()
.disable()
@ -90,7 +93,7 @@ public class SpringSecurityConfig {
httpSecurity.logout().logoutUrl(SecurityConstant.LOGOUT_URL).logoutSuccessHandler(logoutHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter, LogoutFilter.class);
return httpSecurity.build();
}
}

View File

@ -26,6 +26,7 @@ public class SecurityConstant {
public static final String REGISTER_ON_OFF_KEY = "sys_config:sys.account.registerUser";
public static final String REGISTER_ON = "true";
public static final String REDIS_SECRET_KEY = "sys:secret:secret";
public static final String USER_DETAILS_REDIS_KEY = "user_details:";
/**
* 登录成功
*/
@ -54,7 +55,7 @@ public class SecurityConstant {
* Xss过滤白名单
*/
public final static List<String> XSS_WHITELIST = Arrays.asList(
"/captchaImage" ,
"/captchaImage",
"/login",
"/workflow/process/start",
"/workflow/model/save"
@ -64,8 +65,8 @@ public class SecurityConstant {
* 需要限流的接口
*/
public final static List<String> LIMIT_URI = Arrays.asList(
"/captchaImage" ,
"/login" ,
"/captchaImage",
"/login",
"/register"
);
@ -78,4 +79,5 @@ public class SecurityConstant {
* 同IP每秒最大允许访问次数
*/
public final static Integer MAX_RATE_LIMIT_TOTAL = 5;
}

View File

@ -46,7 +46,7 @@ public class LoginUser implements UserDetails {
/**
* 角色列表
*/
private List<String> roleIds;
private List<String> roleKeys;
/**
@ -58,13 +58,13 @@ public class LoginUser implements UserDetails {
public LoginUser() {
}
public LoginUser(String userId, String deptId, String username, String nickname, List<String> roleIds, Set<String> permissions) {
public LoginUser(String userId, String deptId, String username, String nickname, List<String> roleKeys, Set<String> permissions) {
this.userId = userId;
this.deptId = deptId;
this.username = username;
this.permissions = permissions;
this.nickname = nickname;
this.roleIds = roleIds;
this.roleKeys = roleKeys;
}
public String getUserId() {
@ -84,12 +84,12 @@ public class LoginUser implements UserDetails {
}
public List<String> getRoleIds() {
return roleIds;
public List<String> getRoleKeys() {
return roleKeys;
}
public void setRoleIds(List<String> roleIds) {
this.roleIds = roleIds;
public void setRoleKeys(List<String> roleKeys) {
this.roleKeys = roleKeys;
}
public Set<String> getPermissions() {

View File

@ -0,0 +1,55 @@
package com.qiaoba.auth.entity;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
/**
* @author ailanyin
* @version 1.0
* @since 2023/5/19 16:55
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class SecurityUser implements Serializable {
/**
* 用户ID
*/
private String userId;
/**
* 部门ID
*/
private String deptId;
/**
* 登录账号
*/
private String username;
/**
* 用户名称
*/
private String nickname;
/**
* 角色列表
*/
private List<String> roleKeys;
/**
* 权限列表
*/
private Set<String> permissions;
}

View File

@ -2,7 +2,6 @@ package com.qiaoba.auth.filters;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.auth.constants.SecurityConstant;
import com.qiaoba.auth.properties.AuthConfigProperties;
import com.qiaoba.auth.utils.TokenUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@ -17,7 +16,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
/**
* JwtAuthenticationTokenFilter
@ -31,25 +29,20 @@ import java.util.Objects;
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private final UserDetailsService userDetailsService;
private final AuthConfigProperties authConfigProperties;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
// 鉴权白名单, 放行
if (authConfigProperties.getWhitelist().contains(request.getRequestURI())) {
chain.doFilter(request, response);
return;
}
// 取Header中的Token
String authHeader = request.getHeader(SecurityConstant.TOKEN_HEADER);
if (StrUtil.isNotBlank(authHeader) && authHeader.startsWith(SecurityConstant.TOKEN_HEAD)) {
String authToken = authHeader.substring(SecurityConstant.TOKEN_HEAD.length());
if (TokenUtil.validateToken(authToken)) {
String username = TokenUtil.getUserNameFromToken(authToken);
if (StrUtil.isNotBlank(username) && Objects.isNull(SecurityContextHolder.getContext().getAuthentication())) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);

View File

@ -1,12 +1,16 @@
package com.qiaoba.auth.handler;
import com.qiaoba.auth.entity.LoginUser;
import com.qiaoba.common.redis.service.RedisService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 退出处理器
@ -16,11 +20,15 @@ import javax.servlet.http.HttpServletResponse;
* @since 2022/1/4 0004 下午 16:20
*/
@Component
@RequiredArgsConstructor
public class LogoutHandler implements LogoutSuccessHandler {
private final RedisService redisService;
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse httpServletResponse, Authentication authentication) {
//删除SecurityContext上下文中的信息
SecurityContextHolder.clearContext();
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// 删除缓存中的用户信息
LoginUser user = (LoginUser) authentication.getPrincipal();
redisService.del(user.getUserId());
}
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.HashMap;
import java.util.Map;
@ -23,7 +24,6 @@ public class TokenUtil {
*/
public static String secret;
public static String generateToken(String username) {
DateTime now = DateTime.now();
// 3天过期
@ -38,7 +38,6 @@ public class TokenUtil {
payload.put(JWTPayload.NOT_BEFORE, now);
//载荷
payload.put(JWTPayload.SUBJECT, username);
return JWTUtil.createToken(payload, secret.getBytes());
}

View File

@ -38,4 +38,9 @@ public class BaseConstant {
* https请求
*/
public static final String HTTPS = "https://";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/resource";
}

View File

@ -13,13 +13,13 @@ import lombok.Getter;
public enum BaseEnum {
// 是
YES("1" , ""),
YES("1", ""),
// 否
NO("0" , ""),
NO("0", ""),
// 正常
NORMAL("1" , "正常"),
NORMAL("1", "正常"),
// 不正常
ABNORMAL("0" , "不正常");
ABNORMAL("0", "不正常");
private final String code;
private final String info;

View File

@ -74,7 +74,7 @@ public class AjaxResult extends HashMap<String, Object> {
* @return 成功消息
*/
public static AjaxResult success(Object data) {
return AjaxResult.success("操作成功" , data);
return AjaxResult.success("操作成功", data);
}
/**

View File

@ -31,11 +31,11 @@ public class ObjectUtil {
// 得到此属性的值
Object val = f.get(obj);
// 只要有1个属性不为空,那么就不是所有的属性值都为空
if(val != null) {
if (val != null) {
flag = false;
break;
}
}catch (IllegalAccessException e){
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}

View File

@ -22,7 +22,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* 全局跨域配置
* 多数据源配置
*
* @author ailanyin
* @version 1.0

View File

@ -11,6 +11,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MybatisPlusConfig
*
* @author ailanyin
* @version 1.0
* @since 2023/5/8 11:18

View File

@ -1,11 +1,7 @@
package com.qiaoba.common.database.factories;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.qiaoba.common.database.config.DynamicDataSourceConfig;
import com.qiaoba.common.database.config.DynamicDataSourceContext;
import com.qiaoba.common.database.config.MybatisPlusConfig;
import com.qiaoba.common.database.filters.DynamicDataSourceFilter;
import com.qiaoba.common.database.properties.DefaultDataSourceProperties;
import org.springframework.context.annotation.Bean;

View File

@ -1,14 +1,18 @@
package com.qiaoba.common.database.filters;
import com.qiaoba.common.base.utils.TenantUtil;
import com.qiaoba.common.database.config.DynamicDataSourceContext;
import com.qiaoba.common.database.constants.DynamicDatasourceConstant;
import com.qiaoba.common.base.utils.TenantUtil;
import com.qiaoba.common.web.utils.ResponseUtil;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@ -21,17 +25,18 @@ import java.io.IOException;
*/
@Component
@Order(-10000)
public class DynamicDataSourceFilter implements Filter {
public class DynamicDataSourceFilter extends OncePerRequestFilter {
@Resource
private DynamicDataSourceContext dynamicDataSourceContext;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//设置当前租户对应的数据库
dynamicDataSourceContext.setDataSource(DynamicDatasourceConstant.DEFAULT_MASTER_DATASOURCE_KEY);
// todo
TenantUtil.setTenantId("1");
filterChain.doFilter(servletRequest, servletResponse);
filterChain.doFilter(request, response);
dynamicDataSourceContext.clearDataSource();
TenantUtil.clearTenantId();
}

View File

@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.qiaoba.common.web.utils.BeanCopyUtil;
@ -135,6 +135,7 @@ public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
/**
* 插入或更新
*
* @param entity entity
* @return 结果
*/
@ -144,6 +145,7 @@ public interface BaseMapperPlus<M, T, V> extends BaseMapper<T> {
/**
* 查询Vo by id
*
* @param id 主键
* @return Vo
*/

View File

@ -219,13 +219,13 @@ public class RedisServiceImpl implements RedisService {
@Override
@SuppressWarnings("unchecked")
public <T> T getObject(String key, Class<T> clazz) {
return (T) get(handleKey(key));
return (T) get(key);
}
@Override
@SuppressWarnings("unchecked")
public <T> List<T> getObjectList(String key, Class<T> clazz) {
return (List<T>) get(handleKey(key));
return (List<T>) get(key);
}
private String handleKey(String key) {

View File

@ -1,4 +1,4 @@
package com.qiaoba.application.config;
package com.qiaoba.common.web.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -30,7 +30,7 @@ public class GlobalCorsConfig {
config.setMaxAge(1800L);
// 添加映射路径拦截一切请求
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**" , config);
source.registerCorsConfiguration("/**", config);
// 返回新的CorsFilter
return new CorsFilter(source);
}

View File

@ -1,4 +1,5 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.qiaoba.common.web.advice.ExceptionAdvice
com.qiaoba.common.web.advice.ExceptionAdvice,\
com.qiaoba.common.web.config.GlobalCorsConfig

View File

@ -14,6 +14,7 @@
<modules>
<module>qiaoba-module-system</module>
<module>qiaoba-module-job</module>
<module>qiaoba-module-file</module>
</modules>
</project>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>qiaoba-modules</artifactId>
<groupId>com.qiaoba</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>qiaoba-module-file</artifactId>
<dependencies>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-file</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,33 @@
package com.qiaoba.module.file.config;
import cn.hutool.core.util.URLUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 配置静态文件资源服务器
*
* @author ailanyin
* @version 1.0
* @since 2022/2/28 0028 上午 9:12
*/
@Configuration
@Getter
@Setter
public class FileConfig implements WebMvcConfigurer {
@Value("${qiaoba.file-upload-path}")
private String uploadPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(BaseConstant.RESOURCE_PREFIX + "/**")
.addResourceLocations(URLUtil.FILE_URL_PREFIX + uploadPath);
}
}

View File

@ -0,0 +1,41 @@
package com.qiaoba.module.file.controller;
import com.qiaoba.api.file.entity.File;
import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.module.file.service.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件管理 Web层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:14
*/
@RestController
@RequestMapping("/file")
@RequiredArgsConstructor
@Tag(name = "文件管理")
public class FileController {
private final FileService fileService;
@PostMapping("/upload")
@Operation(summary = "上传文件")
public AjaxResult upload(MultipartFile file) {
AjaxResult ajax = AjaxResult.success();
ajax.put("url", fileService.upload(file));
ajax.put("fileName", file.getOriginalFilename());
return ajax;
}
@DeleteMapping
@Operation(summary = "删除文件")
public AjaxResult remove(@RequestBody File file) {
return fileService.delete(file.getUrl()) ? AjaxResult.success("文件删除成功") : AjaxResult.error("文件删除失败");
}
}

View File

@ -0,0 +1,13 @@
package com.qiaoba.module.file.service;
import com.qiaoba.api.file.service.FileApiService;
/**
* 文件管理 服务层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:15
*/
public interface FileService extends FileApiService {
}

View File

@ -0,0 +1,39 @@
package com.qiaoba.module.file.service.impl;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.module.file.config.FileConfig;
import com.qiaoba.module.file.service.FileService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 文件管理 服务层实现
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 9:15
*/
@Service
@RequiredArgsConstructor
public class FileServiceImpl implements FileService {
private FileConfig fileConfig;
@Override
public String upload(MultipartFile file) {
return com.qiaoba.module.file.utils.FileUtil.upload(file, fileConfig.getUploadPath());
}
@Override
public boolean delete(String path) {
String localPath = fileConfig.getUploadPath() + StrUtil.removePrefix(path, BaseConstant.RESOURCE_PREFIX);
if (FileUtil.isDirectory(localPath)) {
throw new ServiceException("删除路径异常, 请勿非法操作");
}
return FileUtil.del(localPath);
}
}

View File

@ -0,0 +1,130 @@
package com.qiaoba.module.file.utils;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.exceptions.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Date;
/**
* 文件工具类
*
* @author ailanyin
* @version 1.0
* @since 2021/10/25 0025 上午 9:15
*/
public class FileUtil {
private static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件
"rar", "zip", "gz", "bz2",
// 音频
"mp3", "wav", "wma", "mp2", "flac", "midi", "ra", "ape", "aac", "cda", "mov",
// 视频
"mp4", "avi", "rmvb", "blob",
// pdf
"pdf"};
/**
* @param file 上传的文件
* @return 文件全路径名称
*/
public static String upload(MultipartFile file, String path) {
// 获取文件后缀名
String extension = getExtension(file);
// 判断是否允许上传
isAllowedExtension(extension);
// 重命名文件
String fileName = extractFilename(extension);
// 日期 + 格式 分类
String dir = DateUtil.format(new Date(), "yyyy/MM/dd") + "/" + extension + "/";
path = path + dir;
// 新建文件
File newFile = getAbsoluteFile(fileName, path);
try {
file.transferTo(newFile);
return getPathFileName(fileName, path, dir);
} catch (IOException e) {
e.printStackTrace();
throw new ServiceException("文件上传失败, 请联系管理员处理");
}
}
/**
* 判断文件类型是否是允许上传的类型
*
* @param extension 文件类型
*/
private static void isAllowedExtension(String extension) {
boolean flag = true;
for (String str : DEFAULT_ALLOWED_EXTENSION) {
if (str.equalsIgnoreCase(extension)) {
flag = false;
}
}
if (flag) {
throw new ServiceException("不允许上传该文件类型");
}
}
/**
* 获取文件名的后缀
*
* @param file 表单文件
* @return 后缀名
*/
private static String getExtension(MultipartFile file) {
String fileName = file.getOriginalFilename();
if (StrUtil.isBlank(fileName)) {
throw new ServiceException("上传文件-获取文件后缀名失败");
}
return fileName.substring(fileName.lastIndexOf(".") + 1);
}
/**
* 编码文件名(UUID去除-)
*/
private static String extractFilename(String extension) {
return UUID.fastUUID().toString(true) + "." + extension;
}
/**
* 创建文件
*
* @param fileName 文件名
* @return file
*/
private static File getAbsoluteFile(String fileName, String path) {
File desc = new File(path + File.separator + fileName);
if (!desc.exists()) {
if (!desc.getParentFile().exists()) {
boolean result = desc.getParentFile().mkdirs();
if (!result) {
throw new ServiceException("上传文件-创建父目录失败");
}
}
}
return desc;
}
private static String getPathFileName(String fileName, String path, String dir) {
int dirLastIndex = path.length() + 1;
String currentDir = StringUtils.substring(path, dirLastIndex);
return currentDir + BaseConstant.RESOURCE_PREFIX + "/" + dir + fileName;
}
}

View File

@ -0,0 +1,11 @@
{
"groups": [
],
"properties": [
{
"name": "qiaoba.file-upload-path",
"type": "java.lang.String"
}
],
"hints": []
}

View File

@ -0,0 +1 @@
null not found

View File

@ -16,5 +16,9 @@
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-system</artifactId>
</dependency>
<dependency>
<groupId>com.qiaoba</groupId>
<artifactId>qiaoba-api-file</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -29,10 +29,11 @@ public class SysLoginController {
private final SysMenuService sysMenuService;
private final SysLoginService sysLoginService;
@GetMapping("/captchaImage")
public AjaxResult getCaptchaImage() {
return sysLoginService.getCaptchaImage();
AjaxResult result = AjaxResult.success();
result.putAll(sysLoginService.getCaptchaImage());
return result;
}
@PostMapping("/login")
@ -44,21 +45,20 @@ public class SysLoginController {
}
@GetMapping("/getInfo")
public String getInfo() {
List<String> roleIds = SecurityUtil.getLoginUser().getRoleIds();
public AjaxResult getInfo() {
List<String> roles = SecurityUtil.getLoginUser().getRoleKeys();
Set<String> permissions = SecurityUtil.getLoginUser().getPermissions();
AjaxResult ajax = AjaxResult.success();
ajax.put("permissions", permissions);
ajax.put("roles", roleIds);
ajax.put("user",sysLoginService.selectUserFromCache(SecurityUtil.getLoginUserId()));
return "{\"msg\":\"操作成功\",\"code\":200,\"permissions\":[\"*:*:*\"],\"roles\":[\"admin\"],\"user\":{\"createBy\":\"admin\",\"createTime\":\"2023-04-23 16:11:38\",\"updateBy\":null,\"updateTime\":null,\"remark\":\"管理员\",\"userId\":1,\"deptId\":103,\"userName\":\"admin\",\"nickName\":\"若依\",\"email\":\"ry@163.com\",\"phonenumber\":\"15888888888\",\"sex\":\"1\",\"avatar\":\"\",\"password\":\"$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2\",\"status\":\"0\",\"delFlag\":\"0\",\"loginIp\":\"27.154.23.192\",\"loginDate\":\"2023-05-05T09:45:24.000+08:00\",\"dept\":{\"createBy\":null,\"createTime\":null,\"updateBy\":null,\"updateTime\":null,\"remark\":null,\"deptId\":103,\"parentId\":101,\"ancestors\":\"0,100,101\",\"deptName\":\"研发部门\",\"orderNum\":1,\"leader\":\"若依\",\"phone\":null,\"email\":null,\"status\":\"0\",\"delFlag\":null,\"parentName\":null,\"children\":[]},\"roles\":[{\"createBy\":null,\"createTime\":null,\"updateBy\":null,\"updateTime\":null,\"remark\":null,\"roleId\":1,\"roleName\":\"超级管理员\",\"roleKey\":\"admin\",\"roleSort\":1,\"dataScope\":\"1\",\"menuCheckStrictly\":false,\"deptCheckStrictly\":false,\"status\":\"0\",\"delFlag\":null,\"flag\":false,\"menuIds\":null,\"deptIds\":null,\"permissions\":null,\"admin\":true}],\"roleIds\":null,\"postIds\":null,\"roleId\":null,\"admin\":true}}";
ajax.put("roles", roles);
ajax.put("user", SecurityUtil.getLoginUser());
return ajax;
}
@GetMapping("/getRouters")
public Object getRouters() {
List<SysMenuVo> sysMenuVos = sysMenuService.selectByUserId("1650123803828019202");
public AjaxResult getRouters() {
List<SysMenuVo> sysMenuVos = sysMenuService.selectByUserId(SecurityUtil.getLoginUserId());
return AjaxResult.success(sysMenuService.menusToRouters(sysMenuVos));
//return "{\"msg\":\"操作成功\",\"code\":200,\"data\":[{\"name\":\"System\",\"path\":\"/system\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统管理\",\"icon\":\"system\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"User\",\"path\":\"user\",\"hidden\":false,\"component\":\"system/user/index\",\"meta\":{\"title\":\"用户管理\",\"icon\":\"user\",\"noCache\":false,\"link\":null}},{\"name\":\"Role\",\"path\":\"role\",\"hidden\":false,\"component\":\"system/role/index\",\"meta\":{\"title\":\"角色管理\",\"icon\":\"peoples\",\"noCache\":false,\"link\":null}},{\"name\":\"Menu\",\"path\":\"menu\",\"hidden\":false,\"component\":\"system/menu/index\",\"meta\":{\"title\":\"菜单管理\",\"icon\":\"tree-table\",\"noCache\":false,\"link\":null}},{\"name\":\"Dept\",\"path\":\"dept\",\"hidden\":false,\"component\":\"system/dept/index\",\"meta\":{\"title\":\"部门管理\",\"icon\":\"tree\",\"noCache\":false,\"link\":null}},{\"name\":\"Post\",\"path\":\"post\",\"hidden\":false,\"component\":\"system/post/index\",\"meta\":{\"title\":\"岗位管理\",\"icon\":\"post\",\"noCache\":false,\"link\":null}},{\"name\":\"Dict\",\"path\":\"dict\",\"hidden\":false,\"component\":\"system/dict/index\",\"meta\":{\"title\":\"字典管理\",\"icon\":\"dict\",\"noCache\":false,\"link\":null}},{\"name\":\"Config\",\"path\":\"config\",\"hidden\":false,\"component\":\"system/config/index\",\"meta\":{\"title\":\"参数设置\",\"icon\":\"edit\",\"noCache\":false,\"link\":null}},{\"name\":\"Notice\",\"path\":\"notice\",\"hidden\":false,\"component\":\"system/notice/index\",\"meta\":{\"title\":\"通知公告\",\"icon\":\"message\",\"noCache\":false,\"link\":null}},{\"name\":\"Log\",\"path\":\"log\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"ParentView\",\"alwaysShow\":true,\"meta\":{\"title\":\"日志管理\",\"icon\":\"log\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Operlog\",\"path\":\"operlog\",\"hidden\":false,\"component\":\"monitor/operlog/index\",\"meta\":{\"title\":\"操作日志\",\"icon\":\"form\",\"noCache\":false,\"link\":null}},{\"name\":\"Logininfor\",\"path\":\"logininfor\",\"hidden\":false,\"component\":\"monitor/logininfor/index\",\"meta\":{\"title\":\"登录日志\",\"icon\":\"logininfor\",\"noCache\":false,\"link\":null}}]}]},{\"name\":\"Monitor\",\"path\":\"/monitor\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统监控\",\"icon\":\"monitor\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Online\",\"path\":\"online\",\"hidden\":false,\"component\":\"monitor/online/index\",\"meta\":{\"title\":\"在线用户\",\"icon\":\"online\",\"noCache\":false,\"link\":null}},{\"name\":\"Job\",\"path\":\"job\",\"hidden\":false,\"component\":\"monitor/job/index\",\"meta\":{\"title\":\"定时任务\",\"icon\":\"job\",\"noCache\":false,\"link\":null}},{\"name\":\"Druid\",\"path\":\"druid\",\"hidden\":false,\"component\":\"monitor/druid/index\",\"meta\":{\"title\":\"数据监控\",\"icon\":\"druid\",\"noCache\":false,\"link\":null}},{\"name\":\"Server\",\"path\":\"server\",\"hidden\":false,\"component\":\"monitor/server/index\",\"meta\":{\"title\":\"服务监控\",\"icon\":\"server\",\"noCache\":false,\"link\":null}},{\"name\":\"Cache\",\"path\":\"cache\",\"hidden\":false,\"component\":\"monitor/cache/index\",\"meta\":{\"title\":\"缓存监控\",\"icon\":\"redis\",\"noCache\":false,\"link\":null}},{\"name\":\"CacheList\",\"path\":\"cacheList\",\"hidden\":false,\"component\":\"monitor/cache/list\",\"meta\":{\"title\":\"缓存列表\",\"icon\":\"redis-list\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Tool\",\"path\":\"/tool\",\"hidden\":false,\"redirect\":\"noRedirect\",\"component\":\"Layout\",\"alwaysShow\":true,\"meta\":{\"title\":\"系统工具\",\"icon\":\"tool\",\"noCache\":false,\"link\":null},\"children\":[{\"name\":\"Build\",\"path\":\"build\",\"hidden\":false,\"component\":\"tool/build/index\",\"meta\":{\"title\":\"表单构建\",\"icon\":\"build\",\"noCache\":false,\"link\":null}},{\"name\":\"Gen\",\"path\":\"gen\",\"hidden\":false,\"component\":\"tool/gen/index\",\"meta\":{\"title\":\"代码生成\",\"icon\":\"code\",\"noCache\":false,\"link\":null}},{\"name\":\"Swagger\",\"path\":\"swagger\",\"hidden\":false,\"component\":\"tool/swagger/index\",\"meta\":{\"title\":\"系统接口\",\"icon\":\"swagger\",\"noCache\":false,\"link\":null}}]},{\"name\":\"Http://ruoyi.vip\",\"path\":\"http://ruoyi.vip\",\"hidden\":false,\"component\":\"Layout\",\"meta\":{\"title\":\"若依官网\",\"icon\":\"guide\",\"noCache\":false,\"link\":\"http://ruoyi.vip\"}}]}";
}
}

View File

@ -0,0 +1,62 @@
package com.qiaoba.module.system.controller;
import com.qiaoba.api.system.entity.dto.ResetUserBasicInfoDto;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.module.system.service.SysProfileService;
import com.qiaoba.module.system.service.SysUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* 个人信息 Web层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 11:25
*/
@RestController
@RequestMapping("/system/user/profile")
@RequiredArgsConstructor
@Tag(name = "用户管理-个人中心")
public class SysProfileController {
private final SysProfileService sysProfileService;
private final SysUserService sysUserService;
@GetMapping
@Operation(summary = "基本信息")
public AjaxResult profile() {
String username = SecurityUtil.getLoginUserId();
AjaxResult ajax = AjaxResult.success(sysUserService.selectById(username, false));
// todo
ajax.put("roleGroup", "超级管理员,普通角色");
ajax.put("postGroup", "董事长");
return ajax;
}
@PutMapping("/update-avatar")
@Operation(summary = "更改头像")
public AjaxResult updateAvatar(@RequestParam("file") MultipartFile file) {
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", sysProfileService.updateAvatar(file));
return ajax;
}
@PutMapping("/update-password")
@Operation(summary = "更改密码")
public AjaxResult updatePassword(String oldPassword, String newPassword) {
sysProfileService.updatePassword(oldPassword, newPassword);
return AjaxResult.success("密码更改成功");
}
@PutMapping
@Operation(summary = "更改信息")
public AjaxResult updateBasicInfo(@RequestBody ResetUserBasicInfoDto dto) {
sysProfileService.updateBasicInfo(dto);
return AjaxResult.success("基本信息更改成功");
}
}

View File

@ -1,9 +1,10 @@
package com.qiaoba.module.system.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysRole;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.dto.ResetPasswordDto;
import com.qiaoba.api.system.entity.dto.ResetUserStatusDto;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.api.system.entity.param.SysPostParam;
@ -70,15 +71,18 @@ public class SysUserController {
@PreAuthorize("hasAuthority('system:user:resetPwd')")
@PutMapping("/resetPwd")
@Operation(summary = "重置密码")
public AjaxResult resetPwd(@RequestBody ResetPwdDto dto) {
return AjaxResult.toAjax(sysUserService.resetPwd(dto));
public AjaxResult resetPwd(@RequestBody ResetPasswordDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
sysUser.setPassword(SecurityUtil.encryptPassword(dto.getPassword()));
return AjaxResult.toAjax(sysUserService.updateById(sysUser));
}
@PreAuthorize("hasAuthority('system:user:edit')")
@PutMapping("/changeStatus")
@Operation(summary = "更改状态")
public AjaxResult changeStatus(@RequestBody ResetUserStatusDto dto) {
return AjaxResult.toAjax(sysUserService.updateUserStatus(dto));
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
return AjaxResult.toAjax(sysUserService.updateById(sysUser));
}
@PreAuthorize("hasAuthority('system:user:remove')")
@ -154,15 +158,4 @@ public class SysUserController {
return AjaxResult.success();
}
/**
* 个人中心-个人信息
*/
@GetMapping("/profile")
public AjaxResult profile() {
String username = SecurityUtil.getLoginUserId();
AjaxResult ajax = AjaxResult.success(sysUserService.selectById(username, false));
ajax.put("roleGroup", "超级管理员,普通角色");
ajax.put("postGroup", "董事长");
return ajax;
}
}

View File

@ -24,6 +24,15 @@ public interface SysUserRoleMapper extends BaseMapper<SysUserRole> {
*/
List<String> selectRoleIdsByUserId(@Param("userId") String userId, @Param("status") String status);
/**
* 通过userId查询所绑定的角色Key列表
*
* @param userId userId
* @param status 状态
* @return roleIds
*/
List<String> selectRoleKeysByUserId(@Param("userId") String userId, @Param("status") String status);
/**
* 批量取消角色所绑定的用户
*

View File

@ -4,6 +4,8 @@ import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.LoginDto;
import com.qiaoba.common.base.result.AjaxResult;
import java.util.Map;
/**
* 登录 服务层
*
@ -18,7 +20,7 @@ public interface SysLoginService {
*
* @return uuid + base64
*/
AjaxResult getCaptchaImage();
Map<String, Object> getCaptchaImage();
/**
* 登录
@ -28,11 +30,4 @@ public interface SysLoginService {
*/
String login(LoginDto dto);
/**
* 从缓存中读取user
*
* @param userId userId
* @return SysUser
*/
SysUser selectUserFromCache(String userId);
}

View File

@ -1,7 +1,6 @@
package com.qiaoba.module.system.service;
import cn.hutool.core.lang.tree.Tree;
import com.qiaoba.api.system.entity.SysMenu;
import com.qiaoba.api.system.entity.vo.RouterVo;
import com.qiaoba.api.system.entity.vo.SysMenuVo;
import com.qiaoba.api.system.service.SysMenuApiService;
@ -37,6 +36,7 @@ public interface SysMenuService extends SysMenuApiService {
/**
* 通过 userId 查询目录和菜单
*
* @param userId userId
* @return list
*/

View File

@ -1,11 +1,8 @@
package com.qiaoba.module.system.service;
import com.qiaoba.api.system.entity.SysPost;
import com.qiaoba.api.system.entity.SysRole;
import com.qiaoba.api.system.entity.param.SysPostParam;
import com.qiaoba.api.system.entity.param.SysRoleParam;
import com.qiaoba.api.system.service.SysPostApiService;
import com.qiaoba.api.system.service.SysRoleApiService;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;

View File

@ -0,0 +1,37 @@
package com.qiaoba.module.system.service;
import com.qiaoba.api.system.entity.dto.ResetUserBasicInfoDto;
import org.springframework.web.multipart.MultipartFile;
/**
* 个人信息 服务层
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 11:28
*/
public interface SysProfileService {
/**
* 更新个人头像
*
* @param file file
* @return 头像链接
*/
String updateAvatar(MultipartFile file);
/**
* 更改密码
*
* @param oldPassword 旧密码
* @param newPassword 新密码
*/
void updatePassword(String oldPassword, String newPassword);
/**
* 更改基本信息
*
* @param dto dto
*/
void updateBasicInfo(ResetUserBasicInfoDto dto);
}

View File

@ -51,6 +51,15 @@ public interface SysUserRoleService {
*/
List<String> selectRoleIdsByUserId(String userId, String status);
/**
* 通过userId查询所绑定的角色Key列表
*
* @param userId userId
* @param status 状态
* @return roleIds
*/
List<String> selectRoleKeysByUserId(String userId, String status);
/**
* 批量选择用户授权
*

View File

@ -1,7 +1,6 @@
package com.qiaoba.module.system.service;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.param.SysUserParam;
import com.qiaoba.api.system.entity.vo.SysUserVo;
import com.qiaoba.api.system.service.SysUserApiService;

View File

@ -3,25 +3,26 @@ package com.qiaoba.module.system.service.impl;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.LoginDto;
import com.qiaoba.api.system.service.SysUserDetailsApiService;
import com.qiaoba.auth.constants.SecurityConstant;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.auth.utils.TokenUtil;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.base.result.AjaxResult;
import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.service.SysLoginService;
import com.qiaoba.module.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 登录 服务层实现
@ -36,24 +37,26 @@ public class SysLoginServiceImpl implements SysLoginService {
private final RedisService redisService;
private final HttpServletRequest request;
private final UserDetailsService userDetailsService;
private final SysUserDetailsApiService userDetailsService;
private final SysUserService sysUserService;
@Override
public AjaxResult getCaptchaImage() {
AjaxResult ajax = AjaxResult.success();
ajax.put("register", getRegisterConfig());
public Map<String, Object> getCaptchaImage() {
Map<String, Object> map = new HashMap<String, Object>(4);
map.put("register", getRegisterConfig());
if (!getCaptchaConfig()) {
ajax.put("captchaEnabled", false);
return ajax;
map.put("captchaEnabled", false);
return map;
}
String uuid = UUID.randomUUID().toString(true);
LineCaptcha captcha = CaptchaUtil.createLineCaptcha(150, 50, 4, 20);
ajax.put("uuid", uuid);
ajax.put("img", captcha.getImageBase64());
map.put("uuid", uuid);
map.put("img", captcha.getImageBase64());
redisService.set(SecurityConstant.CAPTCHA_KEY + uuid, captcha.getCode(), 120);
return ajax;
return map;
}
@Override
@ -67,27 +70,15 @@ public class SysLoginServiceImpl implements SysLoginService {
// 检验密码
validatePassword(dto.getUsername(), sysUser.getPassword(), dto.getPassword());
// 缓存user
addUserToCache(sysUser);
// 创建UserDetails
UserDetails userDetails = userDetailsService.loadUserByUsername(dto.getUsername());
userDetailsService.toCache(sysUser.getUsername());
// 生成Token
return TokenUtil.generateToken(userDetails.getUsername());
}
@Override
public SysUser selectUserFromCache(String userId) {
return redisService.getObject(userId, SysUser.class);
}
private void addUserToCache(SysUser sysUser) {
sysUser.setPassword(null);
redisService.set(sysUser.getUserId(), sysUser);
return TokenUtil.generateToken(sysUser.getUsername());
}
private void validatePassword(String username, String password, String inputPassword) {
boolean result = SecurityUtil.matchesPassword(inputPassword, password);
if (!result) {
beforePasswordError(username);
ThreadUtil.execAsync(() -> beforePasswordError(username));
throw new ServiceException(SecurityConstant.PASSWORD_ERROR);
}
}
@ -105,7 +96,7 @@ public class SysLoginServiceImpl implements SysLoginService {
}
private boolean getCaptchaConfig() {
return false;
return true;
/* try {
return SecurityConstant.CAPTCHA_ON.equals(redisService.get(SecurityConstant.CAPTCHA_ON_OFF_KEY));
} catch (Exception e) {
@ -114,7 +105,7 @@ public class SysLoginServiceImpl implements SysLoginService {
}
private boolean getRegisterConfig() {
return false;
return true;
/* try {
return SecurityConstant.REGISTER_ON.equals(redisService.get(SecurityConstant.REGISTER_ON_OFF_KEY));
} catch (Exception e) {

View File

@ -5,10 +5,10 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiaoba.api.system.entity.SysPost;
import com.qiaoba.api.system.entity.param.SysPostParam;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.module.system.mapper.SysPostMapper;
import com.qiaoba.module.system.service.SysPostService;
import com.qiaoba.module.system.service.SysUserPostService;

View File

@ -0,0 +1,62 @@
package com.qiaoba.module.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.qiaoba.api.file.service.FileApiService;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.ResetUserBasicInfoDto;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.module.system.service.SysProfileService;
import com.qiaoba.module.system.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 个人信息 服务层实现
*
* @author ailanyin
* @version 1.0
* @since 2023/5/19 11:29
*/
@Service
@RequiredArgsConstructor
public class SysProfileServiceImpl implements SysProfileService {
private final FileApiService fileService;
private final SysUserService sysUserService;
@Override
public String updateAvatar(MultipartFile file) {
String url = fileService.upload(file);
SysUser sysUser = new SysUser();
sysUser.setUserId(SecurityUtil.getLoginUserId());
sysUser.setAvatar(url);
if (sysUserService.updateById(sysUser) == 0) {
fileService.delete(url);
throw new ServiceException("修改头像失败");
}
return url;
}
@Override
public void updatePassword(String oldPassword, String newPassword) {
String userId = SecurityUtil.getLoginUserId();
String password = sysUserService.selectById(userId, true).getPassword();
if (!SecurityUtil.matchesPassword(oldPassword, password)) {
throw new ServiceException("旧密码错误, 请重新输入");
}
SysUser sysUser = new SysUser();
sysUser.setUserId(SecurityUtil.getLoginUserId());
sysUser.setPassword(SecurityUtil.encryptPassword(newPassword));
sysUserService.updateById(sysUser);
}
@Override
public void updateBasicInfo(ResetUserBasicInfoDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
sysUser.setUserId(SecurityUtil.getLoginUserId());
sysUserService.checkAddOrUpdate(sysUser);
sysUserService.updateById(sysUser);
}
}

View File

@ -10,10 +10,10 @@ import com.qiaoba.api.system.entity.SysRoleMenu;
import com.qiaoba.api.system.entity.dto.DataScopeDto;
import com.qiaoba.api.system.entity.dto.SysRoleDto;
import com.qiaoba.api.system.entity.param.SysRoleParam;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.module.system.mapper.SysRoleMapper;
import com.qiaoba.module.system.service.SysRoleDeptService;
import com.qiaoba.module.system.service.SysRoleMenuService;

View File

@ -3,10 +3,9 @@ package com.qiaoba.module.system.service.impl;
import com.qiaoba.api.system.entity.SysTenant;
import com.qiaoba.module.system.mapper.SysTenantMapper;
import com.qiaoba.module.system.service.SysTenantService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 租户管理 业务层实现
*
@ -15,18 +14,18 @@ import javax.annotation.Resource;
* @since 2023-04-24 19:46:00
*/
@Service
@RequiredArgsConstructor
public class SysTenantServiceImpl implements SysTenantService {
@Resource
private SysTenantMapper baseMapper;
private final SysTenantMapper sysTenantMapper;
@Override
public int insert(SysTenant sysTenant) {
return baseMapper.insert(sysTenant);
return sysTenantMapper.insert(sysTenant);
}
@Override
public int update(SysTenant sysTenant) {
return baseMapper.updateById(sysTenant);
return sysTenantMapper.updateById(sysTenant);
}
}

View File

@ -1,9 +1,14 @@
package com.qiaoba.module.system.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.service.SysUserDetailsApiService;
import com.qiaoba.auth.constants.SecurityConstant;
import com.qiaoba.auth.entity.LoginUser;
import com.qiaoba.auth.entity.SecurityUser;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.redis.service.RedisService;
import com.qiaoba.module.system.service.SysMenuService;
import com.qiaoba.module.system.service.SysUserRoleService;
import com.qiaoba.module.system.service.SysUserService;
@ -25,23 +30,36 @@ import java.util.Set;
*/
@Service
@RequiredArgsConstructor
public class SysUserDetailsServiceImpl implements UserDetailsService {
public class SysUserDetailsServiceImpl implements UserDetailsService, SysUserDetailsApiService {
private final SysUserService sysUserService;
private final SysMenuService sysMenuService;
private final SysUserRoleService sysUserRoleService;
private final RedisService redisService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SysUser user = sysUserService.selectByUsername(username);
return createUserDetails(user);
if (redisService.hasKey(SecurityConstant.USER_DETAILS_REDIS_KEY + username)) {
SecurityUser user = redisService.getObject(SecurityConstant.USER_DETAILS_REDIS_KEY + username, SecurityUser.class);
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), user.getRoleKeys(), user.getPermissions());
}
return toCache(username);
}
private UserDetails createUserDetails(SysUser user) {
Set<String> perms = sysMenuService.selectPermsByUserId(user.getUserId());
List<String> roleIds = sysUserRoleService.selectRoleIdsByUserId(user.getUserId(), BaseEnum.NORMAL.getCode());
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roleIds, perms);
List<String> roleKeys = sysUserRoleService.selectRoleKeysByUserId(user.getUserId(), BaseEnum.NORMAL.getCode());
return new LoginUser(user.getUserId(), user.getDeptId(), user.getUsername(), user.getNickname(), roleKeys, perms);
}
@Override
public UserDetails toCache(String username) {
SysUser user = sysUserService.selectByUsername(username);
UserDetails details = createUserDetails(user);
SecurityUser securityUser = BeanUtil.copyProperties(details, SecurityUser.class);
redisService.set(SecurityConstant.USER_DETAILS_REDIS_KEY + username, securityUser);
return details;
}
}

View File

@ -2,16 +2,14 @@ package com.qiaoba.module.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.constants.BaseConstant;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.base.utils.ObjectUtil;
import com.qiaoba.module.system.service.SysUserImportService;
import com.qiaoba.module.system.service.SysUserService;
import com.qiaoba.module.system.templates.SysUserImport;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -27,7 +25,7 @@ import java.util.stream.Collectors;
* @since 2023/5/18 14:50
*/
@Service
@AllArgsConstructor
@RequiredArgsConstructor
public class SysUserImportServiceImpl implements SysUserImportService {
private final SysUserService sysUserService;

View File

@ -49,6 +49,11 @@ public class SysUserRoleServiceImpl implements SysUserRoleService {
return sysUserRoleMapper.selectRoleIdsByUserId(userId, status);
}
@Override
public List<String> selectRoleKeysByUserId(String userId, String status) {
return sysUserRoleMapper.selectRoleKeysByUserId(userId, status);
}
@Override
public void insertAuthUsers(String roleId, List<String> userIds) {
List<SysUserRole> list = new ArrayList<>();

View File

@ -9,13 +9,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qiaoba.api.system.entity.SysUser;
import com.qiaoba.api.system.entity.SysUserPost;
import com.qiaoba.api.system.entity.SysUserRole;
import com.qiaoba.api.system.entity.dto.ResetPwdDto;
import com.qiaoba.api.system.entity.dto.ResetUserStatusDto;
import com.qiaoba.api.system.entity.dto.SysUserDto;
import com.qiaoba.api.system.entity.param.SysUserParam;
import com.qiaoba.api.system.entity.vo.SysUserVo;
import com.qiaoba.auth.utils.SecurityUtil;
import com.qiaoba.common.base.enums.BaseEnum;
import com.qiaoba.common.base.exceptions.ServiceException;
import com.qiaoba.common.database.entity.PageQuery;
import com.qiaoba.common.database.entity.TableDataInfo;
@ -83,18 +80,6 @@ public class SysUserServiceImpl implements SysUserService {
return sysUserMapper.selectOne(wrapper);
}
@Override
public int resetPwd(ResetPwdDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
sysUser.setPassword(SecurityUtil.encryptPassword(dto.getPassword()));
return sysUserMapper.updateById(sysUser);
}
@Override
public int updateUserStatus(ResetUserStatusDto dto) {
SysUser sysUser = BeanUtil.copyProperties(dto, SysUser.class);
return sysUserMapper.updateById(sysUser);
}
@Override
@Transactional(rollbackFor = Exception.class)
@ -150,6 +135,11 @@ public class SysUserServiceImpl implements SysUserService {
sysUserRoleService.insertBatch(list);
}
@Override
public int updateById(SysUser sysUser) {
return sysUserMapper.updateById(sysUser);
}
@Override
public List<SysUserExport> selectExportData(SysUserParam param) {
List<SysUserExport> list = sysUserMapper.selectExportData(param);
@ -188,15 +178,16 @@ public class SysUserServiceImpl implements SysUserService {
return sysUser;
}
private void checkAddOrUpdate(SysUser sysUser) {
if (checkUsernameNotUnique(sysUser)) {
throw new ServiceException(StrUtil.format("新增或修改用户'{}'失败,登录账号已存在", sysUser.getUsername()));
@Override
public void checkAddOrUpdate(SysUser sysUser) {
if (StrUtil.isNotBlank(sysUser.getUsername()) && checkUsernameNotUnique(sysUser)) {
throw new ServiceException("登录账号已存在");
}
if (StrUtil.isNotBlank(sysUser.getPhone()) && checkPhoneNotUnique(sysUser)) {
throw new ServiceException(StrUtil.format("新增或修改用户'{}'失败,手机号已存在", sysUser.getUsername()));
throw new ServiceException("手机号已存在");
}
if (StrUtil.isNotBlank(sysUser.getEmail()) && checkEmailNotUnique(sysUser)) {
throw new ServiceException(StrUtil.format("新增或修改用户'{}'失败,邮箱号已存在", sysUser.getUsername()));
throw new ServiceException("邮箱号已存在");
}
}

View File

@ -3,9 +3,6 @@ package com.qiaoba.module.system.templates;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
import java.util.Date;
import java.util.List;
/**
* 用户导入模板
*

View File

@ -73,7 +73,8 @@
</select>
<select id="selectExportData" resultMap="ExportData">
select t1.user_id, t1.username, t1.nickname, t1.email, t1.phone, t1.gender, t1.status,t1.create_time, t2.dept_name,t4.role_name,t6.post_name
select t1.user_id, t1.username, t1.nickname, t1.email, t1.phone, t1.gender, t1.status,t1.create_time,
t2.dept_name,t4.role_name,t6.post_name
from sys_user t1
left join sys_dept t2 on t1.dept_id = t2.dept_id
left join sys_user_role t3 on t1.user_id = t3.user_id
@ -124,13 +125,15 @@
</select>
<select id="selectUnAllocatedList" resultMap="SysUserVoResult">
select distinct t1.user_id, t2.dept_name, t1.username, t1.nickname, t1.email, t1.phone, t1.status, t1.create_time
select distinct t1.user_id, t2.dept_name, t1.username, t1.nickname, t1.email, t1.phone, t1.status,
t1.create_time
from sys_user t1
left join sys_dept t2 on t1.dept_id = t2.dept_id
left join sys_user_role t3 on t1.user_id = t3.user_id
left join sys_role t4 on t4.role_id = t3.role_id
where (t4.role_id != #{param.roleId} or t4.role_id IS NULL)
and t1.user_id not in (select t1.user_id from sys_user t1 inner join sys_user_role t3 on t1.user_id = t3.user_id and
and t1.user_id not in (select t1.user_id from sys_user t1 inner join sys_user_role t3 on t1.user_id = t3.user_id
and
t3.role_id = #{param.roleId})
<if test="param.username != null and param.username != ''">
AND t1.username like concat('%', #{param.username}, '%')

View File

@ -13,6 +13,15 @@
</if>
</select>
<select id="selectRoleKeysByUserId" resultType="string">
select t2.role_key from sys_user_role t1
left join sys_role t2 on t2.role_id = t1.role_id
where t1.user_id = #{userId}
<if test="status != null and status != ''">
and t2.status = #{status}
</if>
</select>
<delete id="deleteByRoleIdAndUserIds">
delete from sys_user_role where role_id = #{roleId} and user_id in
<foreach collection="list" item="userId" open="(" separator="," close=")">