mirror of
https://github.com/cool-team-official/cool-admin-java.git
synced 2026-10-07 14:08:04 +08:00
release v7.1
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
package com.cool.modules.base.controller.admin;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.eps.CoolEps;
|
||||
import com.cool.core.file.FileUploadStrategyFactory;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysLoginService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.base.service.sys.BaseSysUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* 系统通用接口, 每个人都有权限操作
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "系统通用", description = "系统通用")
|
||||
@CoolRestController()
|
||||
public class AdminBaseCommController {
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private BaseSysUserService baseSysUserService;
|
||||
|
||||
final private BaseSysLoginService baseSysLoginService;
|
||||
|
||||
final private CoolEps coolEps;
|
||||
|
||||
final private FileUploadStrategyFactory fileUploadStrategyFactory;
|
||||
|
||||
@Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务")
|
||||
@GetMapping("/eps")
|
||||
public R eps() {
|
||||
return R.ok(coolEps.getAdmin());
|
||||
}
|
||||
|
||||
@Operation(summary = "个人信息")
|
||||
@GetMapping("/person")
|
||||
public R person(@RequestAttribute() Long adminUserId) {
|
||||
BaseSysUserEntity baseSysUserEntity = baseSysUserService.getById(adminUserId);
|
||||
baseSysUserEntity.setPassword(null);
|
||||
baseSysUserEntity.setPasswordV(null);
|
||||
return R.ok(baseSysUserEntity);
|
||||
}
|
||||
|
||||
@Operation(summary = "修改个人信息")
|
||||
@PostMapping("/personUpdate")
|
||||
public R personUpdate(@RequestAttribute Long adminUserId, @RequestBody Dict body) {
|
||||
baseSysUserService.personUpdate(adminUserId, body);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "权限与菜单")
|
||||
@GetMapping("/permmenu")
|
||||
public R permmenu(@RequestAttribute() Long adminUserId) {
|
||||
return R.ok(baseSysPermsService.permmenu(adminUserId));
|
||||
}
|
||||
|
||||
@Operation(summary = "文件上传")
|
||||
@PostMapping(value = "/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE,
|
||||
MediaType.ALL_VALUE})
|
||||
public R upload(
|
||||
@RequestPart(value = "file", required = false) @Parameter(description = "文件") MultipartFile[] files,
|
||||
HttpServletRequest request) {
|
||||
return R.ok(fileUploadStrategyFactory.upload(files, request));
|
||||
}
|
||||
|
||||
@Operation(summary = "文件上传模式")
|
||||
@GetMapping("/uploadMode")
|
||||
public R uploadMode() {
|
||||
return R.ok(fileUploadStrategyFactory.getMode());
|
||||
}
|
||||
|
||||
@Operation(summary = "退出")
|
||||
@PostMapping("/logout")
|
||||
public R logout(@RequestAttribute Long adminUserId, @RequestAttribute String adminUsername) {
|
||||
baseSysLoginService.logout(adminUserId, adminUsername);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "编程")
|
||||
@GetMapping("/program")
|
||||
public R program() {
|
||||
return R.ok("Java");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.cool.modules.base.controller.admin;
|
||||
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.eps.CoolEps;
|
||||
import com.cool.core.file.FileUploadStrategyFactory;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.dto.sys.BaseSysLoginDto;
|
||||
import com.cool.modules.base.service.sys.BaseSysLoginService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 系统开放接口,无需权限校验
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "系统开放", description = "系统开放")
|
||||
@CoolRestController()
|
||||
public class AdminBaseOpenController {
|
||||
|
||||
final private BaseSysLoginService baseSysLoginService;
|
||||
|
||||
final private CoolEps coolEps;
|
||||
|
||||
final private FileUploadStrategyFactory fileUploadStrategyFactory;
|
||||
|
||||
@Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务")
|
||||
@GetMapping("/eps")
|
||||
public R eps() {
|
||||
return R.ok(coolEps.getAdmin());
|
||||
}
|
||||
|
||||
@Operation(summary = "获得网页内容的参数值")
|
||||
@GetMapping("/html")
|
||||
public R html() {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "登录")
|
||||
@PostMapping("/login")
|
||||
public R login(@RequestBody BaseSysLoginDto baseSysLoginDto) {
|
||||
return R.ok(baseSysLoginService.login(baseSysLoginDto));
|
||||
}
|
||||
|
||||
@Operation(summary = "验证码")
|
||||
@GetMapping("/captcha")
|
||||
public R captcha(@Parameter(description = "类型:svg|base64") @RequestParam(defaultValue = "base64") String type,
|
||||
@Parameter(description = "宽度") @RequestParam(defaultValue = "150") Integer width,
|
||||
@Parameter(description = "高度") @RequestParam(defaultValue = "50") Integer height) {
|
||||
return R.ok(baseSysLoginService.captcha(type, width, height));
|
||||
}
|
||||
|
||||
@Operation(summary = "刷新token")
|
||||
@GetMapping("/refreshToken")
|
||||
public R refreshToken(String refreshToken) {
|
||||
return R.ok(baseSysLoginService.refreshToken(refreshToken));
|
||||
}
|
||||
|
||||
@Operation(summary = "文件上传")
|
||||
@PostMapping(value = "/upload", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.ALL_VALUE })
|
||||
public R upload(@RequestPart(value = "file", required = false) @Parameter(description = "文件") MultipartFile[] files,
|
||||
HttpServletRequest request) {
|
||||
return R.ok(fileUploadStrategyFactory.upload(files, request));
|
||||
}
|
||||
|
||||
@Operation(summary = "文件上传模式")
|
||||
@GetMapping("/uploadMode")
|
||||
public R uploadMode() {
|
||||
return R.ok(fileUploadStrategyFactory.getMode());
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysDepartmentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统部门
|
||||
*/
|
||||
@Tag(name = "系统部门", description = "系统部门")
|
||||
@CoolRestController(api = { "add", "delete", "update", "list" })
|
||||
public class AdminBaseSysDepartmentController
|
||||
extends BaseController<BaseSysDepartmentService, BaseSysDepartmentEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
}
|
||||
|
||||
@Operation(summary = "排序")
|
||||
@PostMapping("/order")
|
||||
public R order(@RequestBody List<BaseSysDepartmentEntity> list) {
|
||||
this.service.order(list);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.entity.sys.BaseSysLogEntity;
|
||||
import com.cool.modules.base.entity.sys.table.BaseSysLogEntityTableDef;
|
||||
import com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef;
|
||||
import com.cool.modules.base.service.sys.BaseSysConfService;
|
||||
import com.cool.modules.base.service.sys.BaseSysLogService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "系统日志", description = "系统日志")
|
||||
@CoolRestController(api = {"page"})
|
||||
public class AdminBaseSysLogController extends BaseController<BaseSysLogService, BaseSysLogEntity> {
|
||||
|
||||
private final BaseSysConfService baseSysConfService;
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(
|
||||
createOp()
|
||||
.keyWordLikeFields(
|
||||
BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY.NAME,
|
||||
BaseSysLogEntityTableDef.BASE_SYS_LOG_ENTITY.PARAMS));
|
||||
}
|
||||
|
||||
@Operation(summary = "清理日志")
|
||||
@PostMapping("/clear")
|
||||
public R clear() {
|
||||
service.clear(true);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "设置日志保存时间")
|
||||
@PostMapping("/setKeep")
|
||||
public R setKeep(@RequestAttribute JSONObject requestParams) {
|
||||
baseSysConfService.updateValue("logKeep", requestParams.getStr("value"));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "获得日志报错时间")
|
||||
@PostMapping("/getKeep")
|
||||
public R getKeep() {
|
||||
return R.ok(baseSysConfService.getValue("logKeep"));
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.entity.sys.BaseSysMenuEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysMenuService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
/**
|
||||
* 系统菜单
|
||||
*/
|
||||
@Tag(name = "系统菜单", description = "系统菜单")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"})
|
||||
public class AdminBaseSysMenuController extends
|
||||
BaseController<BaseSysMenuService, BaseSysMenuEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
}
|
||||
|
||||
@Operation(summary = "创建代码", description = "创建代码")
|
||||
@PostMapping("/create")
|
||||
public R create(@RequestBody() Map<String, Object> params) {
|
||||
CoolPreconditions.checkEmpty(params.get("module"), "module参数不能为空");
|
||||
CoolPreconditions.checkEmpty(params.get("entity"), "entity参数不能为空");
|
||||
CoolPreconditions.checkEmpty(params.get("controller"), "controller参数不能为空");
|
||||
CoolPreconditions.checkEmpty(params.get("service"), "service参数不能为空");
|
||||
CoolPreconditions.checkEmpty(params.get("service-impl"), "service-impl参数不能为空");
|
||||
CoolPreconditions.checkEmpty(params.get("mapper"), "mapper参数不能为空");
|
||||
CoolPreconditions.checkEmpty(params.get("fileName"), "fileName参数不能为空");
|
||||
this.service.create(params);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "导出", description = "导出")
|
||||
@PostMapping("/export")
|
||||
public R export(@RequestBody Map<String, Object> params) {
|
||||
return R.ok(this.service.export(getIds(params)));
|
||||
}
|
||||
|
||||
@Operation(summary = "导入", description = "导入")
|
||||
@PostMapping("/import")
|
||||
public R importMenu(@RequestBody Map<String, List<BaseSysMenuEntity>> params) {
|
||||
CoolPreconditions.checkEmpty(params.get("menus"), "参数不能为空");
|
||||
return R.ok(this.service.importMenu(params.get("menus")));
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.base.entity.sys.BaseSysParamEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysParamService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 系统参数配置
|
||||
*/
|
||||
@Tag(name = "系统参数配置", description = "系统参数配置")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "info" })
|
||||
public class AdminBaseSysParamController extends BaseController<BaseSysParamService, BaseSysParamEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
}
|
||||
|
||||
@Operation(summary = "根据键返回网页的参数值")
|
||||
@GetMapping("/html")
|
||||
public String html(String key) {
|
||||
return service.htmlByKey(key);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY;
|
||||
import com.cool.modules.base.service.sys.BaseSysRoleService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
/**
|
||||
* 系统角色
|
||||
*/
|
||||
@Tag(name = "系统角色", description = "系统角色")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" })
|
||||
public class AdminBaseSysRoleController extends BaseController<BaseSysRoleService, BaseSysRoleEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo");
|
||||
boolean isAdmin = tokenInfo.getStr("username").equals("admin");
|
||||
|
||||
setPageOption(createOp().keyWordLikeFields(BASE_SYS_ROLE_ENTITY.NAME, BASE_SYS_ROLE_ENTITY.LABEL).queryWrapper(QueryWrapper.create().and(qw -> {
|
||||
qw.eq(BASE_SYS_ROLE_ENTITY.USER_ID.getName(), tokenInfo.get("userId")).or(w -> {
|
||||
w.in(BASE_SYS_ROLE_ENTITY.ID.getName(), tokenInfo.get("roleIds"));
|
||||
});
|
||||
}, !isAdmin).and(BASE_SYS_ROLE_ENTITY.LABEL.ne("admin"))));
|
||||
}
|
||||
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.cool.modules.base.controller.admin.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Tag(name = "系统用户", description = "系统用户")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "info" })
|
||||
public class AdminBaseSysUserController extends BaseController<BaseSysUserService, BaseSysUserEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
}
|
||||
|
||||
@Operation(summary = "移动部门")
|
||||
@PostMapping("/move")
|
||||
public R move(@RequestAttribute JSONObject requestParams) {
|
||||
service.move(requestParams.getLong("departmentId"), requestParams.get("userIds", Long[].class));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.cool.modules.base.controller.app;
|
||||
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.eps.CoolEps;
|
||||
import com.cool.core.request.R;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
/**
|
||||
* app通用接口
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "应用通用", description = "应用通用")
|
||||
@CoolRestController
|
||||
public class AppBaseCommController {
|
||||
|
||||
final private CoolEps coolEps;
|
||||
|
||||
@Operation(summary = "实体信息与路径", description = "系统所有的实体信息与路径,供前端自动生成代码与服务")
|
||||
@GetMapping("/eps")
|
||||
public R eps() {
|
||||
return R.ok(coolEps.getApp());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.cool.modules.base.dto.sys;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "登录参数")
|
||||
public class BaseSysLoginDto {
|
||||
|
||||
@Schema(description = "用户名")
|
||||
@NotBlank
|
||||
private String username;
|
||||
|
||||
@Schema(description = "密码")
|
||||
@NotBlank
|
||||
private String password;
|
||||
|
||||
@Schema(description = "验证码ID")
|
||||
@NotBlank
|
||||
private String captchaId;
|
||||
|
||||
@Schema(description = "验证码")
|
||||
@NotBlank
|
||||
private String verifyCode;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.tangzc.autotable.annotation.enums.IndexTypeEnum;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 系统配置
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_conf", comment = "系统配置表")
|
||||
public class BaseSysConfEntity extends BaseEntity<BaseSysConfEntity> {
|
||||
@Index(type = IndexTypeEnum.UNIQUE)
|
||||
@ColumnDefine(comment = "配置键", notNull = true)
|
||||
private String cKey;
|
||||
|
||||
@ColumnDefine(comment = "值", notNull = true, type = "text")
|
||||
private String cValue;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 系统部门
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_department", comment = "系统部门")
|
||||
public class BaseSysDepartmentEntity extends BaseEntity<BaseSysDepartmentEntity> {
|
||||
@ColumnDefine(comment = "部门名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "上级部门ID", type = "bigint")
|
||||
private Long parentId;
|
||||
|
||||
@ColumnDefine(comment = "排序", defaultValue = "0")
|
||||
private Integer orderNum;
|
||||
|
||||
// 父菜单名称
|
||||
@Column(ignore = true)
|
||||
private String parentName;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.core.handler.Fastjson2TypeHandler;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_log", comment = "系统日志表")
|
||||
public class BaseSysLogEntity extends BaseEntity<BaseSysLogEntity> {
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "用户ID", type = "bigint")
|
||||
private Long userId;
|
||||
|
||||
@ColumnDefine(comment = "行为", length = 1000)
|
||||
private String action;
|
||||
|
||||
@ColumnDefine(comment = "IP", length = 50)
|
||||
private String ip;
|
||||
|
||||
@ColumnDefine(comment = "参数", type = "json")
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private Object params;
|
||||
|
||||
// 用户名称
|
||||
@Column(ignore = true)
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_menu", comment = "系统菜单表")
|
||||
public class BaseSysMenuEntity extends BaseEntity<BaseSysMenuEntity> {
|
||||
@Index
|
||||
@ColumnDefine(comment = "父菜单ID", type = "bigint")
|
||||
private Long parentId;
|
||||
|
||||
@ColumnDefine(comment = "菜单名称")
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "权限")
|
||||
private String perms;
|
||||
|
||||
@ColumnDefine(comment = "类型 0:目录 1:菜单 2:按钮", type = "tinyint", defaultValue = "0")
|
||||
private Integer type;
|
||||
|
||||
@ColumnDefine(comment = "图标")
|
||||
private String icon;
|
||||
|
||||
@ColumnDefine(comment = "排序", defaultValue = "0")
|
||||
private Integer orderNum;
|
||||
|
||||
@ColumnDefine(comment = "菜单地址")
|
||||
private String router;
|
||||
|
||||
@ColumnDefine(comment = "视图地址")
|
||||
private String viewPath;
|
||||
|
||||
@ColumnDefine(comment = "路由缓存", defaultValue = "true")
|
||||
private Boolean keepAlive;
|
||||
|
||||
@ColumnDefine(comment = "是否显示", defaultValue = "true")
|
||||
private Boolean isShow;
|
||||
|
||||
@Column(ignore = true)
|
||||
private String parentName;
|
||||
|
||||
@Column(ignore = true)
|
||||
private List<BaseSysMenuEntity> childMenus;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_param", comment = "系统参数配置")
|
||||
public class BaseSysParamEntity extends BaseEntity<BaseSysParamEntity> {
|
||||
@Index
|
||||
@ColumnDefine(comment = "键", notNull = true)
|
||||
private String keyName;
|
||||
|
||||
@ColumnDefine(comment = "名称")
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "数据", type = "text")
|
||||
private String data;
|
||||
|
||||
@ColumnDefine(comment = "数据类型 0:字符串 1:数组 2:键值对", defaultValue = "0", type = "tinyint")
|
||||
private Integer dataType;
|
||||
|
||||
@ColumnDefine(comment = "备注")
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_role_department", comment = "系统角色部门")
|
||||
public class BaseSysRoleDepartmentEntity extends BaseEntity<BaseSysRoleDepartmentEntity> {
|
||||
|
||||
@ColumnDefine(comment = "角色ID", type = "bigint")
|
||||
private Long roleId;
|
||||
|
||||
@ColumnDefine(comment = "部门ID", type = "bigint")
|
||||
private Long departmentId;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.Fastjson2TypeHandler;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.autotable.annotation.enums.IndexTypeEnum;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_role", comment = "系统角色表")
|
||||
public class BaseSysRoleEntity extends BaseEntity<BaseSysRoleEntity> {
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "用户ID", notNull = true, type = "bigint")
|
||||
private Long userId;
|
||||
|
||||
@ColumnDefine(comment = "名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@Index(type = IndexTypeEnum.UNIQUE)
|
||||
@ColumnDefine(comment = "角色标签", notNull = true)
|
||||
private String label;
|
||||
|
||||
@ColumnDefine(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
@ColumnDefine(comment = "数据权限是否关联上下级", defaultValue = "1")
|
||||
private Integer relevance;
|
||||
|
||||
@ColumnDefine(comment = "菜单权限", type = "json")
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private List<Long> menuIdList;
|
||||
|
||||
@ColumnDefine(comment = "部门权限", type = "json")
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private List<Long> departmentIdList;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_role_menu", comment = "系统角色菜单表")
|
||||
public class BaseSysRoleMenuEntity extends BaseEntity<BaseSysRoleMenuEntity> {
|
||||
@ColumnDefine(comment = "菜单", type = "bigint")
|
||||
private Long menuId;
|
||||
|
||||
@ColumnDefine(comment = "角色ID", type = "bigint")
|
||||
private Long roleId;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.autotable.annotation.enums.IndexTypeEnum;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_user", comment = "系统用户表")
|
||||
public class BaseSysUserEntity extends BaseEntity<BaseSysUserEntity> {
|
||||
@Index
|
||||
@ColumnDefine(comment = "部门ID", type = "bigint")
|
||||
private Long departmentId;
|
||||
|
||||
@ColumnDefine(comment = "姓名")
|
||||
private String name;
|
||||
|
||||
@Index(type = IndexTypeEnum.UNIQUE)
|
||||
@ColumnDefine(comment = "用户名", length = 100, notNull = true)
|
||||
private String username;
|
||||
|
||||
@ColumnDefine(comment = "密码", notNull = true)
|
||||
private String password;
|
||||
|
||||
@ColumnDefine(comment = "密码版本", defaultValue = "1")
|
||||
private Integer passwordV;
|
||||
|
||||
@ColumnDefine(comment = "昵称", notNull = true)
|
||||
private String nickName;
|
||||
|
||||
@ColumnDefine(comment = "头像")
|
||||
private String headImg;
|
||||
|
||||
@ColumnDefine(comment = "手机号")
|
||||
private String phone;
|
||||
|
||||
@ColumnDefine(comment = "邮箱")
|
||||
private String email;
|
||||
|
||||
@ColumnDefine(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1", type = "tinyint")
|
||||
private Integer status;
|
||||
|
||||
// 部门名称
|
||||
@Column(ignore = true)
|
||||
private String departmentName;
|
||||
|
||||
// 角色名称
|
||||
@Column(ignore = true)
|
||||
private String roleName;
|
||||
|
||||
@ColumnDefine(comment = "socketId")
|
||||
private String socketId;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.cool.modules.base.entity.sys;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "base_sys_user_role", comment = "系统用户角色表")
|
||||
public class BaseSysUserRoleEntity extends BaseEntity<BaseSysUserRoleEntity> {
|
||||
@ColumnDefine(comment = "用户ID", type = "bigint")
|
||||
private Long userId;
|
||||
|
||||
@ColumnDefine(comment = "角色ID", type = "bigint")
|
||||
private Long roleId;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.cool.modules.base.filter;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.modules.base.service.sys.BaseSysLogService;
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Order(10)
|
||||
@RequiredArgsConstructor
|
||||
public class BaseLogFilter implements Filter {
|
||||
|
||||
final private BaseSysLogService baseSysLogService;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
|
||||
FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
// 记录日志
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
baseSysLogService.record(request, (JSONObject) request.getAttribute("requestParams"));
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.cool.modules.base.entity.sys.BaseSysConfEntity;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
|
||||
/**
|
||||
* 系统配置
|
||||
*/
|
||||
public interface BaseSysConfMapper extends BaseMapper<BaseSysConfEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
|
||||
/**
|
||||
* 系统部门
|
||||
*/
|
||||
public interface BaseSysDepartmentMapper extends BaseMapper<BaseSysDepartmentEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysLogEntity;
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*/
|
||||
public interface BaseSysLogMapper extends BaseMapper<BaseSysLogEntity> {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysMenuEntity;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统菜单
|
||||
*/
|
||||
public interface BaseSysMenuMapper extends BaseMapper<BaseSysMenuEntity> {
|
||||
/**
|
||||
* 根据角色ID获得所有菜单
|
||||
*
|
||||
* @param roleIds 角色ID集合
|
||||
* @return SysMenuEntity
|
||||
*/
|
||||
List<BaseSysMenuEntity> getMenus(@Param("roleIds") Long[] roleIds);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysParamEntity;
|
||||
|
||||
/**
|
||||
* 系统参数配置
|
||||
*/
|
||||
public interface BaseSysParamMapper extends BaseMapper<BaseSysParamEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleDepartmentEntity;
|
||||
|
||||
/**
|
||||
* 系统角色部门
|
||||
*/
|
||||
public interface BaseSysRoleDepartmentMapper extends BaseMapper<BaseSysRoleDepartmentEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
|
||||
/**
|
||||
* 系统角色
|
||||
*/
|
||||
public interface BaseSysRoleMapper extends BaseMapper<BaseSysRoleEntity> {
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleMenuEntity;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
/**
|
||||
* 系统角色菜单
|
||||
*/
|
||||
public interface BaseSysRoleMenuMapper extends BaseMapper<BaseSysRoleMenuEntity> {
|
||||
/**
|
||||
* 跟菜单关联的所有用户
|
||||
*
|
||||
* @param menuId 菜单
|
||||
* @return 所有用户ID
|
||||
*/
|
||||
Long[] userIds(@Param("menuId") Long menuId);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
public interface BaseSysUserMapper extends BaseMapper<BaseSysUserEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.mapper.sys;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserRoleEntity;
|
||||
|
||||
/**
|
||||
* 系统用户角色
|
||||
*/
|
||||
public interface BaseSysUserRoleMapper extends BaseMapper<BaseSysUserRoleEntity> {
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Security 工具类
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CoolSecurityUtil {
|
||||
|
||||
final private CoolCache coolCache;
|
||||
|
||||
/**
|
||||
* 登录的用户名
|
||||
*
|
||||
* @return 用户名
|
||||
*/
|
||||
public String username() {
|
||||
return SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得jwt中的信息
|
||||
*
|
||||
* @param requestParams 请求参数
|
||||
* @return jwt
|
||||
*/
|
||||
public JSONObject userInfo(JSONObject requestParams) {
|
||||
JSONObject tokenInfo = requestParams.getJSONObject("tokenInfo");
|
||||
if (tokenInfo != null) {
|
||||
tokenInfo.set("department",
|
||||
coolCache.get("admin:department:" + tokenInfo.get("userId")));
|
||||
tokenInfo.set("roleIds", coolCache.get("admin:roleIds:" + tokenInfo.get("userId")));
|
||||
}
|
||||
return tokenInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param adminUserId 用户ID
|
||||
* @param username 用户名
|
||||
*/
|
||||
public void logout(Long adminUserId, String username) {
|
||||
coolCache.del("admin:department:" + adminUserId, "admin:passwordVersion:" + adminUserId,
|
||||
"admin:userInfo:" + adminUserId, "admin:userDetails:" + username);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param userEntity 用户
|
||||
*/
|
||||
public void logout(BaseSysUserEntity userEntity) {
|
||||
logout(userEntity.getId(), userEntity.getUsername());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Token过滤器
|
||||
*/
|
||||
@Order(1)
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
final private JwtTokenUtil jwtTokenUtil;
|
||||
final private CoolCache coolCache;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain)
|
||||
throws ServletException, IOException {
|
||||
String authToken = request.getHeader("Authorization");
|
||||
if (!StrUtil.isEmpty(authToken)) {
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(authToken);
|
||||
String username = jwt.getPayload("username").toString();
|
||||
if (username != null
|
||||
&& SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
UserDetails userDetails = coolCache.get("admin:userDetails:" + username,
|
||||
JwtUser.class);
|
||||
Integer passwordV = Convert.toInt(jwt.getPayload("passwordVersion"));
|
||||
Integer rv = coolCache.get("admin:passwordVersion:" + jwt.getPayload("userId"),
|
||||
Integer.class);
|
||||
if (jwtTokenUtil.validateToken(authToken, username) && Objects.equals(passwordV, rv)
|
||||
&& userDetails != null) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(
|
||||
new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
request.setAttribute("adminUsername", jwt.getPayload("username"));
|
||||
request.setAttribute("adminUserId", jwt.getPayload("userId"));
|
||||
request.setAttribute("tokenInfo", jwt);
|
||||
}
|
||||
}
|
||||
}
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.base.service.sys.BaseSysUserService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 获得用户信息
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class JwtUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
final private BaseSysUserService baseSysUserService;
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
final private CoolCache coolCache;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
BaseSysUserEntity sysUserEntity = baseSysUserService.getMapper().selectOneByQuery(
|
||||
QueryWrapper.create().eq(BaseSysUserEntity::getUsername, username)
|
||||
.eq(BaseSysUserEntity::getStatus, 1));
|
||||
if (ObjectUtil.isEmpty(sysUserEntity)) {
|
||||
throw new UsernameNotFoundException("用户名不存在");
|
||||
}
|
||||
List<GrantedAuthority> authority = new ArrayList<>();
|
||||
String[] perms = baseSysPermsService.getPerms(sysUserEntity.getId());
|
||||
for (String perm : perms) {
|
||||
authority.add(new SimpleGrantedAuthority(perm));
|
||||
}
|
||||
Long[] departmentIds = baseSysPermsService.getDepartmentIdsByRoleIds(sysUserEntity.getId());
|
||||
JwtUser jwtUser = new JwtUser(sysUserEntity.getUsername(), sysUserEntity.getPassword(),
|
||||
authority,
|
||||
sysUserEntity.getStatus() == 1);
|
||||
Long[] roleIds = baseSysPermsService.getRoles(sysUserEntity);
|
||||
coolCache.set("admin:userDetails:" + jwtUser.getUsername(), jwtUser);
|
||||
coolCache.set("admin:passwordVersion:" + sysUserEntity.getId(),
|
||||
sysUserEntity.getPasswordV());
|
||||
coolCache.set("admin:userInfo:" + sysUserEntity.getId(), sysUserEntity);
|
||||
coolCache.set("admin:department:" + sysUserEntity.getId(), departmentIds);
|
||||
coolCache.set("admin:roleIds:" + sysUserEntity.getId(), roleIds);
|
||||
return jwtUser;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.cool.modules.base.security;
|
||||
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.access.SecurityConfig;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 权限资源管理器 为权限决断器提供支持
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
private Map<String, Collection<ConfigAttribute>> map = null;
|
||||
|
||||
/**
|
||||
* 加载权限表中所有操作请求权限
|
||||
*/
|
||||
public void loadResourceDefine() {
|
||||
map = new HashMap<>();
|
||||
Collection<ConfigAttribute> configAttributes;
|
||||
ConfigAttribute cfg;
|
||||
String[] perms = baseSysPermsService.getAllPerms();
|
||||
// 获取启用的权限操作请求
|
||||
for (String perm : perms) {
|
||||
configAttributes = new ArrayList<>();
|
||||
cfg = new SecurityConfig(perm);
|
||||
// 作为MyAccessDecisionManager类的decide的第三个参数
|
||||
configAttributes.add(cfg);
|
||||
// 用权限的path作为map的key,用ConfigAttribute的集合作为value
|
||||
map.put(perm.replaceAll(":", "/"), configAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判定用户请求的url是否在权限表中 如果在权限表中,则返回给decide方法,用来判定用户是否有此权限 如果不在权限表中则放行
|
||||
*
|
||||
* @param o
|
||||
* @return
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
@Override
|
||||
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
|
||||
if (map == null) {
|
||||
loadResourceDefine();
|
||||
}
|
||||
// Object中包含用户请求request
|
||||
String url = ((FilterInvocation) o).getRequestUrl();
|
||||
return map.get(url.replace("/admin/", "").split("[?]")[0]);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ConfigAttribute> getAllConfigAttributes() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> aClass) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysConfEntity;
|
||||
|
||||
/**
|
||||
* 系统配置
|
||||
*/
|
||||
public interface BaseSysConfService extends BaseService<BaseSysConfEntity> {
|
||||
/**
|
||||
* 更新配置
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
void updateValue(String key, String value);
|
||||
|
||||
/**
|
||||
* 获得值
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
String getValue(String key);
|
||||
|
||||
/**
|
||||
* 获得值(带缓存)
|
||||
*
|
||||
* @param key 键
|
||||
* @return 值
|
||||
*/
|
||||
String getValueWithCache(String key);
|
||||
|
||||
/**
|
||||
* 设置值
|
||||
*
|
||||
* @param key 键
|
||||
* @param value 值
|
||||
*/
|
||||
void setValue(String key, String value);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统部门
|
||||
*/
|
||||
public interface BaseSysDepartmentService extends BaseService<BaseSysDepartmentEntity> {
|
||||
/**
|
||||
* 排序
|
||||
*
|
||||
* @param list 新的排序
|
||||
*/
|
||||
void order(List<BaseSysDepartmentEntity> list);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysLogEntity;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*/
|
||||
public interface BaseSysLogService extends BaseService<BaseSysLogEntity> {
|
||||
/**
|
||||
* 清理日志
|
||||
*
|
||||
* @param isAll 是否全部清除
|
||||
*/
|
||||
void clear(boolean isAll);
|
||||
|
||||
/**
|
||||
* 日志记录
|
||||
*
|
||||
* @param requestParams 请求参数
|
||||
* @param request 请求
|
||||
*/
|
||||
void record(HttpServletRequest request, JSONObject requestParams);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.modules.base.dto.sys.BaseSysLoginDto;
|
||||
|
||||
/**
|
||||
* 系统登录
|
||||
*/
|
||||
public interface BaseSysLoginService {
|
||||
/**
|
||||
* 验证码
|
||||
*
|
||||
* @param type 类型 svg base64 svg是node版本的, java版本用base64, svg未实现
|
||||
* @param width 宽度
|
||||
* @param height 高度
|
||||
* @return base64 验证码与ID
|
||||
*/
|
||||
Object captcha(String type, Integer width, Integer height);
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param baseSysLoginDto 登录必要信息
|
||||
* @return token与相关的过期信息
|
||||
*/
|
||||
Object login(BaseSysLoginDto baseSysLoginDto);
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*
|
||||
* @param adminUserId 用户ID
|
||||
* @param username 用户名称
|
||||
*/
|
||||
void logout(Long adminUserId, String username);
|
||||
|
||||
/**
|
||||
* 刷新token
|
||||
*
|
||||
* @param refreshToken 刷新token
|
||||
* @return 新的token
|
||||
*/
|
||||
Object refreshToken(String refreshToken);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysMenuEntity;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 系统菜单
|
||||
*/
|
||||
public interface BaseSysMenuService extends BaseService<BaseSysMenuEntity> {
|
||||
|
||||
Object export(List<Long> ids);
|
||||
|
||||
boolean importMenu(List<BaseSysMenuEntity> menus);
|
||||
|
||||
void create(Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysParamEntity;
|
||||
|
||||
/**
|
||||
* 系统参数配置
|
||||
*/
|
||||
public interface BaseSysParamService extends BaseService<BaseSysParamEntity> {
|
||||
/**
|
||||
* 根据key获得网页内容
|
||||
*
|
||||
* @param key 键
|
||||
* @return 网页内容
|
||||
*/
|
||||
String htmlByKey(String key);
|
||||
|
||||
/**
|
||||
* 根据key获得数据
|
||||
*
|
||||
* @param key 键
|
||||
* @return 数据
|
||||
*/
|
||||
String dataByKey(String key);
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.modules.base.entity.sys.BaseSysMenuEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 权限菜单
|
||||
*/
|
||||
public interface BaseSysPermsService {
|
||||
/**
|
||||
* 获得权限缓存
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 返回用户相关的权限信息
|
||||
*/
|
||||
String[] getPermsCache(Long userId);
|
||||
|
||||
/**
|
||||
* 获得权限
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 返回用户相关的权限信息
|
||||
*/
|
||||
String[] getPerms(Long userId);
|
||||
|
||||
/**
|
||||
* 获得权限
|
||||
*
|
||||
* @param roleIds 用户角色数组
|
||||
* @return 返回用户相关的权限信息
|
||||
*/
|
||||
String[] getPerms(Long[] roleIds);
|
||||
|
||||
/**
|
||||
* 获得菜单
|
||||
*
|
||||
* @param roleIds 角色
|
||||
* @return 返回菜单
|
||||
*/
|
||||
List<BaseSysMenuEntity> getMenus(Long[] roleIds);
|
||||
|
||||
/**
|
||||
* 获得菜单
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 返回菜单
|
||||
*/
|
||||
List<BaseSysMenuEntity> getMenus(Long userId);
|
||||
|
||||
/**
|
||||
* 获得菜单
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 返回菜单
|
||||
*/
|
||||
List<BaseSysMenuEntity> getMenus(String username);
|
||||
|
||||
/**
|
||||
* 获得角色数组
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @return 返回角色数组
|
||||
*/
|
||||
Long[] getRoles(Long userId);
|
||||
|
||||
/**
|
||||
* 获得角色数组
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 返回角色数组
|
||||
*/
|
||||
Long[] getRoles(String username);
|
||||
|
||||
/**
|
||||
* 获得登录用户的部门权限
|
||||
*
|
||||
* @return 部门ID集合
|
||||
*/
|
||||
Long[] loginDepartmentIds();
|
||||
|
||||
/**
|
||||
* 根据角色获得部门ID
|
||||
*
|
||||
* @param roleIds 角色ID数组
|
||||
* @return 部门ID数组
|
||||
*/
|
||||
Long[] getDepartmentIdsByRoleIds(Long[] roleIds);
|
||||
|
||||
/**
|
||||
* 根据用户ID获得部门ID
|
||||
*
|
||||
* @param userId 角色ID数组
|
||||
* @return 部门ID数组
|
||||
*/
|
||||
Long[] getDepartmentIdsByRoleIds(Long userId);
|
||||
|
||||
/**
|
||||
* 获得角色数组
|
||||
*
|
||||
* @param userEntity 用户
|
||||
* @return 返回角色数组
|
||||
*/
|
||||
Long[] getRoles(BaseSysUserEntity userEntity);
|
||||
|
||||
/**
|
||||
* 所有的操作权限
|
||||
*
|
||||
* @return 返回所有的操作权限
|
||||
*/
|
||||
String[] getAllPerms();
|
||||
|
||||
/**
|
||||
* 用户的权限菜单
|
||||
*
|
||||
* @param adminUserId 登录的用户
|
||||
* @return 权限菜单
|
||||
*/
|
||||
Object permmenu(Long adminUserId);
|
||||
|
||||
/**
|
||||
* 更新角色权限
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @param menuIdList 菜单ID
|
||||
* @param departmentIds 部门ID
|
||||
*/
|
||||
void updatePerms(Long roleId, Long[] menuIdList, Long[] departmentIds);
|
||||
|
||||
/**
|
||||
* 更新用户角色
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param roleIdList 角色集合
|
||||
*/
|
||||
void updateUserRole(Long userId, Long[] roleIdList);
|
||||
|
||||
/**
|
||||
* 刷新权限
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
void refreshPerms(Long userId);
|
||||
|
||||
/**
|
||||
* 刷新权限
|
||||
*
|
||||
* @param menuId 用户ID
|
||||
*/
|
||||
void refreshPermsByMenuId(Long menuId);
|
||||
|
||||
/**
|
||||
* 刷新权限
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
*/
|
||||
void refreshPermsByRoleId(Long roleId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
|
||||
/**
|
||||
* 系统角色
|
||||
*/
|
||||
public interface BaseSysRoleService extends BaseService<BaseSysRoleEntity> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cool.modules.base.service.sys;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
public interface BaseSysUserService extends BaseService<BaseSysUserEntity> {
|
||||
/**
|
||||
* 修改用户信息
|
||||
*
|
||||
* @param body 用户信息
|
||||
*/
|
||||
void personUpdate(Long userId, Dict body);
|
||||
|
||||
/**
|
||||
* 移动部门
|
||||
*
|
||||
* @param departmentId 部门ID
|
||||
* @param userIds 用户ID集合
|
||||
*/
|
||||
void move(Long departmentId, Long[] userIds);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.modules.base.entity.sys.BaseSysConfEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysConfMapper;
|
||||
import com.cool.modules.base.service.sys.BaseSysConfService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.update.UpdateChain;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 系统配置
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BaseSysConfServiceImpl extends BaseServiceImpl<BaseSysConfMapper, BaseSysConfEntity>
|
||||
implements BaseSysConfService {
|
||||
|
||||
private final CoolCache coolCache;
|
||||
|
||||
@Override
|
||||
public void updateValue(String key, String value) {
|
||||
UpdateChain.of(BaseSysConfEntity.class).set(BaseSysConfEntity::getCValue, value)
|
||||
.eq(BaseSysConfEntity::getCKey, key).update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(String key) {
|
||||
BaseSysConfEntity baseSysConfEntity = getOne(QueryWrapper.create().eq(BaseSysConfEntity::getCKey, key));
|
||||
if (baseSysConfEntity != null) {
|
||||
return baseSysConfEntity.getCValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueWithCache(String key) {
|
||||
String value = coolCache.get(key, String.class);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
value = getValue(key);
|
||||
if (value != null) {
|
||||
coolCache.set(key, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, String value) {
|
||||
BaseSysConfEntity baseSysConfEntity = new BaseSysConfEntity();
|
||||
baseSysConfEntity.setCKey(key);
|
||||
baseSysConfEntity.setCValue(value);
|
||||
save(baseSysConfEntity);
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysDepartmentService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.update.UpdateChain;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 系统部门
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class BaseSysDepartmentServiceImpl extends
|
||||
BaseServiceImpl<BaseSysDepartmentMapper, BaseSysDepartmentEntity>
|
||||
implements BaseSysDepartmentService {
|
||||
|
||||
final private BaseSysUserMapper baseSysUserMapper;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
@Override
|
||||
public void order(List<BaseSysDepartmentEntity> list) {
|
||||
list.forEach(baseSysDepartmentEntity -> {
|
||||
UpdateChain.of(BaseSysDepartmentEntity.class)
|
||||
.set(BaseSysDepartmentEntity::getOrderNum, baseSysDepartmentEntity.getOrderNum())
|
||||
.eq(BaseSysDepartmentEntity::getId, baseSysDepartmentEntity.getId()).update();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseSysDepartmentEntity> list(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
String username = coolSecurityUtil.username();
|
||||
Long[] loginDepartmentIds = baseSysPermsService.loginDepartmentIds();
|
||||
if (loginDepartmentIds != null && loginDepartmentIds.length == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<BaseSysDepartmentEntity> list = this.list(
|
||||
QueryWrapper.create()
|
||||
.in(BaseSysDepartmentEntity::getId, loginDepartmentIds, !username.equals("admin"))
|
||||
.orderBy(BaseSysDepartmentEntity::getOrderNum, false));
|
||||
list.forEach(e -> {
|
||||
List<BaseSysDepartmentEntity> parentDepartment = list.stream()
|
||||
.filter(sysDepartmentEntity -> e.getParentId() != null
|
||||
&& e.getParentId().equals(sysDepartmentEntity.getId()))
|
||||
.toList();
|
||||
if (!parentDepartment.isEmpty()) {
|
||||
e.setParentName(parentDepartment.get(0).getName());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(JSONObject requestParams, Long... ids) {
|
||||
super.delete(ids);
|
||||
// 是否删除对应用户 否则移动到顶层部门
|
||||
if (requestParams.getBool("deleteUser")) {
|
||||
return baseSysUserMapper
|
||||
.deleteByQuery(
|
||||
QueryWrapper.create().in(BaseSysUserEntity::getDepartmentId, (Object) ids)) > 0;
|
||||
} else {
|
||||
BaseSysDepartmentEntity topDepartment = getOne(
|
||||
QueryWrapper.create().isNull(BaseSysDepartmentEntity::getParentId));
|
||||
if (topDepartment != null) {
|
||||
UpdateChain.of(BaseSysUserEntity.class)
|
||||
.set(BaseSysUserEntity::getDepartmentId, topDepartment.getId())
|
||||
.in(BaseSysUserEntity::getDepartmentId, (Object) ids).update();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.util.IPUtils;
|
||||
import com.cool.modules.base.entity.sys.BaseSysLogEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.entity.sys.table.BaseSysLogEntityTableDef;
|
||||
import com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysLogMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysConfService;
|
||||
import com.cool.modules.base.service.sys.BaseSysLogService;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 系统日志
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class BaseSysLogServiceImpl extends BaseServiceImpl<BaseSysLogMapper, BaseSysLogEntity>
|
||||
implements BaseSysLogService {
|
||||
|
||||
private final BaseSysConfService baseSysConfService;
|
||||
|
||||
private final CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
private final IPUtils ipUtils;
|
||||
|
||||
@Override
|
||||
public Object page(
|
||||
JSONObject requestParams, Page<BaseSysLogEntity> page, QueryWrapper queryWrapper) {
|
||||
queryWrapper
|
||||
.select(
|
||||
BaseSysLogEntityTableDef.BASE_SYS_LOG_ENTITY.ALL_COLUMNS,
|
||||
BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY.NAME)
|
||||
.from(BaseSysLogEntityTableDef.BASE_SYS_LOG_ENTITY)
|
||||
.leftJoin(BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY)
|
||||
.on(BaseSysLogEntity::getUserId, BaseSysUserEntity::getId);
|
||||
return mapper.paginate(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(boolean isAll) {
|
||||
if (isAll) {
|
||||
this.remove(QueryWrapper.create().ge(BaseSysLogEntity::getId, 0));
|
||||
} else {
|
||||
String keepDay = baseSysConfService.getValue("logKeep");
|
||||
int keepDays = Integer.parseInt(StrUtil.isNotEmpty(keepDay) ? keepDay : "30");
|
||||
Date beforeDate = DateUtil.offsetDay(new Date(), -keepDays);
|
||||
this.remove(QueryWrapper.create().lt(BaseSysLogEntity::getCreateTime, beforeDate));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void record(HttpServletRequest request, JSONObject requestParams) {
|
||||
String requestURI = request.getRequestURI();
|
||||
String ipAddr = ipUtils.getIpAddr(request);
|
||||
JSONObject userInfo = coolSecurityUtil.userInfo(requestParams);
|
||||
|
||||
Long userId = null;
|
||||
if (userInfo != null) {
|
||||
userId = userInfo.getLong("userId");
|
||||
}
|
||||
|
||||
JSONObject newJSONObject = JSONUtil.parseObj(JSONUtil.toJsonStr(requestParams));
|
||||
newJSONObject.remove("tokenInfo");
|
||||
newJSONObject.remove("refreshToken");
|
||||
newJSONObject.remove("body");
|
||||
|
||||
recordAsync(requestURI, ipAddr, userId, newJSONObject);
|
||||
}
|
||||
|
||||
|
||||
@Async
|
||||
public void recordAsync(String requestURI, String ip, Long userId, JSONObject params) {
|
||||
BaseSysLogEntity logEntity = new BaseSysLogEntity();
|
||||
logEntity.setAction(requestURI);
|
||||
logEntity.setIp(ip);
|
||||
if (userId != null) {
|
||||
logEntity.setUserId(userId);
|
||||
}
|
||||
logEntity.setParams(params);
|
||||
save(logEntity);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.captcha.CaptchaUtil;
|
||||
import cn.hutool.captcha.GifCaptcha;
|
||||
import cn.hutool.captcha.generator.RandomGenerator;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.modules.base.dto.sys.BaseSysLoginDto;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysLoginService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.awt.Color;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BaseSysLoginServiceImpl implements BaseSysLoginService {
|
||||
|
||||
private final CoolCache coolCache;
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
private final CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
private final BaseSysUserMapper baseSysUserMapper;
|
||||
|
||||
private final BaseSysPermsService baseSysPermsService;
|
||||
|
||||
@Override
|
||||
public Object captcha(String type, Integer width, Integer height) {
|
||||
// 1、生成验证码 2、生成对应的ID并设置在缓存中,验证码过期时间30分钟;
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
String captchaId = StrUtil.uuid();
|
||||
result.put("captchaId", captchaId);
|
||||
RandomGenerator randomGenerator = new RandomGenerator(4);
|
||||
GifCaptcha gifCaptcha = CaptchaUtil.createGifCaptcha(width, height);
|
||||
gifCaptcha.setGenerator(randomGenerator);
|
||||
gifCaptcha.setBackground(new Color(248, 248, 248));
|
||||
gifCaptcha.setMaxColor(60);
|
||||
gifCaptcha.setMinColor(55);
|
||||
result.put("data", "data:image/png;base64," + gifCaptcha.getImageBase64());
|
||||
coolCache.set("verify:img:" + captchaId, gifCaptcha.getCode(), 1800);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object login(BaseSysLoginDto baseSysLoginDto) {
|
||||
// 1、检查验证码是否正确 2、执行登录操作
|
||||
String verifyCode = coolCache.get("verify:img:" + baseSysLoginDto.getCaptchaId(),
|
||||
String.class);
|
||||
if (StrUtil.isNotEmpty(verifyCode)
|
||||
&& verifyCode.equalsIgnoreCase(baseSysLoginDto.getVerifyCode())) {
|
||||
UsernamePasswordAuthenticationToken upToken =
|
||||
new UsernamePasswordAuthenticationToken(
|
||||
baseSysLoginDto.getUsername(), baseSysLoginDto.getPassword());
|
||||
Authentication authentication = authenticationManager.authenticate(upToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 查询用户信息并生成token
|
||||
BaseSysUserEntity sysUserEntity =
|
||||
baseSysUserMapper.selectOneByQuery(
|
||||
QueryWrapper.create()
|
||||
.eq(BaseSysUserEntity::getUsername, baseSysLoginDto.getUsername()));
|
||||
CoolPreconditions.check(
|
||||
ObjectUtil.isEmpty(sysUserEntity) || sysUserEntity.getStatus() == 0, "用户已禁用");
|
||||
Long[] roleIds = baseSysPermsService.getRoles(sysUserEntity);
|
||||
Dict tokenInfo =
|
||||
Dict.create()
|
||||
.set("roleIds", roleIds)
|
||||
.set("username", baseSysLoginDto.getUsername())
|
||||
.set("userId", sysUserEntity.getId())
|
||||
.set("passwordVersion", sysUserEntity.getPasswordV());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
String refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
coolCache.del("verify:img:" + baseSysLoginDto.getCaptchaId());
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
} else {
|
||||
coolCache.del("verify:img:" + baseSysLoginDto.getCaptchaId());
|
||||
throw new CoolException("验证码不正确");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(Long adminUserId, String username) {
|
||||
coolSecurityUtil.logout(adminUserId, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object refreshToken(String refreshToken) {
|
||||
JWT jwt = jwtTokenUtil.getTokenInfo(refreshToken);
|
||||
try {
|
||||
CoolPreconditions.check(jwt == null || !(Boolean) jwt.getPayload("isRefresh"),
|
||||
"错误的token");
|
||||
|
||||
BaseSysUserEntity baseSysUserEntity =
|
||||
baseSysUserMapper.selectOneById(Convert.toLong(jwt.getPayload("userId")));
|
||||
Long[] roleIds = baseSysPermsService.getRoles(baseSysUserEntity);
|
||||
Dict tokenInfo =
|
||||
Dict.create()
|
||||
.set("roleIds", roleIds)
|
||||
.set("username", baseSysUserEntity.getUsername())
|
||||
.set("userId", baseSysUserEntity.getId())
|
||||
.set("passwordVersion", baseSysUserEntity.getPasswordV());
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire());
|
||||
} catch (Exception e) {
|
||||
throw new CoolException("错误的token", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.util.CompilerUtils;
|
||||
import com.cool.core.util.PathUtils;
|
||||
import com.cool.modules.base.entity.sys.BaseSysMenuEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysMenuMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysMenuService;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 系统菜单
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BaseSysMenuServiceImpl extends BaseServiceImpl<BaseSysMenuMapper, BaseSysMenuEntity>
|
||||
implements BaseSysMenuService {
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Override
|
||||
public Object list(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
List<BaseSysMenuEntity> list = baseSysPermsService.getMenus(coolSecurityUtil.username());
|
||||
list.forEach(e -> {
|
||||
List<BaseSysMenuEntity> parent = list.stream()
|
||||
.filter(sysMenuEntity -> e.getParentId() != null && e.getParentId()
|
||||
.equals(sysMenuEntity.getId()))
|
||||
.toList();
|
||||
if (!parent.isEmpty()) {
|
||||
e.setParentName(parent.get(0).getName());
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAfter(JSONObject requestParams, BaseSysMenuEntity sysMenuEntity,
|
||||
ModifyEnum type) {
|
||||
if (sysMenuEntity != null && sysMenuEntity.getId() != null) {
|
||||
baseSysPermsService.refreshPermsByMenuId(requestParams.getLong("id"));
|
||||
}
|
||||
if (requestParams.get("ids") != null) {
|
||||
Long[] ids = requestParams.get("ids", Long[].class);
|
||||
for (Long id : ids) {
|
||||
baseSysPermsService.refreshPermsByMenuId(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Long... ids) {
|
||||
super.delete(ids);
|
||||
for (Long id : ids) {
|
||||
this.delChildMenu(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除子菜单
|
||||
*
|
||||
* @param id 删除的菜单ID
|
||||
*/
|
||||
private void delChildMenu(Long id) {
|
||||
List<BaseSysMenuEntity> delMenu = list(
|
||||
QueryWrapper.create().eq(BaseSysMenuEntity::getParentId, id));
|
||||
if (CollectionUtil.isEmpty(delMenu)) {
|
||||
return;
|
||||
}
|
||||
Long[] ids = delMenu.stream().map(BaseSysMenuEntity::getId).toArray(Long[]::new);
|
||||
if (ArrayUtil.isNotEmpty(ids)) {
|
||||
delete(ids);
|
||||
for (Long delId : ids) {
|
||||
this.delChildMenu(delId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object export(List<Long> ids) {
|
||||
List<BaseSysMenuEntity> list = list(
|
||||
QueryWrapper.create().in(BaseSysMenuEntity::getId, ids));
|
||||
List<BaseSysMenuEntity> parentList = list.stream()
|
||||
.filter(o -> ObjUtil.isEmpty(o.getParentId())).toList();
|
||||
Map<Long, List<BaseSysMenuEntity>> map = list.stream()
|
||||
.filter(o -> ObjUtil.isNotEmpty(o.getParentId()))
|
||||
.collect(Collectors.groupingBy(BaseSysMenuEntity::getParentId));
|
||||
parentList.forEach(o -> handler(o, map));
|
||||
return parentList;
|
||||
}
|
||||
|
||||
private void handler(BaseSysMenuEntity parentBaseSysMenuEntity,
|
||||
Map<Long, List<BaseSysMenuEntity>> map) {
|
||||
parentBaseSysMenuEntity.setChildMenus(
|
||||
map.getOrDefault(parentBaseSysMenuEntity.getId(), new ArrayList<>()));
|
||||
parentBaseSysMenuEntity.getChildMenus().forEach(o -> {
|
||||
handler(o, map);
|
||||
o.setId(null);
|
||||
o.setParentId(null);
|
||||
o.setCreateTime(null);
|
||||
o.setUpdateTime(null);
|
||||
});
|
||||
parentBaseSysMenuEntity.setId(null);
|
||||
parentBaseSysMenuEntity.setParentId(null);
|
||||
parentBaseSysMenuEntity.setCreateTime(null);
|
||||
parentBaseSysMenuEntity.setUpdateTime(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean importMenu(List<BaseSysMenuEntity> menus) {
|
||||
menus.forEach(this::importMenu);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void importMenu(BaseSysMenuEntity sysMenuEntity) {
|
||||
sysMenuEntity.save();
|
||||
if (ObjUtil.isNotEmpty(sysMenuEntity.getChildMenus())) {
|
||||
sysMenuEntity.getChildMenus().forEach(o -> {
|
||||
o.setParentId(sysMenuEntity.getId());
|
||||
importMenu(o);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(Map<String, Object> params) {
|
||||
String module = (String) params.get("module");
|
||||
String controller = (String) params.get("controller");
|
||||
String entity = (String) params.get("entity");
|
||||
String service = (String) params.get("service");
|
||||
String serviceImpl = (String) params.get("service-impl");
|
||||
String mapper = (String) params.get("mapper");
|
||||
|
||||
String fileName = (String) params.get("fileName");
|
||||
String modulesPath = PathUtils.getModulesPath();
|
||||
// 创建的模块地址
|
||||
String actModulePath = CompilerUtils.createModule(modulesPath, module);
|
||||
// 创建 controller
|
||||
CompilerUtils.createController(actModulePath, fileName, controller);
|
||||
// 创建 entity
|
||||
String entityPath = CompilerUtils.createEntity(actModulePath, fileName, entity);
|
||||
// 创建 service
|
||||
CompilerUtils.createService(actModulePath, fileName, service);
|
||||
// 创建 serviceImpl
|
||||
CompilerUtils.createServiceImpl(actModulePath, fileName, serviceImpl);
|
||||
// 创建 mapper
|
||||
CompilerUtils.createMapper(actModulePath, fileName, mapper);
|
||||
// 关闭springboot
|
||||
System.exit(0);
|
||||
// 构建TableDef
|
||||
// CompilerUtils.compilerEntityTableDef(entityPath);
|
||||
// 重启
|
||||
// CoolApplication.restart();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.modules.base.entity.sys.BaseSysParamEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysParamMapper;
|
||||
import com.cool.modules.base.service.sys.BaseSysParamService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 系统参数配置
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BaseSysParamServiceImpl extends BaseServiceImpl<BaseSysParamMapper, BaseSysParamEntity>
|
||||
implements BaseSysParamService {
|
||||
|
||||
final private CoolCache coolCache;
|
||||
|
||||
@Override
|
||||
public String htmlByKey(String key) {
|
||||
String data = dataByKey(key);
|
||||
return "<html><body>" + (StrUtil.isNotEmpty(data) ? data : "key notfound")
|
||||
+ "</body></html>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dataByKey(String key) {
|
||||
BaseSysParamEntity baseSysParamEntity = coolCache.get(key, BaseSysParamEntity.class);
|
||||
if (baseSysParamEntity == null) {
|
||||
baseSysParamEntity = getOne(
|
||||
QueryWrapper.create().eq(BaseSysParamEntity::getKeyName, key));
|
||||
}
|
||||
if (baseSysParamEntity != null) {
|
||||
coolCache.set("param:" + baseSysParamEntity.getKeyName(), baseSysParamEntity);
|
||||
return baseSysParamEntity.getData();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAfter(JSONObject requestParams, BaseSysParamEntity baseSysParamEntity) {
|
||||
List<BaseSysParamEntity> list = this.list();
|
||||
list.forEach(e -> {
|
||||
coolCache.set("param:" + e.getKeyName(), e);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.util.SpringContextUtils;
|
||||
import com.cool.modules.base.entity.sys.*;
|
||||
import com.cool.modules.base.mapper.sys.*;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.row.Row;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysMenuEntityTableDef.BASE_SYS_MENU_ENTITY;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysRoleMenuEntityTableDef.BASE_SYS_ROLE_MENU_ENTITY;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysUserRoleEntityTableDef.BASE_SYS_USER_ROLE_ENTITY;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BaseSysPermsServiceImpl implements BaseSysPermsService {
|
||||
final private CoolCache coolCache;
|
||||
|
||||
final private BaseSysUserMapper baseSysUserMapper;
|
||||
|
||||
final private BaseSysUserRoleMapper baseSysUserRoleMapper;
|
||||
|
||||
final private BaseSysMenuMapper baseSysMenuMapper;
|
||||
|
||||
final private BaseSysRoleMenuMapper baseSysRoleMenuMapper;
|
||||
|
||||
final private BaseSysRoleDepartmentMapper baseSysRoleDepartmentMapper;
|
||||
|
||||
final private BaseSysDepartmentMapper baseSysDepartmentMapper;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Override
|
||||
public Long[] loginDepartmentIds() {
|
||||
String username = coolSecurityUtil.username();
|
||||
if (username.equals("admin")) {
|
||||
return baseSysDepartmentMapper.selectAll().stream().map(BaseSysDepartmentEntity::getId)
|
||||
.toArray(Long[]::new);
|
||||
} else {
|
||||
Long[] roleIds = getRoles(username);
|
||||
return baseSysRoleDepartmentMapper
|
||||
.selectListByQuery(
|
||||
QueryWrapper.create().in(BaseSysRoleDepartmentEntity::getRoleId, (Object) roleIds))
|
||||
.stream().map(BaseSysRoleDepartmentEntity::getDepartmentId).toArray(Long[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] getDepartmentIdsByRoleIds(Long[] roleIds) {
|
||||
return getLongs(roleIds);
|
||||
}
|
||||
|
||||
private Long[] getLongs(Long[] roleIds) {
|
||||
return baseSysRoleDepartmentMapper
|
||||
.selectListByQuery(QueryWrapper.create().in(BaseSysRoleDepartmentEntity::getRoleId, (Object) roleIds,
|
||||
roleIds != null && !CollUtil.toList(roleIds).contains(1L)))
|
||||
.stream().map(BaseSysRoleDepartmentEntity::getDepartmentId).toArray(Long[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] getDepartmentIdsByRoleIds(Long userId) {
|
||||
Long[] roleIds = getRoles(userId);
|
||||
return getLongs(roleIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPermsCache(Long userId) {
|
||||
Object result = coolCache.get("admin:perms:" + userId);
|
||||
if (ObjectUtil.isNotEmpty(result)) {
|
||||
return Convert.toStrArray(result);
|
||||
}
|
||||
return getPerms(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] getRoles(Long userId) {
|
||||
return getRoles(baseSysUserMapper.selectOneById(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] getRoles(String username) {
|
||||
return getRoles(
|
||||
baseSysUserMapper.selectOneByQuery(QueryWrapper.create().eq(BaseSysUserEntity::getUsername, username)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long[] getRoles(BaseSysUserEntity userEntity) {
|
||||
Long[] roleIds = null;
|
||||
if (!userEntity.getUsername().equals("admin")) {
|
||||
List<BaseSysUserRoleEntity> list = baseSysUserRoleMapper
|
||||
.selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userEntity.getId()));
|
||||
roleIds = list.stream().map(BaseSysUserRoleEntity::getRoleId).toArray(Long[]::new);
|
||||
if (Arrays.asList(roleIds).contains(1L)) {
|
||||
roleIds = null;
|
||||
}
|
||||
}
|
||||
return roleIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPerms(Long userId) {
|
||||
return getPerms(getRoles(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPerms(Long[] roleIds) {
|
||||
List<BaseSysMenuEntity> menus = getMenus(roleIds);
|
||||
Set<String> perms = new HashSet<>();
|
||||
String[] permsData = menus.stream().map(BaseSysMenuEntity::getPerms)
|
||||
.filter(itemPerms -> !StrUtil.isEmpty(itemPerms)).toArray(String[]::new);
|
||||
for (String permData : permsData) {
|
||||
perms.addAll(Arrays.asList(permData.split(",")));
|
||||
}
|
||||
return ArrayUtil.toArray(perms, String.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseSysMenuEntity> getMenus(Long[] roleIds) {
|
||||
if (CollUtil.toList(roleIds).contains(1L)) {
|
||||
roleIds = null;
|
||||
}
|
||||
if (roleIds != null && roleIds.length == 0) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
QueryWrapper queryWrapper = QueryWrapper.create().select(BASE_SYS_MENU_ENTITY.ALL_COLUMNS).from(BASE_SYS_MENU_ENTITY);
|
||||
if (ObjectUtil.isNotEmpty(roleIds)) {
|
||||
queryWrapper.join(BASE_SYS_ROLE_MENU_ENTITY).on(BASE_SYS_MENU_ENTITY.ID.eq(BASE_SYS_ROLE_MENU_ENTITY.MENU_ID)).and(BASE_SYS_ROLE_MENU_ENTITY.ROLE_ID.in((Object) roleIds));
|
||||
}
|
||||
return baseSysMenuMapper.selectListByQuery(queryWrapper.groupBy(BASE_SYS_MENU_ENTITY.ID).orderBy(BASE_SYS_MENU_ENTITY.ORDER_NUM, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseSysMenuEntity> getMenus(Long userId) {
|
||||
return getMenus(getRoles(userId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BaseSysMenuEntity> getMenus(String username) {
|
||||
BaseSysUserEntity sysUserEntity = baseSysUserMapper
|
||||
.selectOneByQuery(QueryWrapper.create().eq(BaseSysUserEntity::getUsername, username));
|
||||
return getMenus(sysUserEntity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAllPerms() {
|
||||
return getPerms((Long[]) null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object permmenu(Long adminUserId) {
|
||||
return Dict.create().set("menus", getMenus(adminUserId)).set("perms", getPerms(adminUserId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePerms(Long roleId, Long[] menuIdList, Long[] departmentIds) {
|
||||
// 更新菜单权限
|
||||
baseSysRoleMenuMapper.deleteByQuery(QueryWrapper.create().eq(BaseSysRoleMenuEntity::getRoleId, roleId));
|
||||
for (Long menuId : menuIdList) {
|
||||
BaseSysRoleMenuEntity roleMenuEntity = new BaseSysRoleMenuEntity();
|
||||
roleMenuEntity.setRoleId(roleId);
|
||||
roleMenuEntity.setMenuId(menuId);
|
||||
baseSysRoleMenuMapper.insert(roleMenuEntity);
|
||||
}
|
||||
// 更新部门权限
|
||||
baseSysRoleDepartmentMapper
|
||||
.deleteByQuery(QueryWrapper.create().eq(BaseSysRoleDepartmentEntity::getRoleId, roleId));
|
||||
for (Long departmentId : departmentIds) {
|
||||
BaseSysRoleDepartmentEntity roleDepartmentEntity = new BaseSysRoleDepartmentEntity();
|
||||
roleDepartmentEntity.setRoleId(roleId);
|
||||
roleDepartmentEntity.setDepartmentId(departmentId);
|
||||
baseSysRoleDepartmentMapper.insert(roleDepartmentEntity);
|
||||
}
|
||||
// 刷新对应角色用户的权限
|
||||
List<BaseSysUserRoleEntity> userRoles = baseSysUserRoleMapper
|
||||
.selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getRoleId, roleId));
|
||||
for (BaseSysUserRoleEntity userRole : userRoles) {
|
||||
refreshPerms(userRole.getUserId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserRole(Long userId, Long[] roleIdList) {
|
||||
baseSysUserRoleMapper.deleteByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userId));
|
||||
if (roleIdList == null) {
|
||||
roleIdList = new Long[0];
|
||||
}
|
||||
for (Long roleId : roleIdList) {
|
||||
BaseSysUserRoleEntity sysUserRoleEntity = new BaseSysUserRoleEntity();
|
||||
sysUserRoleEntity.setRoleId(roleId);
|
||||
sysUserRoleEntity.setUserId(userId);
|
||||
baseSysUserRoleMapper.insert(sysUserRoleEntity);
|
||||
}
|
||||
refreshPerms(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPerms(Long userId) {
|
||||
BaseSysUserEntity baseSysUserEntity = baseSysUserMapper.selectOneById(userId);
|
||||
if (baseSysUserEntity != null && baseSysUserEntity.getStatus() != 0) {
|
||||
SpringContextUtils.getBean(UserDetailsService.class).loadUserByUsername(baseSysUserEntity.getUsername());
|
||||
}
|
||||
if (baseSysUserEntity != null && baseSysUserEntity.getStatus() == 0) {
|
||||
coolSecurityUtil.logout(baseSysUserEntity.getId(), baseSysUserEntity.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void refreshPermsByMenuId(Long menuId) {
|
||||
// 刷新超管权限、 找出这个菜单的所有用户、 刷新用户权限
|
||||
BaseSysUserEntity admin = baseSysUserMapper
|
||||
.selectOneByQuery(QueryWrapper.create().eq(BaseSysUserEntity::getUsername, "admin"));
|
||||
refreshPerms(admin.getId());
|
||||
List<Row> list = baseSysRoleMenuMapper.selectRowsByQuery(QueryWrapper.create().select(BASE_SYS_USER_ROLE_ENTITY.USER_ID)
|
||||
.from(BASE_SYS_ROLE_MENU_ENTITY).leftJoin(BASE_SYS_USER_ROLE_ENTITY)
|
||||
.on(BASE_SYS_ROLE_MENU_ENTITY.ROLE_ID.eq(BASE_SYS_USER_ROLE_ENTITY.ROLE_ID)).and(BASE_SYS_ROLE_MENU_ENTITY.MENU_ID.eq(menuId, ObjectUtil.isNotEmpty(menuId))).groupBy(BASE_SYS_USER_ROLE_ENTITY.USER_ID));
|
||||
for (Row row : list) {
|
||||
refreshPerms(row.getLong("userId"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPermsByRoleId(Long roleId) {
|
||||
// 找出角色对应的所有用户
|
||||
List<BaseSysUserRoleEntity> list = baseSysUserRoleMapper
|
||||
.selectListByQuery(QueryWrapper.create().eq(BaseSysUserRoleEntity::getRoleId, roleId));
|
||||
list.forEach(e -> {
|
||||
refreshPerms(e.getUserId());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleDepartmentEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleMenuEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleDepartmentMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleMenuMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.base.service.sys.BaseSysRoleService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 系统角色
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class BaseSysRoleServiceImpl extends BaseServiceImpl<BaseSysRoleMapper, BaseSysRoleEntity>
|
||||
implements BaseSysRoleService {
|
||||
|
||||
final private BaseSysRoleMapper baseSysRoleMapper;
|
||||
|
||||
final private BaseSysRoleMenuMapper baseSysRoleMenuMapper;
|
||||
|
||||
final private BaseSysRoleDepartmentMapper baseSysRoleDepartmentMapper;
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Override
|
||||
public Object add(JSONObject requestParams, BaseSysRoleEntity entity) {
|
||||
BaseSysRoleEntity checkLabel = getOne(QueryWrapper.create().eq(BaseSysRoleEntity::getLabel, entity.getLabel()));
|
||||
if (checkLabel != null) {
|
||||
throw new CoolException("标识已存在");
|
||||
}
|
||||
entity.setUserId((coolSecurityUtil.userInfo(requestParams).getLong("userId")));
|
||||
return super.add(requestParams, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object info(Long id) {
|
||||
BaseSysRoleEntity roleEntity = getById(id);
|
||||
Long[] menuIdList = new Long[0];
|
||||
Long[] departmentIdList = new Long[0];
|
||||
if (roleEntity != null) {
|
||||
List<BaseSysRoleMenuEntity> list = baseSysRoleMenuMapper
|
||||
.selectListByQuery(QueryWrapper.create().eq(BaseSysRoleMenuEntity::getRoleId, id, !id.equals(1L)));
|
||||
menuIdList = list.stream().map(BaseSysRoleMenuEntity::getMenuId).toArray(Long[]::new);
|
||||
|
||||
List<BaseSysRoleDepartmentEntity> departmentEntities = baseSysRoleDepartmentMapper.selectListByQuery(
|
||||
QueryWrapper.create().eq(BaseSysRoleDepartmentEntity::getRoleId, id, !id.equals(1L)));
|
||||
|
||||
departmentIdList = departmentEntities.stream().map(BaseSysRoleDepartmentEntity::getDepartmentId)
|
||||
.toArray(Long[]::new);
|
||||
}
|
||||
return Dict.parse(roleEntity).set("menuIdList", menuIdList).set("departmentIdList", departmentIdList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAfter(JSONObject requestParams, BaseSysRoleEntity baseSysRoleEntity, ModifyEnum type) {
|
||||
if (type == ModifyEnum.DELETE) {
|
||||
Long[] ids = requestParams.get("ids", Long[].class);
|
||||
for (Long id : ids) {
|
||||
baseSysPermsService.refreshPermsByRoleId(id);
|
||||
}
|
||||
} else {
|
||||
baseSysPermsService.updatePerms(baseSysRoleEntity.getId(), requestParams.get("menuIdList", Long[].class),
|
||||
requestParams.get("departmentIdList", Long[].class));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object list(JSONObject requestParams, QueryWrapper queryWrapper) {
|
||||
return baseSysRoleMapper.selectListByQuery(queryWrapper.ne(BaseSysRoleEntity::getId, 1L).and(qw -> {
|
||||
qw.eq(BaseSysRoleEntity::getUserId, coolSecurityUtil.userInfo(requestParams).get("userId")).or(w -> {
|
||||
w.in(BaseSysRoleEntity::getId,
|
||||
(Object) coolSecurityUtil.userInfo(requestParams).get("roleIds", Long[].class));
|
||||
});
|
||||
}, !coolSecurityUtil.username().equals("admin")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.cool.modules.base.service.sys.impl;
|
||||
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysDepartmentEntityTableDef.BASE_SYS_DEPARTMENT_ENTITY;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysRoleEntityTableDef.BASE_SYS_ROLE_ENTITY;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysUserEntityTableDef.BASE_SYS_USER_ENTITY;
|
||||
import static com.cool.modules.base.entity.sys.table.BaseSysUserRoleEntityTableDef.BASE_SYS_USER_ROLE_ENTITY;
|
||||
import static com.mybatisflex.core.query.QueryMethods.groupConcat;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.crypto.digest.MD5;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.ModifyEnum;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.modules.base.entity.sys.BaseSysDepartmentEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysDepartmentMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.base.service.sys.BaseSysUserService;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.update.UpdateChain;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 系统用户
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BaseSysUserServiceImpl extends BaseServiceImpl<BaseSysUserMapper, BaseSysUserEntity>
|
||||
implements BaseSysUserService {
|
||||
|
||||
final private CoolCache coolCache;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
final private BaseSysPermsService baseSysPermsService;
|
||||
|
||||
final private BaseSysDepartmentMapper baseSysDepartmentMapper;
|
||||
|
||||
@Override
|
||||
public Object page(JSONObject requestParams, Page<BaseSysUserEntity> page, QueryWrapper qw) {
|
||||
String keyWord = requestParams.getStr("keyWord");
|
||||
Integer status = requestParams.getInt("status");
|
||||
Long[] departmentIds = requestParams.get("departmentIds", Long[].class);
|
||||
JSONObject tokenInfo = coolSecurityUtil.userInfo(requestParams);
|
||||
// 用户的部门权限
|
||||
Long[] permsDepartmentArr = coolCache.get("admin:department:" + tokenInfo.get("userId"),
|
||||
Long[].class);
|
||||
|
||||
qw.select(BASE_SYS_USER_ENTITY.ALL_COLUMNS,
|
||||
groupConcat(BASE_SYS_ROLE_ENTITY.NAME).as("roleName"),
|
||||
BASE_SYS_DEPARTMENT_ENTITY.NAME.as("departmentName"))
|
||||
.from(BASE_SYS_USER_ENTITY).leftJoin(BASE_SYS_USER_ROLE_ENTITY)
|
||||
.on(BASE_SYS_USER_ENTITY.ID.eq(BASE_SYS_USER_ROLE_ENTITY.USER_ID))
|
||||
.leftJoin(BASE_SYS_ROLE_ENTITY)
|
||||
.on(BASE_SYS_USER_ROLE_ENTITY.USER_ID.eq(BASE_SYS_ROLE_ENTITY.ID))
|
||||
.leftJoin(BASE_SYS_DEPARTMENT_ENTITY)
|
||||
.on(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.eq(BASE_SYS_DEPARTMENT_ENTITY.ID));
|
||||
|
||||
// 不显示admin用户
|
||||
qw.and(BASE_SYS_USER_ENTITY.USERNAME.ne("admin"));
|
||||
// 筛选部门
|
||||
qw.and(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.in(departmentIds,
|
||||
ArrayUtil.isNotEmpty(departmentIds)));
|
||||
// 筛选状态
|
||||
qw.and(BASE_SYS_USER_ENTITY.STATUS.eq(status, status != null));
|
||||
// 搜索关键字
|
||||
if (StrUtil.isNotEmpty(keyWord)) {
|
||||
qw.and(BASE_SYS_USER_ENTITY.NAME.like(keyWord)
|
||||
.or(BASE_SYS_USER_ENTITY.USERNAME.like(keyWord)));
|
||||
}
|
||||
// 过滤部门权限
|
||||
qw.and(BASE_SYS_USER_ENTITY.DEPARTMENT_ID.in(
|
||||
permsDepartmentArr == null || permsDepartmentArr.length == 0 ? new Long[]{null}
|
||||
: permsDepartmentArr,
|
||||
!coolSecurityUtil.username().equals("admin")));
|
||||
|
||||
qw.groupBy(BASE_SYS_USER_ENTITY.ID);
|
||||
return mapper.paginateWithRelations(page, qw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void personUpdate(Long userId, Dict body) {
|
||||
BaseSysUserEntity userEntity = getById(userId);
|
||||
CoolPreconditions.checkEmpty(userEntity, "用户不存在");
|
||||
userEntity.setNickName(body.getStr("nickName"));
|
||||
// 修改密码
|
||||
if (StrUtil.isNotEmpty(body.getStr("password"))) {
|
||||
userEntity.setPassword(MD5.create().digestHex(body.getStr("password")));
|
||||
userEntity.setPasswordV(userEntity.getPasswordV() + 1);
|
||||
coolCache.set("admin:passwordVersion:" + userId, userEntity.getPasswordV());
|
||||
}
|
||||
updateById(userEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void move(Long departmentId, Long[] userIds) {
|
||||
UpdateChain.of(BaseSysUserEntity.class)
|
||||
.set(BaseSysUserEntity::getDepartmentId, departmentId)
|
||||
.in(BaseSysUserEntity::getId, (Object) userIds).update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long add(JSONObject requestParams, BaseSysUserEntity entity) {
|
||||
BaseSysUserEntity check = getOne(
|
||||
QueryWrapper.create().eq(BaseSysUserEntity::getUsername, entity.getUsername()));
|
||||
CoolPreconditions.check(check != null, "用户名已存在");
|
||||
entity.setPassword(MD5.create().digestHex(entity.getPassword()));
|
||||
super.add(requestParams, entity);
|
||||
return entity.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(JSONObject requestParams, BaseSysUserEntity entity) {
|
||||
CoolPreconditions.check(
|
||||
StrUtil.isNotEmpty(entity.getUsername()) && entity.getUsername().equals("admin"),
|
||||
"非法操作");
|
||||
BaseSysUserEntity userEntity = getById(entity.getId());
|
||||
if (StrUtil.isNotEmpty(entity.getPassword())) {
|
||||
entity.setPasswordV(entity.getPasswordV() + 1);
|
||||
entity.setPassword(MD5.create().digestHex(entity.getPassword()));
|
||||
coolCache.set("admin:passwordVersion:" + entity.getId(), entity.getPasswordV());
|
||||
} else {
|
||||
entity.setPassword(userEntity.getPassword());
|
||||
entity.setPasswordV(userEntity.getPasswordV());
|
||||
}
|
||||
// 被禁用
|
||||
if (entity.getStatus() == 0) {
|
||||
coolSecurityUtil.logout(entity);
|
||||
}
|
||||
return super.update(requestParams, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyAfter(JSONObject requestParams, BaseSysUserEntity baseSysUserEntity,
|
||||
ModifyEnum type) {
|
||||
if (type != ModifyEnum.DELETE && requestParams.get("roleIdList", Long[].class) != null) {
|
||||
// 刷新权限
|
||||
baseSysPermsService.updateUserRole(baseSysUserEntity.getId(),
|
||||
requestParams.get("roleIdList", Long[].class));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object info(Long id) {
|
||||
BaseSysUserEntity userEntity = getById(id);
|
||||
Long[] roleIdList = baseSysPermsService.getRoles(id);
|
||||
BaseSysDepartmentEntity departmentEntity = baseSysDepartmentMapper.selectOneById(
|
||||
userEntity.getDepartmentId());
|
||||
userEntity.setPassword(null);
|
||||
return Dict.parse(userEntity).set("roleIdList", roleIdList).set("departmentName",
|
||||
departmentEntity != null ? departmentEntity.getName() : null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.cool.modules.dict.controller.admin;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.dict.entity.DictInfoEntity;
|
||||
import com.cool.modules.dict.entity.table.DictInfoEntityTableDef;
|
||||
import com.cool.modules.dict.service.DictInfoService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 字典信息
|
||||
*/
|
||||
@Tag(name = "字典信息", description = "字典信息")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" })
|
||||
public class AdminDictInfoController extends BaseController<DictInfoService, DictInfoEntity> {
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setListOption(createOp().fieldEq(DictInfoEntityTableDef.DICT_INFO_ENTITY.TYPE_ID)
|
||||
.keyWordLikeFields(DictInfoEntityTableDef.DICT_INFO_ENTITY.NAME)
|
||||
.queryWrapper(QueryWrapper.create().orderBy(DictInfoEntityTableDef.DICT_INFO_ENTITY.CREATE_TIME, false)));
|
||||
}
|
||||
|
||||
@Operation(summary = "获得字典数据", description = "获得字典数据信息")
|
||||
@PostMapping("/data")
|
||||
public R data(@RequestBody Dict body) {
|
||||
return R.ok(this.service.data(body.get("types", null)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cool.modules.dict.controller.admin;
|
||||
|
||||
import static com.cool.modules.dict.entity.table.DictTypeEntityTableDef.DICT_TYPE_ENTITY;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.dict.entity.DictTypeEntity;
|
||||
import com.cool.modules.dict.service.DictTypeService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@Tag(name = "字典类型", description = "字典类型")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"})
|
||||
public class AdminDictTypeController extends BaseController<DictTypeService, DictTypeEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(
|
||||
createOp().select(DICT_TYPE_ENTITY.ID, DICT_TYPE_ENTITY.KEY, DICT_TYPE_ENTITY.NAME));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.cool.modules.dict.controller.app;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.dict.entity.DictInfoEntity;
|
||||
import com.cool.modules.dict.service.DictInfoService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 字典信息
|
||||
*/
|
||||
@Tag(name = "字典信息", description = "字典信息")
|
||||
@CoolRestController(api = {})
|
||||
public class AppDictInfoController extends BaseController<DictInfoService, DictInfoEntity> {
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
|
||||
}
|
||||
|
||||
@Operation(summary = "获得字典数据", description = "获得字典数据信息")
|
||||
@PostMapping("/data")
|
||||
public R data(@RequestBody Dict body) {
|
||||
return R.ok(this.service.data(Convert.toList(String.class, body.get("types"))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.cool.modules.dict.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "dict_info", comment = "字典信息")
|
||||
public class DictInfoEntity extends BaseEntity<DictInfoEntity> {
|
||||
|
||||
@ColumnDefine(comment = "类型ID", notNull = true)
|
||||
private Long typeId;
|
||||
|
||||
@ColumnDefine(comment = "父ID")
|
||||
private Long parentId;
|
||||
|
||||
@ColumnDefine(comment = "名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "值")
|
||||
private String value;
|
||||
|
||||
@ColumnDefine(comment = "排序", defaultValue = "0")
|
||||
private Integer orderNum;
|
||||
|
||||
@ColumnDefine(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.cool.modules.dict.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "dict_type", comment = "字典类型")
|
||||
public class DictTypeEntity extends BaseEntity<DictTypeEntity> {
|
||||
|
||||
@ColumnDefine(comment = "名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "标识", notNull = true)
|
||||
@UniIndex
|
||||
private String key;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.dict.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.dict.entity.DictInfoEntity;
|
||||
|
||||
/**
|
||||
* 字典信息
|
||||
*/
|
||||
public interface DictInfoMapper extends BaseMapper<DictInfoEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.dict.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.dict.entity.DictTypeEntity;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
public interface DictTypeMapper extends BaseMapper<DictTypeEntity> {
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.cool.modules.dict.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.dict.entity.DictInfoEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 字典信息
|
||||
*/
|
||||
public interface DictInfoService extends BaseService<DictInfoEntity> {
|
||||
/**
|
||||
* 字典数据
|
||||
*
|
||||
* @param types 字典类型
|
||||
* @return
|
||||
*/
|
||||
Object data(List<String> types);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.dict.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.dict.entity.DictTypeEntity;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
public interface DictTypeService extends BaseService<DictTypeEntity> {
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.cool.modules.dict.service.impl;
|
||||
|
||||
import static com.cool.modules.dict.entity.table.DictInfoEntityTableDef.DICT_INFO_ENTITY;
|
||||
import static com.cool.modules.dict.entity.table.DictTypeEntityTableDef.DICT_TYPE_ENTITY;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.dict.entity.DictInfoEntity;
|
||||
import com.cool.modules.dict.entity.DictTypeEntity;
|
||||
import com.cool.modules.dict.mapper.DictInfoMapper;
|
||||
import com.cool.modules.dict.mapper.DictTypeMapper;
|
||||
import com.cool.modules.dict.service.DictInfoService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 字典信息
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DictInfoServiceImpl extends BaseServiceImpl<DictInfoMapper, DictInfoEntity> implements
|
||||
DictInfoService {
|
||||
|
||||
final private DictTypeMapper dictTypeMapper;
|
||||
|
||||
@Override
|
||||
public Object data(List<String> types) {
|
||||
Dict result = Dict.create();
|
||||
QueryWrapper find = QueryWrapper.create();
|
||||
find.select(DICT_TYPE_ENTITY.ID, DICT_TYPE_ENTITY.KEY,
|
||||
DICT_TYPE_ENTITY.NAME);
|
||||
if (CollectionUtil.isNotEmpty(types)) {
|
||||
find.and(DICT_TYPE_ENTITY.KEY.in(types));
|
||||
}
|
||||
List<DictTypeEntity> typeData = dictTypeMapper.selectListByQuery(find);
|
||||
if (typeData.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
List<DictInfoEntity> infos = this.list(QueryWrapper.create()
|
||||
.select(DictInfoEntity::getId, DictInfoEntity::getName, DictInfoEntity::getTypeId,
|
||||
DictInfoEntity::getParentId, DictInfoEntity::getValue)
|
||||
.in(DictInfoEntity::getTypeId,
|
||||
typeData.stream().map(DictTypeEntity::getId).collect(Collectors.toList()))
|
||||
.orderBy(DICT_INFO_ENTITY.ORDER_NUM.getName(), DICT_INFO_ENTITY.CREATE_TIME.getName()));
|
||||
typeData.forEach(item -> {
|
||||
List<Dict> datas = new ArrayList<>();
|
||||
infos.stream().filter(d -> d.getTypeId().equals(item.getId())).toList().forEach(d -> {
|
||||
Dict data = Dict.create();
|
||||
data.set("typeId", d.getTypeId());
|
||||
data.set("parentId", d.getParentId());
|
||||
data.set("name", d.getName());
|
||||
data.set("id", d.getId());
|
||||
data.set("value", StrUtil.isEmpty(d.getValue()) ? null : d.getValue());
|
||||
try {
|
||||
data.set("value", Integer.parseInt(d.getValue()));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
datas.add(data);
|
||||
});
|
||||
result.set(item.getKey(), datas);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Long... ids) {
|
||||
super.delete(ids);
|
||||
for (Long id : ids) {
|
||||
this.delDictChild(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除子菜单
|
||||
*
|
||||
* @param id 删除的菜单ID
|
||||
*/
|
||||
private void delDictChild(Long id) {
|
||||
List<DictInfoEntity> delDict = list(
|
||||
QueryWrapper.create().eq(DictInfoEntity::getParentId, id));
|
||||
if (CollectionUtil.isEmpty(delDict)) {
|
||||
return;
|
||||
}
|
||||
Long[] ids = delDict.stream().map(DictInfoEntity::getId).toArray(Long[]::new);
|
||||
if (ArrayUtil.isNotEmpty(ids)) {
|
||||
delete(ids);
|
||||
for (Long delId : ids) {
|
||||
this.delDictChild(delId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.cool.modules.dict.service.impl;
|
||||
|
||||
import static com.cool.modules.dict.entity.table.DictInfoEntityTableDef.DICT_INFO_ENTITY;
|
||||
import static com.cool.modules.dict.entity.table.DictTypeEntityTableDef.DICT_TYPE_ENTITY;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.dict.entity.DictTypeEntity;
|
||||
import com.cool.modules.dict.mapper.DictInfoMapper;
|
||||
import com.cool.modules.dict.mapper.DictTypeMapper;
|
||||
import com.cool.modules.dict.service.DictTypeService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 字典类型
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class DictTypeServiceImpl extends BaseServiceImpl<DictTypeMapper, DictTypeEntity> implements
|
||||
DictTypeService {
|
||||
|
||||
final private DictInfoMapper dictInfoMapper;
|
||||
|
||||
@Override
|
||||
public List<DictTypeEntity> list(QueryWrapper queryWrapper) {
|
||||
return super.list(
|
||||
queryWrapper.select(DICT_TYPE_ENTITY.ID, DICT_TYPE_ENTITY.KEY,
|
||||
DICT_TYPE_ENTITY.NAME));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean delete(Long... ids) {
|
||||
super.delete(ids);
|
||||
return dictInfoMapper.deleteByQuery(
|
||||
QueryWrapper.create().and(DICT_INFO_ENTITY.TYPE_ID.in((Object) ids))) > 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.cool.modules.plugin.controller.admin;
|
||||
|
||||
import static com.cool.modules.plugin.entity.table.PluginInfoEntityTableDef.PLUGIN_INFO_ENTITY;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.annotation.IgnoreRecycleData;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.plugin.service.CoolPluginService;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.core.util.EntityUtils;
|
||||
import com.cool.modules.plugin.entity.PluginInfoEntity;
|
||||
import com.cool.modules.plugin.service.PluginInfoService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Tag(name = "插件信息", description = "插件信息")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "list", "info"})
|
||||
@RequiredArgsConstructor
|
||||
public class AdminPluginInfoController extends BaseController<PluginInfoService, PluginInfoEntity> {
|
||||
|
||||
final private CoolPluginService coolPluginService;
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
|
||||
setPageOption(createOp().queryWrapper(
|
||||
QueryWrapper.create().orderBy(PLUGIN_INFO_ENTITY.UPDATE_TIME, false))
|
||||
.select(EntityUtils.getFieldNamesWithSuperClass(PLUGIN_INFO_ENTITY.DEFAULT_COLUMNS,
|
||||
PLUGIN_INFO_ENTITY.JAR_FILE.getName())));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "修改", description = "根据ID修改")
|
||||
@PostMapping("/update")
|
||||
protected R update(@RequestBody PluginInfoEntity t,
|
||||
@RequestAttribute() JSONObject requestParams) {
|
||||
coolPluginService.updatePlugin(t);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "安装插件")
|
||||
@PostMapping(value = "/install", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
||||
public R install(
|
||||
@RequestParam(value = "files") @Parameter(description = "文件") MultipartFile[] files,
|
||||
@RequestParam(value = "force") @Parameter(description = "是否强制安装") boolean force) {
|
||||
coolPluginService.install(files[0], force);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Operation(summary = "卸载插件")
|
||||
@PostMapping("/delete")
|
||||
@IgnoreRecycleData()
|
||||
public R delete(HttpServletRequest request, @RequestBody Map<String, Object> params,
|
||||
@RequestAttribute() JSONObject requestParams) {
|
||||
coolPluginService.uninstall(Convert.toLongArray(getIds(params))[0]);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.cool.modules.plugin.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.cool.core.config.PluginJson;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.Fastjson2TypeHandler;
|
||||
import com.tangzc.autotable.annotation.Ignore;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "plugin_info", comment = "插件信息")
|
||||
public class PluginInfoEntity extends BaseEntity<PluginInfoEntity> {
|
||||
|
||||
@ColumnDefine(comment = "名称")
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "简介")
|
||||
private String description;
|
||||
|
||||
@UniIndex
|
||||
@ColumnDefine(comment = "实例对象")
|
||||
private String key;
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "Hook", length = 50)
|
||||
private String hook;
|
||||
|
||||
@ColumnDefine(comment = "描述", type = "text")
|
||||
private String readme;
|
||||
|
||||
@ColumnDefine(comment = "版本")
|
||||
private String version;
|
||||
|
||||
@ColumnDefine(comment = "Logo(base64)", type = "text", notNull = true)
|
||||
private String logo;
|
||||
|
||||
@ColumnDefine(comment = "作者")
|
||||
private String author;
|
||||
|
||||
@ColumnDefine(comment = "状态 0-禁用 1-启用", defaultValue = "1")
|
||||
private Integer status;
|
||||
|
||||
@ColumnDefine(comment = "插件的plugin.json", type = "json", notNull = true)
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private PluginJson pluginJson;
|
||||
|
||||
@ColumnDefine(comment = "jar二进制文件", type = "longblob", notNull = true)
|
||||
private byte[] jarFile;
|
||||
|
||||
@ColumnDefine(comment = "配置", type = "json")
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private Map<String, Object> config;
|
||||
|
||||
@Ignore
|
||||
@Column(ignore = true)
|
||||
public String keyName;
|
||||
|
||||
public String getKeyName() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cool.modules.plugin.mapper;
|
||||
|
||||
import com.cool.modules.plugin.entity.PluginInfoEntity;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
|
||||
public interface PluginInfoMapper extends BaseMapper<PluginInfoEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.plugin.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.plugin.entity.PluginInfoEntity;
|
||||
|
||||
public interface PluginInfoService extends BaseService<PluginInfoEntity> {
|
||||
PluginInfoEntity getByKeyNoJarFile(String key);
|
||||
|
||||
PluginInfoEntity getPluginInfoEntityByHookNoJarFile(String hook);
|
||||
|
||||
PluginInfoEntity getPluginInfoEntityByIdNoJarFile(Long id);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.cool.modules.plugin.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.util.EntityUtils;
|
||||
import com.cool.modules.plugin.entity.PluginInfoEntity;
|
||||
import com.cool.modules.plugin.mapper.PluginInfoMapper;
|
||||
import com.cool.modules.plugin.service.PluginInfoService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static com.cool.modules.plugin.entity.table.PluginInfoEntityTableDef.PLUGIN_INFO_ENTITY;
|
||||
|
||||
/**
|
||||
* 插件信息服务类
|
||||
*/
|
||||
@Service
|
||||
public class PluginInfoServiceImpl extends BaseServiceImpl<PluginInfoMapper, PluginInfoEntity>
|
||||
implements PluginInfoService {
|
||||
|
||||
/**
|
||||
* 通过key获取插件信息,不带jar二进制
|
||||
*/
|
||||
@Override
|
||||
public PluginInfoEntity getByKeyNoJarFile(String key) {
|
||||
QueryWrapper queryWrapper = getPluginInfoEntityQueryWrapper();
|
||||
queryWrapper.and(PLUGIN_INFO_ENTITY.KEY.eq(key));
|
||||
return getOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过hook获取插件信息,不带jar二进制
|
||||
*/
|
||||
@Override
|
||||
public PluginInfoEntity getPluginInfoEntityByHookNoJarFile(String hook) {
|
||||
QueryWrapper queryWrapper = getPluginInfoEntityQueryWrapper().and(PLUGIN_INFO_ENTITY.HOOK.eq(hook))
|
||||
.and(PLUGIN_INFO_ENTITY.STATUS.eq(1)).limit(1);
|
||||
return getOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id获取插件信息,不带jar二进制
|
||||
*/
|
||||
@Override
|
||||
public PluginInfoEntity getPluginInfoEntityByIdNoJarFile(Long id) {
|
||||
QueryWrapper queryWrapper = getPluginInfoEntityQueryWrapper().and(PLUGIN_INFO_ENTITY.ID.eq(id));
|
||||
return getOne(queryWrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取查询对象,排除掉 jar二进制
|
||||
*/
|
||||
private QueryWrapper getPluginInfoEntityQueryWrapper() {
|
||||
return QueryWrapper.create().select(EntityUtils.getFieldNamesWithSuperClass(PLUGIN_INFO_ENTITY.DEFAULT_COLUMNS, PLUGIN_INFO_ENTITY.JAR_FILE.getName()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//package com.cool.modules.recycle.aop;
|
||||
//
|
||||
//import org.springframework.context.annotation.Bean;
|
||||
//import org.springframework.context.annotation.Configuration;
|
||||
//import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
//
|
||||
//@Configuration
|
||||
//@EnableAspectJAutoProxy
|
||||
//public class AopConfig {
|
||||
//
|
||||
// @Bean
|
||||
// public DeleteAspect deleteAspect() {
|
||||
// return new DeleteAspect();
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.cool.modules.recycle.aop;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.IgnoreRecycleData;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.base.security.CoolSecurityUtil;
|
||||
import com.cool.modules.recycle.entity.RecycleDataEntity;
|
||||
import com.cool.modules.recycle.service.RecycleDataService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 数据删除前拦截
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class DeleteAspect {
|
||||
|
||||
final private RecycleDataService recycleDataService;
|
||||
|
||||
final private CoolSecurityUtil coolSecurityUtil;
|
||||
|
||||
@Around(value = "execution(* com.cool.core.base.BaseController.delete*(..)) && args(request, params, requestParams)", argNames = "joinPoint,request,params,requestParams")
|
||||
public Object aroundAdvice(ProceedingJoinPoint joinPoint, HttpServletRequest request,
|
||||
Map<String, Object> params,
|
||||
JSONObject requestParams) throws Throwable {
|
||||
Method currentMethod = getCurrentMethod(joinPoint);
|
||||
if (Objects.nonNull(currentMethod) && currentMethod.isAnnotationPresent(
|
||||
IgnoreRecycleData.class)) {
|
||||
// 忽略回收站记录
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
List<Object> list = null;
|
||||
String className = null;
|
||||
try {
|
||||
log.info("数据删除前拦截");
|
||||
// 可以在目标方法执行前进行一些操作
|
||||
BaseController baseController = (BaseController) joinPoint.getTarget();
|
||||
BaseService service = baseController.getService();
|
||||
className = (baseController.currentEntityClass()).getName();
|
||||
QueryWrapper queryWrapper = new QueryWrapper();
|
||||
Object ids = params.get("ids");
|
||||
if (!(ids instanceof ArrayList)) {
|
||||
ids = ids.toString().split(",");
|
||||
}
|
||||
List<Long> idList = Convert.toList(Long.class, ids);
|
||||
queryWrapper.in("id", (Object) Convert.toLongArray(idList));
|
||||
list = service.list(queryWrapper);
|
||||
} catch (Exception e) {
|
||||
log.error("数据删除前拦截获取数据详情信息失败", e);
|
||||
}
|
||||
|
||||
Object result = joinPoint.proceed();
|
||||
if (ObjUtil.isNotEmpty(list)) {
|
||||
RecycleDataEntity recycleDataEntity = new RecycleDataEntity();
|
||||
recycleDataEntity.setUrl(request.getRequestURI());
|
||||
recycleDataEntity.setUserName(coolSecurityUtil.username());
|
||||
recycleDataEntity
|
||||
.setUserId(Long.parseLong(
|
||||
String.valueOf(coolSecurityUtil.userInfo(requestParams).get("userId"))));
|
||||
recycleDataEntity.setParams(params);
|
||||
recycleDataEntity.setData(list);
|
||||
recycleDataEntity.setParams(params);
|
||||
RecycleDataEntity.EntityInfo entityInfo = new RecycleDataEntity.EntityInfo();
|
||||
entityInfo.setEntityClassName(className);
|
||||
recycleDataEntity.setEntityInfo(entityInfo);
|
||||
recycleDataEntity.setCount(recycleDataEntity.getData().size());
|
||||
|
||||
log.info("数据进入回收站 {}", recycleDataService.add(recycleDataEntity));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Method getCurrentMethod(JoinPoint joinPoint) {
|
||||
String methodName = joinPoint.getSignature().getName();
|
||||
Object[] args = joinPoint.getArgs();
|
||||
Method[] methods = joinPoint.getTarget().getClass().getMethods();
|
||||
|
||||
for (Method method : methods) {
|
||||
if (method.getName().equals(methodName) && method.getParameterCount() == args.length) {
|
||||
boolean isSameMethod = true;
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (!parameterTypes[i].isAssignableFrom(args[i].getClass())) {
|
||||
isSameMethod = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isSameMethod) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.cool.modules.recycle.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.recycle.entity.RecycleDataEntity;
|
||||
import com.cool.modules.recycle.entity.table.RecycleDataEntityTableDef;
|
||||
import com.cool.modules.recycle.service.RecycleDataService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 数据回收站
|
||||
*/
|
||||
@Tag(name = "数据回收站", description = "数据回收站")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" })
|
||||
@RequiredArgsConstructor
|
||||
public class AdminRecycleDataController extends BaseController<RecycleDataService, RecycleDataEntity> {
|
||||
final private RecycleDataService recycleDataService;
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setListOption(createOp().queryWrapper(QueryWrapper.create().orderBy(RecycleDataEntityTableDef.RECYCLE_DATA_ENTITY.CREATE_TIME, false)));
|
||||
}
|
||||
|
||||
@Operation(summary = "恢复数据", description = "恢复数据")
|
||||
@PostMapping("/restore")
|
||||
public R restore(@RequestBody Map<String, Object> params) {
|
||||
return R.ok(this.service.restore(getIds(params)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.cool.modules.recycle.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.mybatisflex.core.handler.Fastjson2TypeHandler;
|
||||
import com.tangzc.autotable.annotation.Ignore;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 数据回收站 软删除的时候数据会回收到该表
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "recycle_data", comment = "数据回收站表")
|
||||
public class RecycleDataEntity extends BaseEntity<RecycleDataEntity> {
|
||||
|
||||
@ColumnDefine(comment = "表信息", type = "json")
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private EntityInfo entityInfo;
|
||||
|
||||
@Index()
|
||||
@ColumnDefine(comment = "操作人", notNull = true)
|
||||
private Long userId;
|
||||
|
||||
@ColumnDefine(comment = "被删除的数据", type = "json")
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private List<Object> data;
|
||||
|
||||
@ColumnDefine(comment = "请求的接口", notNull = true)
|
||||
private String url;
|
||||
|
||||
@ColumnDefine(comment = "请求参数", type = "json", notNull = true)
|
||||
@Column(typeHandler = Fastjson2TypeHandler.class)
|
||||
private Map<String, Object> params;
|
||||
|
||||
@ColumnDefine(comment = "删除数据条数", defaultValue = "1")
|
||||
private Integer count;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
public static class EntityInfo {
|
||||
|
||||
// entityClassName
|
||||
public String entityClassName;
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Column(ignore = true) // 操作人名称
|
||||
public String userName;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.recycle.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.recycle.entity.RecycleDataEntity;
|
||||
|
||||
public interface RecycleDataMapper extends BaseMapper<RecycleDataEntity> {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.cool.modules.recycle.service;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.recycle.entity.RecycleDataEntity;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface RecycleDataService extends BaseService<RecycleDataEntity> {
|
||||
Object page(JSONObject requestParams, Page<RecycleDataEntity> page, QueryWrapper queryWrapper);
|
||||
|
||||
/**
|
||||
* 恢复数据
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
Boolean restore(List<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package com.cool.modules.recycle.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.base.service.MapperProviderService;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserEntity;
|
||||
import com.cool.modules.base.service.sys.BaseSysUserService;
|
||||
import com.cool.modules.recycle.entity.RecycleDataEntity;
|
||||
import com.cool.modules.recycle.mapper.RecycleDataMapper;
|
||||
import com.cool.modules.recycle.service.RecycleDataService;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 数据回收站
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RecycleDataServiceImpl extends BaseServiceImpl<RecycleDataMapper, RecycleDataEntity>
|
||||
implements RecycleDataService {
|
||||
|
||||
final private BaseSysUserService baseSysUserService;
|
||||
|
||||
final private MapperProviderService mapperProviderService;
|
||||
|
||||
@Override
|
||||
public Object page(JSONObject requestParams, Page<RecycleDataEntity> page,
|
||||
QueryWrapper queryWrapper) {
|
||||
String keyWord = requestParams.getStr("keyWord");
|
||||
if (ObjUtil.isNotEmpty(keyWord)) {
|
||||
List<Long> list = baseSysUserService
|
||||
.list(queryWrapper.select(BaseSysUserEntity::getId)
|
||||
.like(BaseSysUserEntity::getName, keyWord))
|
||||
.stream().map(BaseSysUserEntity::getId).toList();
|
||||
queryWrapper.like(RecycleDataEntity::getUrl, keyWord).or(w -> {
|
||||
w.in(RecycleDataEntity::getUserId, list, ObjUtil.isNotEmpty(list));
|
||||
});
|
||||
}
|
||||
Page<RecycleDataEntity> iPage = page(page, queryWrapper);
|
||||
List<RecycleDataEntity> records = iPage.getRecords();
|
||||
List<Long> list = records.stream().map(RecycleDataEntity::getUserId)
|
||||
.filter(ObjUtil::isNotEmpty).toList();
|
||||
|
||||
if (ObjUtil.isNotEmpty(list)) {
|
||||
Map<Long, String> map = baseSysUserService
|
||||
.list(QueryWrapper.create()
|
||||
.select(BaseSysUserEntity::getId, BaseSysUserEntity::getName)
|
||||
.in(BaseSysUserEntity::getId, list))
|
||||
.stream()
|
||||
.collect(Collectors.toMap(BaseSysUserEntity::getId, BaseSysUserEntity::getName));
|
||||
records.forEach(o -> {
|
||||
if (map.containsKey(o.getUserId())) {
|
||||
o.setUserName(map.get(o.getUserId()));
|
||||
}
|
||||
});
|
||||
}
|
||||
return iPage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean restore(List<Long> ids) {
|
||||
if (ObjUtil.isEmpty(ids)) {
|
||||
return false;
|
||||
}
|
||||
List<RecycleDataEntity> list = list(
|
||||
QueryWrapper.create().in(RecycleDataEntity::getId, ids));
|
||||
list.forEach(o -> {
|
||||
// 处理恢复数据
|
||||
boolean flag = handlerRestore(o);
|
||||
if (flag) {
|
||||
// 删除回收站记录
|
||||
o.removeById();
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理数据恢复
|
||||
*/
|
||||
private boolean handlerRestore(RecycleDataEntity recycleDataEntity) {
|
||||
RecycleDataEntity.EntityInfo entityInfo = recycleDataEntity.getEntityInfo();
|
||||
try {
|
||||
Class<?> entityClass = ClassUtil.loadClass(entityInfo.getEntityClassName());
|
||||
List<Object> records = recycleDataEntity.getData();
|
||||
BaseMapper<?> baseMapper = mapperProviderService.getMapperByEntityClass(
|
||||
entityClass);
|
||||
// 插入数据
|
||||
List insertList = new ArrayList<>();
|
||||
for (Object record : records) {
|
||||
Object entity = JSONUtil.toBean(JSONUtil.parseObj(record), entityClass);
|
||||
Method getIdMethod = entityClass.getMethod("getId");
|
||||
Object id = getIdMethod.invoke(entity);
|
||||
if (baseMapper.selectOneById((Long) id) == null) {
|
||||
insertList.add(entity);
|
||||
}
|
||||
}
|
||||
baseMapper.insertBatch(insertList);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
log.error("恢复数据失败", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.cool.modules.space.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.space.entity.SpaceInfoEntity;
|
||||
import com.cool.modules.space.service.SpaceInfoService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import static com.cool.modules.space.entity.table.SpaceInfoEntityTableDef.SPACE_INFO_ENTITY;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
@Tag(name = "文件空间信息", description = "文件空间信息")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" })
|
||||
public class AdminSpaceInfoController extends BaseController<SpaceInfoService, SpaceInfoEntity> {
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp().fieldEq(SPACE_INFO_ENTITY.TYPE, SPACE_INFO_ENTITY.CLASSIFY_ID));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.cool.modules.space.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.space.entity.SpaceTypeEntity;
|
||||
import com.cool.modules.space.service.SpaceTypeService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
@Tag(name = "文件空间信息", description = "文件空间信息")
|
||||
@CoolRestController(api = { "add", "delete", "update", "page", "list", "info" })
|
||||
public class AdminSpaceTypeController extends BaseController<SpaceTypeService, SpaceTypeEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.cool.modules.space.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.tangzc.autotable.annotation.Ignore;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "space_info", comment = "文件空间信息")
|
||||
public class SpaceInfoEntity extends BaseEntity<SpaceInfoEntity> {
|
||||
@ColumnDefine(comment = "地址", notNull = true)
|
||||
private String url;
|
||||
|
||||
@ColumnDefine(comment = "类型", notNull = true)
|
||||
private String type;
|
||||
|
||||
@ColumnDefine(comment = "分类ID", type = "tinyint")
|
||||
private Integer classifyId;
|
||||
|
||||
@Index()
|
||||
@ColumnDefine(comment = "文件id")
|
||||
private String fileId;
|
||||
|
||||
@ColumnDefine(comment = "文件名")
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "文件大小")
|
||||
private Integer size;
|
||||
|
||||
@ColumnDefine(comment = "文档版本", defaultValue = "1")
|
||||
private Long version;
|
||||
|
||||
@ColumnDefine(comment = "文件位置")
|
||||
private String filePath;
|
||||
|
||||
@Ignore
|
||||
@Column(ignore = true)
|
||||
private String key;
|
||||
|
||||
public void setFilePath(String filePath) {
|
||||
this.filePath = filePath;
|
||||
this.key = filePath;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
this.filePath = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.cool.modules.space.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* 图片空间信息分类
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "space_type", comment = "图片空间信息分类")
|
||||
public class SpaceTypeEntity extends BaseEntity<SpaceTypeEntity> {
|
||||
@ColumnDefine(comment = "类别名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "父分类ID", type = "tinyint")
|
||||
private Integer parentId;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.space.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.space.entity.SpaceInfoEntity;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
public interface SpaceInfoMapper extends BaseMapper<SpaceInfoEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.space.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.space.entity.SpaceTypeEntity;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
public interface SpaceTypeMapper extends BaseMapper<SpaceTypeEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.space.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.space.entity.SpaceInfoEntity;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
public interface SpaceInfoService extends BaseService<SpaceInfoEntity> {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.space.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.space.entity.SpaceTypeEntity;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
public interface SpaceTypeService extends BaseService<SpaceTypeEntity> {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.cool.modules.space.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.space.entity.SpaceInfoEntity;
|
||||
import com.cool.modules.space.mapper.SpaceInfoMapper;
|
||||
import com.cool.modules.space.service.SpaceInfoService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
@Service
|
||||
public class SpaceInfoServiceImpl extends BaseServiceImpl<SpaceInfoMapper, SpaceInfoEntity>
|
||||
implements SpaceInfoService {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.cool.modules.space.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.space.entity.SpaceTypeEntity;
|
||||
import com.cool.modules.space.mapper.SpaceTypeMapper;
|
||||
import com.cool.modules.space.service.SpaceTypeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 文件空间信息
|
||||
*/
|
||||
@Service
|
||||
public class SpaceTypeServiceImpl extends BaseServiceImpl<SpaceTypeMapper, SpaceTypeEntity>
|
||||
implements SpaceTypeService {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.cool.modules.task.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.quartz.SchedulerFactoryBeanCustomizer;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||
|
||||
|
||||
/**
|
||||
* 定时任务配置
|
||||
*/
|
||||
@Configuration
|
||||
@EnableScheduling
|
||||
public class ScheduleConfig implements SchedulerFactoryBeanCustomizer {
|
||||
@Override
|
||||
public void customize(SchedulerFactoryBean schedulerFactoryBean) {
|
||||
schedulerFactoryBean.setStartupDelay(2);
|
||||
schedulerFactoryBean.setAutoStartup(true);
|
||||
schedulerFactoryBean.setOverwriteExistingJobs(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.cool.modules.task.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.task.entity.TaskInfoEntity;
|
||||
import com.cool.modules.task.entity.table.TaskInfoEntityTableDef;
|
||||
import com.cool.modules.task.service.TaskInfoService;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import static com.cool.modules.task.entity.table.TaskInfoEntityTableDef.TASK_INFO_ENTITY;
|
||||
|
||||
/**
|
||||
* 任务
|
||||
*/
|
||||
@Tag(name = "任务管理", description = "统一管理任务")
|
||||
@CoolRestController(api = { "add", "delete", "update", "info", "page" })
|
||||
public class AdminTaskInfoController extends BaseController<TaskInfoService, TaskInfoEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp().fieldEq(TASK_INFO_ENTITY.STATUS, TASK_INFO_ENTITY.TYPE));
|
||||
}
|
||||
|
||||
@Operation(summary = "执行一次")
|
||||
@PostMapping("/once")
|
||||
public R once(@RequestAttribute JSONObject requestParams) {
|
||||
service.once(requestParams.getLong("id"));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "开始任务")
|
||||
@PostMapping("/start")
|
||||
public R start(@RequestAttribute JSONObject requestParams) {
|
||||
service.start(requestParams.getLong("id"), requestParams.getInt("type"));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "停止任务")
|
||||
@PostMapping("/stop")
|
||||
public R stop(@RequestAttribute JSONObject requestParams) {
|
||||
service.stop(requestParams.getLong("id"));
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "任务日志")
|
||||
@GetMapping("/log")
|
||||
public R log(@RequestAttribute JSONObject requestParams) {
|
||||
Integer page = requestParams.getInt("page", 0);
|
||||
Integer size = requestParams.getInt("size", 20);
|
||||
return R.ok(pageResult((Page<TaskInfoEntity>) service.log(new Page<>(page, size), requestParams.getLong("id"),
|
||||
requestParams.getInt("status"))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.cool.modules.task.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "task_info", comment = "任务信息")
|
||||
public class TaskInfoEntity extends BaseEntity<TaskInfoEntity> {
|
||||
/**
|
||||
* 任务调度参数key
|
||||
*/
|
||||
@Column(ignore = true)
|
||||
public static final String JOB_PARAM_KEY = "JOB_PARAM_KEY";
|
||||
|
||||
@ColumnDefine(comment = "名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "任务ID")
|
||||
private String jobId;
|
||||
|
||||
@ColumnDefine(comment = "最大执行次数 不传为无限次")
|
||||
private Integer repeatCount;
|
||||
|
||||
@ColumnDefine(comment = "每间隔多少毫秒执行一次 如果cron设置了 这项设置就无效")
|
||||
private Integer every;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:停止 1:运行", defaultValue = "1", notNull = true)
|
||||
private Integer status;
|
||||
|
||||
@ColumnDefine(comment = "服务实例名称")
|
||||
private String service;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:cron 1:时间间隔", defaultValue = "0")
|
||||
private Integer taskType;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:系统 1:用户", defaultValue = "0", type = "tinyint")
|
||||
private Integer type;
|
||||
|
||||
@ColumnDefine(comment = "任务数据")
|
||||
private String data;
|
||||
|
||||
@ColumnDefine(comment = "备注")
|
||||
private String remark;
|
||||
|
||||
@ColumnDefine(comment = "cron")
|
||||
private String cron;
|
||||
|
||||
@ColumnDefine(comment = "下一次执行时间")
|
||||
private Date nextRunTime;
|
||||
|
||||
@ColumnDefine(comment = "开始时间")
|
||||
private Date startDate;
|
||||
|
||||
@ColumnDefine(comment = "结束时间")
|
||||
private Date endDate;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.cool.modules.task.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.tangzc.autotable.annotation.Index;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.ColumnDefine;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "task_log", comment = "任务日志")
|
||||
public class TaskLogEntity extends BaseEntity<TaskLogEntity> {
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "任务ID", notNull = true, type = "bigint")
|
||||
private Long taskId;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:失败 1:成功", defaultValue = "0")
|
||||
private Integer status;
|
||||
|
||||
@ColumnDefine(comment = "详情", type = "text")
|
||||
private String detail;
|
||||
|
||||
// 任务名称
|
||||
@Column(ignore = true)
|
||||
private String taskName;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.cool.modules.task.event;
|
||||
|
||||
import com.cool.core.init.DBFromJsonInit;
|
||||
import com.cool.modules.task.service.TaskInfoService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 事件监听
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class TaskEvent {
|
||||
|
||||
final private TaskInfoService taskInfoService;
|
||||
|
||||
@EventListener
|
||||
public void handleDbInitCompleteEvent(DBFromJsonInit.DbInitCompleteEvent event) {
|
||||
taskInfoService.init();
|
||||
log.info("初始化任务");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cool.modules.task.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.task.entity.TaskInfoEntity;
|
||||
|
||||
public interface TaskInfoMapper extends BaseMapper<TaskInfoEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.cool.modules.task.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.task.entity.TaskLogEntity;
|
||||
|
||||
public interface TaskLogMapper extends BaseMapper<TaskLogEntity> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.cool.modules.task.run;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.cool.modules.task.entity.TaskInfoEntity;
|
||||
import com.cool.modules.task.entity.TaskLogEntity;
|
||||
import com.cool.modules.task.service.TaskInfoLogService;
|
||||
import com.cool.modules.task.service.TaskInfoService;
|
||||
import com.mybatisflex.core.util.StringUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* 定时任务
|
||||
*/
|
||||
@Slf4j
|
||||
public class ScheduleJob extends QuartzJobBean {
|
||||
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) {
|
||||
// 获取spring bean
|
||||
TaskInfoLogService taskInfoLogService = SpringUtil.getBean(TaskInfoLogService.class);
|
||||
// 获取spring bean
|
||||
TaskInfoService taskInfoService = SpringUtil.getBean(TaskInfoService.class);
|
||||
|
||||
Scheduler scheduler = SpringUtil.getBean(Scheduler.class);
|
||||
|
||||
TaskInfoEntity taskInfoEntity = taskInfoService
|
||||
.getById(context.getJobDetail().getKey().getName().split("_")[1]);
|
||||
if (ObjUtil.isEmpty(taskInfoEntity)) {
|
||||
log.warn("taskInfoEntity is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// 数据库保存执行记录
|
||||
TaskLogEntity taskLogEntity = new TaskLogEntity();
|
||||
|
||||
// 任务开始时间
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
// 执行任务
|
||||
log.info("任务准备执行,任务ID:" + taskInfoEntity.getJobId());
|
||||
taskLogEntity.setTaskId(taskInfoEntity.getId());
|
||||
// 解析执行
|
||||
String service = taskInfoEntity.getService();
|
||||
if (StrUtil.isNotEmpty(service)) {
|
||||
String[] arr = service.split("\\.");
|
||||
String methodName = arr[1].substring(0, arr[1].indexOf("("));
|
||||
String params = service.substring(service.indexOf("(") + 1, service.indexOf(")"));
|
||||
|
||||
ScheduleRunnable task = new ScheduleRunnable(StringUtil.firstCharToLowerCase(arr[0]).replaceAll(" ", ""), methodName, params);
|
||||
Future<?> future = executorService.submit(task);
|
||||
|
||||
future.get();
|
||||
}
|
||||
// 任务执行总时长
|
||||
long times = System.currentTimeMillis() - startTime;
|
||||
// 状态 0:失败 1:成功
|
||||
taskLogEntity.setStatus(1);
|
||||
taskLogEntity.setDetail("任务执行完毕,任务ID:" + taskInfoEntity.getJobId() + " 总共耗时:" + times + "毫秒");
|
||||
log.info(taskLogEntity.getDetail());
|
||||
} catch (Exception e) {
|
||||
// 任务执行总时长
|
||||
long times = System.currentTimeMillis() - startTime;
|
||||
|
||||
taskLogEntity.setDetail(
|
||||
"任务执行失败,任务ID:" + taskInfoEntity.getJobId() + " 总共耗时:" + times + "毫秒" + "失败原因:" + e.getMessage());
|
||||
log.error("任务执行失败,任务ID:" + taskInfoEntity.getJobId(), e);
|
||||
|
||||
// 状态 0:失败 1:成功
|
||||
taskLogEntity.setStatus(0);
|
||||
} finally {
|
||||
taskInfoLogService.add(taskLogEntity);
|
||||
}
|
||||
ThreadUtil.execAsync(() -> {
|
||||
ThreadUtil.sleep(2000);
|
||||
TaskInfoEntity next = new TaskInfoEntity();
|
||||
next.setId(taskInfoEntity.getId());
|
||||
try {
|
||||
if (!scheduler.checkExists(context.getTrigger().getJobKey())) {
|
||||
if (context.getTrigger().getNextFireTime() == null) {
|
||||
next.setStatus(0);
|
||||
}
|
||||
} else {
|
||||
if (context.getTrigger().getNextFireTime() == null) {
|
||||
next.setNextRunTime(context.getTrigger().getNextFireTime());
|
||||
}
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
log.error("err", e);
|
||||
}
|
||||
taskInfoService.updateById(next);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.cool.modules.task.run;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 执行定时任务
|
||||
*/
|
||||
public class ScheduleRunnable implements Runnable {
|
||||
private final Object target;
|
||||
private final Method method;
|
||||
private final Object[] params;
|
||||
|
||||
public ScheduleRunnable(String beanName, String methodName, String params)
|
||||
throws NoSuchMethodException, SecurityException {
|
||||
this.target = SpringUtil.getBean(beanName);
|
||||
|
||||
if (StrUtil.isNotBlank(params)) {
|
||||
String[] paramArray = params.split(",");
|
||||
this.params = new Object[paramArray.length];
|
||||
Class<?>[] paramTypes = new Class<?>[paramArray.length];
|
||||
|
||||
for (int i = 0; i < paramArray.length; i++) {
|
||||
String param = paramArray[i].trim();
|
||||
if (param.matches("-?\\d+")) {
|
||||
this.params[i] = Integer.parseInt(param);
|
||||
paramTypes[i] = int.class;
|
||||
} else if (param.matches("-?\\d+L")) {
|
||||
this.params[i] = Long.parseLong(param.substring(0, param.length() - 1));
|
||||
paramTypes[i] = long.class;
|
||||
} else if (param.matches("-?\\d+\\.\\d+")) {
|
||||
this.params[i] = Double.parseDouble(param);
|
||||
paramTypes[i] = double.class;
|
||||
} else if (param.matches("-?\\d+\\.\\d+f")) {
|
||||
this.params[i] = Float.parseFloat(param.substring(0, param.length() - 1));
|
||||
paramTypes[i] = float.class;
|
||||
} else if (param.equalsIgnoreCase("true") || param.equalsIgnoreCase("false")) {
|
||||
this.params[i] = Boolean.parseBoolean(param);
|
||||
paramTypes[i] = boolean.class;
|
||||
} else if (param.length() == 1) {
|
||||
this.params[i] = param.charAt(0);
|
||||
paramTypes[i] = char.class;
|
||||
} else {
|
||||
// Remove leading and trailing quotation marks for string parameters
|
||||
if (param.startsWith("\"") && param.endsWith("\"")) {
|
||||
param = param.substring(1, param.length() - 1);
|
||||
}
|
||||
this.params[i] = param;
|
||||
paramTypes[i] = String.class;
|
||||
}
|
||||
}
|
||||
|
||||
this.method = findMethod(target.getClass(), methodName, paramTypes);
|
||||
} else {
|
||||
this.params = new Object[0];
|
||||
this.method = target.getClass().getDeclaredMethod(methodName);
|
||||
}
|
||||
}
|
||||
|
||||
private Method findMethod(Class<?> targetClass, String methodName, Class<?>[] paramTypes) throws NoSuchMethodException {
|
||||
try {
|
||||
return targetClass.getDeclaredMethod(methodName, paramTypes);
|
||||
} catch (NoSuchMethodException e) {
|
||||
// Try with wrapper classes
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
if (paramTypes[i] == int.class) {
|
||||
paramTypes[i] = Integer.class;
|
||||
} else if (paramTypes[i] == long.class) {
|
||||
paramTypes[i] = Long.class;
|
||||
} else if (paramTypes[i] == double.class) {
|
||||
paramTypes[i] = Double.class;
|
||||
} else if (paramTypes[i] == float.class) {
|
||||
paramTypes[i] = Float.class;
|
||||
} else if (paramTypes[i] == boolean.class) {
|
||||
paramTypes[i] = Boolean.class;
|
||||
} else if (paramTypes[i] == char.class) {
|
||||
paramTypes[i] = Character.class;
|
||||
}
|
||||
}
|
||||
return targetClass.getDeclaredMethod(methodName, paramTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(method);
|
||||
if (params.length > 0) {
|
||||
method.invoke(target, params);
|
||||
} else {
|
||||
method.invoke(target);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new CoolException("执行定时任务失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.cool.modules.task.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.task.entity.TaskLogEntity;
|
||||
|
||||
/**
|
||||
* 任务日志
|
||||
*/
|
||||
public interface TaskInfoLogService extends BaseService<TaskLogEntity> {
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.cool.modules.task.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.task.entity.TaskInfoEntity;
|
||||
import com.cool.modules.task.entity.TaskLogEntity;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
|
||||
/**
|
||||
* 任务信息
|
||||
*/
|
||||
public interface TaskInfoService extends BaseService<TaskInfoEntity> {
|
||||
|
||||
/**
|
||||
* 初始化任务
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* 执行一次
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
*/
|
||||
void once(Long taskId);
|
||||
|
||||
/**
|
||||
* 停止任务
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
*/
|
||||
void stop(Long taskId);
|
||||
|
||||
/**
|
||||
* 任务日志
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @param status 任务状态
|
||||
* @return 日志列表
|
||||
*/
|
||||
Object log(Page<TaskLogEntity> page, Long taskId, Integer status);
|
||||
|
||||
/**
|
||||
* 开始任务
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @param type 任务类型
|
||||
*/
|
||||
void start(Long taskId, Integer type);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.task.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.task.entity.TaskLogEntity;
|
||||
import com.cool.modules.task.mapper.TaskLogMapper;
|
||||
import com.cool.modules.task.service.TaskInfoLogService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class TaskInfoLogServiceImpl extends BaseServiceImpl<TaskLogMapper, TaskLogEntity>
|
||||
implements TaskInfoLogService {
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package com.cool.modules.task.service.impl;
|
||||
|
||||
import static com.cool.modules.task.entity.table.TaskInfoEntityTableDef.TASK_INFO_ENTITY;
|
||||
import static com.cool.modules.task.entity.table.TaskLogEntityTableDef.TASK_LOG_ENTITY;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.task.entity.TaskInfoEntity;
|
||||
import com.cool.modules.task.entity.TaskLogEntity;
|
||||
import com.cool.modules.task.mapper.TaskInfoMapper;
|
||||
import com.cool.modules.task.service.TaskInfoService;
|
||||
import com.cool.modules.task.utils.ScheduleUtils;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.CronTrigger;
|
||||
import org.quartz.Scheduler;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TaskInfoServiceImpl extends BaseServiceImpl<TaskInfoMapper, TaskInfoEntity> implements
|
||||
TaskInfoService {
|
||||
|
||||
final private Scheduler scheduler;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
try {
|
||||
List<TaskInfoEntity> list = list();
|
||||
list.forEach(scheduleJob -> {
|
||||
CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler,
|
||||
scheduleJob.getJobId());
|
||||
if (cronTrigger == null) {
|
||||
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
|
||||
} else {
|
||||
ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
|
||||
}
|
||||
updateById(scheduleJob);
|
||||
});
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void once(Long taskId) {
|
||||
ScheduleUtils.run(scheduler, getById(taskId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void stop(Long taskId) {
|
||||
ScheduleUtils.pauseJob(scheduler, taskId + "");
|
||||
TaskInfoEntity taskInfoEntity = getById(taskId);
|
||||
taskInfoEntity.setStatus(0);
|
||||
updateById(taskInfoEntity);
|
||||
modifyAfter(JSONUtil.parseObj(taskInfoEntity), taskInfoEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object log(Page page, Long taskId, Integer status) {
|
||||
|
||||
QueryWrapper queryWrapper = QueryWrapper.create().select(TASK_LOG_ENTITY.ALL_COLUMNS,
|
||||
TASK_INFO_ENTITY.NAME.as("taskName")).from(TASK_LOG_ENTITY)
|
||||
.leftJoin(TASK_INFO_ENTITY).on(TASK_LOG_ENTITY.TASK_ID.eq(TASK_INFO_ENTITY.ID))
|
||||
.eq(TaskLogEntity::getTaskId, taskId, taskId != null)
|
||||
.eq(TaskLogEntity::getStatus, status, status != null)
|
||||
.orderBy(TaskLogEntity::getCreateTime, false);
|
||||
return mapper.paginate(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void start(Long taskId, Integer type) {
|
||||
TaskInfoEntity taskInfoEntity = getById(taskId);
|
||||
taskInfoEntity.setStatus(1);
|
||||
if (type != null) {
|
||||
taskInfoEntity.setType(type);
|
||||
}
|
||||
boolean isExists = false;
|
||||
try {
|
||||
isExists = scheduler.checkExists(ScheduleUtils.getJobKey(taskId + ""));
|
||||
} catch (SchedulerException e) {
|
||||
log.error("err", e);
|
||||
}
|
||||
if (isExists) {
|
||||
ScheduleUtils.updateScheduleJob(scheduler, taskInfoEntity);
|
||||
ScheduleUtils.resumeJob(scheduler, taskId + "");
|
||||
} else {
|
||||
ScheduleUtils.createScheduleJob(scheduler, taskInfoEntity);
|
||||
}
|
||||
updateById(taskInfoEntity);
|
||||
modifyAfter(JSONUtil.parseObj(taskInfoEntity), taskInfoEntity);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long add(JSONObject requestParams, TaskInfoEntity scheduleJob) {
|
||||
scheduleJob.setStatus(1);
|
||||
super.add(scheduleJob);
|
||||
scheduleJob.setJobId(scheduleJob.getId() + "");
|
||||
|
||||
ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
|
||||
updateById(scheduleJob);
|
||||
super.modifyAfter(requestParams, scheduleJob);
|
||||
return scheduleJob.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean update(JSONObject requestParams, TaskInfoEntity entity) {
|
||||
updateById(entity);
|
||||
ScheduleUtils.deleteScheduleJob(scheduler, entity.getId().toString());
|
||||
if (entity.getStatus() == 1) {
|
||||
start(entity.getId(), entity.getType());
|
||||
} else {
|
||||
stop(entity.getId());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean delete(JSONObject requestParams, Long... ids) {
|
||||
Convert.toList(String.class, ids).forEach(jobId -> {
|
||||
ScheduleUtils.deleteScheduleJob(scheduler, jobId);
|
||||
});
|
||||
return super.delete(requestParams, ids);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package com.cool.modules.task.utils;
|
||||
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.modules.task.entity.TaskInfoEntity;
|
||||
import com.cool.modules.task.run.ScheduleJob;
|
||||
import org.quartz.*;
|
||||
|
||||
/**
|
||||
* 定时任务工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
* @since 1.2.0 2016-11-28
|
||||
*/
|
||||
public class ScheduleUtils {
|
||||
private final static String JOB_NAME = "TASK_";
|
||||
|
||||
public enum ScheduleStatus {
|
||||
/**
|
||||
* 暂停
|
||||
*/
|
||||
PAUSE(0),
|
||||
/**
|
||||
* 正常
|
||||
*/
|
||||
NORMAL(1);
|
||||
|
||||
private int value;
|
||||
|
||||
ScheduleStatus(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取触发器key
|
||||
*/
|
||||
public static TriggerKey getTriggerKey(String jobId) {
|
||||
return TriggerKey.triggerKey(JOB_NAME + jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取jobKey
|
||||
*/
|
||||
public static JobKey getJobKey(String jobId) {
|
||||
return JobKey.jobKey(JOB_NAME + jobId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表达式触发器
|
||||
*/
|
||||
public static CronTrigger getCronTrigger(Scheduler scheduler, String jobId) {
|
||||
try {
|
||||
return (CronTrigger) scheduler.getTrigger(getTriggerKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("获取定时任务CronTrigger出现异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取表达式触发器
|
||||
*/
|
||||
public static SimpleTrigger getSimpleTrigger(Scheduler scheduler, String jobId) {
|
||||
try {
|
||||
return (SimpleTrigger) scheduler.getTrigger(getTriggerKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("获取定时任务CronTrigger出现异常", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建定时任务
|
||||
*/
|
||||
public static void createScheduleJob(Scheduler scheduler, TaskInfoEntity scheduleJob) {
|
||||
try {
|
||||
// 构建job信息
|
||||
JobDetail jobDetail = JobBuilder.newJob(ScheduleJob.class).withIdentity(getJobKey(scheduleJob.getJobId()))
|
||||
.build();
|
||||
|
||||
if (scheduleJob.getTaskType() == 0) {
|
||||
// 表达式调度构建器
|
||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCron())
|
||||
.withMisfireHandlingInstructionDoNothing();
|
||||
|
||||
TriggerBuilder<CronTrigger> triggerBuilder = TriggerBuilder.newTrigger()
|
||||
.withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder);
|
||||
|
||||
if (scheduleJob.getStartDate() != null) {
|
||||
triggerBuilder.startAt(scheduleJob.getStartDate());
|
||||
}
|
||||
|
||||
if (scheduleJob.getEndDate() != null) {
|
||||
triggerBuilder.endAt(scheduleJob.getEndDate());
|
||||
}
|
||||
|
||||
// 按新的cronExpression表达式构建一个新的trigger
|
||||
CronTrigger trigger = triggerBuilder.build();
|
||||
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
scheduleJob.setNextRunTime(trigger.getNextFireTime());
|
||||
}
|
||||
|
||||
if (scheduleJob.getTaskType() == 1) {
|
||||
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
|
||||
.withIntervalInSeconds(scheduleJob.getEvery() / 1000);
|
||||
if (scheduleJob.getRepeatCount() != null) {
|
||||
scheduleBuilder.withRepeatCount(scheduleJob.getRepeatCount());
|
||||
} else {
|
||||
scheduleBuilder.repeatForever();
|
||||
}
|
||||
TriggerBuilder<SimpleTrigger> triggerBuilder = TriggerBuilder.newTrigger()
|
||||
.withIdentity(getTriggerKey(scheduleJob.getJobId())).withSchedule(scheduleBuilder);
|
||||
if (scheduleJob.getStartDate() != null) {
|
||||
triggerBuilder.startAt(scheduleJob.getStartDate());
|
||||
}
|
||||
|
||||
if (scheduleJob.getEndDate() != null) {
|
||||
triggerBuilder.endAt(scheduleJob.getEndDate());
|
||||
}
|
||||
Trigger trigger = triggerBuilder.build();
|
||||
|
||||
scheduler.scheduleJob(jobDetail, trigger);
|
||||
scheduleJob.setNextRunTime(trigger.getNextFireTime());
|
||||
}
|
||||
|
||||
// 暂停任务
|
||||
if (scheduleJob.getStatus() != null && scheduleJob.getStatus() == ScheduleStatus.PAUSE.getValue()) {
|
||||
pauseJob(scheduler, scheduleJob.getJobId());
|
||||
}
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("创建定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新定时任务
|
||||
*/
|
||||
public static void updateScheduleJob(Scheduler scheduler, TaskInfoEntity scheduleJob) {
|
||||
try {
|
||||
TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
|
||||
|
||||
if (scheduleJob.getTaskType() == 0) {
|
||||
// 表达式调度构建器
|
||||
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCron())
|
||||
.withMisfireHandlingInstructionDoNothing();
|
||||
|
||||
CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
|
||||
|
||||
TriggerBuilder<CronTrigger> triggerBuilder = trigger.getTriggerBuilder();
|
||||
|
||||
if (scheduleJob.getStartDate() != null) {
|
||||
triggerBuilder.startAt(scheduleJob.getStartDate());
|
||||
}
|
||||
|
||||
if (scheduleJob.getEndDate() != null) {
|
||||
triggerBuilder.endAt(scheduleJob.getEndDate());
|
||||
}
|
||||
|
||||
// 按新的cronExpression表达式重新构建trigger
|
||||
trigger = triggerBuilder.withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
|
||||
|
||||
scheduler.rescheduleJob(triggerKey, trigger);
|
||||
scheduleJob.setNextRunTime(trigger.getNextFireTime());
|
||||
|
||||
}
|
||||
|
||||
if (scheduleJob.getTaskType() == 1) {
|
||||
SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule()
|
||||
.withIntervalInSeconds(scheduleJob.getEvery() / 1000);
|
||||
|
||||
SimpleTrigger trigger = getSimpleTrigger(scheduler, scheduleJob.getJobId());
|
||||
|
||||
if (scheduleJob.getRepeatCount() != null) {
|
||||
scheduleBuilder.withRepeatCount(scheduleJob.getRepeatCount());
|
||||
} else {
|
||||
scheduleBuilder.repeatForever();
|
||||
}
|
||||
TriggerBuilder<SimpleTrigger> triggerBuilder = trigger.getTriggerBuilder();
|
||||
if (scheduleJob.getStartDate() != null) {
|
||||
triggerBuilder.startAt(scheduleJob.getStartDate());
|
||||
}
|
||||
|
||||
if (scheduleJob.getEndDate() != null) {
|
||||
triggerBuilder.endAt(scheduleJob.getEndDate());
|
||||
}
|
||||
trigger = triggerBuilder.withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
|
||||
|
||||
scheduler.rescheduleJob(triggerKey, trigger);
|
||||
scheduleJob.setNextRunTime(trigger.getNextFireTime());
|
||||
}
|
||||
|
||||
// 暂停任务
|
||||
if (scheduleJob.getStatus() == ScheduleStatus.PAUSE.getValue()) {
|
||||
pauseJob(scheduler, scheduleJob.getJobId());
|
||||
}
|
||||
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("更新定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 立即执行任务
|
||||
*/
|
||||
public static void run(Scheduler scheduler, TaskInfoEntity scheduleJob) {
|
||||
try {
|
||||
// 参数
|
||||
JobDataMap dataMap = new JobDataMap();
|
||||
|
||||
scheduler.triggerJob(getJobKey(scheduleJob.getJobId()), dataMap);
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("立即执行定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 暂停任务
|
||||
*/
|
||||
public static void pauseJob(Scheduler scheduler, String jobId) {
|
||||
try {
|
||||
scheduler.pauseJob(getJobKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("暂停定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复任务
|
||||
*/
|
||||
public static void resumeJob(Scheduler scheduler, String jobId) {
|
||||
try {
|
||||
scheduler.resumeJob(getJobKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("恢复定时任务失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除定时任务
|
||||
*/
|
||||
public static void deleteScheduleJob(Scheduler scheduler, String jobId) {
|
||||
try {
|
||||
scheduler.deleteJob(getJobKey(jobId));
|
||||
} catch (SchedulerException e) {
|
||||
throw new CoolException("删除定时任务失败", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user