refactor(system): 重构系统模块控制器代码结构

- 解决所有接口分页异常
- 剥离控制器校验逻辑
- 解决循环依赖问题
- 解决角色赋权后,权限回显不正确
This commit is contained in:
2025-12-30 12:51:31 +08:00
parent 79b847f9a4
commit 377b0989f8
77 changed files with 4471 additions and 4235 deletions
@@ -15,38 +15,17 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.odboy.annotation.AnonymousPostMapping; import cn.odboy.annotation.AnonymousPostMapping;
import cn.odboy.constant.CaptchaCodeEnum;
import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.model.SystemUserInfoVo; import cn.odboy.system.dal.model.SystemUserInfoVo;
import cn.odboy.system.dal.model.SystemUserJwtVo;
import cn.odboy.system.dal.model.SystemUserLoginArgs; import cn.odboy.system.dal.model.SystemUserLoginArgs;
import cn.odboy.system.dal.redis.SystemCacheKey; import cn.odboy.system.service.SystemAuthService;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.framework.permission.core.handler.TokenProvider;
import cn.odboy.system.framework.permission.core.handler.UserDetailsHandler;
import cn.odboy.util.KitRsaEncryptUtil;
import com.wf.captcha.base.Captcha;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@@ -62,92 +41,35 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "系统:系统授权接口") @Api(tags = "系统:系统授权接口")
public class SystemAuthController { public class SystemAuthController {
@Autowired private KitRedisHelper redisHelper; @Autowired
@Autowired private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO; private SystemAuthService systemAuthService;
@Autowired private TokenProvider tokenProvider;
@Autowired private AppProperties properties;
@Autowired private PasswordEncoder passwordEncoder;
@Autowired private UserDetailsHandler userDetailsService;
@ApiOperation("登录授权") @ApiOperation("登录授权")
@AnonymousPostMapping(value = "/login") @AnonymousPostMapping(value = "/login")
public ResponseEntity<Map<String, Object>> login(@Validated @RequestBody SystemUserLoginArgs loginRequest, public ResponseEntity<Map<String, Object>> login(@Validated @RequestBody SystemUserLoginArgs loginRequest,
HttpServletRequest request) throws Exception { HttpServletRequest request) throws Exception {
// 密码解密 Map<String, Object> loginInfo = systemAuthService.doLogin(loginRequest, request);
String password = return ResponseEntity.ok(loginInfo);
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginRequest.getPassword()); }
// 查询验证码
String code = redisHelper.get(loginRequest.getUuid(), String.class);
// 清除验证码
redisHelper.del(loginRequest.getUuid());
if (StrUtil.isBlank(code)) {
throw new BadRequestException("验证码不存在或已过期");
}
if (StrUtil.isBlank(loginRequest.getCode()) || !loginRequest.getCode().equalsIgnoreCase(code)) {
throw new BadRequestException("验证码错误");
}
// 获取用户信息
SystemUserJwtVo jwtUser = userDetailsService.loadUserByUsername(loginRequest.getUsername());
// 验证用户密码
if (!passwordEncoder.matches(password, jwtUser.getPassword())) {
throw new BadRequestException("登录密码错误");
}
Authentication authentication =
new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成令牌
String token = tokenProvider.createToken(jwtUser);
// 返回 token 与 用户信息
Map<String, Object> authInfo = new HashMap<>(2) {{
put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token));
put("user", BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class));
}};
if (properties.getLogin().isSingle()) {
// 踢掉之前已经登录的token
systemUserOnlineInfoDAO.kickOutByUsername(loginRequest.getUsername());
}
// 保存在线信息
systemUserOnlineInfoDAO.saveUserJwtModelByToken(jwtUser, token, request);
// 返回登录信息
return ResponseEntity.ok(authInfo);
}
@ApiOperation("获取用户信息") @ApiOperation("获取用户信息")
@PostMapping(value = "/info") @PostMapping(value = "/info")
public ResponseEntity<SystemUserInfoVo> getUserInfo() { public ResponseEntity<SystemUserInfoVo> getUserInfo() {
SystemUserJwtVo jwtUser = (SystemUserJwtVo)KitSecurityHelper.getCurrentUser(); SystemUserInfoVo userInfoVo = systemAuthService.getCurrentUserInfoVo();
SystemUserInfoVo userInfoVo = BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class); return ResponseEntity.ok(userInfoVo);
return ResponseEntity.ok(userInfoVo); }
}
@ApiOperation("获取验证码") @ApiOperation("获取验证码")
@AnonymousPostMapping(value = "/captcha/getImage") @AnonymousPostMapping(value = "/captcha/getImage")
public ResponseEntity<Map<String, Object>> getCode() { public ResponseEntity<Map<String, Object>> getCode() {
// 获取运算的结果 Map<String, Object> imgResult = systemAuthService.getCaptchaInfo();
Captcha captcha = properties.getLogin().getCaptchaSetting().getCaptcha(); return ResponseEntity.ok(imgResult);
String uuid = SystemCacheKey.CAPTCHA_LOGIN + IdUtil.simpleUUID(); }
//当验证码类型为 arithmetic时且长度 >= 2 时, captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text();
if (captcha.getCharType() - 1 == CaptchaCodeEnum.ARITHMETIC.ordinal() &&
captchaValue.contains(SystemConst.SYMBOL_DOT)) {
captchaValue = captchaValue.split("\\.")[0];
}
// 保存
redisHelper.set(uuid, captchaValue, properties.getLogin().getCaptchaSetting().getExpiration(),
TimeUnit.MINUTES);
// 验证码信息
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
put("img", captcha.toBase64());
put("uuid", uuid);
}};
return ResponseEntity.ok(imgResult);
}
@ApiOperation("退出登录") @ApiOperation("退出登录")
@AnonymousPostMapping(value = "/logout") @AnonymousPostMapping(value = "/logout")
public ResponseEntity<Void> logout(HttpServletRequest request) { public ResponseEntity<Void> logout(HttpServletRequest request) {
String token = tokenProvider.getToken(request); systemAuthService.doLogout(request);
systemUserOnlineInfoDAO.logoutByToken(token); return ResponseEntity.ok(null);
return ResponseEntity.ok(null); }
}
} }
@@ -15,7 +15,6 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.constant.SystemCaptchaBizEnum; import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.model.SystemCheckEmailCaptchaArgs; import cn.odboy.system.dal.model.SystemCheckEmailCaptchaArgs;
import cn.odboy.system.service.SystemEmailService; import cn.odboy.system.service.SystemEmailService;
@@ -35,30 +34,27 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "系统:验证码管理") @Api(tags = "系统:验证码管理")
public class SystemCaptchaController { public class SystemCaptchaController {
@Autowired private SystemEmailService systemEmailService; @Autowired
private SystemEmailService systemEmailService;
@ApiOperation("重置邮箱, 发送验证码") @ApiOperation("重置邮箱, 发送验证码")
@PostMapping(value = "/sendResetEmailCaptcha") @PostMapping(value = "/sendResetEmailCaptcha")
public ResponseEntity<Void> sendResetEmailCaptcha(@RequestParam String email) { public ResponseEntity<Void> sendResetEmailCaptcha(@RequestParam String email) {
systemEmailService.sendCaptcha(SystemCaptchaBizEnum.EMAIL_RESET_EMAIL_CODE, email); systemEmailService.sendCaptcha(SystemCaptchaBizEnum.EMAIL_RESET_EMAIL_CODE, email);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("重置密码,发送验证码") @ApiOperation("重置密码,发送验证码")
@PostMapping(value = "/sendResetPasswordCaptcha") @PostMapping(value = "/sendResetPasswordCaptcha")
public ResponseEntity<Void> sendResetPasswordCaptcha(@RequestParam String email) { public ResponseEntity<Void> sendResetPasswordCaptcha(@RequestParam String email) {
systemEmailService.sendCaptcha(SystemCaptchaBizEnum.EMAIL_RESET_PWD_CODE, email); systemEmailService.sendCaptcha(SystemCaptchaBizEnum.EMAIL_RESET_PWD_CODE, email);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("验证码验证") @ApiOperation("验证码验证")
@PostMapping(value = "/checkEmailCaptcha") @PostMapping(value = "/checkEmailCaptcha")
public ResponseEntity<Void> checkEmailCaptcha(@Validated @RequestBody SystemCheckEmailCaptchaArgs args) { public ResponseEntity<Void> checkEmailCaptcha(@Validated @RequestBody SystemCheckEmailCaptchaArgs args) {
SystemCaptchaBizEnum biEnum = SystemCaptchaBizEnum.getByBizCode(args.getBizCode()); systemEmailService.checkEmailCaptcha(args);
if (biEnum == null) { return ResponseEntity.ok(null);
throw new BadRequestException("不支持的业务"); }
}
systemEmailService.checkEmailCaptcha(biEnum, args.getEmail(), args.getCode());
return ResponseEntity.ok(null);
}
} }
@@ -30,19 +30,20 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/component") @RequestMapping("/api/component")
public class SystemComponentController { public class SystemComponentController {
@Autowired private SystemDeptService systemDeptService; @Autowired
private SystemDeptService systemDeptService;
@ApiOperation("查询部门下拉选择数据源") @ApiOperation("查询部门下拉选择数据源")
@PostMapping(value = "/queryDeptSelectDataSource") @PostMapping(value = "/queryDeptSelectDataSource")
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public ResponseEntity<?> queryDeptSelectDataSource() { public ResponseEntity<?> queryDeptSelectDataSource() {
return ResponseEntity.ok(systemDeptService.queryDeptSelectDataSource()); return ResponseEntity.ok(systemDeptService.queryDeptSelectDataSource());
} }
@ApiOperation("查询部门下拉选择Pro数据源") @ApiOperation("查询部门下拉选择Pro数据源")
@PostMapping(value = "/queryDeptSelectProDataSource") @PostMapping(value = "/queryDeptSelectProDataSource")
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public ResponseEntity<?> queryDeptSelectProDataSource() { public ResponseEntity<?> queryDeptSelectProDataSource() {
return ResponseEntity.ok(systemDeptService.queryDeptSelectProDataSource()); return ResponseEntity.ok(systemDeptService.queryDeptSelectProDataSource());
} }
} }
@@ -24,9 +24,9 @@ import cn.odboy.system.service.SystemDeptService;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -43,58 +43,54 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/dept") @RequestMapping("/api/dept")
public class SystemDeptController { public class SystemDeptController {
@Autowired private SystemDeptService systemDeptService; @Autowired
private SystemDeptService systemDeptService;
@ApiOperation("导出部门数据") @ApiOperation("导出部门数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('dept:list')") @PreAuthorize("@el.check('dept:list')")
public void exportDept(HttpServletResponse response, SystemQueryDeptArgs args) throws Exception { public void exportDept(HttpServletResponse response, SystemQueryDeptArgs args) throws Exception {
systemDeptService.exportDeptExcel(systemDeptService.queryAllDeptByArgs(args, false), response); systemDeptService.exportDeptExcel(systemDeptService.queryAllDeptByArgs(args, false), response);
} }
@ApiOperation("查询部门") @ApiOperation("查询部门")
@PostMapping @PostMapping
@PreAuthorize("@el.check('user:list','dept:list')") @PreAuthorize("@el.check('user:list','dept:list')")
public ResponseEntity<KitPageResult<SystemDeptTb>> queryDept( public ResponseEntity<KitPageResult<SystemDeptTb>> queryDept(
@Validated @RequestBody KitPageArgs<SystemQueryDeptArgs> pageArgs) throws Exception { @Validated @RequestBody KitPageArgs<SystemQueryDeptArgs> pageArgs) throws Exception {
SystemQueryDeptArgs args = pageArgs.getArgs(); List<SystemDeptTb> depts = systemDeptService.queryAllDeptByArgs(pageArgs.getArgs(), true);
List<SystemDeptTb> depts = systemDeptService.queryAllDeptByArgs(args, true); return ResponseEntity.ok(KitPageUtil.toPage(depts));
return ResponseEntity.ok(KitPageUtil.toPage(depts)); }
}
@ApiOperation("查询部门:根据ID获取同级与上级数据") @ApiOperation("查询部门:根据ID获取同级与上级数据")
@PostMapping("/queryDeptSuperiorTree") @PostMapping("/queryDeptSuperiorTree")
@PreAuthorize("@el.check('user:list','dept:list')") @PreAuthorize("@el.check('user:list','dept:list')")
public ResponseEntity<KitPageResult<SystemDeptTb>> queryDeptSuperiorTree(@RequestBody List<Long> ids, public ResponseEntity<KitPageResult<SystemDeptTb>> queryDeptSuperiorTree(@RequestBody List<Long> ids,
@RequestParam(defaultValue = "false") Boolean exclude) { @RequestParam(defaultValue = "false") Boolean exclude) {
return ResponseEntity.ok(systemDeptService.searchDeptTree(ids, exclude)); return ResponseEntity.ok(systemDeptService.searchDeptTree(ids, exclude));
} }
@ApiOperation("新增部门") @ApiOperation("新增部门")
@PostMapping(value = "/saveDept") @PostMapping(value = "/saveDept")
@PreAuthorize("@el.check('dept:add')") @PreAuthorize("@el.check('dept:add')")
public ResponseEntity<Void> saveDept(@Validated @RequestBody SystemCreateDeptArgs args) { public ResponseEntity<Void> saveDept(@Validated @RequestBody SystemCreateDeptArgs args) {
systemDeptService.saveDept(args); systemDeptService.saveDept(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改部门") @ApiOperation("修改部门")
@PostMapping(value = "/modifyDept") @PostMapping(value = "/modifyDept")
@PreAuthorize("@el.check('dept:edit')") @PreAuthorize("@el.check('dept:edit')")
public ResponseEntity<Void> modifyDept(@Validated(SystemDeptTb.Update.class) @RequestBody SystemDeptTb args) { public ResponseEntity<Void> modifyDept(@Validated(SystemDeptTb.Update.class) @RequestBody SystemDeptTb args) {
systemDeptService.updateDept(args); systemDeptService.updateDept(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("删除部门") @ApiOperation("删除部门")
@PostMapping(value = "/removeDeptByIds") @PostMapping(value = "/removeDeptByIds")
@PreAuthorize("@el.check('dept:del')") @PreAuthorize("@el.check('dept:del')")
public ResponseEntity<Void> removeDeptByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeDeptByIds(@RequestBody Set<Long> ids) {
// 获取部门, 和其所有子部门 systemDeptService.deleteDeptByIds(ids);
Set<SystemDeptTb> depts = systemDeptService.traverseDeptByIdWithPids(ids); return ResponseEntity.ok(null);
// 验证是否被角色或用户关联 }
systemDeptService.verifyBindRelationByIds(depts);
systemDeptService.deleteDeptByIds(depts);
return ResponseEntity.ok(null);
}
} }
@@ -24,10 +24,10 @@ import cn.odboy.system.service.SystemDictService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -43,53 +43,53 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/dict") @RequestMapping("/api/dict")
public class SystemDictController { public class SystemDictController {
@Autowired private SystemDictService systemDictService; @Autowired
private SystemDictService systemDictService;
@ApiOperation("导出字典数据") @ApiOperation("导出字典数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('dict:list')") @PreAuthorize("@el.check('dict:list')")
public void exportDict(HttpServletResponse response, SystemQueryDictArgs args) throws IOException { public void exportDict(HttpServletResponse response, SystemQueryDictArgs args) throws IOException {
systemDictService.exportDictExcel(systemDictService.queryDictByArgs(args), response); systemDictService.exportDictExcel(systemDictService.queryDictByArgs(args), response);
} }
@ApiOperation("查询字典") @ApiOperation("查询字典")
@PostMapping(value = "/queryAllDict") @PostMapping(value = "/queryAllDict")
@PreAuthorize("@el.check('dict:list')") @PreAuthorize("@el.check('dict:list')")
public ResponseEntity<List<SystemDictTb>> queryAllDict() { public ResponseEntity<List<SystemDictTb>> queryAllDict() {
return ResponseEntity.ok(systemDictService.queryDictByArgs(new SystemQueryDictArgs())); return ResponseEntity.ok(systemDictService.queryDictByArgs(new SystemQueryDictArgs()));
} }
@ApiOperation("查询字典") @ApiOperation("查询字典")
@PostMapping @PostMapping
@PreAuthorize("@el.check('dict:list')") @PreAuthorize("@el.check('dict:list')")
public ResponseEntity<KitPageResult<SystemDictTb>> queryDictByArgs( public ResponseEntity<KitPageResult<SystemDictTb>> queryDictByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryDictArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryDictArgs> pageArgs) {
Page<SystemDictTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize()); Page<SystemDictTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
SystemQueryDictArgs args = pageArgs.getArgs(); return ResponseEntity.ok(systemDictService.searchDict(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemDictService.searchDict(args, page)); }
}
@ApiOperation("新增字典") @ApiOperation("新增字典")
@PostMapping(value = "/saveDict") @PostMapping(value = "/saveDict")
@PreAuthorize("@el.check('dict:add')") @PreAuthorize("@el.check('dict:add')")
public ResponseEntity<Void> saveDict(@Validated @RequestBody SystemCreateDictArgs args) { public ResponseEntity<Void> saveDict(@Validated @RequestBody SystemCreateDictArgs args) {
systemDictService.saveDict(args); systemDictService.saveDict(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改字典") @ApiOperation("修改字典")
@PostMapping(value = "/modifyDictById") @PostMapping(value = "/modifyDictById")
@PreAuthorize("@el.check('dict:edit')") @PreAuthorize("@el.check('dict:edit')")
public ResponseEntity<Void> modifyDictById(@Validated(SystemDictTb.Update.class) @RequestBody SystemDictTb args) { public ResponseEntity<Void> modifyDictById(@Validated(SystemDictTb.Update.class) @RequestBody SystemDictTb args) {
systemDictService.updateDictById(args); systemDictService.updateDictById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("删除字典") @ApiOperation("删除字典")
@PostMapping(value = "/removeDictByIds") @PostMapping(value = "/removeDictByIds")
@PreAuthorize("@el.check('dict:del')") @PreAuthorize("@el.check('dict:del')")
public ResponseEntity<Void> removeDictByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeDictByIds(@RequestBody Set<Long> ids) {
systemDictService.deleteDictByIds(ids); systemDictService.deleteDictByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -25,7 +25,6 @@ import cn.odboy.system.service.SystemDictDetailService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -44,57 +43,53 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/dictDetail") @RequestMapping("/api/dictDetail")
public class SystemDictDetailController { public class SystemDictDetailController {
@Autowired private SystemDictDetailService systemDictDetailService; @Autowired
private SystemDictDetailService systemDictDetailService;
@ApiOperation("查询字典详情") @ApiOperation("查询字典详情")
@PostMapping @PostMapping
public ResponseEntity<KitPageResult<SystemDictDetailVo>> queryDictDetailByCrud( public ResponseEntity<KitPageResult<SystemDictDetailVo>> queryDictDetailByCrud(
@Validated @RequestBody KitPageArgs<SystemQueryDictDetailArgs> args) { @Validated @RequestBody KitPageArgs<SystemQueryDictDetailArgs> args) {
return queryDictDetailByArgs(args); return queryDictDetailByArgs(args);
} }
@ApiOperation("查询字典详情") @ApiOperation("查询字典详情")
@PostMapping(value = "/queryDictDetailByArgs") @PostMapping(value = "/queryDictDetailByArgs")
public ResponseEntity<KitPageResult<SystemDictDetailVo>> queryDictDetailByArgs( public ResponseEntity<KitPageResult<SystemDictDetailVo>> queryDictDetailByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryDictDetailArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryDictDetailArgs> pageArgs) {
SystemQueryDictDetailArgs args = pageArgs.getArgs(); Page<SystemDictDetailTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemDictDetailTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize()); return ResponseEntity.ok(systemDictDetailService.searchDictDetail(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemDictDetailService.searchDictDetail(args, page)); }
}
@ApiOperation("查询多个字典详情") @ApiOperation("查询多个字典详情")
@GetMapping(value = "/getDictDetailMaps") @GetMapping(value = "/getDictDetailMaps")
public ResponseEntity<Map<String, List<SystemDictDetailVo>>> getDictDetailMaps(@RequestParam String dictName) { public ResponseEntity<Map<String, List<SystemDictDetailVo>>> getDictDetailMaps(@RequestParam String dictName) {
String[] names = dictName.split("[,, ]"); Map<String, List<SystemDictDetailVo>> dictMap = systemDictDetailService.getDictDetailMap(dictName);
Map<String, List<SystemDictDetailVo>> dictMap = new HashMap<>(16); return ResponseEntity.ok(dictMap);
for (String name : names) { }
dictMap.put(name, systemDictDetailService.listDictDetailByName(name));
}
return ResponseEntity.ok(dictMap);
}
@ApiOperation("新增字典详情") @ApiOperation("新增字典详情")
@PostMapping(value = "/saveDictDetail") @PostMapping(value = "/saveDictDetail")
@PreAuthorize("@el.check('dict:add')") @PreAuthorize("@el.check('dict:add')")
public ResponseEntity<Void> saveDictDetail(@Validated @RequestBody SystemCreateDictDetailArgs args) { public ResponseEntity<Void> saveDictDetail(@Validated @RequestBody SystemCreateDictDetailArgs args) {
systemDictDetailService.saveDictDetail(args); systemDictDetailService.saveDictDetail(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改字典详情") @ApiOperation("修改字典详情")
@PostMapping(value = "/modifyDictDetailById") @PostMapping(value = "/modifyDictDetailById")
@PreAuthorize("@el.check('dict:edit')") @PreAuthorize("@el.check('dict:edit')")
public ResponseEntity<Void> modifyDictDetailById( public ResponseEntity<Void> modifyDictDetailById(
@Validated(SystemDictDetailTb.Update.class) @RequestBody SystemDictDetailTb args) { @Validated(SystemDictDetailTb.Update.class) @RequestBody SystemDictDetailTb args) {
systemDictDetailService.updateDictDetailById(args); systemDictDetailService.updateDictDetailById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("删除字典详情") @ApiOperation("删除字典详情")
@PostMapping(value = "/removeDictDetailById") @PostMapping(value = "/removeDictDetailById")
@PreAuthorize("@el.check('dict:del')") @PreAuthorize("@el.check('dict:del')")
public ResponseEntity<Void> removeDictDetailById(@RequestBody SystemDictDetailTb args) { public ResponseEntity<Void> removeDictDetailById(@RequestBody SystemDictDetailTb args) {
systemDictDetailService.deleteDictDetailById(args.getId()); systemDictDetailService.deleteDictDetailById(args.getId());
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -36,26 +36,27 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "工具:邮件管理") @Api(tags = "工具:邮件管理")
public class SystemEmailController { public class SystemEmailController {
@Autowired private SystemEmailService systemEmailService; @Autowired
private SystemEmailService systemEmailService;
@ApiOperation("查询配置") @ApiOperation("查询配置")
@PostMapping(value = "/getLastEmailConfig") @PostMapping(value = "/getLastEmailConfig")
public ResponseEntity<SystemEmailConfigTb> getLastEmailConfig() { public ResponseEntity<SystemEmailConfigTb> getLastEmailConfig() {
return ResponseEntity.ok(systemEmailService.getLastEmailConfig()); return ResponseEntity.ok(systemEmailService.getLastEmailConfig());
} }
@ApiOperation("配置邮件") @ApiOperation("配置邮件")
@PostMapping(value = "/modifyEmailConfig") @PostMapping(value = "/modifyEmailConfig")
public ResponseEntity<Void> modifyEmailConfig(@Validated @RequestBody SystemEmailConfigTb emailConfig) public ResponseEntity<Void> modifyEmailConfig(@Validated @RequestBody SystemEmailConfigTb emailConfig)
throws Exception { throws Exception {
systemEmailService.updateEmailConfigById(emailConfig); systemEmailService.updateEmailConfigById(emailConfig);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("发送邮件") @ApiOperation("发送邮件")
@PostMapping(value = "/sendEmail") @PostMapping(value = "/sendEmail")
public ResponseEntity<Void> sendEmail(@Validated @RequestBody SystemSendEmailArgs sendEmailRequest) { public ResponseEntity<Void> sendEmail(@Validated @RequestBody SystemSendEmailArgs sendEmailRequest) {
systemEmailService.sendEmail(sendEmailRequest); systemEmailService.sendEmail(sendEmailRequest);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -24,9 +24,9 @@ import cn.odboy.system.service.SystemJobService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -42,56 +42,54 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/job") @RequestMapping("/api/job")
public class SystemJobController { public class SystemJobController {
@Autowired private SystemJobService systemJobService; @Autowired
private SystemJobService systemJobService;
@ApiOperation("导出岗位数据") @ApiOperation("导出岗位数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('job:list')") @PreAuthorize("@el.check('job:list')")
public void exportJob(HttpServletResponse response, SystemQueryJobArgs args) throws IOException { public void exportJob(HttpServletResponse response, SystemQueryJobArgs args) throws IOException {
systemJobService.exportJobExcel(systemJobService.queryJobByArgs(args), response); systemJobService.exportJobExcel(systemJobService.queryJobByArgs(args), response);
} }
@ApiOperation("查询岗位") @ApiOperation("查询岗位")
@PostMapping(value = "/queryAllEnableJob") @PostMapping(value = "/queryAllEnableJob")
@PreAuthorize("@el.check('job:list','user:list')") @PreAuthorize("@el.check('job:list','user:list')")
public ResponseEntity<KitPageResult<SystemJobTb>> queryJobByArgs( public ResponseEntity<KitPageResult<SystemJobTb>> queryJobByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryJobArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryJobArgs> pageArgs) {
SystemQueryJobArgs args = pageArgs.getArgs(); Page<SystemJobTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemJobTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemJobService.searchJobByArgs(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemJobService.searchJobByArgs(args, page)); }
}
@ApiOperation("查询岗位") @ApiOperation("查询岗位")
@PostMapping @PostMapping
@PreAuthorize("@el.check('job:list','user:list')") @PreAuthorize("@el.check('job:list','user:list')")
public ResponseEntity<KitPageResult<SystemJobTb>> queryJobByCrud( public ResponseEntity<KitPageResult<SystemJobTb>> queryJobByCrud(
@Validated @RequestBody KitPageArgs<SystemQueryJobArgs> args) { @Validated @RequestBody KitPageArgs<SystemQueryJobArgs> args) {
return queryJobByArgs(args); return queryJobByArgs(args);
} }
@ApiOperation("新增岗位") @ApiOperation("新增岗位")
@PostMapping(value = "/saveJob") @PostMapping(value = "/saveJob")
@PreAuthorize("@el.check('job:add')") @PreAuthorize("@el.check('job:add')")
public ResponseEntity<Void> saveJob(@Validated @RequestBody SystemCreateJobArgs args) { public ResponseEntity<Void> saveJob(@Validated @RequestBody SystemCreateJobArgs args) {
systemJobService.saveJob(args); systemJobService.saveJob(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改岗位") @ApiOperation("修改岗位")
@PostMapping(value = "/modifyJobById") @PostMapping(value = "/modifyJobById")
@PreAuthorize("@el.check('job:edit')") @PreAuthorize("@el.check('job:edit')")
public ResponseEntity<Void> modifyJobById(@Validated(SystemJobTb.Update.class) @RequestBody SystemJobTb args) { public ResponseEntity<Void> modifyJobById(@Validated(SystemJobTb.Update.class) @RequestBody SystemJobTb args) {
systemJobService.updateJobById(args); systemJobService.updateJobById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("删除岗位") @ApiOperation("删除岗位")
@PostMapping(value = "/removeJobByIds") @PostMapping(value = "/removeJobByIds")
@PreAuthorize("@el.check('job:del')") @PreAuthorize("@el.check('job:del')")
public ResponseEntity<Void> removeJobByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeJobByIds(@RequestBody Set<Long> ids) {
// 验证是否被用户关联 systemJobService.deleteJobByIds(ids);
systemJobService.verifyBindRelationByIds(ids); return ResponseEntity.ok(null);
systemJobService.deleteJobByIds(ids); }
return ResponseEntity.ok(null);
}
} }
@@ -17,17 +17,14 @@ package cn.odboy.system.controller;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.constant.FileTypeEnum;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemLocalStorageTb; import cn.odboy.system.dal.dataobject.SystemLocalStorageTb;
import cn.odboy.system.dal.model.SystemQueryStorageArgs; import cn.odboy.system.dal.model.SystemQueryStorageArgs;
import cn.odboy.system.service.SystemLocalStorageService; import cn.odboy.system.service.SystemLocalStorageService;
import cn.odboy.util.KitFileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -45,57 +42,52 @@ import org.springframework.web.multipart.MultipartFile;
@RequestMapping("/api/localStorage") @RequestMapping("/api/localStorage")
public class SystemLocalStorageController { public class SystemLocalStorageController {
@Autowired private SystemLocalStorageService localStorageService; @Autowired
private SystemLocalStorageService localStorageService;
@ApiOperation("查询文件") @ApiOperation("查询文件")
@PostMapping @PostMapping
@PreAuthorize("@el.check('storage:list')") @PreAuthorize("@el.check('storage:list')")
public ResponseEntity<KitPageResult<SystemLocalStorageTb>> queryLocalStorage( public ResponseEntity<KitPageResult<SystemLocalStorageTb>> queryLocalStorage(
@Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) {
SystemQueryStorageArgs args = pageArgs.getArgs(); Page<SystemLocalStorageTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemLocalStorageTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(localStorageService.searchLocalStorage(pageArgs.getArgs(), page));
return ResponseEntity.ok(localStorageService.searchLocalStorage(args, page)); }
}
@ApiOperation("导出数据") @ApiOperation("导出数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('storage:list')") @PreAuthorize("@el.check('storage:list')")
public void exportFile(HttpServletResponse response, SystemQueryStorageArgs args) throws IOException { public void exportFile(HttpServletResponse response, SystemQueryStorageArgs args) throws IOException {
localStorageService.exportLocalStorageExcel(localStorageService.queryLocalStorageByArgs(args), response); localStorageService.exportLocalStorageExcel(localStorageService.queryLocalStorageByArgs(args), response);
} }
@ApiOperation("上传文件") @ApiOperation("上传文件")
@PostMapping(value = "/uploadFile") @PostMapping(value = "/uploadFile")
@PreAuthorize("@el.check('storage:add')") @PreAuthorize("@el.check('storage:add')")
public ResponseEntity<Void> uploadFile(@RequestParam String name, @RequestParam("file") MultipartFile file) { public ResponseEntity<Void> uploadFile(@RequestParam String name, @RequestParam("file") MultipartFile file) {
localStorageService.uploadFile(name, file); localStorageService.uploadFile(name, file);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("上传图片") @ApiOperation("上传图片")
@PostMapping("/uploadPicture") @PostMapping("/uploadPicture")
public ResponseEntity<SystemLocalStorageTb> uploadPicture(@RequestParam MultipartFile file) { public ResponseEntity<SystemLocalStorageTb> uploadPicture(@RequestParam MultipartFile file) {
// 判断文件是否为图片 SystemLocalStorageTb localStorage = localStorageService.uploadPictureV1(file);
String suffix = KitFileUtil.getSuffix(file.getOriginalFilename()); return ResponseEntity.ok(localStorage);
if (!FileTypeEnum.IMAGE.getCode().equals(KitFileUtil.getFileType(suffix))) { }
throw new BadRequestException("只能上传图片");
}
SystemLocalStorageTb localStorage = localStorageService.uploadFile(null, file);
return ResponseEntity.ok(localStorage);
}
@ApiOperation("修改文件") @ApiOperation("修改文件")
@PostMapping(value = "/modifyLocalStorageById") @PostMapping(value = "/modifyLocalStorageById")
@PreAuthorize("@el.check('storage:edit')") @PreAuthorize("@el.check('storage:edit')")
public ResponseEntity<Void> modifyLocalStorageById(@Validated @RequestBody SystemLocalStorageTb args) { public ResponseEntity<Void> modifyLocalStorageById(@Validated @RequestBody SystemLocalStorageTb args) {
localStorageService.updateLocalStorageById(args); localStorageService.updateLocalStorageById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("多选删除") @ApiOperation("多选删除")
@PostMapping(value = "/removeFileByIds") @PostMapping(value = "/removeFileByIds")
public ResponseEntity<Void> deleteFileByIds(@RequestBody Long[] ids) { public ResponseEntity<Void> deleteFileByIds(@RequestBody Long[] ids) {
localStorageService.deleteFileByIds(ids); localStorageService.deleteFileByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -15,7 +15,6 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
@@ -23,18 +22,13 @@ import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.model.SystemMenuVo; import cn.odboy.system.dal.model.SystemMenuVo;
import cn.odboy.system.dal.model.SystemQueryMenuArgs; import cn.odboy.system.dal.model.SystemQueryMenuArgs;
import cn.odboy.system.dal.mysql.SystemMenuMapper; import cn.odboy.system.dal.mysql.SystemMenuMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.service.SystemMenuService; import cn.odboy.system.service.SystemMenuService;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -51,108 +45,90 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/menu") @RequestMapping("/api/menu")
public class SystemMenuController { public class SystemMenuController {
@Autowired private SystemMenuService systemMenuService; @Autowired
@Autowired private SystemMenuMapper systemMenuMapper; private SystemMenuService systemMenuService;
@Autowired
private SystemMenuMapper systemMenuMapper;
@ApiOperation("导出菜单数据") @ApiOperation("导出菜单数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('menu:list')") @PreAuthorize("@el.check('menu:list')")
public void exportMenu(HttpServletResponse response, SystemQueryMenuArgs args) throws Exception { public void exportMenu(HttpServletResponse response, SystemQueryMenuArgs args) throws Exception {
systemMenuService.exportMenuExcel(systemMenuService.queryAllMenu(args, false), response); systemMenuService.exportMenuExcel(systemMenuService.queryAllMenu(args, false), response);
} }
@PostMapping(value = "/buildMenus") @PostMapping(value = "/buildMenus")
@ApiOperation("获取前端所需菜单") @ApiOperation("获取前端所需菜单")
public ResponseEntity<List<SystemMenuVo>> buildMenus() { public ResponseEntity<List<SystemMenuVo>> buildMenus() {
List<SystemMenuTb> menuList = systemMenuService.listMenuByUserId(KitSecurityHelper.getCurrentUserId()); List<SystemMenuVo> systemMenuVos = systemMenuService.buildFrontMenus();
List<SystemMenuTb> menus = systemMenuService.buildMenuTree(menuList); return ResponseEntity.ok(systemMenuVos);
return ResponseEntity.ok(systemMenuService.buildMenuVo(menus)); }
}
@ApiOperation("返回全部的菜单") @ApiOperation("返回全部的菜单")
@PostMapping(value = "/queryMenuListByPid") @PostMapping(value = "/queryMenuListByPid")
@PreAuthorize("@el.check('menu:list','roles:list')") @PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity<List<SystemMenuTb>> queryMenuListByPid(@RequestParam Long pid) { public ResponseEntity<List<SystemMenuTb>> queryMenuListByPid(@RequestParam Long pid) {
return ResponseEntity.ok(systemMenuService.listMenuByPid(pid)); List<SystemMenuTb> systemMenuTbs = systemMenuService.listMenuByPid(pid);
} return ResponseEntity.ok(systemMenuTbs);
}
@ApiOperation("根据菜单ID返回所有子节点ID, 包含自身ID") @ApiOperation("根据菜单ID返回所有子节点ID, 包含自身ID")
@PostMapping(value = "/queryChildMenuSet") @PostMapping(value = "/queryChildMenuSet")
@PreAuthorize("@el.check('menu:list','roles:list')") @PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity<Set<Long>> queryChildMenuSet(@RequestParam Long id) { public ResponseEntity<Set<Long>> queryChildMenuSet(@RequestParam Long id) {
Set<SystemMenuTb> menuSet = new HashSet<>(); Set<Long> ids = systemMenuService.listChildMenuSetByMenuId(id);
List<SystemMenuTb> menuList = systemMenuService.listMenuByPid(id); return ResponseEntity.ok(ids);
menuSet.add(systemMenuMapper.selectById(id)); }
menuSet = systemMenuService.queryChildMenuByArgs(menuList, menuSet);
Set<Long> ids = menuSet.stream().map(SystemMenuTb::getId).collect(Collectors.toSet());
return ResponseEntity.ok(ids);
}
@PostMapping @PostMapping
@ApiOperation("查询菜单") @ApiOperation("查询菜单")
@PreAuthorize("@el.check('menu:list')") @PreAuthorize("@el.check('menu:list')")
public ResponseEntity<KitPageResult<SystemMenuTb>> queryAllMenuByCrud( public ResponseEntity<KitPageResult<SystemMenuTb>> queryAllMenuByCrud(
@Validated @RequestBody KitPageArgs<SystemQueryMenuArgs> args) throws Exception { @Validated @RequestBody KitPageArgs<SystemQueryMenuArgs> args) throws Exception {
return queryAllMenu(args); return queryAllMenu(args);
} }
@PostMapping(value = "/queryMenuByArgs") @PostMapping(value = "/queryMenuByArgs")
@ApiOperation("查询菜单") @ApiOperation("查询菜单")
@PreAuthorize("@el.check('menu:list')") @PreAuthorize("@el.check('menu:list')")
public ResponseEntity<KitPageResult<SystemMenuTb>> queryAllMenu( public ResponseEntity<KitPageResult<SystemMenuTb>> queryAllMenu(
@Validated @RequestBody KitPageArgs<SystemQueryMenuArgs> pageArgs) throws Exception { @Validated @RequestBody KitPageArgs<SystemQueryMenuArgs> pageArgs) throws Exception {
SystemQueryMenuArgs args = pageArgs.getArgs(); List<SystemMenuTb> menuList = systemMenuService.queryAllMenu(pageArgs.getArgs(), true);
List<SystemMenuTb> menuList = systemMenuService.queryAllMenu(args, true); return ResponseEntity.ok(KitPageUtil.toPage(menuList));
return ResponseEntity.ok(KitPageUtil.toPage(menuList)); }
}
@ApiOperation("查询菜单:根据ID获取同级与上级数据") @ApiOperation("查询菜单:根据ID获取同级与上级数据")
@PostMapping("/queryMenuSuperior") @PostMapping("/queryMenuSuperior")
@PreAuthorize("@el.check('menu:list')") @PreAuthorize("@el.check('menu:list')")
public ResponseEntity<List<SystemMenuTb>> queryMenuSuperior(@RequestBody List<Long> ids) { public ResponseEntity<List<SystemMenuTb>> queryMenuSuperior(@RequestBody List<Long> ids) {
Set<SystemMenuTb> menus; List<SystemMenuTb> systemMenuTbs = systemMenuService.listMenuSuperior(ids);
if (CollectionUtil.isNotEmpty(ids)) { return ResponseEntity.ok(systemMenuTbs);
menus = new LinkedHashSet<>(systemMenuService.listMenuByIds(ids)); }
for (SystemMenuTb menu : menus) {
List<SystemMenuTb> menuList = systemMenuService.querySuperiorMenuByArgs(menu, new ArrayList<>());
for (SystemMenuTb data : menuList) {
if (data.getId().equals(menu.getPid())) {
data.setSubCount(data.getSubCount() - 1);
}
}
menus.addAll(menuList);
}
// 编辑菜单时不显示自己以及自己下级的数据, 避免出现PID数据环形问题
menus = menus.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toSet());
return ResponseEntity.ok(systemMenuService.buildMenuTree(new ArrayList<>(menus)));
}
return ResponseEntity.ok(systemMenuService.listMenuByPid(null));
}
@ApiOperation("新增菜单") @ApiOperation("新增菜单")
@PostMapping(value = "/saveMenu") @PostMapping(value = "/saveMenu")
@PreAuthorize("@el.check('menu:add')") @PreAuthorize("@el.check('menu:add')")
public ResponseEntity<Void> saveMenu(@Validated @RequestBody SystemMenuTb args) { public ResponseEntity<Void> saveMenu(@Validated @RequestBody SystemMenuTb args) {
if (args.getId() != null) { if (args.getId() != null) {
throw new BadRequestException("无效参数id"); throw new BadRequestException("无效参数id");
}
systemMenuService.saveMenu(args);
return ResponseEntity.ok(null);
} }
systemMenuService.saveMenu(args);
return ResponseEntity.ok(null);
}
@ApiOperation("修改菜单") @ApiOperation("修改菜单")
@PostMapping(value = "/modifyMenuById") @PostMapping(value = "/modifyMenuById")
@PreAuthorize("@el.check('menu:edit')") @PreAuthorize("@el.check('menu:edit')")
public ResponseEntity<Void> modifyMenuById(@Validated(SystemMenuTb.Update.class) @RequestBody SystemMenuTb args) { public ResponseEntity<Void> modifyMenuById(@Validated(SystemMenuTb.Update.class) @RequestBody SystemMenuTb args) {
systemMenuService.updateMenuById(args); systemMenuService.updateMenuById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("删除菜单") @ApiOperation("删除菜单")
@PostMapping(value = "/removeMenuByIds") @PostMapping(value = "/removeMenuByIds")
@PreAuthorize("@el.check('menu:del')") @PreAuthorize("@el.check('menu:del')")
public ResponseEntity<Void> removeMenuByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeMenuByIds(@RequestBody Set<Long> ids) {
systemMenuService.deleteMenuByIds(ids); systemMenuService.deleteMenuByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -31,12 +31,13 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/monitor") @RequestMapping("/api/monitor")
public class SystemMonitorController { public class SystemMonitorController {
@Autowired private SystemMonitorService systemMonitorService; @Autowired
private SystemMonitorService systemMonitorService;
@PostMapping(value = "/queryServerMonitorInfo") @PostMapping(value = "/queryServerMonitorInfo")
@ApiOperation("查询服务监控") @ApiOperation("查询服务监控")
@PreAuthorize("@el.check('monitor:list')") @PreAuthorize("@el.check('monitor:list')")
public ResponseEntity<Map<String, Object>> queryServerMonitorInfo() { public ResponseEntity<Map<String, Object>> queryServerMonitorInfo() {
return ResponseEntity.ok(systemMonitorService.getServerMonitorInfo()); return ResponseEntity.ok(systemMonitorService.getServerMonitorInfo());
} }
} }
@@ -19,14 +19,14 @@ import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.system.dal.model.SystemUserOnlineVo; import cn.odboy.system.dal.model.SystemUserOnlineVo;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO; import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.util.KitDesEncryptUtil;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -42,34 +42,31 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "系统:在线用户管理") @Api(tags = "系统:在线用户管理")
public class SystemOnlineController { public class SystemOnlineController {
@Autowired private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO; @Autowired
private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
@ApiOperation("查询在线用户") @ApiOperation("查询在线用户")
@PostMapping @PostMapping
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public ResponseEntity<KitPageResult<SystemUserOnlineVo>> queryOnlineUser( public ResponseEntity<KitPageResult<SystemUserOnlineVo>> queryOnlineUser(
@Validated @RequestBody KitPageArgs<SystemUserOnlineVo> args) { @Validated @RequestBody KitPageArgs<SystemUserOnlineVo> pageArgs) {
IPage<SystemUserOnlineVo> page = new Page<>(args.getPage(), args.getSize()); IPage<SystemUserOnlineVo> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
return ResponseEntity.ok(systemUserOnlineInfoDAO.queryUserOnlineModelPage(args.getArgs(), page)); return ResponseEntity.ok(systemUserOnlineInfoDAO.queryUserOnlineModelPage(pageArgs.getArgs(), page));
} }
@ApiOperation("导出数据") @ApiOperation("导出数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public void exportOnlineUser(HttpServletResponse response, String username) throws IOException { public void exportOnlineUser(HttpServletResponse response, String username) throws IOException {
systemUserOnlineInfoDAO.downloadUserOnlineModelExcel( List<SystemUserOnlineVo> userOnlineVos = systemUserOnlineInfoDAO.queryUserOnlineModelListByUsername(username);
systemUserOnlineInfoDAO.queryUserOnlineModelListByUsername(username), response); systemUserOnlineInfoDAO.downloadUserOnlineModelExcel(userOnlineVos, response);
} }
@ApiOperation("踢出用户") @ApiOperation("踢出用户")
@PostMapping(value = "/kickOutUser") @PostMapping(value = "/kickOutUser")
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public ResponseEntity<Void> kickOutUser(@RequestBody Set<String> keys) throws Exception { public ResponseEntity<Void> kickOutUser(@RequestBody Set<String> keys) throws Exception {
for (String token : keys) { systemUserOnlineInfoDAO.kickOutUser(keys);
// 解密Key return ResponseEntity.ok(null);
token = KitDesEncryptUtil.desDecrypt(token); }
systemUserOnlineInfoDAO.logoutByToken(token);
}
return ResponseEntity.ok(null);
}
} }
@@ -24,8 +24,8 @@ import cn.odboy.system.service.SystemOssStorageService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -45,37 +45,37 @@ import org.springframework.web.multipart.MultipartFile;
@RequestMapping("/api/ossStorage") @RequestMapping("/api/ossStorage")
public class SystemOssStorageController { public class SystemOssStorageController {
@Autowired private SystemOssStorageService systemOssStorageService; @Autowired
private SystemOssStorageService systemOssStorageService;
@ApiOperation("查询文件") @ApiOperation("查询文件")
@PostMapping @PostMapping
@PreAuthorize("@el.check('storage:list')") @PreAuthorize("@el.check('storage:list')")
public ResponseEntity<KitPageResult<SystemOssStorageVo>> queryOssStorage( public ResponseEntity<KitPageResult<SystemOssStorageVo>> queryOssStorage(
@Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) {
SystemQueryStorageArgs args = pageArgs.getArgs(); Page<SystemOssStorageTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemOssStorageTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemOssStorageService.searchOssStorage(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemOssStorageService.searchOssStorage(args, page)); }
}
@ApiOperation("导出数据") @ApiOperation("导出数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('storage:list')") @PreAuthorize("@el.check('storage:list')")
public void exportFile(HttpServletResponse response, SystemQueryStorageArgs args) throws IOException { public void exportFile(HttpServletResponse response, SystemQueryStorageArgs args) throws IOException {
systemOssStorageService.exportOssStorageExcel(systemOssStorageService.queryOssStorage(args), response); systemOssStorageService.exportOssStorageExcel(systemOssStorageService.queryOssStorage(args), response);
} }
@ApiOperation("上传文件") @ApiOperation("上传文件")
@PostMapping(value = "/uploadFile") @PostMapping(value = "/uploadFile")
@PreAuthorize("@el.check('storage:add')") @PreAuthorize("@el.check('storage:add')")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) { public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
String fileUrl = systemOssStorageService.uploadFile(file); String fileUrl = systemOssStorageService.uploadFile(file);
return ResponseEntity.ok(fileUrl); return ResponseEntity.ok(fileUrl);
} }
@ApiOperation("多选删除") @ApiOperation("多选删除")
@PostMapping(value = "/removeFileByIds") @PostMapping(value = "/removeFileByIds")
public ResponseEntity<Void> removeFileByIds(@RequestBody Long[] ids) { public ResponseEntity<Void> removeFileByIds(@RequestBody Long[] ids) {
systemOssStorageService.deleteFileByIds(ids); systemOssStorageService.deleteFileByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -17,8 +17,6 @@ package cn.odboy.system.controller;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.context.KitSpringBeanHolder;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
import cn.odboy.system.dal.dataobject.SystemQuartzLogTb; import cn.odboy.system.dal.dataobject.SystemQuartzLogTb;
import cn.odboy.system.dal.model.SystemQueryQuartzJobArgs; import cn.odboy.system.dal.model.SystemQueryQuartzJobArgs;
@@ -27,9 +25,9 @@ import cn.odboy.system.service.SystemQuartzJobService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -49,98 +47,78 @@ import org.springframework.web.bind.annotation.RestController;
@Api(tags = "系统:定时任务管理") @Api(tags = "系统:定时任务管理")
public class SystemQuartzJobController { public class SystemQuartzJobController {
@Autowired private SystemQuartzJobService systemQuartzJobService; @Autowired
private SystemQuartzJobService systemQuartzJobService;
@ApiOperation("查询定时任务") @ApiOperation("查询定时任务")
@PostMapping @PostMapping
@PreAuthorize("@el.check('quartzJob:list')") @PreAuthorize("@el.check('quartzJob:list')")
public ResponseEntity<KitPageResult<SystemQuartzJobTb>> queryQuartzJobByCrud( public ResponseEntity<KitPageResult<SystemQuartzJobTb>> queryQuartzJobByCrud(
@Validated @RequestBody KitPageArgs<SystemQueryQuartzJobArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryQuartzJobArgs> pageArgs) {
SystemQueryQuartzJobArgs args = pageArgs.getArgs(); Page<SystemQuartzJobTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemQuartzJobTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemQuartzJobService.searchQuartzJobByArgs(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemQuartzJobService.searchQuartzJobByArgs(args, page)); }
}
@ApiOperation("导出任务数据") @ApiOperation("导出任务数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('quartzJob:list')") @PreAuthorize("@el.check('quartzJob:list')")
public void exportQuartzJob(HttpServletResponse response, SystemQueryQuartzJobArgs args) throws IOException { public void exportQuartzJob(HttpServletResponse response, SystemQueryQuartzJobArgs args) throws IOException {
systemQuartzJobService.exportQuartzJobExcel(systemQuartzJobService.queryQuartzJobByArgs(args), response); systemQuartzJobService.exportQuartzJobExcel(systemQuartzJobService.queryQuartzJobByArgs(args), response);
} }
@ApiOperation("导出日志数据") @ApiOperation("导出日志数据")
@GetMapping(value = "/logs/download") @GetMapping(value = "/logs/download")
@PreAuthorize("@el.check('quartzJob:list')") @PreAuthorize("@el.check('quartzJob:list')")
public void exportQuartzJobLog(HttpServletResponse response, SystemQueryQuartzJobArgs args) throws IOException { public void exportQuartzJobLog(HttpServletResponse response, SystemQueryQuartzJobArgs args) throws IOException {
systemQuartzJobService.exportQuartzLogExcel(systemQuartzJobService.queryQuartzLogByArgs(args), response); systemQuartzJobService.exportQuartzLogExcel(systemQuartzJobService.queryQuartzLogByArgs(args), response);
} }
@ApiOperation("查询任务执行日志") @ApiOperation("查询任务执行日志")
@PostMapping(value = "/logs") @PostMapping(value = "/logs")
@PreAuthorize("@el.check('quartzJob:list')") @PreAuthorize("@el.check('quartzJob:list')")
public ResponseEntity<KitPageResult<SystemQuartzLogTb>> queryQuartzJobLog(SystemQueryQuartzJobArgs args) { public ResponseEntity<KitPageResult<SystemQuartzLogTb>> queryQuartzJobLog(SystemQueryQuartzJobArgs args) {
Page<SystemQuartzLogTb> page = new Page<>(args.getPage(), args.getSize()); Page<SystemQuartzLogTb> page = new Page<>(args.getPage(), args.getSize());
return ResponseEntity.ok(systemQuartzJobService.searchQuartzLogByArgs(args, page)); return ResponseEntity.ok(systemQuartzJobService.searchQuartzLogByArgs(args, page));
} }
@ApiOperation("新增定时任务") @ApiOperation("新增定时任务")
@PostMapping(value = "/createQuartzJob") @PostMapping(value = "/createQuartzJob")
@PreAuthorize("@el.check('quartzJob:add')") @PreAuthorize("@el.check('quartzJob:add')")
public ResponseEntity<Void> createQuartzJob(@Validated @RequestBody SystemQuartzJobTb args) { public ResponseEntity<Void> createQuartzJob(@Validated @RequestBody SystemQuartzJobTb args) {
if (args.getId() != null) { systemQuartzJobService.createJob(args);
throw new BadRequestException("无效参数id"); return ResponseEntity.ok(null);
} }
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName());
systemQuartzJobService.createJob(args);
return ResponseEntity.ok(null);
}
@ApiOperation("修改定时任务") @ApiOperation("修改定时任务")
@PutMapping @PutMapping
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> updateQuartzJob( public ResponseEntity<Void> updateQuartzJob(
@Validated(SystemQuartzJobTb.Update.class) @RequestBody SystemUpdateQuartzJobArgs args) { @Validated(SystemQuartzJobTb.Update.class) @RequestBody SystemUpdateQuartzJobArgs args) {
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义 systemQuartzJobService.updateQuartzJobResumeCron(args);
checkBean(args.getBeanName()); return ResponseEntity.ok(null);
systemQuartzJobService.updateQuartzJobResumeCron(args); }
return ResponseEntity.ok(null);
}
@ApiOperation("更改定时任务状态") @ApiOperation("更改定时任务状态")
@PostMapping(value = "/switchQuartzJobStatus/{id}") @PostMapping(value = "/switchQuartzJobStatus/{id}")
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> switchQuartzJobStatus(@PathVariable Long id) { public ResponseEntity<Void> switchQuartzJobStatus(@PathVariable Long id) {
systemQuartzJobService.switchQuartzJobStatus(systemQuartzJobService.getQuartzJobById(id)); systemQuartzJobService.switchQuartzJobStatus(systemQuartzJobService.getQuartzJobById(id));
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("执行定时任务") @ApiOperation("执行定时任务")
@PostMapping(value = "/startQuartzJob/{id}") @PostMapping(value = "/startQuartzJob/{id}")
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> startQuartzJob(@PathVariable Long id) { public ResponseEntity<Void> startQuartzJob(@PathVariable Long id) {
systemQuartzJobService.startQuartzJob(systemQuartzJobService.getQuartzJobById(id)); systemQuartzJobService.startQuartzJob(systemQuartzJobService.getQuartzJobById(id));
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("删除定时任务") @ApiOperation("删除定时任务")
@PostMapping(value = "/removeJobByIds") @PostMapping(value = "/removeJobByIds")
@PreAuthorize("@el.check('quartzJob:del')") @PreAuthorize("@el.check('quartzJob:del')")
public ResponseEntity<Void> removeJobByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeJobByIds(@RequestBody Set<Long> ids) {
systemQuartzJobService.deleteJobByIds(ids); systemQuartzJobService.deleteJobByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
/**
* 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
*
* @param beanName Bean名称
*/
private void checkBean(String beanName) {
// 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类
// 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数,执行任意sql命令。
if (!KitSpringBeanHolder.getAllServiceBeanName().contains(beanName)) {
throw new BadRequestException("非法的 Bean,请重新输入!");
}
}
} }
@@ -18,22 +18,18 @@ package cn.odboy.system.controller;
import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Dict;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.model.SystemCreateRoleArgs; import cn.odboy.system.dal.model.SystemCreateRoleArgs;
import cn.odboy.system.dal.model.SystemQueryRoleArgs; import cn.odboy.system.dal.model.SystemQueryRoleArgs;
import cn.odboy.system.dal.model.SystemRoleVo; import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.service.SystemRoleService; import cn.odboy.system.service.SystemRoleService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
@@ -49,101 +45,74 @@ import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/role") @RequestMapping("/api/role")
public class SystemRoleController { public class SystemRoleController {
@Autowired private SystemRoleService systemRoleService; @Autowired
private SystemRoleService systemRoleService;
@ApiOperation("获取单个role") @ApiOperation("获取单个role")
@PostMapping(value = "/queryRoleById") @PostMapping(value = "/queryRoleById")
@PreAuthorize("@el.check('roles:list')") @PreAuthorize("@el.check('roles:list')")
public ResponseEntity<SystemRoleTb> queryRoleById(@RequestBody SystemRoleTb args) { public ResponseEntity<SystemRoleVo> queryRoleById(@RequestBody SystemRoleTb args) {
return ResponseEntity.ok(systemRoleService.getRoleById(args.getId())); return ResponseEntity.ok(systemRoleService.getRoleById(args.getId()));
} }
@ApiOperation("导出角色数据") @ApiOperation("导出角色数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check('role:list')") @PreAuthorize("@el.check('role:list')")
public void exportRole(HttpServletResponse response, SystemQueryRoleArgs args) throws IOException { public void exportRole(HttpServletResponse response, SystemQueryRoleArgs args) throws IOException {
systemRoleService.exportRoleExcel(systemRoleService.queryRoleByArgs(args), response); systemRoleService.exportRoleExcel(systemRoleService.queryRoleByArgs(args), response);
} }
@ApiOperation("返回全部的角色") @ApiOperation("返回全部的角色")
@PostMapping(value = "/queryRoleList") @PostMapping(value = "/queryRoleList")
@PreAuthorize("@el.check('roles:list','user:add','user:edit')") @PreAuthorize("@el.check('roles:list','user:add','user:edit')")
public ResponseEntity<List<SystemRoleTb>> queryRoleList() { public ResponseEntity<List<SystemRoleTb>> queryRoleList() {
return ResponseEntity.ok(systemRoleService.listAllRole()); return ResponseEntity.ok(systemRoleService.listAllRole());
} }
@ApiOperation("查询角色") @ApiOperation("查询角色")
@PostMapping @PostMapping
@PreAuthorize("@el.check('roles:list')") @PreAuthorize("@el.check('roles:list')")
public ResponseEntity<KitPageResult<SystemRoleVo>> queryRoleByArgs( public ResponseEntity<KitPageResult<SystemRoleVo>> queryRoleByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryRoleArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryRoleArgs> pageArgs) {
SystemQueryRoleArgs args = pageArgs.getArgs(); Page<Object> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<Object> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemRoleService.searchRoleByArgs(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemRoleService.searchRoleByArgs(args, page)); }
}
@ApiOperation("获取用户级别") @ApiOperation("获取用户级别")
@PostMapping(value = "/queryRoleLevel") @PostMapping(value = "/queryRoleLevel")
public ResponseEntity<Dict> queryRoleLevel() { public ResponseEntity<Dict> queryRoleLevel() {
return ResponseEntity.ok(Dict.create().set("level", checkRoleLevels(null))); return ResponseEntity.ok(systemRoleService.getRoleLevel());
} }
@ApiOperation("新增角色") @ApiOperation("新增角色")
@PostMapping(value = "/saveRole") @PostMapping(value = "/saveRole")
@PreAuthorize("@el.check('roles:add')") @PreAuthorize("@el.check('roles:add')")
public ResponseEntity<Void> saveRole(@Validated @RequestBody SystemCreateRoleArgs args) { public ResponseEntity<Void> saveRole(@Validated @RequestBody SystemCreateRoleArgs args) {
checkRoleLevels(args.getLevel()); systemRoleService.saveRole(args);
systemRoleService.saveRole(args); return ResponseEntity.ok(null);
return ResponseEntity.ok(null); }
}
@ApiOperation("修改角色") @ApiOperation("修改角色")
@PostMapping(value = "/modifyRoleById") @PostMapping(value = "/modifyRoleById")
@PreAuthorize("@el.check('roles:edit')") @PreAuthorize("@el.check('roles:edit')")
public ResponseEntity<Void> modifyRoleById(@Validated(SystemRoleTb.Update.class) @RequestBody SystemRoleVo args) { public ResponseEntity<Void> modifyRoleById(@Validated(SystemRoleTb.Update.class) @RequestBody SystemRoleVo args) {
checkRoleLevels(args.getLevel()); systemRoleService.updateRoleById(args);
systemRoleService.updateRoleById(args); return ResponseEntity.ok(null);
return ResponseEntity.ok(null); }
}
@ApiOperation("修改角色菜单") @ApiOperation("修改角色菜单")
@PostMapping(value = "/modifyBindMenuById") @PostMapping(value = "/modifyBindMenuById")
@PreAuthorize("@el.check('roles:edit')") @PreAuthorize("@el.check('roles:edit')")
public ResponseEntity<Void> modifyBindMenuById(@RequestBody SystemRoleVo args) { public ResponseEntity<Void> modifyBindMenuById(@RequestBody SystemRoleVo args) {
SystemRoleTb role = systemRoleService.getRoleById(args.getId()); systemRoleService.updateBindMenuById(args);
checkRoleLevels(role.getLevel()); return ResponseEntity.ok(null);
systemRoleService.updateBindMenuById(args); }
return ResponseEntity.ok(null);
}
@ApiOperation("删除角色") @ApiOperation("删除角色")
@PostMapping(value = "/removeRoleByIds") @PostMapping(value = "/removeRoleByIds")
@PreAuthorize("@el.check('roles:del')") @PreAuthorize("@el.check('roles:del')")
public ResponseEntity<Void> removeRoleByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeRoleByIds(@RequestBody Set<Long> ids) {
for (Long id : ids) { systemRoleService.deleteRoleByIds(ids);
SystemRoleTb role = systemRoleService.getRoleById(id); return ResponseEntity.ok(null);
checkRoleLevels(role.getLevel()); }
}
// 验证是否被用户关联
systemRoleService.verifyBindRelationByIds(ids);
systemRoleService.deleteRoleByIds(ids);
return ResponseEntity.ok(null);
}
/**
* 检查用户的角色级别
*
* @return /
*/
private int checkRoleLevels(Integer level) {
List<Integer> levels = systemRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList());
int min = Collections.min(levels);
if (level != null) {
if (level < min) {
throw new BadRequestException("权限不足, 你的角色级别:" + min + ", 低于操作的角色级别:" + level);
}
}
return min;
}
} }
@@ -15,15 +15,9 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.base.KitSelectOptionVo; import cn.odboy.base.KitSelectOptionVo;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemQueryUserArgs; import cn.odboy.system.dal.model.SystemQueryUserArgs;
import cn.odboy.system.dal.model.SystemUpdateUserPasswordArgs; import cn.odboy.system.dal.model.SystemUpdateUserPasswordArgs;
@@ -31,26 +25,17 @@ import cn.odboy.system.dal.model.SystemUserVo;
import cn.odboy.system.framework.permission.core.KitSecurityHelper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.service.SystemDataService; import cn.odboy.system.service.SystemDataService;
import cn.odboy.system.service.SystemDeptService; import cn.odboy.system.service.SystemDeptService;
import cn.odboy.system.service.SystemEmailService;
import cn.odboy.system.service.SystemRoleService;
import cn.odboy.system.service.SystemUserService; import cn.odboy.system.service.SystemUserService;
import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitRsaEncryptUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@@ -66,173 +51,95 @@ import org.springframework.web.multipart.MultipartFile;
@RequestMapping("/api/user") @RequestMapping("/api/user")
public class SystemUserController { public class SystemUserController {
@Autowired private PasswordEncoder passwordEncoder; @Autowired
@Autowired private SystemUserService systemUserService; private SystemUserService systemUserService;
@Autowired private SystemDataService systemDataService; @Autowired
@Autowired private SystemDeptService systemDeptService; private SystemDataService systemDataService;
@Autowired private SystemRoleService systemRoleService; @Autowired
@Autowired private SystemEmailService systemEmailService; private SystemDeptService systemDeptService;
@Autowired private AppProperties properties;
@ApiOperation("导出用户数据")
@GetMapping(value = "/download")
@PreAuthorize("@el.check('user:list')")
public void exportUserExcel(HttpServletResponse response, SystemQueryUserArgs args) throws IOException {
systemUserService.exportUserExcel(systemUserService.queryUserByArgs(args), response);
}
@ApiOperation("查询用户") @ApiOperation("导出用户数据")
@PostMapping @GetMapping(value = "/download")
@PreAuthorize("@el.check('user:list')") @PreAuthorize("@el.check('user:list')")
public ResponseEntity<KitPageResult<SystemUserVo>> queryUserByArgs( public void exportUserExcel(HttpServletResponse response, SystemQueryUserArgs args) throws IOException {
@Validated @RequestBody KitPageArgs<SystemQueryUserArgs> pageArgs) { systemUserService.exportUserExcel(systemUserService.queryUserByArgs(args), response);
Page<SystemUserTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize()); }
SystemQueryUserArgs args = pageArgs.getArgs();
if (!ObjectUtils.isEmpty(args.getDeptId())) {
args.getDeptIds().add(args.getDeptId());
// 先查找是否存在子节点
List<SystemDeptTb> data = systemDeptService.listDeptByPid(args.getDeptId());
// 然后把子节点的ID都加入到集合中
args.getDeptIds().addAll(systemDeptService.queryChildDeptIdByDeptIds(data));
}
// 数据权限
List<Long> dataScopes = systemDataService.queryDeptIdByArgs(
systemUserService.getUserByUsername(KitSecurityHelper.getCurrentUsername()));
// args.getDeptIds() 不为空并且数据权限不为空则取交集
if (!CollectionUtils.isEmpty(args.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)) {
// 取交集
args.getDeptIds().retainAll(dataScopes);
if (!CollectionUtil.isEmpty(args.getDeptIds())) {
return ResponseEntity.ok(systemUserService.searchUserByArgs(args, page));
}
} else {
// 否则取并集
args.getDeptIds().addAll(dataScopes);
return ResponseEntity.ok(systemUserService.searchUserByArgs(args, page));
}
return ResponseEntity.ok(KitPageUtil.emptyData());
}
@ApiOperation("新增用户") @ApiOperation("查询用户")
@PostMapping(value = "/saveUser") @PostMapping
@PreAuthorize("@el.check('user:add')") @PreAuthorize("@el.check('user:list')")
public ResponseEntity<Object> saveUser(@Validated @RequestBody SystemUserVo args) { public ResponseEntity<KitPageResult<SystemUserVo>> queryUserByArgs(@Validated @RequestBody KitPageArgs<SystemQueryUserArgs> pageArgs) {
checkLevel(args); String currentUsername = KitSecurityHelper.getCurrentUsername();
// 默认密码 123456 Page<SystemUserTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
args.setPassword(passwordEncoder.encode("123456")); return ResponseEntity.ok(systemUserService.aggregationSearchUserByArgs(page, pageArgs.getArgs(), currentUsername));
systemUserService.saveUser(args); }
return ResponseEntity.ok(null);
}
@ApiOperation("修改用户") @ApiOperation("新增用户")
@PostMapping(value = "/modifyUserById") @PostMapping(value = "/saveUser")
@PreAuthorize("@el.check('user:edit')") @PreAuthorize("@el.check('user:add')")
public ResponseEntity<Object> modifyUserById(@Validated(SystemUserTb.Update.class) @RequestBody SystemUserVo args) { public ResponseEntity<Object> saveUser(@Validated @RequestBody SystemUserVo args) {
checkLevel(args); systemUserService.saveUser(args);
systemUserService.updateUserById(args); return ResponseEntity.ok(null);
return ResponseEntity.ok(null); }
}
@ApiOperation("修改用户:个人中心") @ApiOperation("修改用户")
@PostMapping(value = "modifyUserCenterInfoById") @PostMapping(value = "/modifyUserById")
public ResponseEntity<Object> modifyUserCenterInfoById( @PreAuthorize("@el.check('user:edit')")
@Validated(SystemUserTb.Update.class) @RequestBody SystemUserTb args) { public ResponseEntity<Object> modifyUserById(@Validated(SystemUserTb.Update.class) @RequestBody SystemUserVo args) {
if (!args.getId().equals(KitSecurityHelper.getCurrentUserId())) { systemUserService.updateUserById(args);
throw new BadRequestException("不能修改他人资料"); return ResponseEntity.ok(null);
} }
systemUserService.updateUserCenterInfoById(args);
return ResponseEntity.ok(null);
}
@ApiOperation("删除用户") @ApiOperation("修改用户:个人中心")
@PostMapping(value = "/removeUserByIds") @PostMapping(value = "modifyUserCenterInfoById")
@PreAuthorize("@el.check('user:del')") public ResponseEntity<Object> modifyUserCenterInfoById(@Validated(SystemUserTb.Update.class) @RequestBody SystemUserTb args) {
public ResponseEntity<Object> removeUserByIds(@RequestBody Set<Long> ids) { systemUserService.updateUserCenterInfoById(args);
for (Long id : ids) { return ResponseEntity.ok(null);
Integer currentLevel = Collections.min( }
systemRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(
systemRoleService.queryRoleByUsersId(id).stream().map(SystemRoleTb::getLevel)
.collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException(
"角色权限不足, 不能删除:" + systemUserService.getUserById(id).getUsername());
}
}
systemUserService.removeUserByIds(ids);
return ResponseEntity.ok(null);
}
@ApiOperation("修改密码") @ApiOperation("删除用户")
@PostMapping(value = "/modifyUserPasswordByUsername") @PostMapping(value = "/removeUserByIds")
public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody SystemUpdateUserPasswordArgs passVo) @PreAuthorize("@el.check('user:del')")
throws Exception { public ResponseEntity<Object> removeUserByIds(@RequestBody Set<Long> ids) {
String oldPass = systemUserService.removeUserByIds(ids);
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getOldPass()); return ResponseEntity.ok(null);
String newPass = }
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getNewPass());
SystemUserTb user = systemUserService.getUserByUsername(KitSecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(oldPass, user.getPassword())) {
throw new BadRequestException("修改失败,旧密码错误");
}
if (passwordEncoder.matches(newPass, user.getPassword())) {
throw new BadRequestException("新密码不能与旧密码相同");
}
systemUserService.updateUserPasswordByUsername(user.getUsername(), passwordEncoder.encode(newPass));
return ResponseEntity.ok(null);
}
@ApiOperation("重置密码") @ApiOperation("修改密码")
@PostMapping(value = "/resetUserPasswordByIds") @PostMapping(value = "/modifyUserPasswordByUsername")
public ResponseEntity<Object> resetUserPasswordByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody SystemUpdateUserPasswordArgs passVo) throws Exception {
String defaultPwd = passwordEncoder.encode("123456"); String currentUsername = KitSecurityHelper.getCurrentUsername();
systemUserService.resetUserPasswordByIds(ids, defaultPwd); systemUserService.updateUserPasswordByUsername(currentUsername, passVo);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改头像") @ApiOperation("重置密码")
@PostMapping(value = "/modifyUserAvatar") @PostMapping(value = "/resetUserPasswordByIds")
public ResponseEntity<Object> modifyUserAvatar(@RequestParam MultipartFile avatar) { public ResponseEntity<Object> resetUserPasswordByIds(@RequestBody Set<Long> ids) {
return ResponseEntity.ok(systemUserService.updateUserAvatar(avatar)); systemUserService.resetUserPasswordByIds(ids);
} return ResponseEntity.ok(null);
}
@ApiOperation("修改邮箱") @ApiOperation("修改头像")
@PostMapping(value = "/modifyUserEmailByUsername/{code}") @PostMapping(value = "/modifyUserAvatar")
public ResponseEntity<Object> modifyUserEmailByUsername(@PathVariable String code, @RequestBody SystemUserTb args) public ResponseEntity<Object> modifyUserAvatar(@RequestParam MultipartFile avatar) {
throws Exception { return ResponseEntity.ok(systemUserService.updateUserAvatar(avatar));
String password = }
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getPassword());
SystemUserTb user = systemUserService.getUserByUsername(KitSecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadRequestException("密码错误");
}
systemEmailService.checkEmailCaptcha(SystemCaptchaBizEnum.EMAIL_RESET_EMAIL_CODE, args.getEmail(), code);
systemUserService.updateUserEmailByUsername(user.getUsername(), args.getEmail());
return ResponseEntity.ok(null);
}
/** @ApiOperation("修改邮箱")
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误 @PostMapping(value = "/modifyUserEmailByUsername/{code}")
* public ResponseEntity<Object> modifyUserEmailByUsername(@PathVariable String code, @RequestBody SystemUserTb args) throws Exception {
* @param args / String currentUsername = KitSecurityHelper.getCurrentUsername();
*/ systemUserService.updateUserEmailByUsername(currentUsername, args, code);
private void checkLevel(SystemUserVo args) { return ResponseEntity.ok(null);
Integer currentLevel = Collections.min( }
systemRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = systemRoleService.getDeptLevelByRoles(args.getRoles());
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
}
}
@ApiOperation("查询用户基础数据") @ApiOperation("查询用户基础数据")
@PostMapping(value = "/queryUserMetadataOptions") @PostMapping(value = "/queryUserMetadataOptions")
@PreAuthorize("@el.check('user:list')") @PreAuthorize("@el.check('user:list')")
public ResponseEntity<List<KitSelectOptionVo>> queryUserMetadataOptions( public ResponseEntity<List<KitSelectOptionVo>> queryUserMetadataOptions(@Validated @RequestBody KitPageArgs<SystemQueryUserArgs> args) {
@Validated @RequestBody KitPageArgs<SystemQueryUserArgs> args) { List<KitSelectOptionVo> collect = systemUserService.queryUserMetadataOptions(args);
List<KitSelectOptionVo> collect = systemUserService.queryUserMetadataOptions(args); return ResponseEntity.ok(collect);
return ResponseEntity.ok(collect); }
}
} }
@@ -28,10 +28,10 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper
public interface SystemDeptMapper extends BaseMapper<SystemDeptTb> { public interface SystemDeptMapper extends BaseMapper<SystemDeptTb> {
default void updateDeptSubCountById(long count, Long deptId) { default void updateDeptSubCountById(long count, Long deptId) {
LambdaUpdateWrapper<SystemDeptTb> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SystemDeptTb> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(SystemDeptTb::getId, deptId); wrapper.eq(SystemDeptTb::getId, deptId);
wrapper.set(SystemDeptTb::getSubCount, count); wrapper.set(SystemDeptTb::getSubCount, count);
update(null, wrapper); update(null, wrapper);
} }
} }
@@ -30,5 +30,6 @@ import org.apache.ibatis.annotations.Param;
*/ */
@Mapper @Mapper
public interface SystemDictDetailMapper extends BaseMapper<SystemDictDetailTb> { public interface SystemDictDetailMapper extends BaseMapper<SystemDictDetailTb> {
IPage<SystemDictDetailTb> selectPageByArgs(Page<SystemDictDetailTb> page, @Param("args") SystemQueryDictDetailArgs args); IPage<SystemDictDetailTb> selectPageByArgs(Page<SystemDictDetailTb> page, @Param("args") SystemQueryDictDetailArgs args);
} }
@@ -29,13 +29,13 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper
public interface SystemDictMapper extends BaseMapper<SystemDictTb> { public interface SystemDictMapper extends BaseMapper<SystemDictTb> {
default List<SystemDictTb> listAll() { default List<SystemDictTb> listAll() {
return selectList(null); return selectList(null);
} }
default SystemDictTb getByName(String dictName) { default SystemDictTb getByName(String dictName) {
LambdaQueryWrapper<SystemDictTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemDictTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemDictTb::getName, dictName); wrapper.eq(SystemDictTb::getName, dictName);
return selectOne(wrapper); return selectOne(wrapper);
} }
} }
@@ -29,24 +29,24 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper
public interface SystemUserMapper extends BaseMapper<SystemUserTb> { public interface SystemUserMapper extends BaseMapper<SystemUserTb> {
default void updateUserPasswordByUsername(String username, String password) { default void updateUserPasswordByUsername(String username, String password) {
LambdaUpdateWrapper<SystemUserTb> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SystemUserTb> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(SystemUserTb::getUsername, username); wrapper.eq(SystemUserTb::getUsername, username);
wrapper.set(SystemUserTb::getPassword, password); wrapper.set(SystemUserTb::getPassword, password);
update(null, wrapper); update(null, wrapper);
} }
default void updateUserEmailByUsername(String username, String email) { default void updateUserEmailByUsername(String username, String email) {
LambdaUpdateWrapper<SystemUserTb> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SystemUserTb> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(SystemUserTb::getUsername, username); wrapper.eq(SystemUserTb::getUsername, username);
wrapper.set(SystemUserTb::getEmail, email); wrapper.set(SystemUserTb::getEmail, email);
update(null, wrapper); update(null, wrapper);
} }
default void updateUserPasswordByUserIds(String password, Set<Long> userIds) { default void updateUserPasswordByUserIds(String password, Set<Long> userIds) {
LambdaUpdateWrapper<SystemUserTb> wrapper = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<SystemUserTb> wrapper = new LambdaUpdateWrapper<>();
wrapper.in(SystemUserTb::getId, userIds); wrapper.in(SystemUserTb::getId, userIds);
wrapper.set(SystemUserTb::getPassword, password); wrapper.set(SystemUserTb::getPassword, password);
update(null, wrapper); update(null, wrapper);
} }
} }
@@ -20,50 +20,50 @@ package cn.odboy.system.dal.redis;
*/ */
public interface SystemCacheKey { public interface SystemCacheKey {
/** /**
* 用户 * 用户
*/ */
String USER_ID = "user::id:"; String USER_ID = "user::id:";
/** /**
* 数据 * 数据
*/ */
String DATA_USER = "data::user:"; String DATA_USER = "data::user:";
/** /**
* 菜单 * 菜单
*/ */
String MENU_ID = "menu::id:"; String MENU_ID = "menu::id:";
String MENU_USER = "menu::user:"; String MENU_USER = "menu::user:";
/** /**
* 角色授权 * 角色授权
*/ */
String ROLE_AUTH = "role::auth:"; String ROLE_AUTH = "role::auth:";
String ROLE_USER = "role::user:"; String ROLE_USER = "role::user:";
/** /**
* 角色信息 * 角色信息
*/ */
String ROLE_ID = "role::id:"; String ROLE_ID = "role::id:";
/** /**
* 部门 * 部门
*/ */
String DEPT_ID = "dept::id:"; String DEPT_ID = "dept::id:";
/** /**
* 岗位 * 岗位
*/ */
String JOB_ID = "job::id:"; String JOB_ID = "job::id:";
/** /**
* 数据字典 * 数据字典
*/ */
String DICT_NAME = "dict::name:"; String DICT_NAME = "dict::name:";
/** /**
* 在线用户 * 在线用户
*/ */
String ONLINE_USER = "online::token:"; String ONLINE_USER = "online::token:";
/** /**
* 登录验证码 * 登录验证码
*/ */
String CAPTCHA_LOGIN = "captcha::login:"; String CAPTCHA_LOGIN = "captcha::login:";
/** /**
* 用户信息 * 用户信息
*/ */
String USER_INFO = "user::info:"; String USER_INFO = "user::info:";
} }
@@ -5,50 +5,50 @@ package cn.odboy.system.dal.redis;
*/ */
public interface SystemRedisKey { public interface SystemRedisKey {
/** /**
* 用户 * 用户
*/ */
String USER_ID = "user::id:"; String USER_ID = "user::id:";
/** /**
* 数据 * 数据
*/ */
String DATA_USER = "data::user:"; String DATA_USER = "data::user:";
/** /**
* 菜单 * 菜单
*/ */
String MENU_ID = "menu::id:"; String MENU_ID = "menu::id:";
String MENU_USER = "menu::user:"; String MENU_USER = "menu::user:";
/** /**
* 角色授权 * 角色授权
*/ */
String ROLE_AUTH = "role::auth:"; String ROLE_AUTH = "role::auth:";
String ROLE_USER = "role::user:"; String ROLE_USER = "role::user:";
/** /**
* 角色信息 * 角色信息
*/ */
String ROLE_ID = "role::id:"; String ROLE_ID = "role::id:";
/** /**
* 部门 * 部门
*/ */
String DEPT_ID = "dept::id:"; String DEPT_ID = "dept::id:";
/** /**
* 岗位 * 岗位
*/ */
String JOB_ID = "job::id:"; String JOB_ID = "job::id:";
/** /**
* 数据字典 * 数据字典
*/ */
String DICT_NAME = "dict::name:"; String DICT_NAME = "dict::name:";
/** /**
* 在线用户 * 在线用户
*/ */
String ONLINE_USER = "online::token:"; String ONLINE_USER = "online::token:";
/** /**
* 登录验证码 * 登录验证码
*/ */
String CAPTCHA_LOGIN = "captcha::login:"; String CAPTCHA_LOGIN = "captcha::login:";
/** /**
* 用户信息 * 用户信息
*/ */
String USER_INFO = "user::info:"; String USER_INFO = "user::info:";
} }
@@ -14,46 +14,47 @@ import org.springframework.stereotype.Component;
@Component @Component
public class SystemUserInfoDAO { public class SystemUserInfoDAO {
@Autowired private KitRedisHelper redisHelper; @Autowired
private KitRedisHelper redisHelper;
/** /**
* 添加缓存到Redis * 添加缓存到Redis
* *
* @param userName 用户名 * @param userName 用户名
*/ */
@Async @Async
public void saveUserLoginInfoByUserName(String userName, SystemUserJwtVo user) { public void saveUserLoginInfoByUserName(String userName, SystemUserJwtVo user) {
if (StrUtil.isNotEmpty(userName)) { if (StrUtil.isNotEmpty(userName)) {
// 添加数据, 避免数据同时过期(2小时左右) // 添加数据, 避免数据同时过期(2小时左右)
long time = 7200 + RandomUtil.randomInt(900, 1800); long time = 7200 + RandomUtil.randomInt(900, 1800);
redisHelper.set(SystemRedisKey.USER_INFO + userName, user, time); redisHelper.set(SystemRedisKey.USER_INFO + userName, user, time);
}
} }
}
/** /**
* 清理用户缓存信息 用户信息变更时 * 清理用户缓存信息 用户信息变更时
* *
* @param userName 用户名 * @param userName 用户名
*/ */
@Async @Async
public void deleteUserLoginInfoByUserName(String userName) { public void deleteUserLoginInfoByUserName(String userName) {
if (StrUtil.isNotEmpty(userName)) { if (StrUtil.isNotEmpty(userName)) {
// 清除数据 // 清除数据
redisHelper.del(SystemRedisKey.USER_INFO + userName); redisHelper.del(SystemRedisKey.USER_INFO + userName);
}
} }
}
/** /**
* 返回用户缓存 * 返回用户缓存
* *
* @param username 用户名 * @param username 用户名
* @return UserJwtVo * @return UserJwtVo
*/ */
public SystemUserJwtVo getUserLoginInfoByUserName(String username) { public SystemUserJwtVo getUserLoginInfoByUserName(String username) {
if (StrUtil.isNotEmpty(username)) { if (StrUtil.isNotEmpty(username)) {
// 获取数据 // 获取数据
return redisHelper.get(SystemRedisKey.USER_INFO + username, SystemUserJwtVo.class); return redisHelper.get(SystemRedisKey.USER_INFO + username, SystemUserJwtVo.class);
}
return null;
} }
return null;
}
} }
@@ -13,8 +13,6 @@ import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitIPUtil; import cn.odboy.util.KitIPUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -22,7 +20,10 @@ import java.util.Date;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -32,129 +33,137 @@ import org.springframework.stereotype.Component;
@AllArgsConstructor @AllArgsConstructor
public class SystemUserOnlineInfoDAO { public class SystemUserOnlineInfoDAO {
private final AppProperties properties; private final AppProperties properties;
private final TokenProvider tokenProvider; private final TokenProvider tokenProvider;
private final KitRedisHelper redisHelper; private final KitRedisHelper redisHelper;
/** /**
* 保存在线用户信息 * 保存在线用户信息
* *
* @param userJwtVo / * @param userJwtVo /
* @param token / * @param token /
* @param request / * @param request /
*/ */
public void saveUserJwtModelByToken(SystemUserJwtVo userJwtVo, String token, HttpServletRequest request) { public void saveUserJwtModelByToken(SystemUserJwtVo userJwtVo, String token, HttpServletRequest request) {
String dept = userJwtVo.getUser().getDept().getName(); String dept = userJwtVo.getUser().getDept().getName();
String ip = KitBrowserUtil.getIp(request); String ip = KitBrowserUtil.getIp(request);
String id = tokenProvider.getId(token); String id = tokenProvider.getId(token);
String version = KitBrowserUtil.getVersion(request); String version = KitBrowserUtil.getVersion(request);
String address = KitIPUtil.getCityInfo(ip); String address = KitIPUtil.getCityInfo(ip);
SystemUserOnlineVo userOnlineVo = null; SystemUserOnlineVo userOnlineVo = null;
try { try {
userOnlineVo = new SystemUserOnlineVo(); userOnlineVo = new SystemUserOnlineVo();
userOnlineVo.setUid(id); userOnlineVo.setUid(id);
userOnlineVo.setUserName(userJwtVo.getUsername()); userOnlineVo.setUserName(userJwtVo.getUsername());
userOnlineVo.setNickName(userJwtVo.getUser().getNickName()); userOnlineVo.setNickName(userJwtVo.getUser().getNickName());
userOnlineVo.setDept(dept); userOnlineVo.setDept(dept);
userOnlineVo.setBrowser(version); userOnlineVo.setBrowser(version);
userOnlineVo.setIp(ip); userOnlineVo.setIp(ip);
userOnlineVo.setAddress(address); userOnlineVo.setAddress(address);
userOnlineVo.setKey(KitDesEncryptUtil.desEncrypt(token)); userOnlineVo.setKey(KitDesEncryptUtil.desEncrypt(token));
userOnlineVo.setLoginTime(new Date()); userOnlineVo.setLoginTime(new Date());
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
}
String loginKey = tokenProvider.loginKey(token);
redisHelper.set(loginKey, userOnlineVo, properties.getJwt().getTokenValidityInSeconds(), TimeUnit.MILLISECONDS);
} }
String loginKey = tokenProvider.loginKey(token);
redisHelper.set(loginKey, userOnlineVo, properties.getJwt().getTokenValidityInSeconds(), TimeUnit.MILLISECONDS);
}
/** /**
* 退出登录 * 退出登录
* *
* @param token / * @param token /
*/ */
public void logoutByToken(String token) { public void logoutByToken(String token) {
String loginKey = tokenProvider.loginKey(token); String loginKey = tokenProvider.loginKey(token);
redisHelper.del(loginKey); redisHelper.del(loginKey);
} }
/** /**
* 导出 * 导出
* *
* @param all / * @param all /
* @param response / * @param response /
* @throws IOException / * @throws IOException /
*/ */
public void downloadUserOnlineModelExcel(List<SystemUserOnlineVo> all, HttpServletResponse response) public void downloadUserOnlineModelExcel(List<SystemUserOnlineVo> all, HttpServletResponse response)
throws IOException { throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (SystemUserOnlineVo user : all) { for (SystemUserOnlineVo user : all) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("用户名", user.getUserName()); map.put("用户名", user.getUserName());
map.put("部门", user.getDept()); map.put("部门", user.getDept());
map.put("登录IP", user.getIp()); map.put("登录IP", user.getIp());
map.put("登录地点", user.getAddress()); map.put("登录地点", user.getAddress());
map.put("浏览器", user.getBrowser()); map.put("浏览器", user.getBrowser());
map.put("登录日期", user.getLoginTime()); map.put("登录日期", user.getLoginTime());
list.add(map); list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
KitFileUtil.downloadExcel(list, response);
}
/** /**
* 根据用户名强退用户 * 根据用户名强退用户
* *
* @param username / * @param username /
*/ */
public void kickOutByUsername(String username) { public void kickOutByUsername(String username) {
String loginKey = SystemRedisKey.ONLINE_USER + username + "*"; String loginKey = SystemRedisKey.ONLINE_USER + username + "*";
redisHelper.scanDel(loginKey); redisHelper.scanDel(loginKey);
} }
/** /**
* 查询全部数据 * 查询全部数据
* *
* @param onlineVo / * @param onlineVo /
* @param pageable / * @param pageable /
* @return / * @return /
*/ */
public KitPageResult<SystemUserOnlineVo> queryUserOnlineModelPage(SystemUserOnlineVo onlineVo, public KitPageResult<SystemUserOnlineVo> queryUserOnlineModelPage(SystemUserOnlineVo onlineVo,
IPage<SystemUserOnlineVo> pageable) { IPage<SystemUserOnlineVo> pageable) {
String username = null; String username = null;
if (onlineVo != null) { if (onlineVo != null) {
username = onlineVo.getUserName(); username = onlineVo.getUserName();
}
List<SystemUserOnlineVo> onlineUserList = queryUserOnlineModelListByUsername(username);
List<SystemUserOnlineVo> paging =
KitPageUtil.softPaging(pageable.getCurrent(), pageable.getSize(), onlineUserList);
return KitPageUtil.toPage(paging, onlineUserList.size());
} }
List<SystemUserOnlineVo> onlineUserList = queryUserOnlineModelListByUsername(username);
List<SystemUserOnlineVo> paging =
KitPageUtil.softPaging(pageable.getCurrent(), pageable.getSize(), onlineUserList);
return KitPageUtil.toPage(paging, onlineUserList.size());
}
/** /**
* 查询全部数据,不分页 * 查询全部数据,不分页
* *
* @param username / * @param username /
* @return / * @return /
*/ */
public List<SystemUserOnlineVo> queryUserOnlineModelListByUsername(String username) { public List<SystemUserOnlineVo> queryUserOnlineModelListByUsername(String username) {
String loginKey = SystemRedisKey.ONLINE_USER + (StrUtil.isBlank(username) ? "" : "*" + username); String loginKey = SystemRedisKey.ONLINE_USER + (StrUtil.isBlank(username) ? "" : "*" + username);
List<String> keys = redisHelper.scan(loginKey + "*"); List<String> keys = redisHelper.scan(loginKey + "*");
Collections.reverse(keys); Collections.reverse(keys);
List<SystemUserOnlineVo> onlineUserList = new ArrayList<>(); List<SystemUserOnlineVo> onlineUserList = new ArrayList<>();
for (String key : keys) { for (String key : keys) {
onlineUserList.add(redisHelper.get(key, SystemUserOnlineVo.class)); onlineUserList.add(redisHelper.get(key, SystemUserOnlineVo.class));
}
onlineUserList.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
return onlineUserList;
} }
onlineUserList.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
return onlineUserList;
}
/** /**
* 查询用户 * 查询用户
* *
* @param key / * @param key /
* @return / * @return /
*/ */
public SystemUserOnlineVo queryUserOnlineModelByKey(String key) { public SystemUserOnlineVo queryUserOnlineModelByKey(String key) {
return redisHelper.get(key, SystemUserOnlineVo.class); return redisHelper.get(key, SystemUserOnlineVo.class);
}
public void kickOutUser(Set<String> keys) throws Exception {
for (String token : keys) {
// 解密Key
token = KitDesEncryptUtil.desDecrypt(token);
this.logoutByToken(token);
} }
}
} }
@@ -0,0 +1,117 @@
package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.odboy.constant.CaptchaCodeEnum;
import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.model.SystemUserInfoVo;
import cn.odboy.system.dal.model.SystemUserJwtVo;
import cn.odboy.system.dal.model.SystemUserLoginArgs;
import cn.odboy.system.dal.redis.SystemCacheKey;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.framework.permission.core.handler.TokenProvider;
import cn.odboy.system.framework.permission.core.handler.UserDetailsHandler;
import cn.odboy.util.KitRsaEncryptUtil;
import com.wf.captcha.base.Captcha;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class SystemAuthService {
@Autowired
private KitRedisHelper redisHelper;
@Autowired
private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
@Autowired
private TokenProvider tokenProvider;
@Autowired
private AppProperties properties;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsHandler userDetailsService;
public Map<String, Object> doLogin(SystemUserLoginArgs loginRequest, HttpServletRequest request) throws Exception {
// 密码解密
String password =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginRequest.getPassword());
// 查询验证码
String code = redisHelper.get(loginRequest.getUuid(), String.class);
// 清除验证码
redisHelper.del(loginRequest.getUuid());
if (StrUtil.isBlank(code)) {
throw new BadRequestException("验证码不存在或已过期");
}
if (StrUtil.isBlank(loginRequest.getCode()) || !loginRequest.getCode().equalsIgnoreCase(code)) {
throw new BadRequestException("验证码错误");
}
// 获取用户信息
SystemUserJwtVo jwtUser = userDetailsService.loadUserByUsername(loginRequest.getUsername());
// 验证用户密码
if (!passwordEncoder.matches(password, jwtUser.getPassword())) {
throw new BadRequestException("登录密码错误");
}
Authentication authentication =
new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成令牌
String token = tokenProvider.createToken(jwtUser);
// 返回 token 与 用户信息
Map<String, Object> authInfo = new HashMap<>(2) {{
put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token));
put("user", BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class));
}};
if (properties.getLogin().isSingle()) {
// 踢掉之前已经登录的token
systemUserOnlineInfoDAO.kickOutByUsername(loginRequest.getUsername());
}
// 保存在线信息
systemUserOnlineInfoDAO.saveUserJwtModelByToken(jwtUser, token, request);
// 返回登录信息
return authInfo;
}
public SystemUserInfoVo getCurrentUserInfoVo() {
SystemUserJwtVo jwtUser = (SystemUserJwtVo) KitSecurityHelper.getCurrentUser();
return BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class);
}
public Map<String, Object> getCaptchaInfo() {
// 获取运算的结果
Captcha captcha = properties.getLogin().getCaptchaSetting().getCaptcha();
String uuid = SystemCacheKey.CAPTCHA_LOGIN + IdUtil.simpleUUID();
//当验证码类型为 arithmetic时且长度 >= 2 时, captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text();
if (captcha.getCharType() - 1 == CaptchaCodeEnum.ARITHMETIC.ordinal() &&
captchaValue.contains(SystemConst.SYMBOL_DOT)) {
captchaValue = captchaValue.split("\\.")[0];
}
// 保存
redisHelper.set(uuid, captchaValue, properties.getLogin().getCaptchaSetting().getExpiration(),
TimeUnit.MINUTES);
// 验证码信息
return new HashMap<>(2) {{
put("img", captcha.toBase64());
put("uuid", uuid);
}};
}
public void doLogout(HttpServletRequest request) {
String token = tokenProvider.getToken(request);
systemUserOnlineInfoDAO.logoutByToken(token);
}
}
@@ -36,53 +36,56 @@ import org.springframework.stereotype.Service;
@Service @Service
public class SystemDataService { public class SystemDataService {
@Autowired private SystemRoleService systemRoleService; @Autowired
@Autowired private SystemDeptService systemDeptService; private SystemUserRoleService systemUserRoleService;
@Autowired private SystemRoleDeptService systemRoleDeptService; @Autowired
private SystemDeptService systemDeptService;
@Autowired
private SystemRoleDeptService systemRoleDeptService;
/** /**
* 获取数据权限 * 获取数据权限
* *
* @param user / * @param user /
* @return / * @return /
*/ */
public List<Long> queryDeptIdByArgs(SystemUserTb user) { public List<Long> queryDeptIdByArgs(SystemUserTb user) {
List<Long> deptIds = new ArrayList<>(); List<Long> deptIds = new ArrayList<>();
// 查询用户角色 // 查询用户角色
List<SystemRoleVo> roleList = systemRoleService.queryRoleByUsersId(user.getId()); List<SystemRoleVo> roleList = systemUserRoleService.queryRoleByUsersId(user.getId());
// 获取对应的部门ID // 获取对应的部门ID
for (SystemRoleTb role : roleList) { for (SystemRoleTb role : roleList) {
SystemDataScopeEnum dataScopeEnum = SystemDataScopeEnum.find(role.getDataScope()); SystemDataScopeEnum dataScopeEnum = SystemDataScopeEnum.find(role.getDataScope());
switch (Objects.requireNonNull(dataScopeEnum)) { switch (Objects.requireNonNull(dataScopeEnum)) {
case THIS_LEVEL: case THIS_LEVEL:
deptIds.add(user.getDept().getId()); deptIds.add(user.getDept().getId());
break; break;
case CUSTOMIZE: case CUSTOMIZE:
deptIds.addAll(this.queryCustomDataPermissionByArgs(deptIds, role)); deptIds.addAll(this.queryCustomDataPermissionByArgs(deptIds, role));
break; break;
default: default:
return new ArrayList<>(); return new ArrayList<>();
} }
}
return deptIds.stream().distinct().collect(Collectors.toList());
} }
return deptIds.stream().distinct().collect(Collectors.toList());
}
/** /**
* 获取自定义的数据权限 * 获取自定义的数据权限
* *
* @param deptIds 部门ID * @param deptIds 部门ID
* @param role 角色 * @param role 角色
* @return 数据权限ID * @return 数据权限ID
*/ */
private List<Long> queryCustomDataPermissionByArgs(List<Long> deptIds, SystemRoleTb role) { private List<Long> queryCustomDataPermissionByArgs(List<Long> deptIds, SystemRoleTb role) {
List<SystemDeptTb> deptList = systemRoleDeptService.listDeptByRoleId(role.getId()); List<SystemDeptTb> deptList = systemRoleDeptService.listDeptByRoleId(role.getId());
for (SystemDeptTb dept : deptList) { for (SystemDeptTb dept : deptList) {
deptIds.add(dept.getId()); deptIds.add(dept.getId());
List<SystemDeptTb> deptChildren = systemDeptService.listDeptByPid(dept.getId()); List<SystemDeptTb> deptChildren = systemDeptService.listDeptByPid(dept.getId());
if (CollUtil.isNotEmpty(deptChildren)) { if (CollUtil.isNotEmpty(deptChildren)) {
deptIds.addAll(systemDeptService.queryChildDeptIdByDeptIds(deptChildren)); deptIds.addAll(systemDeptService.queryChildDeptIdByDeptIds(deptChildren));
} }
}
return deptIds;
} }
return deptIds;
}
} }
@@ -33,7 +33,6 @@ import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitClassUtil; import cn.odboy.util.KitClassUtil;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
@@ -47,6 +46,7 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -54,429 +54,437 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemDeptService { public class SystemDeptService {
@Autowired private SystemDeptMapper systemDeptMapper; @Autowired
@Autowired private SystemUserService systemUserService; private SystemDeptMapper systemDeptMapper;
@Autowired private SystemRoleService systemRoleService; @Autowired
private SystemUserDeptService systemUserDeptService;
@Autowired
private SystemRoleDeptService systemRoleDeptService;
/** /**
* 创建 * 创建
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveDept(SystemCreateDeptArgs args) { public void saveDept(SystemCreateDeptArgs args) {
systemDeptMapper.insert(BeanUtil.copyProperties(args, SystemDeptTb.class)); systemDeptMapper.insert(BeanUtil.copyProperties(args, SystemDeptTb.class));
this.updateDeptSubCnt(args.getPid()); this.updateDeptSubCnt(args.getPid());
}
/**
* 编辑
*
* @param args /
*/
@Transactional(rollbackFor = Exception.class)
public void updateDept(SystemDeptTb args) {
// 旧的部门
Long oldPid = this.getDeptById(args.getId()).getPid();
Long newPid = args.getPid();
if (args.getPid() != null && args.getId().equals(args.getPid())) {
throw new BadRequestException("上级不能为自己");
} }
SystemDeptTb dept = systemDeptMapper.selectById(args.getId());
args.setId(dept.getId());
systemDeptMapper.insertOrUpdate(args);
this.updateDeptSubCnt(oldPid);
this.updateDeptSubCnt(newPid);
}
/** /**
* 编辑 * 删除
* *
* @param args / * @param ids /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateDept(SystemDeptTb args) { public void deleteDeptByIds(Set<Long> ids) {
// 旧的部门 // 获取部门, 和其所有子部门
Long oldPid = this.getDeptById(args.getId()).getPid(); Set<SystemDeptTb> depts = this.traverseDeptByIdWithPids(ids);
Long newPid = args.getPid(); // 验证是否被角色或用户关联
if (args.getPid() != null && args.getId().equals(args.getPid())) { this.verifyBindRelationByIds(depts);
throw new BadRequestException("上级不能为自己"); for (SystemDeptTb dept : depts) {
systemDeptMapper.deleteById(dept.getId());
this.updateDeptSubCnt(dept.getPid());
}
}
/**
* 导出数据
*
* @param deptList 待导出的数据
* @param response /
* @throws IOException /
*/
public void exportDeptExcel(List<SystemDeptTb> deptList, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (SystemDeptTb dept : deptList) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("部门名称", dept.getName());
map.put("部门状态", dept.getEnabled() ? "启用" : "停用");
map.put("创建日期", dept.getCreateTime());
list.add(map);
}
KitFileUtil.downloadExcel(list, response);
}
/**
* 更新父节点中子节点数目
*
* @param deptId /
*/
@Transactional(rollbackFor = Exception.class)
public void updateDeptSubCnt(Long deptId) {
if (deptId != null) {
long count = this.countDeptByPid(deptId);
systemDeptMapper.updateDeptSubCountById(count, deptId);
}
}
private long countDeptByPid(Long pid) {
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemDeptTb::getPid, pid);
return systemDeptMapper.selectCount(wrapper);
}
/**
* 筛选出 list 中没有父部门(即 pid 不在其他部门 id 列表中的部门)的部门列表
*/
private List<SystemDeptTb> deduplication(List<SystemDeptTb> list) {
List<SystemDeptTb> deptList = new ArrayList<>();
// 使用 Set 存储所有部门的 id
Set<Long> idSet = list.stream().map(SystemDeptTb::getId).collect(Collectors.toSet());
// 遍历部门列表, 筛选出没有父部门的部门
for (SystemDeptTb dept : list) {
if (!idSet.contains(dept.getPid())) {
deptList.add(dept);
}
}
return deptList;
}
private List<SystemDeptTb> queryDeptByArgs(SystemQueryDeptArgs args) {
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) {
wrapper.in(CollUtil.isNotEmpty(args.getIds()), SystemDeptTb::getId, args.getIds());
wrapper.like(StrUtil.isNotBlank(args.getName()), SystemDeptTb::getName, args.getName());
wrapper.eq(args.getEnabled() != null, SystemDeptTb::getEnabled, args.getEnabled());
wrapper.eq(args.getPid() != null, SystemDeptTb::getPid, args.getPid());
wrapper.isNull(args.getPidIsNull() != null, SystemDeptTb::getPid);
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemDeptTb::getCreateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1));
}
}
wrapper.orderByAsc(SystemDeptTb::getDeptSort);
return systemDeptMapper.selectList(wrapper);
}
/**
* 查询所有数据
*
* @param args 条件
* @param isQuery /
* @return /
* @throws Exception /
*/
public List<SystemDeptTb> queryAllDeptByArgs(SystemQueryDeptArgs args, Boolean isQuery) throws Exception {
String dataScopeType = KitSecurityHelper.getDataScopeType();
if (isQuery) {
if (dataScopeType.equals(SystemDataScopeEnum.ALL.getValue())) {
args.setPidIsNull(true);
}
List<Field> fields = KitClassUtil.getAllFields(args.getClass(), new ArrayList<>());
List<String> fieldNames = new ArrayList<>() {{
add("pidIsNull");
add("enabled");
}};
for (Field field : fields) {
// 设置对象的访问权限, 保证对private的属性的访问
field.setAccessible(true);
Object val = field.get(args);
if (fieldNames.contains(field.getName())) {
continue;
} }
SystemDeptTb dept = systemDeptMapper.selectById(args.getId()); if (ObjectUtil.isNotNull(val)) {
args.setId(dept.getId()); args.setPidIsNull(null);
systemDeptMapper.insertOrUpdate(args); break;
this.updateDeptSubCnt(oldPid);
this.updateDeptSubCnt(newPid);
}
/**
* 删除
*
* @param deptSet /
*/
@Transactional(rollbackFor = Exception.class)
public void deleteDeptByIds(Set<SystemDeptTb> deptSet) {
for (SystemDeptTb dept : deptSet) {
systemDeptMapper.deleteById(dept.getId());
this.updateDeptSubCnt(dept.getPid());
} }
}
} }
// 数据权限
args.setIds(KitSecurityHelper.getCurrentUserDataScope());
List<SystemDeptTb> list = this.queryDeptByArgs(args);
// 如果为空, 就代表为自定义权限或者本级权限, 就需要去重, 不理解可以注释掉,看查询结果
if (StrUtil.isBlank(dataScopeType)) {
return this.deduplication(list);
}
return list;
}
/** /**
* 导出数据 * 根据ID查询
* *
* @param deptList 待导出的数据 * @param id /
* @param response / * @return /
* @throws IOException / */
*/ public SystemDeptTb getDeptById(Long id) {
public void exportDeptExcel(List<SystemDeptTb> deptList, HttpServletResponse response) throws IOException { return systemDeptMapper.selectById(id);
List<Map<String, Object>> list = new ArrayList<>(); }
for (SystemDeptTb dept : deptList) {
Map<String, Object> map = new LinkedHashMap<>(); /**
map.put("部门名称", dept.getName()); * 获取部门下所有关联的部门
map.put("部门状态", dept.getEnabled() ? "启用" : "停用"); *
map.put("创建日期", dept.getCreateTime()); * @param deptTbList /
list.add(map); * @param depts /
* @return /
*/
private Set<SystemDeptTb> queryRelationDeptByArgs(List<SystemDeptTb> deptTbList, Set<SystemDeptTb> depts) {
for (SystemDeptTb dept : deptTbList) {
depts.add(dept);
List<SystemDeptTb> deptList = this.listDeptByPid(dept.getId());
if (CollUtil.isNotEmpty(deptList)) {
queryRelationDeptByArgs(deptList, depts);
}
}
return depts;
}
public List<Long> queryChildDeptIdByDeptIds(List<SystemDeptTb> deptList) {
List<Long> list = new ArrayList<>();
for (SystemDeptTb systemDeptTb : deptList) {
if (systemDeptTb != null && systemDeptTb.getEnabled()) {
List<SystemDeptTb> deptList1 = this.listDeptByPid(systemDeptTb.getId());
if (CollUtil.isNotEmpty(deptList1)) {
list.addAll(queryChildDeptIdByDeptIds(deptList1));
} }
KitFileUtil.downloadExcel(list, response); list.add(systemDeptTb.getId());
}
} }
return list;
}
/** /**
* 更新父节点中子节点数目 * 根据ID获取同级与上级数据
* *
* @param deptId / * @param dept /
*/ * @param deptList /
@Transactional(rollbackFor = Exception.class) * @return /
public void updateDeptSubCnt(Long deptId) { */
if (deptId != null) { private List<SystemDeptTb> querySuperiorDeptByPid(SystemDeptTb dept, List<SystemDeptTb> deptList) {
long count = this.countDeptByPid(deptId); if (dept.getPid() == null) {
systemDeptMapper.updateDeptSubCountById(count, deptId); deptList.addAll(this.listRootDept());
return deptList;
}
deptList.addAll(this.listDeptByPid(dept.getPid()));
return querySuperiorDeptByPid(this.getDeptById(dept.getPid()), deptList);
}
private List<SystemDeptTb> listRootDept() {
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.isNull(SystemDeptTb::getPid);
return systemDeptMapper.selectList(wrapper);
}
/**
* 构建树形数据
*
* @return /
*/
public KitPageResult<SystemDeptTb> searchDeptTree(List<Long> ids, Boolean exclude) {
Set<SystemDeptTb> deptSet1 = new LinkedHashSet<>();
for (Long id : ids) {
// 同级数据
SystemDeptTb dept = this.getDeptById(id);
// 上级数据
List<SystemDeptTb> depts = this.querySuperiorDeptByPid(dept, new ArrayList<>());
if (exclude) {
for (SystemDeptTb data : depts) {
if (data.getId().equals(dept.getPid())) {
data.setSubCount(data.getSubCount() - 1);
}
} }
// 编辑部门时不显示自己以及自己下级的数据, 避免出现PID数据环形问题
depts = depts.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toList());
}
deptSet1.addAll(depts);
} }
ArrayList<SystemDeptTb> deptList = new ArrayList<>(deptSet1);
private long countDeptByPid(Long pid) { // 构建部门树
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>(); Set<SystemDeptTb> trees = new LinkedHashSet<>();
wrapper.eq(SystemDeptTb::getPid, pid); Set<SystemDeptTb> deptSet = new LinkedHashSet<>();
return systemDeptMapper.selectCount(wrapper); List<String> deptNames = deptList.stream().map(SystemDeptTb::getName).collect(Collectors.toList());
} boolean isChild;
for (SystemDeptTb dept : deptList) {
/** isChild = false;
* 筛选出 list 中没有父部门(即 pid 不在其他部门 id 列表中的部门)的部门列表 if (dept.getPid() == null) {
*/ trees.add(dept);
private List<SystemDeptTb> deduplication(List<SystemDeptTb> list) { }
List<SystemDeptTb> deptList = new ArrayList<>(); for (SystemDeptTb it : deptList) {
// 使用 Set 存储所有部门的 id if (it.getPid() != null && dept.getId().equals(it.getPid())) {
Set<Long> idSet = list.stream().map(SystemDeptTb::getId).collect(Collectors.toSet()); isChild = true;
// 遍历部门列表, 筛选出没有父部门的部门 if (dept.getChildren() == null) {
for (SystemDeptTb dept : list) { dept.setChildren(new ArrayList<>());
if (!idSet.contains(dept.getPid())) { }
deptList.add(dept); dept.getChildren().add(it);
}
} }
return deptList; }
if (isChild) {
deptSet.add(dept);
} else if (dept.getPid() != null && !deptNames.contains(this.getDeptById(dept.getPid()).getName())) {
deptSet.add(dept);
}
} }
if (CollectionUtil.isEmpty(trees)) {
trees = deptSet;
}
KitPageResult<SystemDeptTb> baseResult = new KitPageResult<>();
baseResult.setContent(CollectionUtil.isEmpty(trees) ? new ArrayList<>(deptSet) : new ArrayList<>(trees));
baseResult.setTotalElements(deptSet.size());
return baseResult;
}
private List<SystemDeptTb> queryDeptByArgs(SystemQueryDeptArgs args) { /**
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>(); * 验证是否被角色或用户关联
if (args != null) { *
wrapper.in(CollUtil.isNotEmpty(args.getIds()), SystemDeptTb::getId, args.getIds()); * @param deptSet /
wrapper.like(StrUtil.isNotBlank(args.getName()), SystemDeptTb::getName, args.getName()); */
wrapper.eq(args.getEnabled() != null, SystemDeptTb::getEnabled, args.getEnabled()); public void verifyBindRelationByIds(Set<SystemDeptTb> deptSet) {
wrapper.eq(args.getPid() != null, SystemDeptTb::getPid, args.getPid()); Set<Long> deptIds = deptSet.stream().map(SystemDeptTb::getId).collect(Collectors.toSet());
wrapper.isNull(args.getPidIsNull() != null, SystemDeptTb::getPid); if (systemUserDeptService.countUserByDeptIds(deptIds) > 0) {
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { throw new BadRequestException("所选部门存在用户关联,请解除后再试!");
wrapper.between(SystemDeptTb::getCreateTime, args.getCreateTime().get(0), args.getCreateTime().get(1));
}
}
wrapper.orderByAsc(SystemDeptTb::getDeptSort);
return systemDeptMapper.selectList(wrapper);
} }
if (systemRoleDeptService.countRoleByDeptIds(deptIds) > 0) {
throw new BadRequestException("所选部门存在角色关联,请解除后再试!");
}
}
/** private List<SystemDeptTb> listEnabledDepts() {
* 查询所有数据 LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>();
* wrapper.eq(SystemDeptTb::getEnabled, 1);
* @param args 条件 return systemDeptMapper.selectList(wrapper);
* @param isQuery / }
* @return /
* @throws Exception /
*/
public List<SystemDeptTb> queryAllDeptByArgs(SystemQueryDeptArgs args, Boolean isQuery) throws Exception {
String dataScopeType = KitSecurityHelper.getDataScopeType();
if (isQuery) {
if (dataScopeType.equals(SystemDataScopeEnum.ALL.getValue())) {
args.setPidIsNull(true);
}
List<Field> fields = KitClassUtil.getAllFields(args.getClass(), new ArrayList<>());
List<String> fieldNames = new ArrayList<>() {{
add("pidIsNull");
add("enabled");
}};
for (Field field : fields) {
// 设置对象的访问权限, 保证对private的属性的访问
field.setAccessible(true);
Object val = field.get(args);
if (fieldNames.contains(field.getName())) {
continue;
}
if (ObjectUtil.isNotNull(val)) {
args.setPidIsNull(null);
break;
}
}
}
// 数据权限
args.setIds(KitSecurityHelper.getCurrentUserDataScope());
List<SystemDeptTb> list = this.queryDeptByArgs(args);
// 如果为空, 就代表为自定义权限或者本级权限, 就需要去重, 不理解可以注释掉,看查询结果
if (StrUtil.isBlank(dataScopeType)) {
return this.deduplication(list);
}
return list;
}
/** /**
* 根据ID查询 * 遍历所有部门和子部门
* *
* @param id / * @param ids /
* @return / */
*/ public Set<SystemDeptTb> traverseDeptByIdWithPids(Set<Long> ids) {
public SystemDeptTb getDeptById(Long id) { Set<SystemDeptTb> depts = new HashSet<>();
return systemDeptMapper.selectById(id); for (Long id : ids) {
// 根部门
depts.add(this.getDeptById(id));
// 子部门
List<SystemDeptTb> deptList = listDeptByPid(id);
if (CollectionUtil.isNotEmpty(deptList)) {
depts = queryRelationDeptByArgs(deptList, depts);
}
} }
return depts;
}
/** public List<SystemProductLineVo> queryDeptSelectDataSource() {
* 获取部门下所有关联的部门 List<SystemDeptTb> depts = this.listEnabledDepts();
* return buildDeptSelectOptions(depts);
* @param deptTbList / }
* @param depts /
* @return /
*/
private Set<SystemDeptTb> queryRelationDeptByArgs(List<SystemDeptTb> deptTbList, Set<SystemDeptTb> depts) {
for (SystemDeptTb dept : deptTbList) {
depts.add(dept);
List<SystemDeptTb> deptList = this.listDeptByPid(dept.getId());
if (CollUtil.isNotEmpty(deptList)) {
queryRelationDeptByArgs(deptList, depts);
}
}
return depts;
}
public List<Long> queryChildDeptIdByDeptIds(List<SystemDeptTb> deptList) { private List<SystemProductLineVo> buildDeptSelectOptions(List<SystemDeptTb> depts) {
List<Long> list = new ArrayList<>(); // 获取所有部门并按父子关系组织
for (SystemDeptTb systemDeptTb : deptList) { Map<Long, SystemDeptTb> deptMap =
if (systemDeptTb != null && systemDeptTb.getEnabled()) { depts.stream().collect(Collectors.toMap(SystemDeptTb::getId, Function.identity()));
List<SystemDeptTb> deptList1 = this.listDeptByPid(systemDeptTb.getId()); List<SystemProductLineVo> options = new ArrayList<>();
if (CollUtil.isNotEmpty(deptList1)) { for (SystemDeptTb dept : depts) {
list.addAll(queryChildDeptIdByDeptIds(deptList1)); // 构建部门ID路径
} List<Long> pathIds = new ArrayList<>();
list.add(systemDeptTb.getId()); buildDeptIdPath(dept, deptMap, pathIds);
} // 反转路径,从顶级部门到当前部门
} Collections.reverse(pathIds);
return list; SystemProductLineVo dto = new SystemProductLineVo();
dto.setValue(dept.getId());
dto.setIdPath(pathIds.stream().map(String::valueOf).collect(Collectors.joining("-")));
// 保留名称路径用于显示
dto.setLabel(buildNamePath(dept, deptMap));
options.add(dto);
} }
// 按部门名称路径排序
options.sort(Comparator.comparing(SystemProductLineVo::getLabel));
return options;
}
/** private void buildDeptIdPath(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap, List<Long> pathIds) {
* 根据ID获取同级与上级数据 pathIds.add(dept.getId());
* if (dept.getPid() != null && dept.getPid() != 0 && deptMap.containsKey(dept.getPid())) {
* @param dept / buildDeptIdPath(deptMap.get(dept.getPid()), deptMap, pathIds);
* @param deptList /
* @return /
*/
private List<SystemDeptTb> querySuperiorDeptByPid(SystemDeptTb dept, List<SystemDeptTb> deptList) {
if (dept.getPid() == null) {
deptList.addAll(this.listRootDept());
return deptList;
}
deptList.addAll(this.listDeptByPid(dept.getPid()));
return querySuperiorDeptByPid(this.getDeptById(dept.getPid()), deptList);
} }
}
private List<SystemDeptTb> listRootDept() { private String buildNamePath(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap) {
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>(); List<String> pathNames = new ArrayList<>();
wrapper.isNull(SystemDeptTb::getPid); buildDeptNamePath(dept, deptMap, pathNames);
return systemDeptMapper.selectList(wrapper); Collections.reverse(pathNames);
} return String.join(" / ", pathNames);
}
/** private void buildDeptNamePath(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap, List<String> pathNames) {
* 构建树形数据 pathNames.add(dept.getName());
* if (dept.getPid() != null && dept.getPid() != 0 && deptMap.containsKey(dept.getPid())) {
* @return / buildDeptNamePath(deptMap.get(dept.getPid()), deptMap, pathNames);
*/
public KitPageResult<SystemDeptTb> searchDeptTree(List<Long> ids, Boolean exclude) {
Set<SystemDeptTb> deptSet1 = new LinkedHashSet<>();
for (Long id : ids) {
// 同级数据
SystemDeptTb dept = this.getDeptById(id);
// 上级数据
List<SystemDeptTb> depts = this.querySuperiorDeptByPid(dept, new ArrayList<>());
if (exclude) {
for (SystemDeptTb data : depts) {
if (data.getId().equals(dept.getPid())) {
data.setSubCount(data.getSubCount() - 1);
}
}
// 编辑部门时不显示自己以及自己下级的数据, 避免出现PID数据环形问题
depts = depts.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toList());
}
deptSet1.addAll(depts);
}
ArrayList<SystemDeptTb> deptList = new ArrayList<>(deptSet1);
// 构建部门树
Set<SystemDeptTb> trees = new LinkedHashSet<>();
Set<SystemDeptTb> deptSet = new LinkedHashSet<>();
List<String> deptNames = deptList.stream().map(SystemDeptTb::getName).collect(Collectors.toList());
boolean isChild;
for (SystemDeptTb dept : deptList) {
isChild = false;
if (dept.getPid() == null) {
trees.add(dept);
}
for (SystemDeptTb it : deptList) {
if (it.getPid() != null && dept.getId().equals(it.getPid())) {
isChild = true;
if (dept.getChildren() == null) {
dept.setChildren(new ArrayList<>());
}
dept.getChildren().add(it);
}
}
if (isChild) {
deptSet.add(dept);
} else if (dept.getPid() != null && !deptNames.contains(this.getDeptById(dept.getPid()).getName())) {
deptSet.add(dept);
}
}
if (CollectionUtil.isEmpty(trees)) {
trees = deptSet;
}
KitPageResult<SystemDeptTb> baseResult = new KitPageResult<>();
baseResult.setContent(CollectionUtil.isEmpty(trees) ? new ArrayList<>(deptSet) : new ArrayList<>(trees));
baseResult.setTotalElements(deptSet.size());
return baseResult;
} }
}
/** public List<SystemProductLineTreeVo> queryDeptSelectProDataSource() {
* 验证是否被角色或用户关联 List<SystemDeptTb> depts = this.listEnabledDepts();
* // 获取所有部门并按父子关系组织
* @param deptSet / Map<Long, SystemDeptTb> deptMap =
*/ depts.stream().collect(Collectors.toMap(SystemDeptTb::getId, Function.identity()));
public void verifyBindRelationByIds(Set<SystemDeptTb> deptSet) { List<SystemProductLineTreeVo> options = new ArrayList<>();
Set<Long> deptIds = deptSet.stream().map(SystemDeptTb::getId).collect(Collectors.toSet()); // 构建树形结构
if (systemUserService.countUserByDeptIds(deptIds) > 0) { for (SystemDeptTb dept : depts) {
throw new BadRequestException("所选部门存在用户关联,请解除后再试!"); // 只处理顶级部门(pid为null或0的部门)
} if (dept.getPid() == null || dept.getPid() == 0) {
if (systemRoleService.countRoleByDeptIds(deptIds) > 0) { SystemProductLineTreeVo vo = buildDeptTreePro(dept, deptMap);
throw new BadRequestException("所选部门存在角色关联,请解除后再试!"); options.add(vo);
} }
} }
// 按排序字段排序
options.sort(Comparator.comparingInt(o -> {
Long id = Long.valueOf(o.getValue());
return deptMap.get(id) != null ? deptMap.get(id).getDeptSort() : 0;
}));
return options;
}
private List<SystemDeptTb> listEnabledDepts() { /**
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>(); * 递归构建部门树
wrapper.eq(SystemDeptTb::getEnabled, 1); *
return systemDeptMapper.selectList(wrapper); * @param dept 当前部门
* @param deptMap 部门映射
* @return SystemProductLineTreeVo 树节点
*/
private SystemProductLineTreeVo buildDeptTreePro(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap) {
SystemProductLineTreeVo vo = new SystemProductLineTreeVo();
vo.setValue(String.valueOf(dept.getId()));
vo.setLabel(dept.getName());
// 查找子部门
List<SystemProductLineTreeVo> children = new ArrayList<>();
for (SystemDeptTb childDept : deptMap.values()) {
if (dept.getId().equals(childDept.getPid())) {
children.add(buildDeptTreePro(childDept, deptMap));
}
} }
// 子部门按排序字段排序
children.sort(Comparator.comparingInt(o -> {
Long id = Long.valueOf(o.getValue());
return deptMap.get(id) != null ? deptMap.get(id).getDeptSort() : 0;
}));
vo.setChildren(children);
return vo;
}
/** public List<SystemDeptTb> listDeptByPid(long pid) {
* 遍历所有部门和子部门 LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>();
* wrapper.eq(SystemDeptTb::getPid, pid);
* @param ids / return systemDeptMapper.selectList(wrapper);
*/ }
public Set<SystemDeptTb> traverseDeptByIdWithPids(Set<Long> ids) {
Set<SystemDeptTb> depts = new HashSet<>();
for (Long id : ids) {
// 根部门
depts.add(this.getDeptById(id));
// 子部门
List<SystemDeptTb> deptList = listDeptByPid(id);
if (CollectionUtil.isNotEmpty(deptList)) {
depts = queryRelationDeptByArgs(deptList, depts);
}
}
return depts;
}
public List<SystemProductLineVo> queryDeptSelectDataSource() {
List<SystemDeptTb> depts = this.listEnabledDepts();
return buildDeptSelectOptions(depts);
}
private List<SystemProductLineVo> buildDeptSelectOptions(List<SystemDeptTb> depts) {
// 获取所有部门并按父子关系组织
Map<Long, SystemDeptTb> deptMap =
depts.stream().collect(Collectors.toMap(SystemDeptTb::getId, Function.identity()));
List<SystemProductLineVo> options = new ArrayList<>();
for (SystemDeptTb dept : depts) {
// 构建部门ID路径
List<Long> pathIds = new ArrayList<>();
buildDeptIdPath(dept, deptMap, pathIds);
// 反转路径,从顶级部门到当前部门
Collections.reverse(pathIds);
SystemProductLineVo dto = new SystemProductLineVo();
dto.setValue(dept.getId());
dto.setIdPath(pathIds.stream().map(String::valueOf).collect(Collectors.joining("-")));
// 保留名称路径用于显示
dto.setLabel(buildNamePath(dept, deptMap));
options.add(dto);
}
// 按部门名称路径排序
options.sort(Comparator.comparing(SystemProductLineVo::getLabel));
return options;
}
private void buildDeptIdPath(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap, List<Long> pathIds) {
pathIds.add(dept.getId());
if (dept.getPid() != null && dept.getPid() != 0 && deptMap.containsKey(dept.getPid())) {
buildDeptIdPath(deptMap.get(dept.getPid()), deptMap, pathIds);
}
}
private String buildNamePath(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap) {
List<String> pathNames = new ArrayList<>();
buildDeptNamePath(dept, deptMap, pathNames);
Collections.reverse(pathNames);
return String.join(" / ", pathNames);
}
private void buildDeptNamePath(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap, List<String> pathNames) {
pathNames.add(dept.getName());
if (dept.getPid() != null && dept.getPid() != 0 && deptMap.containsKey(dept.getPid())) {
buildDeptNamePath(deptMap.get(dept.getPid()), deptMap, pathNames);
}
}
public List<SystemProductLineTreeVo> queryDeptSelectProDataSource() {
List<SystemDeptTb> depts = this.listEnabledDepts();
// 获取所有部门并按父子关系组织
Map<Long, SystemDeptTb> deptMap =
depts.stream().collect(Collectors.toMap(SystemDeptTb::getId, Function.identity()));
List<SystemProductLineTreeVo> options = new ArrayList<>();
// 构建树形结构
for (SystemDeptTb dept : depts) {
// 只处理顶级部门(pid为null或0的部门)
if (dept.getPid() == null || dept.getPid() == 0) {
SystemProductLineTreeVo vo = buildDeptTreePro(dept, deptMap);
options.add(vo);
}
}
// 按排序字段排序
options.sort(Comparator.comparingInt(o -> {
Long id = Long.valueOf(o.getValue());
return deptMap.get(id) != null ? deptMap.get(id).getDeptSort() : 0;
}));
return options;
}
/**
* 递归构建部门树
*
* @param dept 当前部门
* @param deptMap 部门映射
* @return SystemProductLineTreeVo 树节点
*/
private SystemProductLineTreeVo buildDeptTreePro(SystemDeptTb dept, Map<Long, SystemDeptTb> deptMap) {
SystemProductLineTreeVo vo = new SystemProductLineTreeVo();
vo.setValue(String.valueOf(dept.getId()));
vo.setLabel(dept.getName());
// 查找子部门
List<SystemProductLineTreeVo> children = new ArrayList<>();
for (SystemDeptTb childDept : deptMap.values()) {
if (dept.getId().equals(childDept.getPid())) {
children.add(buildDeptTreePro(childDept, deptMap));
}
}
// 子部门按排序字段排序
children.sort(Comparator.comparingInt(o -> {
Long id = Long.valueOf(o.getValue());
return deptMap.get(id) != null ? deptMap.get(id).getDeptSort() : 0;
}));
vo.setChildren(children);
return vo;
}
public List<SystemDeptTb> listDeptByPid(long pid) {
LambdaQueryWrapper<SystemDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemDeptTb::getPid, pid);
return systemDeptMapper.selectList(wrapper);
}
} }
@@ -31,6 +31,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -134,4 +135,13 @@ public class SystemDictDetailService {
return detailVo; return detailVo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
public Map<String, List<SystemDictDetailVo>> getDictDetailMap(String dictName) {
String[] names = dictName.split("[,, ]");
Map<String, List<SystemDictDetailVo>> dictMap = new HashMap<>(16);
for (String name : names) {
dictMap.put(name, this.listDictDetailByName(name));
}
return dictMap;
}
} }
@@ -29,13 +29,13 @@ import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -43,103 +43,105 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemDictService { public class SystemDictService {
@Autowired private SystemDictMapper systemDictMapper; @Autowired
@Autowired private SystemDictDetailService systemDictDetailService; private SystemDictMapper systemDictMapper;
@Autowired
private SystemDictDetailService systemDictDetailService;
/** /**
* 创建 * 创建
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveDict(SystemCreateDictArgs args) { public void saveDict(SystemCreateDictArgs args) {
systemDictMapper.insert(BeanUtil.copyProperties(args, SystemDictTb.class)); systemDictMapper.insert(BeanUtil.copyProperties(args, SystemDictTb.class));
} }
/** /**
* 编辑 * 编辑
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateDictById(SystemDictTb args) { public void updateDictById(SystemDictTb args) {
SystemDictTb dict = systemDictMapper.selectById(args.getId()); SystemDictTb dict = systemDictMapper.selectById(args.getId());
dict.setName(args.getName()); dict.setName(args.getName());
dict.setDescription(args.getDescription()); dict.setDescription(args.getDescription());
systemDictMapper.insertOrUpdate(dict); systemDictMapper.insertOrUpdate(dict);
} }
/** /**
* 删除 * 删除
* *
* @param ids / * @param ids /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteDictByIds(Set<Long> ids) { public void deleteDictByIds(Set<Long> ids) {
// 删除字典 // 删除字典
systemDictMapper.deleteByIds(ids); systemDictMapper.deleteByIds(ids);
// 删除字典详情 // 删除字典详情
systemDictDetailService.deleteDictDetailByDictIds(ids); systemDictDetailService.deleteDictDetailByDictIds(ids);
} }
/** /**
* 导出数据 * 导出数据
* *
* @param dicts 待导出的数据 * @param dicts 待导出的数据
* @param response / * @param response /
* @throws IOException / * @throws IOException /
*/ */
public void exportDictExcel(List<SystemDictTb> dicts, HttpServletResponse response) throws IOException { public void exportDictExcel(List<SystemDictTb> dicts, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (SystemDictTb dict : dicts) { for (SystemDictTb dict : dicts) {
List<SystemDictDetailVo> dictDetails = systemDictDetailService.listDictDetailByName(dict.getName()); List<SystemDictDetailVo> dictDetails = systemDictDetailService.listDictDetailByName(dict.getName());
if (CollectionUtil.isNotEmpty(dictDetails)) { if (CollectionUtil.isNotEmpty(dictDetails)) {
for (SystemDictDetailTb dictDetail : dictDetails) { for (SystemDictDetailTb dictDetail : dictDetails) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("字典名称", dict.getName()); map.put("字典名称", dict.getName());
map.put("字典描述", dict.getDescription()); map.put("字典描述", dict.getDescription());
map.put("字典标签", dictDetail.getLabel()); map.put("字典标签", dictDetail.getLabel());
map.put("字典值", dictDetail.getValue()); map.put("字典值", dictDetail.getValue());
map.put("创建日期", dictDetail.getCreateTime()); map.put("创建日期", dictDetail.getCreateTime());
list.add(map); list.add(map);
}
} else {
Map<String, Object> map = new LinkedHashMap<>();
map.put("字典名称", dict.getName());
map.put("字典描述", dict.getDescription());
map.put("字典标签", null);
map.put("字典值", null);
map.put("创建日期", dict.getCreateTime());
list.add(map);
}
} }
KitFileUtil.downloadExcel(list, response); } else {
Map<String, Object> map = new LinkedHashMap<>();
map.put("字典名称", dict.getName());
map.put("字典描述", dict.getDescription());
map.put("字典标签", null);
map.put("字典值", null);
map.put("创建日期", dict.getCreateTime());
list.add(map);
}
} }
KitFileUtil.downloadExcel(list, response);
}
/** /**
* 分页查询 * 分页查询
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
* @return / * @return /
*/ */
public KitPageResult<SystemDictTb> searchDict(SystemQueryDictArgs args, Page<SystemDictTb> page) { public KitPageResult<SystemDictTb> searchDict(SystemQueryDictArgs args, Page<SystemDictTb> page) {
LambdaQueryWrapper<SystemDictTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemDictTb> wrapper = new LambdaQueryWrapper<>();
injectQueryParams(args, wrapper); injectQueryParams(args, wrapper);
Page<SystemDictTb> selectPage = systemDictMapper.selectPage(page, wrapper); Page<SystemDictTb> selectPage = systemDictMapper.selectPage(page, wrapper);
return KitPageUtil.toPage(selectPage); return KitPageUtil.toPage(selectPage);
} }
private void injectQueryParams(SystemQueryDictArgs args, LambdaQueryWrapper<SystemDictTb> wrapper) { private void injectQueryParams(SystemQueryDictArgs args, LambdaQueryWrapper<SystemDictTb> wrapper) {
if (args != null) { if (args != null) {
wrapper.and(StrUtil.isNotBlank(args.getBlurry()), c -> c.like(SystemDictTb::getName, args.getBlurry()).or() wrapper.and(StrUtil.isNotBlank(args.getBlurry()), c -> c.like(SystemDictTb::getName, args.getBlurry()).or()
.like(SystemDictTb::getDescription, args.getBlurry())); .like(SystemDictTb::getDescription, args.getBlurry()));
}
} }
}
public List<SystemDictTb> queryDictByArgs(SystemQueryDictArgs args) { public List<SystemDictTb> queryDictByArgs(SystemQueryDictArgs args) {
LambdaQueryWrapper<SystemDictTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemDictTb> wrapper = new LambdaQueryWrapper<>();
injectQueryParams(args, wrapper); injectQueryParams(args, wrapper);
return systemDictMapper.selectList(wrapper); return systemDictMapper.selectList(wrapper);
} }
} }
@@ -24,6 +24,7 @@ import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper; import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.constant.SystemCaptchaBizEnum; import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.dataobject.SystemEmailConfigTb; import cn.odboy.system.dal.dataobject.SystemEmailConfigTb;
import cn.odboy.system.dal.model.SystemCheckEmailCaptchaArgs;
import cn.odboy.system.dal.model.SystemSendEmailArgs; import cn.odboy.system.dal.model.SystemSendEmailArgs;
import cn.odboy.system.dal.mysql.SystemEmailConfigMapper; import cn.odboy.system.dal.mysql.SystemEmailConfigMapper;
import cn.odboy.util.KitDesEncryptUtil; import cn.odboy.util.KitDesEncryptUtil;
@@ -39,114 +40,126 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemEmailService { public class SystemEmailService {
@Autowired private SystemEmailConfigMapper systemEmailConfigMapper; @Autowired
@Autowired private KitRedisHelper redisHelper; private SystemEmailConfigMapper systemEmailConfigMapper;
@Autowired private AppProperties properties; @Autowired
@Value("${spring.application.title}") private String applicationTitle; private KitRedisHelper redisHelper;
@Autowired
private AppProperties properties;
@Value("${spring.application.title}")
private String applicationTitle;
/** /**
* 更新邮件配置 * 更新邮件配置
* *
* @param emailConfig 邮箱配置 * @param emailConfig 邮箱配置
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateEmailConfigById(SystemEmailConfigTb emailConfig) throws Exception { public void updateEmailConfigById(SystemEmailConfigTb emailConfig) throws Exception {
SystemEmailConfigTb systemEmailConfigTb = getLastEmailConfig(); SystemEmailConfigTb systemEmailConfigTb = getLastEmailConfig();
if (!emailConfig.getPassword().equals(systemEmailConfigTb.getPassword())) { if (!emailConfig.getPassword().equals(systemEmailConfigTb.getPassword())) {
// 对称加密 // 对称加密
systemEmailConfigTb.setPassword(KitDesEncryptUtil.desEncrypt(emailConfig.getPassword())); systemEmailConfigTb.setPassword(KitDesEncryptUtil.desEncrypt(emailConfig.getPassword()));
}
systemEmailConfigTb.setId(1L);
systemEmailConfigMapper.insertOrUpdate(systemEmailConfigTb);
} }
systemEmailConfigTb.setId(1L);
systemEmailConfigMapper.insertOrUpdate(systemEmailConfigTb);
}
/** /**
* 发送邮件 * 发送邮件
* *
* @param sendEmailRequest 邮件发送的内容 * @param sendEmailRequest 邮件发送的内容
*/ */
public void sendEmail(SystemSendEmailArgs sendEmailRequest) { public void sendEmail(SystemSendEmailArgs sendEmailRequest) {
SystemEmailConfigTb systemEmailConfigTb = getLastEmailConfig(); SystemEmailConfigTb systemEmailConfigTb = getLastEmailConfig();
if (systemEmailConfigTb.getId() == null) { if (systemEmailConfigTb.getId() == null) {
throw new BadRequestException("请先配置, 再操作"); throw new BadRequestException("请先配置, 再操作");
}
// 封装
MailAccount account = new MailAccount();
// 设置用户
String user = systemEmailConfigTb.getFromUser().split("@")[0];
account.setUser(user);
account.setHost(systemEmailConfigTb.getHost());
account.setPort(Integer.parseInt(systemEmailConfigTb.getPort()));
account.setAuth(true);
try {
// 对称解密
account.setPass(KitDesEncryptUtil.desDecrypt(systemEmailConfigTb.getPassword()));
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
account.setFrom(systemEmailConfigTb.getUser() + "<" + systemEmailConfigTb.getFromUser() + ">");
// ssl方式发送
account.setSslEnable(true);
// 使用STARTTLS安全连接
account.setStarttlsEnable(true);
// 解决jdk8之后默认禁用部分tls协议, 导致邮件发送失败的问题
account.setSslProtocols("TLSv1 TLSv1.1 TLSv1.2");
String content = sendEmailRequest.getContent();
// 发送
try {
int size = sendEmailRequest.getTos().size();
Mail.create(account).setTos(sendEmailRequest.getTos().toArray(new String[size]))
.setTitle(sendEmailRequest.getSubject()).setContent(content).setHtml(true)
// 关闭session
.setUseGlobalSession(false).send();
} catch (Exception e) {
log.error("邮件发送失败", e);
throw new BadRequestException("邮件发送失败");
}
} }
// 封装
MailAccount account = new MailAccount();
// 设置用户
String user = systemEmailConfigTb.getFromUser().split("@")[0];
account.setUser(user);
account.setHost(systemEmailConfigTb.getHost());
account.setPort(Integer.parseInt(systemEmailConfigTb.getPort()));
account.setAuth(true);
try {
// 对称解密
account.setPass(KitDesEncryptUtil.desDecrypt(systemEmailConfigTb.getPassword()));
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
account.setFrom(systemEmailConfigTb.getUser() + "<" + systemEmailConfigTb.getFromUser() + ">");
// ssl方式发送
account.setSslEnable(true);
// 使用STARTTLS安全连接
account.setStarttlsEnable(true);
// 解决jdk8之后默认禁用部分tls协议, 导致邮件发送失败的问题
account.setSslProtocols("TLSv1 TLSv1.1 TLSv1.2");
String content = sendEmailRequest.getContent();
// 发送
try {
int size = sendEmailRequest.getTos().size();
Mail.create(account).setTos(sendEmailRequest.getTos().toArray(new String[size]))
.setTitle(sendEmailRequest.getSubject()).setContent(content).setHtml(true)
// 关闭session
.setUseGlobalSession(false).send();
} catch (Exception e) {
log.error("邮件发送失败", e);
throw new BadRequestException("邮件发送失败");
}
}
/** /**
* 校验邮箱验证码 * 校验邮箱验证码
*/ */
public void checkEmailCaptcha(SystemCaptchaBizEnum biEnum, String email, String code) { public void checkEmailCaptchaV1(SystemCaptchaBizEnum biEnum, String email, String code) {
String redisKey = biEnum.getRedisKey() + email; String redisKey = biEnum.getRedisKey() + email;
String value = redisHelper.get(redisKey, String.class); String value = redisHelper.get(redisKey, String.class);
if (value == null || !value.equals(code)) { if (value == null || !value.equals(code)) {
throw new BadRequestException("无效验证码"); throw new BadRequestException("无效验证码");
} else { } else {
redisHelper.del(redisKey); redisHelper.del(redisKey);
}
} }
}
/** /**
* 发送给邮箱验证码 * 发送给邮箱验证码
*/ */
public void sendCaptcha(SystemCaptchaBizEnum biEnum, String email) { public void sendCaptcha(SystemCaptchaBizEnum biEnum, String email) {
if (biEnum == null) { if (biEnum == null) {
throw new BadRequestException("biEnum必填"); throw new BadRequestException("biEnum必填");
}
String content;
String redisKey = biEnum.getRedisKey() + email;
String oldCode = redisHelper.get(redisKey, String.class);
if (oldCode == null) {
String code = RandomUtil.randomNumbers(6);
// 存入缓存
if (!redisHelper.set(redisKey, code, properties.getCaptcha().getExpireTime())) {
throw new BadRequestException("服务异常, 请联系网站负责人");
}
// 存在就再次发送原来的验证码
content = KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", code));
} else {
content =
KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", oldCode));
}
SystemSendEmailArgs sendEmailRequest =
new SystemSendEmailArgs(Collections.singletonList(email), applicationTitle, content);
sendEmail(sendEmailRequest);
} }
String content;
String redisKey = biEnum.getRedisKey() + email;
String oldCode = redisHelper.get(redisKey, String.class);
if (oldCode == null) {
String code = RandomUtil.randomNumbers(6);
// 存入缓存
if (!redisHelper.set(redisKey, code, properties.getCaptcha().getExpireTime())) {
throw new BadRequestException("服务异常, 请联系网站负责人");
}
// 存在就再次发送原来的验证码
content = KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", code));
} else {
content =
KitResourceTemplateUtil.render(null, biEnum.getTemplateName(), Dict.create().set("code", oldCode));
}
SystemSendEmailArgs sendEmailRequest =
new SystemSendEmailArgs(Collections.singletonList(email), applicationTitle, content);
sendEmail(sendEmailRequest);
}
public SystemEmailConfigTb getLastEmailConfig() { public SystemEmailConfigTb getLastEmailConfig() {
SystemEmailConfigTb systemEmailConfigTb = systemEmailConfigMapper.selectById(1L); SystemEmailConfigTb systemEmailConfigTb = systemEmailConfigMapper.selectById(1L);
return systemEmailConfigTb == null ? new SystemEmailConfigTb() : systemEmailConfigTb; return systemEmailConfigTb == null ? new SystemEmailConfigTb() : systemEmailConfigTb;
}
public void checkEmailCaptcha(SystemCheckEmailCaptchaArgs args) {
SystemCaptchaBizEnum biEnum = SystemCaptchaBizEnum.getByBizCode(args.getBizCode());
if (biEnum == null) {
throw new BadRequestException("不支持的业务");
} }
this.checkEmailCaptchaV1(biEnum, args.getEmail(), args.getCode());
}
} }
@@ -28,13 +28,13 @@ import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -42,114 +42,119 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemJobService { public class SystemJobService {
@Autowired private SystemJobMapper systemJobMapper; @Autowired
@Autowired private SystemUserService systemUserService; private SystemJobMapper systemJobMapper;
@Autowired
private SystemUserService systemUserService;
/** /**
* 创建 * 创建
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveJob(SystemCreateJobArgs args) { public void saveJob(SystemCreateJobArgs args) {
SystemJobTb job = this.getJobByName(args.getName()); SystemJobTb job = this.getJobByName(args.getName());
if (job != null) { if (job != null) {
throw new BadRequestException("职位名称已存在"); throw new BadRequestException("职位名称已存在");
}
systemJobMapper.insert(BeanUtil.copyProperties(args, SystemJobTb.class));
} }
systemJobMapper.insert(BeanUtil.copyProperties(args, SystemJobTb.class));
}
/** /**
* 编辑 * 编辑
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateJobById(SystemJobTb args) { public void updateJobById(SystemJobTb args) {
SystemJobTb job = systemJobMapper.selectById(args.getId()); SystemJobTb job = systemJobMapper.selectById(args.getId());
SystemJobTb old = this.getJobByName(args.getName()); SystemJobTb old = this.getJobByName(args.getName());
if (old != null && !old.getId().equals(args.getId())) { if (old != null && !old.getId().equals(args.getId())) {
throw new BadRequestException("职位名称已存在"); throw new BadRequestException("职位名称已存在");
}
args.setId(job.getId());
systemJobMapper.insertOrUpdate(args);
} }
args.setId(job.getId());
systemJobMapper.insertOrUpdate(args);
}
/** /**
* 删除 * 删除
* *
* @param ids / * @param ids /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteJobByIds(Set<Long> ids) { public void deleteJobByIds(Set<Long> ids) {
systemJobMapper.deleteByIds(ids); // 验证是否被用户关联
} this.verifyBindRelationByIds(ids);
systemJobMapper.deleteByIds(ids);
}
/** /**
* 导出数据 * 导出数据
* *
* @param jobs 待导出的数据 * @param jobs 待导出的数据
* @param response / * @param response /
*/ */
public void exportJobExcel(List<SystemJobTb> jobs, HttpServletResponse response) throws IOException { public void exportJobExcel(List<SystemJobTb> jobs, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (SystemJobTb job : jobs) { for (SystemJobTb job : jobs) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("岗位名称", job.getName()); map.put("岗位名称", job.getName());
map.put("岗位状态", job.getEnabled() ? "启用" : "停用"); map.put("岗位状态", job.getEnabled() ? "启用" : "停用");
map.put("创建日期", job.getCreateTime()); map.put("创建日期", job.getCreateTime());
list.add(map); list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
KitFileUtil.downloadExcel(list, response);
}
/** /**
* 分页查询 * 分页查询
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
*/ */
public KitPageResult<SystemJobTb> searchJobByArgs(SystemQueryJobArgs args, Page<SystemJobTb> page) { public KitPageResult<SystemJobTb> searchJobByArgs(SystemQueryJobArgs args, Page<SystemJobTb> page) {
LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>();
this.injectQueryParams(args, wrapper); this.injectQueryParams(args, wrapper);
Page<SystemJobTb> selectPage = systemJobMapper.selectPage(page, wrapper); Page<SystemJobTb> selectPage = systemJobMapper.selectPage(page, wrapper);
return KitPageUtil.toPage(selectPage); return KitPageUtil.toPage(selectPage);
} }
/** /**
* 查询全部数据 * 查询全部数据
*/ */
public List<SystemJobTb> queryJobByArgs(SystemQueryJobArgs args) { public List<SystemJobTb> queryJobByArgs(SystemQueryJobArgs args) {
LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>();
this.injectQueryParams(args, wrapper); this.injectQueryParams(args, wrapper);
return systemJobMapper.selectList(wrapper); return systemJobMapper.selectList(wrapper);
} }
/** /**
* 验证是否被用户关联 * 验证是否被用户关联
* *
* @param ids / * @param ids /
*/ */
public void verifyBindRelationByIds(Set<Long> ids) { public void verifyBindRelationByIds(Set<Long> ids) {
if (systemUserService.countUserByJobIds(ids) > 0) { if (systemUserService.countUserByJobIds(ids) > 0) {
throw new BadRequestException("所选的岗位中存在用户关联, 请解除关联再试!"); throw new BadRequestException("所选的岗位中存在用户关联, 请解除关联再试!");
}
} }
}
public SystemJobTb getJobByName(String name) { public SystemJobTb getJobByName(String name) {
LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemJobTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemJobTb::getName, name); wrapper.eq(SystemJobTb::getName, name);
return systemJobMapper.selectOne(wrapper); return systemJobMapper.selectOne(wrapper);
} }
public void injectQueryParams(SystemQueryJobArgs args, LambdaQueryWrapper<SystemJobTb> wrapper) { public void injectQueryParams(SystemQueryJobArgs args, LambdaQueryWrapper<SystemJobTb> wrapper) {
if (args != null) { if (args != null) {
wrapper.like(StrUtil.isNotBlank(args.getName()), SystemJobTb::getName, args.getName()); wrapper.like(StrUtil.isNotBlank(args.getName()), SystemJobTb::getName, args.getName());
wrapper.eq(args.getEnabled() != null, SystemJobTb::getEnabled, args.getEnabled()); wrapper.eq(args.getEnabled() != null, SystemJobTb::getEnabled, args.getEnabled());
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemJobTb::getCreateTime, args.getCreateTime().get(0), args.getCreateTime().get(1)); wrapper.between(SystemJobTb::getCreateTime, args.getCreateTime().get(0),
} args.getCreateTime().get(1));
} }
wrapper.orderByDesc(SystemJobTb::getJobSort, SystemJobTb::getId);
} }
wrapper.orderByDesc(SystemJobTb::getJobSort, SystemJobTb::getId);
}
} }
@@ -21,6 +21,8 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.constant.FileTypeEnum;
import cn.odboy.framework.context.KitSpringBeanHolder;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties; import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.server.core.KitFileLocalUploadHelper; import cn.odboy.framework.server.core.KitFileLocalUploadHelper;
@@ -31,7 +33,6 @@ import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -39,6 +40,7 @@ import java.util.Date;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -47,134 +49,147 @@ import org.springframework.web.multipart.MultipartFile;
@Service @Service
public class SystemLocalStorageService { public class SystemLocalStorageService {
@Autowired private SystemLocalStorageMapper systemLocalStorageMapper; @Autowired
@Autowired private KitFileLocalUploadHelper fileUploadPathHelper; private SystemLocalStorageMapper systemLocalStorageMapper;
@Autowired private AppProperties properties; @Autowired
private KitFileLocalUploadHelper fileUploadPathHelper;
@Autowired
private AppProperties properties;
/** /**
* 上传 * 上传
* *
* @param name 文件名称 * @param name 文件名称
* @param multipartFile 文件 * @param multipartFile 文件
* @return / * @return /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public SystemLocalStorageTb uploadFile(String name, MultipartFile multipartFile) { public SystemLocalStorageTb uploadFile(String name, MultipartFile multipartFile) {
long size = multipartFile.getSize(); long size = multipartFile.getSize();
KitFileUtil.checkSize(properties.getOss().getMaxSize(), size); KitFileUtil.checkSize(properties.getOss().getMaxSize(), size);
String suffix = KitFileUtil.getSuffix(multipartFile.getOriginalFilename()); String suffix = KitFileUtil.getSuffix(multipartFile.getOriginalFilename());
String type = KitFileUtil.getFileType(suffix); String type = KitFileUtil.getFileType(suffix);
String uploadDateStr = DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT); String uploadDateStr = DateUtil.format(new Date(), DatePattern.PURE_DATE_FORMAT);
File file = KitFileUtil.upload(multipartFile, fileUploadPathHelper.getPath() + uploadDateStr + File.separator); File file = KitFileUtil.upload(multipartFile, fileUploadPathHelper.getPath() + uploadDateStr + File.separator);
if (file == null) { if (file == null) {
throw new BadRequestException("上传失败"); throw new BadRequestException("上传失败");
}
try {
String formatSize = KitFileUtil.getSize(size);
String prefixName =
StrUtil.isBlank(name) ? KitFileUtil.getPrefix(multipartFile.getOriginalFilename()) : name;
SystemLocalStorageTb localStorage = new SystemLocalStorageTb();
localStorage.setRealName(file.getName());
localStorage.setName(prefixName);
localStorage.setSuffix(suffix);
localStorage.setPath(file.getPath());
localStorage.setType(type);
localStorage.setSize(formatSize);
localStorage.setDateGroup(uploadDateStr);
systemLocalStorageMapper.insert(localStorage);
return localStorage;
} catch (Exception e) {
KitFileUtil.del(file);
throw e;
}
} }
try {
String formatSize = KitFileUtil.getSize(size);
String prefixName =
StrUtil.isBlank(name) ? KitFileUtil.getPrefix(multipartFile.getOriginalFilename()) : name;
SystemLocalStorageTb localStorage = new SystemLocalStorageTb();
localStorage.setRealName(file.getName());
localStorage.setName(prefixName);
localStorage.setSuffix(suffix);
localStorage.setPath(file.getPath());
localStorage.setType(type);
localStorage.setSize(formatSize);
localStorage.setDateGroup(uploadDateStr);
systemLocalStorageMapper.insert(localStorage);
return localStorage;
} catch (Exception e) {
KitFileUtil.del(file);
throw e;
}
}
/** /**
* 编辑 * 编辑
* *
* @param args 文件信息 * @param args 文件信息
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateLocalStorageById(SystemLocalStorageTb args) { public void updateLocalStorageById(SystemLocalStorageTb args) {
SystemLocalStorageTb localStorage = systemLocalStorageMapper.selectById(args.getId()); SystemLocalStorageTb localStorage = systemLocalStorageMapper.selectById(args.getId());
localStorage.copy(args); localStorage.copy(args);
systemLocalStorageMapper.insertOrUpdate(localStorage); systemLocalStorageMapper.insertOrUpdate(localStorage);
} }
/** /**
* 多选删除 * 多选删除
* *
* @param ids / * @param ids /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteFileByIds(Long[] ids) { public void deleteFileByIds(Long[] ids) {
for (Long id : ids) { for (Long id : ids) {
SystemLocalStorageTb storage = systemLocalStorageMapper.selectById(id); SystemLocalStorageTb storage = systemLocalStorageMapper.selectById(id);
try { try {
KitFileUtil.del(storage.getPath()); KitFileUtil.del(storage.getPath());
systemLocalStorageMapper.deleteById(storage); systemLocalStorageMapper.deleteById(storage);
} catch (IORuntimeException e) { } catch (IORuntimeException e) {
throw new BadRequestException("删除文件 " + storage.getName() + " 失败"); throw new BadRequestException("删除文件 " + storage.getName() + " 失败");
} }
}
} }
}
/** /**
* 导出数据 * 导出数据
* *
* @param localStorages 待导出的数据 * @param localStorages 待导出的数据
* @param response / * @param response /
* @throws IOException / * @throws IOException /
*/ */
public void exportLocalStorageExcel(List<SystemLocalStorageTb> localStorages, HttpServletResponse response) public void exportLocalStorageExcel(List<SystemLocalStorageTb> localStorages, HttpServletResponse response)
throws IOException { throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (SystemLocalStorageTb localStorage : localStorages) { for (SystemLocalStorageTb localStorage : localStorages) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("文件名", localStorage.getRealName()); map.put("文件名", localStorage.getRealName());
map.put("备注名", localStorage.getName()); map.put("备注名", localStorage.getName());
map.put("文件类型", localStorage.getType()); map.put("文件类型", localStorage.getType());
map.put("文件大小", localStorage.getSize()); map.put("文件大小", localStorage.getSize());
map.put("创建者", localStorage.getCreateBy()); map.put("创建者", localStorage.getCreateBy());
map.put("创建日期", localStorage.getCreateTime()); map.put("创建日期", localStorage.getCreateTime());
list.add(map); list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
KitFileUtil.downloadExcel(list, response);
}
/** /**
* 分页查询 * 分页查询
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
* @return / * @return /
*/ */
public KitPageResult<SystemLocalStorageTb> searchLocalStorage(SystemQueryStorageArgs args, public KitPageResult<SystemLocalStorageTb> searchLocalStorage(SystemQueryStorageArgs args,
Page<SystemLocalStorageTb> page) { Page<SystemLocalStorageTb> page) {
LambdaQueryWrapper<SystemLocalStorageTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemLocalStorageTb> wrapper = new LambdaQueryWrapper<>();
this.injectQueryParams(args, wrapper); this.injectQueryParams(args, wrapper);
Page<SystemLocalStorageTb> selectPage = systemLocalStorageMapper.selectPage(page, wrapper); Page<SystemLocalStorageTb> selectPage = systemLocalStorageMapper.selectPage(page, wrapper);
return KitPageUtil.toPage(selectPage); return KitPageUtil.toPage(selectPage);
} }
private void injectQueryParams(SystemQueryStorageArgs args, LambdaQueryWrapper<SystemLocalStorageTb> wrapper) { private void injectQueryParams(SystemQueryStorageArgs args, LambdaQueryWrapper<SystemLocalStorageTb> wrapper) {
if (args != null) { if (args != null) {
wrapper.and(StrUtil.isNotBlank(args.getBlurry()), wrapper.and(StrUtil.isNotBlank(args.getBlurry()),
c -> c.like(SystemLocalStorageTb::getName, args.getBlurry()).or() c -> c.like(SystemLocalStorageTb::getName, args.getBlurry()).or()
.like(SystemLocalStorageTb::getSuffix, args.getBlurry()).or() .like(SystemLocalStorageTb::getSuffix, args.getBlurry()).or()
.like(SystemLocalStorageTb::getType, args.getBlurry()).or() .like(SystemLocalStorageTb::getType, args.getBlurry()).or()
.like(SystemLocalStorageTb::getCreateBy, args.getBlurry())); .like(SystemLocalStorageTb::getCreateBy, args.getBlurry()));
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemLocalStorageTb::getUpdateTime, args.getCreateTime().get(0), wrapper.between(SystemLocalStorageTb::getUpdateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1)); args.getCreateTime().get(1));
} }
}
wrapper.orderByDesc(SystemLocalStorageTb::getId);
} }
wrapper.orderByDesc(SystemLocalStorageTb::getId);
}
public List<SystemLocalStorageTb> queryLocalStorageByArgs(SystemQueryStorageArgs args) { public List<SystemLocalStorageTb> queryLocalStorageByArgs(SystemQueryStorageArgs args) {
LambdaQueryWrapper<SystemLocalStorageTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemLocalStorageTb> wrapper = new LambdaQueryWrapper<>();
this.injectQueryParams(args, wrapper); this.injectQueryParams(args, wrapper);
return systemLocalStorageMapper.selectList(wrapper); return systemLocalStorageMapper.selectList(wrapper);
}
public SystemLocalStorageTb uploadPictureV1(MultipartFile file) {
// 判断文件是否为图片
String suffix = KitFileUtil.getSuffix(file.getOriginalFilename());
if (!FileTypeEnum.IMAGE.getCode().equals(KitFileUtil.getFileType(suffix))) {
throw new BadRequestException("只能上传图片");
} }
return KitSpringBeanHolder.getBean(SystemLocalStorageService.class).uploadFile(null, file);
}
} }
@@ -31,22 +31,24 @@ import cn.odboy.system.dal.model.SystemQueryMenuArgs;
import cn.odboy.system.dal.model.SystemRoleVo; import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.dal.mysql.SystemMenuMapper; import cn.odboy.system.dal.mysql.SystemMenuMapper;
import cn.odboy.system.dal.mysql.SystemRoleMenuMapper; import cn.odboy.system.dal.mysql.SystemRoleMenuMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitClassUtil; import cn.odboy.util.KitClassUtil;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -54,398 +56,443 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemMenuService { public class SystemMenuService {
private static final String YES_STR = "是"; private static final String YES_STR = "是";
private static final String NO_STR = "否"; private static final String NO_STR = "否";
@Autowired private SystemMenuMapper systemMenuMapper; @Autowired
@Autowired private SystemRoleMenuMapper systemRoleMenuMapper; private SystemMenuMapper systemMenuMapper;
@Autowired private SystemRoleService systemRoleService; @Autowired
@Autowired private SystemRoleMenuService systemRoleMenuService; private SystemRoleMenuMapper systemRoleMenuMapper;
@Autowired
private SystemRoleService systemRoleService;
@Autowired
private SystemRoleMenuService systemRoleMenuService;
@Autowired
private SystemUserRoleService systemUserRoleService;
/** /**
* 创建 * 创建
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveMenu(SystemMenuTb args) { public void saveMenu(SystemMenuTb args) {
if (this.getMenuByTitle(args.getTitle()) != null) { if (this.getMenuByTitle(args.getTitle()) != null) {
throw new BadRequestException("菜单标题已存在"); throw new BadRequestException("菜单标题已存在");
}
if (StrUtil.isNotBlank(args.getComponentName())) {
if (this.getMenuByComponentName(args.getComponentName()) != null) {
throw new BadRequestException("菜单组件名称已存在");
}
}
if (Long.valueOf(0L).equals(args.getPid())) {
args.setPid(null);
}
if (args.getIFrame()) {
if (!(args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTP) ||
args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTPS))) {
throw new BadRequestException(TransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST);
}
}
systemMenuMapper.insert(args);
// 计算子节点数目
args.setSubCount(0);
// 更新父节点菜单数目
this.updateMenuSubCnt(args.getPid());
} }
if (StrUtil.isNotBlank(args.getComponentName())) {
/** if (this.getMenuByComponentName(args.getComponentName()) != null) {
* 编辑 throw new BadRequestException("菜单组件名称已存在");
* }
* @param args /
*/
@Transactional(rollbackFor = Exception.class)
public void updateMenuById(SystemMenuTb args) {
if (args.getId().equals(args.getPid())) {
throw new BadRequestException("上级不能为自己");
}
SystemMenuTb menu = systemMenuMapper.selectById(args.getId());
if (args.getIFrame()) {
if (!(args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTP) ||
args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTPS))) {
throw new BadRequestException(TransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST);
}
}
SystemMenuTb menu1 = this.getMenuByTitle(args.getTitle());
if (menu1 != null && !menu1.getId().equals(menu.getId())) {
throw new BadRequestException("菜单标题已存在");
}
if (args.getPid().equals(0L)) {
args.setPid(null);
}
// 记录的父节点ID
Long oldPid = menu.getPid();
Long newPid = args.getPid();
if (StrUtil.isNotBlank(args.getComponentName())) {
menu1 = this.getMenuByComponentName(args.getComponentName());
if (menu1 != null && !menu1.getId().equals(menu.getId())) {
throw new BadRequestException("菜单组件名称已存在");
}
}
menu.setTitle(args.getTitle());
menu.setComponent(args.getComponent());
menu.setPath(args.getPath());
menu.setIcon(args.getIcon());
menu.setIFrame(args.getIFrame());
menu.setPid(args.getPid());
menu.setMenuSort(args.getMenuSort());
menu.setCache(args.getCache());
menu.setHidden(args.getHidden());
menu.setComponentName(args.getComponentName());
menu.setPermission(args.getPermission());
menu.setType(args.getType());
// auto fill
menu.setUpdateBy(null);
menu.setUpdateTime(null);
systemMenuMapper.insertOrUpdate(menu);
// 计算父级菜单节点数目
this.updateMenuSubCnt(oldPid);
this.updateMenuSubCnt(newPid);
} }
if (Long.valueOf(0L).equals(args.getPid())) {
/** args.setPid(null);
* 删除
*/
@Transactional(rollbackFor = Exception.class)
public void deleteMenuByIds(Set<Long> ids) {
Set<SystemMenuTb> menuSet = new HashSet<>();
for (Long id : ids) {
List<SystemMenuTb> menuList = this.listMenuByPid(id);
menuSet.add(systemMenuMapper.selectById(id));
menuSet = this.queryChildMenuByArgs(menuList, menuSet);
}
List<Long> menuIds =
menuSet.stream().map(SystemMenuTb::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
if (CollUtil.isNotEmpty(menuIds)) {
KitSpringBeanHolder.getBean(SystemMenuService.class).deleteRoleMenuByMenuIds(menuIds);
systemMenuMapper.deleteByIds(menuIds);
}
for (SystemMenuTb menu : menuSet) {
this.updateMenuSubCnt(menu.getPid());
}
} }
if (args.getIFrame()) {
if (!(args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTP) ||
args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTPS))) {
throw new BadRequestException(TransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST);
}
}
systemMenuMapper.insert(args);
// 计算子节点数目
args.setSubCount(0);
// 更新父节点菜单数目
this.updateMenuSubCnt(args.getPid());
}
@Transactional(rollbackFor = Exception.class) /**
public void deleteRoleMenuByMenuIds(List<Long> menuIds) { * 编辑
if (CollUtil.isNotEmpty(menuIds)) { *
LambdaQueryWrapper<SystemRoleMenuTb> wrapper = new LambdaQueryWrapper<>(); * @param args /
wrapper.in(SystemRoleMenuTb::getMenuId, menuIds); */
systemRoleMenuMapper.delete(wrapper); @Transactional(rollbackFor = Exception.class)
public void updateMenuById(SystemMenuTb args) {
if (args.getId().equals(args.getPid())) {
throw new BadRequestException("上级不能为自己");
}
SystemMenuTb menu = systemMenuMapper.selectById(args.getId());
if (args.getIFrame()) {
if (!(args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTP) ||
args.getPath().toLowerCase().startsWith(TransferProtocolConst.PREFIX_HTTPS))) {
throw new BadRequestException(TransferProtocolConst.PREFIX_HTTPS_BAD_REQUEST);
}
}
SystemMenuTb menu1 = this.getMenuByTitle(args.getTitle());
if (menu1 != null && !menu1.getId().equals(menu.getId())) {
throw new BadRequestException("菜单标题已存在");
}
if (args.getPid().equals(0L)) {
args.setPid(null);
}
// 记录的父节点ID
Long oldPid = menu.getPid();
Long newPid = args.getPid();
if (StrUtil.isNotBlank(args.getComponentName())) {
menu1 = this.getMenuByComponentName(args.getComponentName());
if (menu1 != null && !menu1.getId().equals(menu.getId())) {
throw new BadRequestException("菜单组件名称已存在");
}
}
menu.setTitle(args.getTitle());
menu.setComponent(args.getComponent());
menu.setPath(args.getPath());
menu.setIcon(args.getIcon());
menu.setIFrame(args.getIFrame());
menu.setPid(args.getPid());
menu.setMenuSort(args.getMenuSort());
menu.setCache(args.getCache());
menu.setHidden(args.getHidden());
menu.setComponentName(args.getComponentName());
menu.setPermission(args.getPermission());
menu.setType(args.getType());
// auto fill
menu.setUpdateBy(null);
menu.setUpdateTime(null);
systemMenuMapper.insertOrUpdate(menu);
// 计算父级菜单节点数目
this.updateMenuSubCnt(oldPid);
this.updateMenuSubCnt(newPid);
}
/**
* 删除
*/
@Transactional(rollbackFor = Exception.class)
public void deleteMenuByIds(Set<Long> ids) {
Set<SystemMenuTb> menuSet = new HashSet<>();
for (Long id : ids) {
List<SystemMenuTb> menuList = this.listMenuByPid(id);
menuSet.add(systemMenuMapper.selectById(id));
menuSet = this.queryChildMenuByArgs(menuList, menuSet);
}
List<Long> menuIds =
menuSet.stream().map(SystemMenuTb::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
if (CollUtil.isNotEmpty(menuIds)) {
KitSpringBeanHolder.getBean(SystemMenuService.class).deleteRoleMenuByMenuIds(menuIds);
systemMenuMapper.deleteByIds(menuIds);
}
for (SystemMenuTb menu : menuSet) {
this.updateMenuSubCnt(menu.getPid());
}
}
@Transactional(rollbackFor = Exception.class)
public void deleteRoleMenuByMenuIds(List<Long> menuIds) {
if (CollUtil.isNotEmpty(menuIds)) {
LambdaQueryWrapper<SystemRoleMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemRoleMenuTb::getMenuId, menuIds);
systemRoleMenuMapper.delete(wrapper);
}
}
/**
* 导出
*
* @param menus 待导出的数据
* @param response /
* @throws IOException /
*/
public void exportMenuExcel(List<SystemMenuTb> menus, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (SystemMenuTb menu : menus) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("菜单标题", menu.getTitle());
map.put("菜单类型", menu.getType() == null ? "目录" : menu.getType() == 1 ? "菜单" : "按钮");
map.put("权限标识", menu.getPermission());
map.put("外链菜单", menu.getIFrame() ? YES_STR : NO_STR);
map.put("菜单可见", menu.getHidden() ? NO_STR : YES_STR);
map.put("是否缓存", menu.getCache() ? YES_STR : NO_STR);
map.put("创建日期", menu.getCreateTime());
list.add(map);
}
KitFileUtil.downloadExcel(list, response);
}
@Transactional(rollbackFor = Exception.class)
public void updateMenuSubCnt(Long menuId) {
if (menuId != null) {
long count = this.countMenuByPid(menuId);
LambdaUpdateWrapper<SystemMenuTb> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(SystemMenuTb::getId, menuId);
wrapper.set(SystemMenuTb::getSubCount, count);
systemMenuMapper.update(wrapper);
}
}
/**
* 查询全部数据
*
* @param args 条件
* @param isQuery /
* @return /
* @throws Exception /
*/
public List<SystemMenuTb> queryAllMenu(SystemQueryMenuArgs args, Boolean isQuery) throws Exception {
if (Boolean.TRUE.equals(isQuery)) {
args.setPidIsNull(true);
List<Field> fields = KitClassUtil.getAllFields(args.getClass(), new ArrayList<>());
for (Field field : fields) {
//设置对象的访问权限, 保证对private的属性的访问
field.setAccessible(true);
Object val = field.get(args);
if ("pidIsNull".equals(field.getName())) {
continue;
} }
} // 如果有查询条件, 则不指定pidIsNull
if (ObjectUtil.isNotNull(val)) {
/** args.setPidIsNull(null);
* 导出 break;
*
* @param menus 待导出的数据
* @param response /
* @throws IOException /
*/
public void exportMenuExcel(List<SystemMenuTb> menus, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (SystemMenuTb menu : menus) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("菜单标题", menu.getTitle());
map.put("菜单类型", menu.getType() == null ? "目录" : menu.getType() == 1 ? "菜单" : "按钮");
map.put("权限标识", menu.getPermission());
map.put("外链菜单", menu.getIFrame() ? YES_STR : NO_STR);
map.put("菜单可见", menu.getHidden() ? NO_STR : YES_STR);
map.put("是否缓存", menu.getCache() ? YES_STR : NO_STR);
map.put("创建日期", menu.getCreateTime());
list.add(map);
} }
KitFileUtil.downloadExcel(list, response); }
} }
return this.queryMenuByArgs(args);
}
@Transactional(rollbackFor = Exception.class) /**
public void updateMenuSubCnt(Long menuId) { * 根据当前用户获取菜单
if (menuId != null) { *
long count = this.countMenuByPid(menuId); * @param currentUserId /
LambdaUpdateWrapper<SystemMenuTb> wrapper = new LambdaUpdateWrapper<>(); * @return /
wrapper.eq(SystemMenuTb::getId, menuId); */
wrapper.set(SystemMenuTb::getSubCount, count); public List<SystemMenuTb> listMenuByUserId(Long currentUserId) {
systemMenuMapper.update(wrapper); List<SystemRoleVo> roles = systemUserRoleService.queryRoleByUsersId(currentUserId);
Set<Long> roleIds = roles.stream().map(SystemRoleTb::getId).collect(Collectors.toSet());
return new ArrayList<>(systemRoleMenuService.queryMenuByRoleIds(roleIds));
}
/**
* 获取所有子节点, 包含自身ID
*
* @param menuList /
* @param menuSet /
* @return /
*/
public Set<SystemMenuTb> queryChildMenuByArgs(List<SystemMenuTb> menuList, Set<SystemMenuTb> menuSet) {
for (SystemMenuTb menu : menuList) {
menuSet.add(menu);
List<SystemMenuTb> menus = this.listMenuByPid(menu.getId());
if (CollUtil.isNotEmpty(menus)) {
queryChildMenuByArgs(menus, menuSet);
}
}
return menuSet;
}
/**
* 懒加载菜单数据
*
* @param pid /
* @return /
*/
public List<SystemMenuTb> listMenuByPid(Long pid) {
List<SystemMenuTb> menus;
if (pid != null && !pid.equals(0L)) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getPid, pid);
wrapper.orderByAsc(SystemMenuTb::getMenuSort);
return systemMenuMapper.selectList(wrapper);
} else {
menus = this.listRootMenu();
}
return menus;
}
/**
* 根据ID获取同级与上级数据
*
* @param menu /
* @param menus /
* @return /
*/
public List<SystemMenuTb> querySuperiorMenuByArgs(SystemMenuTb menu, List<SystemMenuTb> menus) {
if (menu.getPid() == null) {
menus.addAll(this.listRootMenu());
return menus;
}
menus.addAll(this.listMenuByPid(menu.getPid()));
return querySuperiorMenuByArgs(systemMenuMapper.selectById(menu.getPid()), menus);
}
/**
* 构建菜单树
*
* @param menus 原始数据
* @return /
*/
public List<SystemMenuTb> buildMenuTree(List<SystemMenuTb> menus) {
List<SystemMenuTb> trees = new ArrayList<>();
Set<Long> ids = new HashSet<>();
for (SystemMenuTb menu : menus) {
if (menu.getPid() == null) {
trees.add(menu);
}
for (SystemMenuTb it : menus) {
if (menu.getId().equals(it.getPid())) {
if (menu.getChildren() == null) {
menu.setChildren(new ArrayList<>());
}
menu.getChildren().add(it);
ids.add(it.getId());
} }
}
} }
if (CollUtil.isNotEmpty(trees)) {
/** trees = menus.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
* 查询全部数据
*
* @param args 条件
* @param isQuery /
* @return /
* @throws Exception /
*/
public List<SystemMenuTb> queryAllMenu(SystemQueryMenuArgs args, Boolean isQuery) throws Exception {
if (Boolean.TRUE.equals(isQuery)) {
args.setPidIsNull(true);
List<Field> fields = KitClassUtil.getAllFields(args.getClass(), new ArrayList<>());
for (Field field : fields) {
//设置对象的访问权限, 保证对private的属性的访问
field.setAccessible(true);
Object val = field.get(args);
if ("pidIsNull".equals(field.getName())) {
continue;
}
// 如果有查询条件, 则不指定pidIsNull
if (ObjectUtil.isNotNull(val)) {
args.setPidIsNull(null);
break;
}
}
}
return this.queryMenuByArgs(args);
} }
return trees;
}
/** /**
* 根据当前用户获取菜单 * 构建菜单树
* *
* @param currentUserId / * @param menus /
* @return / * @return /
*/ */
public List<SystemMenuTb> listMenuByUserId(Long currentUserId) { public List<SystemMenuVo> buildMenuVo(List<SystemMenuTb> menus) {
List<SystemRoleVo> roles = systemRoleService.queryRoleByUsersId(currentUserId); List<SystemMenuVo> list = new LinkedList<>();
Set<Long> roleIds = roles.stream().map(SystemRoleTb::getId).collect(Collectors.toSet()); menus.forEach(menu -> {
return new ArrayList<>(systemRoleMenuService.queryMenuByRoleIds(roleIds)); if (menu != null) {
} List<SystemMenuTb> menuList = menu.getChildren();
SystemMenuVo menuVo = new SystemMenuVo();
/** menuVo.setName(
* 获取所有子节点, 包含自身ID ObjectUtil.isNotEmpty(menu.getComponentName()) ? menu.getComponentName() : menu.getTitle());
* // 一级目录需要加斜杠, 不然会报警告
* @param menuList / menuVo.setPath(menu.getPid() == null ? "/" + menu.getPath() : menu.getPath());
* @param menuSet / menuVo.setHidden(menu.getHidden());
* @return / // 如果不是外链
*/
public Set<SystemMenuTb> queryChildMenuByArgs(List<SystemMenuTb> menuList, Set<SystemMenuTb> menuSet) {
for (SystemMenuTb menu : menuList) {
menuSet.add(menu);
List<SystemMenuTb> menus = this.listMenuByPid(menu.getId());
if (CollUtil.isNotEmpty(menus)) {
queryChildMenuByArgs(menus, menuSet);
}
}
return menuSet;
}
/**
* 懒加载菜单数据
*
* @param pid /
* @return /
*/
public List<SystemMenuTb> listMenuByPid(Long pid) {
List<SystemMenuTb> menus;
if (pid != null && !pid.equals(0L)) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getPid, pid);
wrapper.orderByAsc(SystemMenuTb::getMenuSort);
return systemMenuMapper.selectList(wrapper);
} else {
menus = this.listRootMenu();
}
return menus;
}
/**
* 根据ID获取同级与上级数据
*
* @param menu /
* @param menus /
* @return /
*/
public List<SystemMenuTb> querySuperiorMenuByArgs(SystemMenuTb menu, List<SystemMenuTb> menus) {
if (menu.getPid() == null) {
menus.addAll(this.listRootMenu());
return menus;
}
menus.addAll(this.listMenuByPid(menu.getPid()));
return querySuperiorMenuByArgs(systemMenuMapper.selectById(menu.getPid()), menus);
}
/**
* 构建菜单树
*
* @param menus 原始数据
* @return /
*/
public List<SystemMenuTb> buildMenuTree(List<SystemMenuTb> menus) {
List<SystemMenuTb> trees = new ArrayList<>();
Set<Long> ids = new HashSet<>();
for (SystemMenuTb menu : menus) {
if (menu.getPid() == null) {
trees.add(menu);
}
for (SystemMenuTb it : menus) {
if (menu.getId().equals(it.getPid())) {
if (menu.getChildren() == null) {
menu.setChildren(new ArrayList<>());
}
menu.getChildren().add(it);
ids.add(it.getId());
}
}
}
if (CollUtil.isNotEmpty(trees)) {
trees = menus.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList());
}
return trees;
}
/**
* 构建菜单树
*
* @param menus /
* @return /
*/
public List<SystemMenuVo> buildMenuVo(List<SystemMenuTb> menus) {
List<SystemMenuVo> list = new LinkedList<>();
menus.forEach(menu -> {
if (menu != null) {
List<SystemMenuTb> menuList = menu.getChildren();
SystemMenuVo menuVo = new SystemMenuVo();
menuVo.setName(
ObjectUtil.isNotEmpty(menu.getComponentName()) ? menu.getComponentName() : menu.getTitle());
// 一级目录需要加斜杠, 不然会报警告
menuVo.setPath(menu.getPid() == null ? "/" + menu.getPath() : menu.getPath());
menuVo.setHidden(menu.getHidden());
// 如果不是外链
if (!menu.getIFrame()) {
if (menu.getPid() == null) {
menuVo.setComponent(StrUtil.isEmpty(menu.getComponent()) ? "Layout" : menu.getComponent());
// 如果不是一级菜单,并且菜单类型为目录,则代表是多级菜单
} else if (menu.getType() == 0) {
menuVo.setComponent(StrUtil.isEmpty(menu.getComponent()) ? "ParentView" : menu.getComponent());
} else if (StrUtil.isNotBlank(menu.getComponent())) {
menuVo.setComponent(menu.getComponent());
}
}
menuVo.setMeta(new SystemMenuMetaVo(menu.getTitle(), menu.getIcon(), !menu.getCache()));
if (CollectionUtil.isNotEmpty(menuList)) {
menuVo.setAlwaysShow(true);
menuVo.setRedirect("noredirect");
menuVo.setChildren(buildMenuVo(menuList));
// 处理是一级菜单并且没有子菜单的情况
} else if (menu.getPid() == null) {
SystemMenuVo menuVo1 = getMenuVo(menu, menuVo);
menuVo.setName(null);
menuVo.setMeta(null);
menuVo.setComponent("Layout");
List<SystemMenuVo> list1 = new ArrayList<>();
list1.add(menuVo1);
menuVo.setChildren(list1);
}
list.add(menuVo);
}
});
return list;
}
/**
* 获取 MenuResponse
*
* @param menu /
* @param menuVo /
* @return /
*/
private SystemMenuVo getMenuVo(SystemMenuTb menu, SystemMenuVo menuVo) {
SystemMenuVo menuVo1 = new SystemMenuVo();
menuVo1.setMeta(menuVo.getMeta());
// 非外链
if (!menu.getIFrame()) { if (!menu.getIFrame()) {
menuVo1.setPath("index"); if (menu.getPid() == null) {
menuVo1.setName(menuVo.getName()); menuVo.setComponent(StrUtil.isEmpty(menu.getComponent()) ? "Layout" : menu.getComponent());
menuVo1.setComponent(menuVo.getComponent()); // 如果不是一级菜单,并且菜单类型为目录,则代表是多级菜单
} else { } else if (menu.getType() == 0) {
menuVo1.setPath(menu.getPath()); menuVo.setComponent(StrUtil.isEmpty(menu.getComponent()) ? "ParentView" : menu.getComponent());
} else if (StrUtil.isNotBlank(menu.getComponent())) {
menuVo.setComponent(menu.getComponent());
}
} }
return menuVo1; menuVo.setMeta(new SystemMenuMetaVo(menu.getTitle(), menu.getIcon(), !menu.getCache()));
} if (CollectionUtil.isNotEmpty(menuList)) {
menuVo.setAlwaysShow(true);
public List<SystemMenuTb> listMenuByIds(List<Long> ids) { menuVo.setRedirect("noredirect");
return systemMenuMapper.selectByIds(ids); menuVo.setChildren(buildMenuVo(menuList));
} // 处理是一级菜单并且没有子菜单的情况
} else if (menu.getPid() == null) {
private SystemMenuTb getMenuByComponentName(String componentName) { SystemMenuVo menuVo1 = getMenuVo(menu, menuVo);
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>(); menuVo.setName(null);
wrapper.eq(SystemMenuTb::getComponentName, componentName); menuVo.setMeta(null);
return systemMenuMapper.selectOne(wrapper); menuVo.setComponent("Layout");
} List<SystemMenuVo> list1 = new ArrayList<>();
list1.add(menuVo1);
private SystemMenuTb getMenuByTitle(String title) { menuVo.setChildren(list1);
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getTitle, title);
return systemMenuMapper.selectOne(wrapper);
}
private Long countMenuByPid(Long pid) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getPid, pid);
return systemMenuMapper.selectCount(wrapper);
}
private List<SystemMenuTb> queryMenuByArgs(SystemQueryMenuArgs args) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) {
wrapper.isNull(args.getPidIsNull() != null, SystemMenuTb::getPid);
wrapper.eq(args.getPid() != null, SystemMenuTb::getPid, args.getPid());
wrapper.and(StrUtil.isNotBlank(args.getBlurry()), c -> c.like(SystemMenuTb::getTitle, args.getBlurry()).or()
.like(SystemMenuTb::getComponentName, args.getBlurry()).or()
.like(SystemMenuTb::getPermission, args.getBlurry()));
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemMenuTb::getCreateTime, args.getCreateTime().get(0), args.getCreateTime().get(1));
}
} }
wrapper.orderByAsc(SystemMenuTb::getMenuSort); list.add(menuVo);
return systemMenuMapper.selectList(wrapper); }
} });
return list;
}
private List<SystemMenuTb> listRootMenu() { /**
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>(); * 获取 MenuResponse
wrapper.isNull(SystemMenuTb::getPid); *
wrapper.orderByAsc(SystemMenuTb::getMenuSort); * @param menu /
return systemMenuMapper.selectList(wrapper); * @param menuVo /
* @return /
*/
private SystemMenuVo getMenuVo(SystemMenuTb menu, SystemMenuVo menuVo) {
SystemMenuVo menuVo1 = new SystemMenuVo();
menuVo1.setMeta(menuVo.getMeta());
// 非外链
if (!menu.getIFrame()) {
menuVo1.setPath("index");
menuVo1.setName(menuVo.getName());
menuVo1.setComponent(menuVo.getComponent());
} else {
menuVo1.setPath(menu.getPath());
} }
return menuVo1;
}
public List<SystemMenuTb> listMenuByIds(List<Long> ids) {
return systemMenuMapper.selectByIds(ids);
}
private SystemMenuTb getMenuByComponentName(String componentName) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getComponentName, componentName);
return systemMenuMapper.selectOne(wrapper);
}
private SystemMenuTb getMenuByTitle(String title) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getTitle, title);
return systemMenuMapper.selectOne(wrapper);
}
private Long countMenuByPid(Long pid) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemMenuTb::getPid, pid);
return systemMenuMapper.selectCount(wrapper);
}
private List<SystemMenuTb> queryMenuByArgs(SystemQueryMenuArgs args) {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) {
wrapper.isNull(args.getPidIsNull() != null, SystemMenuTb::getPid);
wrapper.eq(args.getPid() != null, SystemMenuTb::getPid, args.getPid());
wrapper.and(StrUtil.isNotBlank(args.getBlurry()),
c -> c.like(SystemMenuTb::getTitle, args.getBlurry()).or()
.like(SystemMenuTb::getComponentName, args.getBlurry()).or()
.like(SystemMenuTb::getPermission, args.getBlurry()));
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemMenuTb::getCreateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1));
}
}
wrapper.orderByAsc(SystemMenuTb::getMenuSort);
return systemMenuMapper.selectList(wrapper);
}
private List<SystemMenuTb> listRootMenu() {
LambdaQueryWrapper<SystemMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.isNull(SystemMenuTb::getPid);
wrapper.orderByAsc(SystemMenuTb::getMenuSort);
return systemMenuMapper.selectList(wrapper);
}
public List<SystemMenuVo> buildFrontMenus() {
List<SystemMenuTb> menuList = this.listMenuByUserId(KitSecurityHelper.getCurrentUserId());
List<SystemMenuTb> menus = this.buildMenuTree(menuList);
return this.buildMenuVo(menus);
}
public Set<Long> listChildMenuSetByMenuId(Long id) {
Set<SystemMenuTb> menuSet = new HashSet<>();
List<SystemMenuTb> menuList = this.listMenuByPid(id);
menuSet.add(systemMenuMapper.selectById(id));
menuSet = this.queryChildMenuByArgs(menuList, menuSet);
return menuSet.stream().map(SystemMenuTb::getId).collect(Collectors.toSet());
}
public List<SystemMenuTb> listMenuSuperior(List<Long> ids) {
Set<SystemMenuTb> menus;
List<SystemMenuTb> systemMenuTbs;
if (CollectionUtil.isNotEmpty(ids)) {
menus = new LinkedHashSet<>(this.listMenuByIds(ids));
for (SystemMenuTb menu : menus) {
List<SystemMenuTb> menuList = this.querySuperiorMenuByArgs(menu, new ArrayList<>());
for (SystemMenuTb data : menuList) {
if (data.getId().equals(menu.getPid())) {
data.setSubCount(data.getSubCount() - 1);
}
}
menus.addAll(menuList);
}
// 编辑菜单时不显示自己以及自己下级的数据, 避免出现PID数据环形问题
menus = menus.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toSet());
systemMenuTbs = this.buildMenuTree(new ArrayList<>(menus));
} else {
systemMenuTbs = this.listMenuByPid(null);
}
return systemMenuTbs;
}
} }
@@ -44,172 +44,172 @@ import oshi.util.Util;
@Service @Service
public class SystemMonitorService { public class SystemMonitorService {
private final DecimalFormat df = new DecimalFormat("0.00"); private final DecimalFormat df = new DecimalFormat("0.00");
/** /**
* 查询服务器监控信息 * 查询服务器监控信息
* *
* @return Map<String, Object> * @return Map<String, Object>
*/ */
public Map<String, Object> getServerMonitorInfo() { public Map<String, Object> getServerMonitorInfo() {
Map<String, Object> resultMap = new LinkedHashMap<>(8); Map<String, Object> resultMap = new LinkedHashMap<>(8);
try { try {
SystemInfo si = new SystemInfo(); SystemInfo si = new SystemInfo();
OperatingSystem os = si.getOperatingSystem(); OperatingSystem os = si.getOperatingSystem();
HardwareAbstractionLayer hal = si.getHardware(); HardwareAbstractionLayer hal = si.getHardware();
// 系统信息 // 系统信息
resultMap.put("sys", getSystemInfo(os)); resultMap.put("sys", getSystemInfo(os));
// cpu 信息 // cpu 信息
resultMap.put("cpu", getCpuInfo(hal.getProcessor())); resultMap.put("cpu", getCpuInfo(hal.getProcessor()));
// 内存信息 // 内存信息
resultMap.put("memory", getMemoryInfo(hal.getMemory())); resultMap.put("memory", getMemoryInfo(hal.getMemory()));
// 交换区信息 // 交换区信息
resultMap.put("swap", getSwapInfo(hal.getMemory())); resultMap.put("swap", getSwapInfo(hal.getMemory()));
// 磁盘 // 磁盘
resultMap.put("disk", getDiskInfo(os)); resultMap.put("disk", getDiskInfo(os));
resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss")); resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss"));
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
}
return resultMap;
} }
return resultMap;
}
/** /**
* 获取磁盘信息 * 获取磁盘信息
* *
* @return / * @return /
*/ */
private Map<String, Object> getDiskInfo(OperatingSystem os) { private Map<String, Object> getDiskInfo(OperatingSystem os) {
Map<String, Object> diskInfo = new LinkedHashMap<>(); Map<String, Object> diskInfo = new LinkedHashMap<>();
FileSystem fileSystem = os.getFileSystem(); FileSystem fileSystem = os.getFileSystem();
List<OSFileStore> fsArray = fileSystem.getFileStores(); List<OSFileStore> fsArray = fileSystem.getFileStores();
String osName = System.getProperty("os.name"); String osName = System.getProperty("os.name");
long available = 0, total = 0; long available = 0, total = 0;
for (OSFileStore fs : fsArray) { for (OSFileStore fs : fsArray) {
// windows 需要将所有磁盘分区累加, linux 和 mac 直接累加会出现磁盘重复的问题, 待修复 // windows 需要将所有磁盘分区累加, linux 和 mac 直接累加会出现磁盘重复的问题, 待修复
if (osName.toLowerCase().startsWith(SystemConst.WIN)) { if (osName.toLowerCase().startsWith(SystemConst.WIN)) {
available += fs.getUsableSpace(); available += fs.getUsableSpace();
total += fs.getTotalSpace(); total += fs.getTotalSpace();
} else { } else {
available = fs.getUsableSpace(); available = fs.getUsableSpace();
total = fs.getTotalSpace(); total = fs.getTotalSpace();
break; break;
} }
}
long used = total - available;
diskInfo.put("total", total > 0 ? KitFileUtil.getSize(total) : "?");
diskInfo.put("available", KitFileUtil.getSize(available));
diskInfo.put("used", KitFileUtil.getSize(used));
if (total != 0) {
diskInfo.put("usageRate", df.format(used / (double)total * 100));
} else {
diskInfo.put("usageRate", 0);
}
return diskInfo;
} }
long used = total - available;
diskInfo.put("total", total > 0 ? KitFileUtil.getSize(total) : "?");
diskInfo.put("available", KitFileUtil.getSize(available));
diskInfo.put("used", KitFileUtil.getSize(used));
if (total != 0) {
diskInfo.put("usageRate", df.format(used / (double) total * 100));
} else {
diskInfo.put("usageRate", 0);
}
return diskInfo;
}
/** /**
* 获取交换区信息 * 获取交换区信息
* *
* @param memory / * @param memory /
* @return / * @return /
*/ */
private Map<String, Object> getSwapInfo(GlobalMemory memory) { private Map<String, Object> getSwapInfo(GlobalMemory memory) {
Map<String, Object> swapInfo = new LinkedHashMap<>(); Map<String, Object> swapInfo = new LinkedHashMap<>();
VirtualMemory virtualMemory = memory.getVirtualMemory(); VirtualMemory virtualMemory = memory.getVirtualMemory();
long total = virtualMemory.getSwapTotal(); long total = virtualMemory.getSwapTotal();
long used = virtualMemory.getSwapUsed(); long used = virtualMemory.getSwapUsed();
swapInfo.put("total", FormatUtil.formatBytes(total)); swapInfo.put("total", FormatUtil.formatBytes(total));
swapInfo.put("used", FormatUtil.formatBytes(used)); swapInfo.put("used", FormatUtil.formatBytes(used));
swapInfo.put("available", FormatUtil.formatBytes(total - used)); swapInfo.put("available", FormatUtil.formatBytes(total - used));
if (used == 0) { if (used == 0) {
swapInfo.put("usageRate", 0); swapInfo.put("usageRate", 0);
} else { } else {
swapInfo.put("usageRate", df.format(used / (double)total * 100)); swapInfo.put("usageRate", df.format(used / (double) total * 100));
}
return swapInfo;
} }
return swapInfo;
}
/** /**
* 获取内存信息 * 获取内存信息
* *
* @param memory / * @param memory /
* @return / * @return /
*/ */
private Map<String, Object> getMemoryInfo(GlobalMemory memory) { private Map<String, Object> getMemoryInfo(GlobalMemory memory) {
Map<String, Object> memoryInfo = new LinkedHashMap<>(); Map<String, Object> memoryInfo = new LinkedHashMap<>();
memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal())); memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal()));
memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable())); memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable()));
memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable())); memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable()));
memoryInfo.put("usageRate", memoryInfo.put("usageRate",
df.format((memory.getTotal() - memory.getAvailable()) / (double)memory.getTotal() * 100)); df.format((memory.getTotal() - memory.getAvailable()) / (double) memory.getTotal() * 100));
return memoryInfo; return memoryInfo;
} }
/** /**
* 获取Cpu相关信息 * 获取Cpu相关信息
* *
* @param processor / * @param processor /
* @return / * @return /
*/ */
private Map<String, Object> getCpuInfo(CentralProcessor processor) { private Map<String, Object> getCpuInfo(CentralProcessor processor) {
Map<String, Object> cpuInfo = new LinkedHashMap<>(); Map<String, Object> cpuInfo = new LinkedHashMap<>();
cpuInfo.put("name", processor.getProcessorIdentifier().getName()); cpuInfo.put("name", processor.getProcessorIdentifier().getName());
cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU"); cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU");
cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心"); cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心");
cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount()); cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount());
cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU"); cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU");
// CPU信息 // CPU信息
long[] prevTicks = processor.getSystemCpuLoadTicks(); long[] prevTicks = processor.getSystemCpuLoadTicks();
// 默认等待300毫秒... // 默认等待300毫秒...
long time = 300; long time = 300;
Util.sleep(time); Util.sleep(time);
long[] ticks = processor.getSystemCpuLoadTicks(); long[] ticks = processor.getSystemCpuLoadTicks();
long minCpuLoadTick = 1000; long minCpuLoadTick = 1000;
while (Arrays.toString(prevTicks).equals(Arrays.toString(ticks)) && time < minCpuLoadTick) { while (Arrays.toString(prevTicks).equals(Arrays.toString(ticks)) && time < minCpuLoadTick) {
time += 25; time += 25;
Util.sleep(25); Util.sleep(25);
ticks = processor.getSystemCpuLoadTicks(); ticks = processor.getSystemCpuLoadTicks();
}
long user =
ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long nice =
ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long sys =
ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long idle =
ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long ioWait =
ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long irq =
ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] -
prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal =
ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long totalCpu = user + nice + sys + idle + ioWait + irq + softIrq + steal;
cpuInfo.put("used", df.format(100d * user / totalCpu + 100d * sys / totalCpu));
cpuInfo.put("idle", df.format(100d * idle / totalCpu));
return cpuInfo;
} }
long user =
ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long nice =
ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long sys =
ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long idle =
ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long ioWait =
ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long irq =
ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softIrq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] -
prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal =
ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long totalCpu = user + nice + sys + idle + ioWait + irq + softIrq + steal;
cpuInfo.put("used", df.format(100d * user / totalCpu + 100d * sys / totalCpu));
cpuInfo.put("idle", df.format(100d * idle / totalCpu));
return cpuInfo;
}
/** /**
* 获取系统相关信息,系统、运行天数、系统IP * 获取系统相关信息,系统、运行天数、系统IP
* *
* @param os / * @param os /
* @return / * @return /
*/ */
private Map<String, Object> getSystemInfo(OperatingSystem os) { private Map<String, Object> getSystemInfo(OperatingSystem os) {
Map<String, Object> systemInfo = new LinkedHashMap<>(); Map<String, Object> systemInfo = new LinkedHashMap<>();
// jvm 运行时间 // jvm 运行时间
long time = ManagementFactory.getRuntimeMXBean().getStartTime(); long time = ManagementFactory.getRuntimeMXBean().getStartTime();
Date date = new Date(time); Date date = new Date(time);
// 计算项目运行时间 // 计算项目运行时间
String formatBetween = DateUtil.formatBetween(date, new Date(), Level.HOUR); String formatBetween = DateUtil.formatBetween(date, new Date(), Level.HOUR);
// 系统信息 // 系统信息
systemInfo.put("os", os.toString()); systemInfo.put("os", os.toString());
systemInfo.put("day", formatBetween); systemInfo.put("day", formatBetween);
systemInfo.put("ip", KitIPUtil.getLocalIp()); systemInfo.put("ip", KitIPUtil.getLocalIp());
return systemInfo; return systemInfo;
} }
} }
@@ -21,9 +21,9 @@ import cn.odboy.system.dal.model.SystemOssStorageVo;
import cn.odboy.system.dal.model.SystemQueryStorageArgs; import cn.odboy.system.dal.model.SystemQueryStorageArgs;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
/** /**
@@ -36,13 +36,13 @@ import org.springframework.web.multipart.MultipartFile;
*/ */
public interface SystemOssStorageService extends IService<SystemOssStorageTb> { public interface SystemOssStorageService extends IService<SystemOssStorageTb> {
KitPageResult<SystemOssStorageVo> searchOssStorage(SystemQueryStorageArgs args, Page<SystemOssStorageTb> page); KitPageResult<SystemOssStorageVo> searchOssStorage(SystemQueryStorageArgs args, Page<SystemOssStorageTb> page);
List<SystemOssStorageVo> queryOssStorage(SystemQueryStorageArgs args); List<SystemOssStorageVo> queryOssStorage(SystemQueryStorageArgs args);
void exportOssStorageExcel(List<SystemOssStorageVo> list, HttpServletResponse response) throws IOException; void exportOssStorageExcel(List<SystemOssStorageVo> list, HttpServletResponse response) throws IOException;
String uploadFile(MultipartFile file); String uploadFile(MultipartFile file);
void deleteFileByIds(Long[] ids); void deleteFileByIds(Long[] ids);
} }
@@ -20,6 +20,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.context.KitSpringBeanHolder;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.redis.KitRedisHelper; import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
@@ -33,7 +34,6 @@ import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -41,6 +41,7 @@ import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import jakarta.servlet.http.HttpServletResponse;
import org.quartz.CronExpression; import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -49,259 +50,285 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemQuartzJobService { public class SystemQuartzJobService {
@Autowired private SystemQuartzJobMapper systemQuartzJobMapper; @Autowired
@Autowired private SystemQuartzLogMapper systemQuartzLogMapper; private SystemQuartzJobMapper systemQuartzJobMapper;
@Autowired private QuartzManage quartzManage; @Autowired
@Autowired private KitRedisHelper redisHelper; private SystemQuartzLogMapper systemQuartzLogMapper;
@Autowired
private QuartzManage quartzManage;
@Autowired
private KitRedisHelper redisHelper;
/** /**
* 创建 * 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
* *
* @param args / * @param beanName Bean名称
*/ */
@Transactional(rollbackFor = Exception.class) private void checkBean(String beanName) {
public void createJob(SystemQuartzJobTb args) { // 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类
if (!CronExpression.isValidExpression(args.getCronExpression())) { // 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数,执行任意sql命令。
throw new BadRequestException("cron表达式格式错误"); if (!KitSpringBeanHolder.getAllServiceBeanName().contains(beanName)) {
} throw new BadRequestException("非法的 Bean,请重新输入!");
systemQuartzJobMapper.insert(args);
quartzManage.addJob(args);
} }
}
/** /**
* 修改任务并重新调度 * 创建
* *
* @param args / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateQuartzJobResumeCron(SystemUpdateQuartzJobArgs args) { public void createJob(SystemQuartzJobTb args) {
if (!CronExpression.isValidExpression(args.getCronExpression())) { if (args.getId() != null) {
throw new BadRequestException("cron表达式格式错误"); throw new BadRequestException("无效参数id");
}
if (StrUtil.isNotBlank(args.getSubTask())) {
List<String> tasks = Arrays.asList(args.getSubTask().split("[,,]"));
if (tasks.contains(args.getId().toString())) {
throw new BadRequestException("子任务中不能添加当前任务ID");
}
}
SystemQuartzJobTb quartzJob = BeanUtil.copyProperties(args, SystemQuartzJobTb.class);
systemQuartzJobMapper.insertOrUpdate(quartzJob);
quartzManage.updateJobCron(quartzJob);
} }
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName());
if (!CronExpression.isValidExpression(args.getCronExpression())) {
throw new BadRequestException("cron表达式格式错误");
}
systemQuartzJobMapper.insert(args);
quartzManage.addJob(args);
}
/** /**
* 更改定时任务状态 * 修改任务并重新调度
* *
* @param quartzJob / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void switchQuartzJobStatus(SystemQuartzJobTb quartzJob) { public void updateQuartzJobResumeCron(SystemUpdateQuartzJobArgs args) {
// 置换暂停状态 // 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
if (quartzJob.getIsPause()) { checkBean(args.getBeanName());
quartzManage.resumeJob(quartzJob); if (!CronExpression.isValidExpression(args.getCronExpression())) {
quartzJob.setIsPause(false); throw new BadRequestException("cron表达式格式错误");
} else {
quartzManage.pauseJob(quartzJob);
quartzJob.setIsPause(true);
}
systemQuartzJobMapper.insertOrUpdate(quartzJob);
} }
if (StrUtil.isNotBlank(args.getSubTask())) {
List<String> tasks = Arrays.asList(args.getSubTask().split("[,,]"));
if (tasks.contains(args.getId().toString())) {
throw new BadRequestException("子任务中不能添加当前任务ID");
}
}
SystemQuartzJobTb quartzJob = BeanUtil.copyProperties(args, SystemQuartzJobTb.class);
systemQuartzJobMapper.insertOrUpdate(quartzJob);
quartzManage.updateJobCron(quartzJob);
}
/** /**
* 立即执行定时任务 * 更改定时任务状态
* *
* @param quartzJob / * @param quartzJob /
*/ */
public void startQuartzJob(SystemQuartzJobTb quartzJob) { @Transactional(rollbackFor = Exception.class)
quartzManage.runJobNow(quartzJob); public void switchQuartzJobStatus(SystemQuartzJobTb quartzJob) {
// 置换暂停状态
if (quartzJob.getIsPause()) {
quartzManage.resumeJob(quartzJob);
quartzJob.setIsPause(false);
} else {
quartzManage.pauseJob(quartzJob);
quartzJob.setIsPause(true);
} }
systemQuartzJobMapper.insertOrUpdate(quartzJob);
}
/** /**
* 删除任务 * 立即执行定时任务
* *
* @param ids / * @param quartzJob /
*/ */
@Transactional(rollbackFor = Exception.class) public void startQuartzJob(SystemQuartzJobTb quartzJob) {
public void deleteJobByIds(Set<Long> ids) { quartzManage.runJobNow(quartzJob);
for (Long id : ids) { }
SystemQuartzJobTb quartzJob = systemQuartzJobMapper.selectById(id);
quartzManage.deleteJob(quartzJob);
systemQuartzJobMapper.deleteById(quartzJob);
}
}
/** /**
* 执行子任务 * 删除任务
* *
* @param tasks / * @param ids /
* @throws InterruptedException / */
*/ @Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class) public void deleteJobByIds(Set<Long> ids) {
public void startSubQuartJob(String[] tasks) throws InterruptedException { for (Long id : ids) {
for (String id : tasks) { SystemQuartzJobTb quartzJob = systemQuartzJobMapper.selectById(id);
if (StrUtil.isBlank(id)) { quartzManage.deleteJob(quartzJob);
// 如果是手动清除子任务id, 会出现id为空字符串的问题 systemQuartzJobMapper.deleteById(quartzJob);
continue;
}
SystemQuartzJobTb quartzJob = systemQuartzJobMapper.selectById(Long.parseLong(id));
if (quartzJob == null) {
// 防止子任务不存在
continue;
}
// 执行任务
String uuid = IdUtil.simpleUUID();
quartzJob.setUuid(uuid);
// 执行任务
startQuartzJob(quartzJob);
// 获取执行状态, 如果执行失败则停止后面的子任务执行
Boolean result = redisHelper.get(uuid, Boolean.class);
while (result == null) {
// 休眠5秒, 再次获取子任务执行情况
Thread.sleep(5000);
result = redisHelper.get(uuid, Boolean.class);
}
if (!result) {
redisHelper.del(uuid);
break;
}
}
} }
}
/** /**
* 导出定时任务 * 执行子任务
* *
* @param quartzJobs 待导出的数据 * @param tasks /
* @param response / * @throws InterruptedException /
* @throws IOException / */
*/ @Transactional(rollbackFor = Exception.class)
public void exportQuartzJobExcel(List<SystemQuartzJobTb> quartzJobs, HttpServletResponse response) public void startSubQuartJob(String[] tasks) throws InterruptedException {
throws IOException { for (String id : tasks) {
List<Map<String, Object>> list = new ArrayList<>(); if (StrUtil.isBlank(id)) {
for (SystemQuartzJobTb quartzJob : quartzJobs) { // 如果是手动清除子任务id, 会出现id为空字符串的问题
Map<String, Object> map = new LinkedHashMap<>(); continue;
map.put("任务名称", quartzJob.getJobName()); }
map.put("Bean名称", quartzJob.getBeanName()); SystemQuartzJobTb quartzJob = systemQuartzJobMapper.selectById(Long.parseLong(id));
map.put("执行方法", quartzJob.getMethodName()); if (quartzJob == null) {
map.put("参数", quartzJob.getParams()); // 防止子任务不存在
map.put("表达式", quartzJob.getCronExpression()); continue;
map.put("状态", quartzJob.getIsPause() ? "暂停中" : "运行中"); }
map.put("描述", quartzJob.getDescription()); // 执行任务
map.put("创建日期", quartzJob.getCreateTime()); String uuid = IdUtil.simpleUUID();
list.add(map); quartzJob.setUuid(uuid);
} // 执行任务
KitFileUtil.downloadExcel(list, response); startQuartzJob(quartzJob);
// 获取执行状态, 如果执行失败则停止后面的子任务执行
Boolean result = redisHelper.get(uuid, Boolean.class);
while (result == null) {
// 休眠5秒, 再次获取子任务执行情况
Thread.sleep(5000);
result = redisHelper.get(uuid, Boolean.class);
}
if (!result) {
redisHelper.del(uuid);
break;
}
} }
}
/** /**
* 导出定时任务日志 * 导出定时任务
* *
* @param queryAllLog 待导出的数据 * @param quartzJobs 待导出的数据
* @param response / * @param response /
* @throws IOException / * @throws IOException /
*/ */
public void exportQuartzLogExcel(List<SystemQuartzLogTb> queryAllLog, HttpServletResponse response) public void exportQuartzJobExcel(List<SystemQuartzJobTb> quartzJobs, HttpServletResponse response)
throws IOException { throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (SystemQuartzLogTb quartzLog : queryAllLog) { for (SystemQuartzJobTb quartzJob : quartzJobs) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("任务名称", quartzLog.getJobName()); map.put("任务名称", quartzJob.getJobName());
map.put("Bean名称", quartzLog.getBeanName()); map.put("Bean名称", quartzJob.getBeanName());
map.put("执行方法", quartzLog.getMethodName()); map.put("执行方法", quartzJob.getMethodName());
map.put("参数", quartzLog.getParams()); map.put("参数", quartzJob.getParams());
map.put("表达式", quartzLog.getCronExpression()); map.put("表达式", quartzJob.getCronExpression());
map.put("异常详情", quartzLog.getExceptionDetail()); map.put("状态", quartzJob.getIsPause() ? "暂停中" : "运行中");
map.put("耗时/毫秒", quartzLog.getTime()); map.put("描述", quartzJob.getDescription());
map.put("状态", quartzLog.getIsSuccess() ? "成功" : "失败"); map.put("创建日期", quartzJob.getCreateTime());
map.put("创建日期", quartzLog.getCreateTime()); list.add(map);
list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
KitFileUtil.downloadExcel(list, response);
}
/** /**
* 分页查询 * 导出定时任务日志
* *
* @param args 条件 * @param queryAllLog 待导出的数据
* @param page 分页参数 * @param response /
* @return / * @throws IOException /
*/ */
public KitPageResult<SystemQuartzJobTb> searchQuartzJobByArgs(SystemQueryQuartzJobArgs args, public void exportQuartzLogExcel(List<SystemQuartzLogTb> queryAllLog, HttpServletResponse response)
Page<SystemQuartzJobTb> page) { throws IOException {
LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>(); List<Map<String, Object>> list = new ArrayList<>();
this.injectQuartzJobQueryParams(args, wrapper); for (SystemQuartzLogTb quartzLog : queryAllLog) {
return KitPageUtil.toPage(systemQuartzJobMapper.selectPage(page, wrapper)); Map<String, Object> map = new LinkedHashMap<>();
map.put("任务名称", quartzLog.getJobName());
map.put("Bean名称", quartzLog.getBeanName());
map.put("执行方法", quartzLog.getMethodName());
map.put("参数", quartzLog.getParams());
map.put("表达式", quartzLog.getCronExpression());
map.put("异常详情", quartzLog.getExceptionDetail());
map.put("耗时/毫秒", quartzLog.getTime());
map.put("状态", quartzLog.getIsSuccess() ? "成功" : "失败");
map.put("创建日期", quartzLog.getCreateTime());
list.add(map);
} }
KitFileUtil.downloadExcel(list, response);
}
private void injectQuartzJobQueryParams(SystemQueryQuartzJobArgs args, /**
LambdaQueryWrapper<SystemQuartzJobTb> wrapper) { * 分页查询
if (args != null) { *
wrapper.like(StrUtil.isNotBlank(args.getJobName()), SystemQuartzJobTb::getJobName, args.getJobName()); * @param args 条件
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { * @param page 分页参数
wrapper.between(SystemQuartzJobTb::getUpdateTime, args.getCreateTime().get(0), * @return /
args.getCreateTime().get(1)); */
} public KitPageResult<SystemQuartzJobTb> searchQuartzJobByArgs(SystemQueryQuartzJobArgs args,
} Page<SystemQuartzJobTb> page) {
wrapper.orderByDesc(SystemQuartzJobTb::getId); LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>();
} this.injectQuartzJobQueryParams(args, wrapper);
return KitPageUtil.toPage(systemQuartzJobMapper.selectPage(page, wrapper));
}
private void injectQuartzLogQueryParams(SystemQueryQuartzJobArgs args, private void injectQuartzJobQueryParams(SystemQueryQuartzJobArgs args,
LambdaQueryWrapper<SystemQuartzLogTb> wrapper) { LambdaQueryWrapper<SystemQuartzJobTb> wrapper) {
if (args != null) { if (args != null) {
wrapper.like(StrUtil.isNotBlank(args.getJobName()), SystemQuartzLogTb::getJobName, args.getJobName()); wrapper.like(StrUtil.isNotBlank(args.getJobName()), SystemQuartzJobTb::getJobName,
wrapper.eq(args.getIsSuccess() != null, SystemQuartzLogTb::getIsSuccess, args.getIsSuccess()); args.getJobName());
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemQuartzLogTb::getCreateTime, args.getCreateTime().get(0), wrapper.between(SystemQuartzJobTb::getUpdateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1)); args.getCreateTime().get(1));
} }
}
wrapper.orderByDesc(SystemQuartzLogTb::getId);
} }
wrapper.orderByDesc(SystemQuartzJobTb::getId);
}
/** private void injectQuartzLogQueryParams(SystemQueryQuartzJobArgs args,
* 分页查询日志 LambdaQueryWrapper<SystemQuartzLogTb> wrapper) {
* if (args != null) {
* @param args 条件 wrapper.like(StrUtil.isNotBlank(args.getJobName()), SystemQuartzLogTb::getJobName,
* @param page 分页参数 args.getJobName());
* @return / wrapper.eq(args.getIsSuccess() != null, SystemQuartzLogTb::getIsSuccess, args.getIsSuccess());
*/ if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
public KitPageResult<SystemQuartzLogTb> searchQuartzLogByArgs(SystemQueryQuartzJobArgs args, wrapper.between(SystemQuartzLogTb::getCreateTime, args.getCreateTime().get(0),
Page<SystemQuartzLogTb> page) { args.getCreateTime().get(1));
LambdaQueryWrapper<SystemQuartzLogTb> wrapper = new LambdaQueryWrapper<>(); }
this.injectQuartzLogQueryParams(args, wrapper);
return KitPageUtil.toPage(systemQuartzLogMapper.selectPage(page, wrapper));
} }
wrapper.orderByDesc(SystemQuartzLogTb::getId);
}
/** /**
* 查询全部 * 分页查询日志
* *
* @param args 条件 * @param args 条件
* @return / * @param page 分页参数
*/ * @return /
public List<SystemQuartzJobTb> queryQuartzJobByArgs(SystemQueryQuartzJobArgs args) { */
LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>(); public KitPageResult<SystemQuartzLogTb> searchQuartzLogByArgs(SystemQueryQuartzJobArgs args,
this.injectQuartzJobQueryParams(args, wrapper); Page<SystemQuartzLogTb> page) {
return systemQuartzJobMapper.selectList(wrapper); LambdaQueryWrapper<SystemQuartzLogTb> wrapper = new LambdaQueryWrapper<>();
} this.injectQuartzLogQueryParams(args, wrapper);
return KitPageUtil.toPage(systemQuartzLogMapper.selectPage(page, wrapper));
}
/** /**
* 查询全部 * 查询全部
* *
* @param args 条件 * @param args 条件
* @return / * @return /
*/ */
public List<SystemQuartzLogTb> queryQuartzLogByArgs(SystemQueryQuartzJobArgs args) { public List<SystemQuartzJobTb> queryQuartzJobByArgs(SystemQueryQuartzJobArgs args) {
LambdaQueryWrapper<SystemQuartzLogTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>();
this.injectQuartzLogQueryParams(args, wrapper); this.injectQuartzJobQueryParams(args, wrapper);
return systemQuartzLogMapper.selectList(wrapper); return systemQuartzJobMapper.selectList(wrapper);
} }
public SystemQuartzJobTb getQuartzJobById(Long id) { /**
return systemQuartzJobMapper.selectById(id); * 查询全部
} *
* @param args 条件
* @return /
*/
public List<SystemQuartzLogTb> queryQuartzLogByArgs(SystemQueryQuartzJobArgs args) {
LambdaQueryWrapper<SystemQuartzLogTb> wrapper = new LambdaQueryWrapper<>();
this.injectQuartzLogQueryParams(args, wrapper);
return systemQuartzLogMapper.selectList(wrapper);
}
public List<SystemQuartzJobTb> listEnableQuartzJob() { public SystemQuartzJobTb getQuartzJobById(Long id) {
LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>(); return systemQuartzJobMapper.selectById(id);
wrapper.eq(SystemQuartzJobTb::getIsPause, 0); }
return systemQuartzJobMapper.selectList(wrapper);
} public List<SystemQuartzJobTb> listEnableQuartzJob() {
LambdaQueryWrapper<SystemQuartzJobTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemQuartzJobTb::getIsPause, 0);
return systemQuartzJobMapper.selectList(wrapper);
}
} }
@@ -32,46 +32,64 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemRoleDeptService { public class SystemRoleDeptService {
@Autowired private SystemRoleDeptMapper systemRoleDeptMapper; @Autowired
@Autowired private SystemDeptMapper systemDeptMapper; private SystemRoleDeptMapper systemRoleDeptMapper;
@Autowired
private SystemDeptMapper systemDeptMapper;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchDeleteRoleDept(Set<Long> roleIds) { public void batchDeleteRoleDept(Set<Long> roleIds) {
if (CollUtil.isNotEmpty(roleIds)) { if (CollUtil.isNotEmpty(roleIds)) {
LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemRoleDeptTb::getRoleId, roleIds); wrapper.in(SystemRoleDeptTb::getRoleId, roleIds);
systemRoleDeptMapper.delete(wrapper); systemRoleDeptMapper.delete(wrapper);
} }
}
@Transactional(rollbackFor = Exception.class)
public void batchInsertRoleDept(Set<SystemDeptTb> depts, Long id) {
if (CollUtil.isNotEmpty(depts)) {
List<SystemRoleDeptTb> records = new ArrayList<>();
for (SystemDeptTb dept : depts) {
SystemRoleDeptTb record = new SystemRoleDeptTb();
record.setRoleId(id);
record.setDeptId(dept.getId());
records.add(record);
}
systemRoleDeptMapper.insert(records);
}
}
/**
* 根据角色id查询
*
* @param roleId /
* @return /
*/
public List<SystemDeptTb> listDeptByRoleId(Long roleId) {
LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemRoleDeptTb::getRoleId, roleId);
List<SystemRoleDeptTb> systemRoleDeptTbs = systemRoleDeptMapper.selectList(wrapper);
if (systemRoleDeptTbs.isEmpty()) {
return new ArrayList<>();
}
List<Long> deptIds = systemRoleDeptTbs.stream().map(SystemRoleDeptTb::getDeptId).collect(Collectors.toList());
return systemDeptMapper.selectByIds(deptIds);
}
/**
* 根据部门ID统计角色数量
*
* @param deptIds 部门ID集合
* @return /
*/
public Long countRoleByDeptIds(Set<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return 0L;
} }
@Transactional(rollbackFor = Exception.class) LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>();
public void batchInsertRoleDept(Set<SystemDeptTb> depts, Long id) { wrapper.in(SystemRoleDeptTb::getDeptId, deptIds);
if (CollUtil.isNotEmpty(depts)) { return systemRoleDeptMapper.selectCount(wrapper);
List<SystemRoleDeptTb> records = new ArrayList<>(); }
for (SystemDeptTb dept : depts) {
SystemRoleDeptTb record = new SystemRoleDeptTb();
record.setRoleId(id);
record.setDeptId(dept.getId());
records.add(record);
}
systemRoleDeptMapper.insert(records);
}
}
/**
* 根据角色id查询
*
* @param roleId /
* @return /
*/
public List<SystemDeptTb> listDeptByRoleId(Long roleId) {
LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemRoleDeptTb::getRoleId, roleId);
List<SystemRoleDeptTb> systemRoleDeptTbs = systemRoleDeptMapper.selectList(wrapper);
if (systemRoleDeptTbs.isEmpty()) {
return new ArrayList<>();
}
List<Long> deptIds = systemRoleDeptTbs.stream().map(SystemRoleDeptTb::getDeptId).collect(Collectors.toList());
return systemDeptMapper.selectByIds(deptIds);
}
} }
@@ -33,55 +33,57 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemRoleMenuService { public class SystemRoleMenuService {
@Autowired private SystemRoleMenuMapper systemRoleMenuMapper; @Autowired
@Autowired private SystemMenuMapper systemMenuMapper; private SystemRoleMenuMapper systemRoleMenuMapper;
@Autowired
private SystemMenuMapper systemMenuMapper;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteRoleMenuByRoleId(Long roleId) { public void deleteRoleMenuByRoleId(Long roleId) {
LambdaQueryWrapper<SystemRoleMenuTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemRoleMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemRoleMenuTb::getRoleId, roleId); wrapper.eq(SystemRoleMenuTb::getRoleId, roleId);
systemRoleMenuMapper.delete(wrapper); systemRoleMenuMapper.delete(wrapper);
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchInsertRoleMenu(Set<SystemMenuTb> menus, Long roleId) { public void batchInsertRoleMenu(Set<SystemMenuTb> menus, Long roleId) {
if (CollUtil.isNotEmpty(menus)) { if (CollUtil.isNotEmpty(menus)) {
List<SystemRoleMenuTb> records = new ArrayList<>(); List<SystemRoleMenuTb> records = new ArrayList<>();
for (SystemMenuTb menu : menus) { for (SystemMenuTb menu : menus) {
SystemRoleMenuTb record = new SystemRoleMenuTb(); SystemRoleMenuTb record = new SystemRoleMenuTb();
record.setMenuId(menu.getId()); record.setMenuId(menu.getId());
record.setRoleId(roleId); record.setRoleId(roleId);
records.add(record); records.add(record);
} }
systemRoleMenuMapper.insert(records); systemRoleMenuMapper.insert(records);
}
} }
}
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchDeleteRoleMenu(Set<Long> roleIds) { public void batchDeleteRoleMenu(Set<Long> roleIds) {
if (CollUtil.isNotEmpty(roleIds)) { if (CollUtil.isNotEmpty(roleIds)) {
LambdaQueryWrapper<SystemRoleMenuTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemRoleMenuTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemRoleMenuTb::getRoleId, roleIds); wrapper.in(SystemRoleMenuTb::getRoleId, roleIds);
systemRoleMenuMapper.delete(wrapper); systemRoleMenuMapper.delete(wrapper);
}
} }
}
public LinkedHashSet<SystemMenuTb> queryMenuByRoleIds(Set<Long> roleIds) { public LinkedHashSet<SystemMenuTb> queryMenuByRoleIds(Set<Long> roleIds) {
if (CollUtil.isEmpty(roleIds)) { if (CollUtil.isEmpty(roleIds)) {
return new LinkedHashSet<>(); return new LinkedHashSet<>();
}
LambdaQueryWrapper<SystemRoleMenuTb> roleMenuWrapper = new LambdaQueryWrapper<>();
roleMenuWrapper.in(SystemRoleMenuTb::getRoleId, roleIds);
List<Long> menuIds = systemRoleMenuMapper.selectList(roleMenuWrapper).stream().map(SystemRoleMenuTb::getMenuId)
.collect(Collectors.toList());
if (CollUtil.isEmpty(menuIds)) {
return new LinkedHashSet<>();
}
LambdaQueryWrapper<SystemMenuTb> menuWrapper = new LambdaQueryWrapper<>();
menuWrapper.in(SystemMenuTb::getId, menuIds);
// 排除"按钮"
menuWrapper.ne(SystemMenuTb::getType, 2);
menuWrapper.orderByAsc(SystemMenuTb::getMenuSort);
return new LinkedHashSet<>(systemMenuMapper.selectList(menuWrapper));
} }
LambdaQueryWrapper<SystemRoleMenuTb> roleMenuWrapper = new LambdaQueryWrapper<>();
roleMenuWrapper.in(SystemRoleMenuTb::getRoleId, roleIds);
List<Long> menuIds = systemRoleMenuMapper.selectList(roleMenuWrapper).stream().map(SystemRoleMenuTb::getMenuId)
.collect(Collectors.toList());
if (CollUtil.isEmpty(menuIds)) {
return new LinkedHashSet<>();
}
LambdaQueryWrapper<SystemMenuTb> menuWrapper = new LambdaQueryWrapper<>();
menuWrapper.in(SystemMenuTb::getId, menuIds);
// 排除"按钮"
menuWrapper.ne(SystemMenuTb::getType, 2);
menuWrapper.orderByAsc(SystemMenuTb::getMenuSort);
return new LinkedHashSet<>(systemMenuMapper.selectList(menuWrapper));
}
} }
@@ -18,322 +18,282 @@ package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemMenuTb; import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.dataobject.SystemRoleDeptTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemCreateRoleArgs; import cn.odboy.system.dal.model.SystemCreateRoleArgs;
import cn.odboy.system.dal.model.SystemQueryRoleArgs; import cn.odboy.system.dal.model.SystemQueryRoleArgs;
import cn.odboy.system.dal.model.SystemRoleCodeVo; import cn.odboy.system.dal.model.SystemRoleCodeVo;
import cn.odboy.system.dal.model.SystemRoleVo; import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.dal.mysql.SystemRoleDeptMapper;
import cn.odboy.system.dal.mysql.SystemRoleMapper; import cn.odboy.system.dal.mysql.SystemRoleMapper;
import cn.odboy.system.dal.mysql.SystemUserRoleMapper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemRoleService { public class SystemRoleService {
@Autowired private SystemRoleMapper systemRoleMapper;
@Autowired private SystemRoleMenuService systemRoleMenuService;
@Autowired private SystemRoleDeptService systemRoleDeptService;
@Autowired private SystemRoleDeptMapper systemRoleDeptMapper;
@Autowired private SystemUserRoleMapper systemUserRoleMapper;
@Autowired private SystemUserService systemUserService;
/** @Autowired
* 创建 private SystemRoleMapper systemRoleMapper;
* @Autowired
* @param args / private SystemRoleMenuService systemRoleMenuService;
*/ @Autowired
@Transactional(rollbackFor = Exception.class) private SystemRoleDeptService systemRoleDeptService;
public void saveRole(SystemCreateRoleArgs args) { @Autowired
if (this.getRoleByName(args.getName()) != null) { private SystemUserService systemUserService;
throw new BadRequestException("角色名称已存在"); @Autowired
} private SystemUserRoleService systemUserRoleService;
systemRoleMapper.insert(BeanUtil.copyProperties(args, SystemRoleTb.class));
// 判断是否有部门数据, 若有, 则需创建关联 /**
if (CollectionUtil.isNotEmpty(args.getDepts())) { * 创建
systemRoleDeptService.batchInsertRoleDept(args.getDepts(), args.getId()); *
} * @param args /
*/
@Transactional(rollbackFor = Exception.class)
public void saveRole(SystemCreateRoleArgs args) {
checkRoleLevels(args.getLevel());
if (this.getRoleByName(args.getName()) != null) {
throw new BadRequestException("角色名称已存在");
} }
systemRoleMapper.insert(BeanUtil.copyProperties(args, SystemRoleTb.class));
private SystemRoleTb getRoleByName(String name) { // 判断是否有部门数据, 若有, 则需创建关联
LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>(); if (CollectionUtil.isNotEmpty(args.getDepts())) {
wrapper.eq(SystemRoleTb::getName, name); systemRoleDeptService.batchInsertRoleDept(args.getDepts(), args.getId());
return systemRoleMapper.selectOne(wrapper);
} }
}
/** private SystemRoleTb getRoleByName(String name) {
* 修改 LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
* wrapper.eq(SystemRoleTb::getName, name);
* @param args / return systemRoleMapper.selectOne(wrapper);
*/ }
@Transactional(rollbackFor = Exception.class)
public void updateRoleById(SystemRoleVo args) { /**
SystemRoleVo role = BeanUtil.copyProperties(systemRoleMapper.selectById(args.getId()), SystemRoleVo.class); * 修改
SystemRoleTb role1 = this.getRoleByName(args.getName()); *
if (role1 != null && !role1.getId().equals(role.getId())) { * @param args /
throw new BadRequestException("角色名称已存在"); */
} @Transactional(rollbackFor = Exception.class)
role.setName(args.getName()); public void updateRoleById(SystemRoleVo args) {
role.setDescription(args.getDescription()); checkRoleLevels(args.getLevel());
role.setDataScope(args.getDataScope()); SystemRoleVo role = BeanUtil.copyProperties(systemRoleMapper.selectById(args.getId()), SystemRoleVo.class);
role.setDepts(args.getDepts()); SystemRoleTb role1 = this.getRoleByName(args.getName());
role.setLevel(args.getLevel()); if (role1 != null && !role1.getId().equals(role.getId())) {
// 更新 throw new BadRequestException("角色名称已存在");
systemRoleMapper.insertOrUpdate(role);
// 删除关联部门数据
systemRoleDeptService.batchDeleteRoleDept(Collections.singleton(args.getId()));
// 判断是否有部门数据, 若有, 则需更新关联
if (CollectionUtil.isNotEmpty(args.getDepts())) {
systemRoleDeptService.batchInsertRoleDept(args.getDepts(), args.getId());
}
} }
role.setName(args.getName());
/** role.setDescription(args.getDescription());
* 修改绑定的菜单 role.setDataScope(args.getDataScope());
* role.setDepts(args.getDepts());
* @param role / role.setLevel(args.getLevel());
*/ // 更新
public void updateBindMenuById(SystemRoleVo role) { systemRoleMapper.insertOrUpdate(role);
// 更新菜单 // 删除关联部门数据
systemRoleMenuService.deleteRoleMenuByRoleId(role.getId()); systemRoleDeptService.batchDeleteRoleDept(Collections.singleton(args.getId()));
// 判断是否为空 // 判断是否有部门数据, 若有, 则需更新关联
if (CollUtil.isNotEmpty(role.getMenus())) { if (CollectionUtil.isNotEmpty(args.getDepts())) {
systemRoleMenuService.batchInsertRoleMenu(role.getMenus(), role.getId()); systemRoleDeptService.batchInsertRoleDept(args.getDepts(), args.getId());
}
} }
}
/** /**
* 删除 * 修改绑定的菜单
* *
* @param ids / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) public void updateBindMenuById(SystemRoleVo args) {
public void deleteRoleByIds(Set<Long> ids) { SystemRoleTb role = systemRoleMapper.selectById(args.getId());
systemRoleMapper.deleteByIds(ids); checkRoleLevels(role.getLevel());
// 删除角色部门关联数据、角色菜单关联数据 // 更新菜单
systemRoleDeptService.batchDeleteRoleDept(ids); systemRoleMenuService.deleteRoleMenuByRoleId(role.getId());
systemRoleMenuService.batchDeleteRoleMenu(ids); // 判断是否为空
if (CollUtil.isNotEmpty(args.getMenus())) {
systemRoleMenuService.batchInsertRoleMenu(args.getMenus(), role.getId());
} }
}
/** /**
* 导出数据 * 删除
* *
* @param roles 待导出的数据 * @param ids /
* @param response / */
* @throws IOException @Transactional(rollbackFor = Exception.class)
*/ public void deleteRoleByIds(Set<Long> ids) {
public void exportRoleExcel(List<SystemRoleVo> roles, HttpServletResponse response) throws IOException { List<Integer> roleLevels = systemRoleMapper.selectByIds(ids).stream().map(SystemRoleTb::getLevel).distinct().collect(Collectors.toList());
List<Map<String, Object>> list = new ArrayList<>(); for (Integer roleLevel : roleLevels) {
for (SystemRoleVo role : roles) { checkRoleLevels(roleLevel);
Map<String, Object> map = new LinkedHashMap<>();
map.put("角色名称", role.getName());
map.put("角色级别", role.getLevel());
map.put("描述", role.getDescription());
map.put("创建日期", role.getCreateTime());
list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
// 验证是否被用户关联
this.verifyBindRelationByIds(ids);
// 删除角色
systemRoleMapper.deleteByIds(ids);
// 删除角色部门关联数据、角色菜单关联数据
systemRoleDeptService.batchDeleteRoleDept(ids);
systemRoleMenuService.batchDeleteRoleMenu(ids);
}
/** /**
* 查询全部角色 * 导出数据
*/ *
public List<SystemRoleTb> listAllRole() { * @param roles 待导出的数据
LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>(); * @param response /
wrapper.orderByAsc(SystemRoleTb::getLevel); */
return systemRoleMapper.selectList(wrapper); public void exportRoleExcel(List<SystemRoleVo> roles, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (SystemRoleVo role : roles) {
Map<String, Object> map = new LinkedHashMap<>();
map.put("角色名称", role.getName());
map.put("角色级别", role.getLevel());
map.put("描述", role.getDescription());
map.put("创建日期", role.getCreateTime());
list.add(map);
} }
KitFileUtil.downloadExcel(list, response);
}
/** /**
* 根据条件查询全部角色 * 查询全部角色
* */
* @param args 条件 public List<SystemRoleTb> listAllRole() {
* @return LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
*/ wrapper.orderByAsc(SystemRoleTb::getLevel);
public List<SystemRoleVo> queryRoleByArgs(SystemQueryRoleArgs args) { return systemRoleMapper.selectList(wrapper);
// 查询角色基本信息 }
LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) { /**
wrapper.and(StrUtil.isNotBlank(args.getBlurry()), c -> c.like(SystemRoleTb::getName, args.getBlurry()).or() * 根据条件查询全部角色
.like(SystemRoleTb::getDescription, args.getBlurry())); *
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { * @param args 条件
wrapper.between(SystemRoleTb::getCreateTime, args.getCreateTime().get(0), args.getCreateTime().get(1)); * @return /
} */
} public List<SystemRoleVo> queryRoleByArgs(SystemQueryRoleArgs args) {
wrapper.orderByAsc(SystemRoleTb::getLevel); // 查询角色基本信息
if (args != null && args.getSize() != null) { LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
Page<SystemRoleTb> rolePage = new Page<>(args.getPage(), args.getSize()); if (args != null) {
Page<SystemRoleTb> page = systemRoleMapper.selectPage(rolePage, wrapper); wrapper.and(StrUtil.isNotBlank(args.getBlurry()),
List<SystemRoleTb> roles = page.getRecords(); c -> c.like(SystemRoleTb::getName, args.getBlurry()).or()
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList()); .like(SystemRoleTb::getDescription, args.getBlurry()));
} else { if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
List<SystemRoleTb> roles = systemRoleMapper.selectList(wrapper); wrapper.between(SystemRoleTb::getCreateTime, args.getCreateTime().get(0),
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList()); args.getCreateTime().get(1));
} }
} }
wrapper.orderByAsc(SystemRoleTb::getLevel);
/** if (args != null && args.getSize() != null) {
* 分页查询角色 Page<SystemRoleTb> rolePage = new Page<>(args.getPage(), args.getSize());
* Page<SystemRoleTb> page = systemRoleMapper.selectPage(rolePage, wrapper);
* @param args 条件 List<SystemRoleTb> roles = page.getRecords();
* @param page 分页参数 return roles.stream().map(systemUserRoleService::convertToRoleVo).collect(Collectors.toList());
* @return } else {
*/ List<SystemRoleTb> roles = systemRoleMapper.selectList(wrapper);
public KitPageResult<SystemRoleVo> searchRoleByArgs(SystemQueryRoleArgs args, Page<Object> page) { return roles.stream().map(systemUserRoleService::convertToRoleVo).collect(Collectors.toList());
args.setOffset(page.offset());
List<SystemRoleVo> roles = this.queryRoleByArgs(args);
Long total = this.countRoleByArgs(args);
return KitPageUtil.toPage(roles, total);
} }
}
/** /**
* 根据用户ID查询 * 分页查询角色
* *
* @param userId 用户ID * @param args 条件
* @return / * @param page 分页参数
*/ * @return /
public List<SystemRoleVo> queryRoleByUsersId(Long userId) { */
// 查询用户角色关联 public KitPageResult<SystemRoleVo> searchRoleByArgs(SystemQueryRoleArgs args, Page<Object> page) {
LambdaQueryWrapper<SystemUserRoleTb> userRoleWrapper = new LambdaQueryWrapper<>(); args.setOffset(page.offset());
userRoleWrapper.eq(SystemUserRoleTb::getUserId, userId); List<SystemRoleVo> roles = this.queryRoleByArgs(args);
List<SystemUserRoleTb> userRoles = systemUserRoleMapper.selectList(userRoleWrapper); Long total = this.countRoleByArgs(args);
if (CollUtil.isEmpty(userRoles)) { return KitPageUtil.toPage(roles, total);
return new ArrayList<>(); }
}
Set<Long> roleIds = userRoles.stream().map(SystemUserRoleTb::getRoleId).collect(Collectors.toSet());
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds); /**
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList()); * 获取用户权限信息
*
* @param user 用户信息
* @return 权限信息
*/
public List<SystemRoleCodeVo> buildUserRolePermissions(SystemUserTb user) {
Set<String> permissions = new HashSet<>();
// 如果是管理员直接返回
if (user.getIsAdmin()) {
permissions.add("admin");
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
} }
List<SystemRoleVo> roles = systemUserRoleService.queryRoleByUsersId(user.getId());
permissions = roles.stream().flatMap(role -> role.getMenus().stream()).map(SystemMenuTb::getPermission)
.filter(StrUtil::isNotBlank).collect(Collectors.toSet());
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
}
/** /**
* 根据角色查询角色级别 * 验证是否被用户关联
* *
* @param roles / * @param ids /
* @return / */
*/ public void verifyBindRelationByIds(Set<Long> ids) {
public Integer getDeptLevelByRoles(Set<SystemRoleTb> roles) { if (systemUserService.countUserByRoleIds(ids) > 0) {
if (CollUtil.isEmpty(roles)) { throw new BadRequestException("所选角色存在用户关联, 请解除关联再试!");
return Integer.MAX_VALUE;
}
Set<SystemRoleTb> roleSet = new HashSet<>();
for (SystemRoleTb role : roles) {
roleSet.add(getRoleById(role.getId()));
}
return Collections.min(roleSet.stream().map(SystemRoleTb::getLevel).collect(Collectors.toList()));
} }
}
/** public Long countRoleByArgs(SystemQueryRoleArgs args) {
* 获取用户权限信息 LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
* if (args != null) {
* @param user 用户信息 wrapper.and(StrUtil.isNotBlank(args.getBlurry()),
* @return 权限信息 c -> c.like(SystemRoleTb::getName, args.getBlurry()).or()
*/ .like(SystemRoleTb::getDescription, args.getBlurry()));
public List<SystemRoleCodeVo> buildUserRolePermissions(SystemUserTb user) { if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
Set<String> permissions = new HashSet<>(); wrapper.between(SystemRoleTb::getCreateTime, args.getCreateTime().get(0),
// 如果是管理员直接返回 args.getCreateTime().get(1));
if (user.getIsAdmin()) { }
permissions.add("admin");
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
}
List<SystemRoleVo> roles = this.queryRoleByUsersId(user.getId());
permissions = roles.stream().flatMap(role -> role.getMenus().stream()).map(SystemMenuTb::getPermission)
.filter(StrUtil::isNotBlank).collect(Collectors.toSet());
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
} }
return systemRoleMapper.selectCount(wrapper);
}
/** public SystemRoleVo getRoleById(Long id) {
* 验证是否被用户关联 SystemRoleTb roleTb = systemRoleMapper.selectById(id);
* if (roleTb == null) {
* @param ids / return null;
*/
public void verifyBindRelationByIds(Set<Long> ids) {
if (systemUserService.countUserByRoleIds(ids) > 0) {
throw new BadRequestException("所选角色存在用户关联, 请解除关联再试!");
}
} }
return systemUserRoleService.convertToRoleVo(roleTb);
}
/** public Dict getRoleLevel() {
* 根据ID查询 return Dict.create().set("level", checkRoleLevels(null));
* }
* @param id /
* @return /
*/
public SystemRoleTb getRoleById(Long id) {
return systemRoleMapper.selectById(id);
}
/** /**
* 根据部门ID统计角色数量 * 检查用户的角色级别
* *
* @param deptIds 部门ID集合 * @return /
* @return / */
*/ private int checkRoleLevels(Integer level) {
public Long countRoleByDeptIds(Set<Long> deptIds) { List<Integer> levels = systemUserRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
if (CollUtil.isEmpty(deptIds)) { .map(SystemRoleTb::getLevel).collect(Collectors.toList());
return 0L; int min = Collections.min(levels);
} if (level != null) {
if (level < min) {
LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>(); throw new BadRequestException("权限不足, 你的角色级别:" + min + ", 低于操作的角色级别:" + level);
wrapper.in(SystemRoleDeptTb::getDeptId, deptIds); }
return systemRoleDeptMapper.selectCount(wrapper);
}
/**
* 转换为SystemRoleVo并关联查询菜单和部门信息
*
* @param role 角色基本信息
* @return 包含关联信息的SystemRoleVo
*/
private SystemRoleVo convertToRoleVo(SystemRoleTb role) {
if (role == null) {
return null;
}
SystemRoleVo roleVo = BeanUtil.copyProperties(role, SystemRoleVo.class);
// 查询关联的菜单信息
Set<SystemMenuTb> menus = systemRoleMenuService.queryMenuByRoleIds(Collections.singleton(role.getId()));
roleVo.setMenus(menus);
// 查询关联的部门信息
List<SystemDeptTb> depts = systemRoleDeptService.listDeptByRoleId(role.getId());
roleVo.setDepts(new LinkedHashSet<>(depts));
return roleVo;
}
public Long countRoleByArgs(SystemQueryRoleArgs args) {
LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) {
wrapper.and(StrUtil.isNotBlank(args.getBlurry()), c -> c.like(SystemRoleTb::getName, args.getBlurry()).or()
.like(SystemRoleTb::getDescription, args.getBlurry()));
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemRoleTb::getCreateTime, args.getCreateTime().get(0), args.getCreateTime().get(1));
}
}
return systemRoleMapper.selectCount(wrapper);
} }
return min;
}
} }
@@ -0,0 +1,21 @@
package cn.odboy.system.service;
import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.mysql.SystemUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SystemUserDeptService {
@Autowired
private SystemUserMapper systemUserMapper;
public long countUserByDeptIds(Set<Long> deptIds) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserTb::getDeptId, deptIds);
return systemUserMapper.selectCount(wrapper);
}
}
@@ -30,28 +30,29 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemUserJobService { public class SystemUserJobService {
@Autowired private SystemUserJobMapper systemUserJobMapper; @Autowired
private SystemUserJobMapper systemUserJobMapper;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchInsertUserJob(Set<SystemJobTb> jobs, Long userId) { public void batchInsertUserJob(Set<SystemJobTb> jobs, Long userId) {
if (CollUtil.isNotEmpty(jobs)) { if (CollUtil.isNotEmpty(jobs)) {
List<SystemUserJobTb> records = new ArrayList<>(); List<SystemUserJobTb> records = new ArrayList<>();
for (SystemJobTb job : jobs) { for (SystemJobTb job : jobs) {
SystemUserJobTb record = new SystemUserJobTb(); SystemUserJobTb record = new SystemUserJobTb();
record.setUserId(userId); record.setUserId(userId);
record.setJobId(job.getId()); record.setJobId(job.getId());
records.add(record); records.add(record);
} }
systemUserJobMapper.insert(records); systemUserJobMapper.insert(records);
}
} }
}
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchDeleteUserJob(Set<Long> userIds) { public void batchDeleteUserJob(Set<Long> userIds) {
if (CollUtil.isNotEmpty(userIds)) { if (CollUtil.isNotEmpty(userIds)) {
LambdaQueryWrapper<SystemUserJobTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemUserJobTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserJobTb::getUserId, userIds); wrapper.in(SystemUserJobTb::getUserId, userIds);
systemUserJobMapper.delete(wrapper); systemUserJobMapper.delete(wrapper);
}
} }
}
} }
@@ -15,14 +15,26 @@
*/ */
package cn.odboy.system.service; package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserRoleTb; import cn.odboy.system.dal.dataobject.SystemUserRoleTb;
import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.dal.model.SystemUserVo;
import cn.odboy.system.dal.mysql.SystemRoleMapper;
import cn.odboy.system.dal.mysql.SystemUserRoleMapper; import cn.odboy.system.dal.mysql.SystemUserRoleMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -30,28 +42,109 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemUserRoleService { public class SystemUserRoleService {
@Autowired private SystemUserRoleMapper systemUserRoleMapper; @Autowired
private SystemRoleMapper systemRoleMapper;
@Autowired
private SystemUserRoleMapper systemUserRoleMapper;
@Autowired
private SystemRoleMenuService systemRoleMenuService;
@Autowired
private SystemRoleDeptService systemRoleDeptService;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchInsertUserRole(Set<SystemRoleTb> roles, Long userId) { public void batchInsertUserRole(Set<SystemRoleTb> roles, Long userId) {
if (CollUtil.isNotEmpty(roles)) { if (CollUtil.isNotEmpty(roles)) {
List<SystemUserRoleTb> records = new ArrayList<>(); List<SystemUserRoleTb> records = new ArrayList<>();
for (SystemRoleTb role : roles) { for (SystemRoleTb role : roles) {
SystemUserRoleTb record = new SystemUserRoleTb(); SystemUserRoleTb record = new SystemUserRoleTb();
record.setUserId(userId); record.setUserId(userId);
record.setRoleId(role.getId()); record.setRoleId(role.getId());
records.add(record); records.add(record);
} }
systemUserRoleMapper.insert(records); systemUserRoleMapper.insert(records);
}
} }
}
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchDeleteUserRole(Set<Long> userIds) { public void batchDeleteUserRole(Set<Long> userIds) {
if (CollUtil.isNotEmpty(userIds)) { if (CollUtil.isNotEmpty(userIds)) {
LambdaQueryWrapper<SystemUserRoleTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemUserRoleTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserRoleTb::getUserId, userIds); wrapper.in(SystemUserRoleTb::getUserId, userIds);
systemUserRoleMapper.delete(wrapper); systemUserRoleMapper.delete(wrapper);
}
} }
}
/**
* 转换为SystemRoleVo并关联查询菜单和部门信息
*
* @param role 角色基本信息
* @return 包含关联信息的SystemRoleVo
*/
public SystemRoleVo convertToRoleVo(SystemRoleTb role) {
if (role == null) {
return null;
}
SystemRoleVo roleVo = BeanUtil.copyProperties(role, SystemRoleVo.class);
// 查询关联的菜单信息
Set<SystemMenuTb> menus = systemRoleMenuService.queryMenuByRoleIds(
Collections.singleton(role.getId()));
roleVo.setMenus(menus);
// 查询关联的部门信息
List<SystemDeptTb> depts = systemRoleDeptService.listDeptByRoleId(role.getId());
roleVo.setDepts(new LinkedHashSet<>(depts));
return roleVo;
}
/**
* 根据用户ID查询
*
* @param userId 用户ID
* @return /
*/
public List<SystemRoleVo> queryRoleByUsersId(Long userId) {
// 查询用户角色关联
LambdaQueryWrapper<SystemUserRoleTb> userRoleWrapper = new LambdaQueryWrapper<>();
userRoleWrapper.eq(SystemUserRoleTb::getUserId, userId);
List<SystemUserRoleTb> userRoles = systemUserRoleMapper.selectList(userRoleWrapper);
if (CollUtil.isEmpty(userRoles)) {
return new ArrayList<>();
}
Set<Long> roleIds = userRoles.stream().map(SystemUserRoleTb::getRoleId).collect(Collectors.toSet());
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds);
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList());
}
/**
* 根据角色查询角色级别
*
* @param roles /
* @return /
*/
public Integer getDeptLevelByRoles(Set<SystemRoleTb> roles) {
if (CollUtil.isEmpty(roles)) {
return Integer.MAX_VALUE;
}
Set<SystemRoleTb> roleSet = new HashSet<>();
for (SystemRoleTb role : roles) {
roleSet.add(systemRoleMapper.selectById(role.getId()));
}
return Collections.min(roleSet.stream().map(SystemRoleTb::getLevel).collect(Collectors.toList()));
}
/**
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误
*
* @param args /
*/
public void checkLevel(SystemUserVo args) {
Integer currentLevel = Collections.min(
this.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = this.getDeptLevelByRoles(args.getRoles());
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
}
}
} }
@@ -17,12 +17,15 @@ package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.base.KitSelectOptionVo; import cn.odboy.base.KitSelectOptionVo;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.server.core.KitFileLocalUploadHelper; import cn.odboy.framework.server.core.KitFileLocalUploadHelper;
import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.dataobject.SystemDeptTb; import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemJobTb; import cn.odboy.system.dal.dataobject.SystemJobTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
@@ -30,6 +33,7 @@ import cn.odboy.system.dal.dataobject.SystemUserJobTb;
import cn.odboy.system.dal.dataobject.SystemUserRoleTb; import cn.odboy.system.dal.dataobject.SystemUserRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemQueryUserArgs; import cn.odboy.system.dal.model.SystemQueryUserArgs;
import cn.odboy.system.dal.model.SystemUpdateUserPasswordArgs;
import cn.odboy.system.dal.model.SystemUserVo; import cn.odboy.system.dal.model.SystemUserVo;
import cn.odboy.system.dal.mysql.SystemDeptMapper; import cn.odboy.system.dal.mysql.SystemDeptMapper;
import cn.odboy.system.dal.mysql.SystemJobMapper; import cn.odboy.system.dal.mysql.SystemJobMapper;
@@ -42,10 +46,10 @@ import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.KitSecurityHelper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitRsaEncryptUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@@ -58,442 +62,516 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@Service @Service
public class SystemUserService { public class SystemUserService {
@Autowired @Autowired
private SystemUserMapper systemUserMapper; private SystemUserMapper systemUserMapper;
@Autowired @Autowired
private SystemUserJobService systemUserJobService; private SystemJobMapper systemJobMapper;
@Autowired @Autowired
private SystemUserRoleService systemUserRoleService; private SystemRoleMapper systemRoleMapper;
@Autowired @Autowired
private SystemUserInfoDAO systemUserInfoDAO; private SystemDeptMapper systemDeptMapper;
@Autowired @Autowired
private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO; private SystemUserJobService systemUserJobService;
@Autowired @Autowired
private KitFileLocalUploadHelper fileUploadPathHelper; private SystemUserRoleService systemUserRoleService;
@Autowired @Autowired
private SystemUserJobMapper systemUserJobMapper; private SystemEmailService systemEmailService;
@Autowired @Autowired
private SystemUserRoleMapper systemUserRoleMapper; private SystemDeptService systemDeptService;
@Autowired @Autowired
private SystemJobMapper systemJobMapper; private SystemDataService systemDataService;
@Autowired @Autowired
private SystemRoleMapper systemRoleMapper; private SystemUserInfoDAO systemUserInfoDAO;
@Autowired @Autowired
private SystemDeptMapper systemDeptMapper; private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
@Autowired
private KitFileLocalUploadHelper fileUploadPathHelper;
@Autowired
private SystemUserJobMapper systemUserJobMapper;
@Autowired
private SystemUserRoleMapper systemUserRoleMapper;
@Autowired
private AppProperties properties;
@Autowired
private PasswordEncoder passwordEncoder;
/**
* 新增用户 /**
* * 新增用户
* @param args / *
*/ * @param args /
@Transactional(rollbackFor = Exception.class) */
public void saveUser(SystemUserVo args) { @Transactional(rollbackFor = Exception.class)
args.setDeptId(args.getDept().getId()); public void saveUser(SystemUserVo args) {
if (this.getUserByUsername(args.getUsername()) != null) { systemUserRoleService.checkLevel(args);
throw new BadRequestException("用户名已存在"); // 默认密码 123456
} args.setPassword(passwordEncoder.encode("123456"));
if (this.getUserByEmail(args.getEmail()) != null) { args.setDeptId(args.getDept().getId());
throw new BadRequestException("邮箱已存在"); if (this.getUserByUsername(args.getUsername()) != null) {
} throw new BadRequestException("用户名已存在");
if (this.getUserByPhone(args.getPhone()) != null) {
throw new BadRequestException("手机号已存在");
}
systemUserMapper.insert(args);
// 保存用户岗位
systemUserJobService.batchInsertUserJob(args.getJobs(), args.getId());
// 保存用户角色
systemUserRoleService.batchInsertUserRole(args.getRoles(), args.getId());
} }
if (this.getUserByEmail(args.getEmail()) != null) {
/** throw new BadRequestException("邮箱已存在");
* 编辑用户
*
* @param args /
*/
@Transactional(rollbackFor = Exception.class)
public void updateUserById(SystemUserVo args) {
SystemUserTb user = systemUserMapper.selectById(args.getId());
SystemUserTb user1 = this.getUserByUsername(args.getUsername());
SystemUserTb user2 = this.getUserByEmail(args.getEmail());
SystemUserTb user3 = this.getUserByPhone(args.getPhone());
if (user1 != null && !user.getId().equals(user1.getId())) {
throw new BadRequestException("用户名已存在");
}
if (user2 != null && !user.getId().equals(user2.getId())) {
throw new BadRequestException("邮箱已存在");
}
if (user3 != null && !user.getId().equals(user3.getId())) {
throw new BadRequestException("手机号已存在");
}
// 如果用户被禁用, 则清除用户登录信息
if (!args.getEnabled()) {
systemUserOnlineInfoDAO.kickOutByUsername(args.getUsername());
}
user.setDeptId(args.getDept().getId());
user.setUsername(args.getUsername());
user.setEmail(args.getEmail());
user.setEnabled(args.getEnabled());
user.setDept(args.getDept());
user.setPhone(args.getPhone());
user.setNickName(args.getNickName());
user.setGender(args.getGender());
systemUserMapper.insertOrUpdate(user);
// 清除用户登录缓存
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
// 更新用户岗位
systemUserJobService.batchDeleteUserJob(Collections.singleton(args.getId()));
systemUserJobService.batchInsertUserJob(args.getJobs(), args.getId());
// 更新用户角色
systemUserRoleService.batchDeleteUserRole(Collections.singleton(args.getId()));
systemUserRoleService.batchInsertUserRole(args.getRoles(), args.getId());
} }
if (this.getUserByPhone(args.getPhone()) != null) {
/** throw new BadRequestException("手机号已存在");
* 用户自助修改资料
*
* @param args /
*/
@Transactional(rollbackFor = Exception.class)
public void updateUserCenterInfoById(SystemUserTb args) {
SystemUserTb user = systemUserMapper.selectById(args.getId());
SystemUserTb user1 = this.getUserByPhone(args.getPhone());
if (user1 != null && !user.getId().equals(user1.getId())) {
throw new BadRequestException("手机号已存在");
}
user.setNickName(args.getNickName());
user.setPhone(args.getPhone());
user.setGender(args.getGender());
systemUserMapper.insertOrUpdate(user);
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
} }
// 保存用户
systemUserMapper.insert(args);
// 保存用户岗位
systemUserJobService.batchInsertUserJob(args.getJobs(), args.getId());
// 保存用户角色
systemUserRoleService.batchInsertUserRole(args.getRoles(), args.getId());
}
/** /**
* 删除用户 * 编辑用户
* *
* @param ids / * @param args /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void removeUserByIds(Set<Long> ids) { public void updateUserById(SystemUserVo args) {
for (Long id : ids) { systemUserRoleService.checkLevel(args);
// 清理缓存 SystemUserTb user = systemUserMapper.selectById(args.getId());
SystemUserTb user = systemUserMapper.selectById(id); SystemUserTb user1 = this.getUserByUsername(args.getUsername());
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername()); SystemUserTb user2 = this.getUserByEmail(args.getEmail());
} SystemUserTb user3 = this.getUserByPhone(args.getPhone());
systemUserMapper.deleteByIds(ids); if (user1 != null && !user.getId().equals(user1.getId())) {
// 删除用户岗位 throw new BadRequestException("用户名已存在");
systemUserJobService.batchDeleteUserJob(ids);
// 删除用户角色
systemUserRoleService.batchDeleteUserRole(ids);
} }
if (user2 != null && !user.getId().equals(user2.getId())) {
/** throw new BadRequestException("邮箱已存在");
* 修改密码
*
* @param username 用户名
* @param encryptPassword 密码
*/
@Transactional(rollbackFor = Exception.class)
public void updateUserPasswordByUsername(String username, String encryptPassword) {
systemUserMapper.updateUserPasswordByUsername(username, encryptPassword);
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
} }
if (user3 != null && !user.getId().equals(user3.getId())) {
/** throw new BadRequestException("手机号已存在");
* 重置密码
*
* @param ids 用户id
* @param password 密码
*/
@Transactional(rollbackFor = Exception.class)
public void resetUserPasswordByIds(Set<Long> ids, String password) {
List<SystemUserTb> users = systemUserMapper.selectByIds(ids);
// 清除缓存
users.forEach(user -> {
// 清除缓存
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
// 强制退出
systemUserOnlineInfoDAO.kickOutByUsername(user.getUsername());
});
// 重置密码
systemUserMapper.updateUserPasswordByUserIds(password, ids);
} }
// 如果用户被禁用, 则清除用户登录信息
/** if (!args.getEnabled()) {
* 修改头像 systemUserOnlineInfoDAO.kickOutByUsername(args.getUsername());
*
* @param multipartFile 文件
* @return /
*/
@Transactional(rollbackFor = Exception.class)
public Map<String, String> updateUserAvatar(MultipartFile multipartFile) {
SystemUserTb user = this.getUserByUsername(KitSecurityHelper.getCurrentUsername());
String username = user.getUsername();
if (StrUtil.isBlank(username)) {
throw new BadRequestException("异常用户数据, 请联系管理员处理");
}
// 文件大小验证
KitFileUtil.checkSize(fileUploadPathHelper.getAvatarMaxSize(), multipartFile.getSize());
// 验证文件上传的格式
String image = "gif jpg png jpeg";
String fileType = KitFileUtil.getSuffix(multipartFile.getOriginalFilename());
if (fileType != null && !image.contains(fileType)) {
throw new BadRequestException("文件格式错误!, 仅支持 " + image + " 格式");
}
String oldPath = user.getAvatarPath();
File file = KitFileUtil.upload(multipartFile, fileUploadPathHelper.getPath());
user.setAvatarPath(Objects.requireNonNull(file).getPath());
user.setAvatarName(file.getName());
systemUserMapper.insertOrUpdate(user);
if (StrUtil.isNotBlank(oldPath)) {
KitFileUtil.del(oldPath);
}
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
return new HashMap<>(1) {{
put("avatar", file.getName());
}};
} }
user.setDeptId(args.getDept().getId());
user.setUsername(args.getUsername());
user.setEmail(args.getEmail());
user.setEnabled(args.getEnabled());
user.setDept(args.getDept());
user.setPhone(args.getPhone());
user.setNickName(args.getNickName());
user.setGender(args.getGender());
systemUserMapper.insertOrUpdate(user);
// 清除用户登录缓存
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
// 更新用户岗位
systemUserJobService.batchDeleteUserJob(Collections.singleton(args.getId()));
systemUserJobService.batchInsertUserJob(args.getJobs(), args.getId());
// 更新用户角色
systemUserRoleService.batchDeleteUserRole(Collections.singleton(args.getId()));
systemUserRoleService.batchInsertUserRole(args.getRoles(), args.getId());
}
/** /**
* 修改邮箱 * 用户自助修改资料
* *
* @param username 用户名 * @param args /
* @param email 邮箱 */
*/ @Transactional(rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class) public void updateUserCenterInfoById(SystemUserTb args) {
public void updateUserEmailByUsername(String username, String email) { if (!args.getId().equals(KitSecurityHelper.getCurrentUserId())) {
systemUserMapper.updateUserEmailByUsername(username, email); throw new BadRequestException("不能修改他人资料");
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
} }
SystemUserTb user = systemUserMapper.selectById(args.getId());
/** SystemUserTb user1 = this.getUserByPhone(args.getPhone());
* 导出数据 if (user1 != null && !user.getId().equals(user1.getId())) {
* throw new BadRequestException("手机号已存在");
* @param users 待导出的数据
* @param response /
* @throws IOException /
*/
public void exportUserExcel(List<SystemUserVo> users, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (SystemUserVo user : users) {
List<String> roles = user.getRoles().stream().map(SystemRoleTb::getName).collect(Collectors.toList());
Map<String, Object> map = new LinkedHashMap<>();
map.put("用户名", user.getUsername());
map.put("角色", roles);
map.put("部门", user.getDept().getName());
map.put("岗位", user.getJobs().stream().map(SystemJobTb::getName).collect(Collectors.toList()));
map.put("邮箱", user.getEmail());
map.put("状态", user.getEnabled() ? "启用" : "禁用");
map.put("手机号码", user.getPhone());
map.put("修改密码的时间", user.getPwdResetTime());
map.put("创建日期", user.getCreateTime());
list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
user.setNickName(args.getNickName());
user.setPhone(args.getPhone());
user.setGender(args.getGender());
systemUserMapper.insertOrUpdate(user);
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
}
/** /**
* 查询全部 * 删除用户
* *
* @param args 条件 * @param ids /
* @param page 分页参数 */
* @return / @Transactional(rollbackFor = Exception.class)
*/ public void removeUserByIds(Set<Long> ids) {
public KitPageResult<SystemUserVo> searchUserByArgs(SystemQueryUserArgs args, Page<SystemUserTb> page) { Long currentUserId = KitSecurityHelper.getCurrentUserId();
// 查询用户基本信息 // 校验权限
LambdaQueryWrapper<SystemUserTb> wrapper = buildUserQueryWrapper(args); for (Long id : ids) {
IPage<SystemUserTb> userPage = systemUserMapper.selectPage(page, wrapper); Integer currentLevel = Collections.min(
List<SystemUserTb> users = userPage.getRecords(); systemUserRoleService.queryRoleByUsersId(currentUserId).stream()
// 转换为SystemUserVo并关联查询 .map(SystemRoleTb::getLevel).collect(Collectors.toList()));
List<SystemUserVo> userVos = users.stream().map(this::convertToUserVo).collect(Collectors.toList()); Integer optLevel = Collections.min(
return KitPageUtil.toPage(userVos, userPage.getTotal()); systemUserRoleService.queryRoleByUsersId(id).stream().map(SystemRoleTb::getLevel)
.collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException(
"角色权限不足, 不能删除:" + this.getUserById(id).getUsername());
}
} }
// 清理缓存
/** List<String> usernameList = systemUserMapper.selectByIds(ids).stream().map(SystemUserTb::getUsername).distinct().collect(Collectors.toList());
* 查询全部不分页 for (String username : usernameList) {
* systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
* @param args 条件
* @return /
*/
public List<SystemUserVo> queryUserByArgs(SystemQueryUserArgs args) {
// 查询用户基本信息
LambdaQueryWrapper<SystemUserTb> wrapper = buildUserQueryWrapper(args);
List<SystemUserTb> users = systemUserMapper.selectList(wrapper);
// 转换为SystemUserVo并关联查询
return users.stream().map(this::convertToUserVo).collect(Collectors.toList());
} }
// 删除用户
systemUserMapper.deleteByIds(ids);
// 删除用户岗位
systemUserJobService.batchDeleteUserJob(ids);
// 删除用户角色
systemUserRoleService.batchDeleteUserRole(ids);
}
/** /**
* 根据ID查询 * 修改密码
* *
* @param id ID * @param username 用户名
* @return / * @param args 参数
*/ */
public SystemUserTb getUserById(long id) { @Transactional(rollbackFor = Exception.class)
return systemUserMapper.selectById(id); public void updateUserPasswordByUsername(String username, SystemUpdateUserPasswordArgs args) throws Exception {
String oldPass =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getOldPass());
String newPass =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getNewPass());
SystemUserTb user = this.getUserByUsername(username);
if (!passwordEncoder.matches(oldPass, user.getPassword())) {
throw new BadRequestException("修改失败,旧密码错误");
} }
if (passwordEncoder.matches(newPass, user.getPassword())) {
public List<KitSelectOptionVo> queryUserMetadataOptions(KitPageArgs<SystemQueryUserArgs> pageArgs) { throw new BadRequestException("新密码不能与旧密码相同");
SystemQueryUserArgs args = pageArgs.getArgs();
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.select(SystemUserTb::getId, SystemUserTb::getDeptId, SystemUserTb::getEmail, SystemUserTb::getPhone);
wrapper.and(c -> {
c.eq(SystemUserTb::getPhone, args.getBlurry());
c.or();
c.eq(SystemUserTb::getEmail, args.getBlurry());
c.or();
c.like(SystemUserTb::getUsername, args.getBlurry());
c.or();
c.like(SystemUserTb::getNickName, args.getBlurry());
});
return systemUserMapper.selectPage(new Page<>(args.getPage(), 50), wrapper).getRecords().stream().map(m -> {
Map<String, Object> ext = new HashMap<>(1);
ext.put("id", m.getId());
ext.put("deptId", m.getDeptId());
ext.put("email", m.getEmail());
ext.put("phone", m.getPhone());
return KitSelectOptionVo.builder().label(m.getNickName()).value(String.valueOf(m.getId())).ext(ext).build();
}).collect(Collectors.toList());
} }
String encryptPassword = passwordEncoder.encode(newPass);
systemUserMapper.updateUserPasswordByUsername(username, encryptPassword);
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
}
/** /**
* 根据岗位ID统计用户数量 * 重置密码
* *
* @param jobIds 岗位ID集合 * @param ids 用户id
* @return / */
*/ @Transactional(rollbackFor = Exception.class)
public Long countUserByJobIds(Set<Long> jobIds) { public void resetUserPasswordByIds(Set<Long> ids) {
if (CollUtil.isEmpty(jobIds)) { String defaultPwd = passwordEncoder.encode("123456");
return 0L; List<SystemUserTb> users = systemUserMapper.selectByIds(ids);
} // 清除缓存
LambdaQueryWrapper<SystemUserJobTb> wrapper = new LambdaQueryWrapper<>(); for (SystemUserTb user : users) {
wrapper.in(SystemUserJobTb::getJobId, jobIds); // 清除缓存
return systemUserJobMapper.selectCount(wrapper); systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
// 强制退出
systemUserOnlineInfoDAO.kickOutByUsername(user.getUsername());
} }
// 重置密码
systemUserMapper.updateUserPasswordByUserIds(defaultPwd, ids);
}
/** /**
* 根据角色ID统计用户数量 * 修改头像
* *
* @param roleIds 角色ID集合 * @param multipartFile 文件
* @return / * @return /
*/ */
public Long countUserByRoleIds(Set<Long> roleIds) { @Transactional(rollbackFor = Exception.class)
if (CollUtil.isEmpty(roleIds)) { public Map<String, String> updateUserAvatar(MultipartFile multipartFile) {
return 0L; SystemUserTb user = this.getUserByUsername(KitSecurityHelper.getCurrentUsername());
} String username = user.getUsername();
LambdaQueryWrapper<SystemUserRoleTb> wrapper = new LambdaQueryWrapper<>(); if (StrUtil.isBlank(username)) {
wrapper.in(SystemUserRoleTb::getRoleId, roleIds); throw new BadRequestException("异常用户数据, 请联系管理员处理");
return systemUserRoleMapper.selectCount(wrapper);
} }
// 文件大小验证
/** KitFileUtil.checkSize(fileUploadPathHelper.getAvatarMaxSize(), multipartFile.getSize());
* 构建用户查询条件 // 验证文件上传的格式
* String image = "gif jpg png jpeg";
* @param args 查询条件 String fileType = KitFileUtil.getSuffix(multipartFile.getOriginalFilename());
* @return / if (fileType != null && !image.contains(fileType)) {
*/ throw new BadRequestException("文件格式错误!, 仅支持 " + image + " 格式");
private LambdaQueryWrapper<SystemUserTb> buildUserQueryWrapper(SystemQueryUserArgs args) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) {
if (args.getId() != null) {
wrapper.eq(SystemUserTb::getId, args.getId());
}
if (args.getEnabled() != null) {
wrapper.eq(SystemUserTb::getEnabled, args.getEnabled());
}
if (CollUtil.isNotEmpty(args.getDeptIds())) {
wrapper.in(SystemUserTb::getDeptId, args.getDeptIds());
}
if (StrUtil.isNotBlank(args.getBlurry())) {
wrapper.and(w -> w.like(SystemUserTb::getUsername, args.getBlurry())
.or().like(SystemUserTb::getNickName, args.getBlurry())
.or().like(SystemUserTb::getEmail, args.getBlurry()));
}
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemUserTb::getCreateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1));
}
}
wrapper.orderByDesc(SystemUserTb::getCreateTime);
return wrapper;
} }
String oldPath = user.getAvatarPath();
/** File file = KitFileUtil.upload(multipartFile, fileUploadPathHelper.getPath());
* 转换为SystemUserVo并关联查询部门、角色、岗位信息 user.setAvatarPath(Objects.requireNonNull(file).getPath());
* user.setAvatarName(file.getName());
* @param user 用户基本信息 systemUserMapper.insertOrUpdate(user);
* @return 包含关联信息的SystemUserVo if (StrUtil.isNotBlank(oldPath)) {
*/ KitFileUtil.del(oldPath);
private SystemUserVo convertToUserVo(SystemUserTb user) {
if (user == null) {
return null;
}
SystemUserVo userVo = BeanUtil.copyProperties(user, SystemUserVo.class);
// 查询关联的部门信息
if (user.getDeptId() != null) {
SystemDeptTb dept = systemDeptMapper.selectById(user.getDeptId());
userVo.setDept(dept);
}
// 查询关联的岗位信息
LambdaQueryWrapper<SystemUserJobTb> jobWrapper = new LambdaQueryWrapper<>();
jobWrapper.eq(SystemUserJobTb::getUserId, user.getId());
List<SystemUserJobTb> userJobs = systemUserJobMapper.selectList(jobWrapper);
if (CollUtil.isNotEmpty(userJobs)) {
Set<Long> jobIds = userJobs.stream().map(SystemUserJobTb::getJobId).collect(Collectors.toSet());
List<SystemJobTb> jobs = systemJobMapper.selectByIds(jobIds);
userVo.setJobs(new LinkedHashSet<>(jobs));
}
// 查询关联的角色信息
LambdaQueryWrapper<SystemUserRoleTb> roleWrapper = new LambdaQueryWrapper<>();
roleWrapper.eq(SystemUserRoleTb::getUserId, user.getId());
List<SystemUserRoleTb> userRoles = systemUserRoleMapper.selectList(roleWrapper);
if (CollUtil.isNotEmpty(userRoles)) {
Set<Long> roleIds = userRoles.stream().map(SystemUserRoleTb::getRoleId).collect(Collectors.toSet());
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds);
userVo.setRoles(new LinkedHashSet<>(roles));
}
return userVo;
} }
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
return new HashMap<>(1) {{
put("avatar", file.getName());
}};
}
public SystemUserTb getUserByUsername(String username) { /**
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>(); * 修改邮箱
wrapper.eq(SystemUserTb::getUsername, username); *
wrapper.eq(SystemUserTb::getEnabled, 1); * @param username 用户名
return systemUserMapper.selectOne(wrapper); * @param args 参数
* @param code 验证码
*/
@Transactional(rollbackFor = Exception.class)
public void updateUserEmailByUsername(String username, SystemUserTb args, String code) throws Exception {
String password =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getPassword());
SystemUserTb user = this.getUserByUsername(username);
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadRequestException("密码错误");
} }
systemEmailService.checkEmailCaptchaV1(SystemCaptchaBizEnum.EMAIL_RESET_EMAIL_CODE, args.getEmail(), code);
systemUserMapper.updateUserEmailByUsername(username, args.getEmail());
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
}
public SystemUserVo getUserVoByUsername(String username) { /**
return this.convertToUserVo(this.getUserByUsername(username)); * 导出数据
*
* @param users 待导出的数据
* @param response /
* @throws IOException /
*/
public void exportUserExcel(List<SystemUserVo> users, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>();
for (SystemUserVo user : users) {
List<String> roles = user.getRoles().stream().map(SystemRoleTb::getName).collect(Collectors.toList());
Map<String, Object> map = new LinkedHashMap<>();
map.put("用户名", user.getUsername());
map.put("角色", roles);
map.put("部门", user.getDept().getName());
map.put("岗位", user.getJobs().stream().map(SystemJobTb::getName).collect(Collectors.toList()));
map.put("邮箱", user.getEmail());
map.put("状态", user.getEnabled() ? "启用" : "禁用");
map.put("手机号码", user.getPhone());
map.put("修改密码的时间", user.getPwdResetTime());
map.put("创建日期", user.getCreateTime());
list.add(map);
} }
KitFileUtil.downloadExcel(list, response);
}
public long countUserByDeptIds(Set<Long> deptIds) { /**
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>(); * 查询全部
wrapper.in(SystemUserTb::getDeptId, deptIds); *
return systemUserMapper.selectCount(wrapper); * @param args 条件
} * @param page 分页参数
* @return /
*/
public KitPageResult<SystemUserVo> searchUserByArgs(SystemQueryUserArgs args, Page<SystemUserTb> page) {
// 查询用户基本信息
LambdaQueryWrapper<SystemUserTb> wrapper = buildUserQueryWrapper(args);
IPage<SystemUserTb> userPage = systemUserMapper.selectPage(page, wrapper);
List<SystemUserTb> users = userPage.getRecords();
// 转换为SystemUserVo并关联查询
List<SystemUserVo> userVos = users.stream().map(this::convertToUserVo).collect(Collectors.toList());
return KitPageUtil.toPage(userVos, userPage.getTotal());
}
public SystemUserTb getUserByEmail(String email) { /**
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>(); * 查询全部不分页
wrapper.eq(SystemUserTb::getEmail, email); *
wrapper.eq(SystemUserTb::getEnabled, 1); * @param args 条件
return systemUserMapper.selectOne(wrapper); * @return /
} */
public List<SystemUserVo> queryUserByArgs(SystemQueryUserArgs args) {
// 查询用户基本信息
LambdaQueryWrapper<SystemUserTb> wrapper = buildUserQueryWrapper(args);
List<SystemUserTb> users = systemUserMapper.selectList(wrapper);
// 转换为SystemUserVo并关联查询
return users.stream().map(this::convertToUserVo).collect(Collectors.toList());
}
public SystemUserTb getUserByPhone(String phone) { /**
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>(); * 根据ID查询
wrapper.eq(SystemUserTb::getPhone, phone); *
wrapper.eq(SystemUserTb::getEnabled, 1); * @param id ID
return systemUserMapper.selectOne(wrapper); * @return /
*/
public SystemUserTb getUserById(long id) {
return systemUserMapper.selectById(id);
}
public List<KitSelectOptionVo> queryUserMetadataOptions(KitPageArgs<SystemQueryUserArgs> pageArgs) {
SystemQueryUserArgs args = pageArgs.getArgs();
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.select(SystemUserTb::getId, SystemUserTb::getDeptId, SystemUserTb::getEmail, SystemUserTb::getPhone);
wrapper.and(c -> {
c.eq(SystemUserTb::getPhone, args.getBlurry());
c.or();
c.eq(SystemUserTb::getEmail, args.getBlurry());
c.or();
c.like(SystemUserTb::getUsername, args.getBlurry());
c.or();
c.like(SystemUserTb::getNickName, args.getBlurry());
});
return systemUserMapper.selectPage(new Page<>(args.getPage(), 50), wrapper).getRecords().stream().map(m -> {
Map<String, Object> ext = new HashMap<>(1);
ext.put("id", m.getId());
ext.put("deptId", m.getDeptId());
ext.put("email", m.getEmail());
ext.put("phone", m.getPhone());
return KitSelectOptionVo.builder().label(m.getNickName()).value(String.valueOf(m.getId())).ext(ext).build();
}).collect(Collectors.toList());
}
/**
* 根据岗位ID统计用户数量
*
* @param jobIds 岗位ID集合
* @return /
*/
public Long countUserByJobIds(Set<Long> jobIds) {
if (CollUtil.isEmpty(jobIds)) {
return 0L;
} }
LambdaQueryWrapper<SystemUserJobTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserJobTb::getJobId, jobIds);
return systemUserJobMapper.selectCount(wrapper);
}
/**
* 根据角色ID统计用户数量
*
* @param roleIds 角色ID集合
* @return /
*/
public Long countUserByRoleIds(Set<Long> roleIds) {
if (CollUtil.isEmpty(roleIds)) {
return 0L;
}
LambdaQueryWrapper<SystemUserRoleTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserRoleTb::getRoleId, roleIds);
return systemUserRoleMapper.selectCount(wrapper);
}
/**
* 构建用户查询条件
*
* @param args 查询条件
* @return /
*/
private LambdaQueryWrapper<SystemUserTb> buildUserQueryWrapper(SystemQueryUserArgs args) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) {
if (args.getId() != null) {
wrapper.eq(SystemUserTb::getId, args.getId());
}
if (args.getEnabled() != null) {
wrapper.eq(SystemUserTb::getEnabled, args.getEnabled());
}
if (CollUtil.isNotEmpty(args.getDeptIds())) {
wrapper.in(SystemUserTb::getDeptId, args.getDeptIds());
}
if (StrUtil.isNotBlank(args.getBlurry())) {
wrapper.and(w -> w.like(SystemUserTb::getUsername, args.getBlurry())
.or().like(SystemUserTb::getNickName, args.getBlurry())
.or().like(SystemUserTb::getEmail, args.getBlurry()));
}
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemUserTb::getCreateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1));
}
}
wrapper.orderByDesc(SystemUserTb::getCreateTime);
return wrapper;
}
/**
* 转换为SystemUserVo并关联查询部门、角色、岗位信息
*
* @param user 用户基本信息
* @return 包含关联信息的SystemUserVo
*/
private SystemUserVo convertToUserVo(SystemUserTb user) {
if (user == null) {
return null;
}
SystemUserVo userVo = BeanUtil.copyProperties(user, SystemUserVo.class);
// 查询关联的部门信息
if (user.getDeptId() != null) {
SystemDeptTb dept = systemDeptMapper.selectById(user.getDeptId());
userVo.setDept(dept);
}
// 查询关联的岗位信息
LambdaQueryWrapper<SystemUserJobTb> jobWrapper = new LambdaQueryWrapper<>();
jobWrapper.eq(SystemUserJobTb::getUserId, user.getId());
List<SystemUserJobTb> userJobs = systemUserJobMapper.selectList(jobWrapper);
if (CollUtil.isNotEmpty(userJobs)) {
Set<Long> jobIds = userJobs.stream().map(SystemUserJobTb::getJobId).collect(Collectors.toSet());
List<SystemJobTb> jobs = systemJobMapper.selectByIds(jobIds);
userVo.setJobs(new LinkedHashSet<>(jobs));
}
// 查询关联的角色信息
LambdaQueryWrapper<SystemUserRoleTb> roleWrapper = new LambdaQueryWrapper<>();
roleWrapper.eq(SystemUserRoleTb::getUserId, user.getId());
List<SystemUserRoleTb> userRoles = systemUserRoleMapper.selectList(roleWrapper);
if (CollUtil.isNotEmpty(userRoles)) {
Set<Long> roleIds = userRoles.stream().map(SystemUserRoleTb::getRoleId).collect(Collectors.toSet());
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds);
userVo.setRoles(new LinkedHashSet<>(roles));
}
return userVo;
}
public SystemUserTb getUserByUsername(String username) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemUserTb::getUsername, username);
wrapper.eq(SystemUserTb::getEnabled, 1);
return systemUserMapper.selectOne(wrapper);
}
public SystemUserVo getUserVoByUsername(String username) {
return this.convertToUserVo(this.getUserByUsername(username));
}
public SystemUserTb getUserByEmail(String email) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemUserTb::getEmail, email);
wrapper.eq(SystemUserTb::getEnabled, 1);
return systemUserMapper.selectOne(wrapper);
}
public SystemUserTb getUserByPhone(String phone) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemUserTb::getPhone, phone);
wrapper.eq(SystemUserTb::getEnabled, 1);
return systemUserMapper.selectOne(wrapper);
}
public KitPageResult<SystemUserVo> aggregationSearchUserByArgs(Page<SystemUserTb> page, SystemQueryUserArgs args, String currentUsername) {
if (!ObjectUtils.isEmpty(args.getDeptId())) {
args.getDeptIds().add(args.getDeptId());
// 先查找是否存在子节点
List<SystemDeptTb> data = systemDeptService.listDeptByPid(args.getDeptId());
// 然后把子节点的ID都加入到集合中
args.getDeptIds().addAll(systemDeptService.queryChildDeptIdByDeptIds(data));
}
// 数据权限
List<Long> dataScopes = systemDataService.queryDeptIdByArgs(
this.getUserByUsername(currentUsername));
// args.getDeptIds() 不为空并且数据权限不为空则取交集
if (!CollectionUtils.isEmpty(args.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)) {
// 取交集
args.getDeptIds().retainAll(dataScopes);
if (!CollectionUtil.isEmpty(args.getDeptIds())) {
return this.searchUserByArgs(args, page);
}
} else {
// 否则取并集
args.getDeptIds().addAll(dataScopes);
return this.searchUserByArgs(args, page);
}
return KitPageUtil.emptyData();
}
} }
@@ -36,13 +36,13 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -60,117 +60,121 @@ import org.springframework.web.multipart.MultipartFile;
public class SystemOssStorageServiceImpl extends ServiceImpl<SystemOssStorageMapper, SystemOssStorageTb> public class SystemOssStorageServiceImpl extends ServiceImpl<SystemOssStorageMapper, SystemOssStorageTb>
implements SystemOssStorageService { implements SystemOssStorageService {
@Autowired private MinioRepository minioRepository; @Autowired
@Autowired private AppProperties properties; private MinioRepository minioRepository;
@Autowired private KitFileLocalUploadHelper fileLocalUploadHelper; @Autowired
@Autowired private SystemOssStorageMapper systemOssStorageMapper; private AppProperties properties;
@Autowired
private KitFileLocalUploadHelper fileLocalUploadHelper;
@Autowired
private SystemOssStorageMapper systemOssStorageMapper;
@Override @Override
public KitPageResult<SystemOssStorageVo> searchOssStorage(SystemQueryStorageArgs args, public KitPageResult<SystemOssStorageVo> searchOssStorage(SystemQueryStorageArgs args,
Page<SystemOssStorageTb> page) { Page<SystemOssStorageTb> page) {
IPage<SystemOssStorageTb> ossStorageTbs = this.selectOssStorageByArgs(args, page); IPage<SystemOssStorageTb> ossStorageTbs = this.selectOssStorageByArgs(args, page);
IPage<SystemOssStorageVo> convert = ossStorageTbs.convert(c -> { IPage<SystemOssStorageVo> convert = ossStorageTbs.convert(c -> {
SystemOssStorageVo storageVo = BeanUtil.copyProperties(c, SystemOssStorageVo.class); SystemOssStorageVo storageVo = BeanUtil.copyProperties(c, SystemOssStorageVo.class);
storageVo.setFileSizeDesc(KitFileUtil.getSize(storageVo.getFileSize())); storageVo.setFileSizeDesc(KitFileUtil.getSize(storageVo.getFileSize()));
return storageVo; return storageVo;
}); });
return KitPageUtil.toPage(convert); return KitPageUtil.toPage(convert);
} }
private IPage<SystemOssStorageTb> selectOssStorageByArgs(SystemQueryStorageArgs args, private IPage<SystemOssStorageTb> selectOssStorageByArgs(SystemQueryStorageArgs args,
Page<SystemOssStorageTb> page) { Page<SystemOssStorageTb> page) {
LambdaQueryWrapper<SystemOssStorageTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemOssStorageTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) { if (args != null) {
wrapper.and(StrUtil.isNotBlank(args.getBlurry()), wrapper.and(StrUtil.isNotBlank(args.getBlurry()),
c -> c.like(SystemOssStorageTb::getFileName, args.getBlurry()).or() c -> c.like(SystemOssStorageTb::getFileName, args.getBlurry()).or()
.like(SystemOssStorageTb::getFilePrefix, args.getBlurry()).or() .like(SystemOssStorageTb::getFilePrefix, args.getBlurry()).or()
.like(SystemOssStorageTb::getFileMime, args.getBlurry()).or() .like(SystemOssStorageTb::getFileMime, args.getBlurry()).or()
.like(SystemOssStorageTb::getFileMd5, args.getBlurry())); .like(SystemOssStorageTb::getFileMd5, args.getBlurry()));
if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) { if (CollUtil.isNotEmpty(args.getCreateTime()) && args.getCreateTime().size() >= 2) {
wrapper.between(SystemOssStorageTb::getUpdateTime, args.getCreateTime().get(0), wrapper.between(SystemOssStorageTb::getUpdateTime, args.getCreateTime().get(0),
args.getCreateTime().get(1)); args.getCreateTime().get(1));
} }
}
wrapper.orderByAsc(SystemOssStorageTb::getId);
return systemOssStorageMapper.selectPage(page, wrapper);
} }
wrapper.orderByAsc(SystemOssStorageTb::getId);
return systemOssStorageMapper.selectPage(page, wrapper);
}
@Override @Override
public List<SystemOssStorageVo> queryOssStorage(SystemQueryStorageArgs args) { public List<SystemOssStorageVo> queryOssStorage(SystemQueryStorageArgs args) {
// 防止刷数据 // 防止刷数据
Page<SystemOssStorageTb> page = new Page<>(1, 500); Page<SystemOssStorageTb> page = new Page<>(1, 500);
return searchOssStorage(args, page).getContent(); return searchOssStorage(args, page).getContent();
} }
@Override @Override
public void exportOssStorageExcel(List<SystemOssStorageVo> ossStorages, HttpServletResponse response) public void exportOssStorageExcel(List<SystemOssStorageVo> ossStorages, HttpServletResponse response)
throws IOException { throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
for (SystemOssStorageVo ossStorage : ossStorages) { for (SystemOssStorageVo ossStorage : ossStorages) {
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
map.put("服务类型", ossStorage.getServiceType()); map.put("服务类型", ossStorage.getServiceType());
map.put("服务地址", ossStorage.getEndpoint()); map.put("服务地址", ossStorage.getEndpoint());
map.put("存储桶名称", ossStorage.getBucketName()); map.put("存储桶名称", ossStorage.getBucketName());
map.put("文件名称", ossStorage.getFileName()); map.put("文件名称", ossStorage.getFileName());
map.put("文件大小", ossStorage.getFileSizeDesc()); map.put("文件大小", ossStorage.getFileSizeDesc());
map.put("文件类型", ossStorage.getFileMime()); map.put("文件类型", ossStorage.getFileMime());
map.put("创建人", ossStorage.getCreateBy()); map.put("创建人", ossStorage.getCreateBy());
map.put("创建日期", ossStorage.getCreateTime()); map.put("创建日期", ossStorage.getCreateTime());
list.add(map); list.add(map);
}
KitFileUtil.downloadExcel(list, response);
} }
KitFileUtil.downloadExcel(list, response);
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public String uploadFile(MultipartFile file) { public String uploadFile(MultipartFile file) {
String originalFilename = file.getOriginalFilename(); String originalFilename = file.getOriginalFilename();
if (StrUtil.isBlank(originalFilename)) { if (StrUtil.isBlank(originalFilename)) {
throw new BadRequestException("文件名不能为空"); throw new BadRequestException("文件名不能为空");
}
StorageOSSModel ossConfig = properties.getOss();
long fileSize = file.getSize();
String contentType = file.getContentType();
KitFileUtil.checkSize(ossConfig.getMaxSize(), fileSize);
// 按天分组
String nowDateStr = KitDateUtil.getNowDateStr();
// 上传到本地临时目录
File tempFile = KitFileUtil.upload(file, fileLocalUploadHelper.getPath() + nowDateStr + File.separator);
if (tempFile == null) {
throw new BadRequestException("上传失败");
}
// 校验文件md5, 看是否已存在云端(不确定, 可能云端已经删除, 但是正常来说云端是不允许私自删除的, 所以这里忽略云端不存在的情况)
String md5 = KitFileUtil.getMd5(tempFile);
SystemOssStorageTb systemOssStorageTb = this.getOssStorageByMd5(md5);
if (systemOssStorageTb != null) {
// 重新生成7天链接
return minioRepository.generatePreviewUrl(systemOssStorageTb.getObjectName());
}
// 上传到OSS
SystemOssStorageTb storageTb = minioRepository.upload(tempFile, originalFilename, fileSize, contentType, md5);
if (storageTb == null) {
throw new BadRequestException("文件上传失败");
}
save(storageTb);
return minioRepository.generatePreviewUrl(storageTb.getObjectName());
} }
StorageOSSModel ossConfig = properties.getOss();
long fileSize = file.getSize();
String contentType = file.getContentType();
KitFileUtil.checkSize(ossConfig.getMaxSize(), fileSize);
// 按天分组
String nowDateStr = KitDateUtil.getNowDateStr();
// 上传到本地临时目录
File tempFile = KitFileUtil.upload(file, fileLocalUploadHelper.getPath() + nowDateStr + File.separator);
if (tempFile == null) {
throw new BadRequestException("上传失败");
}
// 校验文件md5, 看是否已存在云端(不确定, 可能云端已经删除, 但是正常来说云端是不允许私自删除的, 所以这里忽略云端不存在的情况)
String md5 = KitFileUtil.getMd5(tempFile);
SystemOssStorageTb systemOssStorageTb = this.getOssStorageByMd5(md5);
if (systemOssStorageTb != null) {
// 重新生成7天链接
return minioRepository.generatePreviewUrl(systemOssStorageTb.getObjectName());
}
// 上传到OSS
SystemOssStorageTb storageTb = minioRepository.upload(tempFile, originalFilename, fileSize, contentType, md5);
if (storageTb == null) {
throw new BadRequestException("文件上传失败");
}
save(storageTb);
return minioRepository.generatePreviewUrl(storageTb.getObjectName());
}
/** /**
* 多选删除 * 多选删除
* *
* @param ids / * @param ids /
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteFileByIds(Long[] ids) { public void deleteFileByIds(Long[] ids) {
for (Long id : ids) { for (Long id : ids) {
SystemOssStorageTb storage = getById(id); SystemOssStorageTb storage = getById(id);
minioRepository.removeBucketFile(storage.getObjectName()); minioRepository.removeBucketFile(storage.getObjectName());
removeById(storage); removeById(storage);
}
} }
}
private SystemOssStorageTb getOssStorageByMd5(String md5) { private SystemOssStorageTb getOssStorageByMd5(String md5) {
return lambdaQuery().eq(SystemOssStorageTb::getFileMd5, md5).one(); return lambdaQuery().eq(SystemOssStorageTb::getFileMd5, md5).one();
} }
} }
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.odboy.system.dal.mysql.SystemDictDetailMapper"> <mapper namespace="cn.odboy.system.dal.mysql.SystemDictDetailMapper">
<select id="selectPageByArgs" resultType="cn.odboy.system.dal.dataobject.SystemDictDetailTb"> <select id="selectPageByArgs" resultType="cn.odboy.system.dal.dataobject.SystemDictDetailTb">
SELECT SELECT
t1.* t1.*
FROM system_dict_detail t1 LEFT JOIN system_dict t2 ON t1.dict_id = t2.id FROM system_dict_detail t1 LEFT JOIN system_dict t2 ON t1.dict_id = t2.id
<where> <where>
<if test="args.dictName != null and args.dictName != ''"> <if test="args.dictName != null and args.dictName != ''">
AND t2.name = #{args.dictName} AND t2.name = #{args.dictName}
</if> </if>
<if test="args.label != null and args.label != ''"> <if test="args.label != null and args.label != ''">
AND t1.label = #{args.label} AND t1.label = #{args.label}
</if> </if>
</where> </where>
ORDER BY t1.dict_sort ORDER BY t1.dict_sort
</select> </select>
</mapper> </mapper>
@@ -15,38 +15,17 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.odboy.annotation.AnonymousPostMapping; import cn.odboy.annotation.AnonymousPostMapping;
import cn.odboy.constant.CaptchaCodeEnum;
import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.model.SystemUserInfoVo; import cn.odboy.system.dal.model.SystemUserInfoVo;
import cn.odboy.system.dal.model.SystemUserJwtVo;
import cn.odboy.system.dal.model.SystemUserLoginArgs; import cn.odboy.system.dal.model.SystemUserLoginArgs;
import cn.odboy.system.dal.redis.SystemCacheKey; import cn.odboy.system.service.SystemAuthService;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.framework.permission.core.handler.TokenProvider;
import cn.odboy.system.framework.permission.core.handler.UserDetailsHandler;
import cn.odboy.util.KitRsaEncryptUtil;
import com.wf.captcha.base.Captcha;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@@ -63,97 +42,34 @@ import org.springframework.web.bind.annotation.RestController;
public class SystemAuthController { public class SystemAuthController {
@Autowired @Autowired
private KitRedisHelper redisHelper; private SystemAuthService systemAuthService;
@Autowired
private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
@Autowired
private TokenProvider tokenProvider;
@Autowired
private AppProperties properties;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsHandler userDetailsService;
@ApiOperation("登录授权") @ApiOperation("登录授权")
@AnonymousPostMapping(value = "/login") @AnonymousPostMapping(value = "/login")
public ResponseEntity<Map<String, Object>> login(@Validated @RequestBody SystemUserLoginArgs loginRequest, public ResponseEntity<Map<String, Object>> login(@Validated @RequestBody SystemUserLoginArgs loginRequest,
HttpServletRequest request) throws Exception { HttpServletRequest request) throws Exception {
// 密码解密 Map<String, Object> loginInfo = systemAuthService.doLogin(loginRequest, request);
String password = return ResponseEntity.ok(loginInfo);
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginRequest.getPassword());
// 查询验证码
String code = redisHelper.get(loginRequest.getUuid(), String.class);
// 清除验证码
redisHelper.del(loginRequest.getUuid());
if (StrUtil.isBlank(code)) {
throw new BadRequestException("验证码不存在或已过期");
}
if (StrUtil.isBlank(loginRequest.getCode()) || !loginRequest.getCode().equalsIgnoreCase(code)) {
throw new BadRequestException("验证码错误");
}
// 获取用户信息
SystemUserJwtVo jwtUser = userDetailsService.loadUserByUsername(loginRequest.getUsername());
// 验证用户密码
if (!passwordEncoder.matches(password, jwtUser.getPassword())) {
throw new BadRequestException("登录密码错误");
}
Authentication authentication =
new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成令牌
String token = tokenProvider.createToken(jwtUser);
// 返回 token 与 用户信息
Map<String, Object> authInfo = new HashMap<>(2) {{
put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token));
put("user", BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class));
}};
if (properties.getLogin().isSingle()) {
// 踢掉之前已经登录的token
systemUserOnlineInfoDAO.kickOutByUsername(loginRequest.getUsername());
}
// 保存在线信息
systemUserOnlineInfoDAO.saveUserJwtModelByToken(jwtUser, token, request);
// 返回登录信息
return ResponseEntity.ok(authInfo);
} }
@ApiOperation("获取用户信息") @ApiOperation("获取用户信息")
@PostMapping(value = "/info") @PostMapping(value = "/info")
public ResponseEntity<SystemUserInfoVo> getUserInfo() { public ResponseEntity<SystemUserInfoVo> getUserInfo() {
SystemUserJwtVo jwtUser = (SystemUserJwtVo) KitSecurityHelper.getCurrentUser(); SystemUserInfoVo userInfoVo = systemAuthService.getCurrentUserInfoVo();
SystemUserInfoVo userInfoVo = BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class);
return ResponseEntity.ok(userInfoVo); return ResponseEntity.ok(userInfoVo);
} }
@ApiOperation("获取验证码") @ApiOperation("获取验证码")
@AnonymousPostMapping(value = "/captcha/getImage") @AnonymousPostMapping(value = "/captcha/getImage")
public ResponseEntity<Map<String, Object>> getCode() { public ResponseEntity<Map<String, Object>> getCode() {
// 获取运算的结果 Map<String, Object> imgResult = systemAuthService.getCaptchaInfo();
Captcha captcha = properties.getLogin().getCaptchaSetting().getCaptcha();
String uuid = SystemCacheKey.CAPTCHA_LOGIN + IdUtil.simpleUUID();
//当验证码类型为 arithmetic时且长度 >= 2 时, captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text();
if (captcha.getCharType() - 1 == CaptchaCodeEnum.ARITHMETIC.ordinal() &&
captchaValue.contains(SystemConst.SYMBOL_DOT)) {
captchaValue = captchaValue.split("\\.")[0];
}
// 保存
redisHelper.set(uuid, captchaValue, properties.getLogin().getCaptchaSetting().getExpiration(),
TimeUnit.MINUTES);
// 验证码信息
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
put("img", captcha.toBase64());
put("uuid", uuid);
}};
return ResponseEntity.ok(imgResult); return ResponseEntity.ok(imgResult);
} }
@ApiOperation("退出登录") @ApiOperation("退出登录")
@AnonymousPostMapping(value = "/logout") @AnonymousPostMapping(value = "/logout")
public ResponseEntity<Void> logout(HttpServletRequest request) { public ResponseEntity<Void> logout(HttpServletRequest request) {
String token = tokenProvider.getToken(request); systemAuthService.doLogout(request);
systemUserOnlineInfoDAO.logoutByToken(token);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -15,7 +15,6 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.constant.SystemCaptchaBizEnum; import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.model.SystemCheckEmailCaptchaArgs; import cn.odboy.system.dal.model.SystemCheckEmailCaptchaArgs;
import cn.odboy.system.service.SystemEmailService; import cn.odboy.system.service.SystemEmailService;
@@ -55,11 +54,7 @@ public class SystemCaptchaController {
@ApiOperation("验证码验证") @ApiOperation("验证码验证")
@PostMapping(value = "/checkEmailCaptcha") @PostMapping(value = "/checkEmailCaptcha")
public ResponseEntity<Void> checkEmailCaptcha(@Validated @RequestBody SystemCheckEmailCaptchaArgs args) { public ResponseEntity<Void> checkEmailCaptcha(@Validated @RequestBody SystemCheckEmailCaptchaArgs args) {
SystemCaptchaBizEnum biEnum = SystemCaptchaBizEnum.getByBizCode(args.getBizCode()); systemEmailService.checkEmailCaptcha(args);
if (biEnum == null) {
throw new BadRequestException("不支持的业务");
}
systemEmailService.checkEmailCaptcha(biEnum, args.getEmail(), args.getCode());
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -58,8 +58,7 @@ public class SystemDeptController {
@PreAuthorize("@el.check('user:list','dept:list')") @PreAuthorize("@el.check('user:list','dept:list')")
public ResponseEntity<KitPageResult<SystemDeptTb>> queryDept( public ResponseEntity<KitPageResult<SystemDeptTb>> queryDept(
@Validated @RequestBody KitPageArgs<SystemQueryDeptArgs> pageArgs) throws Exception { @Validated @RequestBody KitPageArgs<SystemQueryDeptArgs> pageArgs) throws Exception {
SystemQueryDeptArgs args = pageArgs.getArgs(); List<SystemDeptTb> depts = systemDeptService.queryAllDeptByArgs(pageArgs.getArgs(), true);
List<SystemDeptTb> depts = systemDeptService.queryAllDeptByArgs(args, true);
return ResponseEntity.ok(KitPageUtil.toPage(depts)); return ResponseEntity.ok(KitPageUtil.toPage(depts));
} }
@@ -91,11 +90,7 @@ public class SystemDeptController {
@PostMapping(value = "/removeDeptByIds") @PostMapping(value = "/removeDeptByIds")
@PreAuthorize("@el.check('dept:del')") @PreAuthorize("@el.check('dept:del')")
public ResponseEntity<Void> removeDeptByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeDeptByIds(@RequestBody Set<Long> ids) {
// 获取部门, 和其所有子部门 systemDeptService.deleteDeptByIds(ids);
Set<SystemDeptTb> depts = systemDeptService.traverseDeptByIdWithPids(ids);
// 验证是否被角色或用户关联
systemDeptService.verifyBindRelationByIds(depts);
systemDeptService.deleteDeptByIds(depts);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -66,8 +66,7 @@ public class SystemDictController {
public ResponseEntity<KitPageResult<SystemDictTb>> queryDictByArgs( public ResponseEntity<KitPageResult<SystemDictTb>> queryDictByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryDictArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryDictArgs> pageArgs) {
Page<SystemDictTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize()); Page<SystemDictTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
SystemQueryDictArgs args = pageArgs.getArgs(); return ResponseEntity.ok(systemDictService.searchDict(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemDictService.searchDict(args, page));
} }
@ApiOperation("新增字典") @ApiOperation("新增字典")
@@ -25,7 +25,6 @@ import cn.odboy.system.service.SystemDictDetailService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -58,19 +57,14 @@ public class SystemDictDetailController {
@PostMapping(value = "/queryDictDetailByArgs") @PostMapping(value = "/queryDictDetailByArgs")
public ResponseEntity<KitPageResult<SystemDictDetailVo>> queryDictDetailByArgs( public ResponseEntity<KitPageResult<SystemDictDetailVo>> queryDictDetailByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryDictDetailArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryDictDetailArgs> pageArgs) {
SystemQueryDictDetailArgs args = pageArgs.getArgs();
Page<SystemDictDetailTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize()); Page<SystemDictDetailTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
return ResponseEntity.ok(systemDictDetailService.searchDictDetail(args, page)); return ResponseEntity.ok(systemDictDetailService.searchDictDetail(pageArgs.getArgs(), page));
} }
@ApiOperation("查询多个字典详情") @ApiOperation("查询多个字典详情")
@GetMapping(value = "/getDictDetailMaps") @GetMapping(value = "/getDictDetailMaps")
public ResponseEntity<Map<String, List<SystemDictDetailVo>>> getDictDetailMaps(@RequestParam String dictName) { public ResponseEntity<Map<String, List<SystemDictDetailVo>>> getDictDetailMaps(@RequestParam String dictName) {
String[] names = dictName.split("[,, ]"); Map<String, List<SystemDictDetailVo>> dictMap = systemDictDetailService.getDictDetailMap(dictName);
Map<String, List<SystemDictDetailVo>> dictMap = new HashMap<>(16);
for (String name : names) {
dictMap.put(name, systemDictDetailService.listDictDetailByName(name));
}
return ResponseEntity.ok(dictMap); return ResponseEntity.ok(dictMap);
} }
@@ -57,9 +57,8 @@ public class SystemJobController {
@PreAuthorize("@el.check('job:list','user:list')") @PreAuthorize("@el.check('job:list','user:list')")
public ResponseEntity<KitPageResult<SystemJobTb>> queryJobByArgs( public ResponseEntity<KitPageResult<SystemJobTb>> queryJobByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryJobArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryJobArgs> pageArgs) {
SystemQueryJobArgs args = pageArgs.getArgs(); Page<SystemJobTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemJobTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemJobService.searchJobByArgs(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemJobService.searchJobByArgs(args, page));
} }
@ApiOperation("查询岗位") @ApiOperation("查询岗位")
@@ -90,8 +89,6 @@ public class SystemJobController {
@PostMapping(value = "/removeJobByIds") @PostMapping(value = "/removeJobByIds")
@PreAuthorize("@el.check('job:del')") @PreAuthorize("@el.check('job:del')")
public ResponseEntity<Void> removeJobByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeJobByIds(@RequestBody Set<Long> ids) {
// 验证是否被用户关联
systemJobService.verifyBindRelationByIds(ids);
systemJobService.deleteJobByIds(ids); systemJobService.deleteJobByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -17,12 +17,9 @@ package cn.odboy.system.controller;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.constant.FileTypeEnum;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemLocalStorageTb; import cn.odboy.system.dal.dataobject.SystemLocalStorageTb;
import cn.odboy.system.dal.model.SystemQueryStorageArgs; import cn.odboy.system.dal.model.SystemQueryStorageArgs;
import cn.odboy.system.service.SystemLocalStorageService; import cn.odboy.system.service.SystemLocalStorageService;
import cn.odboy.util.KitFileUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
@@ -53,9 +50,8 @@ public class SystemLocalStorageController {
@PreAuthorize("@el.check('storage:list')") @PreAuthorize("@el.check('storage:list')")
public ResponseEntity<KitPageResult<SystemLocalStorageTb>> queryLocalStorage( public ResponseEntity<KitPageResult<SystemLocalStorageTb>> queryLocalStorage(
@Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) {
SystemQueryStorageArgs args = pageArgs.getArgs(); Page<SystemLocalStorageTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemLocalStorageTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(localStorageService.searchLocalStorage(pageArgs.getArgs(), page));
return ResponseEntity.ok(localStorageService.searchLocalStorage(args, page));
} }
@ApiOperation("导出数据") @ApiOperation("导出数据")
@@ -76,12 +72,7 @@ public class SystemLocalStorageController {
@ApiOperation("上传图片") @ApiOperation("上传图片")
@PostMapping("/uploadPicture") @PostMapping("/uploadPicture")
public ResponseEntity<SystemLocalStorageTb> uploadPicture(@RequestParam MultipartFile file) { public ResponseEntity<SystemLocalStorageTb> uploadPicture(@RequestParam MultipartFile file) {
// 判断文件是否为图片 SystemLocalStorageTb localStorage = localStorageService.uploadPictureV1(file);
String suffix = KitFileUtil.getSuffix(file.getOriginalFilename());
if (!FileTypeEnum.IMAGE.getCode().equals(KitFileUtil.getFileType(suffix))) {
throw new BadRequestException("只能上传图片");
}
SystemLocalStorageTb localStorage = localStorageService.uploadFile(null, file);
return ResponseEntity.ok(localStorage); return ResponseEntity.ok(localStorage);
} }
@@ -15,7 +15,6 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
@@ -23,17 +22,12 @@ import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.model.SystemMenuVo; import cn.odboy.system.dal.model.SystemMenuVo;
import cn.odboy.system.dal.model.SystemQueryMenuArgs; import cn.odboy.system.dal.model.SystemQueryMenuArgs;
import cn.odboy.system.dal.mysql.SystemMenuMapper; import cn.odboy.system.dal.mysql.SystemMenuMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.service.SystemMenuService; import cn.odboy.system.service.SystemMenuService;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -66,27 +60,23 @@ public class SystemMenuController {
@PostMapping(value = "/buildMenus") @PostMapping(value = "/buildMenus")
@ApiOperation("获取前端所需菜单") @ApiOperation("获取前端所需菜单")
public ResponseEntity<List<SystemMenuVo>> buildMenus() { public ResponseEntity<List<SystemMenuVo>> buildMenus() {
List<SystemMenuTb> menuList = systemMenuService.listMenuByUserId(KitSecurityHelper.getCurrentUserId()); List<SystemMenuVo> systemMenuVos = systemMenuService.buildFrontMenus();
List<SystemMenuTb> menus = systemMenuService.buildMenuTree(menuList); return ResponseEntity.ok(systemMenuVos);
return ResponseEntity.ok(systemMenuService.buildMenuVo(menus));
} }
@ApiOperation("返回全部的菜单") @ApiOperation("返回全部的菜单")
@PostMapping(value = "/queryMenuListByPid") @PostMapping(value = "/queryMenuListByPid")
@PreAuthorize("@el.check('menu:list','roles:list')") @PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity<List<SystemMenuTb>> queryMenuListByPid(@RequestParam Long pid) { public ResponseEntity<List<SystemMenuTb>> queryMenuListByPid(@RequestParam Long pid) {
return ResponseEntity.ok(systemMenuService.listMenuByPid(pid)); List<SystemMenuTb> systemMenuTbs = systemMenuService.listMenuByPid(pid);
return ResponseEntity.ok(systemMenuTbs);
} }
@ApiOperation("根据菜单ID返回所有子节点ID, 包含自身ID") @ApiOperation("根据菜单ID返回所有子节点ID, 包含自身ID")
@PostMapping(value = "/queryChildMenuSet") @PostMapping(value = "/queryChildMenuSet")
@PreAuthorize("@el.check('menu:list','roles:list')") @PreAuthorize("@el.check('menu:list','roles:list')")
public ResponseEntity<Set<Long>> queryChildMenuSet(@RequestParam Long id) { public ResponseEntity<Set<Long>> queryChildMenuSet(@RequestParam Long id) {
Set<SystemMenuTb> menuSet = new HashSet<>(); Set<Long> ids = systemMenuService.listChildMenuSetByMenuId(id);
List<SystemMenuTb> menuList = systemMenuService.listMenuByPid(id);
menuSet.add(systemMenuMapper.selectById(id));
menuSet = systemMenuService.queryChildMenuByArgs(menuList, menuSet);
Set<Long> ids = menuSet.stream().map(SystemMenuTb::getId).collect(Collectors.toSet());
return ResponseEntity.ok(ids); return ResponseEntity.ok(ids);
} }
@@ -103,8 +93,7 @@ public class SystemMenuController {
@PreAuthorize("@el.check('menu:list')") @PreAuthorize("@el.check('menu:list')")
public ResponseEntity<KitPageResult<SystemMenuTb>> queryAllMenu( public ResponseEntity<KitPageResult<SystemMenuTb>> queryAllMenu(
@Validated @RequestBody KitPageArgs<SystemQueryMenuArgs> pageArgs) throws Exception { @Validated @RequestBody KitPageArgs<SystemQueryMenuArgs> pageArgs) throws Exception {
SystemQueryMenuArgs args = pageArgs.getArgs(); List<SystemMenuTb> menuList = systemMenuService.queryAllMenu(pageArgs.getArgs(), true);
List<SystemMenuTb> menuList = systemMenuService.queryAllMenu(args, true);
return ResponseEntity.ok(KitPageUtil.toPage(menuList)); return ResponseEntity.ok(KitPageUtil.toPage(menuList));
} }
@@ -112,23 +101,8 @@ public class SystemMenuController {
@PostMapping("/queryMenuSuperior") @PostMapping("/queryMenuSuperior")
@PreAuthorize("@el.check('menu:list')") @PreAuthorize("@el.check('menu:list')")
public ResponseEntity<List<SystemMenuTb>> queryMenuSuperior(@RequestBody List<Long> ids) { public ResponseEntity<List<SystemMenuTb>> queryMenuSuperior(@RequestBody List<Long> ids) {
Set<SystemMenuTb> menus; List<SystemMenuTb> systemMenuTbs = systemMenuService.listMenuSuperior(ids);
if (CollectionUtil.isNotEmpty(ids)) { return ResponseEntity.ok(systemMenuTbs);
menus = new LinkedHashSet<>(systemMenuService.listMenuByIds(ids));
for (SystemMenuTb menu : menus) {
List<SystemMenuTb> menuList = systemMenuService.querySuperiorMenuByArgs(menu, new ArrayList<>());
for (SystemMenuTb data : menuList) {
if (data.getId().equals(menu.getPid())) {
data.setSubCount(data.getSubCount() - 1);
}
}
menus.addAll(menuList);
}
// 编辑菜单时不显示自己以及自己下级的数据, 避免出现PID数据环形问题
menus = menus.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toSet());
return ResponseEntity.ok(systemMenuService.buildMenuTree(new ArrayList<>(menus)));
}
return ResponseEntity.ok(systemMenuService.listMenuByPid(null));
} }
@ApiOperation("新增菜单") @ApiOperation("新增菜单")
@@ -19,12 +19,12 @@ import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.system.dal.model.SystemUserOnlineVo; import cn.odboy.system.dal.model.SystemUserOnlineVo;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO; import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.util.KitDesEncryptUtil;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -49,28 +49,24 @@ public class SystemOnlineController {
@PostMapping @PostMapping
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public ResponseEntity<KitPageResult<SystemUserOnlineVo>> queryOnlineUser( public ResponseEntity<KitPageResult<SystemUserOnlineVo>> queryOnlineUser(
@Validated @RequestBody KitPageArgs<SystemUserOnlineVo> args) { @Validated @RequestBody KitPageArgs<SystemUserOnlineVo> pageArgs) {
IPage<SystemUserOnlineVo> page = new Page<>(args.getPage(), args.getSize()); IPage<SystemUserOnlineVo> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
return ResponseEntity.ok(systemUserOnlineInfoDAO.queryUserOnlineModelPage(args.getArgs(), page)); return ResponseEntity.ok(systemUserOnlineInfoDAO.queryUserOnlineModelPage(pageArgs.getArgs(), page));
} }
@ApiOperation("导出数据") @ApiOperation("导出数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public void exportOnlineUser(HttpServletResponse response, String username) throws IOException { public void exportOnlineUser(HttpServletResponse response, String username) throws IOException {
systemUserOnlineInfoDAO.downloadUserOnlineModelExcel( List<SystemUserOnlineVo> userOnlineVos = systemUserOnlineInfoDAO.queryUserOnlineModelListByUsername(username);
systemUserOnlineInfoDAO.queryUserOnlineModelListByUsername(username), response); systemUserOnlineInfoDAO.downloadUserOnlineModelExcel(userOnlineVos, response);
} }
@ApiOperation("踢出用户") @ApiOperation("踢出用户")
@PostMapping(value = "/kickOutUser") @PostMapping(value = "/kickOutUser")
@PreAuthorize("@el.check()") @PreAuthorize("@el.check()")
public ResponseEntity<Void> kickOutUser(@RequestBody Set<String> keys) throws Exception { public ResponseEntity<Void> kickOutUser(@RequestBody Set<String> keys) throws Exception {
for (String token : keys) { systemUserOnlineInfoDAO.kickOutUser(keys);
// 解密Key
token = KitDesEncryptUtil.desDecrypt(token);
systemUserOnlineInfoDAO.logoutByToken(token);
}
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
} }
@@ -53,9 +53,8 @@ public class SystemOssStorageController {
@PreAuthorize("@el.check('storage:list')") @PreAuthorize("@el.check('storage:list')")
public ResponseEntity<KitPageResult<SystemOssStorageVo>> queryOssStorage( public ResponseEntity<KitPageResult<SystemOssStorageVo>> queryOssStorage(
@Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryStorageArgs> pageArgs) {
SystemQueryStorageArgs args = pageArgs.getArgs(); Page<SystemOssStorageTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemOssStorageTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemOssStorageService.searchOssStorage(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemOssStorageService.searchOssStorage(args, page));
} }
@ApiOperation("导出数据") @ApiOperation("导出数据")
@@ -17,8 +17,6 @@ package cn.odboy.system.controller;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.context.KitSpringBeanHolder;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
import cn.odboy.system.dal.dataobject.SystemQuartzLogTb; import cn.odboy.system.dal.dataobject.SystemQuartzLogTb;
import cn.odboy.system.dal.model.SystemQueryQuartzJobArgs; import cn.odboy.system.dal.model.SystemQueryQuartzJobArgs;
@@ -57,9 +55,8 @@ public class SystemQuartzJobController {
@PreAuthorize("@el.check('quartzJob:list')") @PreAuthorize("@el.check('quartzJob:list')")
public ResponseEntity<KitPageResult<SystemQuartzJobTb>> queryQuartzJobByCrud( public ResponseEntity<KitPageResult<SystemQuartzJobTb>> queryQuartzJobByCrud(
@Validated @RequestBody KitPageArgs<SystemQueryQuartzJobArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryQuartzJobArgs> pageArgs) {
SystemQueryQuartzJobArgs args = pageArgs.getArgs(); Page<SystemQuartzJobTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<SystemQuartzJobTb> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemQuartzJobService.searchQuartzJobByArgs(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemQuartzJobService.searchQuartzJobByArgs(args, page));
} }
@ApiOperation("导出任务数据") @ApiOperation("导出任务数据")
@@ -88,11 +85,6 @@ public class SystemQuartzJobController {
@PostMapping(value = "/createQuartzJob") @PostMapping(value = "/createQuartzJob")
@PreAuthorize("@el.check('quartzJob:add')") @PreAuthorize("@el.check('quartzJob:add')")
public ResponseEntity<Void> createQuartzJob(@Validated @RequestBody SystemQuartzJobTb args) { public ResponseEntity<Void> createQuartzJob(@Validated @RequestBody SystemQuartzJobTb args) {
if (args.getId() != null) {
throw new BadRequestException("无效参数id");
}
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName());
systemQuartzJobService.createJob(args); systemQuartzJobService.createJob(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -102,8 +94,6 @@ public class SystemQuartzJobController {
@PreAuthorize("@el.check('quartzJob:edit')") @PreAuthorize("@el.check('quartzJob:edit')")
public ResponseEntity<Void> updateQuartzJob( public ResponseEntity<Void> updateQuartzJob(
@Validated(SystemQuartzJobTb.Update.class) @RequestBody SystemUpdateQuartzJobArgs args) { @Validated(SystemQuartzJobTb.Update.class) @RequestBody SystemUpdateQuartzJobArgs args) {
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName());
systemQuartzJobService.updateQuartzJobResumeCron(args); systemQuartzJobService.updateQuartzJobResumeCron(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -131,17 +121,4 @@ public class SystemQuartzJobController {
systemQuartzJobService.deleteJobByIds(ids); systemQuartzJobService.deleteJobByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
/**
* 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
*
* @param beanName Bean名称
*/
private void checkBean(String beanName) {
// 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类
// 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数,执行任意sql命令。
if (!KitSpringBeanHolder.getAllServiceBeanName().contains(beanName)) {
throw new BadRequestException("非法的 Bean,请重新输入!");
}
}
} }
@@ -18,21 +18,17 @@ package cn.odboy.system.controller;
import cn.hutool.core.lang.Dict; import cn.hutool.core.lang.Dict;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.model.SystemCreateRoleArgs; import cn.odboy.system.dal.model.SystemCreateRoleArgs;
import cn.odboy.system.dal.model.SystemQueryRoleArgs; import cn.odboy.system.dal.model.SystemQueryRoleArgs;
import cn.odboy.system.dal.model.SystemRoleVo; import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.service.SystemRoleService; import cn.odboy.system.service.SystemRoleService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -55,7 +51,7 @@ public class SystemRoleController {
@ApiOperation("获取单个role") @ApiOperation("获取单个role")
@PostMapping(value = "/queryRoleById") @PostMapping(value = "/queryRoleById")
@PreAuthorize("@el.check('roles:list')") @PreAuthorize("@el.check('roles:list')")
public ResponseEntity<SystemRoleTb> queryRoleById(@RequestBody SystemRoleTb args) { public ResponseEntity<SystemRoleVo> queryRoleById(@RequestBody SystemRoleTb args) {
return ResponseEntity.ok(systemRoleService.getRoleById(args.getId())); return ResponseEntity.ok(systemRoleService.getRoleById(args.getId()));
} }
@@ -78,22 +74,20 @@ public class SystemRoleController {
@PreAuthorize("@el.check('roles:list')") @PreAuthorize("@el.check('roles:list')")
public ResponseEntity<KitPageResult<SystemRoleVo>> queryRoleByArgs( public ResponseEntity<KitPageResult<SystemRoleVo>> queryRoleByArgs(
@Validated @RequestBody KitPageArgs<SystemQueryRoleArgs> pageArgs) { @Validated @RequestBody KitPageArgs<SystemQueryRoleArgs> pageArgs) {
SystemQueryRoleArgs args = pageArgs.getArgs(); Page<Object> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
Page<Object> page = new Page<>(args.getPage(), args.getSize()); return ResponseEntity.ok(systemRoleService.searchRoleByArgs(pageArgs.getArgs(), page));
return ResponseEntity.ok(systemRoleService.searchRoleByArgs(args, page));
} }
@ApiOperation("获取用户级别") @ApiOperation("获取用户级别")
@PostMapping(value = "/queryRoleLevel") @PostMapping(value = "/queryRoleLevel")
public ResponseEntity<Dict> queryRoleLevel() { public ResponseEntity<Dict> queryRoleLevel() {
return ResponseEntity.ok(Dict.create().set("level", checkRoleLevels(null))); return ResponseEntity.ok(systemRoleService.getRoleLevel());
} }
@ApiOperation("新增角色") @ApiOperation("新增角色")
@PostMapping(value = "/saveRole") @PostMapping(value = "/saveRole")
@PreAuthorize("@el.check('roles:add')") @PreAuthorize("@el.check('roles:add')")
public ResponseEntity<Void> saveRole(@Validated @RequestBody SystemCreateRoleArgs args) { public ResponseEntity<Void> saveRole(@Validated @RequestBody SystemCreateRoleArgs args) {
checkRoleLevels(args.getLevel());
systemRoleService.saveRole(args); systemRoleService.saveRole(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -102,7 +96,6 @@ public class SystemRoleController {
@PostMapping(value = "/modifyRoleById") @PostMapping(value = "/modifyRoleById")
@PreAuthorize("@el.check('roles:edit')") @PreAuthorize("@el.check('roles:edit')")
public ResponseEntity<Void> modifyRoleById(@Validated(SystemRoleTb.Update.class) @RequestBody SystemRoleVo args) { public ResponseEntity<Void> modifyRoleById(@Validated(SystemRoleTb.Update.class) @RequestBody SystemRoleVo args) {
checkRoleLevels(args.getLevel());
systemRoleService.updateRoleById(args); systemRoleService.updateRoleById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -111,8 +104,6 @@ public class SystemRoleController {
@PostMapping(value = "/modifyBindMenuById") @PostMapping(value = "/modifyBindMenuById")
@PreAuthorize("@el.check('roles:edit')") @PreAuthorize("@el.check('roles:edit')")
public ResponseEntity<Void> modifyBindMenuById(@RequestBody SystemRoleVo args) { public ResponseEntity<Void> modifyBindMenuById(@RequestBody SystemRoleVo args) {
SystemRoleTb role = systemRoleService.getRoleById(args.getId());
checkRoleLevels(role.getLevel());
systemRoleService.updateBindMenuById(args); systemRoleService.updateBindMenuById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -121,30 +112,7 @@ public class SystemRoleController {
@PostMapping(value = "/removeRoleByIds") @PostMapping(value = "/removeRoleByIds")
@PreAuthorize("@el.check('roles:del')") @PreAuthorize("@el.check('roles:del')")
public ResponseEntity<Void> removeRoleByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Void> removeRoleByIds(@RequestBody Set<Long> ids) {
for (Long id : ids) {
SystemRoleTb role = systemRoleService.getRoleById(id);
checkRoleLevels(role.getLevel());
}
// 验证是否被用户关联
systemRoleService.verifyBindRelationByIds(ids);
systemRoleService.deleteRoleByIds(ids); systemRoleService.deleteRoleByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
/**
* 检查用户的角色级别
*
* @return /
*/
private int checkRoleLevels(Integer level) {
List<Integer> levels = systemRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList());
int min = Collections.min(levels);
if (level != null) {
if (level < min) {
throw new BadRequestException("权限不足, 你的角色级别:" + min + ", 低于操作的角色级别:" + level);
}
}
return min;
}
} }
@@ -15,15 +15,9 @@
*/ */
package cn.odboy.system.controller; package cn.odboy.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.base.KitSelectOptionVo; import cn.odboy.base.KitSelectOptionVo;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemQueryUserArgs; import cn.odboy.system.dal.model.SystemQueryUserArgs;
import cn.odboy.system.dal.model.SystemUpdateUserPasswordArgs; import cn.odboy.system.dal.model.SystemUpdateUserPasswordArgs;
@@ -31,26 +25,17 @@ import cn.odboy.system.dal.model.SystemUserVo;
import cn.odboy.system.framework.permission.core.KitSecurityHelper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.service.SystemDataService; import cn.odboy.system.service.SystemDataService;
import cn.odboy.system.service.SystemDeptService; import cn.odboy.system.service.SystemDeptService;
import cn.odboy.system.service.SystemEmailService;
import cn.odboy.system.service.SystemRoleService;
import cn.odboy.system.service.SystemUserService; import cn.odboy.system.service.SystemUserService;
import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitRsaEncryptUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.io.IOException; import java.io.IOException;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
@@ -66,20 +51,13 @@ import org.springframework.web.multipart.MultipartFile;
@RequestMapping("/api/user") @RequestMapping("/api/user")
public class SystemUserController { public class SystemUserController {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired @Autowired
private SystemUserService systemUserService; private SystemUserService systemUserService;
@Autowired @Autowired
private SystemDataService systemDataService; private SystemDataService systemDataService;
@Autowired @Autowired
private SystemDeptService systemDeptService; private SystemDeptService systemDeptService;
@Autowired
private SystemRoleService systemRoleService;
@Autowired
private SystemEmailService systemEmailService;
@Autowired
private AppProperties properties;
@ApiOperation("导出用户数据") @ApiOperation("导出用户数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@@ -91,42 +69,16 @@ public class SystemUserController {
@ApiOperation("查询用户") @ApiOperation("查询用户")
@PostMapping @PostMapping
@PreAuthorize("@el.check('user:list')") @PreAuthorize("@el.check('user:list')")
public ResponseEntity<KitPageResult<SystemUserVo>> queryUserByArgs( public ResponseEntity<KitPageResult<SystemUserVo>> queryUserByArgs(@Validated @RequestBody KitPageArgs<SystemQueryUserArgs> pageArgs) {
@Validated @RequestBody KitPageArgs<SystemQueryUserArgs> pageArgs) { String currentUsername = KitSecurityHelper.getCurrentUsername();
Page<SystemUserTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize()); Page<SystemUserTb> page = new Page<>(pageArgs.getPage(), pageArgs.getSize());
SystemQueryUserArgs args = pageArgs.getArgs(); return ResponseEntity.ok(systemUserService.aggregationSearchUserByArgs(page, pageArgs.getArgs(), currentUsername));
if (!ObjectUtils.isEmpty(args.getDeptId())) {
args.getDeptIds().add(args.getDeptId());
// 先查找是否存在子节点
List<SystemDeptTb> data = systemDeptService.listDeptByPid(args.getDeptId());
// 然后把子节点的ID都加入到集合中
args.getDeptIds().addAll(systemDeptService.queryChildDeptIdByDeptIds(data));
}
// 数据权限
List<Long> dataScopes = systemDataService.queryDeptIdByArgs(
systemUserService.getUserByUsername(KitSecurityHelper.getCurrentUsername()));
// args.getDeptIds() 不为空并且数据权限不为空则取交集
if (!CollectionUtils.isEmpty(args.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)) {
// 取交集
args.getDeptIds().retainAll(dataScopes);
if (!CollectionUtil.isEmpty(args.getDeptIds())) {
return ResponseEntity.ok(systemUserService.searchUserByArgs(args, page));
}
} else {
// 否则取并集
args.getDeptIds().addAll(dataScopes);
return ResponseEntity.ok(systemUserService.searchUserByArgs(args, page));
}
return ResponseEntity.ok(KitPageUtil.emptyData());
} }
@ApiOperation("新增用户") @ApiOperation("新增用户")
@PostMapping(value = "/saveUser") @PostMapping(value = "/saveUser")
@PreAuthorize("@el.check('user:add')") @PreAuthorize("@el.check('user:add')")
public ResponseEntity<Object> saveUser(@Validated @RequestBody SystemUserVo args) { public ResponseEntity<Object> saveUser(@Validated @RequestBody SystemUserVo args) {
checkLevel(args);
// 默认密码 123456
args.setPassword(passwordEncoder.encode("123456"));
systemUserService.saveUser(args); systemUserService.saveUser(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -135,18 +87,13 @@ public class SystemUserController {
@PostMapping(value = "/modifyUserById") @PostMapping(value = "/modifyUserById")
@PreAuthorize("@el.check('user:edit')") @PreAuthorize("@el.check('user:edit')")
public ResponseEntity<Object> modifyUserById(@Validated(SystemUserTb.Update.class) @RequestBody SystemUserVo args) { public ResponseEntity<Object> modifyUserById(@Validated(SystemUserTb.Update.class) @RequestBody SystemUserVo args) {
checkLevel(args);
systemUserService.updateUserById(args); systemUserService.updateUserById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改用户:个人中心") @ApiOperation("修改用户:个人中心")
@PostMapping(value = "modifyUserCenterInfoById") @PostMapping(value = "modifyUserCenterInfoById")
public ResponseEntity<Object> modifyUserCenterInfoById( public ResponseEntity<Object> modifyUserCenterInfoById(@Validated(SystemUserTb.Update.class) @RequestBody SystemUserTb args) {
@Validated(SystemUserTb.Update.class) @RequestBody SystemUserTb args) {
if (!args.getId().equals(KitSecurityHelper.getCurrentUserId())) {
throw new BadRequestException("不能修改他人资料");
}
systemUserService.updateUserCenterInfoById(args); systemUserService.updateUserCenterInfoById(args);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -155,46 +102,22 @@ public class SystemUserController {
@PostMapping(value = "/removeUserByIds") @PostMapping(value = "/removeUserByIds")
@PreAuthorize("@el.check('user:del')") @PreAuthorize("@el.check('user:del')")
public ResponseEntity<Object> removeUserByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Object> removeUserByIds(@RequestBody Set<Long> ids) {
for (Long id : ids) {
Integer currentLevel = Collections.min(
systemRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(
systemRoleService.queryRoleByUsersId(id).stream().map(SystemRoleTb::getLevel)
.collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException(
"角色权限不足, 不能删除:" + systemUserService.getUserById(id).getUsername());
}
}
systemUserService.removeUserByIds(ids); systemUserService.removeUserByIds(ids);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("修改密码") @ApiOperation("修改密码")
@PostMapping(value = "/modifyUserPasswordByUsername") @PostMapping(value = "/modifyUserPasswordByUsername")
public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody SystemUpdateUserPasswordArgs passVo) public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody SystemUpdateUserPasswordArgs passVo) throws Exception {
throws Exception { String currentUsername = KitSecurityHelper.getCurrentUsername();
String oldPass = systemUserService.updateUserPasswordByUsername(currentUsername, passVo);
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getOldPass());
String newPass =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getNewPass());
SystemUserTb user = systemUserService.getUserByUsername(KitSecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(oldPass, user.getPassword())) {
throw new BadRequestException("修改失败,旧密码错误");
}
if (passwordEncoder.matches(newPass, user.getPassword())) {
throw new BadRequestException("新密码不能与旧密码相同");
}
systemUserService.updateUserPasswordByUsername(user.getUsername(), passwordEncoder.encode(newPass));
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@ApiOperation("重置密码") @ApiOperation("重置密码")
@PostMapping(value = "/resetUserPasswordByIds") @PostMapping(value = "/resetUserPasswordByIds")
public ResponseEntity<Object> resetUserPasswordByIds(@RequestBody Set<Long> ids) { public ResponseEntity<Object> resetUserPasswordByIds(@RequestBody Set<Long> ids) {
String defaultPwd = passwordEncoder.encode("123456"); systemUserService.resetUserPasswordByIds(ids);
systemUserService.resetUserPasswordByIds(ids, defaultPwd);
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
@@ -206,34 +129,12 @@ public class SystemUserController {
@ApiOperation("修改邮箱") @ApiOperation("修改邮箱")
@PostMapping(value = "/modifyUserEmailByUsername/{code}") @PostMapping(value = "/modifyUserEmailByUsername/{code}")
public ResponseEntity<Object> modifyUserEmailByUsername(@PathVariable String code, @RequestBody SystemUserTb args) public ResponseEntity<Object> modifyUserEmailByUsername(@PathVariable String code, @RequestBody SystemUserTb args) throws Exception {
throws Exception { String currentUsername = KitSecurityHelper.getCurrentUsername();
String password = systemUserService.updateUserEmailByUsername(currentUsername, args, code);
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getPassword());
SystemUserTb user = systemUserService.getUserByUsername(KitSecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadRequestException("密码错误");
}
systemEmailService.checkEmailCaptcha(SystemCaptchaBizEnum.EMAIL_RESET_EMAIL_CODE, args.getEmail(), code);
systemUserService.updateUserEmailByUsername(user.getUsername(), args.getEmail());
return ResponseEntity.ok(null); return ResponseEntity.ok(null);
} }
/**
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误
*
* @param args /
*/
private void checkLevel(SystemUserVo args) {
Integer currentLevel = Collections.min(
systemRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = systemRoleService.getDeptLevelByRoles(args.getRoles());
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
}
}
@ApiOperation("查询用户基础数据") @ApiOperation("查询用户基础数据")
@PostMapping(value = "/queryUserMetadataOptions") @PostMapping(value = "/queryUserMetadataOptions")
@PreAuthorize("@el.check('user:list')") @PreAuthorize("@el.check('user:list')")
@@ -15,14 +15,9 @@
*/ */
package cn.odboy.system.dal.mysql; package cn.odboy.system.dal.mysql;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.odboy.system.dal.dataobject.SystemDeptTb; import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.model.SystemQueryDeptArgs;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
/** /**
@@ -30,5 +30,6 @@ import org.apache.ibatis.annotations.Param;
*/ */
@Mapper @Mapper
public interface SystemDictDetailMapper extends BaseMapper<SystemDictDetailTb> { public interface SystemDictDetailMapper extends BaseMapper<SystemDictDetailTb> {
IPage<SystemDictDetailTb> selectPageByArgs(Page<SystemDictDetailTb> page, @Param("args") SystemQueryDictDetailArgs args); IPage<SystemDictDetailTb> selectPageByArgs(Page<SystemDictDetailTb> page, @Param("args") SystemQueryDictDetailArgs args);
} }
@@ -15,14 +15,9 @@
*/ */
package cn.odboy.system.dal.mysql; package cn.odboy.system.dal.mysql;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemQueryUserArgs;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@@ -20,6 +20,7 @@ import java.util.Date;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -157,4 +158,12 @@ public class SystemUserOnlineInfoDAO {
public SystemUserOnlineVo queryUserOnlineModelByKey(String key) { public SystemUserOnlineVo queryUserOnlineModelByKey(String key) {
return redisHelper.get(key, SystemUserOnlineVo.class); return redisHelper.get(key, SystemUserOnlineVo.class);
} }
public void kickOutUser(Set<String> keys) throws Exception {
for (String token : keys) {
// 解密Key
token = KitDesEncryptUtil.desDecrypt(token);
this.logoutByToken(token);
}
}
} }
@@ -0,0 +1,117 @@
package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.odboy.constant.CaptchaCodeEnum;
import cn.odboy.constant.SystemConst;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.model.SystemUserInfoVo;
import cn.odboy.system.dal.model.SystemUserJwtVo;
import cn.odboy.system.dal.model.SystemUserLoginArgs;
import cn.odboy.system.dal.redis.SystemCacheKey;
import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.framework.permission.core.handler.TokenProvider;
import cn.odboy.system.framework.permission.core.handler.UserDetailsHandler;
import cn.odboy.util.KitRsaEncryptUtil;
import com.wf.captcha.base.Captcha;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class SystemAuthService {
@Autowired
private KitRedisHelper redisHelper;
@Autowired
private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
@Autowired
private TokenProvider tokenProvider;
@Autowired
private AppProperties properties;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsHandler userDetailsService;
public Map<String, Object> doLogin(SystemUserLoginArgs loginRequest, HttpServletRequest request) throws Exception {
// 密码解密
String password =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginRequest.getPassword());
// 查询验证码
String code = redisHelper.get(loginRequest.getUuid(), String.class);
// 清除验证码
redisHelper.del(loginRequest.getUuid());
if (StrUtil.isBlank(code)) {
throw new BadRequestException("验证码不存在或已过期");
}
if (StrUtil.isBlank(loginRequest.getCode()) || !loginRequest.getCode().equalsIgnoreCase(code)) {
throw new BadRequestException("验证码错误");
}
// 获取用户信息
SystemUserJwtVo jwtUser = userDetailsService.loadUserByUsername(loginRequest.getUsername());
// 验证用户密码
if (!passwordEncoder.matches(password, jwtUser.getPassword())) {
throw new BadRequestException("登录密码错误");
}
Authentication authentication =
new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成令牌
String token = tokenProvider.createToken(jwtUser);
// 返回 token 与 用户信息
Map<String, Object> authInfo = new HashMap<>(2) {{
put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token));
put("user", BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class));
}};
if (properties.getLogin().isSingle()) {
// 踢掉之前已经登录的token
systemUserOnlineInfoDAO.kickOutByUsername(loginRequest.getUsername());
}
// 保存在线信息
systemUserOnlineInfoDAO.saveUserJwtModelByToken(jwtUser, token, request);
// 返回登录信息
return authInfo;
}
public SystemUserInfoVo getCurrentUserInfoVo() {
SystemUserJwtVo jwtUser = (SystemUserJwtVo) KitSecurityHelper.getCurrentUser();
return BeanUtil.copyProperties(jwtUser, SystemUserInfoVo.class);
}
public Map<String, Object> getCaptchaInfo() {
// 获取运算的结果
Captcha captcha = properties.getLogin().getCaptchaSetting().getCaptcha();
String uuid = SystemCacheKey.CAPTCHA_LOGIN + IdUtil.simpleUUID();
//当验证码类型为 arithmetic时且长度 >= 2 时, captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text();
if (captcha.getCharType() - 1 == CaptchaCodeEnum.ARITHMETIC.ordinal() &&
captchaValue.contains(SystemConst.SYMBOL_DOT)) {
captchaValue = captchaValue.split("\\.")[0];
}
// 保存
redisHelper.set(uuid, captchaValue, properties.getLogin().getCaptchaSetting().getExpiration(),
TimeUnit.MINUTES);
// 验证码信息
return new HashMap<>(2) {{
put("img", captcha.toBase64());
put("uuid", uuid);
}};
}
public void doLogout(HttpServletRequest request) {
String token = tokenProvider.getToken(request);
systemUserOnlineInfoDAO.logoutByToken(token);
}
}
@@ -37,7 +37,7 @@ import org.springframework.stereotype.Service;
public class SystemDataService { public class SystemDataService {
@Autowired @Autowired
private SystemRoleService systemRoleService; private SystemUserRoleService systemUserRoleService;
@Autowired @Autowired
private SystemDeptService systemDeptService; private SystemDeptService systemDeptService;
@Autowired @Autowired
@@ -52,7 +52,7 @@ public class SystemDataService {
public List<Long> queryDeptIdByArgs(SystemUserTb user) { public List<Long> queryDeptIdByArgs(SystemUserTb user) {
List<Long> deptIds = new ArrayList<>(); List<Long> deptIds = new ArrayList<>();
// 查询用户角色 // 查询用户角色
List<SystemRoleVo> roleList = systemRoleService.queryRoleByUsersId(user.getId()); List<SystemRoleVo> roleList = systemUserRoleService.queryRoleByUsersId(user.getId());
// 获取对应的部门ID // 获取对应的部门ID
for (SystemRoleTb role : roleList) { for (SystemRoleTb role : roleList) {
SystemDataScopeEnum dataScopeEnum = SystemDataScopeEnum.find(role.getDataScope()); SystemDataScopeEnum dataScopeEnum = SystemDataScopeEnum.find(role.getDataScope());
@@ -57,9 +57,9 @@ public class SystemDeptService {
@Autowired @Autowired
private SystemDeptMapper systemDeptMapper; private SystemDeptMapper systemDeptMapper;
@Autowired @Autowired
private SystemUserService systemUserService; private SystemUserDeptService systemUserDeptService;
@Autowired @Autowired
private SystemRoleService systemRoleService; private SystemRoleDeptService systemRoleDeptService;
/** /**
* 创建 * 创建
@@ -95,11 +95,15 @@ public class SystemDeptService {
/** /**
* 删除 * 删除
* *
* @param deptSet / * @param ids /
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteDeptByIds(Set<SystemDeptTb> deptSet) { public void deleteDeptByIds(Set<Long> ids) {
for (SystemDeptTb dept : deptSet) { // 获取部门, 和其所有子部门
Set<SystemDeptTb> depts = this.traverseDeptByIdWithPids(ids);
// 验证是否被角色或用户关联
this.verifyBindRelationByIds(depts);
for (SystemDeptTb dept : depts) {
systemDeptMapper.deleteById(dept.getId()); systemDeptMapper.deleteById(dept.getId());
this.updateDeptSubCnt(dept.getPid()); this.updateDeptSubCnt(dept.getPid());
} }
@@ -347,10 +351,10 @@ public class SystemDeptService {
*/ */
public void verifyBindRelationByIds(Set<SystemDeptTb> deptSet) { public void verifyBindRelationByIds(Set<SystemDeptTb> deptSet) {
Set<Long> deptIds = deptSet.stream().map(SystemDeptTb::getId).collect(Collectors.toSet()); Set<Long> deptIds = deptSet.stream().map(SystemDeptTb::getId).collect(Collectors.toSet());
if (systemUserService.countUserByDeptIds(deptIds) > 0) { if (systemUserDeptService.countUserByDeptIds(deptIds) > 0) {
throw new BadRequestException("所选部门存在用户关联,请解除后再试!"); throw new BadRequestException("所选部门存在用户关联,请解除后再试!");
} }
if (systemRoleService.countRoleByDeptIds(deptIds) > 0) { if (systemRoleDeptService.countRoleByDeptIds(deptIds) > 0) {
throw new BadRequestException("所选部门存在角色关联,请解除后再试!"); throw new BadRequestException("所选部门存在角色关联,请解除后再试!");
} }
} }
@@ -31,6 +31,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -134,4 +135,13 @@ public class SystemDictDetailService {
return detailVo; return detailVo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
public Map<String, List<SystemDictDetailVo>> getDictDetailMap(String dictName) {
String[] names = dictName.split("[,, ]");
Map<String, List<SystemDictDetailVo>> dictMap = new HashMap<>(16);
for (String name : names) {
dictMap.put(name, this.listDictDetailByName(name));
}
return dictMap;
}
} }
@@ -24,6 +24,7 @@ import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.redis.KitRedisHelper; import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.constant.SystemCaptchaBizEnum; import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.dataobject.SystemEmailConfigTb; import cn.odboy.system.dal.dataobject.SystemEmailConfigTb;
import cn.odboy.system.dal.model.SystemCheckEmailCaptchaArgs;
import cn.odboy.system.dal.model.SystemSendEmailArgs; import cn.odboy.system.dal.model.SystemSendEmailArgs;
import cn.odboy.system.dal.mysql.SystemEmailConfigMapper; import cn.odboy.system.dal.mysql.SystemEmailConfigMapper;
import cn.odboy.util.KitDesEncryptUtil; import cn.odboy.util.KitDesEncryptUtil;
@@ -112,7 +113,7 @@ public class SystemEmailService {
/** /**
* 校验邮箱验证码 * 校验邮箱验证码
*/ */
public void checkEmailCaptcha(SystemCaptchaBizEnum biEnum, String email, String code) { public void checkEmailCaptchaV1(SystemCaptchaBizEnum biEnum, String email, String code) {
String redisKey = biEnum.getRedisKey() + email; String redisKey = biEnum.getRedisKey() + email;
String value = redisHelper.get(redisKey, String.class); String value = redisHelper.get(redisKey, String.class);
if (value == null || !value.equals(code)) { if (value == null || !value.equals(code)) {
@@ -153,4 +154,12 @@ public class SystemEmailService {
SystemEmailConfigTb systemEmailConfigTb = systemEmailConfigMapper.selectById(1L); SystemEmailConfigTb systemEmailConfigTb = systemEmailConfigMapper.selectById(1L);
return systemEmailConfigTb == null ? new SystemEmailConfigTb() : systemEmailConfigTb; return systemEmailConfigTb == null ? new SystemEmailConfigTb() : systemEmailConfigTb;
} }
public void checkEmailCaptcha(SystemCheckEmailCaptchaArgs args) {
SystemCaptchaBizEnum biEnum = SystemCaptchaBizEnum.getByBizCode(args.getBizCode());
if (biEnum == null) {
throw new BadRequestException("不支持的业务");
}
this.checkEmailCaptchaV1(biEnum, args.getEmail(), args.getCode());
}
} }
@@ -84,6 +84,8 @@ public class SystemJobService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteJobByIds(Set<Long> ids) { public void deleteJobByIds(Set<Long> ids) {
// 验证是否被用户关联
this.verifyBindRelationByIds(ids);
systemJobMapper.deleteByIds(ids); systemJobMapper.deleteByIds(ids);
} }
@@ -21,6 +21,8 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.constant.FileTypeEnum;
import cn.odboy.framework.context.KitSpringBeanHolder;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties; import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.server.core.KitFileLocalUploadHelper; import cn.odboy.framework.server.core.KitFileLocalUploadHelper;
@@ -180,4 +182,14 @@ public class SystemLocalStorageService {
this.injectQueryParams(args, wrapper); this.injectQueryParams(args, wrapper);
return systemLocalStorageMapper.selectList(wrapper); return systemLocalStorageMapper.selectList(wrapper);
} }
public SystemLocalStorageTb uploadPictureV1(MultipartFile file) {
// 判断文件是否为图片
String suffix = KitFileUtil.getSuffix(file.getOriginalFilename());
if (!FileTypeEnum.IMAGE.getCode().equals(KitFileUtil.getFileType(suffix))) {
throw new BadRequestException("只能上传图片");
}
return KitSpringBeanHolder.getBean(SystemLocalStorageService.class).uploadFile(null, file);
}
} }
@@ -31,6 +31,7 @@ import cn.odboy.system.dal.model.SystemQueryMenuArgs;
import cn.odboy.system.dal.model.SystemRoleVo; import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.dal.mysql.SystemMenuMapper; import cn.odboy.system.dal.mysql.SystemMenuMapper;
import cn.odboy.system.dal.mysql.SystemRoleMenuMapper; import cn.odboy.system.dal.mysql.SystemRoleMenuMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitClassUtil; import cn.odboy.util.KitClassUtil;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -40,6 +41,7 @@ import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -64,6 +66,8 @@ public class SystemMenuService {
private SystemRoleService systemRoleService; private SystemRoleService systemRoleService;
@Autowired @Autowired
private SystemRoleMenuService systemRoleMenuService; private SystemRoleMenuService systemRoleMenuService;
@Autowired
private SystemUserRoleService systemUserRoleService;
/** /**
* 创建 * 创建
@@ -251,7 +255,7 @@ public class SystemMenuService {
* @return / * @return /
*/ */
public List<SystemMenuTb> listMenuByUserId(Long currentUserId) { public List<SystemMenuTb> listMenuByUserId(Long currentUserId) {
List<SystemRoleVo> roles = systemRoleService.queryRoleByUsersId(currentUserId); List<SystemRoleVo> roles = systemUserRoleService.queryRoleByUsersId(currentUserId);
Set<Long> roleIds = roles.stream().map(SystemRoleTb::getId).collect(Collectors.toSet()); Set<Long> roleIds = roles.stream().map(SystemRoleTb::getId).collect(Collectors.toSet());
return new ArrayList<>(systemRoleMenuService.queryMenuByRoleIds(roleIds)); return new ArrayList<>(systemRoleMenuService.queryMenuByRoleIds(roleIds));
} }
@@ -454,4 +458,41 @@ public class SystemMenuService {
wrapper.orderByAsc(SystemMenuTb::getMenuSort); wrapper.orderByAsc(SystemMenuTb::getMenuSort);
return systemMenuMapper.selectList(wrapper); return systemMenuMapper.selectList(wrapper);
} }
public List<SystemMenuVo> buildFrontMenus() {
List<SystemMenuTb> menuList = this.listMenuByUserId(KitSecurityHelper.getCurrentUserId());
List<SystemMenuTb> menus = this.buildMenuTree(menuList);
return this.buildMenuVo(menus);
}
public Set<Long> listChildMenuSetByMenuId(Long id) {
Set<SystemMenuTb> menuSet = new HashSet<>();
List<SystemMenuTb> menuList = this.listMenuByPid(id);
menuSet.add(systemMenuMapper.selectById(id));
menuSet = this.queryChildMenuByArgs(menuList, menuSet);
return menuSet.stream().map(SystemMenuTb::getId).collect(Collectors.toSet());
}
public List<SystemMenuTb> listMenuSuperior(List<Long> ids) {
Set<SystemMenuTb> menus;
List<SystemMenuTb> systemMenuTbs;
if (CollectionUtil.isNotEmpty(ids)) {
menus = new LinkedHashSet<>(this.listMenuByIds(ids));
for (SystemMenuTb menu : menus) {
List<SystemMenuTb> menuList = this.querySuperiorMenuByArgs(menu, new ArrayList<>());
for (SystemMenuTb data : menuList) {
if (data.getId().equals(menu.getPid())) {
data.setSubCount(data.getSubCount() - 1);
}
}
menus.addAll(menuList);
}
// 编辑菜单时不显示自己以及自己下级的数据, 避免出现PID数据环形问题
menus = menus.stream().filter(i -> !ids.contains(i.getId())).collect(Collectors.toSet());
systemMenuTbs = this.buildMenuTree(new ArrayList<>(menus));
} else {
systemMenuTbs = this.listMenuByPid(null);
}
return systemMenuTbs;
}
} }
@@ -20,6 +20,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.context.KitSpringBeanHolder;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.redis.KitRedisHelper; import cn.odboy.framework.redis.KitRedisHelper;
import cn.odboy.system.dal.dataobject.SystemQuartzJobTb; import cn.odboy.system.dal.dataobject.SystemQuartzJobTb;
@@ -58,6 +59,19 @@ public class SystemQuartzJobService {
@Autowired @Autowired
private KitRedisHelper redisHelper; private KitRedisHelper redisHelper;
/**
* 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
*
* @param beanName Bean名称
*/
private void checkBean(String beanName) {
// 避免调用攻击者可以从SpringContextHolder获得控制jdbcTemplate类
// 并使用getDeclaredMethod调用jdbcTemplate的queryForMap函数,执行任意sql命令。
if (!KitSpringBeanHolder.getAllServiceBeanName().contains(beanName)) {
throw new BadRequestException("非法的 Bean,请重新输入!");
}
}
/** /**
* 创建 * 创建
* *
@@ -65,6 +79,11 @@ public class SystemQuartzJobService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void createJob(SystemQuartzJobTb args) { public void createJob(SystemQuartzJobTb args) {
if (args.getId() != null) {
throw new BadRequestException("无效参数id");
}
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName());
if (!CronExpression.isValidExpression(args.getCronExpression())) { if (!CronExpression.isValidExpression(args.getCronExpression())) {
throw new BadRequestException("cron表达式格式错误"); throw new BadRequestException("cron表达式格式错误");
} }
@@ -79,6 +98,8 @@ public class SystemQuartzJobService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateQuartzJobResumeCron(SystemUpdateQuartzJobArgs args) { public void updateQuartzJobResumeCron(SystemUpdateQuartzJobArgs args) {
// 验证Bean是不是合法的, 合法的定时任务 Bean 需要用 @Service 定义
checkBean(args.getBeanName());
if (!CronExpression.isValidExpression(args.getCronExpression())) { if (!CronExpression.isValidExpression(args.getCronExpression())) {
throw new BadRequestException("cron表达式格式错误"); throw new BadRequestException("cron表达式格式错误");
} }
@@ -76,4 +76,20 @@ public class SystemRoleDeptService {
List<Long> deptIds = systemRoleDeptTbs.stream().map(SystemRoleDeptTb::getDeptId).collect(Collectors.toList()); List<Long> deptIds = systemRoleDeptTbs.stream().map(SystemRoleDeptTb::getDeptId).collect(Collectors.toList());
return systemDeptMapper.selectByIds(deptIds); return systemDeptMapper.selectByIds(deptIds);
} }
/**
* 根据部门ID统计角色数量
*
* @param deptIds 部门ID集合
* @return /
*/
public Long countRoleByDeptIds(Set<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return 0L;
}
LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemRoleDeptTb::getDeptId, deptIds);
return systemRoleDeptMapper.selectCount(wrapper);
}
} }
@@ -18,24 +18,19 @@ package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemMenuTb; import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.dataobject.SystemRoleDeptTb;
import cn.odboy.system.dal.dataobject.SystemRoleMenuTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemCreateRoleArgs; import cn.odboy.system.dal.model.SystemCreateRoleArgs;
import cn.odboy.system.dal.model.SystemQueryRoleArgs; import cn.odboy.system.dal.model.SystemQueryRoleArgs;
import cn.odboy.system.dal.model.SystemRoleCodeVo; import cn.odboy.system.dal.model.SystemRoleCodeVo;
import cn.odboy.system.dal.model.SystemRoleVo; import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.dal.mysql.SystemRoleDeptMapper;
import cn.odboy.system.dal.mysql.SystemRoleMapper; import cn.odboy.system.dal.mysql.SystemRoleMapper;
import cn.odboy.system.dal.mysql.SystemRoleMenuMapper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.system.dal.mysql.SystemUserRoleMapper;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -45,7 +40,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -57,6 +51,7 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemRoleService { public class SystemRoleService {
@Autowired @Autowired
private SystemRoleMapper systemRoleMapper; private SystemRoleMapper systemRoleMapper;
@Autowired @Autowired
@@ -64,11 +59,9 @@ public class SystemRoleService {
@Autowired @Autowired
private SystemRoleDeptService systemRoleDeptService; private SystemRoleDeptService systemRoleDeptService;
@Autowired @Autowired
private SystemRoleDeptMapper systemRoleDeptMapper;
@Autowired
private SystemUserRoleMapper systemUserRoleMapper;
@Autowired
private SystemUserService systemUserService; private SystemUserService systemUserService;
@Autowired
private SystemUserRoleService systemUserRoleService;
/** /**
* 创建 * 创建
@@ -77,6 +70,7 @@ public class SystemRoleService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveRole(SystemCreateRoleArgs args) { public void saveRole(SystemCreateRoleArgs args) {
checkRoleLevels(args.getLevel());
if (this.getRoleByName(args.getName()) != null) { if (this.getRoleByName(args.getName()) != null) {
throw new BadRequestException("角色名称已存在"); throw new BadRequestException("角色名称已存在");
} }
@@ -100,6 +94,7 @@ public class SystemRoleService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateRoleById(SystemRoleVo args) { public void updateRoleById(SystemRoleVo args) {
checkRoleLevels(args.getLevel());
SystemRoleVo role = BeanUtil.copyProperties(systemRoleMapper.selectById(args.getId()), SystemRoleVo.class); SystemRoleVo role = BeanUtil.copyProperties(systemRoleMapper.selectById(args.getId()), SystemRoleVo.class);
SystemRoleTb role1 = this.getRoleByName(args.getName()); SystemRoleTb role1 = this.getRoleByName(args.getName());
if (role1 != null && !role1.getId().equals(role.getId())) { if (role1 != null && !role1.getId().equals(role.getId())) {
@@ -123,14 +118,16 @@ public class SystemRoleService {
/** /**
* 修改绑定的菜单 * 修改绑定的菜单
* *
* @param role / * @param args /
*/ */
public void updateBindMenuById(SystemRoleVo role) { public void updateBindMenuById(SystemRoleVo args) {
SystemRoleTb role = systemRoleMapper.selectById(args.getId());
checkRoleLevels(role.getLevel());
// 更新菜单 // 更新菜单
systemRoleMenuService.deleteRoleMenuByRoleId(role.getId()); systemRoleMenuService.deleteRoleMenuByRoleId(role.getId());
// 判断是否为空 // 判断是否为空
if (CollUtil.isNotEmpty(role.getMenus())) { if (CollUtil.isNotEmpty(args.getMenus())) {
systemRoleMenuService.batchInsertRoleMenu(role.getMenus(), role.getId()); systemRoleMenuService.batchInsertRoleMenu(args.getMenus(), role.getId());
} }
} }
@@ -141,6 +138,13 @@ public class SystemRoleService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteRoleByIds(Set<Long> ids) { public void deleteRoleByIds(Set<Long> ids) {
List<Integer> roleLevels = systemRoleMapper.selectByIds(ids).stream().map(SystemRoleTb::getLevel).distinct().collect(Collectors.toList());
for (Integer roleLevel : roleLevels) {
checkRoleLevels(roleLevel);
}
// 验证是否被用户关联
this.verifyBindRelationByIds(ids);
// 删除角色
systemRoleMapper.deleteByIds(ids); systemRoleMapper.deleteByIds(ids);
// 删除角色部门关联数据、角色菜单关联数据 // 删除角色部门关联数据、角色菜单关联数据
systemRoleDeptService.batchDeleteRoleDept(ids); systemRoleDeptService.batchDeleteRoleDept(ids);
@@ -152,7 +156,6 @@ public class SystemRoleService {
* *
* @param roles 待导出的数据 * @param roles 待导出的数据
* @param response / * @param response /
* @throws IOException
*/ */
public void exportRoleExcel(List<SystemRoleVo> roles, HttpServletResponse response) throws IOException { public void exportRoleExcel(List<SystemRoleVo> roles, HttpServletResponse response) throws IOException {
List<Map<String, Object>> list = new ArrayList<>(); List<Map<String, Object>> list = new ArrayList<>();
@@ -180,7 +183,7 @@ public class SystemRoleService {
* 根据条件查询全部角色 * 根据条件查询全部角色
* *
* @param args 条件 * @param args 条件
* @return * @return /
*/ */
public List<SystemRoleVo> queryRoleByArgs(SystemQueryRoleArgs args) { public List<SystemRoleVo> queryRoleByArgs(SystemQueryRoleArgs args) {
// 查询角色基本信息 // 查询角色基本信息
@@ -199,10 +202,10 @@ public class SystemRoleService {
Page<SystemRoleTb> rolePage = new Page<>(args.getPage(), args.getSize()); Page<SystemRoleTb> rolePage = new Page<>(args.getPage(), args.getSize());
Page<SystemRoleTb> page = systemRoleMapper.selectPage(rolePage, wrapper); Page<SystemRoleTb> page = systemRoleMapper.selectPage(rolePage, wrapper);
List<SystemRoleTb> roles = page.getRecords(); List<SystemRoleTb> roles = page.getRecords();
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList()); return roles.stream().map(systemUserRoleService::convertToRoleVo).collect(Collectors.toList());
} else { } else {
List<SystemRoleTb> roles = systemRoleMapper.selectList(wrapper); List<SystemRoleTb> roles = systemRoleMapper.selectList(wrapper);
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList()); return roles.stream().map(systemUserRoleService::convertToRoleVo).collect(Collectors.toList());
} }
} }
@@ -211,7 +214,7 @@ public class SystemRoleService {
* *
* @param args 条件 * @param args 条件
* @param page 分页参数 * @param page 分页参数
* @return * @return /
*/ */
public KitPageResult<SystemRoleVo> searchRoleByArgs(SystemQueryRoleArgs args, Page<Object> page) { public KitPageResult<SystemRoleVo> searchRoleByArgs(SystemQueryRoleArgs args, Page<Object> page) {
args.setOffset(page.offset()); args.setOffset(page.offset());
@@ -220,41 +223,6 @@ public class SystemRoleService {
return KitPageUtil.toPage(roles, total); return KitPageUtil.toPage(roles, total);
} }
/**
* 根据用户ID查询
*
* @param userId 用户ID
* @return /
*/
public List<SystemRoleVo> queryRoleByUsersId(Long userId) {
// 查询用户角色关联
LambdaQueryWrapper<SystemUserRoleTb> userRoleWrapper = new LambdaQueryWrapper<>();
userRoleWrapper.eq(SystemUserRoleTb::getUserId, userId);
List<SystemUserRoleTb> userRoles = systemUserRoleMapper.selectList(userRoleWrapper);
if (CollUtil.isEmpty(userRoles)) {
return new ArrayList<>();
}
Set<Long> roleIds = userRoles.stream().map(SystemUserRoleTb::getRoleId).collect(Collectors.toSet());
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds);
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList());
}
/**
* 根据角色查询角色级别
*
* @param roles /
* @return /
*/
public Integer getDeptLevelByRoles(Set<SystemRoleTb> roles) {
if (CollUtil.isEmpty(roles)) {
return Integer.MAX_VALUE;
}
Set<SystemRoleTb> roleSet = new HashSet<>();
for (SystemRoleTb role : roles) {
roleSet.add(getRoleById(role.getId()));
}
return Collections.min(roleSet.stream().map(SystemRoleTb::getLevel).collect(Collectors.toList()));
}
/** /**
* 获取用户权限信息 * 获取用户权限信息
@@ -269,7 +237,7 @@ public class SystemRoleService {
permissions.add("admin"); permissions.add("admin");
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList()); return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
} }
List<SystemRoleVo> roles = this.queryRoleByUsersId(user.getId()); List<SystemRoleVo> roles = systemUserRoleService.queryRoleByUsersId(user.getId());
permissions = roles.stream().flatMap(role -> role.getMenus().stream()).map(SystemMenuTb::getPermission) permissions = roles.stream().flatMap(role -> role.getMenus().stream()).map(SystemMenuTb::getPermission)
.filter(StrUtil::isNotBlank).collect(Collectors.toSet()); .filter(StrUtil::isNotBlank).collect(Collectors.toSet());
return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList()); return permissions.stream().map(SystemRoleCodeVo::new).collect(Collectors.toList());
@@ -286,56 +254,6 @@ public class SystemRoleService {
} }
} }
/**
* 根据ID查询
*
* @param id /
* @return /
*/
public SystemRoleTb getRoleById(Long id) {
return systemRoleMapper.selectById(id);
}
/**
* 根据部门ID统计角色数量
*
* @param deptIds 部门ID集合
* @return /
*/
public Long countRoleByDeptIds(Set<Long> deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return 0L;
}
LambdaQueryWrapper<SystemRoleDeptTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemRoleDeptTb::getDeptId, deptIds);
return systemRoleDeptMapper.selectCount(wrapper);
}
/**
* 转换为SystemRoleVo并关联查询菜单和部门信息
*
* @param role 角色基本信息
* @return 包含关联信息的SystemRoleVo
*/
private SystemRoleVo convertToRoleVo(SystemRoleTb role) {
if (role == null) {
return null;
}
SystemRoleVo roleVo = BeanUtil.copyProperties(role, SystemRoleVo.class);
// 查询关联的菜单信息
Set<SystemMenuTb> menus = systemRoleMenuService.queryMenuByRoleIds(
Collections.singleton(role.getId()));
roleVo.setMenus(menus);
// 查询关联的部门信息
List<SystemDeptTb> depts = systemRoleDeptService.listDeptByRoleId(role.getId());
roleVo.setDepts(new LinkedHashSet<>(depts));
return roleVo;
}
public Long countRoleByArgs(SystemQueryRoleArgs args) { public Long countRoleByArgs(SystemQueryRoleArgs args) {
LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemRoleTb> wrapper = new LambdaQueryWrapper<>();
if (args != null) { if (args != null) {
@@ -349,4 +267,33 @@ public class SystemRoleService {
} }
return systemRoleMapper.selectCount(wrapper); return systemRoleMapper.selectCount(wrapper);
} }
public SystemRoleVo getRoleById(Long id) {
SystemRoleTb roleTb = systemRoleMapper.selectById(id);
if (roleTb == null) {
return null;
}
return systemUserRoleService.convertToRoleVo(roleTb);
}
public Dict getRoleLevel() {
return Dict.create().set("level", checkRoleLevels(null));
}
/**
* 检查用户的角色级别
*
* @return /
*/
private int checkRoleLevels(Integer level) {
List<Integer> levels = systemUserRoleService.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList());
int min = Collections.min(levels);
if (level != null) {
if (level < min) {
throw new BadRequestException("权限不足, 你的角色级别:" + min + ", 低于操作的角色级别:" + level);
}
}
return min;
}
} }
@@ -0,0 +1,21 @@
package cn.odboy.system.service;
import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.mysql.SystemUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SystemUserDeptService {
@Autowired
private SystemUserMapper systemUserMapper;
public long countUserByDeptIds(Set<Long> deptIds) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserTb::getDeptId, deptIds);
return systemUserMapper.selectCount(wrapper);
}
}
@@ -15,14 +15,26 @@
*/ */
package cn.odboy.system.service; package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemMenuTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserRoleTb; import cn.odboy.system.dal.dataobject.SystemUserRoleTb;
import cn.odboy.system.dal.model.SystemRoleVo;
import cn.odboy.system.dal.model.SystemUserVo;
import cn.odboy.system.dal.mysql.SystemRoleMapper;
import cn.odboy.system.dal.mysql.SystemUserRoleMapper; import cn.odboy.system.dal.mysql.SystemUserRoleMapper;
import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -30,8 +42,14 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
public class SystemUserRoleService { public class SystemUserRoleService {
@Autowired
private SystemRoleMapper systemRoleMapper;
@Autowired @Autowired
private SystemUserRoleMapper systemUserRoleMapper; private SystemUserRoleMapper systemUserRoleMapper;
@Autowired
private SystemRoleMenuService systemRoleMenuService;
@Autowired
private SystemRoleDeptService systemRoleDeptService;
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void batchInsertUserRole(Set<SystemRoleTb> roles, Long userId) { public void batchInsertUserRole(Set<SystemRoleTb> roles, Long userId) {
@@ -55,4 +73,78 @@ public class SystemUserRoleService {
systemUserRoleMapper.delete(wrapper); systemUserRoleMapper.delete(wrapper);
} }
} }
/**
* 转换为SystemRoleVo并关联查询菜单和部门信息
*
* @param role 角色基本信息
* @return 包含关联信息的SystemRoleVo
*/
public SystemRoleVo convertToRoleVo(SystemRoleTb role) {
if (role == null) {
return null;
}
SystemRoleVo roleVo = BeanUtil.copyProperties(role, SystemRoleVo.class);
// 查询关联的菜单信息
Set<SystemMenuTb> menus = systemRoleMenuService.queryMenuByRoleIds(
Collections.singleton(role.getId()));
roleVo.setMenus(menus);
// 查询关联的部门信息
List<SystemDeptTb> depts = systemRoleDeptService.listDeptByRoleId(role.getId());
roleVo.setDepts(new LinkedHashSet<>(depts));
return roleVo;
}
/**
* 根据用户ID查询
*
* @param userId 用户ID
* @return /
*/
public List<SystemRoleVo> queryRoleByUsersId(Long userId) {
// 查询用户角色关联
LambdaQueryWrapper<SystemUserRoleTb> userRoleWrapper = new LambdaQueryWrapper<>();
userRoleWrapper.eq(SystemUserRoleTb::getUserId, userId);
List<SystemUserRoleTb> userRoles = systemUserRoleMapper.selectList(userRoleWrapper);
if (CollUtil.isEmpty(userRoles)) {
return new ArrayList<>();
}
Set<Long> roleIds = userRoles.stream().map(SystemUserRoleTb::getRoleId).collect(Collectors.toSet());
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds);
return roles.stream().map(this::convertToRoleVo).collect(Collectors.toList());
}
/**
* 根据角色查询角色级别
*
* @param roles /
* @return /
*/
public Integer getDeptLevelByRoles(Set<SystemRoleTb> roles) {
if (CollUtil.isEmpty(roles)) {
return Integer.MAX_VALUE;
}
Set<SystemRoleTb> roleSet = new HashSet<>();
for (SystemRoleTb role : roles) {
roleSet.add(systemRoleMapper.selectById(role.getId()));
}
return Collections.min(roleSet.stream().map(SystemRoleTb::getLevel).collect(Collectors.toList()));
}
/**
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误
*
* @param args /
*/
public void checkLevel(SystemUserVo args) {
Integer currentLevel = Collections.min(
this.queryRoleByUsersId(KitSecurityHelper.getCurrentUserId()).stream()
.map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = this.getDeptLevelByRoles(args.getRoles());
if (currentLevel > optLevel) {
throw new BadRequestException("角色权限不足");
}
}
} }
@@ -17,12 +17,15 @@ package cn.odboy.system.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.odboy.base.KitPageArgs; import cn.odboy.base.KitPageArgs;
import cn.odboy.base.KitPageResult; import cn.odboy.base.KitPageResult;
import cn.odboy.base.KitSelectOptionVo; import cn.odboy.base.KitSelectOptionVo;
import cn.odboy.framework.exception.BadRequestException; import cn.odboy.framework.exception.BadRequestException;
import cn.odboy.framework.properties.AppProperties;
import cn.odboy.framework.server.core.KitFileLocalUploadHelper; import cn.odboy.framework.server.core.KitFileLocalUploadHelper;
import cn.odboy.system.constant.SystemCaptchaBizEnum;
import cn.odboy.system.dal.dataobject.SystemDeptTb; import cn.odboy.system.dal.dataobject.SystemDeptTb;
import cn.odboy.system.dal.dataobject.SystemJobTb; import cn.odboy.system.dal.dataobject.SystemJobTb;
import cn.odboy.system.dal.dataobject.SystemRoleTb; import cn.odboy.system.dal.dataobject.SystemRoleTb;
@@ -30,6 +33,7 @@ import cn.odboy.system.dal.dataobject.SystemUserJobTb;
import cn.odboy.system.dal.dataobject.SystemUserRoleTb; import cn.odboy.system.dal.dataobject.SystemUserRoleTb;
import cn.odboy.system.dal.dataobject.SystemUserTb; import cn.odboy.system.dal.dataobject.SystemUserTb;
import cn.odboy.system.dal.model.SystemQueryUserArgs; import cn.odboy.system.dal.model.SystemQueryUserArgs;
import cn.odboy.system.dal.model.SystemUpdateUserPasswordArgs;
import cn.odboy.system.dal.model.SystemUserVo; import cn.odboy.system.dal.model.SystemUserVo;
import cn.odboy.system.dal.mysql.SystemDeptMapper; import cn.odboy.system.dal.mysql.SystemDeptMapper;
import cn.odboy.system.dal.mysql.SystemJobMapper; import cn.odboy.system.dal.mysql.SystemJobMapper;
@@ -42,6 +46,7 @@ import cn.odboy.system.dal.redis.SystemUserOnlineInfoDAO;
import cn.odboy.system.framework.permission.core.KitSecurityHelper; import cn.odboy.system.framework.permission.core.KitSecurityHelper;
import cn.odboy.util.KitFileUtil; import cn.odboy.util.KitFileUtil;
import cn.odboy.util.KitPageUtil; import cn.odboy.util.KitPageUtil;
import cn.odboy.util.KitRsaEncryptUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -59,8 +64,11 @@ import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@Service @Service
@@ -69,10 +77,22 @@ public class SystemUserService {
@Autowired @Autowired
private SystemUserMapper systemUserMapper; private SystemUserMapper systemUserMapper;
@Autowired @Autowired
private SystemJobMapper systemJobMapper;
@Autowired
private SystemRoleMapper systemRoleMapper;
@Autowired
private SystemDeptMapper systemDeptMapper;
@Autowired
private SystemUserJobService systemUserJobService; private SystemUserJobService systemUserJobService;
@Autowired @Autowired
private SystemUserRoleService systemUserRoleService; private SystemUserRoleService systemUserRoleService;
@Autowired @Autowired
private SystemEmailService systemEmailService;
@Autowired
private SystemDeptService systemDeptService;
@Autowired
private SystemDataService systemDataService;
@Autowired
private SystemUserInfoDAO systemUserInfoDAO; private SystemUserInfoDAO systemUserInfoDAO;
@Autowired @Autowired
private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO; private SystemUserOnlineInfoDAO systemUserOnlineInfoDAO;
@@ -83,11 +103,10 @@ public class SystemUserService {
@Autowired @Autowired
private SystemUserRoleMapper systemUserRoleMapper; private SystemUserRoleMapper systemUserRoleMapper;
@Autowired @Autowired
private SystemJobMapper systemJobMapper; private AppProperties properties;
@Autowired @Autowired
private SystemRoleMapper systemRoleMapper; private PasswordEncoder passwordEncoder;
@Autowired
private SystemDeptMapper systemDeptMapper;
/** /**
* 新增用户 * 新增用户
@@ -96,6 +115,9 @@ public class SystemUserService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void saveUser(SystemUserVo args) { public void saveUser(SystemUserVo args) {
systemUserRoleService.checkLevel(args);
// 默认密码 123456
args.setPassword(passwordEncoder.encode("123456"));
args.setDeptId(args.getDept().getId()); args.setDeptId(args.getDept().getId());
if (this.getUserByUsername(args.getUsername()) != null) { if (this.getUserByUsername(args.getUsername()) != null) {
throw new BadRequestException("用户名已存在"); throw new BadRequestException("用户名已存在");
@@ -106,6 +128,7 @@ public class SystemUserService {
if (this.getUserByPhone(args.getPhone()) != null) { if (this.getUserByPhone(args.getPhone()) != null) {
throw new BadRequestException("手机号已存在"); throw new BadRequestException("手机号已存在");
} }
// 保存用户
systemUserMapper.insert(args); systemUserMapper.insert(args);
// 保存用户岗位 // 保存用户岗位
systemUserJobService.batchInsertUserJob(args.getJobs(), args.getId()); systemUserJobService.batchInsertUserJob(args.getJobs(), args.getId());
@@ -120,6 +143,7 @@ public class SystemUserService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateUserById(SystemUserVo args) { public void updateUserById(SystemUserVo args) {
systemUserRoleService.checkLevel(args);
SystemUserTb user = systemUserMapper.selectById(args.getId()); SystemUserTb user = systemUserMapper.selectById(args.getId());
SystemUserTb user1 = this.getUserByUsername(args.getUsername()); SystemUserTb user1 = this.getUserByUsername(args.getUsername());
SystemUserTb user2 = this.getUserByEmail(args.getEmail()); SystemUserTb user2 = this.getUserByEmail(args.getEmail());
@@ -163,6 +187,9 @@ public class SystemUserService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateUserCenterInfoById(SystemUserTb args) { public void updateUserCenterInfoById(SystemUserTb args) {
if (!args.getId().equals(KitSecurityHelper.getCurrentUserId())) {
throw new BadRequestException("不能修改他人资料");
}
SystemUserTb user = systemUserMapper.selectById(args.getId()); SystemUserTb user = systemUserMapper.selectById(args.getId());
SystemUserTb user1 = this.getUserByPhone(args.getPhone()); SystemUserTb user1 = this.getUserByPhone(args.getPhone());
if (user1 != null && !user.getId().equals(user1.getId())) { if (user1 != null && !user.getId().equals(user1.getId())) {
@@ -182,11 +209,26 @@ public class SystemUserService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void removeUserByIds(Set<Long> ids) { public void removeUserByIds(Set<Long> ids) {
Long currentUserId = KitSecurityHelper.getCurrentUserId();
// 校验权限
for (Long id : ids) { for (Long id : ids) {
// 清理缓存 Integer currentLevel = Collections.min(
SystemUserTb user = systemUserMapper.selectById(id); systemUserRoleService.queryRoleByUsersId(currentUserId).stream()
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername()); .map(SystemRoleTb::getLevel).collect(Collectors.toList()));
Integer optLevel = Collections.min(
systemUserRoleService.queryRoleByUsersId(id).stream().map(SystemRoleTb::getLevel)
.collect(Collectors.toList()));
if (currentLevel > optLevel) {
throw new BadRequestException(
"角色权限不足, 不能删除:" + this.getUserById(id).getUsername());
}
} }
// 清理缓存
List<String> usernameList = systemUserMapper.selectByIds(ids).stream().map(SystemUserTb::getUsername).distinct().collect(Collectors.toList());
for (String username : usernameList) {
systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
}
// 删除用户
systemUserMapper.deleteByIds(ids); systemUserMapper.deleteByIds(ids);
// 删除用户岗位 // 删除用户岗位
systemUserJobService.batchDeleteUserJob(ids); systemUserJobService.batchDeleteUserJob(ids);
@@ -197,11 +239,23 @@ public class SystemUserService {
/** /**
* 修改密码 * 修改密码
* *
* @param username 用户名 * @param username 用户名
* @param encryptPassword 密码 * @param args 参数
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateUserPasswordByUsername(String username, String encryptPassword) { public void updateUserPasswordByUsername(String username, SystemUpdateUserPasswordArgs args) throws Exception {
String oldPass =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getOldPass());
String newPass =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getNewPass());
SystemUserTb user = this.getUserByUsername(username);
if (!passwordEncoder.matches(oldPass, user.getPassword())) {
throw new BadRequestException("修改失败,旧密码错误");
}
if (passwordEncoder.matches(newPass, user.getPassword())) {
throw new BadRequestException("新密码不能与旧密码相同");
}
String encryptPassword = passwordEncoder.encode(newPass);
systemUserMapper.updateUserPasswordByUsername(username, encryptPassword); systemUserMapper.updateUserPasswordByUsername(username, encryptPassword);
systemUserInfoDAO.deleteUserLoginInfoByUserName(username); systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
} }
@@ -209,21 +263,21 @@ public class SystemUserService {
/** /**
* 重置密码 * 重置密码
* *
* @param ids 用户id * @param ids 用户id
* @param password 密码
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void resetUserPasswordByIds(Set<Long> ids, String password) { public void resetUserPasswordByIds(Set<Long> ids) {
String defaultPwd = passwordEncoder.encode("123456");
List<SystemUserTb> users = systemUserMapper.selectByIds(ids); List<SystemUserTb> users = systemUserMapper.selectByIds(ids);
// 清除缓存 // 清除缓存
users.forEach(user -> { for (SystemUserTb user : users) {
// 清除缓存 // 清除缓存
systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername()); systemUserInfoDAO.deleteUserLoginInfoByUserName(user.getUsername());
// 强制退出 // 强制退出
systemUserOnlineInfoDAO.kickOutByUsername(user.getUsername()); systemUserOnlineInfoDAO.kickOutByUsername(user.getUsername());
}); }
// 重置密码 // 重置密码
systemUserMapper.updateUserPasswordByUserIds(password, ids); systemUserMapper.updateUserPasswordByUserIds(defaultPwd, ids);
} }
/** /**
@@ -265,11 +319,19 @@ public class SystemUserService {
* 修改邮箱 * 修改邮箱
* *
* @param username 用户名 * @param username 用户名
* @param email 邮箱 * @param args 参数
* @param code 验证码
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateUserEmailByUsername(String username, String email) { public void updateUserEmailByUsername(String username, SystemUserTb args, String code) throws Exception {
systemUserMapper.updateUserEmailByUsername(username, email); String password =
KitRsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), args.getPassword());
SystemUserTb user = this.getUserByUsername(username);
if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadRequestException("密码错误");
}
systemEmailService.checkEmailCaptchaV1(SystemCaptchaBizEnum.EMAIL_RESET_EMAIL_CODE, args.getEmail(), code);
systemUserMapper.updateUserEmailByUsername(username, args.getEmail());
systemUserInfoDAO.deleteUserLoginInfoByUserName(username); systemUserInfoDAO.deleteUserLoginInfoByUserName(username);
} }
@@ -436,13 +498,11 @@ public class SystemUserService {
return null; return null;
} }
SystemUserVo userVo = BeanUtil.copyProperties(user, SystemUserVo.class); SystemUserVo userVo = BeanUtil.copyProperties(user, SystemUserVo.class);
// 查询关联的部门信息 // 查询关联的部门信息
if (user.getDeptId() != null) { if (user.getDeptId() != null) {
SystemDeptTb dept = systemDeptMapper.selectById(user.getDeptId()); SystemDeptTb dept = systemDeptMapper.selectById(user.getDeptId());
userVo.setDept(dept); userVo.setDept(dept);
} }
// 查询关联的岗位信息 // 查询关联的岗位信息
LambdaQueryWrapper<SystemUserJobTb> jobWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemUserJobTb> jobWrapper = new LambdaQueryWrapper<>();
jobWrapper.eq(SystemUserJobTb::getUserId, user.getId()); jobWrapper.eq(SystemUserJobTb::getUserId, user.getId());
@@ -452,7 +512,6 @@ public class SystemUserService {
List<SystemJobTb> jobs = systemJobMapper.selectByIds(jobIds); List<SystemJobTb> jobs = systemJobMapper.selectByIds(jobIds);
userVo.setJobs(new LinkedHashSet<>(jobs)); userVo.setJobs(new LinkedHashSet<>(jobs));
} }
// 查询关联的角色信息 // 查询关联的角色信息
LambdaQueryWrapper<SystemUserRoleTb> roleWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemUserRoleTb> roleWrapper = new LambdaQueryWrapper<>();
roleWrapper.eq(SystemUserRoleTb::getUserId, user.getId()); roleWrapper.eq(SystemUserRoleTb::getUserId, user.getId());
@@ -462,7 +521,6 @@ public class SystemUserService {
List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds); List<SystemRoleTb> roles = systemRoleMapper.selectByIds(roleIds);
userVo.setRoles(new LinkedHashSet<>(roles)); userVo.setRoles(new LinkedHashSet<>(roles));
} }
return userVo; return userVo;
} }
@@ -477,12 +535,6 @@ public class SystemUserService {
return this.convertToUserVo(this.getUserByUsername(username)); return this.convertToUserVo(this.getUserByUsername(username));
} }
public long countUserByDeptIds(Set<Long> deptIds) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.in(SystemUserTb::getDeptId, deptIds);
return systemUserMapper.selectCount(wrapper);
}
public SystemUserTb getUserByEmail(String email) { public SystemUserTb getUserByEmail(String email) {
LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<SystemUserTb> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(SystemUserTb::getEmail, email); wrapper.eq(SystemUserTb::getEmail, email);
@@ -496,4 +548,30 @@ public class SystemUserService {
wrapper.eq(SystemUserTb::getEnabled, 1); wrapper.eq(SystemUserTb::getEnabled, 1);
return systemUserMapper.selectOne(wrapper); return systemUserMapper.selectOne(wrapper);
} }
public KitPageResult<SystemUserVo> aggregationSearchUserByArgs(Page<SystemUserTb> page, SystemQueryUserArgs args, String currentUsername) {
if (!ObjectUtils.isEmpty(args.getDeptId())) {
args.getDeptIds().add(args.getDeptId());
// 先查找是否存在子节点
List<SystemDeptTb> data = systemDeptService.listDeptByPid(args.getDeptId());
// 然后把子节点的ID都加入到集合中
args.getDeptIds().addAll(systemDeptService.queryChildDeptIdByDeptIds(data));
}
// 数据权限
List<Long> dataScopes = systemDataService.queryDeptIdByArgs(
this.getUserByUsername(currentUsername));
// args.getDeptIds() 不为空并且数据权限不为空则取交集
if (!CollectionUtils.isEmpty(args.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)) {
// 取交集
args.getDeptIds().retainAll(dataScopes);
if (!CollectionUtil.isEmpty(args.getDeptIds())) {
return this.searchUserByArgs(args, page);
}
} else {
// 否则取并集
args.getDeptIds().addAll(dataScopes);
return this.searchUserByArgs(args, page);
}
return KitPageUtil.emptyData();
}
} }
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="cn.odboy.system.dal.mysql.SystemDictDetailMapper"> <mapper namespace="cn.odboy.system.dal.mysql.SystemDictDetailMapper">
<select id="selectPageByArgs" resultType="cn.odboy.system.dal.dataobject.SystemDictDetailTb"> <select id="selectPageByArgs" resultType="cn.odboy.system.dal.dataobject.SystemDictDetailTb">
SELECT SELECT
t1.* t1.*
FROM system_dict_detail t1 LEFT JOIN system_dict t2 ON t1.dict_id = t2.id FROM system_dict_detail t1 LEFT JOIN system_dict t2 ON t1.dict_id = t2.id
<where> <where>
<if test="args.dictName != null and args.dictName != ''"> <if test="args.dictName != null and args.dictName != ''">
AND t2.name = #{args.dictName} AND t2.name = #{args.dictName}
</if> </if>
<if test="args.label != null and args.label != ''"> <if test="args.label != null and args.label != ''">
AND t1.label = #{args.label} AND t1.label = #{args.label}
</if> </if>
</where> </where>
ORDER BY t1.dict_sort ORDER BY t1.dict_sort
</select> </select>
</mapper> </mapper>