diff --git a/.gitignore b/.gitignore index d76946210ae06d6d94da822c9eae8c88834fc08f..3878d2c1e6557efd6b924fc7665fe459893ccc9f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ target/ !.mvn/wrapper/maven-wrapper.jar !**/src/main/**/target/ !**/src/test/**/target/ +.run ### IntelliJ IDEA ### .idea diff --git a/README.md b/README.md index 445a3660c99b079a56329ed980b551fe4eeea203..3d0cf33d2d3c5a85bb387d214e044150fb28a155 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,8 @@ 权限认证(SaToken) +密码保护(BCrypt) + # 升级java21的问题 升级到java21以后的启动参数,不加会报错 diff --git a/milkbox-app/src/main/java/top/milkbox/Application.java b/milkbox-app/src/main/java/top/milkbox/Application.java index 37e8e2ca39cc5b9a8e90422a2dd6716e08105e67..7914742271797517a594c050b56b74430c85c1f1 100644 --- a/milkbox-app/src/main/java/top/milkbox/Application.java +++ b/milkbox-app/src/main/java/top/milkbox/Application.java @@ -38,6 +38,7 @@ public class Application { new Date() + "," + JSONUtil.toJsonStr(TimeZone.getDefault())); log.info("当前服务器公共字段默认注入时间(DateTime.now()):" + DateTime.now()); // log.info("通用配置:\n" + JSONUtil.toJsonPrettyStr(app.getBean("commonProperties"))); + log.info("文档地址:swagger-ui/index.html"); log.info(">>> {}", Application.class.getSimpleName().toUpperCase() + " STARTING SUCCESS 启动成功"); } diff --git a/milkbox-app/src/main/java/top/milkbox/app/core/handler/mybatisPlus/MyMetaObjectHandler.java b/milkbox-app/src/main/java/top/milkbox/app/core/handler/mybatisPlus/MyMetaObjectHandler.java index a425dcb21a2240057232153e22e0ebc648381471..84391904f9a781912470f1638cb6d3865c634b9d 100644 --- a/milkbox-app/src/main/java/top/milkbox/app/core/handler/mybatisPlus/MyMetaObjectHandler.java +++ b/milkbox-app/src/main/java/top/milkbox/app/core/handler/mybatisPlus/MyMetaObjectHandler.java @@ -1,5 +1,8 @@ package top.milkbox.app.core.handler.mybatisPlus; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.exception.NotWebContextException; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.date.DateTime; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; @@ -9,21 +12,31 @@ import top.milkbox.common.enums.CommonDeleteFlagEnum; import java.util.Date; /** - * 常用字段自动填充器 + * 常用字段自动填充器
+ * 默认填充策略:如果原来的属性有值则不覆盖,如果手动在这里改为null则不填充 * 创建时间: 2024-01-15 下午 4:08 * * @author milkbox */ @Component public class MyMetaObjectHandler implements MetaObjectHandler { + + private Integer getLoginId() { + try { + return StpUtil.getLoginIdAsInt(); + } catch (NotLoginException e) { // 未登录 + return null; + } catch (NotWebContextException e) { // 非web上下文,无法使用sa-token + return null; + } + } + @Override public void insertFill(MetaObject metaObject) { // 删除字段 this.strictInsertFill(metaObject, "deleteFlag", () -> CommonDeleteFlagEnum.NOT_DELETE, CommonDeleteFlagEnum.class); - // TODO 创建人,这个需要saToken - this.strictInsertFill(metaObject, "createUser", - () -> -1, Integer.class); + this.strictInsertFill(metaObject, "createUser", this::getLoginId, Integer.class); // 创建时间 this.strictInsertFill(metaObject, "createTime", DateTime::now, Date.class); @@ -31,9 +44,7 @@ public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void updateFill(MetaObject metaObject) { - // TODO 更新人,这个需要saToken - this.strictUpdateFill(metaObject, "updateUser", - () -> -1, Integer.class); + this.strictUpdateFill(metaObject, "updateUser", this::getLoginId, Integer.class); // 更新时间 this.strictUpdateFill(metaObject, "updateTime", DateTime::now, Date.class); diff --git a/milkbox-common/src/main/java/top/milkbox/common/bo/EntityColumnExistence.java b/milkbox-common/src/main/java/top/milkbox/common/bo/EntityColumnExistence.java new file mode 100644 index 0000000000000000000000000000000000000000..db70c38a013d0a020497391273cd35833607403d --- /dev/null +++ b/milkbox-common/src/main/java/top/milkbox/common/bo/EntityColumnExistence.java @@ -0,0 +1,30 @@ +package top.milkbox.common.bo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 存在性类,对应数据库的同一列中哪些是存在的字段,哪些是不存在的字段
+ * 创建时间: 2024-02-04 下午 1:48 + * + * @param 列的类型 + * @author milkbox + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class EntityColumnExistence { + + /** + * 存在的列 + */ + private List existColumnList; + + /** + * 不存在的列 + */ + private List doesNotExistColumnList; +} diff --git a/milkbox-common/src/main/java/top/milkbox/common/service/CommonService.java b/milkbox-common/src/main/java/top/milkbox/common/service/CommonService.java new file mode 100644 index 0000000000000000000000000000000000000000..f7d977ef971194dab0aab3db1644440a2255bfc6 --- /dev/null +++ b/milkbox-common/src/main/java/top/milkbox/common/service/CommonService.java @@ -0,0 +1,30 @@ +package top.milkbox.common.service; + +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.extension.service.IService; +import top.milkbox.common.bo.EntityColumnExistence; + +import java.io.Serializable; +import java.util.Collection; + +/** + * 抽取通用服务层接口
+ * 创建时间: 2024-02-04 下午 3:09 + * + * @param 实体类类型 + * @author milkbox + */ +public interface CommonService extends IService { + + /** + * 过滤出在数据库中不存在的实体列
+ * 注意:此方法中包含一次数据库查询 + * + * @param column 被操作的字段的get方法的引用 + * @param entityColumnCollection 原始集合 + * @param 列的类型 + * @return 并返回一个包含存在和不存在实体列信息的对象 + */ + EntityColumnExistence filterDoesNotExistColumn( + SFunction column, Collection entityColumnCollection); +} diff --git a/milkbox-common/src/main/java/top/milkbox/common/service/impl/CommonServiceImpl.java b/milkbox-common/src/main/java/top/milkbox/common/service/impl/CommonServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..08efb782e17eebe79a947020d858454691e7a872 --- /dev/null +++ b/milkbox-common/src/main/java/top/milkbox/common/service/impl/CommonServiceImpl.java @@ -0,0 +1,39 @@ +package top.milkbox.common.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import top.milkbox.common.bo.EntityColumnExistence; +import top.milkbox.common.service.CommonService; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; + +/** + * 抽取通用服务
+ * 创建时间: 2024-02-04 下午 2:26 + * + * @author milkbox + */ +public class CommonServiceImpl, E> extends ServiceImpl implements CommonService { + + @Override + public EntityColumnExistence filterDoesNotExistColumn( + SFunction column, Collection entityColumnCollection) { + // 创建可见性对象,用于存储存在的和不存在的实体列集合 + EntityColumnExistence entityColumnExistence = new EntityColumnExistence<>(); + // 查询并保存存在的实体列 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(column, entityColumnCollection); + entityColumnExistence.setExistColumnList(super.list(queryWrapper).stream().map(column).toList()); + // 在原实体中移除已经存在的实体 + // 注意:removeAll方法仅支持可变类型的集合,即ArrayList类型 + ArrayList entityColumnList = new ArrayList<>(entityColumnCollection); + entityColumnList.removeAll(entityColumnExistence.getExistColumnList()); + // 将不存在的id集合保存到可见性对象 + entityColumnExistence.setDoesNotExistColumnList(entityColumnList); + return entityColumnExistence; + } +} diff --git a/milkbox-common/src/main/java/top/milkbox/common/validation/annotation/CollectionElementNotNull.java b/milkbox-common/src/main/java/top/milkbox/common/validation/annotation/CollectionElementNotNull.java new file mode 100644 index 0000000000000000000000000000000000000000..534ab5bd007a08b8bc938e0307de8b2e43b2b672 --- /dev/null +++ b/milkbox-common/src/main/java/top/milkbox/common/validation/annotation/CollectionElementNotNull.java @@ -0,0 +1,41 @@ +package top.milkbox.common.validation.annotation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import top.milkbox.common.validation.validator.CollectionElementNotNullValidator; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// TODO 请参照此注解编写更多的自定义校验,例如手机号、邮箱等 + +/** + * 自定义校验注解
+ * 校验集合中的每一个元素都不为空
+ * 如果校验对象为空、集合元素为0或集合中的所有元素都不为空则校验通过
+ * 创建时间: 2024-01-29 下午 2:22 + * + * @author milkbox + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = CollectionElementNotNullValidator.class) // 校验的逻辑处理类 +public @interface CollectionElementNotNull { + + /** + * 提示的信息 + * + * @return 默认值:集合中不能出现空元素 + */ + String message() default "集合中不能出现空元素"; + + /** + * 分组验证 + * + * @return 默认值:{} + */ + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/milkbox-common/src/main/java/top/milkbox/common/validation/validator/CollectionElementNotNullValidator.java b/milkbox-common/src/main/java/top/milkbox/common/validation/validator/CollectionElementNotNullValidator.java new file mode 100644 index 0000000000000000000000000000000000000000..f97708f95c6f0a8372eb7e362f2d4a00a577da77 --- /dev/null +++ b/milkbox-common/src/main/java/top/milkbox/common/validation/validator/CollectionElementNotNullValidator.java @@ -0,0 +1,24 @@ +package top.milkbox.common.validation.validator; + +import cn.hutool.core.util.ObjectUtil; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import top.milkbox.common.validation.annotation.CollectionElementNotNull; + +import java.util.Collection; + +/** + * 创建时间: 2024-01-29 下午 2:27 + * + * @author milkbox + */ +public class CollectionElementNotNullValidator implements ConstraintValidator> { + + @Override + public boolean isValid(Collection value, ConstraintValidatorContext context) { + if (ObjectUtil.isNotEmpty(value)) { + return value.stream().noneMatch(ObjectUtil::isNull); + } + return true; + } +} diff --git a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/controller/LogMainController.java b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/controller/LogMainController.java index 874881f68f0996db0fbcec21e2d0c6d9a104511c..4d1d855a352c70120715a1477387e2d3b36f9011 100644 --- a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/controller/LogMainController.java +++ b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/controller/LogMainController.java @@ -11,6 +11,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import top.milkbox.common.annotation.CommonLog; import top.milkbox.common.enums.LogTypeEnum; +import top.milkbox.common.validation.annotation.CollectionElementNotNull; import top.milkbox.log.core.config.LogConfiguration; import top.milkbox.log.modular.main.param.LogMainAddParam; import top.milkbox.log.modular.main.param.LogMainEditParam; @@ -50,9 +51,9 @@ public class LogMainController { @Operation(summary = "批量删除") @CommonLog(value = "批量删除", module = LogConfiguration.MODULE_NAME, type = LogTypeEnum.DELETE) public CommonResult delete( - @Validated @RequestBody @Size(min = 1, message = "请至少传递一个删除对象") + @CollectionElementNotNull(message = "集合中的删除对象不能为空") List<@Valid LogMainIdParam> paramList ) { logMainService.delete(paramList); diff --git a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/param/LogMainAddParam.java b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/param/LogMainAddParam.java index 903c6b3d187f374711c6ff4aaac6895c794cd756..9934a202a9779aec5ea934242845b0cb0a0e9bf7 100644 --- a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/param/LogMainAddParam.java +++ b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/param/LogMainAddParam.java @@ -117,4 +117,12 @@ public class LogMainAddParam implements Serializable { description = "类型。枚举") private LogTypeEnum type; + /** + * 创建人
+ * 日志的添加不存在api添加的情况
+ * 由于日志是异步保存的,在mybatis-plus的自动填充功能中无法使用sa-token,所以这个字段需要手动赋值 + */ + @Schema(title = "创建人") + private Integer createUser; + } \ No newline at end of file diff --git a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/LogMainService.java b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/LogMainService.java index d963653b5026034b61408a31d8c0221cf6b60cfc..72f47ed5597ea3407ae9caf57a6e445721d7e328 100644 --- a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/LogMainService.java +++ b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/LogMainService.java @@ -66,7 +66,7 @@ public interface LogMainService extends IService { Page page(LogMainPageParam pageParam); /** - * 异步保存日志 + * 异步保存日志,保存正常日志 * * @param joinPoint 切点 * @param result 方法的返回值 @@ -74,7 +74,7 @@ public interface LogMainService extends IService { void saveNormalLogAsync(ProceedingJoinPoint joinPoint, Object result); /** - * 异步保存报错日志 + * 异步保存报错日志,保存异常日志 * * @param joinPoint 切点 * @param throwable 报错信息 diff --git a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/impl/LogMainServiceImpl.java b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/impl/LogMainServiceImpl.java index 4a7c5c0fb980005bebe7a915e720fda3dfbdbe7b..e66ef9a1a7dd9d1fae14dd075f4e5a0b871015f8 100644 --- a/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/impl/LogMainServiceImpl.java +++ b/milkbox-service/service-log/src/main/java/top/milkbox/log/modular/main/service/impl/LogMainServiceImpl.java @@ -1,5 +1,7 @@ package top.milkbox.log.modular.main.service.impl; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -118,44 +120,89 @@ public class LogMainServiceImpl extends ServiceImpl { - LogMainAddParam addParam = - createLogMainAddParam(servletRequestAttributes, joinPoint, result, null); - add(addParam); + LogMainAddParam finaAddParam = + processLogMainAddParam(addParam, joinPoint, result, null); + add(finaAddParam); // 保存到数据库 }); } @Override public void saveThrowableLogAsync(ProceedingJoinPoint joinPoint, Throwable throwable) { - ServletRequestAttributes servletRequestAttributes - = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + LogMainAddParam addParam = createLogMainAddParam(); logExecute.execute(() -> { - LogMainAddParam addParam = - createLogMainAddParam(servletRequestAttributes, joinPoint, null, throwable); - add(addParam); + LogMainAddParam finaAddParam = + processLogMainAddParam(addParam, joinPoint, null, throwable); + add(finaAddParam); // 保存到数据库 }); } /** - * 构建日志addParam对象 + * @return 返回当前登录用户的id,如果未登录则返回空 + */ + private Integer getLoginId() { + try { + return StpUtil.getLoginIdAsInt(); + } catch (NotLoginException e) { + return null; + } + } + + /** + * 创建并处理日志对象 + * 由于需要处理请求体,所以这里的处理是必须在当前请求线程中执行 * - * @param servletRequestAttributes 请求对象 - * @param joinPoint 切点 - * @param result 方法的返回值 - * @param throwable 抛出的异常,如果为空则表示没有发生异常,可以通过这个值判断方法的运行状况 + * @return 返回日志对象 + */ + private LogMainAddParam createLogMainAddParam() { + LogMainAddParam addParam = new LogMainAddParam(); // 创建被保存的日志参数对象 + + // 当前保存日志的用户id + addParam.setCreateUser(getLoginId()); + + // 如果有request对象则保存相关信息,如果没有则日志为method类型 + ServletRequestAttributes servletRequestAttributes + = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (ObjectUtil.isNotNull(servletRequestAttributes)) { + addParam.setCategory(LogCategoryEnum.API); + + HttpServletRequest request = servletRequestAttributes.getRequest(); + addParam.setRequestUrl(request.getRequestURL().toString()); + // addParam.setOperationIp(NetUtil.getRealIp(request)); // 自己的获取ip方式 + addParam.setOperationIp(JakartaServletUtil.getClientIP(request)); // 糊涂工具的获取ip方式 + + String userAgentString = JakartaServletUtil.getHeaderIgnoreCase( + request, "User-Agent"); + UserAgent userAgent = UserAgentUtil.parse(userAgentString); + if (userAgent.getBrowser().getName().equals(UserAgentInfo.NameUnknown)) { + addParam.setOperationBrowser(userAgentString); + } else { + addParam.setOperationBrowser(userAgent.getBrowser().getName()); + addParam.setOperationSystem(userAgent.getPlatform().getName()); + } + } else { + addParam.setCategory(LogCategoryEnum.METHOD); + } + + return addParam; + } + + /** + * 在子线程中继续处理日志对象 + * + * @param joinPoint 切点 + * @param result 方法的返回值 + * @param throwable 抛出的异常,如果为空则表示没有发生异常,可以通过这个值判断方法的运行状况 * @return 返回AddParam对象 */ - private LogMainAddParam createLogMainAddParam( - ServletRequestAttributes servletRequestAttributes, ProceedingJoinPoint joinPoint, - Object result, Throwable throwable) { + private LogMainAddParam processLogMainAddParam( + LogMainAddParam addParam, ProceedingJoinPoint joinPoint, Object result, Throwable throwable) { + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); CommonLog commonLog = method.getAnnotation(CommonLog.class); - LogMainAddParam addParam = new LogMainAddParam(); - // 状态信息 addParam.setStatus(throwable == null ? 1 : 0); @@ -175,28 +222,6 @@ public class LogMainServiceImpl extends ServiceImpl add(@Validated @RequestBody SysMenuAddParam addParam) { + sysMenuService.add(addParam); + return CommonResult.ok(); + } + + @DeleteMapping("/delete") + @Operation(summary = "批量删除") + @CommonLog(value = "批量删除", module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.DELETE) + public CommonResult delete( + @RequestBody + @Size(min = 1, message = "请至少传递一个删除对象") + @CollectionElementNotNull(message = "集合中的删除对象不能为空") + List<@Valid SysMenuIdParam> paramList + ) { + sysMenuService.delete(paramList); + return CommonResult.ok(); + } + + @PutMapping("/edit") + @Operation(summary = "修改", description = "修改一条数据") + @CommonLog(value = "修改", description = "修改一条数据", + module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.UPDATE) + public CommonResult edit(@Validated @RequestBody SysMenuEditParam editParam) { + sysMenuService.edit(editParam); + return CommonResult.ok(); + } + + @GetMapping("/detail") + @Operation(summary = "详情", description = "查询一条数据的详情") + @CommonLog(value = "详情", description = "查询一条数据的详情", + module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) + public CommonResult detail(@Validated SysMenuIdParam idParam) { + return CommonResult.ok(sysMenuService.detail(idParam)); + } + +// @GetMapping("/page") +// @Operation(summary = "分页查询", description = "查询条件分页查询") +// @CommonLog(value = "分页查询", description = "查询条件分页查询", +// module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) +// public CommonResult> page(@Validated SysMenuPageParam pageParam) { +// return CommonResult.ok(sysMenuService.page(pageParam)); +// } + + @GetMapping("/forest") + @Operation(summary = "获取菜单森林", description = "获取当前登录用户拥有权限的菜单森林") + @CommonLog(value = "获取菜单森林", description = "获取当前登录用户拥有权限的菜单森林", + module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) + public CommonResult>> forest() { + return CommonResult.ok(sysMenuService.forest()); + } + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/entity/SysMenuEntity.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/entity/SysMenuEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..ef540d07a38d997a0f48794c9ad46ec1e6dae1bc --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/entity/SysMenuEntity.java @@ -0,0 +1,127 @@ +package top.milkbox.sys.modular.menu.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import top.milkbox.common.pojo.CommonEntity; + +import java.io.Serializable; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import top.milkbox.sys.modular.menu.enums.SysMenuTypeEnum; + +/** + * 系统_菜单表 + * + * @author milkbox + * @date 2024-1-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@TableName(value = "sys_menu", autoResultMap = true) +@Schema(description = "SysMenuEntity 系统_菜单表。") +public class SysMenuEntity extends CommonEntity implements Serializable { + + /** + * 主键 + */ + @TableId + @Schema(title = "主键", + description = "主键") + private Integer id; + + /** + * 上级id + */ + @Schema(title = "上级id", + description = "上级id") + private String parentId; + + /** + * 中文名 + */ + @Schema(title = "中文名", + description = "中文名") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String title; + + /** + * 组件唯一别名 + */ + @Schema(title = "组件唯一别名", + description = "组件唯一别名") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String name; + + /** + * 组件的导包路径;相对于组件的基准目录,基准目录单独配置,开头不加反斜杠 + */ + @Schema(title = "组件的导包路径", + description = "组件的导包路径。相对于组件的基准目录,基准目录单独配置,开头不加反斜杠") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String component; + + /** + * 相对于父级的路由地址;开头要加反斜杠,可以多级 + */ + @Schema(title = "相对于父级的路由地址", + description = "相对于父级的路由地址。开头要加反斜杠,可以多级") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String path; + + /** + * 重定向地址;当这个字段不为空表示有重定向,开启重定向后component字段失效 + */ + @Schema(title = "重定向地址", + description = "重定向地址。当这个字段不为空表示有重定向,开启重定向后component字段失效") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String redirect; + + /** + * 扩展信息;Json格式 + */ + @Schema(title = "扩展信息", + description = "扩展信息。Json格式") + @TableField(typeHandler = JacksonTypeHandler.class, updateStrategy = FieldStrategy.ALWAYS) + private Object extend; + + /** + * 是否可见;隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见 + */ + @Schema(title = "是否可见", + description = "是否可见。隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private Integer isShow; + + /** + * 类型;菜单MENU或目录CATALOG + */ + @Schema(title = "类型", + description = "类型。菜单MENU或目录CATALOG") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private SysMenuTypeEnum type; + + /** + * 图标 + */ + @Schema(title = "图标", + description = "图标") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String icon; + + /** + * 主题颜色 + */ + @Schema(title = "主题颜色", + description = "主题颜色") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private String color; + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/enums/SysMenuTypeEnum.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/enums/SysMenuTypeEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..03cb4e49c61536526b6b8c91af77797f1bd9ecc7 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/enums/SysMenuTypeEnum.java @@ -0,0 +1,40 @@ +package top.milkbox.sys.modular.menu.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; + +/** + * 菜单类型枚举
+ * 创建时间: 2024-01-29 下午 12:02 + * + * @author milkbox + */ +@AllArgsConstructor // 如果使用此注解,请勿随意修改成员变量的定义顺序 +public enum SysMenuTypeEnum { + + MENU("菜单", "MENU"), + CATEGORY("目录", "CATEGORY"); + + private final String label; + + @EnumValue // mybatis-plus控制数据库字段,数据库中保存的字段。如果数据库中的字段与不在枚举中则返回空 + private final String value; + + public String getLabel() { + return label; + } + + @JsonValue // jackson的标识,用于json转枚举的时候使用的字段 + public String getValue() { + return value; + } + + /** + * 枚举对象转为json的时候,字段的值 + */ + @Override + public String toString() { + return value; + } +} diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/mapper/SysMenuMapper.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/mapper/SysMenuMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..6ebb1f19a7dd8f51485aded95e72b0ffc4e104e8 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/mapper/SysMenuMapper.java @@ -0,0 +1,16 @@ +package top.milkbox.sys.modular.menu.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; + +/** + * 系统_菜单表(sys_menu)表数据库访问层 + * + * @author milkbox + * @date 2024-1-29 + */ +@Mapper +public interface SysMenuMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/mapper/mapping/SysMenuMapper.xml b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/mapper/mapping/SysMenuMapper.xml new file mode 100644 index 0000000000000000000000000000000000000000..3d5da26469e008bca617c5cb3ecf263b8e1ef409 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/mapper/mapping/SysMenuMapper.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuAddParam.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuAddParam.java new file mode 100644 index 0000000000000000000000000000000000000000..587fa20edd4d16c769a10c9b58b245280bd426f5 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuAddParam.java @@ -0,0 +1,102 @@ +package top.milkbox.sys.modular.menu.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import jakarta.validation.constraints.NotBlank; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; +import top.milkbox.sys.modular.menu.enums.SysMenuTypeEnum; + +/** + * 添加参数对象 + * + * @author milkbox + * @date 2024-1-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysMenuAddParam implements Serializable { + + /** + * 上级id + */ + @Schema(title = "上级id", + description = "上级id") + @NotBlank(message = "上级id不能为空") + private String parentId; + + /** + * 中文名 + */ + @Schema(title = "中文名", + description = "中文名") + private String title; + + /** + * 组件唯一别名 + */ + @Schema(title = "组件唯一别名", + description = "组件唯一别名") + private String name; + + /** + * 组件的导包路径;相对于组件的基准目录,基准目录单独配置,开头不加反斜杠 + */ + @Schema(title = "组件的导包路径", + description = "组件的导包路径。相对于组件的基准目录,基准目录单独配置,开头不加反斜杠") + private String component; + + /** + * 相对于父级的路由地址;开头要加反斜杠,可以多级 + */ + @Schema(title = "相对于父级的路由地址", + description = "相对于父级的路由地址。开头要加反斜杠,可以多级") + private String path; + + /** + * 重定向地址;当这个字段不为空表示有重定向,开启重定向后component字段失效 + */ + @Schema(title = "重定向地址", + description = "重定向地址。当这个字段不为空表示有重定向,开启重定向后component字段失效") + private String redirect; + + /** + * 扩展信息;Json格式 + */ + @Schema(title = "扩展信息", + description = "扩展信息。Json格式") + private Object extend; + + /** + * 是否可见;隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见 + */ + @Schema(title = "是否可见", + description = "是否可见。隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见") + private Integer isShow; + + /** + * 类型;菜单MENU或目录CATALOG + */ + @Schema(title = "类型", + description = "类型。菜单MENU或目录CATALOG") + private SysMenuTypeEnum type; + + /** + * 图标 + */ + @Schema(title = "图标", + description = "图标") + private String icon; + + /** + * 主题颜色 + */ + @Schema(title = "主题颜色", + description = "主题颜色") + private String color; + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuEditParam.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuEditParam.java new file mode 100644 index 0000000000000000000000000000000000000000..b07a658151a4a292a4a413fff4d10df75f0157e2 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuEditParam.java @@ -0,0 +1,111 @@ +package top.milkbox.sys.modular.menu.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.NotBlank; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; +import top.milkbox.sys.modular.menu.enums.SysMenuTypeEnum; + +/** + * 编辑参数对象 + * + * @author milkbox + * @date 2024-1-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysMenuEditParam implements Serializable { + + /** + * 主键 + */ + @Schema(title = "主键", + description = "主键") + @NotNull(message = "主键不能为空") + private Integer id; + + /** + * 上级id + */ + @Schema(title = "上级id", + description = "上级id") + @NotBlank(message = "上级id不能为空") + private String parentId; + + /** + * 中文名 + */ + @Schema(title = "中文名", + description = "中文名") + private String title; + + /** + * 组件唯一别名 + */ + @Schema(title = "组件唯一别名", + description = "组件唯一别名") + private String name; + + /** + * 组件的导包路径;相对于组件的基准目录,基准目录单独配置,开头不加反斜杠 + */ + @Schema(title = "组件的导包路径", + description = "组件的导包路径。相对于组件的基准目录,基准目录单独配置,开头不加反斜杠") + private String component; + + /** + * 相对于父级的路由地址;开头要加反斜杠,可以多级 + */ + @Schema(title = "相对于父级的路由地址", + description = "相对于父级的路由地址。开头要加反斜杠,可以多级") + private String path; + + /** + * 重定向地址;当这个字段不为空表示有重定向,开启重定向后component字段失效 + */ + @Schema(title = "重定向地址", + description = "重定向地址。当这个字段不为空表示有重定向,开启重定向后component字段失效") + private String redirect; + + /** + * 扩展信息;Json格式 + */ + @Schema(title = "扩展信息", + description = "扩展信息。Json格式") + private Object extend; + + /** + * 是否可见;隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见 + */ + @Schema(title = "是否可见", + description = "是否可见。隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见") + private Integer isShow; + + /** + * 类型;菜单MENU或目录CATALOG + */ + @Schema(title = "类型", + description = "类型。菜单MENU或目录CATALOG") + private SysMenuTypeEnum type; + + /** + * 图标 + */ + @Schema(title = "图标", + description = "图标") + private String icon; + + /** + * 主题颜色 + */ + @Schema(title = "主题颜色", + description = "主题颜色") + private String color; + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuIdParam.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuIdParam.java new file mode 100644 index 0000000000000000000000000000000000000000..ccdcaf52b3cd9b84db9aaf4b5def25b587ebf4ef --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuIdParam.java @@ -0,0 +1,30 @@ +package top.milkbox.sys.modular.menu.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 主键参数对象 + * + * @author milkbox + * @date 2024-1-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysMenuIdParam implements Serializable { + + /** + * 主键 + */ + @Schema(title = "主键", + description = "主键") + @NotNull(message = "主键不能为空") + private Integer id; + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuPageParam.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuPageParam.java new file mode 100644 index 0000000000000000000000000000000000000000..94097ab40d5b2625b2fe62ee8273641f32fa3c6b --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/param/SysMenuPageParam.java @@ -0,0 +1,103 @@ +package top.milkbox.sys.modular.menu.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import top.milkbox.common.pojo.CommonPageParam; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; +import top.milkbox.sys.modular.menu.enums.SysMenuTypeEnum; + +import java.io.Serializable; + +/** + * 分页参数对象 + * + * @author milkbox + * @date 2024-1-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class SysMenuPageParam extends CommonPageParam implements Serializable { + + /** + * 上级id + */ + @Schema(title = "上级id", + description = "上级id") + private String parentId; + + /** + * 中文名 + */ + @Schema(title = "中文名", + description = "中文名") + private String title; + + /** + * 组件唯一别名 + */ + @Schema(title = "组件唯一别名", + description = "组件唯一别名") + private String name; + + /** + * 组件的导包路径;相对于组件的基准目录,基准目录单独配置,开头不加反斜杠 + */ + @Schema(title = "组件的导包路径", + description = "组件的导包路径。相对于组件的基准目录,基准目录单独配置,开头不加反斜杠") + private String component; + + /** + * 相对于父级的路由地址;开头要加反斜杠,可以多级 + */ + @Schema(title = "相对于父级的路由地址", + description = "相对于父级的路由地址。开头要加反斜杠,可以多级") + private String path; + + /** + * 重定向地址;当这个字段不为空表示有重定向,开启重定向后component字段失效 + */ + @Schema(title = "重定向地址", + description = "重定向地址。当这个字段不为空表示有重定向,开启重定向后component字段失效") + private String redirect; + + /** + * 扩展信息;Json格式 + */ + @Schema(title = "扩展信息", + description = "扩展信息。Json格式") + private Object extend; + + /** + * 是否可见;隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见 + */ + @Schema(title = "是否可见", + description = "是否可见。隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见") + private Integer isShow; + + /** + * 类型;菜单MENU或目录CATALOG + */ + @Schema(title = "类型", + description = "类型。菜单MENU或目录CATALOG") + private SysMenuTypeEnum type; + + /** + * 图标 + */ + @Schema(title = "图标", + description = "图标") + private String icon; + + /** + * 主题颜色 + */ + @Schema(title = "主题颜色", + description = "主题颜色") + private String color; + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/service/SysMenuService.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/service/SysMenuService.java new file mode 100644 index 0000000000000000000000000000000000000000..ea32e88e9a1f6c032914544c70877613c6324954 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/service/SysMenuService.java @@ -0,0 +1,75 @@ +package top.milkbox.sys.modular.menu.service; + +import cn.hutool.core.lang.tree.Tree; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; +import top.milkbox.sys.modular.menu.param.SysMenuAddParam; +import top.milkbox.sys.modular.menu.param.SysMenuEditParam; +import top.milkbox.sys.modular.menu.param.SysMenuIdParam; +import top.milkbox.sys.modular.menu.param.SysMenuPageParam; +import top.milkbox.sys.modular.menu.vo.SysMenuVo; + +import java.util.List; + +/** + * 系统_菜单表(sys_menu)服务层接口 + * + * @author milkbox + * @date 2024-1-29 + */ +public interface SysMenuService extends IService { + + /** + * 添加 + * + * @param addParam 添加参数 + */ + void add(SysMenuAddParam addParam); + + /** + * 删除 + * + * @param paramList 删除id对象集合 + */ + void delete(List paramList); + + /** + * 通过id编辑 + * + * @param editParam 编辑参数 + */ + void edit(SysMenuEditParam editParam); + + /** + * 通过id查询详情 + * + * @param idParam id参数 + * @return 返回查询的详情,如果没有则返回空 + */ + SysMenuVo detail(SysMenuIdParam idParam); + + /** + * 查询实体,即简单查询,包含存在性校验,不存在报业务异常 + * + * @param entityId 实体id + * @return 返回实体 + */ + SysMenuEntity findEntity(Integer entityId); + + +// /** +// * 分页查询 +// * +// * @param pageParam 分页查询参数 +// * @return 返回苞米豆的分页对象,没有数据,则record长度为0 +// */ +// Page page(SysMenuPageParam pageParam); + + /** + * 获取当前登录用户拥有权限的菜单森林 + * + * @return 菜单森林 + */ + List> forest(); +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/service/impl/SysMenuServiceImpl.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/service/impl/SysMenuServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..bc6b17e69f94711d41920e8d33089e89822df9f9 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/service/impl/SysMenuServiceImpl.java @@ -0,0 +1,114 @@ +package top.milkbox.sys.modular.menu.service.impl; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.tree.Tree; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import top.milkbox.common.enums.CommonSortTypeEnum; +import top.milkbox.common.exceprion.CommonServiceException; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; +import top.milkbox.sys.modular.menu.mapper.SysMenuMapper; +import top.milkbox.sys.modular.menu.param.SysMenuAddParam; +import top.milkbox.sys.modular.menu.param.SysMenuEditParam; +import top.milkbox.sys.modular.menu.param.SysMenuIdParam; +import top.milkbox.sys.modular.menu.param.SysMenuPageParam; +import top.milkbox.sys.modular.menu.service.SysMenuService; +import top.milkbox.sys.modular.menu.vo.SysMenuVo; +import top.milkbox.common.utils.CommonUtil; + +import java.util.List; + +/** + * 系统_菜单表(sys_menu)服务层实现类 + * + * @author milkbox + * @date 2024-1-29 + */ +@Slf4j +@Service +@AllArgsConstructor +public class SysMenuServiceImpl extends ServiceImpl implements SysMenuService { + + private SysMenuMapper sysMenuMapper; + + @Override + public void add(SysMenuAddParam addParam) { + SysMenuEntity entity = BeanUtil.toBean(addParam, SysMenuEntity.class); + super.save(entity); + } + + @Override + public void delete(List paramList) { + super.removeByIds(paramList.stream().map(SysMenuIdParam::getId).toList()); + } + + @Override + public void edit(SysMenuEditParam editParam) { + findEntity(editParam.getId()); + SysMenuEntity entity = BeanUtil.toBean(editParam, SysMenuEntity.class); + super.updateById(entity); + } + + @Override + public SysMenuVo detail(SysMenuIdParam idParam) { + SysMenuEntity entity = findEntity(idParam.getId()); + SysMenuVo vo = BeanUtil.toBean(entity, SysMenuVo.class); + // 此处进行数据翻译操作,,根据不同的业务逻辑将entity对象转为vo对象...... + + return vo; + } + + @Override + public SysMenuEntity findEntity(Integer entityId) { + SysMenuEntity entity = super.getById(entityId); + if (ObjectUtil.isEmpty(entity)) { + throw new CommonServiceException("实体未找到({})", entityId); + } + return entity; + } + +// @Override +// public Page page(SysMenuPageParam pageParam) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// if (ObjectUtil.isAllNotEmpty(pageParam.getSortField(), pageParam.getSortType())) { +// queryWrapper.orderBy(true, +// pageParam.getSortType() == CommonSortTypeEnum.ASC, +// StrUtil.toUnderlineCase(pageParam.getSortField())); +// } else { +// queryWrapper.lambda().orderByAsc(SysMenuEntity::getSortCode); +// } +// queryWrapper.lambda().orderByAsc(SysMenuEntity::getId); +// +// Page entityPage = super.page(pageParam.toBaomidouPage(), queryWrapper); +// // 此处进行远程调用或关联查询...... +// +// Page voPage = CommonUtil.convertPage(entityPage, entity -> { +// SysMenuVo vo = BeanUtil.toBean(entity, SysMenuVo.class); +// // 此处进行数据翻译操作,根据不同的业务逻辑将entity对象转为vo对象...... +// +// return vo; +// }); +// return voPage; +// } + + + @Override + public List> forest() { + int loginUserId = StpUtil.getLoginIdAsInt(); + // TODO 获取当前登录用户拥有权限的菜单森林 + // 查询用户所属的角色拥有权限的菜单id集合 + // 查询用户独有权限的菜单id集合 + // 合并两个集合 + // 根据id集合查询菜单表 + // 将菜单表转换为森林结构 + return null; + } + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/vo/SysMenuVo.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/vo/SysMenuVo.java new file mode 100644 index 0000000000000000000000000000000000000000..d06abb7d2db310e1f412cf9edc6296cd2dba54bd --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/menu/vo/SysMenuVo.java @@ -0,0 +1,111 @@ +package top.milkbox.sys.modular.menu.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import top.milkbox.common.pojo.CommonVo; +import top.milkbox.sys.modular.menu.entity.SysMenuEntity; +import top.milkbox.sys.modular.menu.enums.SysMenuTypeEnum; + +import java.io.Serializable; + +/** + * 系统_菜单表默认vo + * + * @author milkbox + * @date 2024-1-29 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = true) +@Schema(description = "SysMenuEntity 系统_菜单表。") +public class SysMenuVo extends CommonVo implements Serializable { + + /** + * 主键 + */ + @Schema(title = "主键", + description = "主键") + private Integer id; + + /** + * 上级id + */ + @Schema(title = "上级id", + description = "上级id") + private String parentId; + + /** + * 中文名 + */ + @Schema(title = "中文名", + description = "中文名") + private String title; + + /** + * 组件唯一别名 + */ + @Schema(title = "组件唯一别名", + description = "组件唯一别名") + private String name; + + /** + * 组件的导包路径;相对于组件的基准目录,基准目录单独配置,开头不加反斜杠 + */ + @Schema(title = "组件的导包路径", + description = "组件的导包路径。相对于组件的基准目录,基准目录单独配置,开头不加反斜杠") + private String component; + + /** + * 相对于父级的路由地址;开头要加反斜杠,可以多级 + */ + @Schema(title = "相对于父级的路由地址", + description = "相对于父级的路由地址。开头要加反斜杠,可以多级") + private String path; + + /** + * 重定向地址;当这个字段不为空表示有重定向,开启重定向后component字段失效 + */ + @Schema(title = "重定向地址", + description = "重定向地址。当这个字段不为空表示有重定向,开启重定向后component字段失效") + private String redirect; + + /** + * 扩展信息;Json格式 + */ + @Schema(title = "扩展信息", + description = "扩展信息。Json格式") + private Object extend; + + /** + * 是否可见;隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见 + */ + @Schema(title = "是否可见", + description = "是否可见。隐藏后可以访问页面,但不在菜单列表显示。1可见,0不可见") + private Integer isShow; + + /** + * 类型;菜单MENU或目录CATALOG + */ + @Schema(title = "类型", + description = "类型。菜单MENU或目录CATALOG") + private SysMenuTypeEnum type; + + /** + * 图标 + */ + @Schema(title = "图标", + description = "图标") + private String icon; + + /** + * 主题颜色 + */ + @Schema(title = "主题颜色", + description = "主题颜色") + private String color; + +} \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/controller/SysRelationshipController.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/controller/SysRelationshipController.java index 116e61914863e28723b86de22f17dd4e403badbd..cc93346c7fa84f768a1ae3571b157b604c8101a4 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/controller/SysRelationshipController.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/controller/SysRelationshipController.java @@ -11,6 +11,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import top.milkbox.common.annotation.CommonLog; import top.milkbox.common.enums.LogTypeEnum; +import top.milkbox.common.validation.annotation.CollectionElementNotNull; import top.milkbox.sys.core.config.SysConfiguration; import top.milkbox.sys.modular.relationship.param.SysRelationshipAddParam; import top.milkbox.sys.modular.relationship.param.SysRelationshipEditParam; @@ -37,51 +38,51 @@ public class SysRelationshipController { private SysRelationshipService sysRelationshipService; - @PostMapping("/add") - @Operation(summary = "添加", description = "添加一条数据") - @CommonLog(value = "添加", description = "添加一条数据", - module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.INSERT) - public CommonResult add(@Validated @RequestBody SysRelationshipAddParam addParam) { - sysRelationshipService.add(addParam); - return CommonResult.ok(); - } - - @DeleteMapping("/delete") - @Operation(summary = "批量删除") - @CommonLog(value = "批量删除", module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.DELETE) - public CommonResult delete( - @Validated - @RequestBody - @Size(min = 1, message = "请至少传递一个删除对象") - List<@Valid SysRelationshipIdParam> paramList - ) { - sysRelationshipService.delete(paramList); - return CommonResult.ok(); - } - - @PutMapping("/edit") - @Operation(summary = "修改", description = "修改一条数据") - @CommonLog(value = "修改", description = "修改一条数据", - module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.UPDATE) - public CommonResult edit(@Validated @RequestBody SysRelationshipEditParam editParam) { - sysRelationshipService.edit(editParam); - return CommonResult.ok(); - } - - @GetMapping("/detail") - @Operation(summary = "详情", description = "查询一条数据的详情") - @CommonLog(value = "详情", description = "查询一条数据的详情", - module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) - public CommonResult detail(@Validated SysRelationshipIdParam idParam) { - return CommonResult.ok(sysRelationshipService.detail(idParam)); - } - - @GetMapping("/page") - @Operation(summary = "分页查询", description = "查询条件分页查询") - @CommonLog(value = "分页查询", description = "查询条件分页查询", - module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) - public CommonResult> page(@Validated SysRelationshipPageParam pageParam) { - return CommonResult.ok(sysRelationshipService.page(pageParam)); - } +// @PostMapping("/add") +// @Operation(summary = "添加", description = "添加一条数据") +// @CommonLog(value = "添加", description = "添加一条数据", +// module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.INSERT) +// public CommonResult add(@Validated @RequestBody SysRelationshipAddParam addParam) { +// sysRelationshipService.add(addParam); +// return CommonResult.ok(); +// } +// +// @DeleteMapping("/delete") +// @Operation(summary = "批量删除") +// @CommonLog(value = "批量删除", module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.DELETE) +// public CommonResult delete( +// @RequestBody +// @Size(min = 1, message = "请至少传递一个删除对象") +// @CollectionElementNotNull(message = "集合中的删除对象不能为空") +// List<@Valid SysRelationshipIdParam> paramList +// ) { +// sysRelationshipService.delete(paramList); +// return CommonResult.ok(); +// } +// +// @PutMapping("/edit") +// @Operation(summary = "修改", description = "修改一条数据") +// @CommonLog(value = "修改", description = "修改一条数据", +// module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.UPDATE) +// public CommonResult edit(@Validated @RequestBody SysRelationshipEditParam editParam) { +// sysRelationshipService.edit(editParam); +// return CommonResult.ok(); +// } +// +// @GetMapping("/detail") +// @Operation(summary = "详情", description = "查询一条数据的详情") +// @CommonLog(value = "详情", description = "查询一条数据的详情", +// module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) +// public CommonResult detail(@Validated SysRelationshipIdParam idParam) { +// return CommonResult.ok(sysRelationshipService.detail(idParam)); +// } +// +// @GetMapping("/page") +// @Operation(summary = "分页查询", description = "查询条件分页查询") +// @CommonLog(value = "分页查询", description = "查询条件分页查询", +// module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.SELECT) +// public CommonResult> page(@Validated SysRelationshipPageParam pageParam) { +// return CommonResult.ok(sysRelationshipService.page(pageParam)); +// } } \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/enums/SysRelationshipTypeEnum.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/enums/SysRelationshipTypeEnum.java index ad37c614c2f2ea2d28ec017d9060c7582d32c375..ab935927275f7b4147eebbbf26531aa32b770b4d 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/enums/SysRelationshipTypeEnum.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/enums/SysRelationshipTypeEnum.java @@ -14,7 +14,7 @@ import lombok.AllArgsConstructor; public enum SysRelationshipTypeEnum { /** - * 用户与角色关系(用户属于哪些角色) + * 用户与角色关系(用户属于哪些角色,用户为object_id,角色为target_id) */ SYS_USER_RELATE_SYS_ROLE("用户与角色关系", "SYS_USER_RELATE_SYS_ROLE"), diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/SysRelationshipService.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/SysRelationshipService.java index 92ad4181fb812acaace09e896cfc2e2ef0a3c505..6b823f14620902175468ea9afc50c4576187f3fa 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/SysRelationshipService.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/SysRelationshipService.java @@ -2,12 +2,14 @@ package top.milkbox.sys.modular.relationship.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import top.milkbox.common.bo.EntityColumnExistence; import top.milkbox.sys.modular.relationship.entity.SysRelationshipEntity; import top.milkbox.sys.modular.relationship.param.SysRelationshipAddParam; import top.milkbox.sys.modular.relationship.param.SysRelationshipEditParam; import top.milkbox.sys.modular.relationship.param.SysRelationshipIdParam; import top.milkbox.sys.modular.relationship.param.SysRelationshipPageParam; import top.milkbox.sys.modular.relationship.vo.SysRelationshipVo; +import top.milkbox.sys.modular.role.param.SysRoleAuthorizationUserParam; import java.util.List; @@ -55,13 +57,34 @@ public interface SysRelationshipService extends IService * @return 返回实体 */ SysRelationshipEntity findEntity(Integer entityId); +// +// /** +// * 分页查询 +// * +// * @param pageParam 分页查询参数 +// * @return 返回苞米豆的分页对象,没有数据,则record长度为0 +// */ +// Page page(SysRelationshipPageParam pageParam); /** - * 分页查询 + * 通过target字段删除 * - * @param pageParam 分页查询参数 - * @return 返回苞米豆的分页对象,没有数据,则record长度为0 + * @param deleteTargetList 要删除的记录的target字段集合 */ - Page page(SysRelationshipPageParam pageParam); + void deleteByTarget(List deleteTargetList); + + /** + * 重新给角色授权用户 + * + * @param assignUserParam 角色id与用户id集合 + */ + EntityColumnExistence reauthorizationUsers(SysRoleAuthorizationUserParam assignUserParam); + + /** + * 给角色授权新用户,新用户中不具有此角色的将被授权,已经拥有此角色的不变 + * + * @param assignUserParam 角色id与用户id集合 + */ + EntityColumnExistence incrementAuthorizationUsers(SysRoleAuthorizationUserParam assignUserParam); } \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/impl/SysRelationshipServiceImpl.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/impl/SysRelationshipServiceImpl.java index 9c6e07641ada3af0600f81dc1ac85ddf448e2853..abfefb3e097d91759217efaa78ac57e7d3330225 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/impl/SysRelationshipServiceImpl.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/relationship/service/impl/SysRelationshipServiceImpl.java @@ -2,25 +2,31 @@ package top.milkbox.sys.modular.relationship.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import top.milkbox.common.enums.CommonSortTypeEnum; +import org.springframework.transaction.annotation.Transactional; +import top.milkbox.common.bo.EntityColumnExistence; import top.milkbox.common.exceprion.CommonServiceException; import top.milkbox.sys.modular.relationship.entity.SysRelationshipEntity; +import top.milkbox.sys.modular.relationship.enums.SysRelationshipTypeEnum; import top.milkbox.sys.modular.relationship.mapper.SysRelationshipMapper; import top.milkbox.sys.modular.relationship.param.SysRelationshipAddParam; import top.milkbox.sys.modular.relationship.param.SysRelationshipEditParam; import top.milkbox.sys.modular.relationship.param.SysRelationshipIdParam; -import top.milkbox.sys.modular.relationship.param.SysRelationshipPageParam; import top.milkbox.sys.modular.relationship.service.SysRelationshipService; import top.milkbox.sys.modular.relationship.vo.SysRelationshipVo; -import top.milkbox.common.utils.CommonUtil; +import top.milkbox.sys.modular.role.entity.SysRoleEntity; +import top.milkbox.sys.modular.role.param.SysRoleAuthorizationUserParam; +import top.milkbox.sys.modular.role.service.SysRoleService; +import top.milkbox.sys.modular.user.entity.SysUserEntity; +import top.milkbox.sys.modular.user.service.SysUserService; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -32,10 +38,15 @@ import java.util.List; @Slf4j @Service @AllArgsConstructor -public class SysRelationshipServiceImpl extends ServiceImpl implements SysRelationshipService { +public class SysRelationshipServiceImpl + extends ServiceImpl + implements SysRelationshipService { private SysRelationshipMapper sysRelationshipMapper; + private SysUserService sysUserService; + private SysRoleService sysRoleService; + @Override public void add(SysRelationshipAddParam addParam) { SysRelationshipEntity entity = BeanUtil.toBean(addParam, SysRelationshipEntity.class); @@ -72,28 +83,107 @@ public class SysRelationshipServiceImpl extends ServiceImpl page(SysRelationshipPageParam pageParam) { +// QueryWrapper queryWrapper = new QueryWrapper<>(); +// if (ObjectUtil.isAllNotEmpty(pageParam.getSortField(), pageParam.getSortType())) { +// queryWrapper.orderBy(true, +// pageParam.getSortType() == CommonSortTypeEnum.ASC, +// StrUtil.toUnderlineCase(pageParam.getSortField())); +// } else { +// queryWrapper.lambda().orderByAsc(SysRelationshipEntity::getSortCode); +// } +// queryWrapper.lambda().orderByAsc(SysRelationshipEntity::getId); +// +// Page entityPage = super.page(pageParam.toBaomidouPage(), queryWrapper); +// // 此处进行远程调用或关联查询...... +// +// Page voPage = CommonUtil.convertPage(entityPage, entity -> { +// SysRelationshipVo vo = BeanUtil.toBean(entity, SysRelationshipVo.class); +// // 此处进行数据翻译操作,根据不同的业务逻辑将entity对象转为vo对象...... +// +// return vo; +// }); +// return voPage; +// } + + @Override - public Page page(SysRelationshipPageParam pageParam) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - if (ObjectUtil.isAllNotEmpty(pageParam.getSortField(), pageParam.getSortType())) { - queryWrapper.orderBy(true, - pageParam.getSortType() == CommonSortTypeEnum.ASC, - StrUtil.toUnderlineCase(pageParam.getSortField())); - } else { - queryWrapper.lambda().orderByAsc(SysRelationshipEntity::getSortCode); + public void deleteByTarget(List deleteTargetList) { + if (ObjectUtil.isEmpty(deleteTargetList)) { + return; } - queryWrapper.lambda().orderByAsc(SysRelationshipEntity::getId); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.in(SysRelationshipEntity::getTargetId, deleteTargetList); + super.remove(queryWrapper); + } - Page entityPage = super.page(pageParam.toBaomidouPage(), queryWrapper); - // 此处进行远程调用或关联查询...... + @Override + @Transactional(rollbackFor = Exception.class) + public EntityColumnExistence reauthorizationUsers(SysRoleAuthorizationUserParam reauthorizationUserParam) { + // 检查角色是否存在 + sysRoleService.findEntity(reauthorizationUserParam.getRoleId()); + // 检查用户列表中的用户是否都存在 + EntityColumnExistence columnExistence = sysUserService.filterDoesNotExistColumn( + SysUserEntity::getId, reauthorizationUserParam.getUserIdList()); + if (ObjectUtil.isEmpty(columnExistence.getExistColumnList())) { + throw new CommonServiceException("被授权的用户全部都不存在"); + } + // 构造实体集合 + List relationshipEntityList = + columnExistence.getExistColumnList().stream().map(userId -> { + SysRelationshipEntity relationshipEntity = new SysRelationshipEntity(); + relationshipEntity.setObjectId(userId); + relationshipEntity.setTargetId(reauthorizationUserParam.getRoleId()); + relationshipEntity.setCategory(SysRelationshipTypeEnum.SYS_USER_RELATE_SYS_ROLE); + return relationshipEntity; + }).toList(); + // 删除此角色原来的授权信息 + deleteByTarget(Collections.singletonList(reauthorizationUserParam.getRoleId())); + // 保存实体集合 + saveBatch(relationshipEntityList); + return columnExistence; + } - Page voPage = CommonUtil.convertPage(entityPage, entity -> { - SysRelationshipVo vo = BeanUtil.toBean(entity, SysRelationshipVo.class); - // 此处进行数据翻译操作,根据不同的业务逻辑将entity对象转为vo对象...... + @Override + @Transactional(rollbackFor = Exception.class) + public EntityColumnExistence incrementAuthorizationUsers( + SysRoleAuthorizationUserParam incrementAuthorizationUserParam) { + // 检查角色是否存在 + sysRoleService.findEntity(incrementAuthorizationUserParam.getRoleId()); + // 检查用户列表中的用户是否都存在 + EntityColumnExistence columnExistence = sysUserService.filterDoesNotExistColumn( + SysUserEntity::getId, incrementAuthorizationUserParam.getUserIdList()); + if (ObjectUtil.isEmpty(columnExistence.getExistColumnList())) { + throw new CommonServiceException("被授权的用户全部都不存在"); + } - return vo; - }); - return voPage; - } + // 查询此角色授权的信息 + LambdaQueryWrapper relationshipQueryWrapper = new LambdaQueryWrapper<>(); + relationshipQueryWrapper.eq(SysRelationshipEntity::getTargetId, incrementAuthorizationUserParam.getRoleId()) + .eq(SysRelationshipEntity::getCategory, SysRelationshipTypeEnum.SYS_USER_RELATE_SYS_ROLE); + List roleRelationshipList = list(relationshipQueryWrapper); -} \ No newline at end of file + // 去掉已经授权的用户 + List incrementAuthorizationUserIdList = new ArrayList<>(columnExistence.getExistColumnList()); + incrementAuthorizationUserIdList.removeAll(roleRelationshipList.stream() + .map(SysRelationshipEntity::getObjectId).toList()); + + if (ObjectUtil.isEmpty(incrementAuthorizationUserIdList)) { + throw new CommonServiceException("无新增授权用户"); + } + + // 将新的用户与角色关系保存 + List relationshipEntityList = incrementAuthorizationUserIdList.stream() + .map(userId -> { + SysRelationshipEntity relationshipEntity = new SysRelationshipEntity(); + relationshipEntity.setObjectId(userId); + relationshipEntity.setTargetId(incrementAuthorizationUserParam.getRoleId()); + relationshipEntity.setCategory(SysRelationshipTypeEnum.SYS_USER_RELATE_SYS_ROLE); + return relationshipEntity; + }).toList(); + saveBatch(relationshipEntityList); + + return columnExistence; + } +} diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/controller/SysRoleController.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/controller/SysRoleController.java index abcf719cf47d0fe65345289ec24d0c0fb4e1ea5e..c967a7829455f3c47693c4dc5dce3610d18c0ef8 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/controller/SysRoleController.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/controller/SysRoleController.java @@ -1,6 +1,8 @@ package top.milkbox.sys.modular.role.controller; import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -10,12 +12,12 @@ import lombok.AllArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import top.milkbox.common.annotation.CommonLog; +import top.milkbox.common.bo.EntityColumnExistence; import top.milkbox.common.enums.LogTypeEnum; +import top.milkbox.common.validation.annotation.CollectionElementNotNull; import top.milkbox.sys.core.config.SysConfiguration; -import top.milkbox.sys.modular.role.param.SysRoleAddParam; -import top.milkbox.sys.modular.role.param.SysRoleEditParam; -import top.milkbox.sys.modular.role.param.SysRoleIdParam; -import top.milkbox.sys.modular.role.param.SysRolePageParam; +import top.milkbox.sys.modular.relationship.service.SysRelationshipService; +import top.milkbox.sys.modular.role.param.*; import top.milkbox.sys.modular.role.service.SysRoleService; import top.milkbox.sys.modular.role.vo.SysRoleVo; import top.milkbox.common.pojo.CommonResult; @@ -35,6 +37,8 @@ import java.util.List; @Tag(name = "角色表控制器", description = "SysRoleController") public class SysRoleController { + private SysRelationshipService sysRelationshipService; + private SysRoleService sysRoleService; @PostMapping("/add") @@ -50,9 +54,9 @@ public class SysRoleController { @Operation(summary = "批量删除") @CommonLog(value = "批量删除", module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.DELETE) public CommonResult delete( - @Validated @RequestBody @Size(min = 1, message = "请至少传递一个删除对象") + @CollectionElementNotNull(message = "集合中的删除对象不能为空") List<@Valid SysRoleIdParam> paramList ) { sysRoleService.delete(paramList); @@ -84,4 +88,50 @@ public class SysRoleController { return CommonResult.ok(sysRoleService.page(pageParam)); } +// @PostMapping("/reauthorizationUserOld") +// @Operation(summary = "重新授权用户,旧", description = "重新给角色授权用户") +// @CommonLog(value = "重新授权用户,旧", description = "重新给角色授权用户", +// module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.NOT) +// public CommonResult reauthorizationUserOld( +// @Validated @RequestBody SysRoleAuthorizationUserParam reauthorizationUserParam) { +// +// EntityColumnExistence columnExistence = sysRoleService.reauthorizationUser(reauthorizationUserParam); +// if (ObjectUtil.isEmpty(columnExistence.getDoesNotExistColumnList())) { +// return CommonResult.ok(); +// } +// +// return CommonResult.ok("用户" + JSONUtil.toJsonStr(columnExistence.getExistColumnList()) + "已授权成功。" +// + "用户" + JSONUtil.toJsonStr(columnExistence.getDoesNotExistColumnList()) +// + "由于不存在所以授权失败。", +// null); +// } + + + @PostMapping("/reauthorizationUsers") + @Operation(summary = "重新授权用户", description = "重新给角色授权用户") + @CommonLog(value = "重新授权用户", description = "重新给角色授权用户", + module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.UPDATE) + public CommonResult reauthorizationUsers( + @Validated @RequestBody SysRoleAuthorizationUserParam reauthorizationUserParam) { + + EntityColumnExistence columnExistence = + sysRelationshipService.reauthorizationUsers(reauthorizationUserParam); + if (ObjectUtil.isEmpty(columnExistence.getDoesNotExistColumnList())) { + return CommonResult.ok(); + } + + return CommonResult.ok("用户" + JSONUtil.toJsonStr(columnExistence.getExistColumnList()) + "已授权成功。" + + "用户" + JSONUtil.toJsonStr(columnExistence.getDoesNotExistColumnList()) + + "由于不存在所以授权失败。", null); + } + + @PostMapping("/incrementAuthorizationUsers") + @Operation(summary = "授权用户", description = "给角色授权新用户,新用户中不具有此角色的将被授权,已经拥有此角色的不变") + @CommonLog(value = "授权用户", description = "给角色授权新用户", + module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.UPDATE) + public CommonResult incrementAuthorizationUsers( + @Validated @RequestBody SysRoleAuthorizationUserParam reauthorizationUserParam) { + sysRelationshipService.incrementAuthorizationUsers(reauthorizationUserParam); + return CommonResult.ok(); + } } \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/param/SysRoleAuthorizationUserParam.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/param/SysRoleAuthorizationUserParam.java new file mode 100644 index 0000000000000000000000000000000000000000..5f164a8810757a12c822e7155eac2e6794a838e6 --- /dev/null +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/param/SysRoleAuthorizationUserParam.java @@ -0,0 +1,32 @@ +package top.milkbox.sys.modular.role.param; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import top.milkbox.common.validation.annotation.CollectionElementNotNull; + +import java.util.Set; + +/** + * 角色授权用户
+ * 创建时间: 2024-01-29 下午 3:27 + * + * @author milkbox + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class SysRoleAuthorizationUserParam { + + @Schema(title = "角色id", description = "角色id") + @NotNull(message = "角色id不能为空") + private Integer roleId; + + @Schema(title = "用户id集合", description = "被授权的用户id集合") + @Size(min = 1, max = 10000, message = "一次性授权用户的个数范围[1, 10000]") + @CollectionElementNotNull(message = "集合中的用户id不能为空") + private Set userIdList; +} diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/SysRoleService.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/SysRoleService.java index d30b545225484717e904efcd186d722cbb19ad12..1f90d0105bf3d57630f94b186f361d6b2e8a5214 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/SysRoleService.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/SysRoleService.java @@ -2,11 +2,9 @@ package top.milkbox.sys.modular.role.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import top.milkbox.common.bo.EntityColumnExistence; import top.milkbox.sys.modular.role.entity.SysRoleEntity; -import top.milkbox.sys.modular.role.param.SysRoleAddParam; -import top.milkbox.sys.modular.role.param.SysRoleEditParam; -import top.milkbox.sys.modular.role.param.SysRoleIdParam; -import top.milkbox.sys.modular.role.param.SysRolePageParam; +import top.milkbox.sys.modular.role.param.*; import top.milkbox.sys.modular.role.vo.SysRoleVo; import java.util.List; @@ -64,4 +62,10 @@ public interface SysRoleService extends IService { */ Page page(SysRolePageParam pageParam); +// /** +// * 重新给角色授权用户 +// * +// * @param assignUserParam 角色id与用户id集合 +// */ +// EntityColumnExistence reauthorizationUser(SysRoleAuthorizationUserParam assignUserParam); } \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/impl/SysRoleServiceImpl.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/impl/SysRoleServiceImpl.java index f18cdcbab1d7274bafc7e0af846579e38f2869bf..176b0ef256d3bb9db3f6281b66d194ac5005a823 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/impl/SysRoleServiceImpl.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/role/service/impl/SysRoleServiceImpl.java @@ -9,18 +9,23 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import top.milkbox.common.bo.EntityColumnExistence; import top.milkbox.common.enums.CommonSortTypeEnum; import top.milkbox.common.exceprion.CommonServiceException; +import top.milkbox.sys.modular.relationship.entity.SysRelationshipEntity; +import top.milkbox.sys.modular.relationship.enums.SysRelationshipTypeEnum; +import top.milkbox.sys.modular.relationship.service.SysRelationshipService; import top.milkbox.sys.modular.role.entity.SysRoleEntity; import top.milkbox.sys.modular.role.mapper.SysRoleMapper; -import top.milkbox.sys.modular.role.param.SysRoleAddParam; -import top.milkbox.sys.modular.role.param.SysRoleEditParam; -import top.milkbox.sys.modular.role.param.SysRoleIdParam; -import top.milkbox.sys.modular.role.param.SysRolePageParam; +import top.milkbox.sys.modular.role.param.*; import top.milkbox.sys.modular.role.service.SysRoleService; import top.milkbox.sys.modular.role.vo.SysRoleVo; import top.milkbox.common.utils.CommonUtil; +import top.milkbox.sys.modular.user.entity.SysUserEntity; +import top.milkbox.sys.modular.user.service.SysUserService; +import java.util.Collections; import java.util.List; /** @@ -36,18 +41,26 @@ public class SysRoleServiceImpl extends ServiceImpl paramList) { + // TODO 同时需要将关系表的角色信息删除 super.removeByIds(paramList.stream().map(SysRoleIdParam::getId).toList()); } @Override + @Transactional(rollbackFor = Exception.class) public void edit(SysRoleEditParam editParam) { findEntity(editParam.getId()); SysRoleEntity entity = BeanUtil.toBean(editParam, SysRoleEntity.class); @@ -96,4 +109,31 @@ public class SysRoleServiceImpl extends ServiceImpl reauthorizationUser(SysRoleAuthorizationUserParam reauthorizationUserParam) { +// // 检查角色是否存在 +// findEntity(reauthorizationUserParam.getRoleId()); +// // 检查用户列表中的用户是否都存在 +// EntityColumnExistence columnExistence = sysUserService.filterDoesNotExistColumn( +// SysUserEntity::getId, reauthorizationUserParam.getUserIdList()); +// if (ObjectUtil.isEmpty(columnExistence.getExistColumnList())) { +// throw new CommonServiceException("被授权的用户全部都不存在"); +// } +// // 构造实体集合 +// List relationshipEntityList = +// columnExistence.getExistColumnList().stream().map(userId -> { +// SysRelationshipEntity relationshipEntity = new SysRelationshipEntity(); +// relationshipEntity.setObjectId(userId); +// relationshipEntity.setTargetId(reauthorizationUserParam.getRoleId()); +// relationshipEntity.setCategory(SysRelationshipTypeEnum.SYS_USER_RELATE_SYS_ROLE); +// return relationshipEntity; +// }).toList(); +// // 删除此角色原来的授权信息 +// sysRelationshipService.deleteByTarget(Collections.singletonList(reauthorizationUserParam.getRoleId())); +// // 保存实体集合 +// sysRelationshipService.saveBatch(relationshipEntityList); +// return columnExistence; +// } + } \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/controller/SysUserController.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/controller/SysUserController.java index 378e57344568245879ec64e97819eef51625b159..aae0e23f4739f17269e48c17ef2b3981dd74bb32 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/controller/SysUserController.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/controller/SysUserController.java @@ -13,6 +13,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import top.milkbox.common.annotation.CommonLog; import top.milkbox.common.enums.LogTypeEnum; +import top.milkbox.common.validation.annotation.CollectionElementNotNull; import top.milkbox.sys.core.config.SysConfiguration; import top.milkbox.sys.modular.user.param.*; import top.milkbox.sys.modular.user.service.SysUserService; @@ -50,9 +51,9 @@ public class SysUserController { @Operation(summary = "批量删除") @CommonLog(value = "批量删除", module = SysConfiguration.MODULE_NAME, type = LogTypeEnum.DELETE) public CommonResult delete( - @Validated @RequestBody @Size(min = 1, message = "请至少传递一个删除对象") + @CollectionElementNotNull(message = "集合中的删除对象不能为空") List<@Valid SysUserIdParam> paramList ) { sysUserService.delete(paramList); @@ -118,4 +119,6 @@ public class SysUserController { sysUserService.logout(); return CommonResult.ok("登出成功", null); } + + // TODO 缺少接口,给用户分配角色assignRole } \ No newline at end of file diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/SysUserService.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/SysUserService.java index ba8a8f027a08c45a807e63aa9c18b196d6d57a27..d1dcc6898daff8e0ff1626b8ed65da3f61c08945 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/SysUserService.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/SysUserService.java @@ -1,7 +1,7 @@ package top.milkbox.sys.modular.user.service; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; +import top.milkbox.common.service.CommonService; import top.milkbox.sys.modular.user.entity.SysUserEntity; import top.milkbox.sys.modular.user.param.*; import top.milkbox.sys.modular.user.vo.SysUserVo; @@ -14,7 +14,7 @@ import java.util.List; * @author milkbox * @date 2024-1-23 */ -public interface SysUserService extends IService { +public interface SysUserService extends CommonService { /** * 添加 diff --git a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/impl/SysUserServiceImpl.java b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/impl/SysUserServiceImpl.java index d1f084eb1308256e6a1874608a6c913b2bbd2e29..dad219be0c2e334e8811f6e316384766519b6906 100644 --- a/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/impl/SysUserServiceImpl.java +++ b/milkbox-service/service-sys/src/main/java/top/milkbox/sys/modular/user/service/impl/SysUserServiceImpl.java @@ -8,12 +8,12 @@ import cn.hutool.crypto.digest.BCrypt; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import top.milkbox.common.enums.CommonSortTypeEnum; import top.milkbox.common.exceprion.CommonServiceException; +import top.milkbox.common.service.impl.CommonServiceImpl; import top.milkbox.sys.modular.user.entity.SysUserEntity; import top.milkbox.sys.modular.user.enums.SysUserGenderEnum; import top.milkbox.sys.modular.user.enums.SysUserStatusEnum; @@ -34,7 +34,7 @@ import java.util.List; @Slf4j @Service @AllArgsConstructor -public class SysUserServiceImpl extends ServiceImpl implements SysUserService { +public class SysUserServiceImpl extends CommonServiceImpl implements SysUserService { private SysUserMapper sysUserMapper; diff --git "a/\345\244\207\345\277\230\345\275\225.md" "b/\345\244\207\345\277\230\345\275\225.md" new file mode 100644 index 0000000000000000000000000000000000000000..9598fdec84e38eb7490b6266a7fb74c459e350a2 --- /dev/null +++ "b/\345\244\207\345\277\230\345\275\225.md" @@ -0,0 +1,14 @@ +# 进度备忘 + +- [x] 现在需要考虑SysRoleService和SysUserService之间循环依赖的函数放到SysRelationshipService中,在SysRoleService和SysUserService的controller调用SysRelationshipService。 +- [x] 在子线程保存日志的过程中,有可能request对象被收回,导致报错。考虑将所有request对象的操作放到子线程外面运行,将所有对request的处理操作完成后再开启日志子线程。通过传参的方式将对request处理的结果传入日志子线程。 +- [ ] 考虑按钮权限功能。 +- [ ] 考虑进行单元测试,两种方案。1:在各个子模块中编写测试用例,但是需要解决模块依赖启动类的问题。2:专门编写一个测试子模块,将其他模块的测试用例写到这个测试子模块中。 +- [ ] 考虑使用一个注解对密级字段进行权限控制。将注解放到实体类的指定字段上,就可以控制整条数据的权限。 +- [ ] 需要接口调用频率的控制。 + + +# 正在进行 + +* 菜单表基础功能 +