升级2.0准备

This commit is contained in:
zccbbg 2024-06-28 11:16:00 +08:00
parent 89f1b77c57
commit 389104621f
1042 changed files with 41593 additions and 60300 deletions

18
.editorconfig Normal file
View file

@ -0,0 +1,18 @@
# http://editorconfig.org
root = true
# 空格替代Tab缩进在各种编辑工具下效果一致
[*]
indent_style = space
indent_size = 4
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.{json,yml,yaml}]
indent_size = 2
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

11
.gitignore vendored
View file

@ -25,11 +25,13 @@ target/
*.iml *.iml
*.ipr *.ipr
### JRebel ###
rebel.xml
### NetBeans ### ### NetBeans ###
nbproject/private/ nbproject/private/
build/* build/*
nbbuild/ nbbuild/
dist/
nbdist/ nbdist/
.nb-gradle/ .nb-gradle/
@ -42,7 +44,6 @@ nbdist/
!*/build/*.java !*/build/*.java
!*/build/*.html !*/build/*.html
!*/build/*.xml !*/build/*.xml
/sql/local.sql application-local.yml
*local*
/ruoyi-admin/src/main/resources/application-dev.yml .flattened-pom.xml
/ruoyi-admin/src/main/resources/application-prod.yml

View file

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2018 RuoYi Copyright (c) 2024 ruoyi-fast-service
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
@ -17,4 +17,4 @@ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

150
README.md
View file

@ -1,75 +1,95 @@
## 若依wms简介 ## 平台简介
若依wms是一套基于若依的wms仓库管理系统支持lodop和网页打印入库单、出库单。毫无保留给个人及企业免费使用。
* 前端采用Vue、Element UIant design 正在开发中)。 [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE)
* 后端采用Spring Boot、Spring Security、Redis & Jwt。 [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.1-blue.svg)]()
* 权限认证使用Jwt支持多终端认证系统。 [![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]()
* 支持加载动态权限菜单,多方式轻松权限控制。
* 高效率开发,使用代码生成器可以一键生成前后端代码。 > 本项目继承自ruoyi-vue-plus,由于ruoyi-vue-plus 4.x版本不再开发而5.x过于庞大增加了flowable和多租户本项目在4.x基础上适当增加一些5.x比较好的功能。
## 代码自动生成
修改application.yml文件中的backPath和frontPath路径。
backPath:为后端项目路径 > 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br>
frontPath:为前端项目路径 活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源
## 更新记录
参考:[UpdateHistory.md](UpdateHistory.md)
## 前端项目地址 ## 前端项目地址
### gitee #### gitee
https://gitee.com/zccbbg/ruo-yi-wms-vue [https://gitee.com/zccbbg/ruoyi-fast-vue3](https://gitee.com/zccbbg/ruoyi-fast-vue3)
### github
https://github.com/zccbbg/RuoYi-WMS-VUE
## 在线体验 #### github
- 演示地址http://wms.ichengle.top [https://github.com/zccbbg/ruoyi-fast-vue3](https://github.com/zccbbg/ruoyi-fast-vue3)
- 陆陆续续收到一些打赏,为了更好的体验已用于演示服务器升级。谢谢各位小伙伴。
## CSDN若依技术专栏 ## 本框架与RuoYi的功能差异
- 常见问题https://blog.csdn.net/qq_27575627/category_12336113.html
- 后端技术https://blog.csdn.net/qq_27575627/category_12331868.html
- 前端技术https://blog.csdn.net/qq_27575627/category_12331867.html
- 运维https://blog.csdn.net/qq_27575627/category_12332546.html
## B站视频介绍 | 功能 | 本框架 | RuoYi |
https://www.bilibili.com/video/BV1ys4y1q7uG |-------------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| 前端项目 | 基于vue3-element-admin开源项目重写<br/>Vue3 + TS + ElementPlus | 基于Vue2/Vue3 + JS |
| 后端项目结构 | 采用插件化 + 扩展包形式 结构解耦 易于扩展 | 模块相互注入耦合严重难以扩展 |
| 后端代码风格 | 严格遵守Alibaba规范与项目统一配置的代码格式化 | 代码书写与常规结构不同阅读障碍大 |
| Web容器 | 采用 Undertow 基于 XNIO 的高性能容器 | 采用 Tomcat |
| 权限认证 | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展 | Spring Security 配置繁琐扩展性极差 |
| 权限注解 | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验<br/>角色与权限校验支持多种条件 如 `AND` `OR``权限 OR 角色` 等复杂表达式 | 只支持是否存在匹配 |
| 关系数据库支持 | 原生支持 MySQL、Oracle、PostgreSQL、SQLServer<br/>可同时使用异构切换 | 支持 Mysql、Oracle 不支持同时使用、不支持异构切换 |
| 缓存数据库 | 支持 Redis 5-7 支持大部分新功能特性 如 分布式限流、分布式队列 | Redis 简单 get set 支持 |
| Redis客户端 | 采用 Redisson Redis官方推荐 基于Netty的客户端工具<br/>支持Redis 90%以上的命令 底层优化规避很多不正确的用法 例如: keys被转换为scan<br/>支持单机、哨兵、单主集群、多主集群等模式 | Lettuce + RedisTemplate 支持模式少 工具使用繁琐<br/>连接池采用 common-pool Bug多经常性出问题 |
| 缓存注解 | 采用 Spring-Cache 注解 对其扩展了实现支持了更多功能<br/>例如 过期时间 最大空闲时间 组最大长度等 只需一个注解即可完成数据自动缓存 | 需手动编写Redis代码逻辑 |
| ORM框架 | 采用 Mybatis-Plus 基于对象几乎不用写SQL全java操作 功能强大插件众多<br/>例如多租户插件 分页插件 乐观锁插件等等 | 采用 Mybatis 基于XML需要手写SQL |
| SQL监控 | 采用 p6spy 可输出完整SQL与执行时间监控 | log输出 需手动拼接sql与参数无法快速查看调试问题 |
| 数据分页 | 采用 Mybatis-Plus 分页插件<br/>框架对其进行了扩展 对象化分页对象 支持多种方式传参 支持前端多排序 复杂排序 | 采用 PageHelper 仅支持单查询分页 参数只能从param传 只能单排序 功能扩展性差 体验不好 |
| 数据权限 | 采用 Mybatis-Plus 插件 自行分析拼接SQL 无感式过滤<br/>只需为Mapper设置好注解条件 支持多种自定义 不限于部门角色 | 采用 注解+aop 实现 基于部门角色 生成的sql兼容性差 不支持其他业务扩展<br/>生成sql后需手动拼接到具体业务sql上 对于多个Mapper查询不起作用 |
| 数据脱敏 | 采用 注解 + jackson 序列化期间脱敏 支持不同模块不同的脱敏条件<br/>支持多种策略 如身份证、手机号、地址、邮箱、银行卡等 可自行扩展 | 无 |
| 数据加解密 | 采用 注解 + mybatis 拦截器 对存取数据期间自动加解密<br/>支持多种策略 如BASE64、AES、RSA、SM2、SM4等 | 无 |
| 数据翻译 | 采用 注解 + jackson 序列化期间动态修改数据 数据进行翻译<br/>支持多种模式: `映射翻译` `直接翻译` `其他扩展条件翻译` 接口化两步即可完成自定义扩展 内置多种翻译实现 | 无 |
| 多数据源框架 | 采用 dynamic-datasource 支持世面大部分数据库<br/>通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源<br/>支持spel表达式从请求头参数等条件切换数据源 | 基于 druid 手动编写代码配置数据源 配置繁琐 支持性差 |
| 多数据源事务 | 采用 dynamic-datasource 支持多数据源不同种类的数据库事务回滚 | 不支持 |
| 数据库连接池 | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下 | 采用 druid bug众多 社区维护差 活跃度低 配置众多繁琐性能一般 |
| 数据库主键 | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁 | 采用 数据库自增ID 支持数据量有限 不支持多数据源主键唯一 |
| 序列化 | 采用 Jackson Spring官方内置序列化 靠谱!!! | 采用 fastjson bugjson 远近闻名 |
| 分布式幂等 | 参考美团GTIS防重系统简化实现(细节可看文档) | 手动编写注解基于aop实现 |
| 分布式任务调度 | 采用 Xxl-Job 天生支持分布式 统一的管理中心 | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造 |
| 文件存储 | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储 | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应 |
| 云存储 | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家 | 不支持 |
| 短信 | 采用 sms4j 短信融合包 支持数十种短信厂家 只需在yml配置好厂家密钥即可使用 可多厂家共用 | 不支持 |
| 邮件 | 采用 mail-api 通用协议支持大部分邮件厂商 | 不支持 |
| 接口文档 | 采用 SpringDoc、javadoc 无注解零入侵基于java注释<br/>只需把注释写好 无需再写一大堆的文档注解了 | 采用 Springfox 已停止维护 需要编写大量的注解来支持文档生成 |
| 校验框架 | 采用 Validation 支持注解与工具类校验 注解支持国际化 | 仅支持注解 且注解不支持国际化 |
| Excel框架 | 采用 Alibaba EasyExcel 基于插件化<br/>框架对其增加了很多功能 例如 自动合并相同内容 自动排列布局 字典翻译等 | 基于 POI 手写实现 功能有限 复杂 扩展性差 |
| 工具类框架 | 采用 Hutool、Lombok 上百种工具覆盖90%的使用需求 基于注解自动生成 get set 等简化框架大量代码 | 手写工具稳定性差易出问题 工具数量有限 代码臃肿需自己手写 get set 等 |
| 监控框架 | 采用 SpringBoot-Admin 基于SpringBoot官方 actuator 探针机制<br/>实时监控服务状态 框架还为其扩展了在线日志查看监控 | 无 |
| 链路追踪 | 采用 Apache SkyWalking 还在为请求不知道去哪了 到哪出了问题而烦恼吗<br/>用了它即可实时查看请求经过的每一处每一个节点 | 无 |
| 代码生成器 | 只需设计好表结构 一键生成所有crud代码与页面<br/>降低80%的开发量 把精力都投入到业务设计上<br/>框架为其适配MP、SpringDoc规范化代码 同时支持动态多数据源代码生成 | 代码生成原生结构 只支持单数据源生成 |
| 项目路径修改 | 提供详细的修改方案文档 并为其做了一些改动 非常简单即可修改成自己想要的 | 需要做很多改造 文档说明有限 |
| 国际化 | 基于请求头动态返回不同语种的文本内容 开发难度低 有对应的工具类 支持大部分注解内容国际化 | 只提供基础功能 其他需自行编写扩展 |
| 代码单例测试 | 提供单例测试 使用方式编写方法与maven多环境单测插件 | 只提供基础功能 其他需自行编写扩展 |
| Demo案例 | 提供框架功能的实际使用案例 单独一个模块提供了很多很全 | 无 |
## 若依框架视频介绍
对若依框架不了解不知道怎么部署、修改密码等操作的请参考https://www.bilibili.com/video/BV1Fi4y1q74p/
## 本地运行文档 ## 本框架与RuoYi的业务差异
https://docs.ichengle.top/wms/open/run.html
## 系统部署文档
https://docs.ichengle.top/wms/open/ops.html
## 若依wms功能 | 业务 | 功能说明 | 本框架 | RuoYi |
1. 首页:库存预警与到期提醒、基础数据报表展示 |--------|-----------------------------------------|-----|------------------|
2. 仓库/库区:管理维护仓库基础数据 | 用户管理 | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等 | 支持 | 支持 |
3. 物料:管理维护物料基础数据 | 部门管理 | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限 | 支持 | 支持 |
4. 客户/供应商/承运商:管理维护联系人基础数据 | 岗位管理 | 配置系统用户所属担任职务 | 支持 | 支持 |
5. 入库创建入库单后包括如下几个状态未发货、在途已发货未入库、部分入库、作废、入库完成入库类型包括采购入库、外协入库、退货入库入库单支持lodop和网页打印 | 菜单管理 | 配置系统菜单、操作权限、按钮权限标识等 | 支持 | 支持 |
6. 出库创建出库单后包括如下几个状态未发货、部分发货、已发货、作废入库类型包括销售出库、外协出库、调拨出库出库单支持lodop和网页打印 | 角色管理 | 角色菜单权限分配、设置角色按机构进行数据范围权限划分 | 支持 | 支持 |
7. 移库:创建移库单后包括如下几个状态:未操作、部分移动、操作完毕、作废 | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | 支持 | 支持 |
8. 库存看板:查看当前物料库存数量 | 参数管理 | 对系统动态配置常用参数 | 支持 | 支持 |
9. 库存记录:查看当前物料库存操作记录 | 通知公告 | 系统通知公告信息发布维护 | 支持 | 支持 |
10. 库存盘点:已完成 | 操作日志 | 系统正常操作日志记录和查询 系统异常信息日志记录和查询 | 支持 | 支持 |
11. 库存月结:已完成 | 登录日志 | 系统登录日志记录查询包含登录异常 | 支持 | 支持 |
12. 各类报表: 已完成 | 文件管理 | 系统文件展示、上传、下载、删除等管理 | 支持 | 无 |
## 状态流转 | 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理 | 支持 | 无 |
#### 入库状态流转 | 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作 | 支持 | 支持 |
![入库状态流转](https://oscimg.oschina.net/oscnet/up-6bdb5ad6d8ab236f763300b71cf175d9a99.jpg) | 定时任务 | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等 | 支持 | 仅支持任务与日志管理 |
#### 出库状态流转 | 代码生成 | 多数据源前后端代码的生成java、html、xml、sql支持CRUD下载 | 支持 | 仅支持单数据源 |
![出库状态流转](https://oscimg.oschina.net/oscnet/up-55cad3f077f914e357efeaae0b3feecf942.jpg) | 系统接口 | 根据业务代码自动生成相关的api接口文档 | 支持 | 支持 |
| 服务监控 | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等 | 支持 | 仅支持单机CPU、内存、磁盘监控 |
| 缓存监控 | 对系统的缓存信息查询,命令统计等。 | 支持 | 支持 |
| 在线构建器 | 拖动表单元素生成相应的HTML代码。 | 支持 | 支持 |
| 使用案例 | 系统的一些功能案例 | 支持 | 不支持 |
## 演示图 ## 贡献代码
![首页](https://oscimg.oschina.net/oscnet/up-89f751967b4145f7da92e23536bf231fbe8.jpg)
![支持两种打印方式](https://oscimg.oschina.net/oscnet/up-6daf90ef19571c7f0e7641ae59c403d8272.jpg)
![lodop打印](https://oscimg.oschina.net/oscnet/up-146d2105ae31a27e497323ad19f8bd0d7bd.jpg)
![网页打印](https://oscimg.oschina.net/oscnet/up-5664440042861199d1f3e60928e0700a9ce.jpg)
![仓库列表](https://oscimg.oschina.net/oscnet/up-a00eb79bee48e481249a12cb5e6c476aaa3.jpg)
![库存看板](https://oscimg.oschina.net/oscnet/up-78990915dfba902384ed4b09e3dc0f0fe05.jpg)
## 大厂、外企内推 欢迎各路英雄豪杰 `PR` 代码 请提交到 `dev` 开发分支 统一测试发版
关注“编写美好前程”公众号:每月记录一篇编程、创业、生活中踩坑的文章,陆续会开放一些微软、阿里、京东、拼多多等大厂或外企的内推岗位!
## 加群/技术支持
| 公众号 |
|:------------------------------------------:|
| <img src="doc/datacall.jpg" width="200px"> |
扫公众号二维码,回复:“加群”或“支持”

12
UpdateHistory.md Normal file
View file

@ -0,0 +1,12 @@
## 230627
1. 删除 snail-job monitor-admin ruoyi-extend 基本用不到
2. 优化 获取aop代理的方式 减少与其他使用aop的功能冲突的概率
## 230620
1. 完成重构 common, framework 包结构, 参照 cloud 版本拆分子模块 ;
update 更新模块包名 ;
2. 使用 jdk17 语法优化代码
3. mapstruct-plus 接入替换 BeanUtil ,用于实体类转换 ; 原先BeanUtil 对jdk17实体类转换会出错。
## 230613
1.删除vue代码vue相关代码重新建项目。

View file

@ -1,12 +0,0 @@
@echo off
echo.
echo [信息] 清理工程target生成路径。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean
pause

View file

@ -1,12 +0,0 @@
@echo off
echo.
echo [信息] 打包Web工程生成war/jar包文件。
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package -Dmaven.test.skip=true
pause

View file

@ -1,14 +0,0 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Web工程。
echo.
cd %~dp0
cd ../ruoyi-admin/target
set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -jar %JAVA_OPTS% ruoyi-admin.jar
cd bin
pause

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

577
pom.xml
View file

@ -5,208 +5,127 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi-fast-service</artifactId>
<version>3.7.0</version> <version>${revision}</version>
<name>ruoyi</name> <name>ruoyi-fast-service</name>
<url>https://gitee.com/zccbbg/ruoyi-fast-service</url>
<description>ruoyi-fast-service后台管理系统</description>
<properties> <properties>
<ruoyi.version>3.7.0</ruoyi.version> <revision>5.2.0</revision>
<spring-boot.version>3.2.6</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>17</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version> <mybatis.version>3.5.16</mybatis.version>
<druid.version>1.2.6</druid.version> <mybatis-plus.version>3.5.6</mybatis-plus.version>
<bitwalker.version>1.21</bitwalker.version> <springdoc.version>2.5.0</springdoc.version>
<swagger.version>3.0.0</swagger.version> <therapi-javadoc.version>0.15.0</therapi-javadoc.version>
<kaptcha.version>2.3.2</kaptcha.version> <poi.version>5.2.3</poi.version>
<mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version> <easyexcel.version>3.3.4</easyexcel.version>
<pagehelper.boot.version>1.3.1</pagehelper.boot.version> <velocity.version>2.3</velocity.version>
<fastjson.version>1.2.78</fastjson.version> <satoken.version>1.37.0</satoken.version>
<oshi.version>5.8.0</oshi.version> <p6spy.version>3.9.1</p6spy.version>
<jna.version>5.8.0</jna.version> <hutool.version>5.8.27</hutool.version>
<commons.io.version>2.11.0</commons.io.version> <okhttp.version>4.10.0</okhttp.version>
<commons.fileupload.version>1.4</commons.fileupload.version> <spring-boot-admin.version>3.2.3</spring-boot-admin.version>
<commons.collections.version>3.2.2</commons.collections.version> <redisson.version>3.29.0</redisson.version>
<poi.version>4.1.2</poi.version> <lock4j.version>2.2.7</lock4j.version>
<velocity.version>1.7</velocity.version> <dynamic-ds.version>4.3.0</dynamic-ds.version>
<jwt.version>0.9.1</jwt.version> <alibaba-ttl.version>2.14.2</alibaba-ttl.version>
<lombok.version>1.16.20</lombok.version> <mapstruct-plus.version>1.3.6</mapstruct-plus.version>
<mybatis.plus.version>3.3.2</mybatis.plus.version> <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
<lombok.version>1.18.32</lombok.version>
<lombok.version>1.18.30</lombok.version>
<bouncycastle.version>1.72</bouncycastle.version>
<!-- 离线IP地址定位库 -->
<ip2region.version>2.7.0</ip2region.version>
<!-- OSS 配置 -->
<aws-java-sdk-s3.version>1.12.540</aws-java-sdk-s3.version>
<!-- SMS 配置 -->
<sms4j.version>2.2.0</sms4j.version>
<!-- 插件版本 -->
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
<maven-war-plugin.version>3.2.2</maven-war-plugin.version>
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
<maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version>
<flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version>
</properties> </properties>
<profiles>
<profile>
<id>local</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>local</profiles.active>
<logging.level>info</logging.level>
</properties>
</profile>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
<logging.level>info</logging.level>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
<logging.level>warn</logging.level>
</properties>
</profile>
</profiles>
<!-- 依赖声明 --> <!-- 依赖声明 -->
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<!-- SpringBoot的依赖配置--> <!-- common 的依赖配置-->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>com.ruoyi</groupId>
<artifactId>spring-boot-dependencies</artifactId> <artifactId>ruoyi-common-bom</artifactId>
<version>2.2.13.RELEASE</version> <version>${revision}</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- 阿里数据库连接池 --> <!-- SpringBoot的依赖配置-->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>druid-spring-boot-starter</artifactId> <artifactId>spring-boot-dependencies</artifactId>
<version>${druid.version}</version> <version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency> </dependency>
<!-- 解析客户端操作系统、浏览器等 --> <!-- hutool 的依赖配置-->
<dependency> <dependency>
<groupId>eu.bitwalker</groupId> <groupId>cn.hutool</groupId>
<artifactId>UserAgentUtils</artifactId> <artifactId>hutool-bom</artifactId>
<version>${bitwalker.version}</version> <version>${hutool.version}</version>
</dependency> <type>pom</type>
<scope>import</scope>
<!-- SpringBoot集成mybatis框架 -->
<!--<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>-->
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.version}</version>
</dependency>
<!-- 获取系统信息 -->
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>${oshi.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.java.dev.jna</groupId> <groupId>org.springdoc</groupId>
<artifactId>jna</artifactId> <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>${jna.version}</version> <version>${springdoc.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.java.dev.jna</groupId> <groupId>com.github.therapi</groupId>
<artifactId>jna-platform</artifactId> <artifactId>therapi-runtime-javadoc</artifactId>
<version>${jna.version}</version> <version>${therapi-javadoc.version}</version>
</dependency>
<!-- Swagger3依赖 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${swagger.version}</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
<exclusion>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.io.version}</version>
</dependency>
<!-- 文件上传工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons.fileupload.version}</version>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<!-- velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
<version>${velocity.version}</version>
<exclusions>
<exclusion>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- collections工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons.collections.version}</version>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.penggle</groupId>
<artifactId>kaptcha</artifactId>
<version>${kaptcha.version}</version>
</dependency>
<!-- 定时任务-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 核心模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${ruoyi.version}</version>
</dependency> </dependency>
<dependency> <dependency>
@ -214,86 +133,310 @@
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>${lombok.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>org.apache.poi</groupId>
<artifactId>hutool-all</artifactId> <artifactId>poi</artifactId>
<version>5.7.13</version> <version>${poi.version}</version>
</dependency> </dependency>
<!-- 代码转换产生器 -->
<dependency> <dependency>
<groupId>org.mapstruct</groupId> <groupId>org.apache.poi</groupId>
<artifactId>mapstruct</artifactId> <artifactId>poi-ooxml</artifactId>
<version>1.4.2.Final</version> <version>${poi.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- velocity代码生成使用模板 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
<version>${satoken.version}</version>
<exclusions>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-core</artifactId>
<version>${satoken.version}</version>
</dependency>
<!-- dynamic-datasource 多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>${dynamic-ds.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- sql性能分析插件 -->
<dependency>
<groupId>p6spy</groupId>
<artifactId>p6spy</artifactId>
<version>${p6spy.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>${aws-java-sdk-s3.version}</version>
</dependency>
<!--短信sms4j-->
<dependency>
<groupId>org.dromara.sms4j</groupId>
<artifactId>sms4j-spring-boot-starter</artifactId>
<version>${sms4j.version}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
<exclusions>
<exclusion>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-30</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
<version>${lock4j.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${alibaba-ttl.version}</version>
</dependency>
<!-- 离线IP地址定位库 ip2region -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>${ip2region.version}</version>
</dependency>
<!-- 加密包引入 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>${bouncycastle.version}</version>
</dependency>
<!-- 代码生成-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId>
<version>${revision}</version>
</dependency>
<!-- 系统模块-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-system</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>${mapstruct-plus.version}</version>
</dependency>
<!-- demo模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-demo</artifactId>
<version>${revision}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<modules> <modules>
<module>ruoyi-admin</module> <module>ruoyi-admin</module>
<module>wms</module>
<module>ruoyi-framework</module>
<module>ruoyi-system</module>
<module>ruoyi-quartz</module>
<module>ruoyi-generator</module>
<module>ruoyi-common</module> <module>ruoyi-common</module>
<module>ruoyi-modules</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
</dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version> <version>${maven-compiler-plugin.verison}</version>
<configuration> <configuration>
<source>${java.version}</source> <source>${java.version}</source>
<target>${java.version}</target> <target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding> <encoding>${project.build.sourceEncoding}</encoding>
<annotationProcessorPaths> <annotationProcessorPaths>
<path> <path>
<groupId>org.mapstruct</groupId> <groupId>com.github.therapi</groupId>
<artifactId>mapstruct-processor</artifactId> <artifactId>therapi-runtime-javadoc-scribe</artifactId>
<version>1.4.2.Final</version> <version>${therapi-javadoc.version}</version>
</path> </path>
<path> <path>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>1.18.4</version> <version>${lombok.version}</version>
</path>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot.version}</version>
</path>
<path>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-processor</artifactId>
<version>${mapstruct-plus.version}</version>
</path> </path>
<path> <path>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId> <artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version> <version>${mapstruct-plus.lombok.version}</version>
</path> </path>
</annotationProcessorPaths> </annotationProcessorPaths>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration> </configuration>
</plugin> </plugin>
<!-- 单元测试使用 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<argLine>-Dfile.encoding=UTF-8</argLine>
<!-- 根据打包环境执行对应的@Tag测试方法 -->
<groups>${profiles.active}</groups>
<!-- 排除标签 -->
<excludedGroups>exclude</excludedGroups>
</configuration>
</plugin>
<!-- 统一版本号管理 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins> </plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 关闭过滤 -->
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<!-- 引入所有 匹配文件进行过滤 -->
<includes>
<include>application*</include>
<include>bootstrap*</include>
<include>banner*</include>
</includes>
<!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
<filtering>true</filtering>
</resource>
</resources>
</build> </build>
<repositories> <repositories>
<repository> <repository>
<id>public</id> <id>public</id>
<name>aliyun nexus</name> <name>huawei nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> <url>https://mirrors.huaweicloud.com/repository/maven/</url>
<releases> <releases>
<enabled>true</enabled> <enabled>true</enabled>
</releases> </releases>
@ -303,8 +446,8 @@
<pluginRepositories> <pluginRepositories>
<pluginRepository> <pluginRepository>
<id>public</id> <id>public</id>
<name>aliyun nexus</name> <name>huawei nexus</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url> <url>https://mirrors.huaweicloud.com/repository/maven/</url>
<releases> <releases>
<enabled>true</enabled> <enabled>true</enabled>
</releases> </releases>
@ -315,3 +458,5 @@
</pluginRepositories> </pluginRepositories>
</project> </project>

23
ruoyi-admin/Dockerfile Normal file
View file

@ -0,0 +1,23 @@
FROM anapsix/alpine-java:8_server-jre_unlimited
MAINTAINER Lion Li
RUN mkdir -p /ruoyi/server/logs \
/ruoyi/server/temp \
/ruoyi/skywalking/agent
WORKDIR /ruoyi/server
ENV SERVER_PORT=8080
EXPOSE ${SERVER_PORT}
ADD ./target/ruoyi-admin.jar ./app.jar
ENTRYPOINT ["java", \
"-Djava.security.egd=file:/dev/./urandom", \
"-Dserver.port=${SERVER_PORT}", \
# 应用名称 如果想区分集群节点监控 改成不同的名称即可
# "-Dskywalking.agent.service_name=ruoyi-server", \
# "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \
"-jar", "app.jar"]

View file

@ -3,9 +3,9 @@
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">
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi-fast-service</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.7.0</version> <version>${revision}</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>
@ -17,91 +17,93 @@
<dependencies> <dependencies>
<!-- spring-boot-devtools 在部分情况可能导致 类型异常或者 linkerror --> <!-- spring-boot-devtools -->
<!--<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId> <artifactId>spring-boot-devtools</artifactId>
<optional>true</optional> &lt;!&ndash; 表示依赖不会传递 &ndash;&gt; <optional>true</optional> <!-- 表示依赖不会传递 -->
</dependency>-->
<!-- swagger3-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
</dependency> </dependency>
<!-- 防止进入swagger页面报类型转换错误排除3.0.0中的引用手动增加1.6.2版本 --> <!-- Mysql驱动包 -->
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>com.mysql</groupId>
<artifactId>swagger-models</artifactId> <artifactId>mysql-connector-j</artifactId>
<version>1.6.2</version> </dependency>
<!-- Oracle -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
</dependency>
<!-- PostgreSql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!-- SqlServer -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency> </dependency>
<!-- Mysql驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 核心模块-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId> <artifactId>ruoyi-system</artifactId>
<version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 定时任务-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-quartz</artifactId> <artifactId>ruoyi-common-oss</artifactId>
<version>${ruoyi.version}</version> </dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-mail</artifactId>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-ratelimiter</artifactId>
</dependency> </dependency>
<!-- 代码生成--> <!-- 代码生成-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-generator</artifactId> <artifactId>ruoyi-generator</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>wms</artifactId>
<version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- demo模块 -->
<dependency> <dependency>
<groupId>org.junit.vintage</groupId> <groupId>com.ruoyi</groupId>
<artifactId>junit-vintage-engine</artifactId> <artifactId>ruoyi-demo</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<version>2.5.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.h2database</groupId> <!-- skywalking 整合 logback -->
<artifactId>h2</artifactId> <!-- <dependency>-->
<scope>test</scope> <!-- <groupId>org.apache.skywalking</groupId>-->
</dependency> <!-- <artifactId>apm-toolkit-logback-1.x</artifactId>-->
<!-- 代码转换产生器 --> <!-- <version>${与你的agent探针版本保持一致}</version>-->
<dependency> <!-- </dependency>-->
<groupId>org.mapstruct</groupId> <!-- <dependency>-->
<artifactId>mapstruct</artifactId> <!-- <groupId>org.apache.skywalking</groupId>-->
<version>1.4.2.Final</version> <!-- <artifactId>apm-toolkit-trace</artifactId>-->
</dependency> <!-- <version>${与你的agent探针版本保持一致}</version>-->
<!-- </dependency>-->
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.1.RELEASE</version> <version>${spring-boot.version}</version>
<configuration>
<fork>true</fork> <!-- 如果没有该配置devtools不会生效 -->
</configuration>
<executions> <executions>
<execution> <execution>
<goals> <goals>
@ -110,17 +112,21 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId> <artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version> <version>${maven-jar-plugin.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
<configuration> <configuration>
<failOnMissingWebXml>false</failOnMissingWebXml> <failOnMissingWebXml>false</failOnMissingWebXml>
<warName>${project.artifactId}</warName> <warName>${project.artifactId}</warName>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
<finalName>${project.artifactId}</finalName>
</build> </build>
</project> </project>

View file

@ -2,30 +2,23 @@ package com.ruoyi;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
/** /**
* 启动程序 * 启动程序
* *
* @author ruoyi * @author ruoyi
*/ */
@SpringBootApplication(
exclude = {DataSourceAutoConfiguration.class}, @SpringBootApplication
scanBasePackages = {"com.ruoyi", "com.cyl"}
)
public class RuoYiApplication { public class RuoYiApplication {
public static void main(String[] args) { public static void main(String[] args) {
// System.setProperty("spring.devtools.restart.enabled", "false"); System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args); SpringApplication application = new SpringApplication(RuoYiApplication.class);
System.out.println("(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙ \n" + application.setApplicationStartup(new BufferingApplicationStartup(2048));
" .-------. ____ __ \n" + application.run(args);
" | _ _ \\ \\ \\ / / \n" + System.out.println("(♥◠‿◠)ノ゙ RuoYi-Vue-Plus启动成功 ლ(´ڡ`ლ)゙");
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
} }
} }

View file

@ -5,14 +5,14 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
/** /**
* web容器中进行部署 * web容器中进行部署
* *
* @author ruoyi * @author ruoyi
*/ */
public class RuoYiServletInitializer extends SpringBootServletInitializer public class RuoYiServletInitializer extends SpringBootServletInitializer {
{
@Override @Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
{
return application.sources(RuoYiApplication.class); return application.sources(RuoYiApplication.class);
} }
} }

View file

@ -1,96 +0,0 @@
package com.ruoyi.web.controller.common;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;
/**
* 验证码操作处理
*
* @author ruoyi
*/
@RestController
public class CaptchaController
{
@Resource(name = "captchaProducer")
private Producer captchaProducer;
@Resource(name = "captchaProducerMath")
private Producer captchaProducerMath;
@Autowired
private RedisCache redisCache;
// 验证码类型
@Value("${ruoyi.captchaType}")
private String captchaType;
@Autowired
private ISysConfigService configService;
/**
* 生成验证码
*/
@GetMapping("/captchaImage")
public AjaxResult getCode(HttpServletResponse response) throws IOException
{
AjaxResult ajax = AjaxResult.success();
boolean captchaOnOff = configService.selectCaptchaOnOff();
ajax.put("captchaOnOff", captchaOnOff);
if (!captchaOnOff)
{
return ajax;
}
// 保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
String capStr = null, code = null;
BufferedImage image = null;
// 生成验证码
if ("math".equals(captchaType))
{
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
code = capText.substring(capText.lastIndexOf("@") + 1);
image = captchaProducerMath.createImage(capStr);
}
else if ("char".equals(captchaType))
{
capStr = code = captchaProducer.createText();
image = captchaProducer.createImage(capStr);
}
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
// 转换流信息写出
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
ajax.put("uuid", uuid);
ajax.put("img", Base64.encode(os.toByteArray()));
return ajax;
}
}

View file

@ -1,29 +0,0 @@
package com.ruoyi.web.controller.common;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.service.PhoneCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/code")
public class CodeController extends BaseController {
@Value("${ruoyi.traceIdName}")
private String traceIdName;
@Autowired
private PhoneCodeService phoneCodeService;
@GetMapping("/get")
public AjaxResult getCode(HttpServletRequest request, @RequestParam String phone) {
String uuid = request.getHeader(traceIdName);
boolean res = phoneCodeService.obtainCode(uuid, phone);
return AjaxResult.success(res);
}
}

View file

@ -1,120 +0,0 @@
package com.ruoyi.web.controller.common;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.framework.config.ServerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 通用请求处理
*
* @author ruoyi
*/
@RestController
public class CommonController
{
private static final Logger log = LoggerFactory.getLogger(CommonController.class);
@Autowired
private ServerConfig serverConfig;
/**
* 通用下载请求
*
* @param fileName 文件名称
* @param delete 是否删除
*/
@GetMapping("common/download")
public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
{
try
{
if (!FileUtils.checkAllowDownload(fileName))
{
throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
}
String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
String filePath = RuoYiConfig.getDownloadPath() + fileName;
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, realFileName);
FileUtils.writeBytes(filePath, response.getOutputStream());
if (delete)
{
FileUtils.deleteFile(filePath);
}
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
/**
* 通用上传请求
*/
@PostMapping("/common/upload")
public AjaxResult uploadFile(MultipartFile file) throws Exception
{
try
{
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file, MimeTypeUtils.isImg(file.getContentType()));
String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success();
ajax.put("fileName", fileName);
ajax.put("url", url);
return ajax;
}
catch (Exception e)
{
return AjaxResult.error(e.getMessage());
}
}
/**
* 本地资源通用下载
*/
@GetMapping("/common/download/resource")
public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
throws Exception
{
try
{
if (!FileUtils.checkAllowDownload(resource))
{
throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
}
// 本地资源路径
String localPath = RuoYiConfig.getProfile();
// 数据库资源地址
String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
// 下载名称
String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
FileUtils.setAttachmentResponseHeader(response, downloadName);
FileUtils.writeBytes(downloadPath, response.getOutputStream());
}
catch (Exception e)
{
log.error("下载文件失败", e);
}
}
}

View file

@ -1,53 +0,0 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
/**
* 缓存监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/cache")
public class CacheController
{
@Autowired
private RedisTemplate<String, String> redisTemplate;
@PreAuthorize("@ss.hasPermi('monitor:cache:list')")
@GetMapping()
public AjaxResult getInfo() throws Exception
{
Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
Map<String, Object> result = new HashMap<>(3);
result.put("info", info);
result.put("dbSize", dbSize);
List<Map<String, String>> pieList = new ArrayList<>();
commandStats.stringPropertyNames().forEach(key -> {
Map<String, String> data = new HashMap<>(2);
String property = commandStats.getProperty(key);
data.put("name", StringUtils.removeStart(key, "cmdstat_"));
data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
pieList.add(data);
});
result.put("commandStats", pieList);
return AjaxResult.success(result);
}
}

View file

@ -1,27 +0,0 @@
package com.ruoyi.web.controller.monitor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.domain.Server;
/**
* 服务器监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/server")
public class ServerController
{
@PreAuthorize("@ss.hasPermi('monitor:server:list')")
@GetMapping()
public AjaxResult getInfo() throws Exception
{
Server server = new Server();
server.copyTo();
return AjaxResult.success(server);
}
}

View file

@ -1,67 +0,0 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysLogininfor;
import com.ruoyi.system.service.ISysLogininforService;
/**
* 系统访问记录
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/logininfor")
public class SysLogininforController extends BaseController
{
@Autowired
private ISysLogininforService logininforService;
@PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
@GetMapping("/list")
public TableDataInfo list(SysLogininfor logininfor)
{
startPage();
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
return getDataTable(list);
}
@Log(title = "登录日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
@GetMapping("/export")
public AjaxResult export(SysLogininfor logininfor)
{
List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
return util.exportExcel(list, "登录日志");
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "登录日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{infoIds}")
public AjaxResult remove(@PathVariable Long[] infoIds)
{
return toAjax(logininforService.deleteLogininforByIds(infoIds));
}
@PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
@Log(title = "登录日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean")
public AjaxResult clean()
{
logininforService.cleanLogininfor();
return AjaxResult.success();
}
}

View file

@ -1,67 +0,0 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.service.ISysOperLogService;
/**
* 操作日志记录
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController
{
@Autowired
private ISysOperLogService operLogService;
@PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
@GetMapping("/list")
public TableDataInfo list(SysOperLog operLog)
{
startPage();
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
return getDataTable(list);
}
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
@GetMapping("/export")
public AjaxResult export(SysOperLog operLog)
{
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
return util.exportExcel(list, "操作日志");
}
@Log(title = "操作日志", businessType = BusinessType.DELETE)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/{operIds}")
public AjaxResult remove(@PathVariable Long[] operIds)
{
return toAjax(operLogService.deleteOperLogByIds(operIds));
}
@Log(title = "操作日志", businessType = BusinessType.CLEAN)
@PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
@DeleteMapping("/clean")
public AjaxResult clean()
{
operLogService.cleanOperLog();
return AjaxResult.success();
}
}

View file

@ -1,92 +0,0 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService;
/**
* 在线用户监控
*
* @author ruoyi
*/
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController
{
@Autowired
private ISysUserOnlineService userOnlineService;
@Autowired
private RedisCache redisCache;
@PreAuthorize("@ss.hasPermi('monitor:online:list')")
@GetMapping("/list")
public TableDataInfo list(String ipaddr, String userName)
{
Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
for (String key : keys)
{
LoginUser user = redisCache.getCacheObject(key);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
{
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
{
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
}
}
else if (StringUtils.isNotEmpty(ipaddr))
{
if (StringUtils.equals(ipaddr, user.getIpaddr()))
{
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
}
}
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
{
if (StringUtils.equals(userName, user.getUsername()))
{
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
}
}
else
{
userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
}
}
Collections.reverse(userOnlineList);
userOnlineList.removeAll(Collections.singleton(null));
return getDataTable(userOnlineList);
}
/**
* 强退用户
*/
@PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
@Log(title = "在线用户", businessType = BusinessType.FORCE)
@DeleteMapping("/{tokenId}")
public AjaxResult forceLogout(@PathVariable String tokenId)
{
redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
return AjaxResult.success();
}
}

View file

@ -1,135 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.annotation.RepeatSubmit;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
/**
* 参数配置 信息操作处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/config")
public class SysConfigController extends BaseController
{
@Autowired
private ISysConfigService configService;
/**
* 获取参数配置列表
*/
@PreAuthorize("@ss.hasPermi('system:config:list')")
@GetMapping("/list")
public TableDataInfo list(SysConfig config)
{
startPage();
List<SysConfig> list = configService.selectConfigList(config);
return getDataTable(list);
}
@Log(title = "参数管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:config:export')")
@GetMapping("/export")
public AjaxResult export(SysConfig config)
{
List<SysConfig> list = configService.selectConfigList(config);
ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
return util.exportExcel(list, "参数数据");
}
/**
* 根据参数编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:config:query')")
@GetMapping(value = "/{configId}")
public AjaxResult getInfo(@PathVariable Long configId)
{
return AjaxResult.success(configService.selectConfigById(configId));
}
/**
* 根据参数键名查询参数值
*/
@GetMapping(value = "/configKey/{configKey}")
public AjaxResult getConfigKey(@PathVariable String configKey)
{
return AjaxResult.success(configService.selectConfigByKey(configKey));
}
/**
* 新增参数配置
*/
@PreAuthorize("@ss.hasPermi('system:config:add')")
@Log(title = "参数管理", businessType = BusinessType.INSERT)
@PostMapping
@RepeatSubmit
public AjaxResult add(@Validated @RequestBody SysConfig config)
{
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
{
return AjaxResult.error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setCreateBy(getUserId());
return toAjax(configService.insertConfig(config));
}
/**
* 修改参数配置
*/
@PreAuthorize("@ss.hasPermi('system:config:edit')")
@Log(title = "参数管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysConfig config)
{
if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config)))
{
return AjaxResult.error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
config.setUpdateBy(getUserId());
return toAjax(configService.updateConfig(config));
}
/**
* 删除参数配置
*/
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{configIds}")
public AjaxResult remove(@PathVariable Long[] configIds)
{
configService.deleteConfigByIds(configIds);
return success();
}
/**
* 刷新参数缓存
*/
@PreAuthorize("@ss.hasPermi('system:config:remove')")
@Log(title = "参数管理", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache")
public AjaxResult refreshCache()
{
configService.resetConfigCache();
return AjaxResult.success();
}
}

View file

@ -1,163 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
/**
* 部门信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController
{
@Autowired
private ISysDeptService deptService;
/**
* 获取部门列表
*/
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list")
public AjaxResult list(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(depts);
}
/**
* 查询部门列表排除节点
*/
@PreAuthorize("@ss.hasPermi('system:dept:list')")
@GetMapping("/list/exclude/{deptId}")
public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
{
List<SysDept> depts = deptService.selectDeptList(new SysDept());
Iterator<SysDept> it = depts.iterator();
while (it.hasNext())
{
SysDept d = (SysDept) it.next();
if (d.getDeptId().intValue() == deptId
|| ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""))
{
it.remove();
}
}
return AjaxResult.success(depts);
}
/**
* 根据部门编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:dept:query')")
@GetMapping(value = "/{deptId}")
public AjaxResult getInfo(@PathVariable Long deptId)
{
deptService.checkDeptDataScope(deptId);
return AjaxResult.success(deptService.selectDeptById(deptId));
}
/**
* 获取部门下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect(SysDept dept)
{
List<SysDept> depts = deptService.selectDeptList(dept);
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
}
/**
* 加载对应角色部门列表树
*/
@GetMapping(value = "/roleDeptTreeselect/{roleId}")
public AjaxResult roleDeptTreeselect(@PathVariable("roleId") Long roleId)
{
List<SysDept> depts = deptService.selectDeptList(new SysDept());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
ajax.put("depts", deptService.buildDeptTreeSelect(depts));
return ajax;
}
/**
* 新增部门
*/
@PreAuthorize("@ss.hasPermi('system:dept:add')")
@Log(title = "部门管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDept dept)
{
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
{
return AjaxResult.error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
dept.setCreateBy(getUserId());
return toAjax(deptService.insertDept(dept));
}
/**
* 修改部门
*/
@PreAuthorize("@ss.hasPermi('system:dept:edit')")
@Log(title = "部门管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDept dept)
{
if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept)))
{
return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
else if (dept.getParentId().equals(dept.getDeptId()))
{
return AjaxResult.error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
}
else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
&& deptService.selectNormalChildrenDeptById(dept.getDeptId()) > 0)
{
return AjaxResult.error("该部门包含未停用的子部门!");
}
dept.setUpdateBy(getUserId());
return toAjax(deptService.updateDept(dept));
}
/**
* 删除部门
*/
@PreAuthorize("@ss.hasPermi('system:dept:remove')")
@Log(title = "部门管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{deptId}")
public AjaxResult remove(@PathVariable Long deptId)
{
if (deptService.hasChildByDeptId(deptId))
{
return AjaxResult.error("存在下级部门,不允许删除");
}
if (deptService.checkDeptExistUser(deptId))
{
return AjaxResult.error("部门存在用户,不允许删除");
}
return toAjax(deptService.deleteDeptById(deptId));
}
}

View file

@ -1,121 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
/**
* 数据字典信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/dict/data")
public class SysDictDataController extends BaseController
{
@Autowired
private ISysDictDataService dictDataService;
@Autowired
private ISysDictTypeService dictTypeService;
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list")
public TableDataInfo list(SysDictData dictData)
{
startPage();
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
return getDataTable(list);
}
@Log(title = "字典数据", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')")
@GetMapping("/export")
public AjaxResult export(SysDictData dictData)
{
List<SysDictData> list = dictDataService.selectDictDataList(dictData);
ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
return util.exportExcel(list, "字典数据");
}
/**
* 查询字典数据详细
*/
@PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictCode}")
public AjaxResult getInfo(@PathVariable Long dictCode)
{
return AjaxResult.success(dictDataService.selectDictDataById(dictCode));
}
/**
* 根据字典类型查询字典数据信息
*/
@GetMapping(value = "/type/{dictType}")
public AjaxResult dictType(@PathVariable String dictType)
{
List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
if (StringUtils.isNull(data))
{
data = new ArrayList<SysDictData>();
}
return AjaxResult.success(data);
}
/**
* 新增字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:add')")
@Log(title = "字典数据", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDictData dict)
{
dict.setCreateBy(getUserId());
return toAjax(dictDataService.insertDictData(dict));
}
/**
* 修改保存字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:edit')")
@Log(title = "字典数据", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictData dict)
{
dict.setUpdateBy(getUserId());
return toAjax(dictDataService.updateDictData(dict));
}
/**
* 删除字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictCodes}")
public AjaxResult remove(@PathVariable Long[] dictCodes)
{
dictDataService.deleteDictDataByIds(dictCodes);
return success();
}
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@PostMapping("/by_types")
public TableDataInfo listByTypes(@RequestBody List<String> dictTypes)
{
List<SysDictData> list = dictDataService.selectDictDataByTypes(dictTypes);
return getDataTable(list);
}
}

View file

@ -1,131 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictTypeService;
/**
* 数据字典信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/dict/type")
public class SysDictTypeController extends BaseController
{
@Autowired
private ISysDictTypeService dictTypeService;
@PreAuthorize("@ss.hasPermi('system:dict:list')")
@GetMapping("/list")
public TableDataInfo list(SysDictType dictType)
{
startPage();
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
return getDataTable(list);
}
@Log(title = "字典类型", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:dict:export')")
@GetMapping("/export")
public AjaxResult export(SysDictType dictType)
{
List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
return util.exportExcel(list, "字典类型");
}
/**
* 查询字典类型详细
*/
@PreAuthorize("@ss.hasPermi('system:dict:query')")
@GetMapping(value = "/{dictId}")
public AjaxResult getInfo(@PathVariable Long dictId)
{
return AjaxResult.success(dictTypeService.selectDictTypeById(dictId));
}
/**
* 新增字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:add')")
@Log(title = "字典类型", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDictType dict)
{
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
{
return AjaxResult.error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setCreateBy(getUserId());
return toAjax(dictTypeService.insertDictType(dict));
}
/**
* 修改字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:edit')")
@Log(title = "字典类型", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictType dict)
{
if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict)))
{
return AjaxResult.error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
dict.setUpdateBy(getUserId());
return toAjax(dictTypeService.updateDictType(dict));
}
/**
* 删除字典类型
*/
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.DELETE)
@DeleteMapping("/{dictIds}")
public AjaxResult remove(@PathVariable Long[] dictIds)
{
dictTypeService.deleteDictTypeByIds(dictIds);
return success();
}
/**
* 刷新字典缓存
*/
@PreAuthorize("@ss.hasPermi('system:dict:remove')")
@Log(title = "字典类型", businessType = BusinessType.CLEAN)
@DeleteMapping("/refreshCache")
public AjaxResult refreshCache()
{
dictTypeService.resetDictCache();
return AjaxResult.success();
}
/**
* 获取字典选择框列表
*/
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
return AjaxResult.success(dictTypes);
}
}

View file

@ -1,29 +0,0 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
/**
* 首页
*
* @author ruoyi
*/
@RestController
public class SysIndexController
{
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoyiConfig;
/**
* 访问首页提示语
*/
@RequestMapping("/")
public String index()
{
return StringUtils.format("欢迎使用{}后台管理框架当前版本v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
}
}

View file

@ -1,98 +0,0 @@
package com.ruoyi.web.controller.system;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.PhoneLoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.service.ISysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Set;
/**
* 登录验证
*
* @author ruoyi
*/
@RestController
public class SysLoginController {
@Autowired
private SysLoginService loginService;
@Autowired
private ISysMenuService menuService;
@Autowired
private SysPermissionService permissionService;
/**
* 登录方法
*
* @param loginBody 登录信息
* @return 结果
*/
@PostMapping("/login")
public AjaxResult login(@RequestBody LoginBody loginBody) {
AjaxResult ajax = AjaxResult.success();
// 生成令牌
String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
loginBody.getUuid());
ajax.put(Constants.TOKEN, token);
return ajax;
}
/**
* 使用手机号登陆
*
* @param loginBody 登录信息
* @return 结果
*/
@PostMapping("/login/phone")
public AjaxResult login(@RequestBody PhoneLoginBody loginBody) {
AjaxResult ajax = AjaxResult.success();
SysUser user = loginService.phoneLogin(loginBody.getPhone(), loginBody.getCode(), loginBody.getUuid());
// lcUserService.initVipUser(user);
ajax.put(Constants.TOKEN, loginService.createToken(user));
return ajax;
}
/**
* 获取用户信息
*
* @return 用户信息
*/
@GetMapping("getInfo")
public AjaxResult getInfo() {
SysUser user = SecurityUtils.getLoginUser().getUser();
// 角色集合
Set<String> roles = permissionService.getRolePermission(user);
// 权限集合
Set<String> permissions = permissionService.getMenuPermission(user);
AjaxResult ajax = AjaxResult.success();
ajax.put("user", user);
ajax.put("roles", roles);
ajax.put("permissions", permissions);
return ajax;
}
/**
* 获取路由信息
*
* @return 路由信息
*/
@GetMapping("getRouters")
public AjaxResult getRouters()
{
Long userId = SecurityUtils.getUserId();
List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
return AjaxResult.success(menuService.buildMenus(menus));
}
}

View file

@ -1,142 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
/**
* 菜单信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/menu")
public class SysMenuController extends BaseController
{
@Autowired
private ISysMenuService menuService;
/**
* 获取菜单列表
*/
@PreAuthorize("@ss.hasPermi('system:menu:list')")
@GetMapping("/list")
public AjaxResult list(SysMenu menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menus);
}
/**
* 根据菜单编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:menu:query')")
@GetMapping(value = "/{menuId}")
public AjaxResult getInfo(@PathVariable Long menuId)
{
return AjaxResult.success(menuService.selectMenuById(menuId));
}
/**
* 获取菜单下拉树列表
*/
@GetMapping("/treeselect")
public AjaxResult treeselect(SysMenu menu)
{
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
}
/**
* 加载对应角色菜单列表树
*/
@GetMapping(value = "/roleMenuTreeselect/{roleId}")
public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
{
List<SysMenu> menus = menuService.selectMenuList(getUserId());
AjaxResult ajax = AjaxResult.success();
ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
ajax.put("menus", menuService.buildMenuTreeSelect(menus));
return ajax;
}
/**
* 新增菜单
*/
@PreAuthorize("@ss.hasPermi('system:menu:add')")
@Log(title = "菜单管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysMenu menu)
{
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
{
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return AjaxResult.error("新增菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
menu.setCreateBy(getUserId());
return toAjax(menuService.insertMenu(menu));
}
/**
* 修改菜单
*/
@PreAuthorize("@ss.hasPermi('system:menu:edit')")
@Log(title = "菜单管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
{
if (UserConstants.NOT_UNIQUE.equals(menuService.checkMenuNameUnique(menu)))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败地址必须以http(s)://开头");
}
else if (menu.getMenuId().equals(menu.getParentId()))
{
return AjaxResult.error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
}
menu.setUpdateBy(getUserId());
return toAjax(menuService.updateMenu(menu));
}
/**
* 删除菜单
*/
@PreAuthorize("@ss.hasPermi('system:menu:remove')")
@Log(title = "菜单管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{menuId}")
public AjaxResult remove(@PathVariable("menuId") Long menuId)
{
if (menuService.hasChildByMenuId(menuId))
{
return AjaxResult.error("存在子菜单,不允许删除");
}
if (menuService.checkMenuExistRole(menuId))
{
return AjaxResult.error("菜单已分配,不允许删除");
}
return toAjax(menuService.deleteMenuById(menuId));
}
}

View file

@ -1,91 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeService;
/**
* 公告 信息操作处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController
{
@Autowired
private ISysNoticeService noticeService;
/**
* 获取通知公告列表
*/
@PreAuthorize("@ss.hasPermi('system:notice:list')")
@GetMapping("/list")
public TableDataInfo list(SysNotice notice)
{
startPage();
List<SysNotice> list = noticeService.selectNoticeList(notice);
return getDataTable(list);
}
/**
* 根据通知公告编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:notice:query')")
@GetMapping(value = "/{noticeId}")
public AjaxResult getInfo(@PathVariable Long noticeId)
{
return AjaxResult.success(noticeService.selectNoticeById(noticeId));
}
/**
* 新增通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:add')")
@Log(title = "通知公告", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysNotice notice)
{
notice.setCreateBy(getUserId());
return toAjax(noticeService.insertNotice(notice));
}
/**
* 修改通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:edit')")
@Log(title = "通知公告", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysNotice notice)
{
notice.setUpdateBy(getUserId());
return toAjax(noticeService.updateNotice(notice));
}
/**
* 删除通知公告
*/
@PreAuthorize("@ss.hasPermi('system:notice:remove')")
@Log(title = "通知公告", businessType = BusinessType.DELETE)
@DeleteMapping("/{noticeIds}")
public AjaxResult remove(@PathVariable Long[] noticeIds)
{
return toAjax(noticeService.deleteNoticeByIds(noticeIds));
}
}

View file

@ -1,129 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.service.ISysPostService;
/**
* 岗位信息操作处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/post")
public class SysPostController extends BaseController
{
@Autowired
private ISysPostService postService;
/**
* 获取岗位列表
*/
@PreAuthorize("@ss.hasPermi('system:post:list')")
@GetMapping("/list")
public TableDataInfo list(SysPost post)
{
startPage();
List<SysPost> list = postService.selectPostList(post);
return getDataTable(list);
}
@Log(title = "岗位管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:post:export')")
@GetMapping("/export")
public AjaxResult export(SysPost post)
{
List<SysPost> list = postService.selectPostList(post);
ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
return util.exportExcel(list, "岗位数据");
}
/**
* 根据岗位编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:post:query')")
@GetMapping(value = "/{postId}")
public AjaxResult getInfo(@PathVariable Long postId)
{
return AjaxResult.success(postService.selectPostById(postId));
}
/**
* 新增岗位
*/
@PreAuthorize("@ss.hasPermi('system:post:add')")
@Log(title = "岗位管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysPost post)
{
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
{
return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
{
return AjaxResult.error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setCreateBy(getUserId());
return toAjax(postService.insertPost(post));
}
/**
* 修改岗位
*/
@PreAuthorize("@ss.hasPermi('system:post:edit')")
@Log(title = "岗位管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysPost post)
{
if (UserConstants.NOT_UNIQUE.equals(postService.checkPostNameUnique(post)))
{
return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(postService.checkPostCodeUnique(post)))
{
return AjaxResult.error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
post.setUpdateBy(getUserId());
return toAjax(postService.updatePost(post));
}
/**
* 删除岗位
*/
@PreAuthorize("@ss.hasPermi('system:post:remove')")
@Log(title = "岗位管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{postIds}")
public AjaxResult remove(@PathVariable Long[] postIds)
{
return toAjax(postService.deletePostByIds(postIds));
}
/**
* 获取岗位选择框列表
*/
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
List<SysPost> posts = postService.selectPostAll();
return AjaxResult.success(posts);
}
}

View file

@ -1,141 +0,0 @@
package com.ruoyi.web.controller.system;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
/**
* 个人信息 业务处理
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/user/profile")
public class SysProfileController extends BaseController
{
@Autowired
private ISysUserService userService;
@Autowired
private TokenService tokenService;
/**
* 个人信息
*/
@GetMapping
public AjaxResult profile()
{
LoginUser loginUser = getLoginUser();
SysUser user = loginUser.getUser();
AjaxResult ajax = AjaxResult.success(user);
ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
return ajax;
}
/**
* 修改用户
*/
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult updateProfile(@RequestBody SysUser user)
{
if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
LoginUser loginUser = getLoginUser();
SysUser sysUser = loginUser.getUser();
user.setUserId(sysUser.getUserId());
user.setPassword(null);
if (userService.updateUserProfile(user) > 0)
{
// 更新缓存用户信息
sysUser.setNickName(user.getNickName());
sysUser.setPhonenumber(user.getPhonenumber());
sysUser.setEmail(user.getEmail());
sysUser.setSex(user.getSex());
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
}
return AjaxResult.error("修改个人信息异常,请联系管理员");
}
/**
* 重置密码
*/
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd")
public AjaxResult updatePwd(String oldPassword, String newPassword)
{
LoginUser loginUser = getLoginUser();
String userName = loginUser.getUsername();
String password = loginUser.getPassword();
if (!SecurityUtils.matchesPassword(oldPassword, password))
{
return AjaxResult.error("修改密码失败,旧密码错误");
}
if (SecurityUtils.matchesPassword(newPassword, password))
{
return AjaxResult.error("新密码不能与旧密码相同");
}
if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
{
// 更新缓存用户密码
loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
tokenService.setLoginUser(loginUser);
return AjaxResult.success();
}
return AjaxResult.error("修改密码异常,请联系管理员");
}
/**
* 头像上传
*/
@Log(title = "用户头像", businessType = BusinessType.UPDATE)
@PostMapping("/avatar")
public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException
{
if (!file.isEmpty())
{
LoginUser loginUser = getLoginUser();
String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file);
if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
{
AjaxResult ajax = AjaxResult.success();
ajax.put("imgUrl", avatar);
// 更新缓存用户头像
loginUser.getUser().setAvatar(avatar);
tokenService.setLoginUser(loginUser);
return ajax;
}
}
return AjaxResult.error("上传图片异常,请联系管理员");
}
}

View file

@ -1,38 +0,0 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.system.service.ISysConfigService;
/**
* 注册验证
*
* @author ruoyi
*/
@RestController
public class SysRegisterController extends BaseController
{
@Autowired
private SysRegisterService registerService;
@Autowired
private ISysConfigService configService;
@PostMapping("/register")
public AjaxResult register(@RequestBody RegisterBody user)
{
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
{
return error("当前系统没有开启注册功能!");
}
String msg = registerService.register(user);
return StringUtils.isEmpty(msg) ? success() : error(msg);
}
}

View file

@ -1,240 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
* 角色信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/role")
public class SysRoleController extends BaseController
{
@Autowired
private ISysRoleService roleService;
@Autowired
private TokenService tokenService;
@Autowired
private SysPermissionService permissionService;
@Autowired
private ISysUserService userService;
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/list")
public TableDataInfo list(SysRole role)
{
startPage();
List<SysRole> list = roleService.selectRoleList(role);
return getDataTable(list);
}
@Log(title = "角色管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:role:export')")
@GetMapping("/export")
public AjaxResult export(SysRole role)
{
List<SysRole> list = roleService.selectRoleList(role);
ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
return util.exportExcel(list, "角色数据");
}
/**
* 根据角色编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping(value = "/{roleId}")
public AjaxResult getInfo(@PathVariable Long roleId)
{
roleService.checkRoleDataScope(roleId);
return AjaxResult.success(roleService.selectRoleById(roleId));
}
/**
* 新增角色
*/
@PreAuthorize("@ss.hasPermi('system:role:add')")
@Log(title = "角色管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysRole role)
{
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
{
return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
{
return AjaxResult.error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setCreateBy(getUserId());
return toAjax(roleService.insertRole(role));
}
/**
* 修改保存角色
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleNameUnique(role)))
{
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (UserConstants.NOT_UNIQUE.equals(roleService.checkRoleKeyUnique(role)))
{
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
role.setUpdateBy(getUserId());
if (roleService.updateRole(role) > 0)
{
// 更新缓存用户权限
LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
tokenService.setLoginUser(loginUser);
}
return AjaxResult.success();
}
return AjaxResult.error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
}
/**
* 修改保存数据权限
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/dataScope")
public AjaxResult dataScope(@RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
return toAjax(roleService.authDataScope(role));
}
/**
* 状态修改
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
public AjaxResult changeStatus(@RequestBody SysRole role)
{
roleService.checkRoleAllowed(role);
role.setUpdateBy(getUserId());
return toAjax(roleService.updateRoleStatus(role));
}
/**
* 删除角色
*/
@PreAuthorize("@ss.hasPermi('system:role:remove')")
@Log(title = "角色管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{roleIds}")
public AjaxResult remove(@PathVariable Long[] roleIds)
{
return toAjax(roleService.deleteRoleByIds(roleIds));
}
/**
* 获取角色选择框列表
*/
@PreAuthorize("@ss.hasPermi('system:role:query')")
@GetMapping("/optionselect")
public AjaxResult optionselect()
{
return AjaxResult.success(roleService.selectRoleAll());
}
/**
* 查询已分配用户角色列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/allocatedList")
public TableDataInfo allocatedList(SysUser user)
{
startPage();
List<SysUser> list = userService.selectAllocatedList(user);
return getDataTable(list);
}
/**
* 查询未分配用户角色列表
*/
@PreAuthorize("@ss.hasPermi('system:role:list')")
@GetMapping("/authUser/unallocatedList")
public TableDataInfo unallocatedList(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUnallocatedList(user);
return getDataTable(list);
}
/**
* 取消授权用户
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancel")
public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
{
return toAjax(roleService.deleteAuthUser(userRole));
}
/**
* 批量取消授权用户
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/cancelAll")
public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
{
return toAjax(roleService.deleteAuthUsers(roleId, userIds));
}
/**
* 批量选择用户授权
*/
@PreAuthorize("@ss.hasPermi('system:role:edit')")
@Log(title = "角色管理", businessType = BusinessType.GRANT)
@PutMapping("/authUser/selectAll")
public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
{
return toAjax(roleService.insertAuthUsers(roleId, userIds));
}
}

View file

@ -1,230 +0,0 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
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.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
* 用户信息
*
* @author ruoyi
*/
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
@Autowired
private ISysUserService userService;
@Autowired
private ISysRoleService roleService;
@Autowired
private ISysPostService postService;
/**
* 获取用户列表
*/
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUserList(user);
return getDataTable(list);
}
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PreAuthorize("@ss.hasPermi('system:user:export')")
@GetMapping("/export")
public AjaxResult export(SysUser user)
{
List<SysUser> list = userService.selectUserList(user);
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
return util.exportExcel(list, "用户数据");
}
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
@PreAuthorize("@ss.hasPermi('system:user:import')")
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
List<SysUser> userList = util.importExcel(file.getInputStream());
String message = userService.importUser(userList, updateSupport, getUserId());
return AjaxResult.success(message);
}
@GetMapping("/importTemplate")
public AjaxResult importTemplate()
{
ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
return util.importTemplateExcel("用户数据");
}
/**
* 根据用户编号获取详细信息
*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping(value = { "/", "/{userId}" })
public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
{
userService.checkUserDataScope(userId);
AjaxResult ajax = AjaxResult.success();
List<SysRole> roles = roleService.selectRoleAll();
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
ajax.put("posts", postService.selectPostAll());
if (StringUtils.isNotNull(userId))
{
ajax.put(AjaxResult.DATA_TAG, userService.selectUserById(userId));
ajax.put("postIds", postService.selectPostListByUserId(userId));
ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
}
return ajax;
}
/**
* 新增用户
*/
@PreAuthorize("@ss.hasPermi('system:user:add')")
@Log(title = "用户管理", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@Validated @RequestBody SysUser user)
{
if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName())))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
}
else if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setCreateBy(getUserId());
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
return toAjax(userService.insertUser(user));
}
/**
* 修改用户
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysUser user)
{
userService.checkUserAllowed(user);
if (StringUtils.isNotEmpty(user.getPhonenumber())
&& UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
else if (StringUtils.isNotEmpty(user.getEmail())
&& UserConstants.NOT_UNIQUE.equals(userService.checkEmailUnique(user)))
{
return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
}
user.setUpdateBy(getUserId());
return toAjax(userService.updateUser(user));
}
/**
* 删除用户
*/
@PreAuthorize("@ss.hasPermi('system:user:remove')")
@Log(title = "用户管理", businessType = BusinessType.DELETE)
@DeleteMapping("/{userIds}")
public AjaxResult remove(@PathVariable Long[] userIds)
{
if (ArrayUtils.contains(userIds, getUserId()))
{
return error("当前用户不能删除");
}
return toAjax(userService.deleteUserByIds(userIds));
}
/**
* 重置密码
*/
@PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd")
public AjaxResult resetPwd(@RequestBody SysUser user)
{
userService.checkUserAllowed(user);
user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
user.setUpdateBy(getUserId());
return toAjax(userService.resetPwd(user));
}
/**
* 状态修改
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/changeStatus")
public AjaxResult changeStatus(@RequestBody SysUser user)
{
userService.checkUserAllowed(user);
user.setUpdateBy(getUserId());
return toAjax(userService.updateUserStatus(user));
}
/**
* 根据用户编号获取授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:query')")
@GetMapping("/authRole/{userId}")
public AjaxResult authRole(@PathVariable("userId") Long userId)
{
AjaxResult ajax = AjaxResult.success();
SysUser user = userService.selectUserById(userId);
List<SysRole> roles = roleService.selectRolesByUserId(userId);
ajax.put("user", user);
ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
return ajax;
}
/**
* 用户授权角色
*/
@PreAuthorize("@ss.hasPermi('system:user:edit')")
@Log(title = "用户管理", businessType = BusinessType.GRANT)
@PutMapping("/authRole")
public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
{
userService.insertUserAuth(userId, roleIds);
return success();
}
}

View file

@ -1,24 +0,0 @@
package com.ruoyi.web.controller.tool;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.ruoyi.common.core.controller.BaseController;
/**
* swagger 接口
*
* @author ruoyi
*/
@Controller
@RequestMapping("/tool/swagger")
public class SwaggerController extends BaseController
{
@PreAuthorize("@ss.hasPermi('tool:swagger:view')")
@GetMapping()
public String index()
{
return redirect("/swagger-ui.html");
}
}

View file

@ -1,170 +0,0 @@
package com.ruoyi.web.controller.tool;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* swagger 用户测试方法
*
* @author ruoyi
*/
@Api("用户信息管理")
@RestController
@RequestMapping("/test/user")
public class TestController extends BaseController
{
private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
{
users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
}
@ApiOperation("获取用户列表")
@GetMapping("/list")
public AjaxResult userList()
{
List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
return AjaxResult.success(userList);
}
@ApiOperation("获取用户详细")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", dataTypeClass = Integer.class, paramType = "path")
@GetMapping("/{userId}")
public AjaxResult getUser(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
return AjaxResult.success(users.get(userId));
}
else
{
return error("用户不存在");
}
}
@ApiOperation("新增用户")
@ApiImplicitParams({
@ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
@ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
@ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
})
@PostMapping("/save")
public AjaxResult save(UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return error("用户ID不能为空");
}
return AjaxResult.success(users.put(user.getUserId(), user));
}
@ApiOperation("更新用户")
@PutMapping("/update")
public AjaxResult update(@RequestBody UserEntity user)
{
if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
{
return error("用户ID不能为空");
}
if (users.isEmpty() || !users.containsKey(user.getUserId()))
{
return error("用户不存在");
}
users.remove(user.getUserId());
return AjaxResult.success(users.put(user.getUserId(), user));
}
@ApiOperation("删除用户信息")
@ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", dataTypeClass = Integer.class, paramType = "path")
@DeleteMapping("/{userId}")
public AjaxResult delete(@PathVariable Integer userId)
{
if (!users.isEmpty() && users.containsKey(userId))
{
users.remove(userId);
return success();
}
else
{
return error("用户不存在");
}
}
}
@ApiModel(value = "UserEntity", description = "用户实体")
class UserEntity
{
@ApiModelProperty("用户ID")
private Integer userId;
@ApiModelProperty("用户名称")
private String username;
@ApiModelProperty("用户密码")
private String password;
@ApiModelProperty("用户手机")
private String mobile;
public UserEntity()
{
}
public UserEntity(Integer userId, String username, String password, String mobile)
{
this.userId = userId;
this.username = username;
this.password = password;
this.mobile = mobile;
}
public Integer getUserId()
{
return userId;
}
public void setUserId(Integer userId)
{
this.userId = userId;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public String getMobile()
{
return mobile;
}
public void setMobile(String mobile)
{
this.mobile = mobile;
}
}

View file

@ -1,121 +0,0 @@
package com.ruoyi.web.core.config;
import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger2的接口配置
*
* @author ruoyi
*/
@Configuration
public class SwaggerConfig
{
/** 系统基础配置 */
@Autowired
private RuoYiConfig ruoyiConfig;
/** 是否开启swagger */
@Value("${swagger.enabled}")
private boolean enabled;
/** 设置请求的统一前缀 */
@Value("${swagger.pathMapping}")
private String pathMapping;
/**
* 创建API
*/
@Bean
public Docket createRestApi()
{
return new Docket(DocumentationType.OAS_30)
// 是否启用Swagger
.enable(enabled)
// 用来创建该API的基本信息展示在文档的页面中自定义展示的信息
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描所有有注解的api用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描指定包中的swagger注解
// .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
/* 设置安全模式swagger可以设置访问token */
.securitySchemes(securitySchemes())
.securityContexts(securityContexts())
.pathMapping(pathMapping);
}
/**
* 安全模式这里指定token通过Authorization头请求头传递
*/
private List<SecurityScheme> securitySchemes()
{
List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
return apiKeyList;
}
/**
* 安全上下文
*/
private List<SecurityContext> securityContexts()
{
List<SecurityContext> securityContexts = new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
.build());
return securityContexts;
}
/**
* 默认的安全上引用
*/
private List<SecurityReference> defaultAuth()
{
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences = new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}
/**
* 添加摘要信息
*/
private ApiInfo apiInfo()
{
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
// 设置标题
.title("标题wms_接口文档")
// 描述
.description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
// 作者信息
.contact(new Contact(ruoyiConfig.getName(), null, null))
// 版本
.version("版本号:" + ruoyiConfig.getVersion())
.build();
}
}

View file

@ -1 +0,0 @@
restart.include.json=/com.alibaba.fastjson.*.jar

View file

@ -0,0 +1,150 @@
--- # 数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: true
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
strict: true
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: root
password: root
# 从库数据源
slave:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username:
password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
connectionTimeout: 30000
# 校验超时时间
validationTimeout: 5000
# 空闲连接存活最大时间默认10分钟
idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000
# 多久检查一次连接的活性
keepaliveTime: 30000
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring.data:
redis:
# 地址
host: localhost
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 密码(如没有密码请注释掉)
# password:
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl: false
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 4
# Netty线程池数量
nettyThreads: 8
# 单节点配置
singleServerConfig:
# 客户端名称
clientName: ${ruoyi.name}
# 最小空闲连接数
connectionMinimumIdleSize: 8
# 连接池大小
connectionPoolSize: 32
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
--- # mail 邮件发送
mail:
enabled: false
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
sslEnable: true
# SMTP超时时长单位毫秒缺省值不超时
timeout: 0
# Socket连接超时值单位毫秒缺省值不超时
connectionTimeout: 0
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
sms:
# 阿里云 dysmsapi.aliyuncs.com
alibaba:
#请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
requestUrl: dysmsapi.aliyuncs.com
#阿里云的accessKey
accessKeyId: xxxxxxx
#阿里云的accessKeySecret
accessKeySecret: xxxxxxx
#短信签名
signature: 测试
tencent:
#请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
requestUrl: sms.tencentcloudapi.com
#腾讯云的accessKey
accessKeyId: xxxxxxx
#腾讯云的accessKeySecret
accessKeySecret: xxxxxxx
#短信签名
signature: 测试
#短信sdkAppId
sdkAppId: appid
#地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
territory: ap-guangzhou

View file

@ -1,37 +0,0 @@
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
# 主库数据源
master:
url: jdbc:mysql://localhost:3306/wms?useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=UTC&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true
username:
password:
# 从库数据源
slave:
# 从数据源开关/默认关闭
enabled: false
url:
username:
password:
statViewServlet:
# 控制台管理用户名和密码
login-username:
login-password:
# redis 配置
redis:
# 地址
host: localhost
# 端口默认为6379
port: 6379
# 数据库索引
database: 1
# 密码
password:
ruoyi:
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: C:/ruoyi/uploadPath
scheduling:
enabled: false

View file

@ -0,0 +1,153 @@
--- # 临时文件存储位置 避免临时文件被系统清理报错
spring.servlet.multipart.location: /ruoyi/server/temp
--- # 数据源配置
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
dynamic:
# 性能分析插件(有性能损耗 不建议生产环境使用)
p6spy: false
# 设置默认的数据源或者数据源组,默认值即为 master
primary: master
# 严格模式 匹配不到数据源则报错
strict: true
datasource:
# 主库数据源
master:
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username: root
password: root
# 从库数据源
slave:
lazy: true
type: ${spring.datasource.type}
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true
username:
password:
# oracle:
# type: ${spring.datasource.type}
# driverClassName: oracle.jdbc.OracleDriver
# url: jdbc:oracle:thin:@//localhost:1521/XE
# username: ROOT
# password: root
# postgres:
# type: ${spring.datasource.type}
# driverClassName: org.postgresql.Driver
# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
# username: root
# password: root
# sqlserver:
# type: ${spring.datasource.type}
# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true
# username: SA
# password: root
hikari:
# 最大连接池数量
maxPoolSize: 20
# 最小空闲线程数量
minIdle: 10
# 配置获取连接等待超时的时间
connectionTimeout: 30000
# 校验超时时间
validationTimeout: 5000
# 空闲连接存活最大时间默认10分钟
idleTimeout: 600000
# 此属性控制池中连接的最长生命周期值0表示无限生命周期默认30分钟
maxLifetime: 1800000
# 多久检查一次连接的活性
keepaliveTime: 30000
--- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉)
spring.data:
redis:
# 地址
host: localhost
# 端口默认为6379
port: 6379
# 数据库索引
database: 0
# 密码(如没有密码请注释掉)
# password:
# 连接超时时间
timeout: 10s
# 是否开启ssl
ssl: false
redisson:
# redis key前缀
keyPrefix:
# 线程池数量
threads: 16
# Netty线程池数量
nettyThreads: 32
# 单节点配置
singleServerConfig:
# 客户端名称
clientName: ${ruoyi.name}
# 最小空闲连接数
connectionMinimumIdleSize: 32
# 连接池大小
connectionPoolSize: 64
# 连接空闲超时,单位:毫秒
idleConnectionTimeout: 10000
# 命令等待超时,单位:毫秒
timeout: 3000
# 发布和订阅连接池大小
subscriptionConnectionPoolSize: 50
--- # mail 邮件发送
mail:
enabled: false
host: smtp.163.com
port: 465
# 是否需要用户名密码验证
auth: true
# 发送方遵循RFC-822标准
from: xxx@163.com
# 用户名注意如果使用foxmail邮箱此处user为qq号
user: xxx@163.com
# 密码注意某些邮箱需要为SMTP服务单独设置密码详情查看相关帮助
pass: xxxxxxxxxx
# 使用 STARTTLS安全连接STARTTLS是对纯文本通信协议的扩展。
starttlsEnable: true
# 使用SSL安全连接
sslEnable: true
# SMTP超时时长单位毫秒缺省值不超时
timeout: 0
# Socket连接超时值单位毫秒缺省值不超时
connectionTimeout: 0
--- # sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
sms:
# 阿里云 dysmsapi.aliyuncs.com
alibaba:
#请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
requestUrl: dysmsapi.aliyuncs.com
#阿里云的accessKey
accessKeyId: xxxxxxx
#阿里云的accessKeySecret
accessKeySecret: xxxxxxx
#短信签名
signature: 测试
tencent:
#请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
requestUrl: sms.tencentcloudapi.com
#腾讯云的accessKey
accessKeyId: xxxxxxx
#腾讯云的accessKeySecret
accessKeySecret: xxxxxxx
#短信签名
signature: 测试
#短信sdkAppId
sdkAppId: appid
#地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
territory: ap-guangzhou

View file

@ -1,21 +1,25 @@
# 项目相关配置 # 项目相关配置
ruoyi: ruoyi:
# 名称 # 名称
name: RuoYi name: RuoYi-Vue-Plus-Service
# 版本 # 版本
version: 3.7.0 version: ${revision}
# 版权年份 # 版权年份
copyrightYear: 2022 copyrightYear: 2023
# 实例演示开关 # 缓存懒加载
demoEnabled: true cacheLazy: false
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: C:/ruoyi/uploadPath captcha:
# 获取ip地址开关 enable: true
addressEnabled: true # 页面 <参数设置> 可开启关闭 验证码校验
# 验证码类型 math 数组计算 char 字符验证 # 验证码类型 math 数组计算 char 字符验证
captchaType: math type: MATH
# 前端请求的 跟踪 header name # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
traceIdName: x-web-trace-id category: CIRCLE
# 数字验证码位数
numberLength: 1
# 字符验证码长度
charLength: 4
# 开发环境配置 # 开发环境配置
server: server:
@ -24,28 +28,46 @@ server:
servlet: servlet:
# 应用的访问路径 # 应用的访问路径
context-path: / context-path: /
tomcat: # undertow 配置
# tomcat的URI编码 undertow:
uri-encoding: UTF-8 # HTTP post内容的最大大小。当值为-1时默认值为大小是无限的
# tomcat最大线程数默认为200 max-http-post-size: -1
max-threads: 800 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# Tomcat启动初始化的线程数默认值25 # 每块buffer的空间大小,越小的空间被利用越充分
min-spare-threads: 30 buffer-size: 512
# 是否分配的直接内存
direct-buffers: true
threads:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io: 8
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
worker: 256
# 日志配置 # 日志配置
logging: logging:
level: level:
com.ruoyi: debug com.ruoyi: @logging.level@
org.springframework: warn org.springframework: warn
config: classpath:logback-plus.xml
# 用户配置
user:
password:
# 密码最大错误次数
maxRetryCount: 5
# 密码锁定时间默认10分钟
lockTime: 10
# Spring配置 # Spring配置
spring: spring:
application:
name: ${ruoyi.name}
# 资源信息 # 资源信息
messages: messages:
# 国际化资源文件路径 # 国际化资源文件路径
basename: i18n/messages basename: i18n/messages
profiles: profiles:
active: druid active: @profiles.active@
# 文件上传 # 文件上传
servlet: servlet:
multipart: multipart:
@ -58,92 +80,156 @@ spring:
restart: restart:
# 热部署开关 # 热部署开关
enabled: true enabled: true
datasource: mvc:
type: com.alibaba.druid.pool.DruidDataSource format:
driverClassName: com.mysql.cj.jdbc.Driver date-time: yyyy-MM-dd HH:mm:ss
druid: jackson:
# 初始连接数 # 日期格式化
initialSize: 5 date-format: yyyy-MM-dd HH:mm:ss
# 最小连接池数量 serialization:
minIdle: 10 # 格式化输出
# 最大连接池数量 indent_output: false
maxActive: 20 # 忽略无法转换的对象
# 配置获取连接等待超时的时间 fail_on_empty_beans: false
maxWait: 60000 deserialization:
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 # 允许对象忽略json中不存在的属性
timeBetweenEvictionRunsMillis: 60000 fail_on_unknown_properties: false
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置白名单,不填则允许所有访问
allow:
url-pattern: /druid/*
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
# redis 配置
redis:
# 连接超时时间
timeout: 50s
lettuce:
pool:
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中的最大空闲连接
max-idle: 8
# 连接池的最大数据库连接数
max-active: 8
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
# token配置 # Sa-Token配置
token: sa-token:
# 令牌自定义标识 # token名称 (同时也是cookie名称)
header: Authorization token-name: Authorization
# 令牌密钥 # token有效期 设为一天 (必定过期) 单位: 秒
secret: abcdefghijkomnopqrstuvwxyx timeout: 86400
# 令牌有效期默认30分钟 # 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
expireTime: 30 # token最低活跃时间 (指定时间无操作就过期) 单位: 秒
# mybatis-plus 配置 active-timeout: 1800
# 允许动态设置 token 有效期
dynamic-active-timeout: true
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
is-concurrent: true
# 在多人登录同一账号时是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)
is-share: false
# 是否尝试从header里读取token
is-read-header: true
# 是否尝试从cookie里读取token
is-read-cookie: false
# token前缀
token-prefix: "Bearer"
# jwt秘钥
jwt-secret-key: abcdefghijklmnopqrstuvwxyz
# security配置
security:
# 排除路径
excludes:
# 静态资源
- /*.html
- /**/*.html
- /**/*.css
- /**/*.js
# 公共路径
- /favicon.ico
- /error
# swagger 文档配置
- /*/api-docs
- /*/api-docs/**
# actuator 监控配置
- /actuator
- /actuator/**
# MyBatisPlus配置
# https://baomidou.com/config/
mybatis-plus: mybatis-plus:
# 搜索指定包别名 # 不支持多包, 如有需要可在注解配置 或 提升扫包等级
typeAliasesPackage: com.cyl.**.domain, com.ruoyi.common.core.domain.entity, com.ruoyi.**.domain # 例如 com.**.**.mapper
# 配置mapper的扫描找到所有的mapper.xml映射文件 mapperPackage: com.ruoyi.**.mapper
# 对应的 XML 文件位置
mapperLocations: classpath*:mapper/**/*Mapper.xml mapperLocations: classpath*:mapper/**/*Mapper.xml
# 加载全局的配置文件 # 实体扫描多个package用逗号或者分号分隔
configLocation: classpath:mybatis/mybatis-config.xml typeAliasesPackage: com.ruoyi.**.domain
# 启动时是否检查 MyBatis XML 文件的存在,默认不检查
checkConfigLocation: false
configuration:
# 自动驼峰命名规则camel case映射
mapUnderscoreToCamelCase: true
# MyBatis 自动映射策略
# NONE不启用 PARTIAL只对非嵌套 resultMap 自动映射 FULL对所有 resultMap 自动映射
autoMappingBehavior: FULL
# MyBatis 自动映射时未知列或未知属性处理策
# NONE不做处理 WARNING打印相关警告 FAILING抛出异常和详细信息
autoMappingUnknownColumnBehavior: NONE
# 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
# 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl
# 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
global-config: global-config:
db-config: # 是否打印 Logo banner
id-type: auto banner: true
update-strategy: ignored dbConfig:
pagehelper: # 主键类型
helperDialect: mysql # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID
supportMethodsArguments: true idType: ASSIGN_ID
params: count=countSql # 逻辑已删除值
logicDeleteValue: 2
# 逻辑未删除值
logicNotDeleteValue: 0
# 字段验证策略之 insert,在 insert 的时候的字段验证策略
# IGNORED 忽略 NOT_NULL 非NULL NOT_EMPTY 非空 DEFAULT 默认 NEVER 不加入 SQL
insertStrategy: NOT_NULL
# 字段验证策略之 update,在 update 的时候的字段验证策略
updateStrategy: NOT_NULL
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
where-strategy: NOT_NULL
# Swagger配置 # 数据加密
swagger: mybatis-encryptor:
# 是否开启swagger # 是否开启加密
enabled: true enable: false
# 请求前缀 # 默认加密算法
pathMapping: /dev-api algorithm: BASE64
# 编码方式 BASE64/HEX。默认BASE64
encode: BASE64
# 安全秘钥 对称算法的秘钥 如AESSM4
password:
# 公私钥 非对称算法的公私钥 如SM2RSA
publicKey:
privateKey:
springdoc:
api-docs:
# 是否开启接口文档
enabled: true
# swagger-ui:
# # 持久化认证数据
# persistAuthorization: true
info:
# 标题
title: '标题:${ruoyi.name}后台管理系统_接口文档'
# 描述
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
# 版本
version: '版本号: ${revision}'
# 作者信息
contact:
name: Lion Li
email: crazylionli@163.com
url: https://gitee.com/dromara/RuoYi-Vue-Plus
components:
# 鉴权方式配置
security-schemes:
apiKey:
type: APIKEY
in: HEADER
name: ${sa-token.token-name}
#这里定义了两个分组,可定义多个,也可以不定义
group-configs:
- group: 1.演示模块
packages-to-scan: com.ruoyi.demo
- group: 2.系统模块
packages-to-scan: com.ruoyi.web
- group: 3.代码生成模块
packages-to-scan: com.ruoyi.generator
# 防止XSS攻击 # 防止XSS攻击
xss: xss:
@ -153,90 +239,31 @@ xss:
excludes: /system/notice excludes: /system/notice
# 匹配链接 # 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/* urlPatterns: /system/*,/monitor/*,/tool/*
extra:
wx: # 全局线程池相关配置
appid: wxappid thread-pool:
secret: wxsecret # 是否开启线程池
redirect: "" enabled: false
scheduling: # 队列最大长度
enabled: true queueCapacity: 128
gen: # 线程池维护线程所允许的空闲时间
# 作者 keepAliveSeconds: 300
author: zcc
# 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool --- # 分布式锁 lock4j 全局配置
packageName: com.cyl.wms lock4j:
# 自动去除表前缀默认是false # 获取分布式锁超时时间,默认为 3000 毫秒
autoRemovePre: true acquire-timeout: 3000
# 表前缀(生成类名不会包含表前缀,多个用逗号分隔) # 分布式锁的超时时间,默认为 30 秒
tablePrefix: wms_ expire: 30000
# 一级权限名
rootPermission: wms --- # Actuator 监控端点的配置项
# 模板根路径 management:
templateRootPath: vm endpoints:
# 路径 web:
path: exposure:
# 后端根目录 include: '*'
backPath: D:\java_project\wms\wms-ruoyi endpoint:
# 后端 service 模块名 health:
serviceModule: wms show-details: ALWAYS
# 后端 api 模块名, 默认与 service 一致 logfile:
apiModule: wms external-file: ./logs/sys-console.log
# 前端根目录
frontPath: D:\java_project\wms\ruoyi-wms-vue2
# 前端 api 目录
frontApiPath: src/api/wms
# 前端 view 目录
frontViewPath: src/views/wms
# sql 目录
sql: sql
# 环境变量
env:
# 审计 的 基类(创建者,创建时间,更新者,更新时间)
baseAudit: com.ruoyi.common.core.domain.BaseAudit
# 树 的 基类
baseTree: com.ruoyi.common.core.domain.TreeEntity
# 对于新增的模板,如果没有默认值,在这里进行配置
fileMap:
"api.js.vm": "${frontPath}/${frontApiPath}/${className}.js"
"controller.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/controller/${ClassName}Controller.java"
"service.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/service/${ClassName}Service.java"
"mapper.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/mapper/${ClassName}Mapper.java"
"convert.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/convert/${ClassName}Convert.java"
"example.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/pojo/example/${ClassName}Example.java"
"query.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/pojo/query/${ClassName}Query.java"
"dto.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/pojo/dto/${ClassName}DTO.java"
"vo.java.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/${packageName}/pojo/vo/${ClassName}VO.java"
"domain.java.vm": "${backPath}/${apiModule}/${MAIN_JAVA}/${packageName}/domain/${ClassName}.java"
"mapper.xml.vm": "${backPath}/${serviceModule}/${MAIN_RESOURCES}/mapper/${ClassName}Mapper.xml"
"sql.vm": "${backPath}/sql/${className}.sql"
"h2.sql.vm": "${backPath}/${serviceModule}/${MAIN_JAVA}/db/${tableName}-h2.sql"
"add.vue.vm": "${frontPath}/${frontViewPath}/Add${ClassName}.vue"
"index.vue.vm": "${frontPath}/${frontViewPath}/${className}/index.vue"
"index-tree.vue.vm": "${frontPath}/${frontViewPath}/index.vue"
"sub-domain.java.vm": "${frontPath}/${frontViewPath}/Sub${ClassName}.vue"
templates:
- vm/js/api.js.vm
- vm/java/controller.java.vm
- vm/java/service.java.vm
- vm/java/mapper.java.vm
- vm/java/convert.java.vm
- vm/java/query.java.vm
- vm/java/dto.java.vm
- vm/java/vo.java.vm
- vm/java/domain.java.vm
- vm/xml/mapper.xml.vm
- vm/sql/sql.vm
testTemplates:
# - vm/sql/h2.sql.vm
crudTemplates:
# - vm/vue/add.vue.vm
- vm/vue/index.vue.vm
treeTemplates:
# - vm/vue/index-tree.vue.vm
subTemplates:
# - vm/vue/index.vue.vm
# - vm/java/sub-domain.java.vm
type2component:
"String": "a-input("
"LocalDate": "a-date-picker("
"LocalDateTime": "a-date-picker(format=\"YYYY-MM-DD HH:mm\""

View file

@ -1,24 +1,2 @@
Application Version: ${ruoyi.version} Application Version: ${revision}
Spring Boot Version: ${spring-boot.version} Spring Boot Version: ${spring-boot.version}
////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////

View file

@ -2,32 +2,35 @@
not.null=* 必须填写 not.null=* 必须填写
user.jcaptcha.error=验证码错误 user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效 user.jcaptcha.expire=验证码已失效
user.not.exists=用户不存在/密码错误 user.not.exists=对不起, 您的账号:{0} 不存在.
user.password.not.match=用户不存在/密码错误 user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次 user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定10分钟 user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号已被删除 user.password.delete=对不起,您的账号{0} 已被删除
user.blocked=用户已封禁,请联系管理员 user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
role.blocked=角色已封禁,请联系管理员 role.blocked=角色已封禁,请联系管理员
user.logout.success=退出成功 user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间 length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.blank=用户名不能为空
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头 user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
user.password.not.blank=用户密码不能为空
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
user.password.not.valid=* 5-50个字符 user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误 user.email.not.valid=邮箱格式错误
user.email.not.blank=邮箱不能为空
user.phonenumber.not.blank=用户手机号不能为空
user.mobile.phone.number.not.valid=手机号格式错误 user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功 user.login.success=登录成功
user.register.success=注册成功 user.register.success=注册成功
user.register.save.error=保存用户 {0} 失败,注册账号已存在
user.register.error=注册失败,请联系系统管理人员
user.notfound=请重新登录 user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录 user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录 user.unknown.error=未知错误,请重新登录
##文件上传消息 ##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB
upload.filename.exceed.length=上传的文件名最长{0}个字符 upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限 ##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}] no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}] no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
@ -35,3 +38,12 @@ no.update.permission=您没有修改数据的权限,请联系管理员添加
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
repeat.submit.message=不允许重复提交,请稍候再试
rate.limiter.message=访问过于频繁,请稍候再试
sms.code.not.blank=短信验证码不能为空
sms.code.retry.limit.count=短信验证码输入错误{0}次
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
xcx.code.not.blank=小程序code不能为空

View file

@ -0,0 +1,49 @@
#错误消息
not.null=* Required fill in
user.jcaptcha.error=Captcha error
user.jcaptcha.expire=Captcha invalid
user.not.exists=Sorry, your account: {0} does not exist
user.password.not.match=User does not exist/Password error
user.password.retry.limit.count=Password input error {0} times
user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes
user.password.delete=Sorry, your account{0} has been deleted
user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator
role.blocked=Role disabledplease contact administrators
user.logout.success=Exit successful
length.not.valid=The length must be between {min} and {max} characters
user.username.not.blank=Username cannot be blank
user.username.not.valid=* 2 to 20 chinese characters, letters, numbers or underscores, and must start with a non number
user.username.length.valid=Account length must be between {min} and {max} characters
user.password.not.blank=Password cannot be empty
user.password.length.valid=Password length must be between {min} and {max} characters
user.password.not.valid=* 5-50 characters
user.email.not.valid=Mailbox format error
user.email.not.blank=Mailbox cannot be blank
user.phonenumber.not.blank=Phone number cannot be blank
user.mobile.phone.number.not.valid=Phone number format error
user.login.success=Login successful
user.register.success=Register successful
user.register.save.error=Failed to save user {0}, The registered account already exists
user.register.error=Register failed, please contact system administrator
user.notfound=Please login again
user.forcelogout=The administrator is forced to exitplease login again
user.unknown.error=Unknown error, please login again
##文件上传消息
upload.exceed.maxSize=The uploaded file size exceeds the limit file size<br/>the maximum allowed file size is{0}MB
upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters
##权限
no.permission=You do not have permission to the dataplease contact your administrator to add permissions [{0}]
no.create.permission=You do not have permission to create dataplease contact your administrator to add permissions [{0}]
no.update.permission=You do not have permission to modify dataplease contact your administrator to add permissions [{0}]
no.delete.permission=You do not have permission to delete dataplease contact your administrator to add permissions [{0}]
no.export.permission=You do not have permission to export dataplease contact your administrator to add permissions [{0}]
no.view.permission=You do not have permission to view dataplease contact your administrator to add permissions [{0}]
repeat.submit.message=Repeat submit is not allowed, please try again later
rate.limiter.message=Visit too frequently, please try again later
sms.code.not.blank=Sms code cannot be blank
sms.code.retry.limit.count=Sms code input error {0} times
sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes
email.code.not.blank=Email code cannot be blank
email.code.retry.limit.count=Email code input error {0} times
email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes
xcx.code.not.blank=Mini program code cannot be blank

View file

@ -0,0 +1,49 @@
#错误消息
not.null=* 必须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=对不起, 您的账号:{0} 不存在.
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号:{0} 已被删除
user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员
role.blocked=角色已封禁,请联系管理员
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.blank=用户名不能为空
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成且必须以非数字开头
user.username.length.valid=账户长度必须在{min}到{max}个字符之间
user.password.not.blank=用户密码不能为空
user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间
user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.email.not.blank=邮箱不能为空
user.phonenumber.not.blank=用户手机号不能为空
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.register.save.error=保存用户 {0} 失败,注册账号已存在
user.register.error=注册失败,请联系系统管理人员
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
repeat.submit.message=不允许重复提交,请稍候再试
rate.limiter.message=访问过于频繁,请稍候再试
sms.code.not.blank=短信验证码不能为空
sms.code.retry.limit.count=短信验证码输入错误{0}次
sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{1}分钟
email.code.not.blank=邮箱验证码不能为空
email.code.retry.limit.count=邮箱验证码输入错误{0}次
email.code.retry.limit.exceed=邮箱验证码输入错误{0}次,帐户锁定{1}分钟
xcx.code.not.blank=小程序code不能为空

Binary file not shown.

View file

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.path" value="./logs"/>
<property name="console.log.pattern"
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${console.log.pattern}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 控制台输出 -->
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-console.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大 1天 -->
<maxHistory>1</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
<charset>utf-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
</filter>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- info异步输出 -->
<appender name="async_info" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="file_info"/>
</appender>
<!-- error异步输出 -->
<appender name="async_error" class="ch.qos.logback.classic.AsyncAppender">
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<!-- 添加附加的appender,最多只能添加一个 -->
<appender-ref ref="file_error"/>
</appender>
<!-- 整合 skywalking 控制台输出 tid -->
<!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!-- 整合 skywalking 推送采集日志 -->
<!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">-->
<!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">-->
<!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">-->
<!-- <pattern>[%tid] ${console.log.pattern}</pattern>-->
<!-- </layout>-->
<!-- <charset>utf-8</charset>-->
<!-- </encoder>-->
<!-- </appender>-->
<!--系统操作日志-->
<root level="info">
<appender-ref ref="console" />
<appender-ref ref="async_info" />
<appender-ref ref="async_error" />
<appender-ref ref="file_console" />
<!-- <appender-ref ref="sky_log"/>-->
</root>
</configuration>

View file

@ -1,87 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="/data/logs/wms" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%thread] [%logger:%L] [%X{spanId}]: %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/wms.current.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/wms.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/wms-error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/wms-error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
</filter>
</appender>
<!-- 用户访问日志输出 -->
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<logger name="com.cyl.wms.mapper" level="debug" />
<logger name="com.cyl.demo.mapper" level="debug" />
<logger name="com.ruoyi.framework.aspectj.LoggingAspect" level="info" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file" />
<appender-ref ref="file_error" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>

View file

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true" /> <!-- 全局映射器启用缓存 -->
<setting name="useGeneratedKeys" value="true" /> <!-- 允许 JDBC 支持自动生成主键 -->
<setting name="defaultExecutorType" value="REUSE" /> <!-- 配置默认的执行器 -->
<setting name="logImpl" value="SLF4J" /> <!-- 指定 MyBatis 所用日志的具体实现 -->
<setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 驼峰式命名 -->
</settings>
</configuration>

View file

@ -0,0 +1,28 @@
# p6spy 性能分析插件配置文件
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
#deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# SQL语句打印时间格式
databaseDialectTimestampFormat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
# 是否过滤 Log
filter=true
# 过滤 Log 时所排除的 sql 关键字,以逗号分隔
exclude=SELECT 1

View file

@ -1,45 +0,0 @@
package com.fjp.lc.test.common;
import cn.hutool.core.img.Img;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
@Slf4j
public class CommonTest {
/* @Test
public void test3() throws IOException {
Long start = System.currentTimeMillis();
log.info("start {}", start);
Thumbnails.of("D:/build/tt.jpg")
.scale(1f)
.outputQuality(0.5f)
.toFile("D:/build/tt1.jpg");
log.info("end {}", System.currentTimeMillis() - start);
}*/
@Test
public void test4() throws IOException {
String f1 = "D:/build/tt.jpg";
String f2 = "D:/build/tt2.jpg";
Long start = System.currentTimeMillis();
log.info("start {}", start);
ImgUtil.scale(new File(f1), new File(f2), .1f);
log.info("end {}", System.currentTimeMillis() - start);
}
@Test
public void test5() throws IOException {
String f1 = "D:/build/tt.jpg";
String f2 = "D:/build/tt3.jpg";
Long start = System.currentTimeMillis();
log.info("start {}", start);
Img.from(FileUtil.file(f1))
.setQuality(1)//压缩比率
.write(FileUtil.file(f2));
log.info("end {}", System.currentTimeMillis() - start);
}
}

View file

@ -1,30 +0,0 @@
package com.fjp.lc.test.service;
import com.cyl.wms.service.ShipmentOrderService;
import com.ruoyi.RuoYiApplication;
import com.ruoyi.common.utils.SecurityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, classes = RuoYiApplication.class)
public class ServiceTest {
@Autowired
private ShipmentOrderService shipmentOrderService;
@Test
public void contextLoads() {
shipmentOrderService.allocatedInventory(490L,1);
}
/*
* 加密密码 重置密码 默认密码 更改密码
* */
@Test
public void encryptPassword() {
String newPwd = "admin123";
System.out.println("新密码:"+SecurityUtils.encryptPassword(newPwd));
}
}

View file

@ -0,0 +1,45 @@
package com.ruoyi.test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
/**
* 断言单元测试案例
*
* @author Lion Li
*/
@DisplayName("断言单元测试案例")
public class AssertUnitTest {
@DisplayName("测试 assertEquals 方法")
@Test
public void testAssertEquals() {
Assertions.assertEquals("666", new String("666"));
Assertions.assertNotEquals("666", new String("666"));
}
@DisplayName("测试 assertSame 方法")
@Test
public void testAssertSame() {
Object obj = new Object();
Object obj1 = obj;
Assertions.assertSame(obj, obj1);
Assertions.assertNotSame(obj, obj1);
}
@DisplayName("测试 assertTrue 方法")
@Test
public void testAssertTrue() {
Assertions.assertTrue(true);
Assertions.assertFalse(true);
}
@DisplayName("测试 assertNull 方法")
@Test
public void testAssertNull() {
Assertions.assertNull(null);
Assertions.assertNotNull(null);
}
}

View file

@ -0,0 +1,70 @@
package com.ruoyi.test;
import com.ruoyi.common.core.config.RuoYiConfig;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.TimeUnit;
/**
* 单元测试案例
*
* @author Lion Li
*/
@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件
@DisplayName("单元测试案例")
public class DemoUnitTest {
@Autowired
private RuoYiConfig ruoYiConfig;
@DisplayName("测试 @SpringBootTest @Test @DisplayName 注解")
@Test
public void testTest() {
System.out.println(ruoYiConfig);
}
@Disabled
@DisplayName("测试 @Disabled 注解")
@Test
public void testDisabled() {
System.out.println(ruoYiConfig);
}
@Timeout(value = 2L, unit = TimeUnit.SECONDS)
@DisplayName("测试 @Timeout 注解")
@Test
public void testTimeout() throws InterruptedException {
Thread.sleep(3000);
System.out.println(ruoYiConfig);
}
@DisplayName("测试 @RepeatedTest 注解")
@RepeatedTest(3)
public void testRepeatedTest() {
System.out.println(666);
}
@BeforeAll
public static void testBeforeAll() {
System.out.println("@BeforeAll ==================");
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
@AfterAll
public static void testAfterAll() {
System.out.println("@AfterAll ==================");
}
}

View file

@ -0,0 +1,72 @@
package com.ruoyi.test;
import com.ruoyi.common.core.enums.UserType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/**
* 带参数单元测试案例
*
* @author Lion Li
*/
@DisplayName("带参数单元测试案例")
public class ParamUnitTest {
@DisplayName("测试 @ValueSource 注解")
@ParameterizedTest
@ValueSource(strings = {"t1", "t2", "t3"})
public void testValueSource(String str) {
System.out.println(str);
}
@DisplayName("测试 @NullSource 注解")
@ParameterizedTest
@NullSource
public void testNullSource(String str) {
System.out.println(str);
}
@DisplayName("测试 @EnumSource 注解")
@ParameterizedTest
@EnumSource(UserType.class)
public void testEnumSource(UserType type) {
System.out.println(type.getUserType());
}
@DisplayName("测试 @MethodSource 注解")
@ParameterizedTest
@MethodSource("getParam")
public void testMethodSource(String str) {
System.out.println(str);
}
public static Stream<String> getParam() {
List<String> list = new ArrayList<>();
list.add("t1");
list.add("t2");
list.add("t3");
return list.stream();
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
}

View file

@ -0,0 +1,54 @@
package com.ruoyi.test;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 标签单元测试案例
*
* @author Lion Li
*/
@SpringBootTest
@DisplayName("标签单元测试案例")
public class TagUnitTest {
@Tag("dev")
@DisplayName("测试 @Tag dev")
@Test
public void testTagDev() {
System.out.println("dev");
}
@Tag("prod")
@DisplayName("测试 @Tag prod")
@Test
public void testTagProd() {
System.out.println("prod");
}
@Tag("local")
@DisplayName("测试 @Tag local")
@Test
public void testTagLocal() {
System.out.println("local");
}
@Tag("exclude")
@DisplayName("测试 @Tag exclude")
@Test
public void testTagExclude() {
System.out.println("exclude");
}
@BeforeEach
public void testBeforeEach() {
System.out.println("@BeforeEach ==================");
}
@AfterEach
public void testAfterEach() {
System.out.println("@AfterEach ==================");
}
}

View file

@ -3,128 +3,39 @@
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">
<parent> <parent>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi-fast-service</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.7.0</version> <version>${revision}</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<modules>
<module>ruoyi-common-bom</module>
<module>ruoyi-common-core</module>
<module>ruoyi-common-oss</module>
<module>ruoyi-common-sms</module>
<module>ruoyi-common-json</module>
<module>ruoyi-common-excel</module>
<module>ruoyi-common-redis</module>
<module>ruoyi-common-satoken</module>
<module>ruoyi-common-web</module>
<module>ruoyi-common-security</module>
<module>ruoyi-common-mybatis</module>
<module>ruoyi-common-mail</module>
<module>ruoyi-common-log</module>
<module>ruoyi-common-ratelimiter</module>
<module>ruoyi-common-translation</module>
<module>ruoyi-common-sensitive</module>
<module>ruoyi-common-encrypt</module>
<module>ruoyi-common-idempotent</module>
<module>ruoyi-common-doc</module>
</modules>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<packaging>pom</packaging>
<description> <description>
common通用工具 common 通用模块
</description> </description>
<dependencies>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- spring security 安全认证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- pagehelper 分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- JSON工具类 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- 阿里JSON解析器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<!-- io常用工具类 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!-- 文件上传工具类 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
<!-- yml解析器 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- Jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- redis 缓存操作 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- pool 对象池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- 解析客户端操作系统、浏览器等 -->
<dependency>
<groupId>eu.bitwalker</groupId>
<artifactId>UserAgentUtils</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>
</project> </project>

View file

@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-bom</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
<description>
ruoyi-common-bom common依赖项
</description>
<properties>
<revision>5.2.0</revision>
</properties>
<dependencyManagement>
<dependencies>
<!-- 核心模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId>
<version>${revision}</version>
</dependency>
<!-- OSS -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-oss</artifactId>
<version>${revision}</version>
</dependency>
<!-- 短信模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-sms</artifactId>
<version>${revision}</version>
</dependency>
<!-- 序列化模块 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-json</artifactId>
<version>${revision}</version>
</dependency>
<!-- excel -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-excel</artifactId>
<version>${revision}</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
<version>${revision}</version>
</dependency>
<!-- satoken -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-satoken</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-web</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-mybatis</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-mail</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-log</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-translation</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-ratelimiter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-encrypt</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-sensitive</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-idempotent</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-job</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-doc</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View file

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
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">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-common-core</artifactId>
<description>
ruoyi-common-core 核心模块
</description>
<dependencies>
<!-- dynamic-datasource 多数据源-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<!-- Spring框架基本的核心工具 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<!-- SpringWeb模块 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<!-- Sa-Token 权限认证, 在线文档http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
</dependency>
<!-- Sa-Token 整合 jwt -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jwt</artifactId>
</dependency>
<!-- 自定义验证注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- yml解析器 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<!-- servlet包 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-jwt</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>jakarta.mail</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 自动生成YML配置关联JSON文件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<!--redisson-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-data-27</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>lock4j-redisson-spring-boot-starter</artifactId>
</dependency>
<!-- 加密包引入 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
</dependency>
<!-- 离线IP地址定位库 -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
</dependency>
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,17 @@
package com.ruoyi.common.core.config;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.scheduling.annotation.EnableAsync;
/**
* 程序注解配置
*
* @author Lion Li
*/
@AutoConfiguration
@EnableAspectJAutoProxy
@EnableAsync(proxyTargetClass = true)
public class ApplicationConfig {
}

View file

@ -0,0 +1,50 @@
package com.ruoyi.common.core.config;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.SpringUtils;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.core.task.VirtualThreadTaskExecutor;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import java.util.Arrays;
import java.util.concurrent.Executor;
/**
* 异步配置
*
* @author Lion Li
*/
@AutoConfiguration
public class AsyncConfig implements AsyncConfigurer {
/**
* 自定义 @Async 注解使用系统线程池
*/
@Override
public Executor getAsyncExecutor() {
if(SpringUtils.isVirtual()) {
return new VirtualThreadTaskExecutor("async-");
}
return SpringUtils.getBean("scheduledExecutorService");
}
/**
* 异步执行异常处理
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (throwable, method, objects) -> {
throwable.printStackTrace();
StringBuilder sb = new StringBuilder();
sb.append("Exception message - ").append(throwable.getMessage())
.append(", Method name - ").append(method.getName());
if (ArrayUtil.isNotEmpty(objects)) {
sb.append(", Parameter value - ").append(Arrays.toString(objects));
}
throw new ServiceException(sb.toString());
};
}
}

View file

@ -0,0 +1,38 @@
package com.ruoyi.common.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 读取项目相关配置
*
* @author Lion Li
*/
@Data
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig {
/**
* 项目名称
*/
private String name;
/**
* 版本
*/
private String version;
/**
* 版权年份
*/
private String copyrightYear;
/**
* 缓存懒加载
*/
private boolean cacheLazy;
}

View file

@ -0,0 +1,78 @@
package com.ruoyi.common.core.config;
import com.ruoyi.common.core.config.properties.ThreadPoolProperties;
import com.ruoyi.common.core.utils.Threads;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 线程池配置
*
* @author Lion Li
**/
@Slf4j
@AutoConfiguration
@EnableConfigurationProperties(ThreadPoolProperties.class)
public class ThreadPoolConfig {
/**
* 核心线程数 = cpu 核心数 + 1
*/
private final int core = Runtime.getRuntime().availableProcessors() + 1;
private ScheduledExecutorService scheduledExecutorService;
@Bean(name = "threadPoolTaskExecutor")
@ConditionalOnProperty(prefix = "thread-pool", name = "enabled", havingValue = "true")
public ThreadPoolTaskExecutor threadPoolTaskExecutor(ThreadPoolProperties threadPoolProperties) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(core);
executor.setMaxPoolSize(core * 2);
executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
new ThreadPoolExecutor.CallerRunsPolicy()) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
this.scheduledExecutorService = scheduledThreadPoolExecutor;
return scheduledThreadPoolExecutor;
}
/**
* 销毁事件
*/
@PreDestroy
public void destroy() {
try {
log.info("====关闭后台任务任务线程池====");
Threads.shutdownAndAwaitTermination(scheduledExecutorService);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}

View file

@ -0,0 +1,40 @@
package com.ruoyi.common.core.config;
import org.hibernate.validator.HibernateValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import jakarta.validation.Validator;
import java.util.Properties;
/**
* 校验框架配置类
*
* @author Lion Li
*/
@Configuration
public class ValidatorConfig {
/**
* 配置校验框架 快速返回模式
*/
@Bean
public Validator validator(MessageSource messageSource) {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
// 国际化
factoryBean.setValidationMessageSource(messageSource);
// 设置使用 HibernateValidator 校验器
factoryBean.setProviderClass(HibernateValidator.class);
Properties properties = new Properties();
// 设置 快速异常返回
properties.setProperty("hibernate.validator.fail_fast", "true");
factoryBean.setValidationProperties(properties);
// 加载配置
factoryBean.afterPropertiesSet();
return factoryBean.getValidator();
}
}

View file

@ -0,0 +1,30 @@
package com.ruoyi.common.core.config.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* 线程池 配置属性
*
* @author Lion Li
*/
@Data
@ConfigurationProperties(prefix = "thread-pool")
public class ThreadPoolProperties {
/**
* 是否开启线程池
*/
private boolean enabled;
/**
* 队列最大长度
*/
private int queueCapacity;
/**
* 线程池维护线程所允许的空闲时间
*/
private int keepAliveSeconds;
}

View file

@ -0,0 +1,44 @@
package com.ruoyi.common.core.constant;
/**
* 缓存的key 常量
*
* @author ruoyi
*/
public interface CacheConstants {
/**
* 在线用户 redis key
*/
String ONLINE_TOKEN_KEY = "online_tokens:";
/**
* 验证码 redis key
*/
String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 参数管理 cache key
*/
String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
String SYS_DICT_KEY = "sys_dict:";
/**
* 防重提交 redis key
*/
String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
String RATE_LIMIT_KEY = "rate_limit:";
/**
* 登录账户密码错误次数 redis key
*/
String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
}

View file

@ -0,0 +1,58 @@
package com.ruoyi.common.core.constant;
/**
* 缓存组名称常量
* <p>
* key 格式为 cacheNames#ttl#maxIdleTime#maxSize
* <p>
* ttl 过期时间 如果设置为0则不过期 默认为0
* maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0
* maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0
* <p>
* 例子: test#60stest#0#60stest#0#1m#1000test#1h#0#500
*
* @author Lion Li
*/
public interface CacheNames {
/**
* 演示案例
*/
String DEMO_CACHE = "demo:cache#60s#10m#20";
/**
* 系统配置
*/
String SYS_CONFIG = "sys_config";
/**
* 数据字典
*/
String SYS_DICT = "sys_dict";
/**
* 用户账户
*/
String SYS_USER_NAME = "sys_user_name#30d";
/**
* 部门
*/
String SYS_DEPT = "sys_dept#30d";
/**
* OSS内容
*/
String SYS_OSS = "sys_oss#30d";
/**
* OSS配置
*/
String SYS_OSS_CONFIG = "sys_oss_config";
/**
* 在线用户
*/
String ONLINE_TOKEN = "online_tokens";
}

View file

@ -0,0 +1,76 @@
package com.ruoyi.common.core.constant;
/**
* 通用常量信息
*
* @author ruoyi
*/
public interface Constants {
/**
* UTF-8 字符集
*/
String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
String GBK = "GBK";
/**
* www主域
*/
String WWW = "www.";
/**
* http请求
*/
String HTTP = "http://";
/**
* https请求
*/
String HTTPS = "https://";
/**
* 通用成功标识
*/
String SUCCESS = "0";
/**
* 通用失败标识
*/
String FAIL = "1";
/**
* 登录成功
*/
String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
String LOGOUT = "Logout";
/**
* 注册
*/
String REGISTER = "Register";
/**
* 登录失败
*/
String LOGIN_FAIL = "Error";
/**
* 验证码有效期分钟
*/
Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
String TOKEN = "token";
}

View file

@ -0,0 +1,30 @@
package com.ruoyi.common.core.constant;
public interface GlobalConstants {
/**
* 全局 redis key (业务无关的key)
*/
String GLOBAL_REDIS_KEY = "global:";
/**
* 验证码 redis key
*/
String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:";
/**
* 防重提交 redis key
*/
String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:";
/**
* 限流 redis key
*/
String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:";
/**
* 登录账户密码错误次数 redis key
*/
String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:";
}

View file

@ -0,0 +1,93 @@
package com.ruoyi.common.core.constant;
/**
* 返回状态码
*
* @author Lion Li
*/
public interface HttpStatus {
/**
* 操作成功
*/
int SUCCESS = 200;
/**
* 对象创建成功
*/
int CREATED = 201;
/**
* 请求已经被接受
*/
int ACCEPTED = 202;
/**
* 操作已经执行成功但是没有返回数据
*/
int NO_CONTENT = 204;
/**
* 资源已被移除
*/
int MOVED_PERM = 301;
/**
* 重定向
*/
int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
int NOT_MODIFIED = 304;
/**
* 参数列表错误缺少格式不匹配
*/
int BAD_REQUEST = 400;
/**
* 未授权
*/
int UNAUTHORIZED = 401;
/**
* 访问受限授权过期
*/
int FORBIDDEN = 403;
/**
* 资源服务未找到
*/
int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
int BAD_METHOD = 405;
/**
* 资源冲突或者资源被锁
*/
int CONFLICT = 409;
/**
* 不支持的数据媒体类型
*/
int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
int ERROR = 500;
/**
* 接口未实现
*/
int NOT_IMPLEMENTED = 501;
/**
* 系统警告消息
*/
int WARN = 601;
}

View file

@ -0,0 +1,54 @@
package com.ruoyi.common.core.constant;
import cn.hutool.core.lang.RegexPool;
/**
* 常用正则表达式字符串
* <p>
* 常用正则表达式集合更多正则见: https://any86.github.io/any-rule/
*
* @author Feng
*/
public interface RegexConstants extends RegexPool {
/**
* 字典类型必须以字母开头且只能为小写字母数字下滑线
*/
String DICTIONARY_TYPE = "^[a-z][a-z0-9_]*$";
/**
* 权限标识必须符合 tool:build:list 格式或者空字符串
*/
String PERMISSION_STRING = "^(|^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+:[a-zA-Z0-9_]+)$";
/**
* 身份证号码后6位
*/
String ID_CARD_LAST_6 = "^(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
/**
* QQ号码
*/
String QQ_NUMBER = "^[1-9][0-9]\\d{4,9}$";
/**
* 邮政编码
*/
String POSTAL_CODE = "^[1-9]\\d{5}$";
/**
* 注册账号
*/
String ACCOUNT = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";
/**
* 密码包含至少8个字符包括大写字母小写字母数字和特殊字符
*/
String PASSWORD = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
/**
* 通用状态0表示正常1表示停用
*/
String STATUS = "^[01]$";
}

View file

@ -0,0 +1,147 @@
package com.ruoyi.common.core.constant;
/**
* 用户常量信息
*
* @author ruoyi
*/
public interface UserConstants {
/**
* 平台内系统用户的唯一标志
*/
String SYS_USER = "SYS_USER";
/**
* 正常状态
*/
String NORMAL = "0";
/**
* 异常状态
*/
String EXCEPTION = "1";
/**
* 用户正常状态
*/
String USER_NORMAL = "0";
/**
* 用户封禁状态
*/
String USER_DISABLE = "1";
/**
* 角色正常状态
*/
String ROLE_NORMAL = "0";
/**
* 角色封禁状态
*/
String ROLE_DISABLE = "1";
/**
* 部门正常状态
*/
String DEPT_NORMAL = "0";
/**
* 部门停用状态
*/
String DEPT_DISABLE = "1";
/**
* 岗位正常状态
*/
String POST_NORMAL = "0";
/**
* 岗位停用状态
*/
String POST_DISABLE = "1";
/**
* 字典正常状态
*/
String DICT_NORMAL = "0";
/**
* 是否为系统默认
*/
String YES = "Y";
/**
* 是否菜单外链
*/
String YES_FRAME = "0";
/**
* 是否菜单外链
*/
String NO_FRAME = "1";
/**
* 菜单正常状态
*/
String MENU_NORMAL = "0";
/**
* 菜单停用状态
*/
String MENU_DISABLE = "1";
/**
* 菜单类型目录
*/
String TYPE_DIR = "M";
/**
* 菜单类型菜单
*/
String TYPE_MENU = "C";
/**
* 菜单类型按钮
*/
String TYPE_BUTTON = "F";
/**
* Layout组件标识
*/
String LAYOUT = "Layout";
/**
* ParentView组件标识
*/
String PARENT_VIEW = "ParentView";
/**
* InnerLink组件标识
*/
String INNER_LINK = "InnerLink";
/**
* 用户名长度限制
*/
int USERNAME_MIN_LENGTH = 2;
int USERNAME_MAX_LENGTH = 20;
/**
* 密码长度限制
*/
int PASSWORD_MIN_LENGTH = 5;
int PASSWORD_MAX_LENGTH = 20;
/**
* 管理员ID
*/
Long ADMIN_ID = 1L;
/**
* 管理员角色key
*/
String ADMIN_ROLE_KEY = "admin";
}

View file

@ -0,0 +1,107 @@
package com.ruoyi.common.core.domain;
import com.ruoyi.common.core.constant.HttpStatus;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 响应信息主体
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class R<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功
*/
public static final int SUCCESS = 200;
/**
* 失败
*/
public static final int FAIL = 500;
private int code;
private String msg;
private T data;
public static <T> R<T> ok() {
return restResult(null, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data) {
return restResult(data, SUCCESS, "操作成功");
}
public static <T> R<T> ok(String msg) {
return restResult(null, SUCCESS, msg);
}
public static <T> R<T> ok(String msg, T data) {
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail() {
return restResult(null, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data) {
return restResult(data, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg, T data) {
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg) {
return restResult(null, code, msg);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static <T> R<T> warn(String msg) {
return restResult(null, HttpStatus.WARN, msg);
}
/**
* 返回警告消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static <T> R<T> warn(String msg, T data) {
return restResult(data, HttpStatus.WARN, msg);
}
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> r = new R<>();
r.setCode(code);
r.setData(data);
r.setMsg(msg);
return r;
}
public static <T> Boolean isError(R<T> ret) {
return !isSuccess(ret);
}
public static <T> Boolean isSuccess(R<T> ret) {
return R.SUCCESS == ret.getCode();
}
}

View file

@ -0,0 +1,30 @@
package com.ruoyi.common.core.domain.bo;
import lombok.Data;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
/**
* 邮箱登录对象
*
* @author Lion Li
*/
@Data
public class EmailLoginBody {
/**
* 邮箱
*/
@NotBlank(message = "{user.email.not.blank}")
@Email(message = "{user.email.not.valid}")
private String email;
/**
* 邮箱code
*/
@NotBlank(message = "{email.code.not.blank}")
private String emailCode;
}

View file

@ -0,0 +1,42 @@
package com.ruoyi.common.core.domain.bo;
import com.ruoyi.common.core.constant.UserConstants;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import jakarta.validation.constraints.NotBlank;
/**
* 用户登录对象
*
* @author Lion Li
*/
@Data
public class LoginBody {
/**
* 用户名
*/
@NotBlank(message = "{user.username.not.blank}")
@Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
private String username;
/**
* 用户密码
*/
@NotBlank(message = "{user.password.not.blank}")
@Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
private String password;
/**
* 验证码
*/
private String code;
/**
* 唯一标识
*/
private String uuid;
}

View file

@ -0,0 +1,116 @@
package com.ruoyi.common.core.domain.bo;
import com.ruoyi.common.core.domain.vo.RoleVO;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
/**
* 登录用户身份权限
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class LoginUser implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 部门ID
*/
private Long deptId;
/**
* 部门名
*/
private String deptName;
/**
* 用户唯一标识
*/
private String token;
/**
* 用户类型
*/
private String userType;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地点
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 菜单权限
*/
private Set<String> menuPermission;
/**
* 角色权限
*/
private Set<String> rolePermission;
/**
* 用户名
*/
private String username;
/**
* 角色对象
*/
private List<RoleVO> roles;
/**
* 数据权限 当前角色ID
*/
private Long roleId;
/**
* 获取登录id
*/
public String getLoginId() {
if (userType == null) {
throw new IllegalArgumentException("用户类型不能为空");
}
if (userId == null) {
throw new IllegalArgumentException("用户ID不能为空");
}
return userType + ":" + userId;
}
}

View file

@ -0,0 +1,17 @@
package com.ruoyi.common.core.domain.bo;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 用户注册对象
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class RegisterBody extends LoginBody {
private String userType;
}

View file

@ -0,0 +1,28 @@
package com.ruoyi.common.core.domain.bo;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
/**
* 短信登录对象
*
* @author Lion Li
*/
@Data
public class SmsLoginBody {
/**
* 手机号
*/
@NotBlank(message = "{user.phonenumber.not.blank}")
private String phonenumber;
/**
* 短信code
*/
@NotBlank(message = "{sms.code.not.blank}")
private String smsCode;
}

View file

@ -0,0 +1,24 @@
package com.ruoyi.common.core.domain.bo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 小程序登录用户身份权限
*
* @author Lion Li
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class XcxLoginUser extends LoginUser {
private static final long serialVersionUID = 1L;
/**
* openid
*/
private String openid;
}

View file

@ -0,0 +1,38 @@
package com.ruoyi.common.core.domain.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 角色
*
* @author Lion Li
*/
@Data
@NoArgsConstructor
public class RoleVO implements Serializable {
/**
* 角色ID
*/
private Long roleId;
/**
* 角色名称
*/
private String roleName;
/**
* 角色权限
*/
private String roleKey;
/**
* 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限
*/
private String dataScope;
}

View file

@ -0,0 +1,60 @@
package com.ruoyi.common.core.domain.vo;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 当前在线会话
*
* @author ruoyi
*/
@Data
@NoArgsConstructor
public class UserOnlineVO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 会话编号
*/
private String tokenId;
/**
* 部门名称
*/
private String deptName;
/**
* 用户名称
*/
private String userName;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 登录地址
*/
private String loginLocation;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 登录时间
*/
private Long loginTime;
}

View file

@ -0,0 +1,18 @@
package com.ruoyi.common.core.enums;
/**
* 操作状态
*
* @author ruoyi
*/
public enum BusinessStatus {
/**
* 成功
*/
SUCCESS,
/**
* 失败
*/
FAIL,
}

View file

@ -0,0 +1,32 @@
package com.ruoyi.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 设备类型
* 针对一套 用户体系
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum DeviceType {
/**
* pc端
*/
PC("pc"),
/**
* app端
*/
APP("app"),
/**
* 小程序端
*/
XCX("xcx");
private final String device;
}

View file

@ -1,36 +1,32 @@
package com.ruoyi.common.enums; package com.ruoyi.common.core.enums;
import org.springframework.lang.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.springframework.lang.Nullable;
/** /**
* 请求方式 * 请求方式
* *
* @author ruoyi * @author ruoyi
*/ */
public enum HttpMethod public enum HttpMethod {
{
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE; GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
private static final Map<String, HttpMethod> mappings = new HashMap<>(16); private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
static static {
{ for (HttpMethod httpMethod : values()) {
for (HttpMethod httpMethod : values())
{
mappings.put(httpMethod.name(), httpMethod); mappings.put(httpMethod.name(), httpMethod);
} }
} }
@Nullable @Nullable
public static HttpMethod resolve(@Nullable String method) public static HttpMethod resolve(@Nullable String method) {
{
return (method != null ? mappings.get(method) : null); return (method != null ? mappings.get(method) : null);
} }
public boolean matches(String method) public boolean matches(String method) {
{
return (this == resolve(method)); return (this == resolve(method));
} }
} }

View file

@ -0,0 +1,44 @@
package com.ruoyi.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 登录类型
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum LoginType {
/**
* 密码登录
*/
PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"),
/**
* 短信登录
*/
SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"),
/**
* 邮箱登录
*/
EMAIL("email.code.retry.limit.exceed", "email.code.retry.limit.count"),
/**
* 小程序登录
*/
XCX("", "");
/**
* 登录重试超出限制提示
*/
final String retryLimitExceed;
/**
* 登录重试限制计数提示
*/
final String retryLimitCount;
}

View file

@ -0,0 +1,23 @@
package com.ruoyi.common.core.enums;
/**
* 操作人类别
*
* @author ruoyi
*/
public enum OperatorType {
/**
* 其它
*/
OTHER,
/**
* 后台用户
*/
MANAGE,
/**
* 手机端用户
*/
MOBILE
}

View file

@ -0,0 +1,29 @@
package com.ruoyi.common.core.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 用户状态
*
* @author ruoyi
*/
@Getter
@AllArgsConstructor
public enum UserStatus {
/**
* 正常
*/
OK("0", "正常"),
/**
* 停用
*/
DISABLE("1", "停用"),
/**
* 删除
*/
DELETED("2", "删除");
private final String code;
private final String info;
}

View file

@ -0,0 +1,37 @@
package com.ruoyi.common.core.enums;
import com.ruoyi.common.core.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 设备类型
* 针对多套 用户体系
*
* @author Lion Li
*/
@Getter
@AllArgsConstructor
public enum UserType {
/**
* pc端
*/
SYS_USER("sys_user"),
/**
* app端
*/
APP_USER("app_user");
private final String userType;
public static UserType getUserType(String str) {
for (UserType value : values()) {
if (StringUtils.contains(str, value.getUserType())) {
return value;
}
}
throw new RuntimeException("'UserType' not found By " + str);
}
}

View file

@ -1,11 +1,11 @@
package com.ruoyi.common.exception; package com.ruoyi.common.core.exception;
/** /**
* 业务异常 * 业务异常
* *
* @author ruoyi * @author ruoyi
*/ */
public class ServiceException extends RuntimeException { public final class ServiceException extends RuntimeException {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
@ -44,6 +44,7 @@ public class ServiceException extends RuntimeException {
return detailMessage; return detailMessage;
} }
@Override
public String getMessage() { public String getMessage() {
return message; return message;
} }

View file

@ -0,0 +1,75 @@
package com.ruoyi.common.core.exception.base;
import com.ruoyi.common.core.utils.MessageUtils;
import com.ruoyi.common.core.utils.StringUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 基础异常
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class BaseException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 所属模块
*/
private String module;
/**
* 错误码
*/
private String code;
/**
* 错误码对应的参数
*/
private Object[] args;
/**
* 错误消息
*/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage) {
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args) {
this(module, code, args, null);
}
public BaseException(String module, String defaultMessage) {
this(module, null, null, defaultMessage);
}
public BaseException(String code, Object[] args) {
this(null, code, args, null);
}
public BaseException(String defaultMessage) {
this(null, null, null, defaultMessage);
}
@Override
public String getMessage() {
String message = null;
if (!StringUtils.isEmpty(code)) {
message = MessageUtils.message(code, args);
}
if (message == null) {
message = defaultMessage;
}
return message;
}
}

View file

@ -0,0 +1,17 @@
package com.ruoyi.common.core.exception.file;
import com.ruoyi.common.core.exception.base.BaseException;
/**
* 文件信息异常类
*
* @author ruoyi
*/
public class FileException extends BaseException {
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args) {
super("file", code, args, null);
}
}

View file

@ -1,16 +1,14 @@
package com.ruoyi.common.exception.file; package com.ruoyi.common.core.exception.file;
/** /**
* 文件名称超长限制异常类 * 文件名称超长限制异常类
* *
* @author ruoyi * @author ruoyi
*/ */
public class FileNameLengthLimitExceededException extends FileException public class FileNameLengthLimitExceededException extends FileException {
{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength) public FileNameLengthLimitExceededException(int defaultFileNameLength) {
{ super("upload.filename.exceed.length", new Object[]{defaultFileNameLength});
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
} }
} }

View file

@ -0,0 +1,14 @@
package com.ruoyi.common.core.exception.file;
/**
* 文件名大小限制异常类
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException {
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize) {
super("upload.exceed.maxSize", new Object[]{defaultMaxSize});
}
}

View file

@ -0,0 +1,14 @@
package com.ruoyi.common.core.exception.user;
/**
* 验证码错误异常类
*
* @author ruoyi
*/
public class CaptchaException extends UserException {
private static final long serialVersionUID = 1L;
public CaptchaException() {
super("user.jcaptcha.error");
}
}

View file

@ -0,0 +1,14 @@
package com.ruoyi.common.core.exception.user;
/**
* 验证码失效异常类
*
* @author ruoyi
*/
public class CaptchaExpireException extends UserException {
private static final long serialVersionUID = 1L;
public CaptchaExpireException() {
super("user.jcaptcha.expire");
}
}

View file

@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception.user;
import com.ruoyi.common.core.exception.base.BaseException;
/**
* 用户信息异常类
*
* @author ruoyi
*/
public class UserException extends BaseException {
private static final long serialVersionUID = 1L;
public UserException(String code, Object... args) {
super("user", code, args, null);
}
}

View file

@ -0,0 +1,52 @@
package com.ruoyi.common.core.factory;
import cn.hutool.core.lang.PatternPool;
import com.ruoyi.common.core.constant.RegexConstants;
import java.util.regex.Pattern;
/**
* 正则表达式模式池工厂
* <p>初始化的时候将正则表达式加入缓存池当中</p>
* <p>提高正则表达式的性能避免重复编译相同的正则表达式</p>
*
* @author 21001
*/
public class RegexPatternPoolFactory extends PatternPool {
/**
* 字典类型必须以字母开头且只能为小写字母数字下滑线
*/
public static final Pattern DICTIONARY_TYPE = get(RegexConstants.DICTIONARY_TYPE);
/**
* 身份证号码后6位
*/
public static final Pattern ID_CARD_LAST_6 = get(RegexConstants.ID_CARD_LAST_6);
/**
* QQ号码
*/
public static final Pattern QQ_NUMBER = get(RegexConstants.QQ_NUMBER);
/**
* 邮政编码
*/
public static final Pattern POSTAL_CODE = get(RegexConstants.POSTAL_CODE);
/**
* 注册账号
*/
public static final Pattern ACCOUNT = get(RegexConstants.ACCOUNT);
/**
* 密码包含至少8个字符包括大写字母小写字母数字和特殊字符
*/
public static final Pattern PASSWORD = get(RegexConstants.PASSWORD);
/**
* 通用状态0表示正常1表示停用
*/
public static final Pattern STATUS = get(RegexConstants.STATUS);
}

Some files were not shown because too many files have changed in this diff Show more