chore: continew-starter 2.7.2 => 2.7.3

1.CrudApi GET => DETAIL(支持详情权限)
2.适配 CharConstants
3.适配 EnumValue 校验器
This commit is contained in:
2024-11-15 22:25:30 +08:00
parent 985bc25716
commit 556f6c33b1
24 changed files with 48 additions and 27 deletions

View File

@@ -13,7 +13,7 @@
<img src="https://sonarcloud.io/api/project_badges/measure?project=Charles7c_continew-admin&metric=alert_status" alt="Sonar Status" />
</a>
<a href="https://github.com/continew-org/continew-starter" target="_blank">
<img src="https://img.shields.io/badge/ContiNew Starter-2.7.2-%236CB52D.svg" alt="ContiNew Starter" />
<img src="https://img.shields.io/badge/ContiNew Starter-2.7.3-%236CB52D.svg" alt="ContiNew Starter" />
</a>
<a href="https://spring.io/projects/spring-boot" target="_blank">
<img src="https://img.shields.io/badge/Spring Boot-3.2.10-%236CB52D.svg?logo=Spring-Boot" alt="Spring Boot" />
@@ -216,7 +216,7 @@ public class DeptController extends BaseController<DeptService, DeptResp, DeptDe
| <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design</a> | 2.56.0 | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。 |
| <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 5.0.4 | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 |
| <a href="https://cn.vitejs.dev/" target="_blank">Vite</a> | 5.1.5 | 下一代的前端工具链,为开发提供极速响应。 |
| [ContiNew Starter](https://github.com/continew-org/continew-starter) | 2.7.2 | ContiNew Starter 包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken可轻松集成到应用中为开发人员减少手动引入依赖及配置的麻烦为 Spring Boot Web 项目的灵活快速构建提供支持。 |
| [ContiNew Starter](https://github.com/continew-org/continew-starter) | 2.7.3 | ContiNew Starter 包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken可轻松集成到应用中为开发人员减少手动引入依赖及配置的麻烦为 Spring Boot Web 项目的灵活快速构建提供支持。 |
| <a href="https://spring.io/projects/spring-boot" target="_blank">Spring Boot</a> | 3.2.10 | 简化 Spring 应用的初始搭建和开发过程基于“约定优于配置”的理念使开发人员不再需要定义样板化的配置。Spring Boot 3.0 开始,要求 Java 17 作为最低版本) |
| <a href="https://undertow.io/" target="_blank">Undertow</a> | 2.3.13.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 |
| <a href="https://sa-token.dev33.cn/" target="_blank">Sa-Token + JWT</a> | 1.39.0 | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。 |

View File

@@ -24,6 +24,7 @@ import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.exception.BusinessException;
@@ -58,6 +59,16 @@ public class GlobalExceptionHandler {
return R.fail(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage());
}
/**
* 拦截校验异常-方法参数类型不匹配异常
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e,
HttpServletRequest request) {
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
return R.fail(String.valueOf(HttpStatus.BAD_REQUEST.value()), "参数 '%s' 类型不匹配".formatted(e.getName()));
}
/**
* 拦截文件上传异常-超过上传大小限制
*/

View File

@@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.system.enums.OptionCategoryEnum;
import top.continew.admin.system.service.OptionService;
import top.continew.starter.messaging.mail.core.MailConfig;
import top.continew.starter.messaging.mail.core.MailConfigurer;
@@ -43,7 +44,7 @@ public class MailConfigurerImpl implements MailConfigurer {
@Override
public MailConfig getMailConfig() {
// 查询邮件配置
Map<String, String> map = optionService.getByCategory("MAIL");
Map<String, String> map = optionService.getByCategory(OptionCategoryEnum.MAIL);
// 封装邮件配置
MailConfig mailConfig = new MailConfig();
mailConfig.setProtocol(MapUtil.getStr(map, "MAIL_PROTOCOL"));

View File

@@ -168,7 +168,7 @@ public enum PasswordPolicyEnum {
/**
* 策略类别
*/
public static final String CATEGORY = "PASSWORD";
public static final OptionCategoryEnum CATEGORY = OptionCategoryEnum.PASSWORD;
/**
* 校验取值范围

View File

@@ -19,6 +19,7 @@ package top.continew.admin.system.model.query;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.system.enums.OptionCategoryEnum;
import top.continew.starter.core.validation.constraints.EnumValue;
import top.continew.starter.data.core.annotation.Query;
import top.continew.starter.data.core.enums.QueryType;
@@ -50,5 +51,6 @@ public class OptionQuery implements Serializable {
* 类别
*/
@Schema(description = "类别", example = "SITE")
private OptionCategoryEnum category;
@EnumValue(value = OptionCategoryEnum.class, message = "类别非法")
private String category;
}

View File

@@ -16,6 +16,7 @@
package top.continew.admin.system.service;
import top.continew.admin.system.enums.OptionCategoryEnum;
import top.continew.admin.system.model.query.OptionQuery;
import top.continew.admin.system.model.req.OptionReq;
import top.continew.admin.system.model.req.OptionResetValueReq;
@@ -47,7 +48,7 @@ public interface OptionService {
* @param category 类别
* @return 参数信息
*/
Map<String, String> getByCategory(String category);
Map<String, String> getByCategory(OptionCategoryEnum category);
/**
* 修改参数

View File

@@ -26,6 +26,7 @@ import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWra
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.system.enums.OptionCategoryEnum;
import top.continew.admin.system.enums.PasswordPolicyEnum;
import top.continew.admin.system.mapper.OptionMapper;
import top.continew.admin.system.model.entity.OptionDO;
@@ -64,8 +65,8 @@ public class OptionServiceImpl implements OptionService {
@Override
@Cached(key = "#category", name = CacheConstants.OPTION_KEY_PREFIX + "MAP:")
public Map<String, String> getByCategory(String category) {
return baseMapper.selectByCategory(category)
public Map<String, String> getByCategory(OptionCategoryEnum category) {
return baseMapper.selectByCategory(category.name())
.stream()
.collect(Collectors.toMap(OptionDO::getCode, o -> StrUtil.emptyIfNull(ObjectUtil.defaultIfNull(o
.getValue(), o.getDefaultValue())), (oldVal, newVal) -> oldVal));
@@ -87,8 +88,8 @@ public class OptionServiceImpl implements OptionService {
}
// 校验密码策略参数取值范围
Map<String, String> passwordPolicyOptionMap = options.stream()
.filter(option -> StrUtil.startWith(option
.getCode(), PasswordPolicyEnum.CATEGORY + StringConstants.UNDERLINE))
.filter(option -> StrUtil.startWith(option.getCode(), PasswordPolicyEnum.CATEGORY
.name() + StringConstants.UNDERLINE))
.collect(Collectors.toMap(OptionReq::getCode, OptionReq::getValue, (oldVal, newVal) -> oldVal));
for (Map.Entry<String, String> passwordPolicyOptionEntry : passwordPolicyOptionMap.entrySet()) {
String code = passwordPolicyOptionEntry.getKey();

View File

@@ -61,6 +61,7 @@ import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.enums.GenderEnum;
import top.continew.admin.common.util.SecureUtils;
import top.continew.admin.system.enums.OptionCategoryEnum;
import top.continew.admin.system.mapper.UserMapper;
import top.continew.admin.system.model.entity.DeptDO;
import top.continew.admin.system.model.entity.RoleDO;
@@ -630,7 +631,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
* @return 密码允许重复使用次数
*/
private int checkPassword(String password, UserDO user) {
Map<String, String> passwordPolicy = optionService.getByCategory(CATEGORY);
Map<String, String> passwordPolicy = optionService.getByCategory(OptionCategoryEnum.PASSWORD);
// 密码最小长度
PASSWORD_MIN_LENGTH.validate(password, MapUtil.getInt(passwordPolicy, PASSWORD_MIN_LENGTH.name()), user);
// 密码是否必须包含特殊字符

View File

@@ -26,7 +26,7 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import top.continew.admin.common.constant.RegexConstants;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.constant.CharConstants;
import top.continew.starter.core.util.StrUtils;
import java.io.Serial;
@@ -130,7 +130,7 @@ public class GenConfigDO implements Serializable {
public void setTableName(String tableName) {
this.tableName = tableName;
// 默认表前缀sys_user -> sys_
int underLineIndex = StrUtil.indexOf(tableName, StringConstants.C_UNDERLINE);
int underLineIndex = StrUtil.indexOf(tableName, CharConstants.UNDERLINE);
if (-1 != underLineIndex) {
this.tablePrefix = StrUtil.subPre(tableName, underLineIndex + 1);
}

View File

@@ -22,5 +22,5 @@ import ${packageName}.service.${classNamePrefix}Service;
*/
@Tag(name = "${businessName}管理 API")
@RestController
@CrudRequestMapping(value = "/${apiModuleName}/${apiName}", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
@CrudRequestMapping(value = "/${apiModuleName}/${apiName}", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class ${className} extends BaseController<${classNamePrefix}Service, ${classNamePrefix}Resp, ${classNamePrefix}DetailResp, ${classNamePrefix}Query, ${classNamePrefix}Req> {}

View File

@@ -14,6 +14,7 @@
<script setup lang="ts">
import { Message } from '@arco-design/web-vue'
import { useWindowSize } from '@vueuse/core'
import { get${classNamePrefix}, add${classNamePrefix}, update${classNamePrefix} } from '@/apis/${apiModuleName}/${apiName}'
import { type Columns, GiForm, type Options } from '@/components/GiForm'
import { useForm } from '@/hooks'
@@ -23,6 +24,8 @@ const emit = defineEmits<{
(e: 'save-success'): void
}>()
const { width } = useWindowSize()
const dataId = ref('')
const visible = ref(false)
const isUpdate = computed(() => !!dataId.value)

View File

@@ -48,6 +48,7 @@ import org.springframework.web.bind.annotation.*;
import top.continew.admin.common.config.properties.CaptchaProperties;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.auth.model.resp.CaptchaResp;
import top.continew.admin.system.enums.OptionCategoryEnum;
import top.continew.admin.system.service.OptionService;
import top.continew.starter.cache.redisson.util.RedisUtils;
import top.continew.starter.captcha.graphic.core.GraphicCaptchaService;
@@ -151,7 +152,7 @@ public class CaptchaController {
String captcha = RandomUtil.randomNumbers(captchaMail.getLength());
// 发送验证码
Long expirationInMinutes = captchaMail.getExpirationInMinutes();
Map<String, String> siteConfig = optionService.getByCategory("SITE");
Map<String, String> siteConfig = optionService.getByCategory(OptionCategoryEnum.SITE);
String content = TemplateUtils.render(captchaMail.getTemplatePath(), Dict.create()
.set("siteUrl", projectProperties.getUrl())
.set("siteTitle", siteConfig.get("SITE_TITLE"))

View File

@@ -109,7 +109,7 @@ public class CommonController {
@Cached(key = "'SITE'", name = CacheConstants.OPTION_KEY_PREFIX)
public List<LabelValueResp<String>> listSiteOptionDict() {
OptionQuery optionQuery = new OptionQuery();
optionQuery.setCategory(OptionCategoryEnum.SITE);
optionQuery.setCategory(OptionCategoryEnum.SITE.name());
return optionService.list(optionQuery)
.stream()
.map(option -> new LabelValueResp<>(option.getCode(), StrUtil.nullToDefault(option.getValue(), option

View File

@@ -46,7 +46,7 @@ import top.continew.starter.extension.crud.model.resp.BaseIdResp;
@Tag(name = "应用管理 API")
@RestController
@RequiredArgsConstructor
@CrudRequestMapping(value = "/open/app", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
@CrudRequestMapping(value = "/open/app", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class AppController extends BaseController<AppService, AppResp, AppDetailResp, AppQuery, AppReq> {
private final AppService appService;

View File

@@ -34,6 +34,6 @@ import top.continew.starter.extension.crud.enums.Api;
*/
@Tag(name = "部门管理 API")
@RestController
@CrudRequestMapping(value = "/system/dept", api = {Api.TREE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
@CrudRequestMapping(value = "/system/dept", api = {Api.TREE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class DeptController extends BaseController<DeptService, DeptResp, DeptResp, DeptQuery, DeptReq> {
}

View File

@@ -34,6 +34,6 @@ import top.continew.starter.extension.crud.enums.Api;
*/
@Tag(name = "字典管理 API")
@RestController
@CrudRequestMapping(value = "/system/dict", api = {Api.LIST, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE})
@CrudRequestMapping(value = "/system/dict", api = {Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class DictController extends BaseController<DictService, DictResp, DictResp, DictQuery, DictReq> {
}

View File

@@ -36,6 +36,6 @@ import top.continew.starter.log.core.annotation.Log;
@Log(module = "字典管理")
@Tag(name = "字典项管理 API")
@RestController
@CrudRequestMapping(value = "/system/dict/item", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE})
@CrudRequestMapping(value = "/system/dict/item", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class DictItemController extends BaseController<DictItemService, DictItemResp, DictItemResp, DictItemQuery, DictItemReq> {
}

View File

@@ -44,7 +44,7 @@ import top.continew.starter.extension.crud.util.ValidateGroup;
*/
@Tag(name = "菜单管理 API")
@RestController
@CrudRequestMapping(value = "/system/menu", api = {Api.TREE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE})
@CrudRequestMapping(value = "/system/menu", api = {Api.TREE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class MenuController extends BaseController<MenuService, MenuResp, MenuResp, MenuQuery, MenuReq> {
@Override

View File

@@ -44,7 +44,7 @@ import java.time.LocalDateTime;
*/
@Tag(name = "公告管理 API")
@RestController
@CrudRequestMapping(value = "/system/notice", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE})
@CrudRequestMapping(value = "/system/notice", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class NoticeController extends BaseController<NoticeService, NoticeResp, NoticeDetailResp, NoticeQuery, NoticeReq> {
@Override

View File

@@ -49,7 +49,7 @@ import java.util.List;
@Validated
@RestController
@RequiredArgsConstructor
@CrudRequestMapping(value = "/system/role", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE})
@CrudRequestMapping(value = "/system/role", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class RoleController extends BaseController<RoleService, RoleResp, RoleDetailResp, RoleQuery, RoleReq> {
private final UserRoleService userRoleService;

View File

@@ -34,6 +34,6 @@ import top.continew.starter.extension.crud.enums.Api;
*/
@Tag(name = "存储管理 API")
@RestController
@CrudRequestMapping(value = "/system/storage", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE})
@CrudRequestMapping(value = "/system/storage", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE})
public class StorageController extends BaseController<StorageService, StorageResp, StorageResp, StorageQuery, StorageReq> {
}

View File

@@ -61,7 +61,7 @@ import java.io.IOException;
@Validated
@RestController
@RequiredArgsConstructor
@CrudRequestMapping(value = "/system/user", api = {Api.PAGE, Api.LIST, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE,
@CrudRequestMapping(value = "/system/user", api = {Api.PAGE, Api.LIST, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE,
Api.EXPORT})
public class UserController extends BaseController<UserService, UserResp, UserDetailResp, UserQuery, UserReq> {

View File

@@ -5,5 +5,5 @@
\____|\___/ |_| |_| \__||_||_| \_| \___| \_/\_/ /_/ \_\\__,_||_| |_| |_||_||_| |_|
:: ${project.name} :: v${project.version}
:: ContiNew Starter :: v2.7.2
:: ContiNew Starter :: v2.7.3
:: Spring Boot :: v${spring-boot.version}

View File

@@ -13,7 +13,7 @@
<parent>
<groupId>top.continew</groupId>
<artifactId>continew-starter</artifactId>
<version>2.7.2</version>
<version>2.7.3</version>
</parent>
<groupId>top.continew</groupId>