From 7d1b6d11ba1141c256fc03b8578ac8d9bc5670ce Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Thu, 24 Oct 2024 10:42:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E4=BF=AE=E6=94=B9=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 3 +- .../configuration/WebConfiguration.java | 148 ++++++++++++++++++ .../bunny/dao/pojo/result/ResultCodeEnum.java | 1 + .../vo/configuration/WebConfigurationVo.java | 121 ++++++++++++++ .../controller/ConfigurationController.java | 28 +++- .../services/controller/FilesController.java | 18 +-- .../service/ConfigurationService.java | 18 ++- .../impl/ConfigurationServiceImpl.java | 86 ++++++++++ .../src/main/resources/application-dev.yml | 2 +- 9 files changed, 406 insertions(+), 19 deletions(-) create mode 100644 dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java create mode 100644 dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java diff --git a/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java b/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java index ef7f132..f0ba522 100644 --- a/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java +++ b/common/service-utils/src/main/java/cn/bunny/common/service/exception/GlobalExceptionHandler.java @@ -1,6 +1,7 @@ package cn.bunny.common.service.exception; +import cn.bunny.common.service.context.BaseContext; import cn.bunny.dao.pojo.result.Result; import cn.bunny.dao.pojo.result.ResultCodeEnum; import lombok.extern.slf4j.Slf4j; @@ -87,7 +88,7 @@ public class GlobalExceptionHandler { // 表单验证字段 @ExceptionHandler(MethodArgumentNotValidException.class) public Result handleValidationExceptions(MethodArgumentNotValidException ex) { - log.error("表单验证失败:{}", ex.getMessage()); + log.error("表单验证失败,用户Id:{}", BaseContext.getUserId()); String errorMessage = ex.getBindingResult().getFieldErrors().stream() .map(DefaultMessageSourceResolvable::getDefaultMessage) .collect(Collectors.joining(", ")); diff --git a/dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java b/dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java new file mode 100644 index 0000000..95db1de --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/entity/configuration/WebConfiguration.java @@ -0,0 +1,148 @@ +package cn.bunny.dao.entity.configuration; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "WebConfiguration对象", title = "前端配置文件", description = "前端配置文件") +public class WebConfiguration { + + @Schema(name = "Version", description = "应用程序的版本") + @JSONField(name = "Version") + @JsonProperty("Version") + private String version; + + @Schema(name = "Title", description = "应用程序的标题") + @JSONField(name = "Title") + @JsonProperty("Title") + private String title; + + @Schema(name = "Copyright", description = "版权信息") + @JSONField(name = "Copyright") + @JsonProperty("Copyright") + private String copyright; + + @Schema(name = "FixedHeader", description = "头部是否固定") + @JSONField(name = "FixedHeader") + @JsonProperty("FixedHeader") + private boolean fixedHeader; + + @Schema(name = "HiddenSideBar", description = "侧边栏是否隐藏") + @JSONField(name = "HiddenSideBar") + @JsonProperty("HiddenSideBar") + private boolean hiddenSideBar; + + @Schema(name = "MultiTagsCache", description = "是否缓存多个标签") + @JSONField(name = "MultiTagsCache") + @JsonProperty("MultiTagsCache") + private boolean multiTagsCache; + + @Schema(name = "KeepAlive", description = "是否持久化") + @JSONField(name = "KeepAlive") + @JsonProperty("KeepAlive") + private boolean keepAlive; + + @Schema(name = "Locale", description = "语言类型") + @JSONField(name = "Locale") + @JsonProperty("Locale") + private String locale; + + @Schema(name = "Layout", description = "应用程序的布局") + @JSONField(name = "Layout") + @JsonProperty("Layout") + private String layout; + + @Schema(name = "Theme", description = "应用程序的主题") + @JSONField(name = "Theme") + @JsonProperty("Theme") + private String theme; + + @Schema(name = "DarkMode", description = "是否启用深色模式") + @JSONField(name = "DarkMode") + @JsonProperty("DarkMode") + private boolean darkMode; + + @Schema(name = "OverallStyle", description = "应用程序的整体样式") + @JSONField(name = "OverallStyle") + @JsonProperty("OverallStyle") + private String overallStyle; + + @Schema(name = "Grey", description = "是否启用灰色模式") + @JSONField(name = "Grey") + @JsonProperty("Grey") + private boolean grey; + + @Schema(name = "Weak", description = "色弱模式") + @JSONField(name = "Weak") + @JsonProperty("Weak") + private boolean weak; + + @Schema(name = "HideTabs", description = "是否隐藏选项卡") + @JSONField(name = "HideTabs") + @JsonProperty("HideTabs") + private boolean hideTabs; + + @Schema(name = "HideFooter", description = "是否隐藏页脚") + @JSONField(name = "HideFooter") + @JsonProperty("HideFooter") + private boolean hideFooter; + + @Schema(name = "Stretch", description = "是否拉伸显示") + @JSONField(name = "Stretch") + @JsonProperty("Stretch") + private boolean stretch; + + @Schema(name = "SidebarStatus", description = "侧边栏的状态") + @JSONField(name = "SidebarStatus") + @JsonProperty("SidebarStatus") + private boolean sidebarStatus; + + @Schema(name = "EpThemeColor", description = "主题颜色") + @JSONField(name = "EpThemeColor") + @JsonProperty("EpThemeColor") + private String epThemeColor; + + @Schema(name = "ShowLogo", description = "是否显示logo") + @JSONField(name = "ShowLogo") + @JsonProperty("ShowLogo") + private boolean showLogo; + + @Schema(name = "ShowModel", description = "要显示的模型") + @JSONField(name = "ShowModel") + @JsonProperty("ShowModel") + private String showModel; + + @Schema(name = "MenuArrowIconNoTransition", description = "菜单箭头图标是否没有过渡效果") + @JSONField(name = "MenuArrowIconNoTransition") + @JsonProperty("MenuArrowIconNoTransition") + private boolean menuArrowIconNoTransition; + + @Schema(name = "CachingAsyncRoutes", description = "是否缓存异步路由") + @JSONField(name = "CachingAsyncRoutes") + @JsonProperty("CachingAsyncRoutes") + private boolean cachingAsyncRoutes; + + @Schema(name = "TooltipEffect", description = "工具提示的效果") + @JSONField(name = "TooltipEffect") + @JsonProperty("TooltipEffect") + private String tooltipEffect; + + @Schema(name = "ResponsiveStorageNameSpace", description = "响应式存储的命名空间") + @JSONField(name = "ResponsiveStorageNameSpace") + @JsonProperty("ResponsiveStorageNameSpace") + private String responsiveStorageNameSpace; + + @Schema(name = "MenuSearchHistory", description = "菜单搜索历史") + @JSONField(name = "MenuSearchHistory") + @JsonProperty("MenuSearchHistory") + private int menuSearchHistory; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java b/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java index 355b5b4..220f8cb 100644 --- a/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java +++ b/dao/src/main/java/cn/bunny/dao/pojo/result/ResultCodeEnum.java @@ -47,6 +47,7 @@ public enum ResultCodeEnum { USER_IS_EMPTY(206, "用户不存在"), FILE_NOT_EXIST(206, "文件不存在"), NEW_PASSWORD_SAME_OLD_PASSWORD(206, "新密码不能和旧密码相同"), + MISSING_TEMPLATE_FILES(206, "缺少模板文件"), // 身份过期 208 LOGIN_AUTH(208, "请先登陆"), diff --git a/dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java b/dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java new file mode 100644 index 0000000..287c131 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/vo/configuration/WebConfigurationVo.java @@ -0,0 +1,121 @@ +package cn.bunny.dao.vo.configuration; + +import com.alibaba.fastjson2.annotation.JSONField; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "WebConfigurationVo对象", title = "前端配置获取返回结果", description = "前端配置获取返回结果") +public class WebConfigurationVo { + + @Schema(name = "Version", description = "应用程序的版本") + @JSONField(name = "Version") + private String version; + + @Schema(name = "Title", description = "应用程序的标题") + @JSONField(name = "Title") + private String title; + + @Schema(name = "Copyright", description = "版权信息") + @JSONField(name = "Copyright") + private String copyright; + + @Schema(name = "FixedHeader", description = "头部是否固定") + @JSONField(name = "FixedHeader") + private boolean fixedHeader; + + @Schema(name = "HiddenSideBar", description = "侧边栏是否隐藏") + @JSONField(name = "HiddenSideBar") + private boolean hiddenSideBar; + + @Schema(name = "MultiTagsCache", description = "是否缓存多个标签") + @JSONField(name = "MultiTagsCache") + private boolean multiTagsCache; + + @Schema(name = "KeepAlive", description = "是否持久化") + @JSONField(name = "KeepAlive") + private boolean keepAlive; + + @Schema(name = "Locale", description = "语言类型") + @JSONField(name = "Locale") + private String locale; + + @Schema(name = "Layout", description = "应用程序的布局") + @JSONField(name = "Layout") + private String layout; + + @Schema(name = "Theme", description = "应用程序的主题") + @JSONField(name = "Theme") + private String theme; + + @Schema(name = "DarkMode", description = "是否启用深色模式") + @JSONField(name = "DarkMode") + private boolean darkMode; + + @Schema(name = "OverallStyle", description = "应用程序的整体样式") + @JSONField(name = "OverallStyle") + private String overallStyle; + + @Schema(name = "Grey", description = "是否启用灰色模式") + @JSONField(name = "Grey") + private boolean grey; + + @Schema(name = "Weak", description = "色弱模式") + @JSONField(name = "Weak") + private boolean weak; + + @Schema(name = "HideTabs", description = "是否隐藏选项卡") + @JSONField(name = "HideTabs") + private boolean hideTabs; + + @Schema(name = "HideFooter", description = "是否隐藏页脚") + @JSONField(name = "HideFooter") + private boolean hideFooter; + + @Schema(name = "Stretch", description = "是否拉伸显示") + @JSONField(name = "Stretch") + private boolean stretch; + + @Schema(name = "SidebarStatus", description = "侧边栏的状态") + @JSONField(name = "SidebarStatus") + private boolean sidebarStatus; + + @Schema(name = "EpThemeColor", description = "主题颜色") + @JSONField(name = "EpThemeColor") + private String epThemeColor; + + @Schema(name = "ShowLogo", description = "是否显示logo") + @JSONField(name = "ShowLogo") + private boolean showLogo; + + @Schema(name = "ShowModel", description = "要显示的模型") + @JSONField(name = "ShowModel") + private String showModel; + + @Schema(name = "MenuArrowIconNoTransition", description = "菜单箭头图标是否没有过渡效果") + @JSONField(name = "MenuArrowIconNoTransition") + private boolean menuArrowIconNoTransition; + + @Schema(name = "CachingAsyncRoutes", description = "是否缓存异步路由") + @JSONField(name = "CachingAsyncRoutes") + private boolean cachingAsyncRoutes; + + @Schema(name = "TooltipEffect", description = "工具提示的效果") + @JSONField(name = "TooltipEffect") + private String tooltipEffect; + + @Schema(name = "ResponsiveStorageNameSpace", description = "响应式存储的命名空间") + @JSONField(name = "ResponsiveStorageNameSpace") + private String responsiveStorageNameSpace; + + @Schema(name = "MenuSearchHistory", description = "菜单搜索历史") + @JSONField(name = "MenuSearchHistory") + private int menuSearchHistory; + +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/controller/ConfigurationController.java b/service/src/main/java/cn/bunny/services/controller/ConfigurationController.java index f59abb3..29499b9 100644 --- a/service/src/main/java/cn/bunny/services/controller/ConfigurationController.java +++ b/service/src/main/java/cn/bunny/services/controller/ConfigurationController.java @@ -1,17 +1,17 @@ package cn.bunny.services.controller; import cn.bunny.dao.dto.system.configuration.WebConfigurationDto; +import cn.bunny.dao.entity.configuration.WebConfiguration; import cn.bunny.dao.pojo.result.Result; import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.configuration.WebConfigurationVo; import cn.bunny.services.service.ConfigurationService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; @Tag(name = "配置", description = "系统配置相关接口") @@ -22,10 +22,26 @@ public class ConfigurationController { @Autowired private ConfigurationService configurationService; - @Operation(summary = "更新web配置", description = "更新web配置") - @PostMapping("updateWebConfiguration") + @SneakyThrows + @Operation(summary = "读取web配置文件", description = "读取web配置文件") + @GetMapping("noAuth/webConfig") + public WebConfiguration webConfig() { + return configurationService.webConfig(); + } + + @SneakyThrows + @Operation(summary = "获取修改web配置文件", description = "获取修改web配置文件") + @GetMapping("getWebConfig") + public Mono> getWebConfig() { + WebConfigurationVo webConfiguration = configurationService.getWebConfig(); + return Mono.just(Result.success(webConfiguration)); + } + + @Operation(summary = "更新web配置文件", description = "更新web配置文件") + @PutMapping("updateWebConfiguration") public Mono> updateWebConfiguration(@Valid @RequestBody WebConfigurationDto dto) { configurationService.updateWebConfiguration(dto); return Mono.just(Result.success(ResultCodeEnum.UPDATE_SUCCESS)); } + } diff --git a/service/src/main/java/cn/bunny/services/controller/FilesController.java b/service/src/main/java/cn/bunny/services/controller/FilesController.java index 087a842..e77edc2 100644 --- a/service/src/main/java/cn/bunny/services/controller/FilesController.java +++ b/service/src/main/java/cn/bunny/services/controller/FilesController.java @@ -1,6 +1,5 @@ package cn.bunny.services.controller; -import cn.bunny.common.service.exception.BunnyException; import cn.bunny.dao.dto.system.files.FileUploadDto; import cn.bunny.dao.dto.system.files.FilesAddDto; import cn.bunny.dao.dto.system.files.FilesDto; @@ -19,8 +18,6 @@ import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Mono; @@ -86,13 +83,14 @@ public class FilesController { return filesService.downloadFilesByFilepath(filepath); } - @Operation(summary = "根据文件名访问resource下文件", description = "根据文件名访问resource下文件") - @GetMapping("noManage/resourceFiles/{filename}") - public ResponseEntity getResourceByFilename(@PathVariable String filename) { - Resource file = new ClassPathResource("static/" + filename); - if (!file.exists()) throw new BunnyException(ResultCodeEnum.FILE_NOT_EXIST); - return ResponseEntity.ok().body(file); - } + // 无法做权限校验 + // @Operation(summary = "根据文件名访问resource下文件", description = "根据文件名访问resource下文件") + // @GetMapping("noManage/resourceFiles/{filename}") + // public ResponseEntity getResourceByFilename(@PathVariable String filename) { + // Resource file = new ClassPathResource("static/" + filename); + // if (!file.exists()) throw new BunnyException(ResultCodeEnum.FILE_NOT_EXIST); + // return ResponseEntity.ok().body(file); + // } @Operation(summary = "更新系统文件", description = "更新系统文件") @PutMapping("updateFiles") diff --git a/service/src/main/java/cn/bunny/services/service/ConfigurationService.java b/service/src/main/java/cn/bunny/services/service/ConfigurationService.java index 1ad0c3d..2aa1cb5 100644 --- a/service/src/main/java/cn/bunny/services/service/ConfigurationService.java +++ b/service/src/main/java/cn/bunny/services/service/ConfigurationService.java @@ -1,6 +1,8 @@ package cn.bunny.services.service; import cn.bunny.dao.dto.system.configuration.WebConfigurationDto; +import cn.bunny.dao.entity.configuration.WebConfiguration; +import cn.bunny.dao.vo.configuration.WebConfigurationVo; public interface ConfigurationService { @@ -10,4 +12,18 @@ public interface ConfigurationService { * @param dto 前端配置选项 */ void updateWebConfiguration(WebConfigurationDto dto); -} + + /** + * 读取web配置文件 + * + * @return 前端配置文件 + */ + WebConfiguration webConfig(); + + /** + * 获取修改web配置文件 + * + * @return 要修改前端配置文件 + */ + WebConfigurationVo getWebConfig(); +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/service/impl/ConfigurationServiceImpl.java b/service/src/main/java/cn/bunny/services/service/impl/ConfigurationServiceImpl.java index 0914aae..6d099f5 100644 --- a/service/src/main/java/cn/bunny/services/service/impl/ConfigurationServiceImpl.java +++ b/service/src/main/java/cn/bunny/services/service/impl/ConfigurationServiceImpl.java @@ -1,18 +1,104 @@ package cn.bunny.services.service.impl; +import cn.bunny.common.service.exception.BunnyException; import cn.bunny.dao.dto.system.configuration.WebConfigurationDto; +import cn.bunny.dao.entity.configuration.WebConfiguration; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.configuration.WebConfigurationVo; import cn.bunny.services.service.ConfigurationService; +import com.alibaba.fastjson2.JSON; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; + @Service public class ConfigurationServiceImpl implements ConfigurationService { + + @Value("${bunny.bashPath}") + private String bashPath; + + private static @NotNull String getWebConfigString(InputStream inputStream, Path templatePath) throws IOException { + if (inputStream == null) throw new BunnyException(ResultCodeEnum.MISSING_TEMPLATE_FILES); + + // 判断web模板文件是否存在,不存在进行复制 + boolean exists = Files.exists(templatePath); + if (!exists) Files.copy(inputStream, templatePath); + + // 将读取文件返回 + byte[] bytes = Files.readAllBytes(templatePath); + return new String(bytes); + } + /** * * 更新web配置 * * @param dto 前端配置选项 */ @Override + @CacheEvict(cacheNames = "webConfig", key = "'platformConfig'", beforeInvocation = true, cacheManager = "cacheManagerWithMouth") public void updateWebConfiguration(WebConfigurationDto dto) { + try { + // 系统模板文件位置 + Path templatePath = Path.of(bashPath + "/platform-config.json"); + // 提交表单转换 + WebConfiguration webConfiguration = new WebConfiguration(); + BeanUtils.copyProperties(dto, webConfiguration); + + // 将表单转成存储的类型 + WebConfigurationVo webConfigurationVo = new WebConfigurationVo(); + BeanUtils.copyProperties(webConfiguration, webConfigurationVo); + + // 将文件写入 + String jsonString = JSON.toJSONString(webConfigurationVo); + Files.writeString(templatePath, jsonString); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 读取web配置文件 + * + * @return 前端配置文件 + */ + @Override + @Cacheable(cacheNames = "webConfig", key = "'platformConfig'", cacheManager = "cacheManagerWithMouth") + public WebConfiguration webConfig() { + // 系统模板文件位置 + Path templatePath = Path.of(bashPath + "/platform-config.json"); + + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("static/platform-config.json")) { + String string = getWebConfigString(inputStream, templatePath); + return JSON.parseObject(string, WebConfiguration.class); + } catch (IOException exception) { + throw new BunnyException(exception.getMessage()); + } + } + + /** + * 获取修改web配置文件 + * + * @return 要修改前端配置文件 + */ + @Override + public WebConfigurationVo getWebConfig() { + // 系统模板文件位置 + Path templatePath = Path.of(bashPath + "/platform-config.json"); + + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream("static/platform-config.json")) { + String string = getWebConfigString(inputStream, templatePath); + return JSON.parseObject(string, WebConfigurationVo.class); + } catch (IOException exception) { + throw new BunnyException(exception.getMessage()); + } } } diff --git a/service/src/main/resources/application-dev.yml b/service/src/main/resources/application-dev.yml index 3329f3b..f500682 100644 --- a/service/src/main/resources/application-dev.yml +++ b/service/src/main/resources/application-dev.yml @@ -38,4 +38,4 @@ bunny: secretKey: "02120212" bucket-name: auth-admin - bashPath: "H:\\资料" \ No newline at end of file + bashPath: "D:\\MyFolder" \ No newline at end of file