first commit
This commit is contained in:
		
							
								
								
									
										18
									
								
								.editorconfig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.editorconfig
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										54
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | ###################################################################### | ||||||
|  | # Build Tools | ||||||
|  |  | ||||||
|  | .gradle | ||||||
|  | /build/ | ||||||
|  | !gradle/wrapper/gradle-wrapper.jar | ||||||
|  |  | ||||||
|  | target/ | ||||||
|  | !.mvn/wrapper/maven-wrapper.jar | ||||||
|  |  | ||||||
|  | ###################################################################### | ||||||
|  | # IDE | ||||||
|  |  | ||||||
|  | ### STS ### | ||||||
|  | .apt_generated | ||||||
|  | .classpath | ||||||
|  | .factorypath | ||||||
|  | .project | ||||||
|  | .settings | ||||||
|  | .springBeans | ||||||
|  |  | ||||||
|  | ### IntelliJ IDEA ### | ||||||
|  | .idea | ||||||
|  | *.iws | ||||||
|  | *.iml | ||||||
|  | *.ipr | ||||||
|  |  | ||||||
|  | ### JRebel ### | ||||||
|  | rebel.xml | ||||||
|  |  | ||||||
|  | ### NetBeans ### | ||||||
|  | nbproject/private/ | ||||||
|  | build/* | ||||||
|  | nbbuild/ | ||||||
|  | nbdist/ | ||||||
|  | .nb-gradle/ | ||||||
|  |  | ||||||
|  | ###################################################################### | ||||||
|  | # Others | ||||||
|  | *.log | ||||||
|  | *.xml.versionsBackup | ||||||
|  | *.swp | ||||||
|  |  | ||||||
|  | !*/build/*.java | ||||||
|  | !*/build/*.html | ||||||
|  | !*/build/*.xml | ||||||
|  |  | ||||||
|  | .flattened-pom.xml | ||||||
|  |  | ||||||
|  | .gitee | ||||||
|  | .run | ||||||
|  | logs/ | ||||||
|  | docs | ||||||
|  | /file | ||||||
							
								
								
									
										20
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | The MIT License (MIT) | ||||||
|  |  | ||||||
|  | Copyright (c) 2019 RuoYi-Vue-Plus | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  | the Software without restriction, including without limitation the rights to | ||||||
|  | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | ||||||
|  | the Software, and to permit persons to whom the Software is furnished to do so, | ||||||
|  | subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||||||
|  | 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 | ||||||
|  | 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. | ||||||
							
								
								
									
										185
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,185 @@ | |||||||
|  | <img src="https://foruda.gitee.com/images/1679673773341074847/178e8451_1766278.png" width="50%" height="50%"> | ||||||
|  | <div style="height: 10px; clear: both;"></div> | ||||||
|  |  | ||||||
|  | - - - | ||||||
|  | ## 平台简介 | ||||||
|  |  | ||||||
|  | [](https://gitee.com/dromara/RuoYi-Vue-Plus) | ||||||
|  | [](https://github.com/dromara/RuoYi-Vue-Plus) | ||||||
|  | [](https://gitcode.com/dromara/RuoYi-Vue-Plus) | ||||||
|  | [](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/master/LICENSE) | ||||||
|  | [](https://www.jetbrains.com/?from=RuoYi-Vue-Plus) | ||||||
|  | <br> | ||||||
|  | [](https://gitee.com/dromara/RuoYi-Vue-Plus) | ||||||
|  | []() | ||||||
|  | []() | ||||||
|  | []() | ||||||
|  |  | ||||||
|  | > Dromara RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群与多租户` 场景全方位升级(不兼容原框架) | ||||||
|  |  | ||||||
|  | > 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可<br> | ||||||
|  | 活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源 | ||||||
|  |  | ||||||
|  | > 系统演示: [传送门](https://plus-doc.dromara.org/#/common/demo_system) | ||||||
|  |  | ||||||
|  | > 官方前端项目地址: [plus-ui](https://gitee.com/JavaLionLi/plus-ui)<br> | ||||||
|  | > 成员前端项目地址: 基于vben5 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5) | ||||||
|  |  | ||||||
|  | > 文档地址: [plus-doc](https://plus-doc.dromara.org) | ||||||
|  |  | ||||||
|  | ## 赞助商 | ||||||
|  |  | ||||||
|  | MaxKey 业界领先单点登录产品 - https://gitee.com/dromara/MaxKey <br> | ||||||
|  | CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow <br> | ||||||
|  | 数舵科技 软件定制开发APP小程序等 - http://www.shuduokeji.com/ <br> | ||||||
|  | 引迈信息 软件开发平台 - https://www.jnpfsoft.com/index.html?from=plus-doc <br> | ||||||
|  | <font color="red">**启山商城系统 多租户商城源码可免费商用可二次开发 - https://www.73app.cn/** </font><br> | ||||||
|  | [如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group) | ||||||
|  |  | ||||||
|  | # 本框架与RuoYi的功能差异 | ||||||
|  |  | ||||||
|  | | 功能          | 本框架                                                                                                               | RuoYi                                                                              | | ||||||
|  | |-------------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| | ||||||
|  | | 前端项目        | 采用 Vue3 + TS + ElementPlus 重写                                                                                     | 基于Vue2/Vue3 + JS                                                                   |  | ||||||
|  | | 后端项目结构      | 采用插件化 + 扩展包形式 结构解耦 易于扩展                                                                                           | 模块相互注入耦合严重难以扩展                                                                     |  | ||||||
|  | | 后端代码风格      | 严格遵守Alibaba规范与项目统一配置的代码格式化                                                                                        | 代码书写与常规结构不同阅读障碍大                                                                   | | ||||||
|  | | Web容器       | 采用 Undertow 基于 XNIO 的高性能容器                                                                                        | 采用 Tomcat                                                                          | | ||||||
|  | | 权限认证        | 采用 Sa-Token、Jwt 静态使用功能齐全 低耦合 高扩展                                                                                  | Spring Security 配置繁琐扩展性极差                                                          | | ||||||
|  | | 权限注解        | 采用 Sa-Token 支持注解 登录校验、角色校验、权限校验、二级认证校验、HttpBasic校验、忽略校验<br/>角色与权限校验支持多种条件 如 `AND` `OR` 或 `权限 OR 角色` 等复杂表达式        | 只支持是否存在匹配                                                                          | | ||||||
|  | | 三方鉴权        | 采用 JustAuth 第三方登录组件 支持微信、钉钉等数十种三方认证                                                                               | 无                                                                                  | | ||||||
|  | | 关系数据库支持     | 原生支持 MySQL、Oracle、PostgreSQL、SQLServer<br/>可同时使用异构切换(支持其他 mybatis-plus 支持的所有数据库 只需要增加jdbc依赖即可使用 达梦金仓等均有成功案例)      | 支持 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等                                              | 无                                                                                  | | ||||||
|  | | 接口传输加密      | 采用 动态 AES + RSA 加密请求 body 每一次请求秘钥都不同大幅度降低可破解性                                                                     | 无                                                                                  | | ||||||
|  | | 数据翻译        | 采用 注解 + jackson 序列化期间动态修改数据 数据进行翻译<br/>支持多种模式: `映射翻译` `直接翻译` `其他扩展条件翻译` 接口化两步即可完成自定义扩展 内置多种翻译实现                   | 无                                                                                  | | ||||||
|  | | 多数据源框架      | 采用 dynamic-datasource 支持市面大部分数据库<br/>通过yml配置即可动态管理异构不同种类的数据库 也可通过前端页面添加数据源<br/>支持spel表达式从请求头参数等条件切换数据源            | 基于 druid 手动编写代码配置数据源 配置繁琐 支持性差                                                     | | ||||||
|  | | 多数据源事务      | 采用 dynamic-datasource 支持多数据源不同种类的数据库事务回滚                                                                          | 不支持                                                                                | | ||||||
|  | | 数据库连接池      | 采用 HikariCP Spring官方内置连接池 配置简单 以性能与稳定性闻名天下                                                                        | 采用 druid bug众多 社区维护差 活跃度低 配置众多繁琐性能一般                                               | | ||||||
|  | | 数据库主键       | 采用 雪花ID 基于时间戳的 有序增长 唯一ID 再也不用为分库分表 数据合并主键冲突重复而发愁                                                                  | 采用 数据库自增ID 支持数据量有限 不支持多数据源主键唯一                                                     | | ||||||
|  | | WebSocket协议 | 基于 Spring 封装的 WebSocket 协议 扩展了Token鉴权与分布式会话同步 不再只是基于单机的废物                                                         | 无                                                                                  | | ||||||
|  | | SSE推送       | 采用 Spring SSE 实现 扩展了Token鉴权与分布式会话同步                                                                               | 无                                                                                  | | ||||||
|  | | 序列化         | 采用 Jackson Spring官方内置序列化 靠谱!!!                                                                                    | 采用 fastjson bugjson 远近闻名                                                           |  | ||||||
|  | | 分布式幂等       | 参考美团GTIS防重系统简化实现(细节可看文档)                                                                                          | 手动编写注解基于aop实现                                                                      | | ||||||
|  | | 分布式锁        | 采用 Lock4j 底层基于 Redisson                                                                                           | 无                                                                                  | | ||||||
|  | | 分布式任务调度     | 采用 SnailJob 天生支持分布式 统一的管理中心 支持多种数据库 支持分片重试DAG任务流等                                                                 | 采用 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规范化代码 同时支持动态多数据源代码生成                    | 代码生成原生结构 只支持单数据源生成                                                                 | | ||||||
|  | | 部署方式        | 支持 Docker 编排 一键搭建所有环境 让开发人员从此不再为搭建环境而烦恼                                                                           | 原生jar部署 其他环境需手动下载安装 自行搭建                                                           |  | ||||||
|  | | 项目路径修改      | 提供详细的修改方案文档 并为其做了一些改动 非常简单即可修改成自己想要的                                                                              | 需要做很多改造 文档说明有限                                                                     | | ||||||
|  | | 国际化         | 基于请求头动态返回不同语种的文本内容 开发难度低 有对应的工具类 支持大部分注解内容国际化                                                                     | 只提供基础功能 其他需自行编写扩展                                                                  | | ||||||
|  | | 代码单例测试      | 提供单例测试 使用方式编写方法与maven多环境单测插件                                                                                      | 只提供基础功能 其他需自行编写扩展                                                                  | | ||||||
|  | | Demo案例      | 提供框架功能的实际使用案例 单独一个模块提供了很多很全                                                                                       | 无                                                                                  | | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## 本框架与RuoYi的业务差异 | ||||||
|  |  | ||||||
|  | | 业务     | 功能说明                                                                 | 本框架 | RuoYi            | | ||||||
|  | |--------|----------------------------------------------------------------------|-----|------------------| | ||||||
|  | | 租户管理   | 系统内租户的管理 如:租户套餐、过期时间、用户数量、企业信息等                                      | 支持  | 无                | | ||||||
|  | | 租户套餐管理 | 系统内租户所能使用的套餐管理 如:套餐内所包含的菜单等                                          | 支持  | 无                | | ||||||
|  | | 客户端管理  | 系统内对接的所有客户端管理 如: pc端、小程序端等<br>支持动态授权登录方式 如: 短信登录、密码登录等 支持动态控制token时效 | 支持  | 无                | | ||||||
|  | | 用户管理   | 用户的管理配置 如:新增用户、分配用户所属部门、角色、岗位等                                       | 支持  | 支持               | | ||||||
|  | | 部门管理   | 配置系统组织机构(公司、部门、小组) 树结构展现支持数据权限                                       | 支持  | 支持               | | ||||||
|  | | 岗位管理   | 配置系统用户所属担任职务                                                         | 支持  | 支持               | | ||||||
|  | | 菜单管理   | 配置系统菜单、操作权限、按钮权限标识等                                                  | 支持  | 支持               | | ||||||
|  | | 角色管理   | 角色菜单权限分配、设置角色按机构进行数据范围权限划分                                           | 支持  | 支持               | | ||||||
|  | | 字典管理   | 对系统中经常使用的一些较为固定的数据进行维护                                               | 支持  | 支持               | | ||||||
|  | | 参数管理   | 对系统动态配置常用参数                                                          | 支持  | 支持               | | ||||||
|  | | 通知公告   | 系统通知公告信息发布维护                                                         | 支持  | 支持               | | ||||||
|  | | 操作日志   | 系统正常操作日志记录和查询 系统异常信息日志记录和查询                                          | 支持  | 支持               | | ||||||
|  | | 登录日志   | 系统登录日志记录查询包含登录异常                                                     | 支持  | 支持               | | ||||||
|  | | 文件管理   | 系统文件展示、上传、下载、删除等管理                                                   | 支持  | 无                | | ||||||
|  | | 文件配置管理 | 系统文件上传、下载所需要的配置信息动态添加、修改、删除等管理                                       | 支持  | 无                | | ||||||
|  | | 在线用户管理 | 已登录系统的在线用户信息监控与强制踢出操作                                                | 支持  | 支持               | | ||||||
|  | | 定时任务   | 运行报表、任务管理(添加、修改、删除)、日志管理、执行器管理等                                      | 支持  | 仅支持任务与日志管理       | | ||||||
|  | | 代码生成   | 多数据源前后端代码的生成(java、html、xml、sql)支持CRUD下载                              | 支持  | 仅支持单数据源          | | ||||||
|  | | 系统接口   | 根据业务代码自动生成相关的api接口文档                                                 | 支持  | 支持               | | ||||||
|  | | 服务监控   | 监视集群系统CPU、内存、磁盘、堆栈、在线日志、Spring相关配置等                                  | 支持  | 仅支持单机CPU、内存、磁盘监控 | | ||||||
|  | | 缓存监控   | 对系统的缓存信息查询,命令统计等。                                                    | 支持  | 支持               | | ||||||
|  | | 在线构建器  | 拖动表单元素生成相应的HTML代码。                                                   | 支持  | 支持               | | ||||||
|  | | 使用案例   | 系统的一些功能案例                                                            | 支持  | 不支持              | | ||||||
|  |  | ||||||
|  | ## 参考文档 | ||||||
|  |  | ||||||
|  | 使用框架前请仔细阅读文档重点注意事项 | ||||||
|  | <br> | ||||||
|  | >[初始化项目 必看](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init) | ||||||
|  | >>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init) | ||||||
|  | > | ||||||
|  | >[专栏与视频 入门必看](https://plus-doc.dromara.org/#/common/column) | ||||||
|  | >>[https://plus-doc.dromara.org/#/common/column](https://plus-doc.dromara.org/#/common/column) | ||||||
|  | > | ||||||
|  | >[部署项目 必看](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy) | ||||||
|  | >>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy) | ||||||
|  | > | ||||||
|  | >[如何加群](https://plus-doc.dromara.org/#/common/add_group) | ||||||
|  | >>[https://plus-doc.dromara.org/#/common/add_group](https://plus-doc.dromara.org/#/common/add_group) | ||||||
|  | > | ||||||
|  | >[参考文档 Wiki](https://plus-doc.dromara.org) | ||||||
|  | >>[https://plus-doc.dromara.org](https://plus-doc.dromara.org) | ||||||
|  |  | ||||||
|  | ## 软件架构图 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## 如何参与贡献 | ||||||
|  |  | ||||||
|  | [参与贡献的方式 https://plus-doc.dromara.org/#/common/contribution](https://plus-doc.dromara.org/#/common/contribution) | ||||||
|  |  | ||||||
|  | ## 捐献作者 | ||||||
|  | 作者为兼职做开源,平时还需要工作,如果帮到了您可以请作者吃个盒饭   | ||||||
|  | <img src="https://foruda.gitee.com/images/1678975784848381069/d8661ed9_1766278.png" width="300px" height="450px" /> | ||||||
|  | <img src="https://foruda.gitee.com/images/1678975801230205215/6f96229d_1766278.png" width="300px" height="450px" /> | ||||||
|  |  | ||||||
|  | ## 演示图例 | ||||||
|  |  | ||||||
|  | |                                                                                            |                                                                                            | | ||||||
|  | |--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  | |  |  | | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								file/resource/design/main.exe
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								file/resource/design/main.exe
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										521
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										521
									
								
								pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,521 @@ | |||||||
|  | <?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>org.dromara</groupId> | ||||||
|  |     <artifactId>xinnengyuan</artifactId> | ||||||
|  |     <version>${revision}</version> | ||||||
|  |  | ||||||
|  |     <name>xinnengyuan</name> | ||||||
|  |     <description>新能源项目</description> | ||||||
|  |  | ||||||
|  |     <properties> | ||||||
|  |         <revision>5.3.0</revision> | ||||||
|  |         <spring-boot.version>3.4.2</spring-boot.version> | ||||||
|  |         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||||
|  |         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||||||
|  |         <java.version>21</java.version> | ||||||
|  |         <mybatis.version>3.5.16</mybatis.version> | ||||||
|  |         <springdoc.version>2.8.4</springdoc.version> | ||||||
|  |         <therapi-javadoc.version>0.15.0</therapi-javadoc.version> | ||||||
|  |         <easyexcel.version>4.0.3</easyexcel.version> | ||||||
|  |         <velocity.version>2.3</velocity.version> | ||||||
|  |         <satoken.version>1.40.0</satoken.version> | ||||||
|  |         <mybatis-plus.version>3.5.10</mybatis-plus.version> | ||||||
|  |         <p6spy.version>3.9.1</p6spy.version> | ||||||
|  |         <hutool.version>5.8.35</hutool.version> | ||||||
|  |         <spring-boot-admin.version>3.4.1</spring-boot-admin.version> | ||||||
|  |         <redisson.version>3.44.0</redisson.version> | ||||||
|  |         <lock4j.version>2.2.7</lock4j.version> | ||||||
|  |         <dynamic-ds.version>4.3.1</dynamic-ds.version> | ||||||
|  |         <snailjob.version>1.3.0</snailjob.version> | ||||||
|  |         <mapstruct-plus.version>1.4.6</mapstruct-plus.version> | ||||||
|  |         <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version> | ||||||
|  |         <lombok.version>1.18.36</lombok.version> | ||||||
|  |         <bouncycastle.version>1.76</bouncycastle.version> | ||||||
|  |         <justauth.version>1.16.7</justauth.version> | ||||||
|  |         <!-- 离线IP地址定位库 --> | ||||||
|  |         <ip2region.version>2.7.0</ip2region.version> | ||||||
|  |  | ||||||
|  |         <!-- OSS 配置 --> | ||||||
|  |         <aws.sdk.version>2.28.22</aws.sdk.version> | ||||||
|  |         <aws.crt.version>0.31.3</aws.crt.version> | ||||||
|  |         <!-- SMS 配置 --> | ||||||
|  |         <sms4j.version>3.3.3</sms4j.version> | ||||||
|  |         <!-- 限制框架中的fastjson版本 --> | ||||||
|  |         <fastjson.version>1.2.83</fastjson.version> | ||||||
|  |         <!-- 面向运行时的D-ORM依赖 --> | ||||||
|  |         <anyline.version>8.7.2-20250101</anyline.version> | ||||||
|  |         <!--工作流配置--> | ||||||
|  |         <warm-flow.version>1.7.4</warm-flow.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.version>3.11.0</maven-compiler-plugin.version> | ||||||
|  |         <maven-surefire-plugin.version>3.1.2</maven-surefire-plugin.version> | ||||||
|  |         <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version> | ||||||
|  |         <!-- JTS库版本 --> | ||||||
|  |         <jts.version>1.20.0</jts.version> | ||||||
|  |     </properties> | ||||||
|  |  | ||||||
|  |     <profiles> | ||||||
|  |         <profile> | ||||||
|  |             <id>local</id> | ||||||
|  |             <properties> | ||||||
|  |                 <!-- 环境标识,需要与配置文件的名称相对应 --> | ||||||
|  |                 <profiles.active>local</profiles.active> | ||||||
|  |                 <logging.level>info</logging.level> | ||||||
|  |                 <monitor.username>ruoyi</monitor.username> | ||||||
|  |                 <monitor.password>123456</monitor.password> | ||||||
|  |             </properties> | ||||||
|  |         </profile> | ||||||
|  |         <profile> | ||||||
|  |             <id>dev</id> | ||||||
|  |             <properties> | ||||||
|  |                 <!-- 环境标识,需要与配置文件的名称相对应 --> | ||||||
|  |                 <profiles.active>dev</profiles.active> | ||||||
|  |                 <logging.level>info</logging.level> | ||||||
|  |                 <monitor.username>ruoyi</monitor.username> | ||||||
|  |                 <monitor.password>123456</monitor.password> | ||||||
|  |             </properties> | ||||||
|  |             <activation> | ||||||
|  |                 <!-- 默认环境 --> | ||||||
|  |                 <activeByDefault>true</activeByDefault> | ||||||
|  |             </activation> | ||||||
|  |         </profile> | ||||||
|  |         <profile> | ||||||
|  |             <id>prod</id> | ||||||
|  |             <properties> | ||||||
|  |                 <profiles.active>prod</profiles.active> | ||||||
|  |                 <logging.level>info</logging.level> | ||||||
|  |                 <monitor.username>ruoyi</monitor.username> | ||||||
|  |                 <monitor.password>123456</monitor.password> | ||||||
|  |             </properties> | ||||||
|  |         </profile> | ||||||
|  |     </profiles> | ||||||
|  |  | ||||||
|  |     <!-- 依赖声明 --> | ||||||
|  |     <dependencyManagement> | ||||||
|  |         <dependencies> | ||||||
|  |  | ||||||
|  |             <!-- SpringBoot的依赖配置--> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.springframework.boot</groupId> | ||||||
|  |                 <artifactId>spring-boot-dependencies</artifactId> | ||||||
|  |                 <version>${spring-boot.version}</version> | ||||||
|  |                 <type>pom</type> | ||||||
|  |                 <scope>import</scope> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- hutool 的依赖配置--> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>cn.hutool</groupId> | ||||||
|  |                 <artifactId>hutool-bom</artifactId> | ||||||
|  |                 <version>${hutool.version}</version> | ||||||
|  |                 <type>pom</type> | ||||||
|  |                 <scope>import</scope> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- Warm-Flow国产工作流引擎, 在线文档:http://warm-flow.cn/ --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara.warm</groupId> | ||||||
|  |                 <artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId> | ||||||
|  |                 <version>${warm-flow.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara.warm</groupId> | ||||||
|  |                 <artifactId>warm-flow-plugin-ui-sb-web</artifactId> | ||||||
|  |                 <version>${warm-flow.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- JustAuth 的依赖配置--> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>me.zhyd.oauth</groupId> | ||||||
|  |                 <artifactId>JustAuth</artifactId> | ||||||
|  |                 <version>${justauth.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- common 的依赖配置--> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-bom</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |                 <type>pom</type> | ||||||
|  |                 <scope>import</scope> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.springdoc</groupId> | ||||||
|  |                 <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> | ||||||
|  |                 <version>${springdoc.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 补充SpringDoc UI模块依赖 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.springdoc</groupId> | ||||||
|  |                 <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> | ||||||
|  |                 <version>${springdoc.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.github.therapi</groupId> | ||||||
|  |                 <artifactId>therapi-runtime-javadoc</artifactId> | ||||||
|  |                 <version>${therapi-javadoc.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.projectlombok</groupId> | ||||||
|  |                 <artifactId>lombok</artifactId> | ||||||
|  |                 <version>${lombok.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.alibaba</groupId> | ||||||
|  |                 <artifactId>easyexcel</artifactId> | ||||||
|  |                 <version>${easyexcel.version}</version> | ||||||
|  |             </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-jsqlparser</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> | ||||||
|  |  | ||||||
|  |             <!--  AWS SDK for Java 2.x  --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>software.amazon.awssdk</groupId> | ||||||
|  |                 <artifactId>s3</artifactId> | ||||||
|  |                 <version>${aws.sdk.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |             <!-- 使用AWS基于 CRT 的 S3 客户端 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>software.amazon.awssdk.crt</groupId> | ||||||
|  |                 <artifactId>aws-crt</artifactId> | ||||||
|  |                 <version>${aws.crt.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |             <!-- 基于 AWS CRT 的 S3 客户端的性能增强的 S3 传输管理器 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>software.amazon.awssdk</groupId> | ||||||
|  |                 <artifactId>s3-transfer-manager</artifactId> | ||||||
|  |                 <version>${aws.sdk.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> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.baomidou</groupId> | ||||||
|  |                 <artifactId>lock4j-redisson-spring-boot-starter</artifactId> | ||||||
|  |                 <version>${lock4j.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- SnailJob Client --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.aizuda</groupId> | ||||||
|  |                 <artifactId>snail-job-client-starter</artifactId> | ||||||
|  |                 <version>${snailjob.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.aizuda</groupId> | ||||||
|  |                 <artifactId>snail-job-client-job-core</artifactId> | ||||||
|  |                 <version>${snailjob.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 加密包引入 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.bouncycastle</groupId> | ||||||
|  |                 <artifactId>bcprov-jdk15to18</artifactId> | ||||||
|  |                 <version>${bouncycastle.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>io.github.linpeilie</groupId> | ||||||
|  |                 <artifactId>mapstruct-plus-spring-boot-starter</artifactId> | ||||||
|  |                 <version>${mapstruct-plus.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 离线IP地址定位库 ip2region --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.lionsoul</groupId> | ||||||
|  |                 <artifactId>ip2region</artifactId> | ||||||
|  |                 <version>${ip2region.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>commons-io</groupId> | ||||||
|  |                 <artifactId>commons-io</artifactId> | ||||||
|  |                 <version>2.15.0</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>com.alibaba</groupId> | ||||||
|  |                 <artifactId>fastjson</artifactId> | ||||||
|  |                 <version>${fastjson.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-system</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-app</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-job</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-generator</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!--  工作流模块  --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-workflow</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- https://mvnrepository.com/artifact/org.locationtech.jts/jts-core --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.locationtech.jts</groupId> | ||||||
|  |                 <artifactId>jts-core</artifactId> | ||||||
|  |                 <version>${jts.version}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |         </dependencies> | ||||||
|  |     </dependencyManagement> | ||||||
|  |  | ||||||
|  |     <modules> | ||||||
|  |         <module>ruoyi-admin</module> | ||||||
|  |         <module>ruoyi-common</module> | ||||||
|  |         <module>ruoyi-extend</module> | ||||||
|  |         <module>ruoyi-modules</module> | ||||||
|  |     </modules> | ||||||
|  |     <packaging>pom</packaging> | ||||||
|  |  | ||||||
|  |     <build> | ||||||
|  |         <plugins> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
|  |                 <artifactId>maven-compiler-plugin</artifactId> | ||||||
|  |                 <version>${maven-compiler-plugin.version}</version> | ||||||
|  |                 <configuration> | ||||||
|  |                     <source>${java.version}</source> | ||||||
|  |                     <target>${java.version}</target> | ||||||
|  |                     <encoding>${project.build.sourceEncoding}</encoding> | ||||||
|  |                     <annotationProcessorPaths> | ||||||
|  |                         <path> | ||||||
|  |                             <groupId>com.github.therapi</groupId> | ||||||
|  |                             <artifactId>therapi-runtime-javadoc-scribe</artifactId> | ||||||
|  |                             <version>${therapi-javadoc.version}</version> | ||||||
|  |                         </path> | ||||||
|  |                         <path> | ||||||
|  |                             <groupId>org.projectlombok</groupId> | ||||||
|  |                             <artifactId>lombok</artifactId> | ||||||
|  |                             <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> | ||||||
|  |                             <groupId>org.projectlombok</groupId> | ||||||
|  |                             <artifactId>lombok-mapstruct-binding</artifactId> | ||||||
|  |                             <version>${mapstruct-plus.lombok.version}</version> | ||||||
|  |                         </path> | ||||||
|  |                     </annotationProcessorPaths> | ||||||
|  |                     <compilerArgs> | ||||||
|  |                         <arg>-parameters</arg> | ||||||
|  |                     </compilerArgs> | ||||||
|  |                 </configuration> | ||||||
|  |             </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> | ||||||
|  |         <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> | ||||||
|  |  | ||||||
|  |     <repositories> | ||||||
|  |         <repository> | ||||||
|  |             <id>public</id> | ||||||
|  |             <name>huawei nexus</name> | ||||||
|  |             <url>https://mirrors.huaweicloud.com/repository/maven/</url> | ||||||
|  |             <releases> | ||||||
|  |                 <enabled>true</enabled> | ||||||
|  |             </releases> | ||||||
|  |         </repository> | ||||||
|  |     </repositories> | ||||||
|  |  | ||||||
|  |     <pluginRepositories> | ||||||
|  |         <pluginRepository> | ||||||
|  |             <id>public</id> | ||||||
|  |             <name>huawei nexus</name> | ||||||
|  |             <url>https://mirrors.huaweicloud.com/repository/maven/</url> | ||||||
|  |             <releases> | ||||||
|  |                 <enabled>true</enabled> | ||||||
|  |             </releases> | ||||||
|  |             <snapshots> | ||||||
|  |                 <enabled>false</enabled> | ||||||
|  |             </snapshots> | ||||||
|  |         </pluginRepository> | ||||||
|  |     </pluginRepositories> | ||||||
|  |  | ||||||
|  | </project> | ||||||
|  |  | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								ruoyi-admin/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								ruoyi-admin/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | # 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/ | ||||||
|  | #FROM bellsoft/liberica-openjdk-debian:17.0.11-cds | ||||||
|  | FROM bellsoft/liberica-openjdk-debian:21.0.5-cds | ||||||
|  | #FROM findepi/graalvm:java17-native | ||||||
|  |  | ||||||
|  | LABEL maintainer="lilemy" | ||||||
|  |  | ||||||
|  | RUN mkdir -p /ruoyi/server/logs \ | ||||||
|  |     /ruoyi/server/temp \ | ||||||
|  |     /ruoyi/skywalking/agent | ||||||
|  |  | ||||||
|  | WORKDIR /ruoyi/server | ||||||
|  |  | ||||||
|  | ENV SERVER_PORT=8899 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="" | ||||||
|  |  | ||||||
|  | EXPOSE ${SERVER_PORT} | ||||||
|  |  | ||||||
|  | ADD ./target/ruoyi-admin.jar ./app.jar | ||||||
|  | # 工作流字体文件 | ||||||
|  | ADD ./zhFonts/ /usr/share/fonts/zhFonts/ | ||||||
|  |  | ||||||
|  | SHELL ["/bin/bash", "-c"] | ||||||
|  |  | ||||||
|  | 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 \ | ||||||
|  |            -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \ | ||||||
|  |            -jar app.jar | ||||||
|  |  | ||||||
							
								
								
									
										152
									
								
								ruoyi-admin/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								ruoyi-admin/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,152 @@ | |||||||
|  | <?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> | ||||||
|  |         <artifactId>xinnengyuan</artifactId> | ||||||
|  |         <groupId>org.dromara</groupId> | ||||||
|  |         <version>${revision}</version> | ||||||
|  |     </parent> | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |     <packaging>jar</packaging> | ||||||
|  |     <artifactId>ruoyi-admin</artifactId> | ||||||
|  |  | ||||||
|  |     <description> | ||||||
|  |         web服务入口 | ||||||
|  |     </description> | ||||||
|  |  | ||||||
|  |     <dependencies> | ||||||
|  |  | ||||||
|  |         <!-- Mysql驱动包 --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>com.mysql</groupId> | ||||||
|  |             <artifactId>mysql-connector-j</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  | <!--        <!– mp支持的数据库均支持 只需要增加对应的jdbc依赖即可 –>--> | ||||||
|  | <!--        <!– Oracle –>--> | ||||||
|  | <!--        <dependency>--> | ||||||
|  | <!--            <groupId>com.oracle.database.jdbc</groupId>--> | ||||||
|  | <!--            <artifactId>ojdbc8</artifactId>--> | ||||||
|  | <!--        </dependency>--> | ||||||
|  | <!--        <!– 兼容oracle低版本 –>--> | ||||||
|  | <!--        <dependency>--> | ||||||
|  | <!--            <groupId>com.oracle.database.nls</groupId>--> | ||||||
|  | <!--            <artifactId>orai18n</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> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-common-doc</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-common-social</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-common-ratelimiter</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-common-mail</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-system</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-app</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-job</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!-- 代码生成--> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-generator</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!--  工作流模块  --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.dromara</groupId> | ||||||
|  |             <artifactId>ruoyi-workflow</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>de.codecentric</groupId> | ||||||
|  |             <artifactId>spring-boot-admin-starter-client</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-test</artifactId> | ||||||
|  |             <scope>test</scope> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!-- skywalking 整合 logback --> | ||||||
|  | <!--        <dependency>--> | ||||||
|  | <!--            <groupId>org.apache.skywalking</groupId>--> | ||||||
|  | <!--            <artifactId>apm-toolkit-logback-1.x</artifactId>--> | ||||||
|  | <!--            <version>${与你的agent探针版本保持一致}</version>--> | ||||||
|  | <!--        </dependency>--> | ||||||
|  | <!--        <dependency>--> | ||||||
|  | <!--            <groupId>org.apache.skywalking</groupId>--> | ||||||
|  | <!--            <artifactId>apm-toolkit-trace</artifactId>--> | ||||||
|  | <!--            <version>${与你的agent探针版本保持一致}</version>--> | ||||||
|  | <!--        </dependency>--> | ||||||
|  |  | ||||||
|  |     </dependencies> | ||||||
|  |  | ||||||
|  |     <build> | ||||||
|  |         <finalName>${project.artifactId}</finalName> | ||||||
|  |         <plugins> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.springframework.boot</groupId> | ||||||
|  |                 <artifactId>spring-boot-maven-plugin</artifactId> | ||||||
|  |                 <version>${spring-boot.version}</version> | ||||||
|  |                 <executions> | ||||||
|  |                     <execution> | ||||||
|  |                         <goals> | ||||||
|  |                             <goal>repackage</goal> | ||||||
|  |                         </goals> | ||||||
|  |                     </execution> | ||||||
|  |                 </executions> | ||||||
|  |             </plugin> | ||||||
|  |             <plugin> | ||||||
|  |                 <groupId>org.apache.maven.plugins</groupId> | ||||||
|  |                 <artifactId>maven-jar-plugin</artifactId> | ||||||
|  |                 <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> | ||||||
|  |                     <failOnMissingWebXml>false</failOnMissingWebXml> | ||||||
|  |                     <warName>${project.artifactId}</warName> | ||||||
|  |                 </configuration> | ||||||
|  |             </plugin> | ||||||
|  |         </plugins> | ||||||
|  |     </build> | ||||||
|  |  | ||||||
|  | </project> | ||||||
| @ -0,0 +1,36 @@ | |||||||
|  | package org.dromara; | ||||||
|  |  | ||||||
|  | import org.springframework.boot.SpringApplication; | ||||||
|  | import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||||
|  | import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup; | ||||||
|  | import org.springframework.context.annotation.EnableAspectJAutoProxy; | ||||||
|  | import org.springframework.scheduling.annotation.EnableAsync; | ||||||
|  | import org.springframework.scheduling.annotation.EnableScheduling; | ||||||
|  | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; | ||||||
|  | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 启动程序 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @SpringBootApplication | ||||||
|  | @EnableAsync | ||||||
|  | @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) | ||||||
|  | @EnableScheduling | ||||||
|  | public class DromaraApplication implements WebMvcConfigurer { | ||||||
|  |  | ||||||
|  |     public static void main(String[] args) { | ||||||
|  |         SpringApplication application = new SpringApplication(DromaraApplication.class); | ||||||
|  |         application.setApplicationStartup(new BufferingApplicationStartup(2048)); | ||||||
|  |         application.run(args); | ||||||
|  |         System.out.println("(♥◠‿◠)ノ゙  RuoYi-Vue-Plus启动成功   ლ(´ڡ`ლ)゙"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void addResourceHandlers(ResourceHandlerRegistry registry) { | ||||||
|  |         registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); | ||||||
|  |         registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | package org.dromara; | ||||||
|  |  | ||||||
|  | import org.springframework.boot.builder.SpringApplicationBuilder; | ||||||
|  | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * web容器中进行部署 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | public class DromaraServletInitializer extends SpringBootServletInitializer { | ||||||
|  |     @Override | ||||||
|  |     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { | ||||||
|  |         return application.sources(DromaraApplication.class); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,239 @@ | |||||||
|  | package org.dromara.web.controller; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.annotation.SaIgnore; | ||||||
|  | import cn.dev33.satoken.exception.NotLoginException; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.codec.Base64; | ||||||
|  | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import jakarta.servlet.http.HttpServletRequest; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import me.zhyd.oauth.model.AuthResponse; | ||||||
|  | import me.zhyd.oauth.model.AuthUser; | ||||||
|  | import me.zhyd.oauth.request.AuthRequest; | ||||||
|  | import me.zhyd.oauth.utils.AuthStateUtils; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.domain.R; | ||||||
|  | import org.dromara.common.core.domain.model.LoginBody; | ||||||
|  | import org.dromara.common.core.domain.model.RegisterBody; | ||||||
|  | import org.dromara.common.core.domain.model.SocialLoginBody; | ||||||
|  | import org.dromara.common.core.utils.*; | ||||||
|  | import org.dromara.common.encrypt.annotation.ApiEncrypt; | ||||||
|  | import org.dromara.common.json.utils.JsonUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.social.config.properties.SocialLoginConfigProperties; | ||||||
|  | import org.dromara.common.social.config.properties.SocialProperties; | ||||||
|  | import org.dromara.common.social.utils.SocialUtils; | ||||||
|  | import org.dromara.common.sse.dto.SseMessageDto; | ||||||
|  | import org.dromara.common.sse.utils.SseMessageUtils; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.system.domain.bo.SysTenantBo; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.system.domain.vo.SysTenantVo; | ||||||
|  | import org.dromara.system.service.ISysClientService; | ||||||
|  | import org.dromara.system.service.ISysConfigService; | ||||||
|  | import org.dromara.system.service.ISysSocialService; | ||||||
|  | import org.dromara.system.service.ISysTenantService; | ||||||
|  | import org.dromara.web.domain.vo.LoginTenantVo; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  | import org.dromara.web.domain.vo.TenantListVo; | ||||||
|  | import org.dromara.web.service.IAuthStrategy; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.dromara.web.service.SysRegisterService; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  | import org.springframework.web.bind.annotation.*; | ||||||
|  |  | ||||||
|  | import java.net.URL; | ||||||
|  | import java.nio.charset.StandardCharsets; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.concurrent.ScheduledExecutorService; | ||||||
|  | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 认证 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @SaIgnore | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | @RestController | ||||||
|  | @RequestMapping("/auth") | ||||||
|  | public class AuthController { | ||||||
|  |  | ||||||
|  |     private final SocialProperties socialProperties; | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |     private final SysRegisterService registerService; | ||||||
|  |     private final ISysConfigService configService; | ||||||
|  |     private final ISysTenantService tenantService; | ||||||
|  |     private final ISysSocialService socialUserService; | ||||||
|  |     private final ISysClientService clientService; | ||||||
|  |     private final ScheduledExecutorService scheduledExecutorService; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录方法 | ||||||
|  |      * | ||||||
|  |      * @param body 登录信息 | ||||||
|  |      * @return 结果 | ||||||
|  |      */ | ||||||
|  |     @ApiEncrypt | ||||||
|  |     @PostMapping("/login") | ||||||
|  |     public R<LoginVo> login(@RequestBody String body) { | ||||||
|  |         LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class); | ||||||
|  |         ValidatorUtils.validate(loginBody); | ||||||
|  |         // 授权类型和客户端id | ||||||
|  |         String clientId = loginBody.getClientId(); | ||||||
|  |         String grantType = loginBody.getGrantType(); | ||||||
|  |         SysClientVo client = clientService.queryByClientId(clientId); | ||||||
|  |         // 查询不到 client 或 client 内不包含 grantType | ||||||
|  |         if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { | ||||||
|  |             log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType); | ||||||
|  |             return R.fail(MessageUtils.message("auth.grant.type.error")); | ||||||
|  |         } else if (!SystemConstants.NORMAL.equals(client.getStatus())) { | ||||||
|  |             return R.fail(MessageUtils.message("auth.grant.type.blocked")); | ||||||
|  |         } | ||||||
|  |         // 校验租户 | ||||||
|  |         loginService.checkTenant(loginBody.getTenantId()); | ||||||
|  |         // 登录 | ||||||
|  |         LoginVo loginVo = IAuthStrategy.login(body, client, grantType); | ||||||
|  |  | ||||||
|  |         Long userId = LoginHelper.getUserId(); | ||||||
|  |         scheduledExecutorService.schedule(() -> { | ||||||
|  |             SseMessageDto dto = new SseMessageDto(); | ||||||
|  |             dto.setMessage("欢迎登录新能源项目管理系统"); | ||||||
|  |             dto.setUserIds(List.of(userId)); | ||||||
|  |             SseMessageUtils.publishMessage(dto); | ||||||
|  |         }, 5, TimeUnit.SECONDS); | ||||||
|  |         return R.ok(loginVo); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取跳转URL | ||||||
|  |      * | ||||||
|  |      * @param source 登录来源 | ||||||
|  |      * @return 结果 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/binding/{source}") | ||||||
|  |     public R<String> authBinding(@PathVariable("source") String source, | ||||||
|  |                                  @RequestParam String tenantId, @RequestParam String domain) { | ||||||
|  |         SocialLoginConfigProperties obj = socialProperties.getType().get(source); | ||||||
|  |         if (ObjectUtil.isNull(obj)) { | ||||||
|  |             return R.fail(source + "平台账号暂不支持"); | ||||||
|  |         } | ||||||
|  |         AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties); | ||||||
|  |         Map<String, String> map = new HashMap<>(); | ||||||
|  |         map.put("tenantId", tenantId); | ||||||
|  |         map.put("domain", domain); | ||||||
|  |         map.put("state", AuthStateUtils.createState()); | ||||||
|  |         String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8)); | ||||||
|  |         return R.ok("操作成功", authorizeUrl); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 前端回调绑定授权(需要token) | ||||||
|  |      * | ||||||
|  |      * @param loginBody 请求体 | ||||||
|  |      * @return 结果 | ||||||
|  |      */ | ||||||
|  |     @PostMapping("/social/callback") | ||||||
|  |     public R<Void> socialCallback(@RequestBody SocialLoginBody loginBody) { | ||||||
|  |         // 校验token | ||||||
|  |         StpUtil.checkLogin(); | ||||||
|  |         // 获取第三方登录信息 | ||||||
|  |         AuthResponse<AuthUser> response = SocialUtils.loginAuth( | ||||||
|  |                 loginBody.getSource(), loginBody.getSocialCode(), | ||||||
|  |                 loginBody.getSocialState(), socialProperties); | ||||||
|  |         AuthUser authUserData = response.getData(); | ||||||
|  |         // 判断授权响应是否成功 | ||||||
|  |         if (!response.ok()) { | ||||||
|  |             return R.fail(response.getMsg()); | ||||||
|  |         } | ||||||
|  |         loginService.socialRegister(authUserData); | ||||||
|  |         return R.ok(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 取消授权(需要token) | ||||||
|  |      * | ||||||
|  |      * @param socialId socialId | ||||||
|  |      */ | ||||||
|  |     @DeleteMapping(value = "/unlock/{socialId}") | ||||||
|  |     public R<Void> unlockSocial(@PathVariable Long socialId) { | ||||||
|  |         // 校验token | ||||||
|  |         StpUtil.checkLogin(); | ||||||
|  |         Boolean rows = socialUserService.deleteWithValidById(socialId); | ||||||
|  |         return rows ? R.ok() : R.fail("取消授权失败"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 退出登录 | ||||||
|  |      */ | ||||||
|  |     @PostMapping("/logout") | ||||||
|  |     public R<Void> logout() { | ||||||
|  |         loginService.logout(); | ||||||
|  |         return R.ok("退出成功"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户注册 | ||||||
|  |      */ | ||||||
|  |     @ApiEncrypt | ||||||
|  |     @PostMapping("/register") | ||||||
|  |     public R<Void> register(@Validated @RequestBody RegisterBody user) { | ||||||
|  |         if (!configService.selectRegisterEnabled(user.getTenantId())) { | ||||||
|  |             return R.fail("当前系统没有开启注册功能!"); | ||||||
|  |         } | ||||||
|  |         registerService.register(user); | ||||||
|  |         return R.ok(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录页面租户下拉框 | ||||||
|  |      * | ||||||
|  |      * @return 租户列表 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/tenant/list") | ||||||
|  |     public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception { | ||||||
|  |         // 返回对象 | ||||||
|  |         LoginTenantVo result = new LoginTenantVo(); | ||||||
|  |         boolean enable = TenantHelper.isEnable(); | ||||||
|  |         result.setTenantEnabled(enable); | ||||||
|  |         // 如果未开启租户这直接返回 | ||||||
|  |         if (!enable) { | ||||||
|  |             return R.ok(result); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo()); | ||||||
|  |         List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class); | ||||||
|  |         try { | ||||||
|  |             // 如果只超管返回所有租户 | ||||||
|  |             if (LoginHelper.isSuperAdmin()) { | ||||||
|  |                 result.setVoList(voList); | ||||||
|  |                 return R.ok(result); | ||||||
|  |             } | ||||||
|  |         } catch (NotLoginException ignored) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 获取域名 | ||||||
|  |         String host; | ||||||
|  |         String referer = request.getHeader("referer"); | ||||||
|  |         if (StringUtils.isNotBlank(referer)) { | ||||||
|  |             // 这里从referer中取值是为了本地使用hosts添加虚拟域名,方便本地环境调试 | ||||||
|  |             host = referer.split("//")[1].split("/")[0]; | ||||||
|  |         } else { | ||||||
|  |             host = new URL(request.getRequestURL().toString()).getHost(); | ||||||
|  |         } | ||||||
|  |         // 根据域名进行筛选 | ||||||
|  |         List<TenantListVo> list = StreamUtils.filter(voList, vo -> | ||||||
|  |             StringUtils.equalsIgnoreCase(vo.getDomain(), host)); | ||||||
|  |         result.setVoList(CollUtil.isNotEmpty(list) ? list : voList); | ||||||
|  |         return R.ok(result); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,136 @@ | |||||||
|  | package org.dromara.web.controller; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.annotation.SaIgnore; | ||||||
|  | import cn.hutool.captcha.AbstractCaptcha; | ||||||
|  | import cn.hutool.captcha.generator.CodeGenerator; | ||||||
|  | import cn.hutool.core.util.IdUtil; | ||||||
|  | import cn.hutool.core.util.RandomUtil; | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.constant.GlobalConstants; | ||||||
|  | import org.dromara.common.core.domain.R; | ||||||
|  | import org.dromara.common.core.utils.SpringUtils; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.core.utils.reflect.ReflectUtils; | ||||||
|  | import org.dromara.common.mail.config.properties.MailProperties; | ||||||
|  | import org.dromara.common.mail.utils.MailUtils; | ||||||
|  | import org.dromara.common.ratelimiter.annotation.RateLimiter; | ||||||
|  | import org.dromara.common.ratelimiter.enums.LimitType; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.web.config.properties.CaptchaProperties; | ||||||
|  | import org.dromara.common.web.enums.CaptchaType; | ||||||
|  | import org.dromara.sms4j.api.SmsBlend; | ||||||
|  | import org.dromara.sms4j.api.entity.SmsResponse; | ||||||
|  | import org.dromara.sms4j.core.factory.SmsFactory; | ||||||
|  | import org.dromara.web.domain.vo.CaptchaVo; | ||||||
|  | import org.springframework.expression.Expression; | ||||||
|  | import org.springframework.expression.ExpressionParser; | ||||||
|  | import org.springframework.expression.spel.standard.SpelExpressionParser; | ||||||
|  | import org.springframework.validation.annotation.Validated; | ||||||
|  | import org.springframework.web.bind.annotation.GetMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
|  | import java.time.Duration; | ||||||
|  | import java.util.LinkedHashMap; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 验证码操作处理 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @SaIgnore | ||||||
|  | @Slf4j | ||||||
|  | @Validated | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | @RestController | ||||||
|  | public class CaptchaController { | ||||||
|  |  | ||||||
|  |     private final CaptchaProperties captchaProperties; | ||||||
|  |     private final MailProperties mailProperties; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 短信验证码 | ||||||
|  |      * | ||||||
|  |      * @param phonenumber 用户手机号 | ||||||
|  |      */ | ||||||
|  |     @RateLimiter(key = "#phonenumber", time = 60, count = 1) | ||||||
|  |     @GetMapping("/resource/sms/code") | ||||||
|  |     public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) { | ||||||
|  |         String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber; | ||||||
|  |         String code = RandomUtil.randomNumbers(4); | ||||||
|  |         RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); | ||||||
|  |         // 验证码模板id 自行处理 (查数据库或写死均可) | ||||||
|  |         String templateId = ""; | ||||||
|  |         LinkedHashMap<String, String> map = new LinkedHashMap<>(1); | ||||||
|  |         map.put("code", code); | ||||||
|  |         SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); | ||||||
|  |         SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map); | ||||||
|  |         if (!smsResponse.isSuccess()) { | ||||||
|  |             log.error("验证码短信发送异常 => {}", smsResponse); | ||||||
|  |             return R.fail(smsResponse.getData().toString()); | ||||||
|  |         } | ||||||
|  |         return R.ok(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 邮箱验证码 | ||||||
|  |      * | ||||||
|  |      * @param email 邮箱 | ||||||
|  |      */ | ||||||
|  |     @RateLimiter(key = "#email", time = 60, count = 1) | ||||||
|  |     @GetMapping("/resource/email/code") | ||||||
|  |     public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) { | ||||||
|  |         if (!mailProperties.getEnabled()) { | ||||||
|  |             return R.fail("当前系统没有开启邮箱功能!"); | ||||||
|  |         } | ||||||
|  |         String key = GlobalConstants.CAPTCHA_CODE_KEY + email; | ||||||
|  |         String code = RandomUtil.randomNumbers(4); | ||||||
|  |         RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); | ||||||
|  |         try { | ||||||
|  |             MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。"); | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             log.error("验证码短信发送异常 => {}", e.getMessage()); | ||||||
|  |             return R.fail(e.getMessage()); | ||||||
|  |         } | ||||||
|  |         return R.ok(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 生成验证码 | ||||||
|  |      */ | ||||||
|  |     @RateLimiter(time = 60, count = 10, limitType = LimitType.IP) | ||||||
|  |     @GetMapping("/auth/code") | ||||||
|  |     public R<CaptchaVo> getCode() { | ||||||
|  |         CaptchaVo captchaVo = new CaptchaVo(); | ||||||
|  |         boolean captchaEnabled = captchaProperties.getEnable(); | ||||||
|  |         if (!captchaEnabled) { | ||||||
|  |             captchaVo.setCaptchaEnabled(false); | ||||||
|  |             return R.ok(captchaVo); | ||||||
|  |         } | ||||||
|  |         // 保存验证码信息 | ||||||
|  |         String uuid = IdUtil.simpleUUID(); | ||||||
|  |         String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid; | ||||||
|  |         // 生成验证码 | ||||||
|  |         CaptchaType captchaType = captchaProperties.getType(); | ||||||
|  |         boolean isMath = CaptchaType.MATH == captchaType; | ||||||
|  |         Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength(); | ||||||
|  |         CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length); | ||||||
|  |         AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz()); | ||||||
|  |         captcha.setGenerator(codeGenerator); | ||||||
|  |         captcha.createCode(); | ||||||
|  |         // 如果是数学验证码,使用SpEL表达式处理验证码结果 | ||||||
|  |         String code = captcha.getCode(); | ||||||
|  |         if (isMath) { | ||||||
|  |             ExpressionParser parser = new SpelExpressionParser(); | ||||||
|  |             Expression exp = parser.parseExpression(StringUtils.remove(code, "=")); | ||||||
|  |             code = exp.getValue(String.class); | ||||||
|  |         } | ||||||
|  |         RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); | ||||||
|  |         captchaVo.setUuid(uuid); | ||||||
|  |         captchaVo.setImg(captcha.getImageBase64()); | ||||||
|  |         return R.ok(captchaVo); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,32 @@ | |||||||
|  | package org.dromara.web.controller; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.annotation.SaIgnore; | ||||||
|  | import org.dromara.common.core.config.RuoYiConfig; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.springframework.web.bind.annotation.GetMapping; | ||||||
|  | import org.springframework.web.bind.annotation.RestController; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 首页 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @SaIgnore | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | @RestController | ||||||
|  | public class IndexController { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 系统基础配置 | ||||||
|  |      */ | ||||||
|  |     private final RuoYiConfig ruoyiConfig; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 访问首页,提示语 | ||||||
|  |      */ | ||||||
|  |     @GetMapping("/") | ||||||
|  |     public String index() { | ||||||
|  |         return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | package org.dromara.web.domain.vo; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 验证码信息 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class CaptchaVo { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否开启验证码 | ||||||
|  |      */ | ||||||
|  |     private Boolean captchaEnabled = true; | ||||||
|  |  | ||||||
|  |     private String uuid; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 验证码图片 | ||||||
|  |      */ | ||||||
|  |     private String img; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,25 @@ | |||||||
|  | package org.dromara.web.domain.vo; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登录租户对象 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class LoginTenantVo { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户开关 | ||||||
|  |      */ | ||||||
|  |     private Boolean tenantEnabled; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户对象列表 | ||||||
|  |      */ | ||||||
|  |     private List<TenantListVo> voList; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,54 @@ | |||||||
|  | package org.dromara.web.domain.vo; | ||||||
|  |  | ||||||
|  | import com.fasterxml.jackson.annotation.JsonProperty; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登录验证信息 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class LoginVo { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 授权令牌 | ||||||
|  |      */ | ||||||
|  |     @JsonProperty("access_token") | ||||||
|  |     private String accessToken; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 刷新令牌 | ||||||
|  |      */ | ||||||
|  |     @JsonProperty("refresh_token") | ||||||
|  |     private String refreshToken; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 授权令牌 access_token 的有效期 | ||||||
|  |      */ | ||||||
|  |     @JsonProperty("expire_in") | ||||||
|  |     private Long expireIn; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 刷新令牌 refresh_token 的有效期 | ||||||
|  |      */ | ||||||
|  |     @JsonProperty("refresh_expire_in") | ||||||
|  |     private Long refreshExpireIn; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 应用id | ||||||
|  |      */ | ||||||
|  |     @JsonProperty("client_id") | ||||||
|  |     private String clientId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 令牌权限 | ||||||
|  |      */ | ||||||
|  |     private String scope; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户 openid | ||||||
|  |      */ | ||||||
|  |     private String openid; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | package org.dromara.web.domain.vo; | ||||||
|  |  | ||||||
|  | import org.dromara.system.domain.vo.SysTenantVo; | ||||||
|  | import io.github.linpeilie.annotations.AutoMapper; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 租户列表 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @AutoMapper(target = SysTenantVo.class) | ||||||
|  | public class TenantListVo { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户编号 | ||||||
|  |      */ | ||||||
|  |     private String tenantId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 企业名称 | ||||||
|  |      */ | ||||||
|  |     private String companyName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 域名 | ||||||
|  |      */ | ||||||
|  |     private String domain; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,165 @@ | |||||||
|  | package org.dromara.web.listener; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.config.SaTokenConfig; | ||||||
|  | import cn.dev33.satoken.listener.SaTokenListener; | ||||||
|  | import cn.dev33.satoken.stp.SaLoginModel; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.convert.Convert; | ||||||
|  | import cn.hutool.http.useragent.UserAgent; | ||||||
|  | import cn.hutool.http.useragent.UserAgentUtil; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.core.constant.CacheConstants; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.domain.dto.UserOnlineDTO; | ||||||
|  | import org.dromara.common.core.utils.MessageUtils; | ||||||
|  | import org.dromara.common.core.utils.ServletUtils; | ||||||
|  | import org.dromara.common.core.utils.SpringUtils; | ||||||
|  | import org.dromara.common.core.utils.ip.AddressUtils; | ||||||
|  | import org.dromara.common.log.event.LogininforEvent; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.springframework.stereotype.Component; | ||||||
|  |  | ||||||
|  | import java.time.Duration; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户行为 侦听器的实现 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | @Component | ||||||
|  | @Slf4j | ||||||
|  | public class UserActionListener implements SaTokenListener { | ||||||
|  |  | ||||||
|  |     private final SaTokenConfig tokenConfig; | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次登录时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) { | ||||||
|  |         UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); | ||||||
|  |         String ip = ServletUtils.getClientIP(); | ||||||
|  |         UserOnlineDTO dto = new UserOnlineDTO(); | ||||||
|  |         dto.setIpaddr(ip); | ||||||
|  |         dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); | ||||||
|  |         dto.setBrowser(userAgent.getBrowser().getName()); | ||||||
|  |         dto.setOs(userAgent.getOs().getName()); | ||||||
|  |         dto.setLoginTime(System.currentTimeMillis()); | ||||||
|  |         dto.setTokenId(tokenValue); | ||||||
|  |         String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY); | ||||||
|  |         String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY); | ||||||
|  |         dto.setUserName(username); | ||||||
|  |         dto.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY)); | ||||||
|  |         dto.setDeviceType(loginModel.getDevice()); | ||||||
|  |         dto.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY)); | ||||||
|  |         TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             if(tokenConfig.getTimeout() == -1) { | ||||||
|  |                 RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); | ||||||
|  |             } else { | ||||||
|  |                 RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout())); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |         // 记录登录日志 | ||||||
|  |         LogininforEvent logininforEvent = new LogininforEvent(); | ||||||
|  |         logininforEvent.setTenantId(tenantId); | ||||||
|  |         logininforEvent.setUsername(username); | ||||||
|  |         logininforEvent.setStatus(Constants.LOGIN_SUCCESS); | ||||||
|  |         logininforEvent.setMessage(MessageUtils.message("user.login.success")); | ||||||
|  |         logininforEvent.setRequest(ServletUtils.getRequest()); | ||||||
|  |         SpringUtils.context().publishEvent(logininforEvent); | ||||||
|  |         // 更新登录信息 | ||||||
|  |         loginService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip); | ||||||
|  |         log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次注销时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doLogout(String loginType, Object loginId, String tokenValue) { | ||||||
|  |         String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); | ||||||
|  |         TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); | ||||||
|  |         }); | ||||||
|  |         log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次被踢下线时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doKickout(String loginType, Object loginId, String tokenValue) { | ||||||
|  |         String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); | ||||||
|  |         TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); | ||||||
|  |         }); | ||||||
|  |         log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次被顶下线时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doReplaced(String loginType, Object loginId, String tokenValue) { | ||||||
|  |         String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); | ||||||
|  |         TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); | ||||||
|  |         }); | ||||||
|  |         log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次被封禁时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次被解封时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doUntieDisable(String loginType, Object loginId, String service) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次打开二级认证时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次创建Session时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doCloseSafe(String loginType, String tokenValue, String service) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次创建Session时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doCreateSession(String id) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次注销Session时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doLogoutSession(String id) { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每次Token续期时触发 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public void doRenewTimeout(String tokenValue, Object loginId, long timeout) { | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | package org.dromara.web.service; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
|  | import org.dromara.common.core.utils.SpringUtils; | ||||||
|  | import org.dromara.system.domain.SysClient; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 授权策略 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | public interface IAuthStrategy { | ||||||
|  |  | ||||||
|  |     String BASE_NAME = "AuthStrategy"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录 | ||||||
|  |      * | ||||||
|  |      * @param body      登录对象 | ||||||
|  |      * @param client    授权管理视图对象 | ||||||
|  |      * @param grantType 授权类型 | ||||||
|  |      * @return 登录验证信息 | ||||||
|  |      */ | ||||||
|  |     static LoginVo login(String body, SysClientVo client, String grantType) { | ||||||
|  |         // 授权类型和客户端id | ||||||
|  |         String beanName = grantType + BASE_NAME; | ||||||
|  |         if (!SpringUtils.containsBean(beanName)) { | ||||||
|  |             throw new ServiceException("授权类型不正确!"); | ||||||
|  |         } | ||||||
|  |         IAuthStrategy instance = SpringUtils.getBean(beanName); | ||||||
|  |         return instance.login(body, client); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录 | ||||||
|  |      * | ||||||
|  |      * @param body   登录对象 | ||||||
|  |      * @param client 授权管理视图对象 | ||||||
|  |      * @return 登录验证信息 | ||||||
|  |      */ | ||||||
|  |     LoginVo login(String body, SysClientVo client); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,251 @@ | |||||||
|  | package org.dromara.web.service; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.exception.NotLoginException; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.bean.BeanUtil; | ||||||
|  | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import cn.hutool.core.lang.Opt; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import com.baomidou.lock.annotation.Lock4j; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import me.zhyd.oauth.model.AuthUser; | ||||||
|  | import org.dromara.common.core.constant.CacheConstants; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.constant.TenantConstants; | ||||||
|  | import org.dromara.common.core.domain.dto.PostDTO; | ||||||
|  | import org.dromara.common.core.domain.dto.RoleDTO; | ||||||
|  | import org.dromara.common.core.domain.model.LoginUser; | ||||||
|  | import org.dromara.common.core.enums.LoginType; | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
|  | import org.dromara.common.core.exception.user.UserException; | ||||||
|  | import org.dromara.common.core.utils.*; | ||||||
|  | import org.dromara.common.log.event.LogininforEvent; | ||||||
|  | import org.dromara.common.mybatis.helper.DataPermissionHelper; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.tenant.exception.TenantException; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.system.domain.SysUser; | ||||||
|  | import org.dromara.system.domain.bo.SysSocialBo; | ||||||
|  | import org.dromara.system.domain.vo.*; | ||||||
|  | import org.dromara.system.mapper.SysUserMapper; | ||||||
|  | import org.dromara.system.service.*; | ||||||
|  | import org.springframework.beans.factory.annotation.Value; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | import java.time.Duration; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.function.Supplier; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登录校验方法 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | @Slf4j | ||||||
|  | @Service | ||||||
|  | public class SysLoginService { | ||||||
|  |  | ||||||
|  |     @Value("${user.password.maxRetryCount}") | ||||||
|  |     private Integer maxRetryCount; | ||||||
|  |  | ||||||
|  |     @Value("${user.password.lockTime}") | ||||||
|  |     private Integer lockTime; | ||||||
|  |  | ||||||
|  |     private final ISysTenantService tenantService; | ||||||
|  |     private final ISysPermissionService permissionService; | ||||||
|  |     private final ISysSocialService sysSocialService; | ||||||
|  |     private final ISysRoleService roleService; | ||||||
|  |     private final ISysDeptService deptService; | ||||||
|  |     private final ISysPostService postService; | ||||||
|  |     private final SysUserMapper userMapper; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 绑定第三方用户 | ||||||
|  |      * | ||||||
|  |      * @param authUserData 授权响应实体 | ||||||
|  |      */ | ||||||
|  |     @Lock4j | ||||||
|  |     public void socialRegister(AuthUser authUserData) { | ||||||
|  |         String authId = authUserData.getSource() + authUserData.getUuid(); | ||||||
|  |         // 第三方用户信息 | ||||||
|  |         SysSocialBo bo = BeanUtil.toBean(authUserData, SysSocialBo.class); | ||||||
|  |         BeanUtil.copyProperties(authUserData.getToken(), bo); | ||||||
|  |         Long userId = LoginHelper.getUserId(); | ||||||
|  |         bo.setUserId(userId); | ||||||
|  |         bo.setAuthId(authId); | ||||||
|  |         bo.setOpenId(authUserData.getUuid()); | ||||||
|  |         bo.setUserName(authUserData.getUsername()); | ||||||
|  |         bo.setNickName(authUserData.getNickname()); | ||||||
|  |         List<SysSocialVo> checkList = sysSocialService.selectByAuthId(authId); | ||||||
|  |         if (CollUtil.isNotEmpty(checkList)) { | ||||||
|  |             throw new ServiceException("此三方账号已经被绑定!"); | ||||||
|  |         } | ||||||
|  |         // 查询是否已经绑定用户 | ||||||
|  |         SysSocialBo params = new SysSocialBo(); | ||||||
|  |         params.setUserId(userId); | ||||||
|  |         params.setSource(bo.getSource()); | ||||||
|  |         List<SysSocialVo> list = sysSocialService.queryList(params); | ||||||
|  |         if (CollUtil.isEmpty(list)) { | ||||||
|  |             // 没有绑定用户, 新增用户信息 | ||||||
|  |             sysSocialService.insertByBo(bo); | ||||||
|  |         } else { | ||||||
|  |             // 更新用户信息 | ||||||
|  |             bo.setId(list.get(0).getId()); | ||||||
|  |             sysSocialService.updateByBo(bo); | ||||||
|  |             // 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断 | ||||||
|  |             // throw new ServiceException("此平台账号已经被绑定!"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 退出登录 | ||||||
|  |      */ | ||||||
|  |     public void logout() { | ||||||
|  |         try { | ||||||
|  |             LoginUser loginUser = LoginHelper.getLoginUser(); | ||||||
|  |             if (ObjectUtil.isNull(loginUser)) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) { | ||||||
|  |                 // 超级管理员 登出清除动态租户 | ||||||
|  |                 TenantHelper.clearDynamic(); | ||||||
|  |             } | ||||||
|  |             recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success")); | ||||||
|  |         } catch (NotLoginException ignored) { | ||||||
|  |         } finally { | ||||||
|  |             try { | ||||||
|  |                 StpUtil.logout(); | ||||||
|  |             } catch (NotLoginException ignored) { | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录登录信息 | ||||||
|  |      * | ||||||
|  |      * @param tenantId 租户ID | ||||||
|  |      * @param username 用户名 | ||||||
|  |      * @param status   状态 | ||||||
|  |      * @param message  消息内容 | ||||||
|  |      */ | ||||||
|  |     public void recordLogininfor(String tenantId, String username, String status, String message) { | ||||||
|  |         LogininforEvent logininforEvent = new LogininforEvent(); | ||||||
|  |         logininforEvent.setTenantId(tenantId); | ||||||
|  |         logininforEvent.setUsername(username); | ||||||
|  |         logininforEvent.setStatus(status); | ||||||
|  |         logininforEvent.setMessage(message); | ||||||
|  |         logininforEvent.setRequest(ServletUtils.getRequest()); | ||||||
|  |         SpringUtils.context().publishEvent(logininforEvent); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 构建登录用户 | ||||||
|  |      */ | ||||||
|  |     public LoginUser buildLoginUser(SysUserVo user) { | ||||||
|  |         LoginUser loginUser = new LoginUser(); | ||||||
|  |         Long userId = user.getUserId(); | ||||||
|  |         loginUser.setTenantId(user.getTenantId()); | ||||||
|  |         loginUser.setUserId(userId); | ||||||
|  |         loginUser.setDeptId(user.getDeptId()); | ||||||
|  |         loginUser.setUsername(user.getUserName()); | ||||||
|  |         loginUser.setNickname(user.getNickName()); | ||||||
|  |         loginUser.setUserType(user.getUserType()); | ||||||
|  |         loginUser.setMenuPermission(permissionService.getMenuPermission(userId)); | ||||||
|  |         loginUser.setRolePermission(permissionService.getRolePermission(userId)); | ||||||
|  |         if (ObjectUtil.isNotNull(user.getDeptId())) { | ||||||
|  |             Opt<SysDeptVo> deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); | ||||||
|  |             loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); | ||||||
|  |             loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); | ||||||
|  |         } | ||||||
|  |         List<SysRoleVo> roles = roleService.selectRolesByUserId(userId); | ||||||
|  |         List<SysPostVo> posts = postService.selectPostsByUserId(userId); | ||||||
|  |         loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); | ||||||
|  |         loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class)); | ||||||
|  |         return loginUser; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录登录信息 | ||||||
|  |      * | ||||||
|  |      * @param userId 用户ID | ||||||
|  |      */ | ||||||
|  |     public void recordLoginInfo(Long userId, String ip) { | ||||||
|  |         SysUser sysUser = new SysUser(); | ||||||
|  |         sysUser.setUserId(userId); | ||||||
|  |         sysUser.setLoginIp(ip); | ||||||
|  |         sysUser.setLoginDate(DateUtils.getNowDate()); | ||||||
|  |         sysUser.setUpdateBy(userId); | ||||||
|  |         DataPermissionHelper.ignore(() -> userMapper.updateById(sysUser)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录校验 | ||||||
|  |      */ | ||||||
|  |     public void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) { | ||||||
|  |         String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username; | ||||||
|  |         String loginFail = Constants.LOGIN_FAIL; | ||||||
|  |  | ||||||
|  |         // 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip) | ||||||
|  |         int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0); | ||||||
|  |         // 锁定时间内登录 则踢出 | ||||||
|  |         if (errorNumber >= maxRetryCount) { | ||||||
|  |             recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime)); | ||||||
|  |             throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (supplier.get()) { | ||||||
|  |             // 错误次数递增 | ||||||
|  |             errorNumber++; | ||||||
|  |             RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime)); | ||||||
|  |             // 达到规定错误次数 则锁定登录 | ||||||
|  |             if (errorNumber >= maxRetryCount) { | ||||||
|  |                 recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime)); | ||||||
|  |                 throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); | ||||||
|  |             } else { | ||||||
|  |                 // 未达到规定错误次数 | ||||||
|  |                 recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber)); | ||||||
|  |                 throw new UserException(loginType.getRetryLimitCount(), errorNumber); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // 登录成功 清空错误次数 | ||||||
|  |         RedisUtils.deleteObject(errorKey); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验租户 | ||||||
|  |      * | ||||||
|  |      * @param tenantId 租户ID | ||||||
|  |      */ | ||||||
|  |     public void checkTenant(String tenantId) { | ||||||
|  |         if (!TenantHelper.isEnable()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         if (StringUtils.isBlank(tenantId)) { | ||||||
|  |             throw new TenantException("tenant.number.not.blank"); | ||||||
|  |         } | ||||||
|  |         if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         SysTenantVo tenant = tenantService.queryByTenantId(tenantId); | ||||||
|  |         if (ObjectUtil.isNull(tenant)) { | ||||||
|  |             log.info("登录租户:{} 不存在.", tenantId); | ||||||
|  |             throw new TenantException("tenant.not.exists"); | ||||||
|  |         } else if (SystemConstants.DISABLE.equals(tenant.getStatus())) { | ||||||
|  |             log.info("登录租户:{} 已被停用.", tenantId); | ||||||
|  |             throw new TenantException("tenant.blocked"); | ||||||
|  |         } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) | ||||||
|  |             && new Date().after(tenant.getExpireTime())) { | ||||||
|  |             log.info("登录租户:{} 已超过有效期.", tenantId); | ||||||
|  |             throw new TenantException("tenant.expired"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,120 @@ | |||||||
|  | package org.dromara.web.service; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.secure.BCrypt; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.constant.GlobalConstants; | ||||||
|  | import org.dromara.common.core.domain.model.RegisterBody; | ||||||
|  | import org.dromara.common.core.enums.UserType; | ||||||
|  | import org.dromara.common.core.exception.user.CaptchaException; | ||||||
|  | import org.dromara.common.core.exception.user.CaptchaExpireException; | ||||||
|  | import org.dromara.common.core.exception.user.UserException; | ||||||
|  | import org.dromara.common.core.utils.MessageUtils; | ||||||
|  | import org.dromara.common.core.utils.ServletUtils; | ||||||
|  | import org.dromara.common.core.utils.SpringUtils; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.log.event.LogininforEvent; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.common.web.config.properties.CaptchaProperties; | ||||||
|  | import org.dromara.system.domain.SysUser; | ||||||
|  | import org.dromara.system.domain.bo.SysUserBo; | ||||||
|  | import org.dromara.system.mapper.SysUserMapper; | ||||||
|  | import org.dromara.system.service.ISysUserService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 注册校验方法 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | @Service | ||||||
|  | public class SysRegisterService { | ||||||
|  |  | ||||||
|  |     private final ISysUserService userService; | ||||||
|  |     private final SysUserMapper userMapper; | ||||||
|  |     private final CaptchaProperties captchaProperties; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 注册 | ||||||
|  |      */ | ||||||
|  |     public void register(RegisterBody registerBody) { | ||||||
|  |         String tenantId = registerBody.getTenantId(); | ||||||
|  |         String username = registerBody.getUsername(); | ||||||
|  |         String password = registerBody.getPassword(); | ||||||
|  |         // 校验用户类型是否存在 | ||||||
|  |         String userType = UserType.getUserType(registerBody.getUserType()).getUserType(); | ||||||
|  |         // 校验密码是否符合要求 | ||||||
|  |         String pattern = "^(?!.*\\s)(?!^[a-zA-Z]+$)(?!^[0-9]+$)(?!^[^a-zA-Z0-9]+$)(?!^[a-zA-Z0-9]+$).{8,18}$"; | ||||||
|  |         boolean isValid = password.matches(pattern); | ||||||
|  |         if (!isValid) { | ||||||
|  |             throw new UserException("注册失败,密码需满足8–18位,包含大小写字母、数字、特殊字符中的至少三种组合"); | ||||||
|  |         } | ||||||
|  |         boolean captchaEnabled = captchaProperties.getEnable(); | ||||||
|  |         // 验证码开关 | ||||||
|  |         if (captchaEnabled) { | ||||||
|  |             validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid()); | ||||||
|  |         } | ||||||
|  |         SysUserBo sysUser = new SysUserBo(); | ||||||
|  |         sysUser.setUserName(username); | ||||||
|  |         sysUser.setNickName(username); | ||||||
|  |         sysUser.setPassword(BCrypt.hashpw(password)); | ||||||
|  |         sysUser.setUserType(userType); | ||||||
|  |  | ||||||
|  |         boolean exist = TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             return userMapper.exists(new LambdaQueryWrapper<SysUser>() | ||||||
|  |                 .eq(SysUser::getUserName, sysUser.getUserName())); | ||||||
|  |         }); | ||||||
|  |         if (exist) { | ||||||
|  |             throw new UserException("user.register.save.error", username); | ||||||
|  |         } | ||||||
|  |         boolean regFlag = userService.registerUser(sysUser, tenantId); | ||||||
|  |         if (!regFlag) { | ||||||
|  |             throw new UserException("user.register.error"); | ||||||
|  |         } | ||||||
|  |         recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success")); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验验证码 | ||||||
|  |      * | ||||||
|  |      * @param username 用户名 | ||||||
|  |      * @param code     验证码 | ||||||
|  |      * @param uuid     唯一标识 | ||||||
|  |      */ | ||||||
|  |     public void validateCaptcha(String tenantId, String username, String code, String uuid) { | ||||||
|  |         String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, ""); | ||||||
|  |         String captcha = RedisUtils.getCacheObject(verifyKey); | ||||||
|  |         RedisUtils.deleteObject(verifyKey); | ||||||
|  |         if (captcha == null) { | ||||||
|  |             recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); | ||||||
|  |             throw new CaptchaExpireException(); | ||||||
|  |         } | ||||||
|  |         if (!code.equalsIgnoreCase(captcha)) { | ||||||
|  |             recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); | ||||||
|  |             throw new CaptchaException(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 记录登录信息 | ||||||
|  |      * | ||||||
|  |      * @param tenantId 租户ID | ||||||
|  |      * @param username 用户名 | ||||||
|  |      * @param status   状态 | ||||||
|  |      * @param message  消息内容 | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     private void recordLogininfor(String tenantId, String username, String status, String message) { | ||||||
|  |         LogininforEvent logininforEvent = new LogininforEvent(); | ||||||
|  |         logininforEvent.setTenantId(tenantId); | ||||||
|  |         logininforEvent.setUsername(username); | ||||||
|  |         logininforEvent.setStatus(status); | ||||||
|  |         logininforEvent.setMessage(message); | ||||||
|  |         logininforEvent.setRequest(ServletUtils.getRequest()); | ||||||
|  |         SpringUtils.context().publishEvent(logininforEvent); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,102 @@ | |||||||
|  | package org.dromara.web.service.impl; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.stp.SaLoginModel; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.constant.GlobalConstants; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.domain.model.EmailLoginBody; | ||||||
|  | import org.dromara.common.core.domain.model.LoginUser; | ||||||
|  | import org.dromara.common.core.enums.LoginType; | ||||||
|  | import org.dromara.common.core.exception.user.CaptchaExpireException; | ||||||
|  | import org.dromara.common.core.exception.user.UserException; | ||||||
|  | import org.dromara.common.core.utils.MessageUtils; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.core.utils.ValidatorUtils; | ||||||
|  | import org.dromara.common.json.utils.JsonUtils; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.system.domain.SysUser; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.system.domain.vo.SysUserVo; | ||||||
|  | import org.dromara.system.mapper.SysUserMapper; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  | import org.dromara.web.service.IAuthStrategy; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 邮件认证策略 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Service("email" + IAuthStrategy.BASE_NAME) | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | public class EmailAuthStrategy implements IAuthStrategy { | ||||||
|  |  | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |     private final SysUserMapper userMapper; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LoginVo login(String body, SysClientVo client) { | ||||||
|  |         EmailLoginBody loginBody = JsonUtils.parseObject(body, EmailLoginBody.class); | ||||||
|  |         ValidatorUtils.validate(loginBody); | ||||||
|  |         String tenantId = loginBody.getTenantId(); | ||||||
|  |         String email = loginBody.getEmail(); | ||||||
|  |         String emailCode = loginBody.getEmailCode(); | ||||||
|  |         LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             SysUserVo user = loadUserByEmail(email); | ||||||
|  |             loginService.checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode)); | ||||||
|  |             // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 | ||||||
|  |             return loginService.buildLoginUser(user); | ||||||
|  |         }); | ||||||
|  |         loginUser.setClientKey(client.getClientKey()); | ||||||
|  |         loginUser.setDeviceType(client.getDeviceType()); | ||||||
|  |         SaLoginModel model = new SaLoginModel(); | ||||||
|  |         model.setDevice(client.getDeviceType()); | ||||||
|  |         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 | ||||||
|  |         // 例如: 后台用户30分钟过期 app用户1天过期 | ||||||
|  |         model.setTimeout(client.getTimeout()); | ||||||
|  |         model.setActiveTimeout(client.getActiveTimeout()); | ||||||
|  |         model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); | ||||||
|  |         // 生成token | ||||||
|  |         LoginHelper.login(loginUser, model); | ||||||
|  |  | ||||||
|  |         LoginVo loginVo = new LoginVo(); | ||||||
|  |         loginVo.setAccessToken(StpUtil.getTokenValue()); | ||||||
|  |         loginVo.setExpireIn(StpUtil.getTokenTimeout()); | ||||||
|  |         loginVo.setClientId(client.getClientId()); | ||||||
|  |         return loginVo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验邮箱验证码 | ||||||
|  |      */ | ||||||
|  |     private boolean validateEmailCode(String tenantId, String email, String emailCode) { | ||||||
|  |         String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + email); | ||||||
|  |         if (StringUtils.isBlank(code)) { | ||||||
|  |             loginService.recordLogininfor(tenantId, email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); | ||||||
|  |             throw new CaptchaExpireException(); | ||||||
|  |         } | ||||||
|  |         return code.equals(emailCode); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private SysUserVo loadUserByEmail(String email) { | ||||||
|  |         SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, email)); | ||||||
|  |         if (ObjectUtil.isNull(user)) { | ||||||
|  |             log.info("登录用户:{} 不存在.", email); | ||||||
|  |             throw new UserException("user.not.exists", email); | ||||||
|  |         } else if (SystemConstants.DISABLE.equals(user.getStatus())) { | ||||||
|  |             log.info("登录用户:{} 已被停用.", email); | ||||||
|  |             throw new UserException("user.blocked", email); | ||||||
|  |         } | ||||||
|  |         return user; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,123 @@ | |||||||
|  | package org.dromara.web.service.impl; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.secure.BCrypt; | ||||||
|  | import cn.dev33.satoken.stp.SaLoginModel; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.constant.GlobalConstants; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.domain.model.LoginUser; | ||||||
|  | import org.dromara.common.core.domain.model.PasswordLoginBody; | ||||||
|  | import org.dromara.common.core.enums.LoginType; | ||||||
|  | import org.dromara.common.core.exception.user.CaptchaException; | ||||||
|  | import org.dromara.common.core.exception.user.CaptchaExpireException; | ||||||
|  | import org.dromara.common.core.exception.user.UserException; | ||||||
|  | import org.dromara.common.core.utils.MessageUtils; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.core.utils.ValidatorUtils; | ||||||
|  | import org.dromara.common.json.utils.JsonUtils; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.common.web.config.properties.CaptchaProperties; | ||||||
|  | import org.dromara.system.domain.SysUser; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.system.domain.vo.SysUserVo; | ||||||
|  | import org.dromara.system.mapper.SysUserMapper; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  | import org.dromara.web.service.IAuthStrategy; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 密码认证策略 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Service("password" + IAuthStrategy.BASE_NAME) | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | public class PasswordAuthStrategy implements IAuthStrategy { | ||||||
|  |  | ||||||
|  |     private final CaptchaProperties captchaProperties; | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |     private final SysUserMapper userMapper; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LoginVo login(String body, SysClientVo client) { | ||||||
|  |         PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class); | ||||||
|  |         ValidatorUtils.validate(loginBody); | ||||||
|  |         String tenantId = loginBody.getTenantId(); | ||||||
|  |         String username = loginBody.getUsername(); | ||||||
|  |         String password = loginBody.getPassword(); | ||||||
|  |         String code = loginBody.getCode(); | ||||||
|  |         String uuid = loginBody.getUuid(); | ||||||
|  |  | ||||||
|  |         boolean captchaEnabled = captchaProperties.getEnable(); | ||||||
|  |         // 验证码开关 | ||||||
|  |         if (captchaEnabled) { | ||||||
|  |             validateCaptcha(tenantId, username, code, uuid); | ||||||
|  |         } | ||||||
|  |         LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             SysUserVo user = loadUserByUsername(username); | ||||||
|  |             loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword())); | ||||||
|  |             // 此处可根据登录用户的数据不同 自行创建 loginUser | ||||||
|  |             return loginService.buildLoginUser(user); | ||||||
|  |         }); | ||||||
|  |         loginUser.setClientKey(client.getClientKey()); | ||||||
|  |         loginUser.setDeviceType(client.getDeviceType()); | ||||||
|  |         SaLoginModel model = new SaLoginModel(); | ||||||
|  |         model.setDevice(client.getDeviceType()); | ||||||
|  |         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 | ||||||
|  |         // 例如: 后台用户30分钟过期 app用户1天过期 | ||||||
|  |         model.setTimeout(client.getTimeout()); | ||||||
|  |         model.setActiveTimeout(client.getActiveTimeout()); | ||||||
|  |         model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); | ||||||
|  |         // 生成token | ||||||
|  |         LoginHelper.login(loginUser, model); | ||||||
|  |  | ||||||
|  |         LoginVo loginVo = new LoginVo(); | ||||||
|  |         loginVo.setAccessToken(StpUtil.getTokenValue()); | ||||||
|  |         loginVo.setExpireIn(StpUtil.getTokenTimeout()); | ||||||
|  |         loginVo.setClientId(client.getClientId()); | ||||||
|  |         return loginVo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验验证码 | ||||||
|  |      * | ||||||
|  |      * @param username 用户名 | ||||||
|  |      * @param code     验证码 | ||||||
|  |      * @param uuid     唯一标识 | ||||||
|  |      */ | ||||||
|  |     private void validateCaptcha(String tenantId, String username, String code, String uuid) { | ||||||
|  |         String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, ""); | ||||||
|  |         String captcha = RedisUtils.getCacheObject(verifyKey); | ||||||
|  |         RedisUtils.deleteObject(verifyKey); | ||||||
|  |         if (captcha == null) { | ||||||
|  |             loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); | ||||||
|  |             throw new CaptchaExpireException(); | ||||||
|  |         } | ||||||
|  |         if (!code.equalsIgnoreCase(captcha)) { | ||||||
|  |             loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); | ||||||
|  |             throw new CaptchaException(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private SysUserVo loadUserByUsername(String username) { | ||||||
|  |         SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, username)); | ||||||
|  |         if (ObjectUtil.isNull(user)) { | ||||||
|  |             log.info("登录用户:{} 不存在.", username); | ||||||
|  |             throw new UserException("user.not.exists", username); | ||||||
|  |         } else if (SystemConstants.DISABLE.equals(user.getStatus())) { | ||||||
|  |             log.info("登录用户:{} 已被停用.", username); | ||||||
|  |             throw new UserException("user.blocked", username); | ||||||
|  |         } | ||||||
|  |         return user; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,102 @@ | |||||||
|  | package org.dromara.web.service.impl; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.stp.SaLoginModel; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.core.constant.Constants; | ||||||
|  | import org.dromara.common.core.constant.GlobalConstants; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.domain.model.LoginUser; | ||||||
|  | import org.dromara.common.core.domain.model.SmsLoginBody; | ||||||
|  | import org.dromara.common.core.enums.LoginType; | ||||||
|  | import org.dromara.common.core.exception.user.CaptchaExpireException; | ||||||
|  | import org.dromara.common.core.exception.user.UserException; | ||||||
|  | import org.dromara.common.core.utils.MessageUtils; | ||||||
|  | import org.dromara.common.core.utils.StringUtils; | ||||||
|  | import org.dromara.common.core.utils.ValidatorUtils; | ||||||
|  | import org.dromara.common.json.utils.JsonUtils; | ||||||
|  | import org.dromara.common.redis.utils.RedisUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.system.domain.SysUser; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.system.domain.vo.SysUserVo; | ||||||
|  | import org.dromara.system.mapper.SysUserMapper; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  | import org.dromara.web.service.IAuthStrategy; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 短信认证策略 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Service("sms" + IAuthStrategy.BASE_NAME) | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | public class SmsAuthStrategy implements IAuthStrategy { | ||||||
|  |  | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |     private final SysUserMapper userMapper; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LoginVo login(String body, SysClientVo client) { | ||||||
|  |         SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class); | ||||||
|  |         ValidatorUtils.validate(loginBody); | ||||||
|  |         String tenantId = loginBody.getTenantId(); | ||||||
|  |         String phonenumber = loginBody.getPhonenumber(); | ||||||
|  |         String smsCode = loginBody.getSmsCode(); | ||||||
|  |         LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { | ||||||
|  |             SysUserVo user = loadUserByPhonenumber(phonenumber); | ||||||
|  |             loginService.checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode)); | ||||||
|  |             // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 | ||||||
|  |             return loginService.buildLoginUser(user); | ||||||
|  |         }); | ||||||
|  |         loginUser.setClientKey(client.getClientKey()); | ||||||
|  |         loginUser.setDeviceType(client.getDeviceType()); | ||||||
|  |         SaLoginModel model = new SaLoginModel(); | ||||||
|  |         model.setDevice(client.getDeviceType()); | ||||||
|  |         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 | ||||||
|  |         // 例如: 后台用户30分钟过期 app用户1天过期 | ||||||
|  |         model.setTimeout(client.getTimeout()); | ||||||
|  |         model.setActiveTimeout(client.getActiveTimeout()); | ||||||
|  |         model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); | ||||||
|  |         // 生成token | ||||||
|  |         LoginHelper.login(loginUser, model); | ||||||
|  |  | ||||||
|  |         LoginVo loginVo = new LoginVo(); | ||||||
|  |         loginVo.setAccessToken(StpUtil.getTokenValue()); | ||||||
|  |         loginVo.setExpireIn(StpUtil.getTokenTimeout()); | ||||||
|  |         loginVo.setClientId(client.getClientId()); | ||||||
|  |         return loginVo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 校验短信验证码 | ||||||
|  |      */ | ||||||
|  |     private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) { | ||||||
|  |         String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber); | ||||||
|  |         if (StringUtils.isBlank(code)) { | ||||||
|  |             loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); | ||||||
|  |             throw new CaptchaExpireException(); | ||||||
|  |         } | ||||||
|  |         return code.equals(smsCode); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private SysUserVo loadUserByPhonenumber(String phonenumber) { | ||||||
|  |         SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, phonenumber)); | ||||||
|  |         if (ObjectUtil.isNull(user)) { | ||||||
|  |             log.info("登录用户:{} 不存在.", phonenumber); | ||||||
|  |             throw new UserException("user.not.exists", phonenumber); | ||||||
|  |         } else if (SystemConstants.DISABLE.equals(user.getStatus())) { | ||||||
|  |             log.info("登录用户:{} 已被停用.", phonenumber); | ||||||
|  |             throw new UserException("user.blocked", phonenumber); | ||||||
|  |         } | ||||||
|  |         return user; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,131 @@ | |||||||
|  | package org.dromara.web.service.impl; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.stp.SaLoginModel; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.collection.CollUtil; | ||||||
|  | import cn.hutool.core.map.MapUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import cn.hutool.http.HttpUtil; | ||||||
|  | import cn.hutool.http.Method; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import me.zhyd.oauth.model.AuthResponse; | ||||||
|  | import me.zhyd.oauth.model.AuthUser; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.domain.model.LoginUser; | ||||||
|  | import org.dromara.common.core.domain.model.SocialLoginBody; | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
|  | import org.dromara.common.core.exception.user.UserException; | ||||||
|  | import org.dromara.common.core.utils.StreamUtils; | ||||||
|  | import org.dromara.common.core.utils.ValidatorUtils; | ||||||
|  | import org.dromara.common.json.utils.JsonUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.common.social.config.properties.SocialProperties; | ||||||
|  | import org.dromara.common.social.utils.SocialUtils; | ||||||
|  | import org.dromara.common.tenant.helper.TenantHelper; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.system.domain.vo.SysSocialVo; | ||||||
|  | import org.dromara.system.domain.vo.SysUserVo; | ||||||
|  | import org.dromara.system.mapper.SysUserMapper; | ||||||
|  | import org.dromara.system.service.ISysSocialService; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  | import org.dromara.web.service.IAuthStrategy; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Optional; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 第三方授权策略 | ||||||
|  |  * | ||||||
|  |  * @author thiszhc is 三三 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Service("social" + IAuthStrategy.BASE_NAME) | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | public class SocialAuthStrategy implements IAuthStrategy { | ||||||
|  |  | ||||||
|  |     private final SocialProperties socialProperties; | ||||||
|  |     private final ISysSocialService sysSocialService; | ||||||
|  |     private final SysUserMapper userMapper; | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录-第三方授权登录 | ||||||
|  |      * | ||||||
|  |      * @param body     登录信息 | ||||||
|  |      * @param client   客户端信息 | ||||||
|  |      */ | ||||||
|  |     @Override | ||||||
|  |     public LoginVo login(String body, SysClientVo client) { | ||||||
|  |         SocialLoginBody loginBody = JsonUtils.parseObject(body, SocialLoginBody.class); | ||||||
|  |         ValidatorUtils.validate(loginBody); | ||||||
|  |         AuthResponse<AuthUser> response = SocialUtils.loginAuth( | ||||||
|  |                 loginBody.getSource(), loginBody.getSocialCode(), | ||||||
|  |                 loginBody.getSocialState(), socialProperties); | ||||||
|  |         if (!response.ok()) { | ||||||
|  |             throw new ServiceException(response.getMsg()); | ||||||
|  |         } | ||||||
|  |         AuthUser authUserData = response.getData(); | ||||||
|  |         if ("GITEE".equals(authUserData.getSource())) { | ||||||
|  |             // 如用户使用 gitee 登录顺手 star 给作者一点支持 拒绝白嫖 | ||||||
|  |             HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Vue-Plus") | ||||||
|  |                     .formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken())) | ||||||
|  |                     .executeAsync(); | ||||||
|  |             HttpUtil.createRequest(Method.PUT, "https://gitee.com/api/v5/user/starred/dromara/RuoYi-Cloud-Plus") | ||||||
|  |                     .formStr(MapUtil.of("access_token", authUserData.getToken().getAccessToken())) | ||||||
|  |                     .executeAsync(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         List<SysSocialVo> list = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); | ||||||
|  |         if (CollUtil.isEmpty(list)) { | ||||||
|  |             throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!"); | ||||||
|  |         } | ||||||
|  |         SysSocialVo social; | ||||||
|  |         if (TenantHelper.isEnable()) { | ||||||
|  |             Optional<SysSocialVo> opt = StreamUtils.findAny(list, x -> x.getTenantId().equals(loginBody.getTenantId())); | ||||||
|  |             if (opt.isEmpty()) { | ||||||
|  |                 throw new ServiceException("对不起,你没有权限登录当前租户!"); | ||||||
|  |             } | ||||||
|  |             social = opt.get(); | ||||||
|  |         } else { | ||||||
|  |             social = list.get(0); | ||||||
|  |         } | ||||||
|  |         LoginUser loginUser = TenantHelper.dynamic(social.getTenantId(), () -> { | ||||||
|  |             SysUserVo user = loadUser(social.getUserId()); | ||||||
|  |             // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 | ||||||
|  |             return loginService.buildLoginUser(user); | ||||||
|  |         }); | ||||||
|  |         loginUser.setClientKey(client.getClientKey()); | ||||||
|  |         loginUser.setDeviceType(client.getDeviceType()); | ||||||
|  |         SaLoginModel model = new SaLoginModel(); | ||||||
|  |         model.setDevice(client.getDeviceType()); | ||||||
|  |         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 | ||||||
|  |         // 例如: 后台用户30分钟过期 app用户1天过期 | ||||||
|  |         model.setTimeout(client.getTimeout()); | ||||||
|  |         model.setActiveTimeout(client.getActiveTimeout()); | ||||||
|  |         model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); | ||||||
|  |         // 生成token | ||||||
|  |         LoginHelper.login(loginUser, model); | ||||||
|  |  | ||||||
|  |         LoginVo loginVo = new LoginVo(); | ||||||
|  |         loginVo.setAccessToken(StpUtil.getTokenValue()); | ||||||
|  |         loginVo.setExpireIn(StpUtil.getTokenTimeout()); | ||||||
|  |         loginVo.setClientId(client.getClientId()); | ||||||
|  |         return loginVo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private SysUserVo loadUser(Long userId) { | ||||||
|  |         SysUserVo user = userMapper.selectVoById(userId); | ||||||
|  |         if (ObjectUtil.isNull(user)) { | ||||||
|  |             log.info("登录用户:{} 不存在.", ""); | ||||||
|  |             throw new UserException("user.not.exists", ""); | ||||||
|  |         } else if (SystemConstants.DISABLE.equals(user.getStatus())) { | ||||||
|  |             log.info("登录用户:{} 已被停用.", ""); | ||||||
|  |             throw new UserException("user.blocked", ""); | ||||||
|  |         } | ||||||
|  |         return user; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,111 @@ | |||||||
|  | package org.dromara.web.service.impl; | ||||||
|  |  | ||||||
|  | import cn.dev33.satoken.stp.SaLoginModel; | ||||||
|  | import cn.dev33.satoken.stp.StpUtil; | ||||||
|  | import cn.hutool.core.util.ObjectUtil; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import me.zhyd.oauth.config.AuthConfig; | ||||||
|  | import me.zhyd.oauth.model.AuthCallback; | ||||||
|  | import me.zhyd.oauth.model.AuthResponse; | ||||||
|  | import me.zhyd.oauth.model.AuthToken; | ||||||
|  | import me.zhyd.oauth.model.AuthUser; | ||||||
|  | import me.zhyd.oauth.request.AuthRequest; | ||||||
|  | import me.zhyd.oauth.request.AuthWechatMiniProgramRequest; | ||||||
|  | import org.dromara.common.core.constant.SystemConstants; | ||||||
|  | import org.dromara.common.core.domain.model.XcxLoginBody; | ||||||
|  | import org.dromara.common.core.domain.model.XcxLoginUser; | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
|  | import org.dromara.common.core.utils.ValidatorUtils; | ||||||
|  | import org.dromara.common.json.utils.JsonUtils; | ||||||
|  | import org.dromara.common.satoken.utils.LoginHelper; | ||||||
|  | import org.dromara.system.domain.vo.SysClientVo; | ||||||
|  | import org.dromara.system.domain.vo.SysUserVo; | ||||||
|  | import org.dromara.web.domain.vo.LoginVo; | ||||||
|  | import org.dromara.web.service.IAuthStrategy; | ||||||
|  | import org.dromara.web.service.SysLoginService; | ||||||
|  | import org.springframework.stereotype.Service; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 小程序认证策略 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @Service("xcx" + IAuthStrategy.BASE_NAME) | ||||||
|  | @RequiredArgsConstructor | ||||||
|  | public class XcxAuthStrategy implements IAuthStrategy { | ||||||
|  |  | ||||||
|  |     private final SysLoginService loginService; | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public LoginVo login(String body, SysClientVo client) { | ||||||
|  |         XcxLoginBody loginBody = JsonUtils.parseObject(body, XcxLoginBody.class); | ||||||
|  |         ValidatorUtils.validate(loginBody); | ||||||
|  |         // xcxCode 为 小程序调用 wx.login 授权后获取 | ||||||
|  |         String xcxCode = loginBody.getXcxCode(); | ||||||
|  |         // 多个小程序识别使用 | ||||||
|  |         String appid = loginBody.getAppid(); | ||||||
|  |  | ||||||
|  |         // 校验 appid + appsrcret + xcxCode 调用登录凭证校验接口 获取 session_key 与 openid | ||||||
|  |         AuthRequest authRequest = new AuthWechatMiniProgramRequest(AuthConfig.builder() | ||||||
|  |             .clientId(appid).clientSecret("自行填写密钥 可根据不同appid填入不同密钥") | ||||||
|  |             .ignoreCheckRedirectUri(true).ignoreCheckState(true).build()); | ||||||
|  |         AuthCallback authCallback = new AuthCallback(); | ||||||
|  |         authCallback.setCode(xcxCode); | ||||||
|  |         AuthResponse<AuthUser> resp = authRequest.login(authCallback); | ||||||
|  |         String openid, unionId; | ||||||
|  |         if (resp.ok()) { | ||||||
|  |             AuthToken token = resp.getData().getToken(); | ||||||
|  |             openid = token.getOpenId(); | ||||||
|  |             // 微信小程序只有关联到微信开放平台下之后才能获取到 unionId,因此unionId不一定能返回。 | ||||||
|  |             unionId = token.getUnionId(); | ||||||
|  |         } else { | ||||||
|  |             throw new ServiceException(resp.getMsg()); | ||||||
|  |         } | ||||||
|  |         // 框架登录不限制从什么表查询 只要最终构建出 LoginUser 即可 | ||||||
|  |         SysUserVo user = loadUserByOpenid(openid); | ||||||
|  |         // 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了 | ||||||
|  |         XcxLoginUser loginUser = new XcxLoginUser(); | ||||||
|  |         loginUser.setTenantId(user.getTenantId()); | ||||||
|  |         loginUser.setUserId(user.getUserId()); | ||||||
|  |         loginUser.setUsername(user.getUserName()); | ||||||
|  |         loginUser.setNickname(user.getNickName()); | ||||||
|  |         loginUser.setUserType(user.getUserType()); | ||||||
|  |         loginUser.setClientKey(client.getClientKey()); | ||||||
|  |         loginUser.setDeviceType(client.getDeviceType()); | ||||||
|  |         loginUser.setOpenid(openid); | ||||||
|  |  | ||||||
|  |         SaLoginModel model = new SaLoginModel(); | ||||||
|  |         model.setDevice(client.getDeviceType()); | ||||||
|  |         // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置 | ||||||
|  |         // 例如: 后台用户30分钟过期 app用户1天过期 | ||||||
|  |         model.setTimeout(client.getTimeout()); | ||||||
|  |         model.setActiveTimeout(client.getActiveTimeout()); | ||||||
|  |         model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); | ||||||
|  |         // 生成token | ||||||
|  |         LoginHelper.login(loginUser, model); | ||||||
|  |  | ||||||
|  |         LoginVo loginVo = new LoginVo(); | ||||||
|  |         loginVo.setAccessToken(StpUtil.getTokenValue()); | ||||||
|  |         loginVo.setExpireIn(StpUtil.getTokenTimeout()); | ||||||
|  |         loginVo.setClientId(client.getClientId()); | ||||||
|  |         loginVo.setOpenid(openid); | ||||||
|  |         return loginVo; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private SysUserVo loadUserByOpenid(String openid) { | ||||||
|  |         // 使用 openid 查询绑定用户 如未绑定用户 则根据业务自行处理 例如 创建默认用户 | ||||||
|  |         // todo 自行实现 userService.selectUserByOpenid(openid); | ||||||
|  |         SysUserVo user = new SysUserVo(); | ||||||
|  |         if (ObjectUtil.isNull(user)) { | ||||||
|  |             log.info("登录用户:{} 不存在.", openid); | ||||||
|  |             // todo 用户不存在 业务逻辑自行实现 | ||||||
|  |         } else if (SystemConstants.DISABLE.equals(user.getStatus())) { | ||||||
|  |             log.info("登录用户:{} 已被停用.", openid); | ||||||
|  |             // todo 用户已被停用 业务逻辑自行实现 | ||||||
|  |         } | ||||||
|  |         return user; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										290
									
								
								ruoyi-admin/src/main/resources/application-dev.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								ruoyi-admin/src/main/resources/application-dev.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,290 @@ | |||||||
|  | --- # 监控中心配置 | ||||||
|  | spring.boot.admin.client: | ||||||
|  |   # 增加客户端开关 | ||||||
|  |   enabled: false | ||||||
|  |   url: http://192.168.110.119:9090/admin | ||||||
|  |   instance: | ||||||
|  |     service-host-type: IP | ||||||
|  |     metadata: | ||||||
|  |       username: ${spring.boot.admin.client.username} | ||||||
|  |       userpassword: ${spring.boot.admin.client.password} | ||||||
|  |   username: @monitor.username@ | ||||||
|  |   password: @monitor.password@ | ||||||
|  |  | ||||||
|  | --- # snail-job 配置 | ||||||
|  | snail-job: | ||||||
|  |   enabled: false | ||||||
|  |   # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 | ||||||
|  |   group: "ruoyi_group" | ||||||
|  |   # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config` 表 | ||||||
|  |   token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" | ||||||
|  |   server: | ||||||
|  |     host: 192.168.110.119 | ||||||
|  |     port: 17888 | ||||||
|  |   # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 | ||||||
|  |   namespace: ${spring.profiles.active} | ||||||
|  |   # 随主应用端口漂移 | ||||||
|  |   port: 2${server.port} | ||||||
|  |   # 客户端ip指定 | ||||||
|  |   host: | ||||||
|  |   # RPC类型: netty, grpc | ||||||
|  |   rpc-type: grpc | ||||||
|  |  | ||||||
|  | --- # 数据源配置 | ||||||
|  | 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://192.168.110.2:13386/xinnengyuandev?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 | ||||||
|  |           username: xinnengyuandev | ||||||
|  |           password: StRWCZdZirysNSs2 | ||||||
|  |       #        # 从库数据源 | ||||||
|  |       #        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&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=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: 192.168.110.2 | ||||||
|  |     # 端口,默认为6379 | ||||||
|  |     port: 9287 | ||||||
|  |     # 数据库索引 | ||||||
|  |     database: 10 | ||||||
|  |     # redis 密码必须配置 | ||||||
|  |     password: syar23rdsaagdrsa | ||||||
|  |     # 连接超时时间 | ||||||
|  |     timeout: 10s | ||||||
|  |     # 是否开启ssl | ||||||
|  |     ssl.enabled: false | ||||||
|  |  | ||||||
|  | # redisson 配置 | ||||||
|  | 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://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用 | ||||||
|  | sms: | ||||||
|  |   # 配置源类型用于标定配置来源(interface,yaml) | ||||||
|  |   config-type: yaml | ||||||
|  |   # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制 | ||||||
|  |   restricted: true | ||||||
|  |   # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效 | ||||||
|  |   minute-max: 1 | ||||||
|  |   # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效 | ||||||
|  |   account-max: 30 | ||||||
|  |   # 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中 | ||||||
|  |   blends: | ||||||
|  |     # 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可 | ||||||
|  |     # 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户 | ||||||
|  |     config1: | ||||||
|  |       # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 | ||||||
|  |       supplier: alibaba | ||||||
|  |       # 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。 | ||||||
|  |       access-key-id: 您的accessKey | ||||||
|  |       # 称为accessSecret有些称之为apiSecret | ||||||
|  |       access-key-secret: 您的accessKeySecret | ||||||
|  |       signature: 您的短信签名 | ||||||
|  |       sdk-app-id: 您的sdkAppId | ||||||
|  |     config2: | ||||||
|  |       # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 | ||||||
|  |       supplier: tencent | ||||||
|  |       access-key-id: 您的accessKey | ||||||
|  |       access-key-secret: 您的accessKeySecret | ||||||
|  |       signature: 您的短信签名 | ||||||
|  |       sdk-app-id: 您的sdkAppId | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- # 三方授权 | ||||||
|  | justauth: | ||||||
|  |   # 前端外网访问地址 | ||||||
|  |   address: http://localhost:80 | ||||||
|  |   type: | ||||||
|  |     maxkey: | ||||||
|  |       # maxkey 服务器地址 | ||||||
|  |       # 注意 如下均配置均不需要修改 maxkey 已经内置好了数据 | ||||||
|  |       server-url: http://sso.maxkey.top | ||||||
|  |       client-id: 876892492581044224 | ||||||
|  |       client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=maxkey | ||||||
|  |     topiam: | ||||||
|  |       # topiam 服务器地址 | ||||||
|  |       server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol | ||||||
|  |       client-id: 449c4*********937************759 | ||||||
|  |       client-secret: ac7***********1e0************28d | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=topiam | ||||||
|  |       scopes: [ openid, email, phone, profile ] | ||||||
|  |     qq: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=qq | ||||||
|  |       union-id: false | ||||||
|  |     weibo: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=weibo | ||||||
|  |     gitee: | ||||||
|  |       client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98 | ||||||
|  |       client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=gitee | ||||||
|  |     dingtalk: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=dingtalk | ||||||
|  |     baidu: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=baidu | ||||||
|  |     csdn: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=csdn | ||||||
|  |     coding: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=coding | ||||||
|  |       coding-group-name: xx | ||||||
|  |     oschina: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=oschina | ||||||
|  |     alipay_wallet: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet | ||||||
|  |       alipay-public-key: MIIB**************DAQAB | ||||||
|  |     wechat_open: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=wechat_open | ||||||
|  |     wechat_mp: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=wechat_mp | ||||||
|  |     wechat_enterprise: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise | ||||||
|  |       agent-id: 1000002 | ||||||
|  |     gitlab: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=gitlab | ||||||
|  | # 和风天气 https://dev.qweather.com/ | ||||||
|  | weather: | ||||||
|  |   key-id: T65EAABUXC | ||||||
|  |   project-id: 2JTHPUQ5YY | ||||||
|  |   private-key: MC4CAQAwBQYDK2VwBCIEIMAglX7IsxYiTeM+FXXnvCUsIggajeP4s8gAllewm6BN | ||||||
|  |   api-host: n35rk53njv.re.qweatherapi.com | ||||||
|  | # dxf转 geojson 执行文件名 | ||||||
|  | dxf2GeoJson: | ||||||
|  |   file-name: main.exe | ||||||
|  | ys7: | ||||||
|  |   app-key: 3acf9f1a43dc4209841e0893003db0a2 | ||||||
|  |   app-secret: 4bbf3e9394f55d3af6e3af27b2d3db36 | ||||||
|  | #ys7: | ||||||
|  | #  app-key: 081b0d6d5f7f4de8bc5c7fa350fb26ec | ||||||
|  | #  app-secret: caa37b9f60ef02deb57e563bc190e6db | ||||||
|  | # 斯巴达算法 | ||||||
|  | sparta: | ||||||
|  |   url: http://119.3.204.120:8040 | ||||||
|  |   client-id: test | ||||||
|  |   client-secret: 115fcb08fa6742a1b086d9bb80a6ad59 | ||||||
|  | # 身份证加密密钥(32 位) | ||||||
|  | id-card: | ||||||
|  |   encrypt-key: 7ae260d150a14027d2238a1cf80a48ef | ||||||
|  | recognizer: | ||||||
|  |   url: http://192.168.110.5:50070 | ||||||
							
								
								
									
										289
									
								
								ruoyi-admin/src/main/resources/application-prod.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								ruoyi-admin/src/main/resources/application-prod.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,289 @@ | |||||||
|  | --- # 临时文件存储位置 避免临时文件被系统清理报错 | ||||||
|  | spring.servlet.multipart.location: /ruoyi/server/temp | ||||||
|  |  | ||||||
|  | --- # 监控中心配置 | ||||||
|  | spring.boot.admin.client: | ||||||
|  |   # 增加客户端开关 | ||||||
|  |   enabled: false | ||||||
|  |   url: http://localhost:9090/admin | ||||||
|  |   instance: | ||||||
|  |     service-host-type: IP | ||||||
|  |     metadata: | ||||||
|  |       username: ${spring.boot.admin.client.username} | ||||||
|  |       userpassword: ${spring.boot.admin.client.password} | ||||||
|  |   username: @monitor.username@ | ||||||
|  |   password: @monitor.password@ | ||||||
|  |  | ||||||
|  | --- # snail-job 配置 | ||||||
|  | snail-job: | ||||||
|  |   enabled: false | ||||||
|  |   # 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务 | ||||||
|  |   group: "ruoyi_group" | ||||||
|  |   # SnailJob 接入验证令牌 详见 script/sql/ry_job.sql `sj_group_config`表 | ||||||
|  |   token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" | ||||||
|  |   server: | ||||||
|  |     host: 127.0.0.1 | ||||||
|  |     port: 17888 | ||||||
|  |   # 命名空间UUID 详见 script/sql/ry_job.sql `sj_namespace`表`unique_id`字段 | ||||||
|  |   namespace: ${spring.profiles.active} | ||||||
|  |   # 随主应用端口漂移 | ||||||
|  |   port: 2${server.port} | ||||||
|  |   # 客户端ip指定 | ||||||
|  |   host: | ||||||
|  |   # RPC类型: netty, grpc | ||||||
|  |   rpc-type: grpc | ||||||
|  |  | ||||||
|  | --- # 数据源配置 | ||||||
|  | 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://192.168.110.2:13386/xinnengyuan?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true | ||||||
|  |           username: xinnengyuan | ||||||
|  |           password: mEZPC5Sdf3r2HENi | ||||||
|  |       #        # 从库数据源 | ||||||
|  |       #        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&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=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: 192.168.110.2 | ||||||
|  |     # 端口,默认为6379 | ||||||
|  |     port: 9287 | ||||||
|  |     # 数据库索引 | ||||||
|  |     database: 5 | ||||||
|  |     # redis 密码必须配置 | ||||||
|  |     password: syar23rdsaagdrsa | ||||||
|  |     # 连接超时时间 | ||||||
|  |     timeout: 10s | ||||||
|  |     # 是否开启ssl | ||||||
|  |     ssl.enabled: false | ||||||
|  |  | ||||||
|  | # redisson 配置 | ||||||
|  | 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://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用 | ||||||
|  | sms: | ||||||
|  |   # 配置源类型用于标定配置来源(interface,yaml) | ||||||
|  |   config-type: yaml | ||||||
|  |   # 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制 | ||||||
|  |   restricted: true | ||||||
|  |   # 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效 | ||||||
|  |   minute-max: 1 | ||||||
|  |   # 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效 | ||||||
|  |   account-max: 30 | ||||||
|  |   # 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中 | ||||||
|  |   blends: | ||||||
|  |     # 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可 | ||||||
|  |     # 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户 | ||||||
|  |     config1: | ||||||
|  |       # 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 | ||||||
|  |       supplier: alibaba | ||||||
|  |       # 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。 | ||||||
|  |       access-key-id: 您的accessKey | ||||||
|  |       # 称为accessSecret有些称之为apiSecret | ||||||
|  |       access-key-secret: 您的accessKeySecret | ||||||
|  |       signature: 您的短信签名 | ||||||
|  |       sdk-app-id: 您的sdkAppId | ||||||
|  |     config2: | ||||||
|  |       # 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分 | ||||||
|  |       supplier: tencent | ||||||
|  |       access-key-id: 您的accessKey | ||||||
|  |       access-key-secret: 您的accessKeySecret | ||||||
|  |       signature: 您的短信签名 | ||||||
|  |       sdk-app-id: 您的sdkAppId | ||||||
|  |  | ||||||
|  | --- # 三方授权 | ||||||
|  | justauth: | ||||||
|  |   # 前端外网访问地址 | ||||||
|  |   address: http://localhost:80 | ||||||
|  |   type: | ||||||
|  |     maxkey: | ||||||
|  |       # maxkey 服务器地址 | ||||||
|  |       # 注意 如下均配置均不需要修改 maxkey 已经内置好了数据 | ||||||
|  |       server-url: http://sso.maxkey.top | ||||||
|  |       client-id: 876892492581044224 | ||||||
|  |       client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=maxkey | ||||||
|  |     topiam: | ||||||
|  |       # topiam 服务器地址 | ||||||
|  |       server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol | ||||||
|  |       client-id: 449c4*********937************759 | ||||||
|  |       client-secret: ac7***********1e0************28d | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=topiam | ||||||
|  |       scopes: [ openid, email, phone, profile ] | ||||||
|  |     qq: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=qq | ||||||
|  |       union-id: false | ||||||
|  |     weibo: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=weibo | ||||||
|  |     gitee: | ||||||
|  |       client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98 | ||||||
|  |       client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=gitee | ||||||
|  |     dingtalk: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=dingtalk | ||||||
|  |     baidu: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=baidu | ||||||
|  |     csdn: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=csdn | ||||||
|  |     coding: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=coding | ||||||
|  |       coding-group-name: xx | ||||||
|  |     oschina: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=oschina | ||||||
|  |     alipay_wallet: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet | ||||||
|  |       alipay-public-key: MIIB**************DAQAB | ||||||
|  |     wechat_open: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=wechat_open | ||||||
|  |     wechat_mp: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=wechat_mp | ||||||
|  |     wechat_enterprise: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise | ||||||
|  |       agent-id: 1000002 | ||||||
|  |     gitlab: | ||||||
|  |       client-id: 10**********6 | ||||||
|  |       client-secret: 1f7d08**********5b7**********29e | ||||||
|  |       redirect-uri: ${justauth.address}/social-callback?source=gitlab | ||||||
|  | # 和风天气 https://dev.qweather.com/ | ||||||
|  | weather: | ||||||
|  |   key-id: T65EAABUXC | ||||||
|  |   project-id: 2JTHPUQ5YY | ||||||
|  |   private-key: MC4CAQAwBQYDK2VwBCIEIMAglX7IsxYiTeM+FXXnvCUsIggajeP4s8gAllewm6BN | ||||||
|  |   api-host: n35rk53njv.re.qweatherapi.com | ||||||
|  | # dxf转 geojson 执行文件名 | ||||||
|  | dxf2GeoJson: | ||||||
|  |   file-name: main | ||||||
|  | ys7: | ||||||
|  |   app-key: 3acf9f1a43dc4209841e0893003db0a2 | ||||||
|  |   app-secret: 4bbf3e9394f55d3af6e3af27b2d3db36 | ||||||
|  | # 斯巴达算法 | ||||||
|  | sparta: | ||||||
|  |   url: http://119.3.204.120:8040 | ||||||
|  |   client-id: test | ||||||
|  |   client-secret: 115fcb08fa6742a1b086d9bb80a6ad59 | ||||||
|  | # 身份证加密密钥(32 位) | ||||||
|  | id-card: | ||||||
|  |   encrypt-key: 7ae260d150a14027d2238a1cf80a48ef | ||||||
|  | recognizer: | ||||||
|  |   url: http://192.168.110.5:50070 | ||||||
							
								
								
									
										338
									
								
								ruoyi-admin/src/main/resources/application.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										338
									
								
								ruoyi-admin/src/main/resources/application.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,338 @@ | |||||||
|  | # 项目相关配置 | ||||||
|  | ruoyi: | ||||||
|  |   # 名称 | ||||||
|  |   name: RuoYi-Vue-Plus | ||||||
|  |   # 版本 | ||||||
|  |   version: ${revision} | ||||||
|  |   # 版权年份 | ||||||
|  |   copyrightYear: 2024 | ||||||
|  |  | ||||||
|  | captcha: | ||||||
|  |   enable: true | ||||||
|  |   # 页面 <参数设置> 可开启关闭 验证码校验 | ||||||
|  |   # 验证码类型 math 数组计算 char 字符验证 | ||||||
|  |   type: MATH | ||||||
|  |   # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰 | ||||||
|  |   category: CIRCLE | ||||||
|  |   # 数字验证码位数 | ||||||
|  |   numberLength: 1 | ||||||
|  |   # 字符验证码长度 | ||||||
|  |   charLength: 4 | ||||||
|  |  | ||||||
|  | # 开发环境配置 | ||||||
|  | server: | ||||||
|  |   # 服务器的HTTP端口,默认为8080 | ||||||
|  |   port: 8899 | ||||||
|  |   servlet: | ||||||
|  |     # 应用的访问路径 | ||||||
|  |     context-path: / | ||||||
|  |   # undertow 配置 | ||||||
|  |   undertow: | ||||||
|  |     # HTTP post内容的最大大小。当值为-1时,默认值为大小是无限的 | ||||||
|  |     max-http-post-size: -1 | ||||||
|  |     # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 | ||||||
|  |     # 每块buffer的空间大小,越小的空间被利用越充分 | ||||||
|  |     buffer-size: 512 | ||||||
|  |     # 是否分配的直接内存 | ||||||
|  |     direct-buffers: true | ||||||
|  |     threads: | ||||||
|  |       # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 | ||||||
|  |       io: 8 | ||||||
|  |       # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载 | ||||||
|  |       worker: 256 | ||||||
|  |  | ||||||
|  | # 日志配置 | ||||||
|  | logging: | ||||||
|  |   level: | ||||||
|  |     org.dromara: @logging.level@ | ||||||
|  |     org.springframework: warn | ||||||
|  |     org.mybatis.spring.mapper: error | ||||||
|  |     org.apache.fury: warn | ||||||
|  |   config: classpath:logback-plus.xml | ||||||
|  |  | ||||||
|  | # 用户配置 | ||||||
|  | user: | ||||||
|  |   password: | ||||||
|  |     # 密码最大错误次数 | ||||||
|  |     maxRetryCount: 5 | ||||||
|  |     # 密码锁定时间(默认10分钟) | ||||||
|  |     lockTime: 10 | ||||||
|  |  | ||||||
|  | # Spring配置 | ||||||
|  | spring: | ||||||
|  |   application: | ||||||
|  |     name: ${ruoyi.name} | ||||||
|  |   threads: | ||||||
|  |     # 开启虚拟线程 仅jdk21可用 | ||||||
|  |     virtual: | ||||||
|  |       enabled: false | ||||||
|  |   # 资源信息 | ||||||
|  |   messages: | ||||||
|  |     # 国际化资源文件路径 | ||||||
|  |     basename: i18n/messages | ||||||
|  |   profiles: | ||||||
|  |     active: @profiles.active@ | ||||||
|  |   # 文件上传 | ||||||
|  |   servlet: | ||||||
|  |     multipart: | ||||||
|  |       # 单个文件大小 | ||||||
|  |       max-file-size: 200MB | ||||||
|  |       # 设置总上传的文件大小 | ||||||
|  |       max-request-size: 200MB | ||||||
|  |   mvc: | ||||||
|  |     # 设置静态资源路径 防止所有请求都去查静态资源 | ||||||
|  |     static-path-pattern: /static/** | ||||||
|  |     format: | ||||||
|  |       date-time: yyyy-MM-dd HH:mm:ss | ||||||
|  |   jackson: | ||||||
|  |     # 日期格式化 | ||||||
|  |     date-format: yyyy-MM-dd HH:mm:ss | ||||||
|  |     serialization: | ||||||
|  |       # 格式化输出 | ||||||
|  |       indent_output: false | ||||||
|  |       # 忽略无法转换的对象 | ||||||
|  |       fail_on_empty_beans: false | ||||||
|  |     deserialization: | ||||||
|  |       # 允许对象忽略json中不存在的属性 | ||||||
|  |       fail_on_unknown_properties: false | ||||||
|  |  | ||||||
|  | # Sa-Token配置 | ||||||
|  | sa-token: | ||||||
|  |   # token名称 (同时也是cookie名称) | ||||||
|  |   token-name: Authorization | ||||||
|  |   # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) | ||||||
|  |   is-concurrent: true | ||||||
|  |   # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) | ||||||
|  |   is-share: false | ||||||
|  |   # jwt秘钥 | ||||||
|  |   jwt-secret-key: abcdefghijklmnopqrstuvwxyz | ||||||
|  |  | ||||||
|  | # security配置 | ||||||
|  | security: | ||||||
|  |   # 排除路径 | ||||||
|  |   excludes: | ||||||
|  |     - /*.html | ||||||
|  |     - /**/*.html | ||||||
|  |     - /**/*.css | ||||||
|  |     - /**/*.js | ||||||
|  |     - /favicon.ico | ||||||
|  |     - /error | ||||||
|  |     - /*/api-docs | ||||||
|  |     - /*/api-docs/** | ||||||
|  |     - /warm-flow-ui/** | ||||||
|  |     - /warm-flow/** | ||||||
|  |     - /other/ys7Device/webhook | ||||||
|  |     # todo 仅测试 | ||||||
|  |     - /facility/matrix/** | ||||||
|  |     - /**/changxie/callback/** | ||||||
|  |  | ||||||
|  | # 多租户配置 | ||||||
|  | tenant: | ||||||
|  |   # 是否开启 | ||||||
|  |   enable: false | ||||||
|  |   # 排除表 | ||||||
|  |   excludes: | ||||||
|  |     - sys_menu | ||||||
|  |     - sys_tenant | ||||||
|  |     - sys_tenant_package | ||||||
|  |     - sys_role_dept | ||||||
|  |     - sys_role_menu | ||||||
|  |     - sys_user_post | ||||||
|  |     - sys_user_role | ||||||
|  |     - sys_client | ||||||
|  |     - sys_oss_config | ||||||
|  |  | ||||||
|  | # MyBatisPlus配置 | ||||||
|  | # https://baomidou.com/config/ | ||||||
|  | mybatis-plus: | ||||||
|  |   # 自定义配置 是否全局开启逻辑删除 关闭后 所有逻辑删除功能将失效 | ||||||
|  |   enableLogicDelete: true | ||||||
|  |   # 多包名使用 例如 org.dromara.**.mapper,org.xxx.**.mapper | ||||||
|  |   mapperPackage: org.dromara.**.mapper,org.dromara.app.**.mapper | ||||||
|  |   # 对应的 XML 文件位置 | ||||||
|  |   mapperLocations: classpath*:mapper/**/*Mapper.xml,classpath*:mapper/app/**/*Mapper.xml | ||||||
|  |   # 实体扫描,多个package用逗号或者分号分隔 | ||||||
|  |   typeAliasesPackage: org.dromara.**.domain,org.dromara.app.**.domain | ||||||
|  |   global-config: | ||||||
|  |     dbConfig: | ||||||
|  |       # 主键类型 | ||||||
|  |       # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID | ||||||
|  |       # 如需改为自增 需要将数据库表全部设置为自增 | ||||||
|  |       idType: ASSIGN_ID | ||||||
|  |  | ||||||
|  | # 数据加密 | ||||||
|  | mybatis-encryptor: | ||||||
|  |   # 是否开启加密 | ||||||
|  |   enable: false | ||||||
|  |   # 默认加密算法 | ||||||
|  |   algorithm: BASE64 | ||||||
|  |   # 编码方式 BASE64/HEX。默认BASE64 | ||||||
|  |   encode: BASE64 | ||||||
|  |   # 安全秘钥 对称算法的秘钥 如:AES,SM4 | ||||||
|  |   password: | ||||||
|  |   # 公私钥 非对称算法的公私钥 如:SM2,RSA | ||||||
|  |   publicKey: | ||||||
|  |   privateKey: | ||||||
|  |  | ||||||
|  | # api接口加密 | ||||||
|  | api-decrypt: | ||||||
|  |   # 是否开启全局接口加密 | ||||||
|  |   enabled: true | ||||||
|  |   # AES 加密头标识 | ||||||
|  |   headerFlag: encrypt-key | ||||||
|  |   # 响应加密公钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换 | ||||||
|  |   # 对应前端解密私钥 MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE= | ||||||
|  |   publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ== | ||||||
|  |   # 请求解密私钥 非对称算法的公私钥 如:SM2,RSA 使用者请自行更换 | ||||||
|  |   # 对应前端加密公钥 MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ== | ||||||
|  |   privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y= | ||||||
|  |   # cory 放行部分接口 | ||||||
|  |   excluded-paths: | ||||||
|  |     - /doc.html    # 放行Swagger文档 | ||||||
|  |     - /swagger-ui/**     # 放行Swagger文档 | ||||||
|  |     - /v3/api-docs/**    # 放行OpenAPI文档 | ||||||
|  |     - /actuator/**       # 放行监控接口 | ||||||
|  |     - /other/ys7Device/webhook    # 放行萤石云设备回调接口 | ||||||
|  |     - /auth/register # 放行注册接口 | ||||||
|  |  | ||||||
|  | springdoc: | ||||||
|  |   api-docs: | ||||||
|  |     # 是否开启接口文档 | ||||||
|  |     enabled: true | ||||||
|  |     path: /v3/api-docs | ||||||
|  |   info: | ||||||
|  |     # 标题 | ||||||
|  |     title: '标题:${ruoyi.name}多租户管理系统_接口文档' | ||||||
|  |     # 描述 | ||||||
|  |     description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...' | ||||||
|  |     # 版本 | ||||||
|  |     version: '版本号: ${ruoyi.version}' | ||||||
|  |     # 作者信息 | ||||||
|  |     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: org.dromara.web | ||||||
|  |     - group: 2.系统模块 | ||||||
|  |       packages-to-scan: org.dromara.system | ||||||
|  |     - group: 3.项目模块 | ||||||
|  |       packages-to-scan: org.dromara.project | ||||||
|  |     - group: 4.材料模块 | ||||||
|  |       packages-to-scan: org.dromara.materials | ||||||
|  |     - group: 5.机械模块 | ||||||
|  |       packages-to-scan: org.dromara.machinery | ||||||
|  |     - group: 6.安全模块 | ||||||
|  |       packages-to-scan: org.dromara.safety | ||||||
|  |     - group: 7.质量模块 | ||||||
|  |       packages-to-scan: org.dromara.quality | ||||||
|  |     - group: 8.设施模块 | ||||||
|  |       packages-to-scan: org.dromara.facility | ||||||
|  |     - group: 9.进度模块 | ||||||
|  |       packages-to-scan: org.dromara.progress | ||||||
|  |     - group: 10.其他模块 | ||||||
|  |       packages-to-scan: org.dromara.other | ||||||
|  |     - group: 11.分包模块 | ||||||
|  |       packages-to-scan: org.dromara.contractor | ||||||
|  |     - group: 12.设计模块 | ||||||
|  |       packages-to-scan: org.dromara.design | ||||||
|  |     - group: 13.工作流模块 | ||||||
|  |       packages-to-scan: org.dromara.workflow | ||||||
|  |     - group: 14.罗成模块 | ||||||
|  |       packages-to-scan: org.dromara.cory | ||||||
|  |     - group: 15.无人机模块 | ||||||
|  |       packages-to-scan: org.dromara.drone | ||||||
|  |     - group: 20.代码生成模块 | ||||||
|  |       packages-to-scan: org.dromara.generator | ||||||
|  |     - group: 16.app模块 | ||||||
|  |       packages-to-scan: org.dromara.app | ||||||
|  | # knife4j的增强配置,不需要增强可以不配 | ||||||
|  | knife4j: | ||||||
|  |   enable: true | ||||||
|  |   setting: | ||||||
|  |     language: zh_cn | ||||||
|  |  | ||||||
|  | # 防止XSS攻击 | ||||||
|  | xss: | ||||||
|  |   # 过滤开关 | ||||||
|  |   enabled: true | ||||||
|  |   # 排除链接(多个用逗号分隔) | ||||||
|  |   excludeUrls: | ||||||
|  |     - /system/notice | ||||||
|  |     - /warm-flow/save-xml | ||||||
|  |  | ||||||
|  | # 全局线程池相关配置 | ||||||
|  | # 如使用JDK21请直接使用虚拟线程 不要开启此配置 | ||||||
|  | thread-pool: | ||||||
|  |   # 是否开启线程池 | ||||||
|  |   enabled: false | ||||||
|  |   # 队列最大长度 | ||||||
|  |   queueCapacity: 128 | ||||||
|  |   # 线程池维护线程所允许的空闲时间 | ||||||
|  |   keepAliveSeconds: 300 | ||||||
|  |  | ||||||
|  | --- # 分布式锁 lock4j 全局配置 | ||||||
|  | lock4j: | ||||||
|  |   # 获取分布式锁超时时间,默认为 3000 毫秒 | ||||||
|  |   acquire-timeout: 3000 | ||||||
|  |   # 分布式锁的超时时间,默认为 30 秒 | ||||||
|  |   expire: 30000 | ||||||
|  |  | ||||||
|  | --- # Actuator 监控端点的配置项 | ||||||
|  | management: | ||||||
|  |   endpoints: | ||||||
|  |     web: | ||||||
|  |       exposure: | ||||||
|  |         include: '*' | ||||||
|  |   endpoint: | ||||||
|  |     health: | ||||||
|  |       show-details: ALWAYS | ||||||
|  |     logfile: | ||||||
|  |       external-file: ./logs/sys-console.log | ||||||
|  |  | ||||||
|  | --- # 默认/推荐使用sse推送 | ||||||
|  | sse: | ||||||
|  |   enabled: true | ||||||
|  |   path: /resource/sse | ||||||
|  |  | ||||||
|  | --- # websocket | ||||||
|  | websocket: | ||||||
|  |   # 如果关闭 需要和前端开关一起关闭 | ||||||
|  |   enabled: false | ||||||
|  |   # 路径 | ||||||
|  |   path: /resource/websocket | ||||||
|  |   # 设置访问源地址 | ||||||
|  |   allowedOrigins: '*' | ||||||
|  |  | ||||||
|  | --- # warm-flow工作流配置 | ||||||
|  | warm-flow: | ||||||
|  |   # 是否开启工作流,默认true | ||||||
|  |   enabled: true | ||||||
|  |   # 是否开启设计器ui | ||||||
|  |   ui: true | ||||||
|  |   # 默认Authorization,如果有多个token,用逗号分隔 | ||||||
|  |   token-name: ${sa-token.token-name},clientid | ||||||
|  |   # 流程状态对应的三元色 | ||||||
|  |   chart-status-color: | ||||||
|  |     ## 未办理 | ||||||
|  |     - 62,62,62 | ||||||
|  |     ## 待办理 | ||||||
|  |     - 255,205,23 | ||||||
|  |     ## 已办理 | ||||||
|  |     - 157,255,0 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | --- # 百度云配置 | ||||||
|  | baidu: | ||||||
|  |   client: | ||||||
|  |     id: zSB7KdLgY7a1tIEx3eTy65TE | ||||||
|  |     secret: 5nabjclW5BWGV8UwEueDgBDmOveRVkmD | ||||||
							
								
								
									
										8
									
								
								ruoyi-admin/src/main/resources/banner.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ruoyi-admin/src/main/resources/banner.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | Application Version: ${revision} | ||||||
|  | Spring Boot Version: ${spring-boot.version} | ||||||
|  | __________            _____.___.__         ____   ____                     __________.__ | ||||||
|  | \______   \__ __  ____\__  |   |__|        \   \ /   /_ __   ____          \______   \  |  __ __  ______ | ||||||
|  |  |       _/  |  \/  _ \/   |   |  |  ______ \   Y   /  |  \_/ __ \   ______ |     ___/  | |  |  \/  ___/ | ||||||
|  |  |    |   \  |  (  <_> )____   |  | /_____/  \     /|  |  /\  ___/  /_____/ |    |   |  |_|  |  /\___ \ | ||||||
|  |  |____|_  /____/ \____// ______|__|           \___/ |____/  \___  >         |____|   |____/____//____  > | ||||||
|  |         \/             \/                                       \/                                   \/ | ||||||
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 7.9 KiB | 
							
								
								
									
										61
									
								
								ruoyi-admin/src/main/resources/i18n/messages.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								ruoyi-admin/src/main/resources/i18n/messages.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | |||||||
|  | #错误消息 | ||||||
|  | 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=未知错误,请重新登录 | ||||||
|  | auth.grant.type.error=认证权限类型错误 | ||||||
|  | auth.grant.type.blocked=认证权限类型已禁用 | ||||||
|  | auth.grant.type.not.blank=认证权限类型不能为空 | ||||||
|  | auth.clientid.not.blank=认证客户端id不能为空 | ||||||
|  | ##文件上传消息 | ||||||
|  | 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]不能为空 | ||||||
|  | social.source.not.blank=第三方登录平台[source]不能为空 | ||||||
|  | social.code.not.blank=第三方登录平台[code]不能为空 | ||||||
|  | social.state.not.blank=第三方登录平台[state]不能为空 | ||||||
|  | ##租户 | ||||||
|  | tenant.number.not.blank=租户编号不能为空 | ||||||
|  | tenant.not.exists=对不起, 您的租户不存在,请联系管理员 | ||||||
|  | tenant.blocked=对不起,您的租户已禁用,请联系管理员 | ||||||
|  | tenant.expired=对不起,您的租户已过期,请联系管理员 | ||||||
| @ -0,0 +1,61 @@ | |||||||
|  | #错误消息 | ||||||
|  | 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 disabled,please 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 exit,please login again | ||||||
|  | user.unknown.error=Unknown error, please login again | ||||||
|  | auth.grant.type.error=Auth grant type error | ||||||
|  | auth.grant.type.blocked=Auth grant type disabled | ||||||
|  | auth.grant.type.not.blank=Auth grant type cannot be blank | ||||||
|  | auth.clientid.not.blank=Auth clientid cannot be blank | ||||||
|  | ##文件上传消息 | ||||||
|  | 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 data,please contact your administrator to add permissions [{0}] | ||||||
|  | no.create.permission=You do not have permission to create data,please contact your administrator to add permissions [{0}] | ||||||
|  | no.update.permission=You do not have permission to modify data,please contact your administrator to add permissions [{0}] | ||||||
|  | no.delete.permission=You do not have permission to delete data,please contact your administrator to add permissions [{0}] | ||||||
|  | no.export.permission=You do not have permission to export data,please contact your administrator to add permissions [{0}] | ||||||
|  | no.view.permission=You do not have permission to view data,please 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 | ||||||
|  | social.source.not.blank=Social login platform [source] cannot be blank | ||||||
|  | social.code.not.blank=Social login platform [code] cannot be blank | ||||||
|  | social.state.not.blank=Social login platform [state] cannot be blank | ||||||
|  | ##租户 | ||||||
|  | tenant.number.not.blank=Tenant number cannot be blank | ||||||
|  | tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator | ||||||
|  | tenant.blocked=Sorry, your tenant is disabled. Please contact the administrator | ||||||
|  | tenant.expired=Sorry, your tenant has expired. Please contact the administrator. | ||||||
| @ -0,0 +1,61 @@ | |||||||
|  | #错误消息 | ||||||
|  | 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=未知错误,请重新登录 | ||||||
|  | auth.grant.type.error=认证权限类型错误 | ||||||
|  | auth.grant.type.blocked=认证权限类型已禁用 | ||||||
|  | auth.grant.type.not.blank=认证权限类型不能为空 | ||||||
|  | auth.clientid.not.blank=认证客户端id不能为空 | ||||||
|  | ##文件上传消息 | ||||||
|  | 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]不能为空 | ||||||
|  | social.source.not.blank=第三方登录平台[source]不能为空 | ||||||
|  | social.code.not.blank=第三方登录平台[code]不能为空 | ||||||
|  | social.state.not.blank=第三方登录平台[state]不能为空 | ||||||
|  | ##租户 | ||||||
|  | tenant.number.not.blank=租户编号不能为空 | ||||||
|  | tenant.not.exists=对不起, 您的租户不存在,请联系管理员 | ||||||
|  | tenant.blocked=对不起,您的租户已禁用,请联系管理员 | ||||||
|  | tenant.expired=对不起,您的租户已过期,请联系管理员 | ||||||
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/ip2region.xdb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/ip2region.xdb
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										129
									
								
								ruoyi-admin/src/main/resources/logback-plus.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								ruoyi-admin/src/main/resources/logback-plus.xml
									
									
									
									
									
										Normal 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="%cyan(%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> | ||||||
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/安全生产监督检查通知书模版.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/安全生产监督检查通知书模版.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/整改通知单模版.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/整改通知单模版.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/施工日志模版.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/施工日志模版.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/物料接收单模版.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/物料接收单模版.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/物料领料单模版.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/物料领料单模版.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/设计变更申请单模版.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/src/main/resources/template/设计变更申请单模版.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -0,0 +1,45 @@ | |||||||
|  | package org.dromara.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); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										64
									
								
								ruoyi-admin/src/test/java/org/dromara/test/CmdTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								ruoyi-admin/src/test/java/org/dromara/test/CmdTest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.io.BufferedReader; | ||||||
|  | import java.io.File; | ||||||
|  | import java.io.IOException; | ||||||
|  | import java.io.InputStreamReader; | ||||||
|  | import java.util.Arrays; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/4/23 10:15 | ||||||
|  |  */ | ||||||
|  | @SpringBootTest | ||||||
|  | public class CmdTest { | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     public void test() { | ||||||
|  |         // 获取当前项目根目录 | ||||||
|  |         String projectRoot = System.getProperty("user.dir"); | ||||||
|  |         // EXE 和参数 | ||||||
|  |         String exePath = projectRoot + File.separator + "file" + File.separator + "resource" + File.separator + "dxf" + File.separator + "main.exe"; | ||||||
|  |         String inputDXF = "file/resource/dxf/1897160897167638529/桩点图.dxf"; | ||||||
|  |         String outputJSON = "file/resource/dxf/1897160897167638529/output.json"; | ||||||
|  |         String sourceEPSG = "4524"; | ||||||
|  |         String targetEPSG = "4326"; | ||||||
|  |  | ||||||
|  |         // 构造命令行 | ||||||
|  |         List<String> command = Arrays.asList( | ||||||
|  |             exePath, | ||||||
|  |             inputDXF, | ||||||
|  |             outputJSON, | ||||||
|  |             sourceEPSG, | ||||||
|  |             targetEPSG | ||||||
|  |         ); | ||||||
|  |  | ||||||
|  |         ProcessBuilder builder = new ProcessBuilder(command); | ||||||
|  |         builder.redirectErrorStream(true); // 合并标准错误和输出 | ||||||
|  |  | ||||||
|  |         try { | ||||||
|  |             Process process = builder.start(); | ||||||
|  |  | ||||||
|  |             // 读取输出 | ||||||
|  |             BufferedReader reader = new BufferedReader( | ||||||
|  |                 new InputStreamReader(process.getInputStream(), "GBK") | ||||||
|  |             ); | ||||||
|  |             String line; | ||||||
|  |             System.out.println("程序输出:"); | ||||||
|  |             while ((line = reader.readLine()) != null) { | ||||||
|  |                 System.out.println(line); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             int exitCode = process.waitFor(); | ||||||
|  |             System.out.println("程序退出码:" + exitCode); | ||||||
|  |  | ||||||
|  |             reader.close(); | ||||||
|  |         } catch (IOException | InterruptedException e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										92
									
								
								ruoyi-admin/src/test/java/org/dromara/test/DemoTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								ruoyi-admin/src/test/java/org/dromara/test/DemoTest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.io.FileUtil; | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.design.service.IDesTechnicalStandardService; | ||||||
|  | import org.dromara.facility.domain.FacMatrix; | ||||||
|  | import org.dromara.facility.service.IFacMatrixService; | ||||||
|  | import org.dromara.facility.service.IFacPhotovoltaicPanelPartsService; | ||||||
|  | import org.dromara.progress.service.IPgsProgressCategoryService; | ||||||
|  | import org.dromara.project.service.IBusProjectService; | ||||||
|  | import org.dromara.system.service.ISysDeptService; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/5/30 9:48 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @SpringBootTest | ||||||
|  | public class DemoTest { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IFacPhotovoltaicPanelPartsService photovoltaicPanelPartsService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IPgsProgressCategoryService progressCategoryService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IFacMatrixService matrixService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IBusProjectService projectService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IDesTechnicalStandardService desTechnicalStandardService; | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private ISysDeptService deptService; | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void test() { | ||||||
|  |         Boolean result = photovoltaicPanelPartsService | ||||||
|  |             .updatePartsFinishStatus( | ||||||
|  |                 "14", | ||||||
|  |                 new Date(), | ||||||
|  |                 1897160897167638529L, | ||||||
|  |                 1927270270872109058L, | ||||||
|  |                 List.of("G01.01.01", "G01.08.06") | ||||||
|  |             ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void testProjectSync() { | ||||||
|  |         Long id = 1897160897167638529L; | ||||||
|  | /*        projectService.insertProjectSyncThing(id) | ||||||
|  |             .thenAccept(result -> log.info("项目异步执行数据同步成功")) | ||||||
|  |             .exceptionally(ex -> { | ||||||
|  |                 log.error("项目异步执行数据同步失败", ex); | ||||||
|  |                 return null; | ||||||
|  |             });*/ | ||||||
|  |         Boolean saveTechnicalStandard = desTechnicalStandardService.insertFolderByTemplate(id); | ||||||
|  |         if (!saveTechnicalStandard) { | ||||||
|  |             log.error("同步数据失败,项目[{}]新增技术标准管理文件夹模版失败", id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void testMethod() { | ||||||
|  |         String originalFilename = "test"; | ||||||
|  |         String suffix = FileUtil.getSuffix(originalFilename); | ||||||
|  |         System.out.println(suffix); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void testTemple() { | ||||||
|  |         List<FacMatrix> matrixList = matrixService.lambdaQuery() | ||||||
|  |             .eq(FacMatrix::getProjectId, 1906557369562726402L) | ||||||
|  |             .list(); | ||||||
|  |         Boolean result = progressCategoryService.insertByTemplate(1906557369562726402L, matrixList, null); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void testDeptProject() { | ||||||
|  |         deptService.selectProjectIdById(100L); | ||||||
|  |         deptService.selectProjectIdById(1937478258803171329L); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										70
									
								
								ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								ruoyi-admin/src/test/java/org/dromara/test/DemoUnitTest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import org.dromara.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 =================="); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								ruoyi-admin/src/test/java/org/dromara/test/PDFTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								ruoyi-admin/src/test/java/org/dromara/test/PDFTest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.common.utils.PdfBoxQrCodeGenerator; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/7/7 10:13 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @SpringBootTest | ||||||
|  | public class PDFTest { | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void test() { | ||||||
|  |         String srcPdf = "http://58.17.134.85:9000/xinnengyuan-dev/2025/07/07/146cb913cb4841eb9944463b762cba53.pdf";         // 原始PDF | ||||||
|  |         String destPdf = "output.pdf";       // 输出PDF | ||||||
|  |         Map<String, Object> params = new HashMap<>(); | ||||||
|  |         params.put("版本:", "1.0"); | ||||||
|  |         params.put("文件名:", "绝对哦啊手机号丢啊"); | ||||||
|  |         params.put("文件类型:", "蓝图"); | ||||||
|  |         String qrText = "fdas:1.0 das:asd sad:dsa"; | ||||||
|  |         String qrPath = "qrcode.png"; | ||||||
|  |  | ||||||
|  |         byte[] bytes = PdfBoxQrCodeGenerator.generateQRCodeBytes(qrText, 200, 200); | ||||||
|  |         try { | ||||||
|  |             PdfBoxQrCodeGenerator.addQRCodeToPDF(srcPdf, destPdf, bytes, 1, 1510, 900); // 页码从1开始,坐标单位是 pt(约1/72英寸) | ||||||
|  |         } catch (Exception e) { | ||||||
|  |             e.printStackTrace(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         System.out.println("二维码添加成功!"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,72 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import org.dromara.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 =================="); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.manager.recognizermanager.RecognizerManager; | ||||||
|  | import org.dromara.manager.recognizermanager.enums.RecognizerTypeEnum; | ||||||
|  | import org.dromara.manager.recognizermanager.vo.RecognizeVo; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/7/21 11:35 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @SpringBootTest | ||||||
|  | public class RecognizerTest { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private RecognizerManager recognizerManager; | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void test() { | ||||||
|  |         RecognizeVo recognize = recognizerManager.recognize("http://xny.yj-3d.com:7363/file/tif/20250625160218orthophoto.png", List.of(RecognizerTypeEnum.PHO)); | ||||||
|  |         log.info("recognize: {}", recognize); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										54
									
								
								ruoyi-admin/src/test/java/org/dromara/test/TagUnitTest.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								ruoyi-admin/src/test/java/org/dromara/test/TagUnitTest.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | |||||||
|  | package org.dromara.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 =================="); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,58 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import org.dromara.safety.domain.dto.violationrecord.HseViolationRecordCreateDto; | ||||||
|  | import org.dromara.safety.service.IHseViolationRecordService; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.util.ArrayList; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/7/22 15:36 | ||||||
|  |  */ | ||||||
|  | @SpringBootTest | ||||||
|  | public class ViolationRecordTest { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private IHseViolationRecordService violationRecordService; | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void test() { | ||||||
|  |         List<HseViolationRecordCreateDto> list = new ArrayList<>(); | ||||||
|  |         HseViolationRecordCreateDto dto1 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto1.setProjectId(1897160897167638529L); | ||||||
|  |         dto1.setRecognizeId(1937451365735419905L); | ||||||
|  |         dto1.setViolationType("3"); | ||||||
|  |         dto1.setViolationTime(new Date()); | ||||||
|  |         list.add(dto1); | ||||||
|  |         HseViolationRecordCreateDto dto2 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto2.setProjectId(1897160897167638529L); | ||||||
|  |         dto2.setRecognizeId(1937451365735419906L); | ||||||
|  |         dto2.setViolationType("1,2,3"); | ||||||
|  |         dto2.setViolationTime(new Date()); | ||||||
|  |         list.add(dto2); | ||||||
|  |         HseViolationRecordCreateDto dto3 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto3.setProjectId(1897160897167638529L); | ||||||
|  |         dto3.setRecognizeId(1937451365735419907L); | ||||||
|  |         dto3.setViolationType("2,7,8"); | ||||||
|  |         dto3.setViolationTime(new Date()); | ||||||
|  |         list.add(dto3); | ||||||
|  |         HseViolationRecordCreateDto dto4 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto4.setProjectId(1897160897167638529L); | ||||||
|  |         dto4.setRecognizeId(1937451365735419908L); | ||||||
|  |         dto4.setViolationType("5,8"); | ||||||
|  |         dto4.setViolationTime(new Date()); | ||||||
|  |         list.add(dto4); | ||||||
|  |         HseViolationRecordCreateDto dto5 = new HseViolationRecordCreateDto(); | ||||||
|  |         dto5.setProjectId(1897160897167638529L); | ||||||
|  |         dto5.setRecognizeId(1937451365735419909L); | ||||||
|  |         dto5.setViolationType("3,9"); | ||||||
|  |         dto5.setViolationTime(new Date()); | ||||||
|  |         list.add(dto5); | ||||||
|  |         violationRecordService.insertByMonitor(list); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										37
									
								
								ruoyi-admin/src/test/java/org/dromara/test/Ys7Test.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								ruoyi-admin/src/test/java/org/dromara/test/Ys7Test.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | |||||||
|  | package org.dromara.test; | ||||||
|  |  | ||||||
|  | import jakarta.annotation.Resource; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.dromara.manager.ys7manager.Ys7Manager; | ||||||
|  | import org.dromara.manager.ys7manager.Ys7RequestUtils; | ||||||
|  | import org.dromara.manager.ys7manager.vo.Ys7QueryDeviceResponseVo; | ||||||
|  | import org.junit.jupiter.api.Test; | ||||||
|  | import org.springframework.boot.test.context.SpringBootTest; | ||||||
|  |  | ||||||
|  | import java.util.List; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/6/12 17:06 | ||||||
|  |  */ | ||||||
|  | @Slf4j | ||||||
|  | @SpringBootTest | ||||||
|  | public class Ys7Test { | ||||||
|  |  | ||||||
|  |     @Resource | ||||||
|  |     private Ys7Manager ys7Manager; | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void test() { | ||||||
|  |         String token = ys7Manager.getToken(); | ||||||
|  |         List<Ys7QueryDeviceResponseVo> ys7QueryDeviceResponseVos = Ys7RequestUtils.queryDeviceVoList(token, 1, 20); | ||||||
|  |         System.out.println(ys7QueryDeviceResponseVos); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Test | ||||||
|  |     void testCaptureDevicePic() { | ||||||
|  |         String pic = ys7Manager.getCaptureDevicePic("AE9470016", 1, 1); | ||||||
|  |         System.out.println(pic); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								ruoyi-admin/zhFonts/.uuid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ruoyi-admin/zhFonts/.uuid
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3f2ee348-0303-40ca-bf03-03f48d2d2141 | ||||||
							
								
								
									
										
											BIN
										
									
								
								ruoyi-admin/zhFonts/SIMSUN.TTC
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ruoyi-admin/zhFonts/SIMSUN.TTC
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										4
									
								
								ruoyi-admin/zhFonts/fonts.dir
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								ruoyi-admin/zhFonts/fonts.dir
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | 3 | ||||||
|  | SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso10646-1 | ||||||
|  | SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso8859-1 | ||||||
|  | SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-koi8-r | ||||||
							
								
								
									
										4
									
								
								ruoyi-admin/zhFonts/fonts.scale
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								ruoyi-admin/zhFonts/fonts.scale
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | |||||||
|  | 3 | ||||||
|  | SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso10646-1 | ||||||
|  | SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-iso8859-1 | ||||||
|  | SIMSUN.TTC -misc-simsun-medium-r-normal--0-0-0-0-p-0-koi8-r | ||||||
							
								
								
									
										47
									
								
								ruoyi-common/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								ruoyi-common/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | <?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> | ||||||
|  |         <artifactId>xinnengyuan</artifactId> | ||||||
|  |         <groupId>org.dromara</groupId> | ||||||
|  |         <version>${revision}</version> | ||||||
|  |     </parent> | ||||||
|  |     <modelVersion>4.0.0</modelVersion> | ||||||
|  |  | ||||||
|  |     <modules> | ||||||
|  |         <module>ruoyi-common-bom</module> | ||||||
|  |         <module>ruoyi-common-social</module> | ||||||
|  |         <module>ruoyi-common-core</module> | ||||||
|  |         <module>ruoyi-common-doc</module> | ||||||
|  |         <module>ruoyi-common-excel</module> | ||||||
|  |         <module>ruoyi-common-idempotent</module> | ||||||
|  |         <module>ruoyi-common-job</module> | ||||||
|  |         <module>ruoyi-common-log</module> | ||||||
|  |         <module>ruoyi-common-mail</module> | ||||||
|  |         <module>ruoyi-common-mybatis</module> | ||||||
|  |         <module>ruoyi-common-oss</module> | ||||||
|  |         <module>ruoyi-common-ratelimiter</module> | ||||||
|  |         <module>ruoyi-common-redis</module> | ||||||
|  |         <module>ruoyi-common-satoken</module> | ||||||
|  |         <module>ruoyi-common-security</module> | ||||||
|  |         <module>ruoyi-common-sms</module> | ||||||
|  |         <module>ruoyi-common-web</module> | ||||||
|  |         <module>ruoyi-common-translation</module> | ||||||
|  |         <module>ruoyi-common-sensitive</module> | ||||||
|  |         <module>ruoyi-common-json</module> | ||||||
|  |         <module>ruoyi-common-encrypt</module> | ||||||
|  |         <module>ruoyi-common-tenant</module> | ||||||
|  |         <module>ruoyi-common-websocket</module> | ||||||
|  |         <module>ruoyi-common-sse</module> | ||||||
|  |         <module>ruoyi-common-jts</module> | ||||||
|  |     </modules> | ||||||
|  |  | ||||||
|  |     <artifactId>ruoyi-common</artifactId> | ||||||
|  |     <packaging>pom</packaging> | ||||||
|  |  | ||||||
|  |     <description> | ||||||
|  |         common 通用模块 | ||||||
|  |     </description> | ||||||
|  |  | ||||||
|  | </project> | ||||||
							
								
								
									
										192
									
								
								ruoyi-common/ruoyi-common-bom/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								ruoyi-common/ruoyi-common-bom/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,192 @@ | |||||||
|  | <?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>org.dromara</groupId> | ||||||
|  |     <artifactId>ruoyi-common-bom</artifactId> | ||||||
|  |     <version>${revision}</version> | ||||||
|  |     <packaging>pom</packaging> | ||||||
|  |  | ||||||
|  |     <description> | ||||||
|  |         ruoyi-common-bom common依赖项 | ||||||
|  |     </description> | ||||||
|  |  | ||||||
|  |     <properties> | ||||||
|  |         <revision>5.3.0</revision> | ||||||
|  |     </properties> | ||||||
|  |  | ||||||
|  |     <dependencyManagement> | ||||||
|  |         <dependencies> | ||||||
|  |             <!-- 核心模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-core</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 接口模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-doc</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- excel --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-excel</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 幂等 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-idempotent</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 调度模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-job</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 日志记录 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-log</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 邮件服务 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-mail</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 数据库服务 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-mybatis</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- OSS --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-oss</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 限流 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-ratelimiter</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 缓存服务 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-redis</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- satoken --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-satoken</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 安全模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-security</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 短信模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-sms</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-social</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- web服务 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-web</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 翻译模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-translation</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 脱敏模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-sensitive</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 序列化模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-json</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 数据库加解密模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-encrypt</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 租户模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-tenant</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- WebSocket模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-websocket</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- SSE模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-sse</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |             <!-- 地图模块 --> | ||||||
|  |             <dependency> | ||||||
|  |                 <groupId>org.dromara</groupId> | ||||||
|  |                 <artifactId>ruoyi-common-jts</artifactId> | ||||||
|  |                 <version>${revision}</version> | ||||||
|  |             </dependency> | ||||||
|  |  | ||||||
|  |         </dependencies> | ||||||
|  |     </dependencyManagement> | ||||||
|  |  | ||||||
|  | </project> | ||||||
							
								
								
									
										99
									
								
								ruoyi-common/ruoyi-common-core/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								ruoyi-common/ruoyi-common-core/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | |||||||
|  | <?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>org.dromara</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> | ||||||
|  |         <!-- Spring框架基本的核心工具 --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework</groupId> | ||||||
|  |             <artifactId>spring-context-support</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!-- SpringWeb模块 --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework</groupId> | ||||||
|  |             <artifactId>spring-web</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!-- 自定义验证注解 --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-validation</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-starter-aop</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!--常用工具类 --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.apache.commons</groupId> | ||||||
|  |             <artifactId>commons-lang3</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-extra</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> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.springframework.boot</groupId> | ||||||
|  |             <artifactId>spring-boot-properties-migrator</artifactId> | ||||||
|  |             <scope>runtime</scope> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>io.github.linpeilie</groupId> | ||||||
|  |             <artifactId>mapstruct-plus-spring-boot-starter</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |         <!-- 离线IP地址定位库 --> | ||||||
|  |         <dependency> | ||||||
|  |             <groupId>org.lionsoul</groupId> | ||||||
|  |             <artifactId>ip2region</artifactId> | ||||||
|  |         </dependency> | ||||||
|  |  | ||||||
|  |     </dependencies> | ||||||
|  |  | ||||||
|  | </project> | ||||||
| @ -0,0 +1,17 @@ | |||||||
|  | package org.dromara.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 { | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,52 @@ | |||||||
|  | package org.dromara.common.core.config; | ||||||
|  |  | ||||||
|  | import cn.hutool.core.util.ArrayUtil; | ||||||
|  | import org.dromara.common.core.exception.ServiceException; | ||||||
|  | import org.dromara.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; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 异步配置 | ||||||
|  |  * <p> | ||||||
|  |  * 如果未使用虚拟线程则生效 | ||||||
|  |  * | ||||||
|  |  * @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()); | ||||||
|  |         }; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,33 @@ | |||||||
|  | package org.dromara.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; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,87 @@ | |||||||
|  | package org.dromara.common.core.config; | ||||||
|  |  | ||||||
|  | import jakarta.annotation.PreDestroy; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.apache.commons.lang3.concurrent.BasicThreadFactory; | ||||||
|  | import org.dromara.common.core.config.properties.ThreadPoolProperties; | ||||||
|  | import org.dromara.common.core.utils.SpringUtils; | ||||||
|  | import org.dromara.common.core.utils.Threads; | ||||||
|  | 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.core.task.VirtualThreadTaskExecutor; | ||||||
|  | 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() { | ||||||
|  |         // daemon 必须为 true | ||||||
|  |         BasicThreadFactory.Builder builder = new BasicThreadFactory.Builder().daemon(true); | ||||||
|  |         if (SpringUtils.isVirtual()) { | ||||||
|  |             builder.namingPattern("virtual-schedule-pool-%d").wrappedFactory(new VirtualThreadTaskExecutor().getVirtualThreadFactory()); | ||||||
|  |         } else { | ||||||
|  |             builder.namingPattern("schedule-pool-%d"); | ||||||
|  |         } | ||||||
|  |         ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core, | ||||||
|  |             builder.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); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,40 @@ | |||||||
|  | package org.dromara.common.core.config; | ||||||
|  |  | ||||||
|  | import jakarta.validation.Validator; | ||||||
|  | import org.hibernate.validator.HibernateValidator; | ||||||
|  | import org.springframework.boot.autoconfigure.AutoConfiguration; | ||||||
|  | import org.springframework.context.MessageSource; | ||||||
|  | import org.springframework.context.annotation.Bean; | ||||||
|  | import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; | ||||||
|  |  | ||||||
|  | import java.util.Properties; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 校验框架配置类 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @AutoConfiguration | ||||||
|  | public class ValidatorConfig { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 配置校验框架 快速返回模式 | ||||||
|  |      */ | ||||||
|  |     @Bean | ||||||
|  |     public Validator validator(MessageSource messageSource) { | ||||||
|  |         try (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(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | package org.dromara.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; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | package org.dromara.common.core.constant; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 缓存的key 常量 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | public interface CacheConstants { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 在线用户 redis key | ||||||
|  |      */ | ||||||
|  |     String ONLINE_TOKEN_KEY = "online_tokens:"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 参数管理 cache key | ||||||
|  |      */ | ||||||
|  |     String SYS_CONFIG_KEY = "sys_config:"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字典管理 cache key | ||||||
|  |      */ | ||||||
|  |     String SYS_DICT_KEY = "sys_dict:"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录账户密码错误次数 redis key | ||||||
|  |      */ | ||||||
|  |     String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,83 @@ | |||||||
|  | package org.dromara.common.core.constant; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 缓存组名称常量 | ||||||
|  |  * <p> | ||||||
|  |  * key 格式为 cacheNames#ttl#maxIdleTime#maxSize | ||||||
|  |  * <p> | ||||||
|  |  * ttl 过期时间 如果设置为0则不过期 默认为0 | ||||||
|  |  * maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0 | ||||||
|  |  * maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0 | ||||||
|  |  * <p> | ||||||
|  |  * 例子: test#60s、test#0#60s、test#0#1m#1000、test#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_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 客户端 | ||||||
|  |      */ | ||||||
|  |     String SYS_CLIENT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_client#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户账户 | ||||||
|  |      */ | ||||||
|  |     String SYS_USER_NAME = "sys_user_name#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户名称 | ||||||
|  |      */ | ||||||
|  |     String SYS_NICKNAME = "sys_nickname#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门 | ||||||
|  |      */ | ||||||
|  |     String SYS_DEPT = "sys_dept#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * OSS内容 | ||||||
|  |      */ | ||||||
|  |     String SYS_OSS = "sys_oss#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 角色自定义权限 | ||||||
|  |      */ | ||||||
|  |     String SYS_ROLE_CUSTOM = "sys_role_custom#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门及以下权限 | ||||||
|  |      */ | ||||||
|  |     String SYS_DEPT_AND_CHILD = "sys_dept_and_child#30d"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * OSS配置 | ||||||
|  |      */ | ||||||
|  |     String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 在线用户 | ||||||
|  |      */ | ||||||
|  |     String ONLINE_TOKEN = "online_tokens"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,76 @@ | |||||||
|  | package org.dromara.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; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 顶级父级id | ||||||
|  |      */ | ||||||
|  |     Long TOP_PARENT_ID = 0L; | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| @ -0,0 +1,14 @@ | |||||||
|  | package org.dromara.common.core.constant; | ||||||
|  |  | ||||||
|  | import java.util.regex.Pattern; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * @author lilemy | ||||||
|  |  * @date 2025/4/7 17:12 | ||||||
|  |  */ | ||||||
|  | public interface DateConstant { | ||||||
|  |  | ||||||
|  |     // 匹配 "yyyy-MM",年四位,月 01~12 | ||||||
|  |     Pattern YEAR_MONTH_PATTERN = Pattern.compile("^\\d{4}-(0[1-9]|1[0-2])$"); | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | package org.dromara.common.core.constant; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 全局的key常量 (业务无关的key) | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | 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 SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; | ||||||
|  | } | ||||||
| @ -0,0 +1,93 @@ | |||||||
|  | package org.dromara.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; | ||||||
|  | } | ||||||
| @ -0,0 +1,54 @@ | |||||||
|  | package org.dromara.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]$"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,75 @@ | |||||||
|  | package org.dromara.common.core.constant; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 系统常量信息 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | public interface SystemConstants { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 正常状态 | ||||||
|  |      */ | ||||||
|  |     String NORMAL = "0"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 异常状态 | ||||||
|  |      */ | ||||||
|  |     String DISABLE = "1"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否为系统默认(是) | ||||||
|  |      */ | ||||||
|  |     String YES = "Y"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否为系统默认(否) | ||||||
|  |      */ | ||||||
|  |     String NO = "N"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否菜单外链(是) | ||||||
|  |      */ | ||||||
|  |     String YES_FRAME = "0"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否菜单外链(否) | ||||||
|  |      */ | ||||||
|  |     String NO_FRAME = "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"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 超级管理员ID | ||||||
|  |      */ | ||||||
|  |     Long SUPER_ADMIN_ID = 1L; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | package org.dromara.common.core.constant; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 租户常量信息 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | public interface TenantConstants { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 超级管理员ID | ||||||
|  |      */ | ||||||
|  |     Long SUPER_ADMIN_ID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 超级管理员角色 roleKey | ||||||
|  |      */ | ||||||
|  |     String SUPER_ADMIN_ROLE_KEY = "superadmin"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户管理员角色 roleKey | ||||||
|  |      */ | ||||||
|  |     String TENANT_ADMIN_ROLE_KEY = "admin"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户管理员角色名称 | ||||||
|  |      */ | ||||||
|  |     String TENANT_ADMIN_ROLE_NAME = "管理员"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 默认租户ID | ||||||
|  |      */ | ||||||
|  |     String DEFAULT_TENANT_ID = "000000"; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,110 @@ | |||||||
|  | package org.dromara.common.core.domain; | ||||||
|  |  | ||||||
|  | import org.dromara.common.core.constant.HttpStatus; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 响应信息主体 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class R<T> implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     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(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,71 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Objects; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 办理任务请求对象 | ||||||
|  |  * | ||||||
|  |  * @author may | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class CompleteTaskDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 任务id | ||||||
|  |      */ | ||||||
|  |     private Long taskId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 附件id | ||||||
|  |      */ | ||||||
|  |     private String fileId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 抄送人员 | ||||||
|  |      */ | ||||||
|  |     private List<FlowCopyDTO> flowCopyList; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 消息类型 | ||||||
|  |      */ | ||||||
|  |     private List<String> messageType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 办理意见 | ||||||
|  |      */ | ||||||
|  |     private String message; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 消息通知 | ||||||
|  |      */ | ||||||
|  |     private String notice; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程变量 | ||||||
|  |      */ | ||||||
|  |     private Map<String, Object> variables; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 扩展变量(此处为逗号分隔的ossId) | ||||||
|  |      */ | ||||||
|  |     private String ext; | ||||||
|  |  | ||||||
|  |     public Map<String, Object> getVariables() { | ||||||
|  |         if (variables == null) { | ||||||
|  |             return new HashMap<>(16); | ||||||
|  |         } | ||||||
|  |         variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); | ||||||
|  |         return variables; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,37 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 部门 | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class DeptDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门ID | ||||||
|  |      */ | ||||||
|  |     private Long deptId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 父部门ID | ||||||
|  |      */ | ||||||
|  |     private Long parentId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门名称 | ||||||
|  |      */ | ||||||
|  |     private String deptName; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,41 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 字典数据DTO | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class DictDataDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字典标签 | ||||||
|  |      */ | ||||||
|  |     private String dictLabel; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字典键值 | ||||||
|  |      */ | ||||||
|  |     private String dictValue; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 是否默认(Y是 N否) | ||||||
|  |      */ | ||||||
|  |     private String isDefault; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 备注 | ||||||
|  |      */ | ||||||
|  |     private String remark; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,41 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 字典类型DTO | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class DictTypeDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字典主键 | ||||||
|  |      */ | ||||||
|  |     private Long dictId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字典名称 | ||||||
|  |      */ | ||||||
|  |     private String dictName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 字典类型 | ||||||
|  |      */ | ||||||
|  |     private String dictType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 备注 | ||||||
|  |      */ | ||||||
|  |     private String remark; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 抄送 | ||||||
|  |  * | ||||||
|  |  * @author may | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class FlowCopyDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户id | ||||||
|  |      */ | ||||||
|  |     private Long userId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户名称 | ||||||
|  |      */ | ||||||
|  |     private String userName; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * OSS对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class OssDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 对象存储主键 | ||||||
|  |      */ | ||||||
|  |     private Long ossId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 文件名 | ||||||
|  |      */ | ||||||
|  |     private String fileName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 原名 | ||||||
|  |      */ | ||||||
|  |     private String originalName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 文件后缀名 | ||||||
|  |      */ | ||||||
|  |     private String fileSuffix; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * URL地址 | ||||||
|  |      */ | ||||||
|  |     private String url; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,46 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 岗位 | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class PostDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 岗位ID | ||||||
|  |      */ | ||||||
|  |     private Long postId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门id | ||||||
|  |      */ | ||||||
|  |     private Long deptId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 岗位编码 | ||||||
|  |      */ | ||||||
|  |     private String postCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 岗位名称 | ||||||
|  |      */ | ||||||
|  |     private String postName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 岗位类别编码 | ||||||
|  |      */ | ||||||
|  |     private String postCategory; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,42 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 角色 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class RoleDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 角色ID | ||||||
|  |      */ | ||||||
|  |     private Long roleId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 角色名称 | ||||||
|  |      */ | ||||||
|  |     private String roleName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 角色权限 | ||||||
|  |      */ | ||||||
|  |     private String roleKey; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) | ||||||
|  |      */ | ||||||
|  |     private String dataScope; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,45 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  | import java.util.Objects; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 启动流程对象 | ||||||
|  |  * | ||||||
|  |  * @author may | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class StartProcessDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 业务唯一值id | ||||||
|  |      */ | ||||||
|  |     private String businessId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程定义编码 | ||||||
|  |      */ | ||||||
|  |     private String flowCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}} | ||||||
|  |      */ | ||||||
|  |     private Map<String, Object> variables; | ||||||
|  |  | ||||||
|  |     public Map<String, Object> getVariables() { | ||||||
|  |         if (variables == null) { | ||||||
|  |             return new HashMap<>(16); | ||||||
|  |         } | ||||||
|  |         variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); | ||||||
|  |         return variables; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @ -0,0 +1,30 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 启动流程返回对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class StartProcessReturnDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程实例id | ||||||
|  |      */ | ||||||
|  |     private Long processInstanceId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 任务id | ||||||
|  |      */ | ||||||
|  |     private Long taskId; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,101 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.AllArgsConstructor; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.function.Function; | ||||||
|  | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 任务受让人 | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class TaskAssigneeDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 总大小 | ||||||
|  |      */ | ||||||
|  |     private Long total = 0L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * | ||||||
|  |      */ | ||||||
|  |     private List<TaskHandler> list; | ||||||
|  |  | ||||||
|  |     public TaskAssigneeDTO(Long total, List<TaskHandler> list) { | ||||||
|  |         this.total = total; | ||||||
|  |         this.list = list; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 将源列表转换为 TaskHandler 列表 | ||||||
|  |      * | ||||||
|  |      * @param <T>              通用类型 | ||||||
|  |      * @param sourceList       待转换的源列表 | ||||||
|  |      * @param storageId        提取 storageId 的函数 | ||||||
|  |      * @param handlerCode      提取 handlerCode 的函数 | ||||||
|  |      * @param handlerName      提取 handlerName 的函数 | ||||||
|  |      * @param groupName        提取 groupName 的函数 | ||||||
|  |      * @param createTimeMapper 提取 createTime 的函数 | ||||||
|  |      * @return 转换后的 TaskHandler 列表 | ||||||
|  |      */ | ||||||
|  |     public static <T> List<TaskHandler> convertToHandlerList( | ||||||
|  |         List<T> sourceList, | ||||||
|  |         Function<T, Long> storageId, | ||||||
|  |         Function<T, String> handlerCode, | ||||||
|  |         Function<T, String> handlerName, | ||||||
|  |         Function<T, Long> groupName, | ||||||
|  |         Function<T, Date> createTimeMapper) { | ||||||
|  |         return sourceList.stream() | ||||||
|  |             .map(item -> new TaskHandler( | ||||||
|  |                 String.valueOf(storageId.apply(item)), | ||||||
|  |                 handlerCode.apply(item), | ||||||
|  |                 handlerName.apply(item), | ||||||
|  |                 groupName != null ? String.valueOf(groupName.apply(item)) : null, | ||||||
|  |                 createTimeMapper.apply(item) | ||||||
|  |             )).collect(Collectors.toList()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Data | ||||||
|  |     @NoArgsConstructor | ||||||
|  |     @AllArgsConstructor | ||||||
|  |     public static class TaskHandler { | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 主键 | ||||||
|  |          */ | ||||||
|  |         private String storageId; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 权限编码 | ||||||
|  |          */ | ||||||
|  |         private String handlerCode; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 权限名称 | ||||||
|  |          */ | ||||||
|  |         private String handlerName; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 权限分组 | ||||||
|  |          */ | ||||||
|  |         private String groupName; | ||||||
|  |  | ||||||
|  |         /** | ||||||
|  |          * 创建时间 | ||||||
|  |          */ | ||||||
|  |         private Date createTime; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,73 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Date; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户 | ||||||
|  |  * | ||||||
|  |  * @author Michelle.Chung | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class UserDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户ID | ||||||
|  |      */ | ||||||
|  |     private Long userId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门ID | ||||||
|  |      */ | ||||||
|  |     private Long deptId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户账号 | ||||||
|  |      */ | ||||||
|  |     private String userName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户昵称 | ||||||
|  |      */ | ||||||
|  |     private String nickName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户类型(sys_user系统用户) | ||||||
|  |      */ | ||||||
|  |     private String userType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户邮箱 | ||||||
|  |      */ | ||||||
|  |     private String email; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 手机号码 | ||||||
|  |      */ | ||||||
|  |     private String phonenumber; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户性别(0男 1女 2未知) | ||||||
|  |      */ | ||||||
|  |     private String sex; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 帐号状态(0正常 1停用) | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 创建时间 | ||||||
|  |      */ | ||||||
|  |     private Date createTime; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,72 @@ | |||||||
|  | package org.dromara.common.core.domain.dto; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 当前在线会话 | ||||||
|  |  * | ||||||
|  |  * @author ruoyi | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class UserOnlineDTO implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 会话编号 | ||||||
|  |      */ | ||||||
|  |     private String tokenId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门名称 | ||||||
|  |      */ | ||||||
|  |     private String deptName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户名称 | ||||||
|  |      */ | ||||||
|  |     private String userName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 客户端 | ||||||
|  |      */ | ||||||
|  |     private String clientKey; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设备类型 | ||||||
|  |      */ | ||||||
|  |     private String deviceType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录IP地址 | ||||||
|  |      */ | ||||||
|  |     private String ipaddr; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录地址 | ||||||
|  |      */ | ||||||
|  |     private String loginLocation; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 浏览器类型 | ||||||
|  |      */ | ||||||
|  |     private String browser; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 操作系统 | ||||||
|  |      */ | ||||||
|  |     private String os; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 登录时间 | ||||||
|  |      */ | ||||||
|  |     private Long loginTime; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,34 @@ | |||||||
|  | package org.dromara.common.core.domain.event; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 删除流程监听 | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class ProcessDeleteEvent implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户ID | ||||||
|  |      */ | ||||||
|  |     private String tenantId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程定义编码 | ||||||
|  |      */ | ||||||
|  |     private String flowCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 业务id | ||||||
|  |      */ | ||||||
|  |     private String businessId; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,65 @@ | |||||||
|  | package org.dromara.common.core.domain.event; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 总体流程监听 | ||||||
|  |  * | ||||||
|  |  * @author may | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class ProcessEvent implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户ID | ||||||
|  |      */ | ||||||
|  |     private String tenantId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程定义编码 | ||||||
|  |      */ | ||||||
|  |     private String flowCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 业务id | ||||||
|  |      */ | ||||||
|  |     private String businessId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) | ||||||
|  |      */ | ||||||
|  |     private Integer nodeType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程节点编码 | ||||||
|  |      */ | ||||||
|  |     private String nodeCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程节点名称 | ||||||
|  |      */ | ||||||
|  |     private String nodeName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程状态 | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 办理参数 | ||||||
|  |      */ | ||||||
|  |     private Map<String, Object> params; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 当为true时为申请人节点办理 | ||||||
|  |      */ | ||||||
|  |     private Boolean submit; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,59 @@ | |||||||
|  | package org.dromara.common.core.domain.event; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 流程办理监听 | ||||||
|  |  * | ||||||
|  |  * @author may | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | public class ProcessTaskEvent implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户ID | ||||||
|  |      */ | ||||||
|  |     private String tenantId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程定义编码 | ||||||
|  |      */ | ||||||
|  |     private String flowCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) | ||||||
|  |      */ | ||||||
|  |     private Integer nodeType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程节点编码 | ||||||
|  |      */ | ||||||
|  |     private String nodeCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程节点名称 | ||||||
|  |      */ | ||||||
|  |     private String nodeName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 任务id | ||||||
|  |      */ | ||||||
|  |     private Long taskId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 业务id | ||||||
|  |      */ | ||||||
|  |     private String businessId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 流程状态 | ||||||
|  |      */ | ||||||
|  |     private String status; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.Email; | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 邮件登录对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | public class EmailLoginBody extends LoginBody { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 邮箱 | ||||||
|  |      */ | ||||||
|  |     @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; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,48 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户登录对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | public class LoginBody implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 客户端id | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{auth.clientid.not.blank}") | ||||||
|  |     private String clientId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 授权类型 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{auth.grant.type.not.blank}") | ||||||
|  |     private String grantType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户ID | ||||||
|  |      */ | ||||||
|  |     private String tenantId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 验证码 | ||||||
|  |      */ | ||||||
|  |     private String code; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 唯一标识 | ||||||
|  |      */ | ||||||
|  |     private String uuid; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,148 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  | import org.dromara.common.core.domain.dto.PostDTO; | ||||||
|  | import org.dromara.common.core.domain.dto.RoleDTO; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Set; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 登录用户身份权限 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class LoginUser implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 租户ID | ||||||
|  |      */ | ||||||
|  |     private String tenantId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户ID | ||||||
|  |      */ | ||||||
|  |     private Long userId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门ID | ||||||
|  |      */ | ||||||
|  |     private Long deptId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门类别编码 | ||||||
|  |      */ | ||||||
|  |     private String deptCategory; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 部门名 | ||||||
|  |      */ | ||||||
|  |     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 String nickname; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 角色对象 | ||||||
|  |      */ | ||||||
|  |     private List<RoleDTO> roles; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 岗位对象 | ||||||
|  |      */ | ||||||
|  |     private List<PostDTO> posts; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 数据权限 当前角色ID | ||||||
|  |      */ | ||||||
|  |     private Long roleId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 客户端 | ||||||
|  |      */ | ||||||
|  |     private String clientKey; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 设备类型 | ||||||
|  |      */ | ||||||
|  |     private String deviceType; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 获取登录id | ||||||
|  |      */ | ||||||
|  |     public String getLoginId() { | ||||||
|  |         if (userType == null) { | ||||||
|  |             throw new IllegalArgumentException("用户类型不能为空"); | ||||||
|  |         } | ||||||
|  |         if (userId == null) { | ||||||
|  |             throw new IllegalArgumentException("用户ID不能为空"); | ||||||
|  |         } | ||||||
|  |         return userType + ":" + userId; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,31 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  | import org.hibernate.validator.constraints.Length; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 密码登录对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | public class PasswordLoginBody extends LoginBody { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户名 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{user.username.not.blank}") | ||||||
|  |     @Length(min = 2, max = 20, message = "{user.username.length.valid}") | ||||||
|  |     private String username; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户密码 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{user.password.not.blank}") | ||||||
|  |     @Length(min = 5, max = 20, message = "{user.password.length.valid}") | ||||||
|  |     private String password; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,33 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  | import org.hibernate.validator.constraints.Length; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 用户注册对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | public class RegisterBody extends LoginBody { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户名 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{user.username.not.blank}") | ||||||
|  |     @Length(min = 2, max = 20, message = "{user.username.length.valid}") | ||||||
|  |     private String username; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 用户密码 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{user.password.not.blank}") | ||||||
|  |     @Length(min = 5, max = 20, message = "{user.password.length.valid}") | ||||||
|  |     private String password; | ||||||
|  |  | ||||||
|  |     private String userType; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,29 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 短信登录对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | public class SmsLoginBody extends LoginBody { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 手机号 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{user.phonenumber.not.blank}") | ||||||
|  |     private String phonenumber; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 短信code | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{sms.code.not.blank}") | ||||||
|  |     private String smsCode; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,35 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 三方登录对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | public class SocialLoginBody extends LoginBody { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 第三方登录平台 | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{social.source.not.blank}") | ||||||
|  |     private String source; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 第三方登录code | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{social.code.not.blank}") | ||||||
|  |     private String socialCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 第三方登录socialState | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{social.state.not.blank}") | ||||||
|  |     private String socialState; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,56 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.NoArgsConstructor; | ||||||
|  |  | ||||||
|  | import java.io.Serial; | ||||||
|  | import java.io.Serializable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 任务受让人 | ||||||
|  |  * | ||||||
|  |  * @author AprilWind | ||||||
|  |  */ | ||||||
|  | @Data | ||||||
|  | @NoArgsConstructor | ||||||
|  | public class TaskAssigneeBody implements Serializable { | ||||||
|  |  | ||||||
|  |     @Serial | ||||||
|  |     private static final long serialVersionUID = 1L; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 权限编码 | ||||||
|  |      */ | ||||||
|  |     private String handlerCode; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 权限名称 | ||||||
|  |      */ | ||||||
|  |     private String handlerName; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 权限分组 | ||||||
|  |      */ | ||||||
|  |     private String groupId; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 开始时间 | ||||||
|  |      */ | ||||||
|  |     private String beginTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 结束时间 | ||||||
|  |      */ | ||||||
|  |     private String endTime; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 当前页 | ||||||
|  |      */ | ||||||
|  |     private Integer pageNum = 1; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 每页显示条数 | ||||||
|  |      */ | ||||||
|  |     private Integer pageSize = 10; | ||||||
|  |  | ||||||
|  | } | ||||||
| @ -0,0 +1,28 @@ | |||||||
|  | package org.dromara.common.core.domain.model; | ||||||
|  |  | ||||||
|  | import jakarta.validation.constraints.NotBlank; | ||||||
|  | import lombok.Data; | ||||||
|  | import lombok.EqualsAndHashCode; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * 三方登录对象 | ||||||
|  |  * | ||||||
|  |  * @author Lion Li | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | @Data | ||||||
|  | @EqualsAndHashCode(callSuper = true) | ||||||
|  | public class XcxLoginBody extends LoginBody { | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 小程序id(多个小程序时使用) | ||||||
|  |      */ | ||||||
|  |     private String appid; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * 小程序code | ||||||
|  |      */ | ||||||
|  |     @NotBlank(message = "{xcx.code.not.blank}") | ||||||
|  |     private String xcxCode; | ||||||
|  |  | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user