23 Commits

Author SHA1 Message Date
ae3a01fb7b revert: 回退全局响应结果处理器(遗漏项) 2024-01-26 22:21:10 +08:00
5ee430cbfa docs: 完善 README 文档 2023-12-03 00:13:44 +08:00
1fc76a4123 refactor: 优化部分注解使用 2023-11-30 22:14:19 +08:00
2146605a86 revert: 回退全局响应结果处理器
1.影响 API 文档生成
2.其他已知及未知影响
2023-11-30 22:09:44 +08:00
cde515b186 !8 回退全局响应结果处理器
Merge pull request !8 from Yoofff/1.3.x
2023-11-30 14:05:50 +00:00
Bull-BCLS
d668620bfe refactor: 回退全局响应结果处理器
1.影响 API 文档生成
2.其他已知及未知影响
2023-11-29 23:34:00 +08:00
27d401f44b docs: 完善 README 文档 2023-11-20 20:12:06 +08:00
a8aa9f28f6 chore: 移除 XML 文件头部的协议信息 2023-11-19 18:15:48 +08:00
2930619964 chore: 新增 idea 图标 2023-11-19 18:13:37 +08:00
11b3b87337 fix: 修复保存生成配置校验失效的问题,并优化部分提示效果 2023-11-16 21:18:01 +08:00
0eddbfb978 refactor: 优化菜单标题校验 2023-11-16 21:13:10 +08:00
adf6d900f3 chore: 更新版本号 2023-11-16 21:12:59 +08:00
3f8f4e2bf4 release: v1.3.1 2023-11-15 21:12:04 +08:00
3fcdb54442 fix: sms4j 3.0.3 => 3.0.4
修复发送容联云短信错误
2023-11-15 20:57:04 +08:00
5d159c6ab3 fix: 发送消息增加事务处理 2023-11-15 20:55:27 +08:00
39969ebf61 chore: 完善 Redis 部署配置 2023-11-12 00:21:04 +08:00
47a5746794 fix: 修复仪表盘访问趋势区块 y 轴数值过大时无法展示的问题
增加 y 轴单位转换逻辑
2023-11-11 00:09:18 +08:00
8820c1dfc8 refactor: 优化 401 状态处理逻辑
1.退出接口增加登录校验
2.前端获取用户信息失败,自动清理客户端信息并跳转回登录页
2023-11-07 19:53:29 +08:00
712eedba1b refactor: 优化超时登录处理逻辑 2023-11-06 22:12:27 +08:00
47a8160d70 fix: 修复控制台报错 Please use theme before using plugins
1.由 v-md-editor 使用方式不佳引起
2023-11-05 23:23:54 +08:00
b63d7d725d fix: 修复 Swagger 分组接口缺失 2023-11-05 21:11:34 +08:00
f15494d348 style: 优化部分变量命名 2023-11-05 17:36:41 +08:00
91ea4ed685 chore: 更新版本号 2023-11-05 17:30:23 +08:00
42 changed files with 200 additions and 355 deletions

1
.gitignore vendored
View File

@@ -15,6 +15,7 @@ target/
### IntelliJ IDEA ### ### IntelliJ IDEA ###
.idea .idea
!.idea/icon.png
*.iws *.iws
*.iml *.iml
*.ipr *.ipr

BIN
.idea/icon.png generated Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -1,3 +1,20 @@
## [v1.3.1](https://github.com/Charles7c/continew-admin/compare/v1.3.0...v1.3.1) (2023-11-15)
### 💎 功能优化
- 完善 Redis 部署配置 ([39969eb](https://github.com/Charles7c/continew-admin/commit/39969ebf6173fc379dc3501e9204a344d1cf62cf))
- 优化 401 状态处理逻辑 ([8820c1d](https://github.com/Charles7c/continew-admin/commit/8820c1dfc858b9ef9df470e90dfe9ba4b1166e29))
- 优化超时登录处理逻辑 ([712eedb](https://github.com/Charles7c/continew-admin/commit/712eedba1be0ec371119745d4596cd35c2ce25d6))
- 优化部分变量命名 ([f15494d](https://github.com/Charles7c/continew-admin/commit/f15494d34823ded87efc396d98e2eb0108f74a3d))
### 🐛 问题修复
- sms4j 3.0.3 => 3.0.4 ([3fcdb54](https://github.com/Charles7c/continew-admin/commit/3fcdb54442b380e76838478fa46e8dfb70a2759b))
- 发送消息增加事务处理 ([5d159c6](https://github.com/Charles7c/continew-admin/commit/5d159c6ab337a9432419d84cf246cff506500567))
- 修复仪表盘访问趋势区块 y 轴数值过大时无法展示的问题 ([47a5746](https://github.com/Charles7c/continew-admin/commit/47a5746794e552faf9c41fbcc21af091a878eb95))
- 修复控制台报错 Please use theme before using plugins ([47a8160](https://github.com/Charles7c/continew-admin/commit/47a8160d70862a5ee7284c165004cece2714a10f))
- 修复 Swagger 分组接口缺失 ([b63d7d7](https://github.com/Charles7c/continew-admin/commit/b63d7d725da5e9e9b2db9fd59bd140d64b50040c))
## [v1.3.0](https://github.com/Charles7c/continew-admin/compare/v1.2.0...v1.3.0) (2023-11-04) ## [v1.3.0](https://github.com/Charles7c/continew-admin/compare/v1.2.0...v1.3.0) (2023-11-04)
### ✨ 新特性 ### ✨ 新特性

View File

@@ -4,7 +4,7 @@
<img src="https://img.shields.io/badge/License-Apache--2.0-blue.svg" alt="License" /> <img src="https://img.shields.io/badge/License-Apache--2.0-blue.svg" alt="License" />
</a> </a>
<a href="https://github.com/Charles7c/continew-admin" target="_blank"> <a href="https://github.com/Charles7c/continew-admin" target="_blank">
<img src="https://img.shields.io/badge/RELEASE-v1.3.0-%23ff3f59.svg" alt="Release" /> <img src="https://img.shields.io/badge/SNAPSHOT-v1.3.2-%23ff3f59.svg" alt="Release" />
</a> </a>
<a href="https://github.com/Charles7c/continew-admin" target="_blank"> <a href="https://github.com/Charles7c/continew-admin" target="_blank">
<img src="https://img.shields.io/github/stars/Charles7c/continew-admin?style=social" alt="GitHub stars" /> <img src="https://img.shields.io/github/stars/Charles7c/continew-admin?style=social" alt="GitHub stars" />
@@ -18,12 +18,14 @@
<a href="https://gitee.com/Charles7c/continew-admin" target="_blank"> <a href="https://gitee.com/Charles7c/continew-admin" target="_blank">
<img src="https://gitee.com/Charles7c/continew-admin/badge/fork.svg?theme=white" alt="Gitee forks" /> <img src="https://gitee.com/Charles7c/continew-admin/badge/fork.svg?theme=white" alt="Gitee forks" />
</a> </a>
<img src="https://img.shields.io/badge/Spring Boot-2.7.16-%236CB52D.svg" alt="Release" />
<img src="https://img.shields.io/badge/Java-8-%236CB52D.svg" alt="Release" />
📚 [在线文档](https://doc.charles7c.top) | ✨ [提交需求](https://doc.charles7c.top/require.html) | 🚀 [演示地址](https://cnadmin.charles7c.top)(账号/密码admin/admin123 📚 [在线文档](https://doc.charles7c.top) | ✨ [提交需求](https://doc.charles7c.top/require.html) | 🚀 [演示地址](https://cnadmin.charles7c.top)(账号/密码admin/admin123
## 简介 ## 简介
ContiNew Admin Continue New Admin中后台管理框架/脚手架持续以最新流行技术栈构建拥抱变化迭代优化。在社区贡献者的支持和参与下持续发展并源源不断地为企业级项目开发提供助力。当前采用的技术栈Vue3、Spring Boot3、TypeScript、Arco Design Vue、Undertow、Sa-Token、JWT、MariaDB、MyBatis Plus、Redis、Redisson、Easy Excel、Hutool 等。 ContiNew Admin Continue New Admin中后台管理框架/脚手架持续以最新流行技术栈构建拥抱变化迭代优化。在社区贡献者的支持和参与下持续发展并源源不断地为企业级项目开发提供助力。当前采用的技术栈Vue3、**Spring Boot 2.7.xJDK8** 、TypeScript、Arco Design Vue、Undertow、Sa-Token、JWT、MariaDB、MyBatis Plus、Redis、Redisson、Easy Excel、Hutool 等。
## 项目源码 ## 项目源码
@@ -32,30 +34,9 @@ ContiNew Admin Continue New Admin中后台管理框架/脚手架,持续
| GitHub | https://github.com/Charles7c/continew-admin | | GitHub | https://github.com/Charles7c/continew-admin |
| Gitee码云 | https://gitee.com/Charles7c/continew-admin | | Gitee码云 | https://gitee.com/Charles7c/continew-admin |
<img src="https://repobeats.axiom.co/api/embed/be43df158b86ce201cd2b7e0e6c8a85740149b7e.svg" alt="Alt" title="Repobeats github analytics image" />
## 反馈交流
💬 欢迎各位小伙伴儿扫描下方二维码加好友,备注 `cnadmin`,拉你进群,探讨技术、提提需求~
加入交流群后,你将会:
- 第一时间收到框架动态
- 第一时间收到框架更新通知
- 第一时间收到框架 Bug 通知
- 和众多大佬互相 (huá shuǐ) 交流 (mō yú)
<div align="left">
<img src=".image/qrcode.jpg" alt="二维码" width="230px" />
</div>
<details>
<summary>无加群意愿</summary>
💬 如无加群意愿,欢迎在 <a href="https://github.com/Charles7c/continew-admin/discussions" target="_blank">Discussions</a> 中进行交流探讨~ 🍻
</details>
## 主要特性 ## 主要特性
- :fire: 在 2.x 及以上版本中,下方部分通用基础能力及配置,已抽取到 [ContiNew Starter](https://github.com/Charles7c/continew-starter) 项目,现已发布到 Maven 中央仓库,为 Spring Boot Web 项目开发提供更灵活的助力
- 精选技术栈:使用综合考虑成熟度、流行性、发展潜力较佳的技术栈,包括 Spring Boot、MyBatis Plus、Sa-Token、Hutool 等 - 精选技术栈:使用综合考虑成熟度、流行性、发展潜力较佳的技术栈,包括 Spring Boot、MyBatis Plus、Sa-Token、Hutool 等
- 高效率开发:后端提供了 CRUD 组件,在 Controller 中只需添加一个注解,即可自动生成增、删、改、查、分页、列表、树列表等 API - 高效率开发:后端提供了 CRUD 组件,在 Controller 中只需添加一个注解,即可自动生成增、删、改、查、分页、列表、树列表等 API
- 提供代码生成功能,根据用户提供的项目信息和配置,自动生成前后端项目结构、代码文件和部分逻辑代码,提高开发效率 - 提供代码生成功能,根据用户提供的项目信息和配置,自动生成前后端项目结构、代码文件和部分逻辑代码,提高开发效率
@@ -222,8 +203,8 @@ pnpm dev
## 核心技术栈 ## 核心技术栈
| 名称 | 版本 | 简介 | | 名称 | 版本 | 简介 |
| :----------------------------------------------------------- | :----------- | :----------------------------------------------------------- | | :----------------------------------------------------------- |:-------------| :----------------------------------------------------------- |
| <a href="https://cn.vuejs.org/" target="_blank">Vue</a> | 3.3.4 | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 | | <a href="https://cn.vuejs.org/" target="_blank">Vue</a> | 3.3.4 | 渐进式 JavaScript 框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 |
| <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 4.9.5 | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 | | <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 4.9.5 | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 |
| <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design Vue</a> | 2.52.0 | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。 | | <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design Vue</a> | 2.52.0 | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。 |
@@ -239,7 +220,7 @@ pnpm dev
| <a href="https://github.com/liquibase/liquibase" target="_blank">Liquibase</a> | 4.9.1 | 用于管理数据库版本,跟踪、管理和应用数据库变化。 | | <a href="https://github.com/liquibase/liquibase" target="_blank">Liquibase</a> | 4.9.1 | 用于管理数据库版本,跟踪、管理和应用数据库变化。 |
| <a href="https://redis.io/" target="_blank">Redis</a> | 6.2.7 | 高性能的 key-value 数据库。 | | <a href="https://redis.io/" target="_blank">Redis</a> | 6.2.7 | 高性能的 key-value 数据库。 |
| <a href="https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D" target="_blank">Redisson</a> | 3.20.1 | 不仅仅是一个 Redis Java 客户端,同其他 Redis Java 客户端有着很大的区别,相比之下其他客户端提供的功能还仅仅停留在作为数据库驱动层面上,比如仅针对 Redis 提供连接方式,发送命令和处理返回结果等。而 Redisson 充分的利用了 Redis 键值数据库提供的一系列优势,基于 Java 实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。 | | <a href="https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D" target="_blank">Redisson</a> | 3.20.1 | 不仅仅是一个 Redis Java 客户端,同其他 Redis Java 客户端有着很大的区别,相比之下其他客户端提供的功能还仅仅停留在作为数据库驱动层面上,比如仅针对 Redis 提供连接方式,发送命令和处理返回结果等。而 Redisson 充分的利用了 Redis 键值数据库提供的一系列优势,基于 Java 实用工具包中常用接口,为使用者提供了一系列具有分布式特性的常用工具类。使得原本作为协调单机多线程并发程序的工具包获得了协调分布式多机多线程并发系统的能力,大大降低了设计和研发大规模分布式系统的难度。同时结合各富特色的分布式服务,更进一步简化了分布式环境中程序相互之间的协作。 |
| <a href="https://sms4j.com/" target="_blank">SMS4J</a> | 3.0.3 | 短信聚合框架,轻松集成多家短信服务,解决接入多个短信 SDK 的繁琐流程。 | | <a href="https://sms4j.com/" target="_blank">SMS4J</a> | 3.0.4 | 短信聚合框架,轻松集成多家短信服务,解决接入多个短信 SDK 的繁琐流程。 |
| <a href="https://justauth.cn/" target="_blank">Just Auth</a> | 1.16.5 | 开箱即用的整合第三方登录的开源组件,脱离繁琐的第三方登录 SDK让登录变得 So easy | | <a href="https://justauth.cn/" target="_blank">Just Auth</a> | 1.16.5 | 开箱即用的整合第三方登录的开源组件,脱离繁琐的第三方登录 SDK让登录变得 So easy |
| <a href="https://easyexcel.opensource.alibaba.com/" target="_blank">Easy Excel</a> | 3.3.2 | 一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具。 | | <a href="https://easyexcel.opensource.alibaba.com/" target="_blank">Easy Excel</a> | 3.3.2 | 一个基于 Java 的、快速、简洁、解决大文件内存溢出的 Excel 处理工具。 |
| Easy Captcha | 1.6.2 | Java 图形验证码,支持 gif、中文、算术等类型可用于 Java Web、JavaSE 等项目。 | | Easy Captcha | 1.6.2 | Java 图形验证码,支持 gif、中文、算术等类型可用于 Java Web、JavaSE 等项目。 |
@@ -481,11 +462,31 @@ ContiNew Admin 的分支目前分为下个大版本的开发分支和上个大
> 2. 在提交代码前,请按照 [Angular 提交规范](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular) 编写 commit 的 message建议在 IntelliJ IDEA 中下载并安装 Git Commit Template 插件,以便按照规范进行 commit > 2. 在提交代码前,请按照 [Angular 提交规范](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular) 编写 commit 的 message建议在 IntelliJ IDEA 中下载并安装 Git Commit Template 插件,以便按照规范进行 commit
> 3. 提交代码之前,请关闭所有代码窗口,执行 mvn compile 命令(项目已配置代码格式化插件,编译通过的同时也会自动进行代码格式化),编译通过后,不要再打开查看任何代码窗口,直接提交即可,以免不同的 IDE 配置会自动进行代码格式化 > 3. 提交代码之前,请关闭所有代码窗口,执行 mvn compile 命令(项目已配置代码格式化插件,编译通过的同时也会自动进行代码格式化),编译通过后,不要再打开查看任何代码窗口,直接提交即可,以免不同的 IDE 配置会自动进行代码格式化
## 反馈交流
💬 欢迎各位小伙伴儿扫描下方二维码加好友,备注 `cnadmin`,拉你进群,探讨技术、提提需求~
加入交流群后,你将会:
- 第一时间收到框架动态
- 第一时间收到框架更新通知
- 第一时间收到框架 Bug 通知
- 和众多大佬互相 (huá shuǐ) 交流 (mō yú)
<div align="left">
<img src=".image/qrcode.jpg" alt="二维码" width="230px" />
</div>
<details>
<summary>无加群意愿</summary>
💬 如无加群意愿,欢迎在 <a href="https://github.com/Charles7c/continew-admin/issues" target="_blank">Issues</a> 中反馈交流~ 🍻
</details>
## 鸣谢 ## 鸣谢
### 鸣谢 ### 鸣谢
感谢参与贡献的每一位小伙伴!(以下排名不分先后) 感谢参与贡献的每一位小伙伴🥰
<a href="https://github.com/Charles7c/continew-admin/graphs/contributors"> <a href="https://github.com/Charles7c/continew-admin/graphs/contributors">
<img src="https://opencollective.com/continew-admin/contributors.svg?width=890&button=false" alt="contributors" /> <img src="https://opencollective.com/continew-admin/contributors.svg?width=890&button=false" alt="contributors" />
@@ -496,7 +497,11 @@ ContiNew Admin 的分支目前分为下个大版本的开发分支和上个大
- 感谢 <a href="https://www.jetbrains.com/" target="_blank">JetBrains</a> 提供的 <a href="https://www.jetbrains.com/shop/eform/opensource" target="_blank">非商业开源软件开发授权</a> - 感谢 <a href="https://www.jetbrains.com/" target="_blank">JetBrains</a> 提供的 <a href="https://www.jetbrains.com/shop/eform/opensource" target="_blank">非商业开源软件开发授权</a>
- 感谢 <a href="http://pro.arco.design/" target="_blank">Arco Design Pro</a> 开箱即用的中后台前端解决方案 - 感谢 <a href="http://pro.arco.design/" target="_blank">Arco Design Pro</a> 开箱即用的中后台前端解决方案
- 感谢 <a href="https://github.com/baomidou/mybatis-plus" target="_blank">MyBatis Plus</a><a href="https://github.com/dromara/sa-token" target="_blank">Sa-Token</a><a href="https://github.com/alibaba/easyexcel" target="_blank">Easy Excel</a><a href="https://github.com/xiaoymin/knife4j" target="_blank">Knife4j</a><a href="https://github.com/dromara/hutool" target="_blank">Hutool</a> 等国产开源组件作者为国内开源世界作出的贡献 - 感谢 <a href="https://github.com/baomidou/mybatis-plus" target="_blank">MyBatis Plus</a><a href="https://github.com/dromara/sa-token" target="_blank">Sa-Token</a><a href="https://github.com/alibaba/easyexcel" target="_blank">Easy Excel</a><a href="https://github.com/xiaoymin/knife4j" target="_blank">Knife4j</a><a href="https://github.com/dromara/hutool" target="_blank">Hutool</a> 等国产开源组件作者为国内开源世界作出的贡献
- 感谢 <a href="https://github.com/elunez/eladmin" target="_blank">ELADMIN</a><a href="https://github.com/dromara/RuoYi-Vue-Plus" target="_blank">RuoYi-Vue-Plus</a><a href="https://github.com/yangzongzhuan/RuoYi-Vue3" target="_blank">RuoYi-Vue3</a> 提供的诸多成熟方案,致敬各位作者为开源脚手架领域作出的贡献 - 感谢 <a href="https://github.com/elunez/eladmin" target="_blank">ELADMIN</a><a href="https://github.com/yangzongzhuan/RuoYi-Vue3" target="_blank">RuoYi-Vue3</a><a href="https://github.com/dromara/RuoYi-Vue-Plus" target="_blank">RuoYi-Vue-Plus</a>,致敬各位作者为开源脚手架领域作出的贡献
- e.g. 脱胎于 ELADMIN 项目开源的 QueryHelper 组件
- e.g. 参考 RuoYi-Vue3 前端项目的 Vue3 编码风格和规范
- e.g. 使用 RuoYi-Vue-Plus 项目封装的 SaToken 相关认证鉴权配置等
- 感谢项目使用或未使用到的每一款开源组件,致敬各位开源先驱 :fire: - 感谢项目使用或未使用到的每一款开源组件,致敬各位开源先驱 :fire:
## License ## License

View File

@@ -1,19 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- 生成当前格式化配置文件参照https://github.com/diffplug/spotless/blob/main/ECLIPSE_SCREENSHOTS.md --> <!-- 生成当前格式化配置文件参照https://github.com/diffplug/spotless/blob/main/ECLIPSE_SCREENSHOTS.md -->
<profiles version="12"> <profiles version="12">
<profile kind="CodeFormatterProfile" name="P3C-CodeStyle" version="13"> <profile kind="CodeFormatterProfile" name="P3C-CodeStyle" version="13">

View File

@@ -1,19 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

View File

@@ -1,32 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 响应拦截忽略注解
*
* @author BULL_BCLS
* @since 2023/10/8 20:44
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoResponseAdvice {}

View File

@@ -37,7 +37,6 @@ import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import top.charles7c.cnadmin.common.annotation.CrudRequestMapping; import top.charles7c.cnadmin.common.annotation.CrudRequestMapping;
import top.charles7c.cnadmin.common.annotation.NoResponseAdvice;
import top.charles7c.cnadmin.common.constant.StringConsts; import top.charles7c.cnadmin.common.constant.StringConsts;
import top.charles7c.cnadmin.common.model.query.PageQuery; import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.query.SortQuery; import top.charles7c.cnadmin.common.model.query.SortQuery;
@@ -78,9 +77,9 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q,
@Operation(summary = "分页查询列表", description = "分页查询列表") @Operation(summary = "分页查询列表", description = "分页查询列表")
@ResponseBody @ResponseBody
@GetMapping @GetMapping
public PageDataResp<L> page(Q query, @Validated PageQuery pageQuery) { public R<PageDataResp<L>> page(Q query, @Validated PageQuery pageQuery) {
this.checkPermission(Api.LIST); this.checkPermission(Api.LIST);
return baseService.page(query, pageQuery); return R.ok(baseService.page(query, pageQuery));
} }
/** /**
@@ -95,9 +94,9 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q,
@Operation(summary = "查询树列表", description = "查询树列表") @Operation(summary = "查询树列表", description = "查询树列表")
@ResponseBody @ResponseBody
@GetMapping("/tree") @GetMapping("/tree")
public List<Tree<Long>> tree(Q query, SortQuery sortQuery) { public R<List<Tree<Long>>> tree(Q query, SortQuery sortQuery) {
this.checkPermission(Api.LIST); this.checkPermission(Api.LIST);
return baseService.tree(query, sortQuery, false); return R.ok(baseService.tree(query, sortQuery, false));
} }
/** /**
@@ -112,9 +111,9 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q,
@Operation(summary = "查询列表", description = "查询列表") @Operation(summary = "查询列表", description = "查询列表")
@ResponseBody @ResponseBody
@GetMapping("/list") @GetMapping("/list")
public List<L> list(Q query, SortQuery sortQuery) { public R<List<L>> list(Q query, SortQuery sortQuery) {
this.checkPermission(Api.LIST); this.checkPermission(Api.LIST);
return baseService.list(query, sortQuery); return R.ok(baseService.list(query, sortQuery));
} }
/** /**
@@ -128,9 +127,9 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q,
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@ResponseBody @ResponseBody
@GetMapping("/{id}") @GetMapping("/{id}")
public D get(@PathVariable Long id) { public R<D> get(@PathVariable Long id) {
this.checkPermission(Api.LIST); this.checkPermission(Api.LIST);
return baseService.get(id); return R.ok(baseService.get(id));
} }
/** /**
@@ -196,7 +195,6 @@ public abstract class BaseController<S extends BaseService<L, D, Q, C>, L, D, Q,
* 响应对象 * 响应对象
*/ */
@Operation(summary = "导出数据", description = "导出数据") @Operation(summary = "导出数据", description = "导出数据")
@NoResponseAdvice
@GetMapping("/export") @GetMapping("/export")
public void export(Q query, SortQuery sortQuery, HttpServletResponse response) { public void export(Q query, SortQuery sortQuery, HttpServletResponse response) {
this.checkPermission(Api.EXPORT); this.checkPermission(Api.EXPORT);

View File

@@ -1,70 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.charles7c.cnadmin.common.handler;
import lombok.RequiredArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import cn.hutool.core.util.StrUtil;
import top.charles7c.cnadmin.common.annotation.NoResponseAdvice;
import top.charles7c.cnadmin.common.model.resp.R;
/**
* 全局响应结果处理器
*
* @author BULL_BCLS
* @since 2023/10/8 20:19
*/
@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalResponseBodyAdviceHandler implements ResponseBodyAdvice<Object> {
private static final String[] EXCLUDE = {"MultipleOpenApiWebMvcResource", "SwaggerConfigResource",};
private final ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {
return !methodParameter.getParameterType().isAssignableFrom(R.class)
&& !methodParameter.hasMethodAnnotation(NoResponseAdvice.class)
&& !StrUtil.equalsAny(methodParameter.getDeclaringClass().getSimpleName(), EXCLUDE);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
if (String.class.equals(returnType.getGenericParameterType())) {
try {
return objectMapper.writeValueAsString(R.ok(body));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
return R.ok(body);
}
}

View File

@@ -1,19 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

View File

@@ -139,10 +139,9 @@ public class LogServiceImpl implements LogService {
public SystemLogDetailResp get(Long id) { public SystemLogDetailResp get(Long id) {
LogDO logDO = logMapper.selectById(id); LogDO logDO = logMapper.selectById(id);
CheckUtils.throwIfNotExists(logDO, "LogDO", "ID", id); CheckUtils.throwIfNotExists(logDO, "LogDO", "ID", id);
SystemLogDetailResp detail = BeanUtil.copyProperties(logDO, SystemLogDetailResp.class);
SystemLogDetailResp detailVO = BeanUtil.copyProperties(logDO, SystemLogDetailResp.class); this.fill(detail);
this.fill(detailVO); return detail;
return detailVO;
} }
@Override @Override

View File

@@ -1,19 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

View File

@@ -19,7 +19,6 @@ package top.charles7c.cnadmin.system.model.req;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import lombok.Data; import lombok.Data;
@@ -28,7 +27,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
import top.charles7c.cnadmin.common.base.BaseReq; import top.charles7c.cnadmin.common.base.BaseReq;
import top.charles7c.cnadmin.common.constant.RegexConsts;
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum; import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
import top.charles7c.cnadmin.common.enums.MenuTypeEnum; import top.charles7c.cnadmin.common.enums.MenuTypeEnum;
@@ -63,7 +61,7 @@ public class MenuReq extends BaseReq {
*/ */
@Schema(description = "菜单标题", example = "用户管理") @Schema(description = "菜单标题", example = "用户管理")
@NotBlank(message = "菜单标题不能为空") @NotBlank(message = "菜单标题不能为空")
@Pattern(regexp = RegexConsts.GENERAL_NAME, message = "菜单标题长度为 2 到 30 位,可以包含中文、字母、数字、下划线,短横线") @Length(max = 30, message = "菜单标题长度不能超过 {max} 个字符")
private String title; private String title;
/** /**

View File

@@ -68,6 +68,7 @@ public class MessageServiceImpl implements MessageService {
} }
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void add(MessageReq req, List<Long> userIdList) { public void add(MessageReq req, List<Long> userIdList) {
CheckUtils.throwIf(() -> CollUtil.isEmpty(userIdList), "消息接收人不能为空"); CheckUtils.throwIf(() -> CollUtil.isEmpty(userIdList), "消息接收人不能为空");
MessageDO message = BeanUtil.copyProperties(req, MessageDO.class); MessageDO message = BeanUtil.copyProperties(req, MessageDO.class);

View File

@@ -135,16 +135,16 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
public void fillDetail(Object detailObj) { public void fillDetail(Object detailObj) {
super.fillDetail(detailObj); super.fillDetail(detailObj);
if (detailObj instanceof RoleDetailResp) { if (detailObj instanceof RoleDetailResp) {
RoleDetailResp detailVO = (RoleDetailResp)detailObj; RoleDetailResp detail = (RoleDetailResp)detailObj;
Long roleId = detailVO.getId(); Long roleId = detail.getId();
if (SysConsts.ADMIN_ROLE_CODE.equals(detailVO.getCode())) { if (SysConsts.ADMIN_ROLE_CODE.equals(detail.getCode())) {
List<MenuResp> list = menuService.list(null, null); List<MenuResp> list = menuService.list(null, null);
List<Long> menuIds = list.stream().map(MenuResp::getId).collect(Collectors.toList()); List<Long> menuIds = list.stream().map(MenuResp::getId).collect(Collectors.toList());
detailVO.setMenuIds(menuIds); detail.setMenuIds(menuIds);
} else { } else {
detailVO.setMenuIds(roleMenuService.listMenuIdByRoleIds(CollUtil.newArrayList(roleId))); detail.setMenuIds(roleMenuService.listMenuIdByRoleIds(CollUtil.newArrayList(roleId)));
} }
detailVO.setDeptIds(roleDeptService.listDeptIdByRoleId(roleId)); detail.setDeptIds(roleDeptService.listDeptIdByRoleId(roleId));
} }
} }

View File

@@ -153,11 +153,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
public void fillDetail(Object detailObj) { public void fillDetail(Object detailObj) {
super.fillDetail(detailObj); super.fillDetail(detailObj);
if (detailObj instanceof UserDetailResp) { if (detailObj instanceof UserDetailResp) {
UserDetailResp detailVO = (UserDetailResp)detailObj; UserDetailResp detail = (UserDetailResp)detailObj;
detailVO.setDeptName(ExceptionUtils.exToNull(() -> deptService.get(detailVO.getDeptId()).getName())); detail.setDeptName(ExceptionUtils.exToNull(() -> deptService.get(detail.getDeptId()).getName()));
List<Long> roleIdList = userRoleService.listRoleIdByUserId(detailVO.getId()); List<Long> roleIdList = userRoleService.listRoleIdByUserId(detail.getId());
detailVO.setRoleIds(roleIdList); detail.setRoleIds(roleIdList);
detailVO.setRoleNames(String.join(StringConsts.CHINESE_COMMA, roleService.listNameByIds(roleIdList))); detail.setRoleNames(String.join(StringConsts.CHINESE_COMMA, roleService.listNameByIds(roleIdList)));
} }
} }

View File

@@ -20,6 +20,7 @@ import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@@ -45,6 +46,7 @@ public class GenConfigReq implements Serializable {
/** /**
* 字段配置信息 * 字段配置信息
*/ */
@Valid
@Schema(description = "字段配置信息") @Schema(description = "字段配置信息")
@NotEmpty(message = "字段配置不能为空") @NotEmpty(message = "字段配置不能为空")
private List<FieldConfigDO> fieldConfigs = new ArrayList<>(); private List<FieldConfigDO> fieldConfigs = new ArrayList<>();
@@ -52,6 +54,7 @@ public class GenConfigReq implements Serializable {
/** /**
* 生成配置信息 * 生成配置信息
*/ */
@Valid
@Schema(description = "生成配置信息") @Schema(description = "生成配置信息")
@NotNull(message = "生成配置不能为空") @NotNull(message = "生成配置不能为空")
private GenConfigDO genConfig; private GenConfigDO genConfig;

View File

@@ -1,7 +1,7 @@
{ {
"name": "continew-admin-ui", "name": "continew-admin-ui",
"description": "ContiNew Admin 中后台管理框架Continue New Admin持续以最新流行技术栈构建拥抱变化迭代优化。", "description": "ContiNew Admin 中后台管理框架Continue New Admin持续以最新流行技术栈构建拥抱变化迭代优化。",
"version": "1.3.0", "version": "1.3.2-SNAPSHOT",
"private": true, "private": true,
"author": "Charles7c", "author": "Charles7c",
"license": "Apache-2.0", "license": "Apache-2.0",

View File

@@ -40,17 +40,17 @@ import App from './App.vue';
import '@/assets/style/global.less'; import '@/assets/style/global.less';
import '@/utils/request'; import '@/utils/request';
VueMarkdownEditor.use(createEmojiPlugin());
VueMarkdownEditor.use(createCopyCodePlugin());
VueMarkdownEditor.use(createTodoListPlugin());
hljs.registerLanguage('json', json);
hljs.registerLanguage('java', java);
VueMarkdownEditor.use(githubTheme, { VueMarkdownEditor.use(githubTheme, {
Hljs: hljs, Hljs: hljs,
}); });
VMdPreview.use(githubTheme, { VMdPreview.use(githubTheme, {
Hljs: hljs, Hljs: hljs,
}); });
VueMarkdownEditor.use(createEmojiPlugin());
VueMarkdownEditor.use(createCopyCodePlugin());
VueMarkdownEditor.use(createTodoListPlugin());
hljs.registerLanguage('json', json);
hljs.registerLanguage('java', java);
const app = createApp(App); const app = createApp(App);
// 全局方法挂载 // 全局方法挂载

View File

@@ -23,7 +23,7 @@ export default function setupUserLoginInfoGuard(router: Router) {
await userStore.getInfo(); await userStore.getInfo();
next(); next();
} catch (error) { } catch (error) {
await userStore.logout(); await userStore.logoutCallBack();
next({ next({
name: 'login', name: 'login',
query: { query: {

View File

@@ -22,8 +22,11 @@ const setTimer = (timer: number) => {
}; };
const clearTimer = () => { const clearTimer = () => {
clearInterval(Number(localStorage.getItem(TIMER_KEY))); const timer = localStorage.getItem(TIMER_KEY);
localStorage.removeItem(TIMER_KEY); if (timer) {
clearInterval(Number(timer));
localStorage.removeItem(TIMER_KEY);
}
}; };
export { isLogin, getToken, setToken, clearToken, setTimer, clearTimer }; export { isLogin, getToken, setToken, clearToken, setTimer, clearTimer };

View File

@@ -1,7 +1,7 @@
import axios from 'axios'; import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios'; import type { AxiosRequestConfig, AxiosResponse } from 'axios';
import { useUserStore } from '@/store'; import { useUserStore } from '@/store';
import { getToken } from '@/utils/auth'; import { getToken, clearTimer } from '@/utils/auth';
import modalErrorWrapper from '@/utils/modal-error-wrapper'; import modalErrorWrapper from '@/utils/modal-error-wrapper';
import messageErrorWrapper from '@/utils/message-error-wrapper'; import messageErrorWrapper from '@/utils/message-error-wrapper';
@@ -51,8 +51,7 @@ axios.interceptors.response.use(
return res; return res;
} }
if ([401].includes(res.code) && response.config.url !== '/auth/user/info') { if ([401].includes(res.code) && response.config.url !== '/auth/user/info') {
const userStore = useUserStore(); clearTimer();
userStore.logout();
modalErrorWrapper({ modalErrorWrapper({
title: '确认退出', title: '确认退出',
content: res.msg, content: res.msg,
@@ -60,6 +59,8 @@ axios.interceptors.response.use(
escToClose: false, escToClose: false,
okText: '重新登录', okText: '重新登录',
async onOk() { async onOk() {
const userStore = useUserStore();
userStore.logoutCallBack();
window.location.reload(); window.location.reload();
}, },
}); });

View File

@@ -60,7 +60,7 @@
const { chartOption } = useChartOption((isDark) => { const { chartOption } = useChartOption((isDark) => {
return { return {
grid: { grid: {
left: '30', left: '38',
right: '0', right: '0',
top: '10', top: '10',
bottom: '50', bottom: '50',
@@ -114,6 +114,9 @@
axisLabel: { axisLabel: {
formatter(value: any, idx: number) { formatter(value: any, idx: number) {
if (idx === 0) return value; if (idx === 0) return value;
if (value >= 1000) {
return `${value / 1000}k`;
}
return `${value}`; return `${value}`;
}, },
}, },

View File

@@ -145,13 +145,17 @@
ellipsis ellipsis
tooltip tooltip
/> />
<a-table-column <a-table-column title="类型" :width="95" ellipsis tooltip>
title="类型" <template #cell="{ record }">
data-index="fieldType" <span v-if="record.fieldType">{{ record.fieldType }}</span>
:width="95" <a-tooltip v-else content="请检查 generator.properties 配置">
ellipsis <icon-exclamation-circle-fill
tooltip size="large"
/> style="color: #f53f3f"
/>
</a-tooltip>
</template>
</a-table-column>
<a-table-column title="描述" :width="170"> <a-table-column title="描述" :width="170">
<template #cell="{ record }"> <template #cell="{ record }">
<a-input v-model="record.comment" /> <a-input v-model="record.comment" />

View File

@@ -1,19 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

View File

@@ -41,6 +41,7 @@ import top.charles7c.cnadmin.auth.model.resp.UserInfoResp;
import top.charles7c.cnadmin.auth.service.LoginService; import top.charles7c.cnadmin.auth.service.LoginService;
import top.charles7c.cnadmin.common.constant.CacheConsts; import top.charles7c.cnadmin.common.constant.CacheConsts;
import top.charles7c.cnadmin.common.model.dto.LoginUser; import top.charles7c.cnadmin.common.model.dto.LoginUser;
import top.charles7c.cnadmin.common.model.resp.R;
import top.charles7c.cnadmin.common.util.ExceptionUtils; import top.charles7c.cnadmin.common.util.ExceptionUtils;
import top.charles7c.cnadmin.common.util.RedisUtils; import top.charles7c.cnadmin.common.util.RedisUtils;
import top.charles7c.cnadmin.common.util.SecureUtils; import top.charles7c.cnadmin.common.util.SecureUtils;
@@ -69,7 +70,7 @@ public class AuthController {
@SaIgnore @SaIgnore
@Operation(summary = "账号登录", description = "根据账号和密码进行登录认证") @Operation(summary = "账号登录", description = "根据账号和密码进行登录认证")
@PostMapping("/account") @PostMapping("/account")
public LoginResp accountLogin(@Validated @RequestBody AccountLoginReq loginReq) { public R<LoginResp> accountLogin(@Validated @RequestBody AccountLoginReq loginReq) {
String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, loginReq.getUuid()); String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, loginReq.getUuid());
String captcha = RedisUtils.getCacheObject(captchaKey); String captcha = RedisUtils.getCacheObject(captchaKey);
ValidationUtils.throwIfBlank(captcha, "验证码已失效"); ValidationUtils.throwIfBlank(captcha, "验证码已失效");
@@ -79,13 +80,13 @@ public class AuthController {
String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(loginReq.getPassword())); String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(loginReq.getPassword()));
ValidationUtils.throwIfBlank(rawPassword, "密码解密失败"); ValidationUtils.throwIfBlank(rawPassword, "密码解密失败");
String token = loginService.accountLogin(loginReq.getUsername(), rawPassword); String token = loginService.accountLogin(loginReq.getUsername(), rawPassword);
return LoginResp.builder().token(token).build(); return R.ok(LoginResp.builder().token(token).build());
} }
@SaIgnore @SaIgnore
@Operation(summary = "邮箱登录", description = "根据邮箱和验证码进行登录认证") @Operation(summary = "邮箱登录", description = "根据邮箱和验证码进行登录认证")
@PostMapping("/email") @PostMapping("/email")
public LoginResp emailLogin(@Validated @RequestBody EmailLoginReq loginReq) { public R<LoginResp> emailLogin(@Validated @RequestBody EmailLoginReq loginReq) {
String email = loginReq.getEmail(); String email = loginReq.getEmail();
String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, email); String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, email);
String captcha = RedisUtils.getCacheObject(captchaKey); String captcha = RedisUtils.getCacheObject(captchaKey);
@@ -93,13 +94,13 @@ public class AuthController {
ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, "验证码错误"); ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, "验证码错误");
RedisUtils.deleteCacheObject(captchaKey); RedisUtils.deleteCacheObject(captchaKey);
String token = loginService.emailLogin(email); String token = loginService.emailLogin(email);
return LoginResp.builder().token(token).build(); return R.ok(LoginResp.builder().token(token).build());
} }
@SaIgnore @SaIgnore
@Operation(summary = "手机号登录", description = "根据手机号和验证码进行登录认证") @Operation(summary = "手机号登录", description = "根据手机号和验证码进行登录认证")
@PostMapping("/phone") @PostMapping("/phone")
public LoginResp phoneLogin(@Validated @RequestBody PhoneLoginReq loginReq) { public R<LoginResp> phoneLogin(@Validated @RequestBody PhoneLoginReq loginReq) {
String phone = loginReq.getPhone(); String phone = loginReq.getPhone();
String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, phone); String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, phone);
String captcha = RedisUtils.getCacheObject(captchaKey); String captcha = RedisUtils.getCacheObject(captchaKey);
@@ -107,35 +108,35 @@ public class AuthController {
ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, "验证码错误"); ValidationUtils.throwIfNotEqualIgnoreCase(loginReq.getCaptcha(), captcha, "验证码错误");
RedisUtils.deleteCacheObject(captchaKey); RedisUtils.deleteCacheObject(captchaKey);
String token = loginService.phoneLogin(phone); String token = loginService.phoneLogin(phone);
return LoginResp.builder().token(token).build(); return R.ok(LoginResp.builder().token(token).build());
} }
@SaIgnore
@Operation(summary = "用户退出", description = "注销用户的当前登录") @Operation(summary = "用户退出", description = "注销用户的当前登录")
@Parameter(name = "Authorization", description = "令牌", required = true, example = "Bearer xxxx-xxxx-xxxx-xxxx", @Parameter(name = "Authorization", description = "令牌", required = true, example = "Bearer xxxx-xxxx-xxxx-xxxx",
in = ParameterIn.HEADER) in = ParameterIn.HEADER)
@PostMapping("/logout") @PostMapping("/logout")
public void logout() { public R logout() {
StpUtil.logout(); StpUtil.logout();
return R.ok();
} }
@Log(ignore = true) @Log(ignore = true)
@Operation(summary = "获取用户信息", description = "获取登录用户信息") @Operation(summary = "获取用户信息", description = "获取登录用户信息")
@GetMapping("/user/info") @GetMapping("/user/info")
public UserInfoResp getUserInfo() { public R<UserInfoResp> getUserInfo() {
LoginUser loginUser = LoginHelper.getLoginUser(); LoginUser loginUser = LoginHelper.getLoginUser();
UserDetailResp userDetailResp = userService.get(loginUser.getId()); UserDetailResp userDetailResp = userService.get(loginUser.getId());
UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class); UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
userInfoResp.setPermissions(loginUser.getPermissions()); userInfoResp.setPermissions(loginUser.getPermissions());
userInfoResp.setRoles(loginUser.getRoleCodes()); userInfoResp.setRoles(loginUser.getRoleCodes());
return userInfoResp; return R.ok(userInfoResp);
} }
@Log(ignore = true) @Log(ignore = true)
@Operation(summary = "获取路由信息", description = "获取登录用户的路由信息") @Operation(summary = "获取路由信息", description = "获取登录用户的路由信息")
@GetMapping("/route") @GetMapping("/route")
public List<RouteResp> listRoute() { public R<List<RouteResp>> listRoute() {
Long userId = LoginHelper.getUserId(); Long userId = LoginHelper.getUserId();
return loginService.buildRouteTree(userId); return R.ok(loginService.buildRouteTree(userId));
} }
} }

View File

@@ -71,7 +71,7 @@ public class SocialAuthController {
@Operation(summary = "三方账号登录", description = "三方账号登录") @Operation(summary = "三方账号登录", description = "三方账号登录")
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH) @Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
@PostMapping("/{source}") @PostMapping("/{source}")
public LoginResp login(@PathVariable String source, @RequestBody AuthCallback callback) { public R<LoginResp> login(@PathVariable String source, @RequestBody AuthCallback callback) {
if (StpUtil.isLogin()) { if (StpUtil.isLogin()) {
StpUtil.logout(); StpUtil.logout();
} }
@@ -80,7 +80,7 @@ public class SocialAuthController {
ValidationUtils.throwIf(!response.ok(), response.getMsg()); ValidationUtils.throwIf(!response.ok(), response.getMsg());
AuthUser authUser = response.getData(); AuthUser authUser = response.getData();
String token = loginService.socialLogin(authUser); String token = loginService.socialLogin(authUser);
return LoginResp.builder().token(token).build(); return R.ok(LoginResp.builder().token(token).build());
} }
private AuthRequest getAuthRequest(String source) { private AuthRequest getAuthRequest(String source) {

View File

@@ -76,7 +76,7 @@ public class CaptchaController {
@Operation(summary = "获取图片验证码", description = "获取图片验证码Base64编码带图片格式data:image/gif;base64") @Operation(summary = "获取图片验证码", description = "获取图片验证码Base64编码带图片格式data:image/gif;base64")
@GetMapping("/img") @GetMapping("/img")
public CaptchaResp getImageCaptcha() { public R<CaptchaResp> getImageCaptcha() {
// 生成验证码 // 生成验证码
CaptchaProperties.CaptchaImage captchaImage = captchaProperties.getImage(); CaptchaProperties.CaptchaImage captchaImage = captchaProperties.getImage();
Captcha captcha = captchaImage.getCaptcha(); Captcha captcha = captchaImage.getCaptcha();
@@ -85,7 +85,7 @@ public class CaptchaController {
String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, uuid); String captchaKey = RedisUtils.formatKey(CacheConsts.CAPTCHA_KEY_PREFIX, uuid);
RedisUtils.setCacheObject(captchaKey, captcha.text(), RedisUtils.setCacheObject(captchaKey, captcha.text(),
Duration.ofMinutes(captchaImage.getExpirationInMinutes())); Duration.ofMinutes(captchaImage.getExpirationInMinutes()));
return CaptchaResp.builder().uuid(uuid).img(captcha.toBase64()).build(); return R.ok(CaptchaResp.builder().uuid(uuid).img(captcha.toBase64()).build());
} }
@Operation(summary = "获取邮箱验证码", description = "发送验证码到指定邮箱") @Operation(summary = "获取邮箱验证码", description = "发送验证码到指定邮箱")

View File

@@ -97,39 +97,39 @@ public class CommonController {
@Operation(summary = "查询部门树", description = "查询树结构的部门列表") @Operation(summary = "查询部门树", description = "查询树结构的部门列表")
@GetMapping("/tree/dept") @GetMapping("/tree/dept")
public List<Tree<Long>> listDeptTree(DeptQuery query, SortQuery sortQuery) { public R<List<Tree<Long>>> listDeptTree(DeptQuery query, SortQuery sortQuery) {
return deptService.tree(query, sortQuery, true); return R.ok(deptService.tree(query, sortQuery, true));
} }
@Operation(summary = "查询菜单树", description = "查询树结构的菜单列表") @Operation(summary = "查询菜单树", description = "查询树结构的菜单列表")
@GetMapping("/tree/menu") @GetMapping("/tree/menu")
public List<Tree<Long>> listMenuTree(MenuQuery query, SortQuery sortQuery) { public R<List<Tree<Long>>> listMenuTree(MenuQuery query, SortQuery sortQuery) {
return menuService.tree(query, sortQuery, true); return R.ok(menuService.tree(query, sortQuery, true));
} }
@Operation(summary = "查询角色字典", description = "查询角色字典列表") @Operation(summary = "查询角色字典", description = "查询角色字典列表")
@GetMapping("/dict/role") @GetMapping("/dict/role")
public List<LabelValueResp<Long>> listRoleDict(RoleQuery query, SortQuery sortQuery) { public R<List<LabelValueResp<Long>>> listRoleDict(RoleQuery query, SortQuery sortQuery) {
List<RoleResp> list = roleService.list(query, sortQuery); List<RoleResp> list = roleService.list(query, sortQuery);
return roleService.buildDict(list); return R.ok(roleService.buildDict(list));
} }
@Operation(summary = "查询字典", description = "查询字典列表") @Operation(summary = "查询字典", description = "查询字典列表")
@Parameter(name = "code", description = "字典编码", example = "announcement_type", in = ParameterIn.PATH) @Parameter(name = "code", description = "字典编码", example = "announcement_type", in = ParameterIn.PATH)
@GetMapping("/dict/{code}") @GetMapping("/dict/{code}")
@Cacheable(key = "#code", cacheNames = CacheConsts.DICT_KEY_PREFIX) @Cacheable(key = "#code", cacheNames = CacheConsts.DICT_KEY_PREFIX)
public List<LabelValueResp> listDict(@PathVariable String code) { public R<List<LabelValueResp>> listDict(@PathVariable String code) {
Optional<Class<?>> enumClass = this.getEnumClassByName(code); Optional<Class<?>> enumClass = this.getEnumClassByName(code);
return enumClass.map(this::listEnumDict).orElseGet(() -> dictItemService.listByDictCode(code)); return R.ok(enumClass.map(this::listEnumDict).orElseGet(() -> dictItemService.listByDictCode(code)));
} }
@SaIgnore @SaIgnore
@Operation(summary = "查询参数", description = "查询参数") @Operation(summary = "查询参数", description = "查询参数")
@GetMapping("/option") @GetMapping("/option")
@Cacheable(cacheNames = CacheConsts.OPTION_KEY_PREFIX) @Cacheable(cacheNames = CacheConsts.OPTION_KEY_PREFIX)
public List<LabelValueResp> listOption(@Validated OptionQuery query) { public R<List<LabelValueResp>> listOption(@Validated OptionQuery query) {
return optionService.list(query).stream().map(option -> new LabelValueResp(option.getCode(), return R.ok(optionService.list(query).stream().map(option -> new LabelValueResp(option.getCode(),
StrUtil.nullToDefault(option.getValue(), option.getDefaultValue()))).collect(Collectors.toList()); StrUtil.nullToDefault(option.getValue(), option.getDefaultValue()))).collect(Collectors.toList()));
} }
/** /**

View File

@@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import top.charles7c.cnadmin.common.model.resp.R;
import top.charles7c.cnadmin.common.util.validate.ValidationUtils; import top.charles7c.cnadmin.common.util.validate.ValidationUtils;
import top.charles7c.cnadmin.monitor.annotation.Log; import top.charles7c.cnadmin.monitor.annotation.Log;
import top.charles7c.cnadmin.monitor.model.resp.DashboardAccessTrendResp; import top.charles7c.cnadmin.monitor.model.resp.DashboardAccessTrendResp;
@@ -58,33 +59,33 @@ public class DashboardController {
@Operation(summary = "查询总计信息", description = "查询总计信息") @Operation(summary = "查询总计信息", description = "查询总计信息")
@GetMapping("/total") @GetMapping("/total")
public DashboardTotalResp getTotal() { public R<DashboardTotalResp> getTotal() {
return dashboardService.getTotal(); return R.ok(dashboardService.getTotal());
} }
@Operation(summary = "查询访问趋势信息", description = "查询访问趋势信息") @Operation(summary = "查询访问趋势信息", description = "查询访问趋势信息")
@Parameter(name = "days", description = "日期数", example = "30", in = ParameterIn.PATH) @Parameter(name = "days", description = "日期数", example = "30", in = ParameterIn.PATH)
@GetMapping("/access/trend/{days}") @GetMapping("/access/trend/{days}")
public List<DashboardAccessTrendResp> listAccessTrend(@PathVariable Integer days) { public R<List<DashboardAccessTrendResp>> listAccessTrend(@PathVariable Integer days) {
ValidationUtils.throwIf(7 != days && 30 != days, "仅支持查询近 7/30 天访问趋势信息"); ValidationUtils.throwIf(7 != days && 30 != days, "仅支持查询近 7/30 天访问趋势信息");
return dashboardService.listAccessTrend(days); return R.ok(dashboardService.listAccessTrend(days));
} }
@Operation(summary = "查询热门模块列表", description = "查询热门模块列表") @Operation(summary = "查询热门模块列表", description = "查询热门模块列表")
@GetMapping("/popular/module") @GetMapping("/popular/module")
public List<DashboardPopularModuleResp> listPopularModule() { public R<List<DashboardPopularModuleResp>> listPopularModule() {
return dashboardService.listPopularModule(); return R.ok(dashboardService.listPopularModule());
} }
@Operation(summary = "查询访客地域分布信息", description = "查询访客地域分布信息") @Operation(summary = "查询访客地域分布信息", description = "查询访客地域分布信息")
@GetMapping("/geo/distribution") @GetMapping("/geo/distribution")
public DashboardGeoDistributionResp getGeoDistribution() { public R<DashboardGeoDistributionResp> getGeoDistribution() {
return dashboardService.getGeoDistribution(); return R.ok(dashboardService.getGeoDistribution());
} }
@Operation(summary = "查询公告列表", description = "查询公告列表") @Operation(summary = "查询公告列表", description = "查询公告列表")
@GetMapping("/announcement") @GetMapping("/announcement")
public List<DashboardAnnouncementResp> listAnnouncement() { public R<List<DashboardAnnouncementResp>> listAnnouncement() {
return dashboardService.listAnnouncement(); return R.ok(dashboardService.listAnnouncement());
} }
} }

View File

@@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RestController;
import top.charles7c.cnadmin.common.model.query.PageQuery; import top.charles7c.cnadmin.common.model.query.PageQuery;
import top.charles7c.cnadmin.common.model.resp.PageDataResp; import top.charles7c.cnadmin.common.model.resp.PageDataResp;
import top.charles7c.cnadmin.common.model.resp.R;
import top.charles7c.cnadmin.monitor.annotation.Log; import top.charles7c.cnadmin.monitor.annotation.Log;
import top.charles7c.cnadmin.monitor.model.query.LoginLogQuery; import top.charles7c.cnadmin.monitor.model.query.LoginLogQuery;
import top.charles7c.cnadmin.monitor.model.query.OperationLogQuery; import top.charles7c.cnadmin.monitor.model.query.OperationLogQuery;
@@ -58,29 +59,29 @@ public class LogController {
@Log(module = "登录日志") @Log(module = "登录日志")
@Operation(summary = "分页查询登录日志列表", description = "分页查询登录日志列表") @Operation(summary = "分页查询登录日志列表", description = "分页查询登录日志列表")
@GetMapping("/login") @GetMapping("/login")
public PageDataResp<LoginLogResp> page(LoginLogQuery query, @Validated PageQuery pageQuery) { public R<PageDataResp<LoginLogResp>> page(LoginLogQuery query, @Validated PageQuery pageQuery) {
return logService.page(query, pageQuery); return R.ok(logService.page(query, pageQuery));
} }
@Log(module = "操作日志") @Log(module = "操作日志")
@Operation(summary = "分页查询操作日志列表", description = "分页查询操作日志列表") @Operation(summary = "分页查询操作日志列表", description = "分页查询操作日志列表")
@GetMapping("/operation") @GetMapping("/operation")
public PageDataResp<OperationLogResp> page(OperationLogQuery query, @Validated PageQuery pageQuery) { public R<PageDataResp<OperationLogResp>> page(OperationLogQuery query, @Validated PageQuery pageQuery) {
return logService.page(query, pageQuery); return R.ok(logService.page(query, pageQuery));
} }
@Log(module = "系统日志") @Log(module = "系统日志")
@Operation(summary = "分页查询系统日志列表", description = "分页查询系统日志列表") @Operation(summary = "分页查询系统日志列表", description = "分页查询系统日志列表")
@GetMapping("/system") @GetMapping("/system")
public PageDataResp<SystemLogResp> page(SystemLogQuery query, @Validated PageQuery pageQuery) { public R<PageDataResp<SystemLogResp>> page(SystemLogQuery query, @Validated PageQuery pageQuery) {
return logService.page(query, pageQuery); return R.ok(logService.page(query, pageQuery));
} }
@Log(module = "系统日志") @Log(module = "系统日志")
@Operation(summary = "查看系统日志详情", description = "查看系统日志详情") @Operation(summary = "查看系统日志详情", description = "查看系统日志详情")
@Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH) @Parameter(name = "id", description = "ID", example = "1", in = ParameterIn.PATH)
@GetMapping("/system/{id}") @GetMapping("/system/{id}")
public SystemLogDetailResp get(@PathVariable Long id) { public R<SystemLogDetailResp> get(@PathVariable Long id) {
return logService.get(id); return R.ok(logService.get(id));
} }
} }

View File

@@ -54,8 +54,8 @@ public class OnlineUserController {
@Operation(summary = "分页查询列表", description = "分页查询列表") @Operation(summary = "分页查询列表", description = "分页查询列表")
@SaCheckPermission("monitor:online:user:list") @SaCheckPermission("monitor:online:user:list")
@GetMapping @GetMapping
public PageDataResp<OnlineUserResp> page(OnlineUserQuery query, @Validated PageQuery pageQuery) { public R<PageDataResp<OnlineUserResp>> page(OnlineUserQuery query, @Validated PageQuery pageQuery) {
return onlineUserService.page(query, pageQuery); return R.ok(onlineUserService.page(query, pageQuery));
} }
@Operation(summary = "强退在线用户", description = "强退在线用户") @Operation(summary = "强退在线用户", description = "强退在线用户")

View File

@@ -16,8 +16,6 @@
package top.charles7c.cnadmin.webapi.controller.system; package top.charles7c.cnadmin.webapi.controller.system;
import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -46,8 +44,7 @@ import top.charles7c.cnadmin.system.service.AnnouncementService;
*/ */
@Tag(name = "公告管理 API") @Tag(name = "公告管理 API")
@RestController @RestController
@CrudRequestMapping(value = "/system/announcement", @CrudRequestMapping("/system/announcement")
api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class AnnouncementController extends public class AnnouncementController extends
BaseController<AnnouncementService, AnnouncementResp, AnnouncementDetailResp, AnnouncementQuery, AnnouncementReq> { BaseController<AnnouncementService, AnnouncementResp, AnnouncementDetailResp, AnnouncementQuery, AnnouncementReq> {

View File

@@ -16,8 +16,6 @@
package top.charles7c.cnadmin.webapi.controller.system; package top.charles7c.cnadmin.webapi.controller.system;
import static top.charles7c.cnadmin.common.annotation.CrudRequestMapping.Api;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -38,5 +36,5 @@ import top.charles7c.cnadmin.system.service.DictService;
*/ */
@Tag(name = "字典管理 API") @Tag(name = "字典管理 API")
@RestController @RestController
@CrudRequestMapping(value = "/system/dict", api = {Api.PAGE, Api.GET, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT}) @CrudRequestMapping("/system/dict")
public class DictController extends BaseController<DictService, DictResp, DictDetailResp, DictQuery, DictReq> {} public class DictController extends BaseController<DictService, DictResp, DictDetailResp, DictQuery, DictReq> {}

View File

@@ -56,9 +56,9 @@ public class MessageController {
@Operation(summary = "分页查询列表", description = "分页查询列表") @Operation(summary = "分页查询列表", description = "分页查询列表")
@GetMapping @GetMapping
public PageDataResp<MessageResp> page(MessageQuery query, @Validated PageQuery pageQuery) { public R<PageDataResp<MessageResp>> page(MessageQuery query, @Validated PageQuery pageQuery) {
query.setUserId(LoginHelper.getUserId()); query.setUserId(LoginHelper.getUserId());
return baseService.page(query, pageQuery); return R.ok(baseService.page(query, pageQuery));
} }
@Operation(summary = "删除数据", description = "删除数据") @Operation(summary = "删除数据", description = "删除数据")
@@ -72,15 +72,16 @@ public class MessageController {
@Operation(summary = "标记已读", description = "将消息标记为已读状态") @Operation(summary = "标记已读", description = "将消息标记为已读状态")
@Parameter(name = "ids", description = "消息ID列表", example = "1,2", in = ParameterIn.QUERY) @Parameter(name = "ids", description = "消息ID列表", example = "1,2", in = ParameterIn.QUERY)
@PatchMapping("/read") @PatchMapping("/read")
public void readMessage(@RequestParam(required = false) List<Long> ids) { public R readMessage(@RequestParam(required = false) List<Long> ids) {
messageUserService.readMessage(ids); messageUserService.readMessage(ids);
return R.ok();
} }
@Log(ignore = true) @Log(ignore = true)
@Operation(summary = "查询未读消息数量", description = "查询当前用户的未读消息数量") @Operation(summary = "查询未读消息数量", description = "查询当前用户的未读消息数量")
@Parameter(name = "isDetail", description = "是否查询详情", example = "true", in = ParameterIn.QUERY) @Parameter(name = "isDetail", description = "是否查询详情", example = "true", in = ParameterIn.QUERY)
@GetMapping("/unread") @GetMapping("/unread")
public MessageUnreadResp countUnreadMessage(@RequestParam(required = false) Boolean detail) { public R<MessageUnreadResp> countUnreadMessage(@RequestParam(required = false) Boolean detail) {
return messageUserService.countUnreadMessageByUserId(LoginHelper.getUserId(), detail); return R.ok(messageUserService.countUnreadMessageByUserId(LoginHelper.getUserId(), detail));
} }
} }

View File

@@ -28,6 +28,7 @@ import org.springframework.web.bind.annotation.*;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import top.charles7c.cnadmin.common.model.resp.R;
import top.charles7c.cnadmin.system.model.query.OptionQuery; import top.charles7c.cnadmin.system.model.query.OptionQuery;
import top.charles7c.cnadmin.system.model.req.OptionReq; import top.charles7c.cnadmin.system.model.req.OptionReq;
import top.charles7c.cnadmin.system.model.req.OptionResetValueReq; import top.charles7c.cnadmin.system.model.req.OptionResetValueReq;
@@ -51,21 +52,23 @@ public class OptionController {
@Operation(summary = "查询参数列表", description = "查询参数列表") @Operation(summary = "查询参数列表", description = "查询参数列表")
@SaCheckPermission("system:config:list") @SaCheckPermission("system:config:list")
@GetMapping @GetMapping
public List<OptionResp> list(@Validated OptionQuery query) { public R<List<OptionResp>> list(@Validated OptionQuery query) {
return optionService.list(query); return R.ok(optionService.list(query));
} }
@Operation(summary = "修改参数", description = "修改参数") @Operation(summary = "修改参数", description = "修改参数")
@SaCheckPermission("system:config:update") @SaCheckPermission("system:config:update")
@PatchMapping @PatchMapping
public void update(@Validated @RequestBody List<OptionReq> req) { public R update(@Validated @RequestBody List<OptionReq> req) {
optionService.update(req); optionService.update(req);
return R.ok();
} }
@Operation(summary = "重置参数", description = "重置参数") @Operation(summary = "重置参数", description = "重置参数")
@SaCheckPermission("system:config:reset") @SaCheckPermission("system:config:reset")
@PatchMapping("/value") @PatchMapping("/value")
public void resetValue(@Validated @RequestBody OptionResetValueReq req) { public R resetValue(@Validated @RequestBody OptionResetValueReq req) {
optionService.resetValue(req); optionService.resetValue(req);
return R.ok();
} }
} }

View File

@@ -139,15 +139,15 @@ public class UserCenterController {
@Operation(summary = "查询绑定的三方账号", description = "查询绑定的三方账号") @Operation(summary = "查询绑定的三方账号", description = "查询绑定的三方账号")
@GetMapping("/social") @GetMapping("/social")
public List<UserSocialBindResp> listSocialBind() { public R<List<UserSocialBindResp>> listSocialBind() {
List<UserSocialDO> userSocialList = userSocialService.listByUserId(LoginHelper.getUserId()); List<UserSocialDO> userSocialList = userSocialService.listByUserId(LoginHelper.getUserId());
return userSocialList.stream().map(userSocial -> { return R.ok(userSocialList.stream().map(userSocial -> {
String source = userSocial.getSource(); String source = userSocial.getSource();
UserSocialBindResp userSocialBind = new UserSocialBindResp(); UserSocialBindResp userSocialBind = new UserSocialBindResp();
userSocialBind.setSource(source); userSocialBind.setSource(source);
userSocialBind.setDescription(SocialSourceEnum.valueOf(source).getDescription()); userSocialBind.setDescription(SocialSourceEnum.valueOf(source).getDescription());
return userSocialBind; return userSocialBind;
}).collect(Collectors.toList()); }).collect(Collectors.toList()));
} }
@Operation(summary = "绑定三方账号", description = "绑定三方账号") @Operation(summary = "绑定三方账号", description = "绑定三方账号")

View File

@@ -62,8 +62,8 @@ public class GeneratorController {
@Operation(summary = "分页查询数据表", description = "分页查询数据表") @Operation(summary = "分页查询数据表", description = "分页查询数据表")
@SaCheckPermission("tool:generator:list") @SaCheckPermission("tool:generator:list")
@GetMapping("/table") @GetMapping("/table")
public PageDataResp<TableResp> pageTable(TableQuery query, @Validated PageQuery pageQuery) throws SQLException { public R<PageDataResp<TableResp>> pageTable(TableQuery query, @Validated PageQuery pageQuery) throws SQLException {
return generatorService.pageTable(query, pageQuery); return R.ok(generatorService.pageTable(query, pageQuery));
} }
@Operation(summary = "查询字段配置列表", description = "查询字段配置列表") @Operation(summary = "查询字段配置列表", description = "查询字段配置列表")
@@ -71,17 +71,17 @@ public class GeneratorController {
@Parameter(name = "requireSync", description = "是否需要同步", example = "false", in = ParameterIn.QUERY) @Parameter(name = "requireSync", description = "是否需要同步", example = "false", in = ParameterIn.QUERY)
@SaCheckPermission("tool:generator:list") @SaCheckPermission("tool:generator:list")
@GetMapping("/field/{tableName}") @GetMapping("/field/{tableName}")
public List<FieldConfigDO> listFieldConfig(@PathVariable String tableName, public R<List<FieldConfigDO>> listFieldConfig(@PathVariable String tableName,
@RequestParam(required = false, defaultValue = "false") Boolean requireSync) { @RequestParam(required = false, defaultValue = "false") Boolean requireSync) {
return generatorService.listFieldConfig(tableName, requireSync); return R.ok(generatorService.listFieldConfig(tableName, requireSync));
} }
@Operation(summary = "查询生成配置信息", description = "查询生成配置信息") @Operation(summary = "查询生成配置信息", description = "查询生成配置信息")
@Parameter(name = "tableName", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH) @Parameter(name = "tableName", description = "表名称", required = true, example = "sys_user", in = ParameterIn.PATH)
@SaCheckPermission("tool:generator:list") @SaCheckPermission("tool:generator:list")
@GetMapping("/config/{tableName}") @GetMapping("/config/{tableName}")
public GenConfigDO getGenConfig(@PathVariable String tableName) throws SQLException { public R<GenConfigDO> getGenConfig(@PathVariable String tableName) throws SQLException {
return generatorService.getGenConfig(tableName); return R.ok(generatorService.getGenConfig(tableName));
} }
@Operation(summary = "保存配置信息", description = "保存配置信息") @Operation(summary = "保存配置信息", description = "保存配置信息")

View File

@@ -5,7 +5,7 @@ project:
# 应用名称 # 应用名称
appName: continew-admin appName: continew-admin
# 版本 # 版本
version: 1.3.0 version: 1.3.2-SNAPSHOT
# 描述 # 描述
description: ContiNew Admin 中后台管理框架/脚手架Continue New Admin持续以最新流行技术栈构建拥抱变化迭代优化。 description: ContiNew Admin 中后台管理框架/脚手架Continue New Admin持续以最新流行技术栈构建拥抱变化迭代优化。
# 基本包 # 基本包
@@ -58,7 +58,9 @@ springdoc:
packages-to-scan: ${project.basePackage}.webapi.controller packages-to-scan: ${project.basePackage}.webapi.controller
- group: 'auth' - group: 'auth'
display-name: '系统认证' display-name: '系统认证'
paths-to-match: '/auth/**' paths-to-match:
- '/auth/**'
- '/oauth/**'
packages-to-scan: ${project.basePackage}.webapi.controller.auth packages-to-scan: ${project.basePackage}.webapi.controller.auth
- group: 'common' - group: 'common'
display-name: '通用接口' display-name: '通用接口'

View File

@@ -28,7 +28,7 @@ services:
- /docker/redis/conf/redis.conf:/usr/local/redis/config/redis.conf - /docker/redis/conf/redis.conf:/usr/local/redis/config/redis.conf
- /docker/redis/data:/data - /docker/redis/data:/data
- /docker/redis/logs:/logs - /docker/redis/logs:/logs
command: 'redis-server /usr/local/redis/config/redis.conf --appendonly yes --requirepass 123456' command: 'redis-server /usr/local/redis/config/redis.conf --appendonly yes --requirepass 你的 Redis 密码'
continew-admin-server: continew-admin-server:
build: ./continew-admin build: ./continew-admin
restart: always restart: always
@@ -67,5 +67,5 @@ services:
volumes: volumes:
- /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf - /docker/nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- /docker/nginx/cert:/etc/nginx/cert - /docker/nginx/cert:/etc/nginx/cert
- /docker/continew-admin/web:/usr/share/nginx/html
- /docker/nginx/logs:/var/log/nginx - /docker/nginx/logs:/var/log/nginx
- /docker/continew-admin/web:/usr/share/nginx/html

View File

@@ -1,6 +1,6 @@
bind 0.0.0.0 bind 0.0.0.0
# redis 密码 # redis 密码
requirepass 123456 requirepass 你的 Redis 密码
# key 监听器配置 # key 监听器配置
# notify-keyspace-events Ex # notify-keyspace-events Ex

33
pom.xml
View File

@@ -1,24 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.16</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>top.charles7c</groupId> <groupId>top.charles7c</groupId>
<artifactId>continew-admin</artifactId> <artifactId>continew-admin</artifactId>
<version>${revision}</version> <version>${revision}</version>
@@ -36,13 +28,6 @@ limitations under the License.
<module>continew-admin-common</module> <module>continew-admin-common</module>
</modules> </modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.16</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties> <properties>
<sa-token.version>1.36.0</sa-token.version> <sa-token.version>1.36.0</sa-token.version>
@@ -52,7 +37,7 @@ limitations under the License.
<p6spy.version>3.9.1</p6spy.version> <p6spy.version>3.9.1</p6spy.version>
<!-- ### 工具库相关 ### --> <!-- ### 工具库相关 ### -->
<sms4j.version>3.0.3</sms4j.version> <sms4j.version>3.0.4</sms4j.version>
<justauth.version>1.16.5</justauth.version> <justauth.version>1.16.5</justauth.version>
<easyexcel.version>3.3.2</easyexcel.version> <easyexcel.version>3.3.2</easyexcel.version>
<ip2region.version>2.7.15</ip2region.version> <ip2region.version>2.7.15</ip2region.version>
@@ -62,7 +47,7 @@ limitations under the License.
<hutool.version>5.8.22</hutool.version> <hutool.version>5.8.22</hutool.version>
<!-- ### 基础环境相关 ### --> <!-- ### 基础环境相关 ### -->
<revision>1.3.0</revision> <revision>1.3.2-SNAPSHOT</revision>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spotless.version>2.30.0</spotless.version> <spotless.version>2.30.0</spotless.version>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>