liu
2026-09-22 0837c3ff473499d8a267924125c776b34cc8b517
feat(cj): 接入江苏商贸职业学院产教融合后端,替换原有业务代码

- 引入若依 RuoYi 3.9.2 后端全部模块(ruoyi-admin/common/framework/generator/quartz/system)
- 含管理端 ruoyi-ui、数据库脚本 sql/、开发启动脚本与 doc 手册
- 移除原有 src/main 下的售后/账务等业务代码

Co-Authored-By: Claude <noreply@anthropic.com>
已删除1,059个文件
已添加665个文件
已修改5个文件
已重命名6个文件
177866 ■■■■■ 文件已修改
.gitignore 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/run-tomcat.bat 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/run.bat 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/start-prod.sh 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/stop-prod.sh 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/add.sql 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/若依环境使用手册.docx 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 497 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/pom.xml 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/HealthController.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/miniapp/MiniappAccountController.java 440 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/miniapp/MiniappCaptchaService.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/miniapp/MiniappController.java 854 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-druid.yml 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-prod.yml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application.yml 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/banner.txt 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/i18n/messages.properties 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/logback.xml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java 198 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java 204 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java 203 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java 1018 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/filter/RefererFilter.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java 921 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java 260 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java 303 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java 570 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java 293 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/UserAgentUtils.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelSheet.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java 2067 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java 412 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java 484 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/pom.xml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/pom.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java 264 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java 411 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java 564 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java 492 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/generator.yml 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/controller.java.vm 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/domain.java.vm 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/mapper.java.vm 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/service.java.vm 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/js/api.js.vm 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/sql/sql.vm 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/ts/api.ts.vm 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/ts/index.ts.vm 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/ts/type.ts.vm 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm 565 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm 660 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm 526 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm 639 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3/view.vue.vm 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3ts/index-tree.vue.vm 528 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3ts/index.vue.vm 644 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3ts/view.vue.vm 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/view.vue.vm 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/pom.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/pom.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjClassController.java 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjCollegeController.java 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjFillTaskController.java 806 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjFormConfigController.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjMajorController.java 277 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjStudentBindController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjStudentController.java 702 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/controller/CjWorkbenchController.java 418 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjClass.java 199 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjCollege.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjFillRecord.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjFillTask.java 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjFormConfig.java 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjMajor.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjStudent.java 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/CjStudentBind.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNoticeRead.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjClassMapper.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjCollegeMapper.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjFillRecordMapper.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjFillTaskMapper.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjFormConfigMapper.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjMajorMapper.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjStudentBindMapper.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjStudentMapper.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeReadMapper.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjClassService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjCollegeService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjFillTaskService.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjFormConfigService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjMajorService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjStudentBindService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ICjStudentService.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeReadService.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java 217 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/MiniappTokenService.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjClassServiceImpl.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjCollegeServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjFillTaskServiceImpl.java 364 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjFormConfigServiceImpl.java 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjMajorServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjStudentBindServiceImpl.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjStudentServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java 364 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java 618 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeReadServiceImpl.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java 426 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java 565 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/form/builtinDefault.json 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjClassMapper.xml 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjCollegeMapper.xml 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjFillRecordMapper.xml 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjFillTaskMapper.xml 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjFormConfigMapper.xml 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjMajorMapper.xml 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjStudentBindMapper.xml 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/CjStudentMapper.xml 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysNoticeReadMapper.xml 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/.env.development 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/.env.production 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/.env.staging 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/.github/FUNDING.yml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/.gitignore 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/LICENSE 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/README.md 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/bin/build.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/bin/package.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/bin/run-web.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/html/ie.html 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/index.html 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/package.json 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/App.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/login.js 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/menu.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/cache.js 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/job.js 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/jobLog.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/logininfor.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/online.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/operlog.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/monitor/server.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/class.js 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/college.js 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/config.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/dept.js 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/dict/data.js 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/dict/type.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/formConfig.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/formTask.js 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/major.js 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/menu.js 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/notice.js 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/post.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/role.js 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/student.js 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/user.js 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/system/workbench.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/api/tool/gen.js 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/401_images/401.gif 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/404_images/404.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/404_images/404_cloud.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/404.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/bell.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/bug.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/build.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/button.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/cascader.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/chart.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/checkbox.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/clipboard.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/code.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/color.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/component.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/dashboard.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/date-range.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/date.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/dict.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/documentation.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/download.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/drag.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/druid.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/edit.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/education.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/email.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/enter.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/example.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/excel.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/exit-fullscreen.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/eye-open.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/eye.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/form.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/fullscreen.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/github.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/guide.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/icon.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/input.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/international.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/job.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/language.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/link.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/list.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/lock.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/log.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/logininfor.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/message.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/money.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/monitor.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/moon.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/more-up.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/nested.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/number.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/online.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/password.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/pdf.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/people.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/peoples.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/phone.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/post.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/qq.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/question.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/radio.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/rate.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/redis-list.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/redis.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/row.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/search.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/select.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/server.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/shopping.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/size.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/skill.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/slider.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/star.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/sunny.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/swagger.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/switch.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/system.svg 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/tab.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/table.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/textarea.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/theme.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/time-range.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/time.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/tool.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/tree-table.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/tree.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/upload.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/user.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/validCode.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/wechat.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/icons/svg/zip.svg 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/brand/logo-navy.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/brand/logo-white.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/dark.svg 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/light.svg 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/login-background.jpg 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/pay.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/images/profile.jpg 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/logo/logo-white.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/logo/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/btn.scss 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/element-ui.scss 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/index.scss 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/mixin.scss 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/ruoyi.scss 506 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/sidebar.scss 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/transition.scss 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/assets/styles/variables.module.scss 448 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Breadcrumb/index.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/day.vue 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/hour.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/index.vue 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/min.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/month.vue 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/result.vue 540 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/second.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/week.vue 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Crontab/year.vue 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/DictTag/index.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Editor/index.vue 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/ExcelImportDialog/index.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/FileUpload/index.vue 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Hamburger/index.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/HeaderSearch/index.vue 397 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/IconSelect/index.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/IconSelect/requireIcons.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/ImagePreview/index.vue 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/ImageUpload/index.vue 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Pagination/index.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/ParentView/index.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/RightToolbar/index.vue 249 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/RuoYi/Doc/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/RuoYi/Git/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/Screenfull/index.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/SizeSelect/index.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/SvgIcon/index.vue 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/SvgIcon/svgicon.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/TreePanel/index.vue 756 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/components/iFrame/index.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/directive/common/copyText.js 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/directive/index.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/directive/permission/hasPermi.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/directive/permission/hasRole.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/AppMain.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Copyright/index.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/HeaderNotice/DetailView.vue 326 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/HeaderNotice/index.vue 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/IframeToggle/index.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/InnerLink/index.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Navbar.vue 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Settings/index.vue 344 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Sidebar/Link.vue 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Sidebar/Logo.vue 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/Sidebar/index.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/TagsView/index.vue 712 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/TopBar/index.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/TopNav/index.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/components/index.js 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/layout/index.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/main.js 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/permission.js 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/plugins/auth.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/plugins/cache.js 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/plugins/download.js 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/plugins/index.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/plugins/modal.js 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/plugins/tab.js 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/router/index.js 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/settings.js 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/index.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/app.js 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/dict.js 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/lock.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/permission.js 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/settings.js 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/tagsView.js 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/store/modules/user.js 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/auth.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/dict.js 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/dynamicTitle.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/errorCode.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/config.js 452 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/css.js 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/drawingDefault.js 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/html.js 359 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/icon.json 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/js.js 370 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/generator/render.js 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/index.js 390 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/jsencrypt.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/passwordRule.js 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/permission.js 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/qrcode-lite.js 585 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/region.js 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/request.js 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/ruoyi.js 228 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/scroll-to.js 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/theme.js 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/utils/validate.js 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/error/401.vue 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/error/404.vue 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/index.vue 546 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/lock.vue 374 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/login.vue 379 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/monitor/logininfor/index.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/redirect/index.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/class/index.vue 651 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/college/index.vue 367 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/config/index.vue 316 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/dept/index.vue 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/dict/data.vue 362 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/dict/detail.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/dict/index.vue 346 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/fillData/index.vue 359 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/formConfig/index.vue 556 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/formTask/index.vue 466 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/major/index.vue 396 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/menu/index.vue 508 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/notice/ReadUsers.vue 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/notice/index.vue 306 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/post/index.vue 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/role/authUser.vue 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/role/index.vue 584 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/role/selectUser.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/student/index.vue 512 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/authRole.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/index.vue 459 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/profile/index.vue 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/profile/resetPwd.vue 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/profile/userAvatar.vue 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/profile/userInfo.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/system/user/view.vue 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/tool/gen/basicInfoForm.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/tool/gen/createTable.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/tool/gen/editTable.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/tool/gen/genInfoForm.vue 328 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/tool/gen/importTable.vue 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/src/views/tool/gen/index.vue 309 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/vite.config.js 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/vite/plugins/auto-import.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/vite/plugins/compression.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/vite/plugins/index.js 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/vite/plugins/setup-extend.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-ui/vite/plugins/svg-icon.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ry.bat 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ry.sh 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/quartz.sql 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/ry_20260417.sql 723 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/RuoYiApplication.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/RuoYiServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/controller/AccountExpenseController.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/controller/AccountFileController.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/controller/AccountIncomeController.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/dto/AccountDto.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/dto/AccountDto2.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/dto/AccountDto3.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/mapper/AccountExpenseMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/mapper/AccountFileMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/mapper/AccountIncomeMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/pojo/AccountExpense.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/pojo/AccountFile.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/pojo/AccountIncome.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/AccountExpenseService.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/AccountFileService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/AccountIncomeService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/impl/AccountFileServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceDto.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/aftersalesservice/mapper/AfterSalesServiceMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/aftersalesservice/service/AfterSalesServiceService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/api/Api.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/api/ScheduledApi.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/api/dto/ApiProperties.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/api/dto/DataRequest.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/api/dto/ElectricityDto.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/api/dto/LoggingDto.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/AnnualLeaveSettingMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/ApproveLogMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/ApproveNodeMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/FileSharingMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/HolidaySettingsMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/KnowledgeBaseMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/NotificationManagementMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/OnlineMeetingMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/OvertimeSettingMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/RpaProcessAutomationMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/mapper/WorkingHoursSettingMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/ApproveLog.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/ApproveNode.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/FileSharing.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/HolidaySettingsService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/IApproveNodeService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/IApproveProcessService.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/KnowledgeBaseService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/NotificationManagementService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/RpaProcessAutomationService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/utils/ListToStringTypeHandler.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/vo/ApproveGetAndUpdateVo.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/vo/ApproveProcessVO.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/CustomerController.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/ProductController.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/SupplierManageController.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/ProductDto.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/ProductModelDto.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/ProductMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/StorageAttachmentMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/Customer.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/Product.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/StorageBlob.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/SupplierManage.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/ICustomerService.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/IProductModelService.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/IProductService.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/ISupplierService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/StorageBlobService.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java 211 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/DutyPlanDTO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/MeetUseDto.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/MeetingItem.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/MeetingSimpleDto.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/NoticeDTO.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/RulesRegulationsManagementDTO.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/SealApplicationManagementDTO.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/dto/StaffContactsPersonalDTO.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/DutyPlanMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetApplicationMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetDraftMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetingMinutesMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetingRoomMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/NoticeMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/ReadingStatusMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/RulesRegulationsManagementMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/SealApplicationManagementMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/mapper/StaffContactsPersonalMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/MeetingService.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/NoticeService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/RulesRegulationsManagementService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/SealApplicationManagementService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/StaffContactsPersonalService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/NoticeServiceImpl.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingApplicationVo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingDraftVo.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingRoomVo.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingUseVo.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/MinioConfig.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/MyBaseMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/MybatisHandler.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/config/TomcatConfig.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/CacheConstants.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/Constants.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/GenConstants.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/HttpStatus.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/ScheduleConstants.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/StorageAttachmentConstants.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/constant/UserConstants.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/core/text/CharsetKit.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/core/text/Convert.java 1012 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/core/text/StrFormatter.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/FileNameType.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/HttpMethod.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/SalesLedgerType.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/UserStatus.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/DemoModeException.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/GlobalException.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/ServiceException.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/UtilException.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/base/BaseException.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/file/FileException.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/job/TaskException.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/user/CaptchaException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/user/UserException.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/filter/RepeatableFilter.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/filter/XssFilter.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/handler/CustomTenantLineHandler.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/Arith.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/DateUtils.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/DictUtils.java 239 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/ExceptionUtil.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/HackLoopTableRenderPolicy.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/LogUtils.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/MessageUtils.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/MinioUtils.java 433 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/OrderUtils.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/PageUtils.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/SecurityUtils.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/ServletUtils.java 218 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/StringUtils.java 722 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/Threads.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/excel/ConfigurableMergeStrategy.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/excel/CustomCellStyleHandler.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/excel/ExcelClassField.java 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/excel/ExcelExport.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/excel/ExcelImport.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java 1039 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/file/FileUtils.java 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/file/ImageUtils.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java 570 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/http/HttpHelper.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/http/HttpUtils.java 293 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/ip/IpUtils.java 382 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/job/AbstractQuartzJob.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/job/CronUtils.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/job/JobInvokeUtil.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/job/QuartzDisallowConcurrentExecution.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/job/QuartzJobExecution.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/job/ScheduleUtils.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java 1897 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java 410 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/sign/Base64.java 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/uuid/Seq.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/uuid/UUID.java 484 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/vo/FileVo.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/xss/Xss.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/xss/XssValidator.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/compensationperformance/mapper/CompensationPerformanceMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/compensationperformance/service/CompensationPerformanceService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/mapper/CustomerVisitsMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/service/CustomerVisitsService.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/DeviceRepairController.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceMonthlyRepairTableDTO.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/dto/RepairAmountGroupDTO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/DeviceDefectRecordMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/DeviceLedgerMapper.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceFileMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/mapper/MaintenanceTaskMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceLedger.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/DeviceRepair.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/DeviceDefectRecordService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/DeviceMaintenanceFileService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/IDeviceRepairService.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceFileServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java 215 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java 278 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/dto/DateQueryDto.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/dto/MapDto.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/dto/PageDto.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/mapper/ElectricityConsumptionAreaMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/mapper/EnergyPeriodMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/mapper/EquipmentEnergyConsumptionMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/service/ElectricityConsumptionAreaService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/service/EnergyPeriodService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/service/EquipmentEnergyConsumptionService.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/LogAspect.java 256 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Anonymous.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataSource.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excel.java 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excels.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Log.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/RateLimiter.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Sensitive.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessStatus.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessType.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/enums/DataSourceType.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/enums/DesensitizedType.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/enums/LimitType.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/aspectj/lang/enums/OperatorType.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/ApplicationConfig.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/CaptchaConfig.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/DruidConfig.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/FilterConfig.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/GenConfig.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/RedisConfig.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/ResourcesConfig.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/RuoYiConfig.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/ScheduleConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/SecurityConfig.java 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/SensitiveJsonSerializer.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/ServerConfig.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/SwaggerConfig.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/manager/AsyncManager.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/manager/ShutdownManager.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/redis/RedisCache.java 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/LoginBody.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/LoginUser.java 320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/RegisterBody.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/PermissionService.java 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/SysLoginService.java 284 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/TokenService.java 253 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/task/RyTask.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/controller/BaseController.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/MinioResult.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/R.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/Server.java 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/TreeEntity.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/TreeSelect.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/server/Mem.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/server/Sys.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java 145 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/page/PageDomain.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/framework/web/page/TableSupport.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/controller/HomeController.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/HomeService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java 409 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/StorageAttachmentRecordType.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/dto/QrCodeDto.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/dto/TimingTaskDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/mapper/InspectionTaskMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeScanRecordMapper.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/mapper/TimingTaskMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/QrCodeScanRecordService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/QrCodeService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java 240 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/SpringContextHolder.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java 463 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/lavorissue/mapper/LavorIssueMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java 365 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java 126 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsDto.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/mapper/MeasuringInstrumentLedgerMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/mapper/MeasuringInstrumentLedgerRecordMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/mapper/SparePartsMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/SparePartsService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/controller/OaProjectController.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/dto/OaProjectDto.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/dto/OaProjectPhaseDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/mapper/OaProjectMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/mapper/OaProjectPhaseMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/mapper/OaProjectPhaseTaskMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/pojo/OaProject.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/service/OaProjectPhaseService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/service/OaProjectPhaseTaskService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/service/OaProjectService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseTaskServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/officesupplies/mapper/OfficeSuppliesMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/officesupplies/service/OfficeSuppliesService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/controller/TempFileController.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/mapper/TempFileMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/pojo/TempFile.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/service/TempFileService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/Details.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementAddDto.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementDto.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementManagementUpdateDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutAdd.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutPageDto.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/dto/ProcurementUpdateDto.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/GasTankWarningMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/InboundManagementMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPlanMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPriceManagementMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementRecordMapper.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementRecordOutMapper.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/mapper/ReturnManagementMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/InboundManagementService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/ReturnManagementService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java 477 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/SalesLedgerProductionAccountingController.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/SalesLedgerSchedulingController.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/SalesLedgerWorkController.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/DaiDto.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProcessSchedulingDto.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductionReportDto.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SalesLedgerProductionAccountingDto.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingDto.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingProcessDto.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/SalesLedgerWorkDto.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/SalesLedgerProductionAccountingMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/SalesLedgerSchedulingMapper.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/SalesLedgerWorkMapper.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/SalesLedgerProductionAccounting.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/SalesLedgerScheduling.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/SalesLedgerWork.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/SalesLedgerSchedulingService.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/SalesLedgerWorkService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/common/CaptchaController.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/common/CommonController.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/CacheController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/ServerController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java 185 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/domain/SysCache.java 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/domain/SysJob.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/domain/SysJobLog.java 155 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/domain/SysLogininfor.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/domain/SysOperLog.java 269 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/domain/SysUserOnline.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/mapper/SysJobLogMapper.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/mapper/SysJobMapper.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/mapper/SysLogininforMapper.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/mapper/SysOperLogMapper.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/ISysJobLogService.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/ISysJobService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/ISysLogininforService.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/ISysOperLogService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysConfigController.java 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysDeptController.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysIndexController.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysLoginController.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysMenuController.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysPostController.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysProfileController.java 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysRoleController.java 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/controller/SysUserController.java 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysConfig.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysDept.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysDictData.java 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysDictType.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysMenu.java 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysNotice.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysPost.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysRole.java 241 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysRoleDept.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysRoleMenu.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysUser.java 377 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysUserDept.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysUserPost.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/SysUserRole.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/vo/MetaVo.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/vo/RouterVo.java 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysConfigMapper.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysDictDataMapper.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysDictTypeMapper.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysNoticeMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysPostMapper.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysRoleDeptMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysRoleMenuMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserPostMapper.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/mapper/SysUserRoleMapper.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysConfigService.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysDeptService.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysMenuService.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysPostService.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysRoleService.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysUserDeptService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysUserOnlineService.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/ISysUserService.java 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java 229 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java 348 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java 223 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java 543 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java 427 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java 581 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java 263 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java 385 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java 373 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableColumnMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableMapper.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java 531 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/service/IGenTableService.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/util/VelocityInitializer.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/gen/util/VelocityUtils.java 408 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/project/tool/swagger/TestController.java 183 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseDto.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseReportDto.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PaymentHistoryRecordVo.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PaymentLedgerDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PaymentRegistrationDto.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/ProductRecordDto.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/TicketRegistrationDto.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/dto/VatDto.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/InvoicePurchaseMapper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/PaymentRegistrationMapper.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/ProductRecordMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/TicketRegistrationMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java 166 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/IInvoicePurchaseService.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/IPaymentRegistrationService.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/IProductRecordService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/ITicketRegistrationService.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java 535 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java 538 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java 472 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/controller/QualityInspectController.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/mapper/QualityInspectFileMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/mapper/QualityInspectParamMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/mapper/QualityTestStandardMapper.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/pojo/QualityInspect.java 142 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/IQualityInspectFileService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/IQualityInspectParamService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/IQualityInspectService.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/IQualityTestStandardService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityInspectFileServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityInspectParamServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/CommonFileController.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 321 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/CustomerInteractionDto.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/MonthlyAmountDto.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/CommonFileMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerFileMapper.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationMapper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationProductMapper.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/PaymentShippingMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/ReceiptPaymentMapper.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesQuotationMapper.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalesQuotationProductMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/SalespersonManagementMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/CommonFile.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ICommonFileService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/PaymentShippingService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/SalesQuotationProductService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/SalesQuotationService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/SalespersonManagementService.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ShippingInfoService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java 483 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java 324 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 656 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesQuotationProductServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/vo/SalesLedgerProductVo.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/vo/ShippingInfoVo.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/controller/StaffJoinLeaveRecordController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/dto/StaffSchedulingDto.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/mapper/HolidayApplicationMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/mapper/PersonalAttendanceRecordsMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/mapper/StaffJoinLeaveRecordMapper.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/mapper/StaffSchedulingMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/pojo/StaffJoinLeaveRecord.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/HolidayApplicationService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/IStaffJoinLeaveRecordService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/StaffSchedulingService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffJoinLeaveRecordServiceImpl.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/staff/vo/SearchSchedulingVo.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/DocumentClassificationDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/DocumentClassificationTreeDto.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/DocumentationDto.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/DocumentationReturnManagementDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/WarehouseDto.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/WarehouseGoodsShelvesDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/WarehouseGoodsShelvesRowcolDto.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/dto/WarehouseTreeDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/DocumentClassificationMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/DocumentationMapper.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/DocumentationReturnManagementMapper.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/WarehouseGoodsShelvesMapper.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/WarehouseGoodsShelvesRowcolMapper.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/mapper/WarehouseMapper.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/Documentation.java 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/DocumentClassificationService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/DocumentationService.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/WarehouseGoodsShelvesRowcolService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/WarehouseGoodsShelvesService.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/WarehouseService.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/DocumentationFileServiceImpl.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/waterrecord/mapper/WaterRecordMapper.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/waterrecord/service/WaterRecordService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-aynm.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-bdsm.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-bhmy.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-cjny.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-cmny.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-demo.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dev.yml 258 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dhdc.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-druid.yml 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-dzys.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hbkj.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hbxm.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hckx.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hcmy.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hhkj.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hsmy.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hsxny.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hxgy.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hxsj.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-hysn.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-jjxm.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-jlsn.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-jmsl.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-jsmy.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-jsyny.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-jyhj.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-khl.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-mkzs.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-mqsp.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-mxsc.yml 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-nydl.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-phmk.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-prod.yml 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-qlmc.yml 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-rzny.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-test.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-test1.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-tjxm.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-trsw.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-tymk.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-wdsy.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-xyhb.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-zjyj.yml 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-zqhx.yml 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-zyrq.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application-zyrqCopy.yml 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/banner.txt 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/i18n/messages.properties 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/logback.xml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/account/AccountExpenseMapper.xml 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/account/AccountFileMapper.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/account/AccountIncomeMapper.xml 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/aftersalesservice/AfterSalesServiceMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/AnnualLeaveSettingMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/ApproveLogMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/ApproveNodeMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/ApproveProcessMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/FileSharingMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/HolidaySettingsMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/KnowledgeBaseMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/NotificationManagementMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/OnlineMeetingMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/OvertimeSettingMapper.xml 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/RpaProcessAutomationMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/approve/WorkingHoursSettingMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/StorageAttachmentMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/StorageBlobMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/basic/SupplierManageMapper.xml 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/DutyPlanMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/MeetApplicationMapper.xml 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/MeetDraftMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/MeetingMinutesMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/MeetingRoomMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/NoticeMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/ReadingStatusMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/RulesRegulationsManagementMapper.xml 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/SealApplicationManagementMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/collaborativeApproval/StaffContactsPersonalMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/compensationperformance/CompensationPerformanceMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/customervisits/CustomerVisitsMapper.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceDefectRecordMapper.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceLedgerMapper.xml 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceMaintenanceMapper.xml 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/device/DeviceRepairMapper.xml 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/equipmentenergyconsumption/EnergyPeriodMapper.xml 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/equipmentenergyconsumption/EquipmentEnergyConsumptionMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/equipmentenergyconsumption/electricityConsumptionAreaMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/inspectiontask/TimingTaskMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/lavorissue/LavorIssueMapper.xml 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerRecordMapper.xml 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/measuringinstrumentledger/SparePartsMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/monitor/SysLogininforMapper.xml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/monitor/SysOperLogMapper.xml 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/oA/OaProjectMapper.xml 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/oA/OaProjectPhaseMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/oA/OaProjectPhaseTaskMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/officesupplies/OfficeSuppliesMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/GasTankWarningMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/InboundManagementMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementPlanMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ProcurementRecordOutMapper.xml 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/SalesLedgerWorkMapper.xml 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/ProductRecordMapper.xml 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityInspectFileMapper.xml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityInspectMapper.xml 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityInspectParamMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityTestStandardMapper.xml 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/InvoiceLedgerMapper.xml 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/InvoiceRegistrationMapper.xml 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/InvoiceRegistrationProductMapper.xml 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/PaymentShippingMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/ReceiptPaymentMapper.xml 430 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerMapper.xml 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesQuotationMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesQuotationProductMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalespersonManagementMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/ShippingInfoMapper.xml 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/HolidayApplicationMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/PersonalAttendanceRecordsMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/StaffJoinLeaveRecordMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/StaffOnJobMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/staff/StaffSchedulingMapper.xml 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysConfigMapper.xml 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysDeptMapper.xml 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysDictDataMapper.xml 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysDictTypeMapper.xml 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysJobLogMapper.xml 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysJobMapper.xml 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysMenuMapper.xml 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysNoticeMapper.xml 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysPostMapper.xml 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysRoleDeptMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysRoleMapper.xml 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysRoleMenuMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysUserDeptMapper.xml 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysUserMapper.xml 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysUserPostMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/system/SysUserRoleMapper.xml 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/tool/GenTableColumnMapper.xml 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/tool/GenTableMapper.xml 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/DocumentClassificationMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/DocumentationBorrowManagementMapper.xml 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/DocumentationFileMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/DocumentationMapper.xml 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/DocumentationReturnManagementMapper.xml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/WarehouseGoodsShelvesMapper.xml 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/WarehouseGoodsShelvesRowcolMapper.xml 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/warehouse/WarehouseMapper.xml 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/waterrecord/WaterRecordMapper.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mybatis/mybatis-config.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/static/report-template.docx 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/java/controller.java.vm 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/java/domain.java.vm 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/java/mapper.java.vm 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/java/service.java.vm 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/java/serviceImpl.java.vm 162 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/java/sub-domain.java.vm 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/js/api.js.vm 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/sql/sql.vm 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/vue/index-tree.vue.vm 505 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/vue/index.vue.vm 602 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/vue/v3/index-tree.vue.vm 474 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/vue/v3/index.vue.vm 590 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/vm/xml/mapper.xml.vm 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
start-dev.cmd 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -23,12 +23,11 @@
.idea
*.iws
*.iml
### vscode ###
.vscode
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
@@ -45,4 +44,16 @@
!*/build/*.java
!*/build/*.html
!*/build/*.xml
!*/build/*.xml
######################################################################
# é¡¹ç›®å®‰å…¨ï¼šæ—¥å¿— / ä¸Šä¼ æ–‡ä»¶ / æœ¬åœ°å¯†é’¥ï¼ˆå‹¿æäº¤ï¼‰
######################################################################
ruoyi-admin/logs/
uploadPath/
/logs/
*.log
D:/ruoyi/
/tmp/
*.key
*.pem
README.md
@@ -1,26 +1,47 @@
<p align="center">
    <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
</p>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.9</h1>
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.9.2</h1>
<h4 align="center">基于SpringBoot+Vue前后端分离的Java快速开发框架</h4>
<p align="center">
    <a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
    <a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.9-brightgreen.svg"></a>
    <a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.9.2-brightgreen.svg"></a>
    <a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
</p>
## å¹³å°ç®€ä»‹
* æœ¬ä»“库为RuoYi-Vue的单应用版本,保持同步更新。
* é…å¥—前端代码地址[RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue/tree/master/ruoyi-ui),技术栈([Vue2](https://cn.vuejs.org) + [Element](https://github.com/ElemeFE/element) + [Vue CLI](https://cli.vuejs.org/zh))。
* é…å¥—前端代码地址[RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3),技术栈([Vue3](https://v3.cn.vuejs.org) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev))。
* å‰ç«¯é‡‡ç”¨Vue、Element UI。
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* å‰ç«¯é‡‡ç”¨Vue、Element(提供 Vue2/Vue3/TS å¤šç‰ˆæœ¬ï¼‰ã€‚
* åŽç«¯é‡‡ç”¨Spring Boot、Spring Security、Redis & Jwt。
* æƒé™è®¤è¯ä½¿ç”¨Jwt,支持多终端认证系统。
* æ”¯æŒåŠ è½½åŠ¨æ€æƒé™èœå•ï¼Œå¤šæ–¹å¼è½»æ¾æƒé™æŽ§åˆ¶ã€‚
* é«˜æ•ˆçŽ‡å¼€å‘ï¼Œä½¿ç”¨ä»£ç ç”Ÿæˆå™¨å¯ä»¥ä¸€é”®ç”Ÿæˆå‰åŽç«¯ä»£ç ã€‚
* ä¸åˆ†ç¦»ç‰ˆæœ¬ï¼Œè¯·ç§»æ­¥[RuoYi](https://gitee.com/y_project/RuoYi),微服务版本,请移步[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
* åŸºäºŽJwt的Token认证,支持多终端(Web、App、小程序)无缝接入。
* æ”¯æŒåŠ è½½åŠ¨æ€æƒé™èœå•ï¼Œå¤šæ–¹å¼è½»æ¾æƒé™æŽ§åˆ¶ï¼Œç»†ç²’åº¦åˆ°æŒ‰é’®çº§åˆ«ã€‚
* å†…置强大代码生成器,一键生成前后端代码(java、vue、xml、sql),支持 CRUD ä¸‹è½½ã€‚
* é˜¿é‡Œäº‘折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)&nbsp;&nbsp;
# ç‰ˆæœ¬åˆ†æ”¯
RuoYi-Vue åŽç«¯é¡¹ç›®æä¾› Spring Boot 2.x / 3.x / 4.x å¤šç‰ˆæœ¬åˆ†æ”¯çš„并行维护
| åç§°              | è¯´æ˜Ž                      | åœ°å€                                                    |
| :---------------- | :------------------------ | :------------------------------------------------------ |
| master é»˜è®¤åˆ†æ”¯   | Spring Boot 4.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue                   |
| springboot3 åˆ†æ”¯  | Spring Boot 3.x (JDK 17+) | https://gitee.com/y_project/RuoYi-Vue/tree/springboot3  |
| springboot2 åˆ†æ”¯  | Spring Boot 2.x (JDK 8+)  | https://gitee.com/y_project/RuoYi-Vue/tree/springboot2  |
RuoYi-Vue å‰ç«¯é¡¹ç›®æä¾› Vue 2.x / 3.x / JavaScript / TypeScript ç‰ˆæœ¬ï¼Œå‡å¯æ··ç”¨æ­é…
| é¡¹ç›®åç§°      | **RuoYi-Vue2** | **RuoYi-Vue3** | **RuoYi-Vue3-TypeScript**   |
| :---          | :---           | :---           | :---                        |
| **前端框架**  | Vue 2         | Vue 3          | Vue 3                       |
| **脚本语言**  | JavaScript    | JavaScript     | TypeScript                  |
| **构建工具**  | Vue CLI       | Vite           | Vite                        |
| **UI ç»„件库** | Element UI    | Element Plus   | Element Plus                |
| **状态管理**  | Vuex          | Pinia          | Pinia                       |
| **路由管理**  | Vue Router 3  | Vue Router 4   | Vue Router 4                |
| **核心特点**  | 1. æŠ€æœ¯æ ˆç»å…¸ç¨³å®š<br>2. ç¤¾åŒºèµ„料丰富<br>3. å½“前维护重心已转移 | 1. çŽ°ä»£å‰ç«¯æŠ€æœ¯æ ˆ<br>2. å¼€å‘体验与性能更优<br>3. å®˜æ–¹ä¸»æŽ¨çš„æ´»è·ƒç‰ˆæœ¬ | 1. ç±»åž‹åŠ æŒï¼Œå‡å°‘æ²Ÿé€šæˆæœ¬<br>2. å¼€å‘时有提示,效率更高<br>3. å¤šäººåä½œä¼ä¸šçº§å¼€å‘项目 |
| **仓库地址**  | [RuoYi-Vue2](https://gitcode.com/yangzongzhuan/RuoYi-Vue2) | [RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3) | [RuoYi-Vue3-TypeScript](https://gitcode.com/yangzongzhuan/RuoYi-Vue3/tree/typescript) |
## å†…置功能
@@ -91,4 +112,4 @@
## è‹¥ä¾å‰åŽç«¯åˆ†ç¦»äº¤æµç¾¤
QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/已满-136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [![加入QQ群](https://img.shields.io/badge/已满-143961921-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [![加入QQ群](https://img.shields.io/badge/已满-174951577-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [![加入QQ群](https://img.shields.io/badge/已满-161281055-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [![加入QQ群](https://img.shields.io/badge/已满-138988063-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [![加入QQ群](https://img.shields.io/badge/已满-151450850-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [![加入QQ群](https://img.shields.io/badge/已满-224622315-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [![加入QQ群](https://img.shields.io/badge/已满-287842588-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [![加入QQ群](https://img.shields.io/badge/已满-187944233-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [![加入QQ群](https://img.shields.io/badge/228578329-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) ç‚¹å‡»æŒ‰é’®å…¥ç¾¤ã€‚
QQ群: [![加入QQ群](https://img.shields.io/badge/已满-937441-blue.svg)](https://jq.qq.com/?_wv=1027&k=5bVB1og) [![加入QQ群](https://img.shields.io/badge/已满-887144332-blue.svg)](https://jq.qq.com/?_wv=1027&k=5eiA4DH) [![加入QQ群](https://img.shields.io/badge/已满-180251782-blue.svg)](https://jq.qq.com/?_wv=1027&k=5AxMKlC) [![加入QQ群](https://img.shields.io/badge/已满-104180207-blue.svg)](https://jq.qq.com/?_wv=1027&k=51G72yr) [![加入QQ群](https://img.shields.io/badge/已满-186866453-blue.svg)](https://jq.qq.com/?_wv=1027&k=VvjN2nvu) [![加入QQ群](https://img.shields.io/badge/已满-201396349-blue.svg)](https://jq.qq.com/?_wv=1027&k=5vYAqA05) [![加入QQ群](https://img.shields.io/badge/已满-101456076-blue.svg)](https://jq.qq.com/?_wv=1027&k=kOIINEb5) [![加入QQ群](https://img.shields.io/badge/已满-101539465-blue.svg)](https://jq.qq.com/?_wv=1027&k=UKtX5jhs) [![加入QQ群](https://img.shields.io/badge/已满-264312783-blue.svg)](https://jq.qq.com/?_wv=1027&k=EI9an8lJ) [![加入QQ群](https://img.shields.io/badge/已满-167385320-blue.svg)](https://jq.qq.com/?_wv=1027&k=SWCtLnMz) [![加入QQ群](https://img.shields.io/badge/已满-104748341-blue.svg)](https://jq.qq.com/?_wv=1027&k=96Dkdq0k) [![加入QQ群](https://img.shields.io/badge/已满-160110482-blue.svg)](https://jq.qq.com/?_wv=1027&k=0fsNiYZt) [![加入QQ群](https://img.shields.io/badge/已满-170801498-blue.svg)](https://jq.qq.com/?_wv=1027&k=7xw4xUG1) [![加入QQ群](https://img.shields.io/badge/已满-108482800-blue.svg)](https://jq.qq.com/?_wv=1027&k=eCx8eyoJ) [![加入QQ群](https://img.shields.io/badge/已满-101046199-blue.svg)](https://jq.qq.com/?_wv=1027&k=SpyH2875) [![加入QQ群](https://img.shields.io/badge/已满-136919097-blue.svg)](https://jq.qq.com/?_wv=1027&k=tKEt51dz) [![加入QQ群](https://img.shields.io/badge/已满-143961921-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=0vBbSb0ztbBgVtn3kJS-Q4HUNYwip89G&authKey=8irq5PhutrZmWIvsUsklBxhj57l%2F1nOZqjzigkXZVoZE451GG4JHPOqW7AW6cf0T&noverify=0&group_code=143961921) [![加入QQ群](https://img.shields.io/badge/已满-174951577-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=ZFAPAbp09S2ltvwrJzp7wGlbopsc0rwi&authKey=HB2cxpxP2yspk%2Bo3WKTBfktRCccVkU26cgi5B16u0KcAYrVu7sBaE7XSEqmMdFQp&noverify=0&group_code=174951577) [![加入QQ群](https://img.shields.io/badge/已满-161281055-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Fn2aF5IHpwsy8j6VlalNJK6qbwFLFHat&authKey=uyIT%2B97x2AXj3odyXpsSpVaPMC%2Bidw0LxG5MAtEqlrcBcWJUA%2FeS43rsF1Tg7IRJ&noverify=0&group_code=161281055) [![加入QQ群](https://img.shields.io/badge/已满-138988063-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=XIzkm_mV2xTsUtFxo63bmicYoDBA6Ifm&authKey=dDW%2F4qsmw3x9govoZY9w%2FoWAoC4wbHqGal%2BbqLzoS6VBarU8EBptIgPKN%2FviyC8j&noverify=0&group_code=138988063) [![加入QQ群](https://img.shields.io/badge/已满-151450850-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=DkugnCg68PevlycJSKSwjhFqfIgrWWwR&authKey=pR1Pa5lPIeGF%2FFtIk6d%2FGB5qFi0EdvyErtpQXULzo03zbhopBHLWcuqdpwY241R%2F&noverify=0&group_code=151450850) [![加入QQ群](https://img.shields.io/badge/已满-224622315-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=F58bgRa-Dp-rsQJThiJqIYv8t4-lWfXh&authKey=UmUs4CVG5OPA1whvsa4uSespOvyd8%2FAr9olEGaWAfdLmfKQk%2FVBp2YU3u2xXXt76&noverify=0&group_code=224622315) [![加入QQ群](https://img.shields.io/badge/已满-287842588-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=Nxb2EQ5qozWa218Wbs7zgBnjLSNk_tVT&authKey=obBKXj6SBKgrFTJZx0AqQnIYbNOvBB2kmgwWvGhzxR67RoRr84%2Bus5OadzMcdJl5&noverify=0&group_code=287842588) [![加入QQ群](https://img.shields.io/badge/已满-187944233-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=numtK1M_I4eVd2Gvg8qtbuL8JgX42qNh&authKey=giV9XWMaFZTY%2FqPlmWbkB9g3fi0Ev5CwEtT9Tgei0oUlFFCQLDp4ozWRiVIzubIm&noverify=0&group_code=187944233) [![加入QQ群](https://img.shields.io/badge/已满-228578329-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=G6r5KGCaa3pqdbUSXNIgYloyb8e0_L0D&authKey=4w8tF1eGW7%2FedWn%2FHAypQksdrML%2BDHolQSx7094Agm7Luakj9EbfPnSTxSi2T1LQ&noverify=0&group_code=228578329) [![加入QQ群](https://img.shields.io/badge/已满-191164766-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=GsOo-OLz53J8y_9TPoO6XXSGNRTgbFxA&authKey=R7Uy%2Feq%2BZsoKNqHvRKhiXpypW7DAogoWapOawUGHokJSBIBIre2%2FoiAZeZBSLuBc&noverify=0&group_code=191164766) [![加入QQ群](https://img.shields.io/badge/已满-174569686-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=PmYavuzsOthVqfdAPbo4uAeIbu7Ttjgc&authKey=p52l8%2FXa4PS1JcEmS3VccKSwOPJUZ1ZfQ69MEKzbrooNUljRtlKjvsXf04bxNp3G&noverify=0&group_code=174569686) [![加入QQ群](https://img.shields.io/badge/已满-127358632-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=M9y5NjAl44lAL_Vh2crmEehZU_PMU6KS&authKey=ZSDz8hEREWSaPuxQV3gEwqGIaGjfRNnkB4rJjf0IvXhrSUGSGwQFmBA%2Boe8HFxyl&noverify=0&group_code=127358632) [![加入QQ群](https://img.shields.io/badge/113071109-blue.svg)](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=UGnoqRcFRxUaX-JAUNrSDbPimKrllp4x&authKey=Bbzf8Bc0XaQhq5c4QOg46Uqngd%2FvtIixrLvCM1EkPf41diqKXKZqXVwAxHTxJ8R1&noverify=0&group_code=113071109) ç‚¹å‡»æŒ‰é’®å…¥ç¾¤ã€‚
bin/run-tomcat.bat
ÎļþÒÑɾ³ý
bin/run.bat
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] ä½¿ç”¨Jar命令运行Web工程。
echo.
cd %~dp0
cd ../ruoyi-admin/target
set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -jar %JAVA_OPTS% ruoyi-admin.jar
cd bin
pause
bin/start-prod.sh
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# =============================================================
# äº§æ•™èžåˆå®žè·µæ•™å­¦ç®¡ç†å¹³å° â€”— ç”Ÿäº§å¯åŠ¨è„šæœ¬
# ç”¨æ³•: ./start-prod.sh [profile]
# é»˜è®¤ profile: prod,druid
# =============================================================
set -e
PROFILE="${1:-prod,druid}"
JAR_DIR="$(cd "$(dirname "$0")/../ruoyi-admin/target" && pwd)"
JAR_FILE="${JAR_DIR}/ruoyi-admin.jar"
LOG_DIR="${LOG_DIR:-/var/log/ruoyi}"
PID_FILE="${PID_FILE:-/var/run/ruoyi-admin.pid}"
# è‹¥ jar ä¸å­˜åœ¨ï¼Œå…ˆç”¨ maven æ‰“包
if [ ! -f "$JAR_FILE" ]; then
  echo "JAR not found: $JAR_FILE, building..."
  cd "$(dirname "$0")/.."
  mvn clean package -DskipTests -P "${PROFILE%%,*}" -q
fi
mkdir -p "$LOG_DIR"
echo "Starting ruoyi-admin with profile: $PROFILE"
nohup java -Xms512m -Xmx1024m \
  -Dfile.encoding=UTF-8 \
  -Dlog.path="$LOG_DIR" \
  -jar "$JAR_FILE" \
  --spring.profiles.active="$PROFILE" \
  > "${LOG_DIR}/startup.log" 2>&1 &
PID=$!
echo "$PID" > "$PID_FILE"
echo "Started (PID=$PID). Log: ${LOG_DIR}/startup.log"
tail -f "${LOG_DIR}/startup.log"
bin/stop-prod.sh
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# =============================================================
# äº§æ•™èžåˆå®žè·µæ•™å­¦ç®¡ç†å¹³å° â€”— ç”Ÿäº§åœæ­¢è„šæœ¬
# ç”¨æ³•: ./stop-prod.sh
# =============================================================
set -e
PID_FILE="${PID_FILE:-/var/run/ruoyi-admin.pid}"
if [ -f "$PID_FILE" ]; then
  PID=$(cat "$PID_FILE")
  echo "Stopping ruoyi-admin (PID=$PID)..."
  kill "$PID" 2>/dev/null || true
  for i in $(seq 1 10); do
    if ! kill -0 "$PID" 2>/dev/null; then break; fi
    sleep 1
  done
  kill -9 "$PID" 2>/dev/null || true
  rm -f "$PID_FILE"
  echo "Stopped."
else
  # å°è¯•从进程列表找
  PID=$(ps aux | grep 'ruoyi-admin.jar' | grep -v grep | awk '{print $2}')
  if [ -n "$PID" ]; then
    kill "$PID" 2>/dev/null && echo "Stopped (PID=$PID)" || echo "No process found"
  else
    echo "No running ruoyi-admin process found"
  fi
fi
doc/add.sql
ÎļþÒÑɾ³ý
doc/ÈôÒÀ»·¾³Ê¹ÓÃÊÖ²á.docx
Binary files differ
pom.xml
@@ -1,345 +1,232 @@
<?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"
<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>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ruoyi</groupId>
    <artifactId>ruoyi</artifactId>
    <version>3.8.9</version>
    <packaging>jar</packaging>
    <version>3.9.2</version>
    <name>ruoyi</name>
    <url>http://www.ruoyi.vip</url>
    <description>若依管理系统</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.15</version>
        <relativePath />
    </parent>
    <description>产教融合实践教学管理平台</description>
    <properties>
        <ruoyi.version>3.9.2</ruoyi.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
        <pagehelper.spring.boot.starter.version>1.4.7</pagehelper.spring.boot.starter.version>
        <fastjson.version>2.0.53</fastjson.version>
        <druid.version>1.2.23</druid.version>
        <commons.io.version>2.13.0</commons.io.version>
        <bitwalker.version>1.21</bitwalker.version>
        <jwt.version>0.9.1</jwt.version>
        <java.version>17</java.version>
        <spring-boot.version>4.1.0</spring-boot.version>
        <mybatis-spring-boot.version>4.1.0</mybatis-spring-boot.version>
        <druid.version>1.2.28</druid.version>
        <yauaa.version>8.2.0</yauaa.version>
        <kaptcha.version>2.3.3</kaptcha.version>
        <swagger.version>3.0.0</swagger.version>
        <poi.version>5.2.3</poi.version>
        <oshi.version>6.6.5</oshi.version>
        <pagehelper.boot.version>4.1.1</pagehelper.boot.version>
        <fastjson.version>2.0.64</fastjson.version>
        <oshi.version>7.4.4</oshi.version>
        <commons.io.version>2.22.0</commons.io.version>
        <poi.version>5.5.1</poi.version>
        <velocity.version>2.3</velocity.version>
        <!-- override dependency version -->
        <tomcat.version>9.0.102</tomcat.version>
        <minio.version>8.4.3</minio.version>
        <okhttp.version>4.9.0</okhttp.version>
        <logback.version>1.2.13</logback.version>
        <spring-security.version>5.7.12</spring-security.version>
        <spring-framework.version>5.3.39</spring-framework.version>
        <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
        <jwt.version>0.9.1</jwt.version>
        <jaxb-api.version>2.3.1</jaxb-api.version>
        <springdoc.version>3.1.0</springdoc.version>
    </properties>
    <dependencies>
        <!-- ruoyi-springboot2 / swagger knife4j é…ç½® -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
    <!-- ä¾èµ–声明 -->
    <dependencyManagement>
        <dependencies>
        <!-- SpringBoot æ ¸å¿ƒåŒ… -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
            <!-- SpringBoot的依赖配置 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        <!-- SpringBoot æµ‹è¯• -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
            <!-- é˜¿é‡Œæ•°æ®åº“连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-4-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
        <!-- SpringBoot æ‹¦æˆªå™¨ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
            <!-- è§£æžå®¢æˆ·ç«¯æ“ä½œç³»ç»Ÿã€æµè§ˆå™¨ç­‰ -->
            <dependency>
                <groupId>nl.basjes.parse.useragent</groupId>
                <artifactId>yauaa</artifactId>
                <version>${yauaa.version}</version>
            </dependency>
        <!-- SpringBoot Web容器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
            <!-- pagehelper åˆ†é¡µæ’ä»¶ -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper.boot.version}</version>
            </dependency>
        <!-- spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- è¡¨ç¤ºä¾èµ–不会传递 -->
        </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot.version}</version>
            </dependency>
        <!-- spring security å®‰å…¨è®¤è¯ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>${jaxb-api.version}</version>
            </dependency>
        <!-- redis ç¼“存操作 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
            <!-- èŽ·å–ç³»ç»Ÿä¿¡æ¯ -->
            <dependency>
                <groupId>com.github.oshi</groupId>
                <artifactId>oshi-core</artifactId>
                <version>${oshi.version}</version>
            </dependency>
        <!-- pool å¯¹è±¡æ±  -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
            <!-- spring-doc -->
            <dependency>
                <groupId>org.springdoc</groupId>
                <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
                <version>${springdoc.version}</version>
            </dependency>
        <!-- Mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
            <!-- io常用工具类 -->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons.io.version}</version>
            </dependency>
        <!-- pagehelper åˆ†é¡µæ’ä»¶ -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper.spring.boot.starter.version}</version>
        </dependency>
            <!-- excel工具 -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>${poi.version}</version>
            </dependency>
        <!-- é˜¿é‡Œæ•°æ®åº“连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
            <!-- velocity代码生成使用模板 -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>${velocity.version}</version>
            </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
            <!-- é˜¿é‡ŒJSON解析器 -->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        <!--mybatis-plus代码生成器-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
            <!-- Token生成与解析-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jwt.version}</version>
            </dependency>
        <!-- è‡ªå®šä¹‰éªŒè¯æ³¨è§£ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
            <!-- éªŒè¯ç  -->
            <dependency>
                <groupId>pro.fessional</groupId>
                <artifactId>kaptcha</artifactId>
                <version>${kaptcha.version}</version>
            </dependency>
        <!-- å¸¸ç”¨å·¥å…·ç±» -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
            <!-- å®šæ—¶ä»»åŠ¡-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-quartz</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        <!-- io常用工具类 -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons.io.version}</version>
        </dependency>
            <!-- ä»£ç ç”Ÿæˆ-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-generator</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        <!-- è§£æžå®¢æˆ·ç«¯æ“ä½œç³»ç»Ÿã€æµè§ˆå™¨ç­‰ -->
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>${bitwalker.version}</version>
        </dependency>
            <!-- æ ¸å¿ƒæ¨¡å—-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-framework</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        <!-- é˜¿é‡ŒJSON解析器 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
            <!-- ç³»ç»Ÿæ¨¡å—-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-system</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        <!-- Spring框架基本的核心工具-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
            <!-- é€šç”¨å·¥å…·-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-common</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        <!-- Token生成与解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>${jwt.version}</version>
        </dependency>
        </dependencies>
    </dependencyManagement>
        <!-- Jaxb -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
    <modules>
        <module>ruoyi-admin</module>
        <module>ruoyi-framework</module>
        <module>ruoyi-system</module>
        <module>ruoyi-quartz</module>
        <module>ruoyi-generator</module>
        <module>ruoyi-common</module>
    </modules>
    <packaging>pom</packaging>
        <!-- Swagger3依赖 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>${swagger.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>io.swagger</groupId>
                    <artifactId>swagger-models</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- é˜²æ­¢è¿›å…¥swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.6.2</version>
        </dependency>
        <!-- èŽ·å–ç³»ç»Ÿä¿¡æ¯ -->
        <dependency>
            <groupId>com.github.oshi</groupId>
            <artifactId>oshi-core</artifactId>
            <version>${oshi.version}</version>
        </dependency>
        <!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>${poi.version}</version>
        </dependency>
        <!-- velocity代码生成使用模板 -->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>${velocity.version}</version>
        </dependency>
        <!-- å®šæ—¶ä»»åŠ¡ -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.mchange</groupId>
                    <artifactId>c3p0</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- éªŒè¯ç  -->
        <dependency>
            <groupId>pro.fessional</groupId>
            <artifactId>kaptcha</artifactId>
            <version>${kaptcha.version}</version>
            <exclusions>
                <exclusion>
                    <artifactId>servlet-api</artifactId>
                    <groupId>javax.servlet</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>${minio.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.squareup.okhttp3</groupId>
                    <artifactId>okhttp</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- minio依赖okhttp ä¸ç„¶æŠ¥é”™ -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>${okhttp.version}</version>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.2</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>4.0.3</version>
        </dependency>
        <!-- Hutool æ ¸å¿ƒå·¥å…·åŒ…(包含http模块,无需单独引入http子包) -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.7</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork> <!-- å¦‚果没有该配置,devtools不会生效 -->
                </configuration>
            </plugin>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <parameters>true</parameters>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
            </plugin>
        </plugins>
    </build>
    </build>
    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>
    <repositories>
        <repository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>aliyun nexus</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>
</project>
ruoyi-admin/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,88 @@
<?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>ruoyi</artifactId>
        <groupId>com.ruoyi</groupId>
        <version>3.9.2</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>ruoyi-admin</artifactId>
    <description>
        web服务入口
    </description>
    <dependencies>
        <!-- spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- è¡¨ç¤ºä¾èµ–不会传递 -->
        </dependency>
        <!-- spring-doc -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        </dependency>
         <!-- Mysql驱动包 -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <!-- æ ¸å¿ƒæ¨¡å—-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-framework</artifactId>
        </dependency>
        <!-- å®šæ—¶ä»»åŠ¡-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-quartz</artifactId>
        </dependency>
        <!-- ä»£ç ç”Ÿæˆ-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-generator</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <addResources>true</addResources>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                    <warName>${project.artifactId}</warName>
                </configuration>
           </plugin>
        </plugins>
        <finalName>${project.artifactId}</finalName>
    </build>
</project>
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.ruoyi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.jdbc.autoconfigure.DataSourceAutoConfiguration;
/**
 * å¯åŠ¨ç¨‹åº
 *
 * @author ruoyi
 */
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiApplication
{
    public static void main(String[] args)
    {
        // System.setProperty("spring.devtools.restart.enabled", "false");
        SpringApplication.run(RuoYiApplication.class, args);
        System.out.println("(♥◠‿◠)ノ゙  äº§æ•™èžåˆå®žè·µæ•™å­¦ç®¡ç†å¹³å°å¯åŠ¨æˆåŠŸ   áƒš(´ڡ`ლ)゙  \n" +
                " .-------.       ____     __        \n" +
                " |  _ _   \\      \\   \\   /  /    \n" +
                " | ( ' )  |       \\  _. /  '       \n" +
                " |(_ o _) /        _( )_ .'         \n" +
                " | (_,_).' __  ___(_ o _)'          \n" +
                " |  |\\ \\  |  ||   |(_,_)'         \n" +
                " |  | \\ `'   /|   `-'  /           \n" +
                " |  |  \\    /  \\      /           \n" +
                " ''-'   `'-'    `-..-'              ");
    }
}
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
 * web容器中进行部署
 *
 * @author ruoyi
 */
public class RuoYiServletInitializer extends SpringBootServletInitializer
{
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
    {
        return application.sources(RuoYiApplication.class);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/HealthController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.ruoyi.web.controller;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.AjaxResult;
/**
 * ç³»ç»Ÿå¥åº·æ£€æŸ¥æŽ¥å£ï¼ˆæ— è®¤è¯ï¼Œç”¨äºŽè´Ÿè½½å‡è¡¡/监控探活)
 */
@RestController
public class HealthController {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private Environment environment;
    @GetMapping("/api/health")
    @Anonymous
    public AjaxResult health() {
        Map<String, Object> info = new HashMap<>();
        info.put("status", "UP");
        info.put("timestamp", new Date());
        // æ•°æ®åº“检查
        try {
            jdbcTemplate.queryForObject("SELECT 1", Integer.class);
            info.put("database", "UP");
        } catch (Exception e) {
            info.put("database", "DOWN");
            info.put("dbError", e.getMessage());
        }
        // å†…存信息
        Runtime rt = Runtime.getRuntime();
        Map<String, Object> mem = new HashMap<>();
        mem.put("total", rt.totalMemory() / 1024 / 1024 + "MB");
        mem.put("free", rt.freeMemory() / 1024 / 1024 + "MB");
        mem.put("max", rt.maxMemory() / 1024 / 1024 + "MB");
        info.put("memory", mem);
        // ç³»ç»Ÿä¿¡æ¯
        info.put("os", System.getProperty("os.name"));
        info.put("java", System.getProperty("java.version"));
        info.put("activeProfiles", String.join(",", environment.getActiveProfiles()));
        return AjaxResult.success(info);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.ruoyi.web.controller.common;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import jakarta.annotation.Resource;
import javax.imageio.ImageIO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;
/**
 * éªŒè¯ç æ“ä½œå¤„理
 *
 * @author ruoyi
 */
@RestController
public class CaptchaController
{
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private ISysConfigService configService;
    /**
     * ç”ŸæˆéªŒè¯ç 
     */
    @GetMapping("/captchaImage")
    public AjaxResult getCode(HttpServletResponse response) throws IOException
    {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        ajax.put("captchaEnabled", captchaEnabled);
        if (!captchaEnabled)
        {
            return ajax;
        }
        // ä¿å­˜éªŒè¯ç ä¿¡æ¯
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        String capStr = null, code = null;
        BufferedImage image = null;
        // ç”ŸæˆéªŒè¯ç 
        String captchaType = RuoYiConfig.getCaptchaType();
        if ("math".equals(captchaType))
        {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        }
        else if ("char".equals(captchaType))
        {
            capStr = code = captchaProducer.createText();
            image = captchaProducer.createImage(capStr);
        }
        redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // è½¬æ¢æµä¿¡æ¯å†™å‡º
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try
        {
            ImageIO.write(image, "jpg", os);
        }
        catch (IOException e)
        {
            return AjaxResult.error(e.getMessage());
        }
        ajax.put("uuid", uuid);
        ajax.put("img", Base64.encode(os.toByteArray()));
        return ajax;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,162 @@
package com.ruoyi.web.controller.common;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig;
/**
 * é€šç”¨è¯·æ±‚处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/common")
public class CommonController
{
    private static final Logger log = LoggerFactory.getLogger(CommonController.class);
    @Autowired
    private ServerConfig serverConfig;
    private static final String FILE_DELIMITER = ",";
    /**
     * é€šç”¨ä¸‹è½½è¯·æ±‚
     *
     * @param fileName æ–‡ä»¶åç§°
     * @param delete æ˜¯å¦åˆ é™¤
     */
    @GetMapping("/download")
    public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
    {
        try
        {
            if (!FileUtils.checkAllowDownload(fileName))
            {
                throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
            }
            String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
            String filePath = RuoYiConfig.getDownloadPath() + fileName;
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, realFileName);
            FileUtils.writeBytes(filePath, response.getOutputStream());
            if (delete)
            {
                FileUtils.deleteFile(filePath);
            }
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚(单个)
     */
    @PostMapping("/upload")
    public AjaxResult uploadFile(MultipartFile file) throws Exception
    {
        try
        {
            // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
            String filePath = RuoYiConfig.getUploadPath();
            // ä¸Šä¼ å¹¶è¿”回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }
    /**
     * é€šç”¨ä¸Šä¼ è¯·æ±‚(多个)
     */
    @PostMapping("/uploads")
    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
    {
        try
        {
            // ä¸Šä¼ æ–‡ä»¶è·¯å¾„
            String filePath = RuoYiConfig.getUploadPath();
            List<String> urls = new ArrayList<String>();
            List<String> fileNames = new ArrayList<String>();
            List<String> newFileNames = new ArrayList<String>();
            List<String> originalFilenames = new ArrayList<String>();
            for (MultipartFile file : files)
            {
                // ä¸Šä¼ å¹¶è¿”回新文件名称
                String fileName = FileUploadUtils.upload(filePath, file);
                String url = serverConfig.getUrl() + fileName;
                urls.add(url);
                fileNames.add(fileName);
                newFileNames.add(FileUtils.getName(fileName));
                originalFilenames.add(file.getOriginalFilename());
            }
            AjaxResult ajax = AjaxResult.success();
            ajax.put("urls", StringUtils.join(urls, FILE_DELIMITER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMITER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMITER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMITER));
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }
    /**
     * æœ¬åœ°èµ„源通用下载
     */
    @GetMapping("/download/resource")
    public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
            throws Exception
    {
        try
        {
            if (!FileUtils.checkAllowDownload(resource))
            {
                throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
            }
            // æœ¬åœ°èµ„源路径
            String localPath = RuoYiConfig.getProfile();
            // æ•°æ®åº“资源地址
            String downloadPath = localPath + FileUtils.stripPrefix(resource);
            // ä¸‹è½½åç§°
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/miniapp/MiniappAccountController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,440 @@
package com.ruoyi.web.controller.miniapp;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.text.SimpleDateFormat;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.CjClass;
import com.ruoyi.system.domain.CjCollege;
import com.ruoyi.system.domain.CjMajor;
import com.ruoyi.system.domain.CjStudent;
import com.ruoyi.system.mapper.CjClassMapper;
import com.ruoyi.system.mapper.CjCollegeMapper;
import com.ruoyi.system.mapper.CjMajorMapper;
import com.ruoyi.system.mapper.CjStudentMapper;
import com.ruoyi.system.service.MiniappTokenService;
/**
 * å­¦ç”Ÿç«¯è´¦å·ä½“系接口:图形验证码 / æ³¨å†Œ(花名册激活) / ç™»å½• / å¿˜è®°å¯†ç (三要素自助重置) / ä¿®æ”¹å¯†ç ã€‚
 *
 * çº¦å®šï¼š
 * - è·¯å¾„挂在 /miniapp/** ä¸‹ï¼ŒSecurityConfig å·²æ•´ä½“ permitAll,登录态接口在方法内自校验 token;
 * - ç™»å½•标识 = å­¦å· + å§“名(学号仅班级内唯一,姓名消歧义,与既有 /miniapp/bind å£å¾„一致);
 * - æ³¨å†Œå³"花名册激活":学生须已在花名册且尚未设置密码;花名册已登记手机号的,注册需手机号校验(防二要素抢注);
 * - å¤±è´¥é”å®šæŒ‰ å­¦å·+姓名 ç»„合计数(固定 10 åˆ†é’Ÿçª—口),避免跨班同学号互锁与滚存锁;
 * - ä¼šè¯ token ç»Ÿä¸€èµ° MiniappTokenService(含反向索引,支持重置/改密/强制下线时作废全部会话)。
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/miniapp")
public class MiniappAccountController
{
    /** ä¿®æ”¹å¯†ç æ—¶åŽŸå¯†ç é”™è¯¯è®¡æ•°ï¼ˆæŒ‰ studentId) */
    private static final String CHANGE_ERR_KEY = "miniapp_change_err:";
    private static final int PWD_ERR_MAX = 5;
    private static final int RESET_ERR_MAX = 3;
    private static final int CHANGE_ERR_MAX = 5;
    /** å¯†ç å¤æ‚度:8-20 ä½ï¼Œè‡³å°‘含字母和数字 */
    private static final String PWD_RULE_RE = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d!@#$%^&*_.\\-+=?]{8,20}$";
    private static final String PHONE_RE = "^1[3-9]\\d{9}$";
    private static final String FAIL_IDENTITY_MSG = "校验失败,请核对学号/姓名/手机号;如有疑问请联系班级管理人重置";
    private static final String MULTI_MATCH_MSG = "存在相同学号与姓名的多名学生,请联系班级管理人核对";
    @Autowired private RedisCache redisCache;
    @Autowired private CjStudentMapper studentMapper;
    @Autowired private CjClassMapper classMapper;
    @Autowired private CjMajorMapper majorMapper;
    @Autowired private CjCollegeMapper collegeMapper;
    @Autowired private MiniappTokenService tokenService;
    @Autowired private MiniappCaptchaService captchaService;
    // =================================================================
    // 1. å›¾å½¢éªŒè¯ç ï¼ˆä¸Žç®¡ç†ç«¯é£Žæ ¼ä¸€è‡´ï¼Œkey å‰ç¼€ç‹¬ç«‹ï¼‰
    // =================================================================
    @GetMapping("/captcha")
    public AjaxResult captcha()
    {
        return captchaService.generate();
    }
    // =================================================================
    // 2. æ³¨å†Œ = æ‰«ç­çº§äºŒç»´ç è‡ªåŠ©å»ºæ¡£ï¼ˆæˆåŠŸå³ç™»å½•ï¼›æ‰‹æœºå·è‡ªå¡«ï¼Œä½œæ‰¾å›žå¯†ç éªŒè¯æ‰‹æ®µï¼‰
    // =================================================================
    @PostMapping("/account/register")
    public AjaxResult register(@RequestBody Map<String, String> body)
    {
        String bindCode = trim(body.get("bindCode"));
        String classIdStr = trim(body.get("classId"));
        String studentNo = trim(body.get("studentNo"));
        String name = trim(body.get("name"));
        String phone = trim(body.get("phone"));
        String password = body.get("password");
        if (isEmpty(bindCode) && isEmpty(classIdStr)) return AjaxResult.error("请选择所在班级(或扫描班级二维码进入)");
        if (isEmpty(studentNo) || isEmpty(name)) return AjaxResult.error("请输入学号和姓名");
        String capErr = captchaService.verify(body.get("code"), body.get("uuid"));
        if (capErr != null) return AjaxResult.error(capErr);
        String pwdErr = checkPwdRule(password, studentNo);
        if (pwdErr != null) return AjaxResult.error(pwdErr);
        if (isEmpty(phone) || !phone.matches(PHONE_RE)) return AjaxResult.error("请填写手机号(用于找回密码)");
        // ç­çº§å®šä½ï¼šæ‰«ç ä¼˜å…ˆï¼Œæœªæ‰«ç åˆ™ç”¨å­¦ç”Ÿè‡ªé€‰çš„ classId
        CjClass clazz;
        if (!isEmpty(bindCode))
        {
            clazz = findClassByBindCode(bindCode);
            if (clazz == null) return AjaxResult.error("注册码无效或已更换,请向老师确认本班最新二维码");
        }
        else
        {
            Long classId;
            try { classId = Long.valueOf(classIdStr); }
            catch (NumberFormatException e) { return AjaxResult.error("所选班级不正确"); }
            clazz = classMapper.selectCjClassByClassId(classId);
            if (clazz == null) return AjaxResult.error("所选班级不存在,请重新选择");
        }
        if (!"0".equals(clazz.getStatus())) return AjaxResult.error("本班注册已暂停,请联系老师");
        CjStudent exists = null;
        List<CjStudent> matched = findRoster(studentNo, name);
        if (matched.size() > 1) return AjaxResult.error(MULTI_MATCH_MSG);
        if (!matched.isEmpty()) exists = matched.get(0);
        if (exists != null && !isEmpty(studentMapper.selectPasswordByStudentId(exists.getStudentId())))
        {
            return AjaxResult.error("该学号已注册过,请直接登录;忘记密码可用“忘记密码”自助重置");
        }
        CjStudent student = exists;
        if (student == null)
        {
            // å…¨æ–°è‡ªåŠ©å»ºæ¡£
            student = new CjStudent();
            student.setClassId(clazz.getClassId());
            student.setStudentNo(studentNo);
            student.setName(name);
            student.setPhone(phone);
            student.setStatus("0");
            student.setDelFlag("0");
            student.setCreateBy("self-register");
            try
            {
                studentMapper.insertCjStudent(student);
            }
            catch (org.springframework.dao.DuplicateKeyException e)
            {
                return AjaxResult.error("该学号与姓名已被注册");
            }
        }
        else
        {
            // å‘½ä¸­å­˜é‡è®°å½•(如历史数据):激活并按本次选择班级归位,手机号补齐;备注留痕
            String trace = "[注册激活 " + stamp() + "] ç­çº§ â†’ " + clazz.getClassName();
            CjStudent upd = new CjStudent();
            upd.setStudentId(student.getStudentId());
            upd.setClassId(clazz.getClassId());
            upd.setPhone(phone);
            upd.setRemark(appendRemark(student.getRemark(), trace));
            upd.setUpdateBy("self-register");
            studentMapper.updateCjStudent(upd);
        }
        studentMapper.updateStudentPassword(student.getStudentId(), SecurityUtils.encryptPassword(password), "0", new Date());
        String token = tokenService.createSession(student.getStudentId());
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("token", token);
        data.put("mustChange", false);
        return AjaxResult.success("注册成功", data);
    }
    /**
     * å…¨éƒ¨æ­£å¸¸çŠ¶æ€ç­çº§ï¼ˆä¾›æœªæ‰«ç å­¦ç”Ÿæ³¨å†Œæ—¶è‡ªé€‰ï¼‰ï¼š[{classId, label:'学院·专业·班级'}]
     */
    @GetMapping("/account/classes")
    public AjaxResult classes()
    {
        List<CjClass> all = classMapper.selectCjClassList(new CjClass());
        Map<Long, CjMajor> majorMap = new LinkedHashMap<>();
        for (CjMajor m : majorMapper.selectCjMajorList(new CjMajor())) majorMap.put(m.getMajorId(), m);
        Map<Long, CjCollege> collegeMap = new LinkedHashMap<>();
        for (CjCollege c : collegeMapper.selectCjCollegeList(new CjCollege())) collegeMap.put(c.getCollegeId(), c);
        List<Map<String, Object>> out = new ArrayList<>();
        for (CjClass cl : all)
        {
            if (!"0".equals(cl.getStatus())) continue;
            CjMajor m = majorMap.get(cl.getMajorId());
            CjCollege co = m == null ? null : collegeMap.get(m.getCollegeId());
            String label = ((co == null ? "" : co.getCollegeName() + "·") + (m == null ? "" : m.getMajorName() + "·") + cl.getClassName());
            Map<String, Object> row = new LinkedHashMap<>();
            row.put("classId", cl.getClassId());
            row.put("label", label);
            out.add(row);
        }
        return AjaxResult.success(out);
    }
    /**
     * è§£æžæ³¨å†Œç  â†’ ç­çº§ä¿¡æ¯ï¼ˆæ³¨å†Œé¡µå±•示"你正在加入:××学院××专业××班")
     */
    @GetMapping("/account/resolve")
    public AjaxResult resolve(@RequestParam("bindCode") String bindCode)
    {
        CjClass clazz = findClassByBindCode(trim(bindCode));
        if (clazz == null) return AjaxResult.error("二维码无效或已更换,请向老师确认");
        if (!"0".equals(clazz.getStatus())) return AjaxResult.error("本班注册已暂停,请联系老师");
        Map<String, Object> out = new LinkedHashMap<>();
        out.put("classId", clazz.getClassId());
        out.put("className", clazz.getClassName());
        CjMajor m = clazz.getMajorId() == null ? null : majorMapper.selectCjMajorByMajorId(clazz.getMajorId());
        out.put("majorName", m == null ? "" : m.getMajorName());
        CjCollege co = (m == null || m.getCollegeId() == null) ? null : collegeMapper.selectCjCollegeByCollegeId(m.getCollegeId());
        out.put("collegeName", co == null ? "" : co.getCollegeName());
        return AjaxResult.success(out);
    }
    /**
     * é‡æ–°ç»‘定班级(登录态,扫新班级码);已提交记录按快照保留原班级归属,此处仅移动学生当前班级并留痕
     */
    @PostMapping("/account/rebind")
    public AjaxResult rebind(@RequestBody Map<String, String> body,
                             @RequestHeader(value = "Authorization", required = false) String auth)
    {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error(401, "未登录或登录已过期");
        CjStudent student = studentMapper.selectCjStudentByStudentId(sid);
        if (student == null) return AjaxResult.error(401, "账号不存在");
        CjClass target = findClassByBindCode(trim(body.get("bindCode")));
        if (target == null) return AjaxResult.error("二维码无效或已更换,请向老师确认");
        if (!"0".equals(target.getStatus())) return AjaxResult.error("目标班级注册已暂停,请联系老师");
        if (target.getClassId().equals(student.getClassId())) return AjaxResult.error("你已在该班级,无需换班");
        String oldClassName = "";
        if (student.getClassId() != null)
        {
            CjClass old = classMapper.selectCjClassByClassId(student.getClassId());
            oldClassName = old == null ? String.valueOf(student.getClassId()) : old.getClassName();
        }
        String trace = "[换班 " + stamp() + "] " + oldClassName + " â†’ " + target.getClassName();
        CjStudent upd = new CjStudent();
        upd.setStudentId(sid);
        upd.setClassId(target.getClassId());
        upd.setRemark(appendRemark(student.getRemark(), trace));
        upd.setUpdateBy("self-rebind");
        studentMapper.updateCjStudent(upd);
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("className", target.getClassName());
        return AjaxResult.success("已换班,此前已提交的表单仍归属原班级", data);
    }
    // =================================================================
    // 3. ç™»å½•(学号 + å§“名 + å¯†ç ï¼ŒæˆåŠŸç­¾å‘ token)
    // =================================================================
    @PostMapping("/account/login")
    public AjaxResult login(@RequestBody Map<String, String> body)
    {
        String studentNo = trim(body.get("studentNo"));
        String name = trim(body.get("name"));
        String password = body.get("password");
        if (isEmpty(studentNo) || isEmpty(name) || isEmpty(password))
        {
            return AjaxResult.error("请填写完整的登录信息");
        }
        String capErr = captchaService.verify(body.get("code"), body.get("uuid"));
        if (capErr != null) return AjaxResult.error(capErr);
        String lockKey = MiniappTokenService.pwdErrKey(studentNo, name);
        if (captchaService.failCount(lockKey) >= PWD_ERR_MAX)
        {
            return AjaxResult.error("密码错误次数过多,请 10 åˆ†é’ŸåŽå†è¯•,或使用“忘记密码”");
        }
        List<CjStudent> matched = findRoster(studentNo, name);
        if (matched.size() > 1) return AjaxResult.error(MULTI_MATCH_MSG);
        if (matched.isEmpty())
        {
            return AjaxResult.error("学号或姓名不正确");
        }
        CjStudent student = matched.get(0);
        String stored = studentMapper.selectPasswordByStudentId(student.getStudentId());
        if (isEmpty(stored))
        {
            return AjaxResult.error("该账号尚未注册,请先注册");
        }
        if (!SecurityUtils.matchesPassword(password, stored))
        {
            captchaService.incrFail(lockKey, PWD_ERR_MAX);
            return AjaxResult.error("学号、姓名或密码不正确");
        }
        if (!"0".equals(student.getStatus()))
        {
            return AjaxResult.error("你的账号已停用,请联系班级管理人");
        }
        captchaService.clearFail(lockKey);
        studentMapper.updateStudentLoginDate(student.getStudentId(), new Date());
        String token = tokenService.createSession(student.getStudentId());
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("token", token);
        data.put("mustChange", "1".equals(student.getPwdResetFlag()));
        return AjaxResult.success("登录成功", data);
    }
    // =================================================================
    // 4. å¿˜è®°å¯†ç  = èº«ä»½ä¸‰è¦ç´ è‡ªåŠ©é‡ç½®ï¼ˆå­¦å· + å§“名 + èŠ±åå†Œç™»è®°æ‰‹æœºå·ï¼‰
    // =================================================================
    @PostMapping("/account/reset")
    public AjaxResult reset(@RequestBody Map<String, String> body)
    {
        String studentNo = trim(body.get("studentNo"));
        String name = trim(body.get("name"));
        String phone = trim(body.get("phone"));
        String newPassword = body.get("newPassword");
        if (isEmpty(studentNo) || isEmpty(name) || isEmpty(phone) || isEmpty(newPassword))
        {
            return AjaxResult.error("请填写完整的找回信息");
        }
        String capErr = captchaService.verify(body.get("code"), body.get("uuid"));
        if (capErr != null) return AjaxResult.error(capErr);
        String lockKey = MiniappTokenService.resetErrKey(studentNo, name);
        if (captchaService.failCount(lockKey) >= RESET_ERR_MAX)
        {
            return AjaxResult.error("自助重置尝试次数过多,请联系班级管理人");
        }
        String pwdErr = checkPwdRule(newPassword, studentNo);
        if (pwdErr != null) return AjaxResult.error(pwdErr);
        List<CjStudent> matched = findRoster(studentNo, name);
        if (matched.size() > 1) return AjaxResult.error(FAIL_IDENTITY_MSG); // ä¸æ³„露多命中细节
        CjStudent student = matched.isEmpty() ? null : matched.get(0);
        boolean ok = student != null && !isEmpty(student.getPhone()) && phone.equals(student.getPhone().trim())
                && "0".equals(student.getStatus());
        if (!ok)
        {
            captchaService.incrFail(lockKey, RESET_ERR_MAX);
            return AjaxResult.error(FAIL_IDENTITY_MSG);
        }
        boolean firstActivate = isEmpty(studentMapper.selectPasswordByStudentId(student.getStudentId()));
        studentMapper.updateStudentPassword(student.getStudentId(), SecurityUtils.encryptPassword(newPassword), "0",
                firstActivate ? new Date() : null);
        tokenService.invalidateAll(student.getStudentId());
        captchaService.clearFail(lockKey);
        captchaService.clearFail(MiniappTokenService.pwdErrKey(studentNo, name));
        return AjaxResult.success("密码重置成功,请使用新密码登录");
    }
    // =================================================================
    // 5. ä¿®æ”¹å¯†ç ï¼ˆç™»å½•态;作废旧会话、签发新 token,即“改密踢其他设备”)
    // =================================================================
    @PostMapping("/account/change")
    public AjaxResult change(@RequestBody Map<String, String> body,
                             @RequestHeader(value = "Authorization", required = false) String auth)
    {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error(401, "未登录或登录已过期");
        String oldPassword = body.get("oldPassword");
        String newPassword = body.get("newPassword");
        if (isEmpty(oldPassword) || isEmpty(newPassword))
        {
            return AjaxResult.error("请填写原密码与新密码");
        }
        String changeLock = CHANGE_ERR_KEY + sid;
        if (captchaService.failCount(changeLock) >= CHANGE_ERR_MAX)
        {
            return AjaxResult.error("原密码错误次数过多,请 10 åˆ†é’ŸåŽå†è¯•");
        }
        CjStudent student = studentMapper.selectCjStudentByStudentId(sid);
        if (student == null) return AjaxResult.error(401, "账号不存在");
        String stored = studentMapper.selectPasswordByStudentId(sid);
        if (isEmpty(stored) || !SecurityUtils.matchesPassword(oldPassword, stored))
        {
            captchaService.incrFail(changeLock, CHANGE_ERR_MAX);
            return AjaxResult.error("原密码不正确");
        }
        if (oldPassword.equals(newPassword))
        {
            return AjaxResult.error("新密码不能与原密码相同");
        }
        String pwdErr = checkPwdRule(newPassword, student.getStudentNo());
        if (pwdErr != null) return AjaxResult.error(pwdErr);
        studentMapper.updateStudentPassword(sid, SecurityUtils.encryptPassword(newPassword), "0", null);
        captchaService.clearFail(changeLock);
        tokenService.invalidateAll(sid);
        String token = tokenService.createSession(sid);
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("token", token);
        return AjaxResult.success("密码修改成功,其他设备已退出登录", data);
    }
    // =================================================================
    // ç§æœ‰å·¥å…·
    // =================================================================
    /** èŠ±åå†ŒåŒ¹é…ï¼ˆæŒ‰ å­¦å·+姓名):返回命中列表(可能 0/1/多条);null = åŒé”®å¤šæ¡ä¸”无法由调用方消歧 */
    private List<CjStudent> findRoster(String studentNo, String name)
    {
        CjStudent q = new CjStudent();
        q.setStudentNo(studentNo);
        List<CjStudent> list = studentMapper.selectCjStudentList(q);
        return list.stream().filter(s -> name.equals(s.getName())).collect(Collectors.toList());
    }
    /** ç­çº§æ³¨å†Œç  â†’ ç­çº§ï¼ˆå¤ç”¨å»ºè¡¨é¢„留的 bind_code åˆ—,32 ä½éšæœºç ä¸å¯æžšä¸¾ï¼‰ */
    private CjClass findClassByBindCode(String bindCode)
    {
        if (isEmpty(bindCode)) return null;
        CjClass q = new CjClass();
        q.setBindCode(bindCode);
        List<CjClass> list = classMapper.selectCjClassList(q);
        return list.isEmpty() ? null : list.get(0);
    }
    /** ç•™ç—•时间戳 */
    private String stamp()
    {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date());
    }
    /** å¤‡æ³¨è¿½åŠ æµæ°´ï¼ˆé™é•¿ä¿æŠ¤ï¼Œremark åˆ— varchar(500)) */
    private String appendRemark(String old, String line)
    {
        String base = old == null ? "" : old;
        String merged = base.isEmpty() ? line : base + ";" + line;
        return merged.length() > 500 ? merged.substring(merged.length() - 500) : merged;
    }
    /** å¯†ç è§„则校验;通过返回 null */
    private String checkPwdRule(String password, String studentNo)
    {
        if (isEmpty(password)) return "请输入密码";
        if (!password.matches(PWD_RULE_RE)) return "密码须为 8-20 ä½ï¼Œä¸”同时包含字母和数字";
        if (password.equals(studentNo)) return "密码不能与学号相同";
        return null;
    }
    /** ä¸Ž MiniappController ç›¸åŒå£å¾„çš„ token æ ¡éªŒ */
    private Long resolveStudentId(String auth)
    {
        if (auth == null || !auth.startsWith("Bearer ")) return null;
        Object val = redisCache.getCacheObject(MiniappTokenService.TOKEN_PREFIX + auth.substring(7));
        if (val instanceof Long)
        {
            Long sid = (Long) val;
            return sid > 0 ? sid : null;
        }
        return null;
    }
    private String trim(String s) { return s == null ? null : s.trim(); }
    private boolean isEmpty(String s) { return s == null || s.trim().isEmpty(); }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/miniapp/MiniappCaptchaService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package com.ruoyi.web.controller.miniapp;
import java.awt.image.BufferedImage;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream;
import com.google.code.kaptcha.Producer;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.sign.Base64;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.service.ISysConfigService;
import jakarta.annotation.Resource;
/**
 * å­¦ç”Ÿç«¯å›¾å½¢éªŒè¯ç ï¼šç”Ÿæˆ + ä¸€æ¬¡æ€§æ¶ˆè´¹æ ¡éªŒã€‚
 * ä¾› MiniappAccountController(登录/注册/找回)与 MiniappController(绑定/开放登记)共用,
 * å µæ­»"无验证码枚举花名册"的匿名爆破面。
 */
@Service
public class MiniappCaptchaService
{
    /** å­¦ç”Ÿç«¯ç‹¬ç«‹éªŒè¯ç  key å‰ç¼€ï¼ˆä¸ä¸Žç®¡ç†ç«¯ captcha_codes: äº’串) */
    public static final String CAPTCHA_KEY = "miniapp_captcha:";
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    @Autowired private RedisCache redisCache;
    @Autowired private ISysConfigService configService;
    /** ç”ŸæˆéªŒè¯ç ï¼Œè¿”回 { captchaEnabled, uuid, img };开关与管理端一致 */
    public AjaxResult generate()
    {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        ajax.put("captchaEnabled", captchaEnabled);
        if (!captchaEnabled)
        {
            return ajax;
        }
        String uuid = IdUtils.simpleUUID();
        String capStr;
        String code;
        BufferedImage image;
        if ("math".equals(RuoYiConfig.getCaptchaType()))
        {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        }
        else
        {
            capStr = code = captchaProducer.createText();
            image = captchaProducer.createImage(capStr);
        }
        redisCache.setCacheObject(CAPTCHA_KEY + uuid, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        try (FastByteArrayOutputStream os = new FastByteArrayOutputStream())
        {
            ImageIO.write(image, "jpg", os);
            ajax.put("uuid", uuid);
            ajax.put("img", Base64.encode(os.toByteArray()));
        }
        catch (Exception e)
        {
            return AjaxResult.error("验证码生成失败");
        }
        return ajax;
    }
    /** ä¸€æ¬¡æ€§æ ¡éªŒï¼šé€šè¿‡è¿”回 null,否则返回错误消息(先删 key é˜²é‡æ”¾ï¼‰ */
    public String verify(String code, String uuid)
    {
        if (!configService.selectCaptchaEnabled()) return null;
        if (code == null || code.trim().isEmpty() || uuid == null || uuid.trim().isEmpty()) return "请输入图形验证码";
        String key = CAPTCHA_KEY + uuid;
        Object expected = redisCache.getCacheObject(key);
        if (expected == null) return "验证码已失效,请刷新后重试";
        redisCache.deleteObject(key);
        if (!code.trim().equalsIgnoreCase(expected.toString())) return "验证码错误";
        return null;
    }
    /** å¤±è´¥è®¡æ•°ï¼šå›ºå®š 10 åˆ†é’Ÿçª—口内累计(首次失败设定窗口,后续只增量,不滚存续命) */
    public int incrFail(String key, int max)
    {
        long cnt = redisCache.redisTemplate.opsForValue().increment(key);
        if (cnt == 1L)
        {
            redisCache.redisTemplate.expire(key, 10, TimeUnit.MINUTES);
        }
        return (int) cnt;
    }
    public int failCount(String key)
    {
        Object v = redisCache.getCacheObject(key);
        return v instanceof Number ? ((Number) v).intValue() : 0;
    }
    public void clearFail(String key)
    {
        redisCache.deleteObject(key);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/miniapp/MiniappController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,854 @@
package com.ruoyi.web.controller.miniapp;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.system.domain.CjClass;
import com.ruoyi.system.domain.CjCollege;
import com.ruoyi.system.domain.CjFillRecord;
import com.ruoyi.system.domain.CjFillTask;
import com.ruoyi.system.domain.CjMajor;
import com.ruoyi.system.domain.CjStudent;
import com.ruoyi.system.domain.CjStudentBind;
import com.ruoyi.system.mapper.CjClassMapper;
import com.ruoyi.system.mapper.CjCollegeMapper;
import com.ruoyi.system.mapper.CjFillRecordMapper;
import com.ruoyi.system.mapper.CjFillTaskMapper;
import com.ruoyi.system.mapper.CjMajorMapper;
import com.ruoyi.system.mapper.CjStudentBindMapper;
import com.ruoyi.system.mapper.CjStudentMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
 * å­¦ç”Ÿç«¯ï¼ˆå°ç¨‹åº/MiniApp)接口控制器 â€”— å¡«è¡¨ä»»åŠ¡é©±åŠ¨å¡«æŠ¥
 * ä¸ä¾èµ– RuoYi æƒé™ä½“系,用 Redis è‡ªå®šä¹‰ token ä¼šè¯ã€‚
 *
 * å¡«æŠ¥å¯¹è±¡ï¼šå¡«è¡¨ä»»åŠ¡(cj_fill_task)发布后在填报窗口内、且该生班级在任务范围内的任务;
 * è¡¨å•按任务 form schema åŠ¨æ€æ¸²æŸ“ï¼›è®°å½•å­˜ cj_fill_record(学生×任务唯一,0草稿/1已提交)。
 */
@RestController
@RequestMapping("/miniapp")
public class MiniappController {
    private static final String TOKEN_PREFIX = "miniapp:token:";
    /** æœªç»‘定登录时,临时把 openid å­˜è¿™é‡Œï¼Œç»‘定接口按 token è¯»å–并真正落库 */
    private static final String OPENID_PREFIX = "miniapp:openid:";
    private static final Logger log = LoggerFactory.getLogger(MiniappController.class);
    private static final String PHONE_RE = "^1[3-9]\\d{9}$";
    /** ç»Ÿä¸€ç¤¾ä¼šä¿¡ç”¨ä»£ç ï¼š18位,大写字母+数字,不含 I/O/Z/S/V */
    private static final String CREDIT_CODE_RE = "^[0-9A-HJ-NPQRTUWXY]{18}$";
    @Value("${wechat.appid:}") private String wxAppid;
    @Value("${wechat.secret:}") private String wxSecret;
    @Autowired private RedisCache redisCache;
    @Autowired private CjStudentMapper studentMapper;
    @Autowired private CjStudentBindMapper bindMapper;
    @Autowired private CjClassMapper classMapper;
    @Autowired private CjMajorMapper majorMapper;
    @Autowired private CjCollegeMapper collegeMapper;
    @Autowired private CjFillTaskMapper taskMapper;
    @Autowired private CjFillRecordMapper recordMapper;
    @Autowired private com.ruoyi.system.service.MiniappTokenService tokenService;
    @Autowired private MiniappCaptchaService captchaService;
    @Autowired private com.ruoyi.system.service.ISysDictTypeService dictTypeService;
    private final ObjectMapper om = new ObjectMapper();
    /** æ–‡æ¡ˆå­—典类型(dict_label=用途键名,dict_value=文案正文),见 skill/sql/15_cj_title_dict.sql */
    private static final String TITLE_DICT_TYPE = "cj_fill_title";
    // ========== 0. ç«™ç‚¹æ–‡æ¡ˆï¼ˆå­—典驱动,登录/注册页未登录也要显示,故随 /miniapp/** åŒ¿åæ”¾è¡Œï¼‰ ==========
    @GetMapping("/site-titles")
    public AjaxResult siteTitles() {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("platformTitle", dictText("平台标题", "产教融合实践教学管理平台"));
        data.put("platformSubtitle", dictText("平台副标题", "江苏商贸职业学院 Â· å­¦ç”Ÿå®žè·µæ•™å­¦ä¿¡æ¯å¡«æŠ¥"));
        data.put("loginSubtitle", dictText("登录页副标题", "产教融合实践教学管理平台 Â· å­¦ç”Ÿè´¦å·"));
        return AjaxResult.success(data);
    }
    /**
     * å–文案字典中某个用途的正文;字典项缺失/被清空时回退内置默认,页面不会空白。
     * ç”¨ selectDictDataByType è€Œéž DictUtils:前者缓存未命中会回源数据库并补缓存,
     * çº¿ä¸Šè·‘完 15 å·è„šæœ¬æ— éœ€é‡å¯æˆ–æ‰‹åŠ¨åˆ·ç¼“å­˜å³å¯ç”Ÿæ•ˆã€‚
     */
    private String dictText(String label, String fallback) {
        try {
            List<SysDictData> datas = dictTypeService.selectDictDataByType(TITLE_DICT_TYPE);
            if (datas != null) {
                for (SysDictData d : datas) {
                    if (label.equals(d.getDictLabel())) {
                        String v = d.getDictValue();
                        if (v != null && !v.trim().isEmpty()) return v.trim();
                        break;
                    }
                }
            }
        } catch (Exception e) {
            log.warn("读取文案字典失败 label={},回退默认文案", label, e);
        }
        return fallback;
    }
    // ========== 1. ç™»å½•(openid é€šé“已下线:花名册废除后统一走账号密码体系) ==========
    @PostMapping("/login")
    public AjaxResult login(@RequestBody Map<String, String> params) {
        return AjaxResult.error("该通道已停用,请通过班级二维码注册并使用账号密码登录");
    }
    /** æ—§å¾®ä¿¡ç™»å½•实现(保留代码备小程序上线时改造,暂不接流量) */
    private AjaxResult legacyWxLogin(Map<String, String> params) {
        String code = params.getOrDefault("code", "");
        String openid;
        if ("H5_DEV_CODE".equals(code) || code.isEmpty()) {
            // æ—§è”调方式:随机(每次不同,仅用于功能调试)
            openid = "mock-openid-" + UUID.randomUUID().toString().substring(0, 8);
        } else if (code.startsWith("H5_DEV_")) {
            // H5 ç¨³å®šè”调:同一个“设备码”永远得到同一 openid â†’ ç»‘定可被记住
            openid = "h5mock-" + md5Hex(code);
        } else {
            openid = code2session(code);
            if (openid == null) return AjaxResult.error("微信登录失败,请稍后重试");
        }
        CjStudentBind q = new CjStudentBind();
        q.setOpenidHash(openid);
        List<CjStudentBind> list = bindMapper.selectCjStudentBindList(q);
        if (!list.isEmpty()) {
            String token = UUID.randomUUID().toString().replace("-", "");
            redisCache.setCacheObject(TOKEN_PREFIX + token, list.get(0).getStudentId(), 24, TimeUnit.HOURS);
            tokenService.registerSession(list.get(0).getStudentId(), token); // ç™»è®°åå‘索引,供改密/强制下线作废
            return AjaxResult.success("success", Map.of("token", token, "bound", true));
        }
        String token = UUID.randomUUID().toString().replace("-", "");
        redisCache.setCacheObject(TOKEN_PREFIX + token, -1L, 30, TimeUnit.MINUTES);
        // è®°ä½æœ¬æ¬¡å¾®ä¿¡ openid,供绑定接口使用,保证“微信身份 â†” å­¦å·â€çœŸæ­£ç»‘在一起
        redisCache.setCacheObject(OPENID_PREFIX + token, openid, 30, TimeUnit.MINUTES);
        return AjaxResult.success("need_bind", Map.of("token", token, "bound", false));
    }
    // ========== 2. ç»‘定学生身份(花名册通道已下线,仅保留方法体备查) ==========
    @PostMapping("/bind")
    public AjaxResult bind(@RequestBody Map<String, String> params,
                           @RequestHeader(value = "Authorization", required = false) String auth) {
        return AjaxResult.error("该通道已停用,请通过班级二维码注册并使用账号密码登录");
    }
    private AjaxResult legacyBind(Map<String, String> params, String auth) {
        String studentNo = params.get("studentNo") == null ? null : params.get("studentNo").trim();
        String name = params.get("name") == null ? null : params.get("name").trim();
        if (studentNo == null || studentNo.isEmpty() || name == null || name.isEmpty()) return AjaxResult.error("请提供学号和姓名");
        String capErr = captchaService.verify(params.get("code"), params.get("uuid"));
        if (capErr != null) return AjaxResult.error(capErr);
        CjStudent qs = new CjStudent();
        qs.setStudentNo(studentNo);
        List<CjStudent> students = studentMapper.selectCjStudentList(qs);
        List<CjStudent> matched = new ArrayList<>();
        for (CjStudent s : students) { if (name.equals(s.getName())) matched.add(s); }
        // ç»Ÿä¸€æ–‡æ¡ˆï¼šä¸åŒºåˆ†"学号不存在/姓名不匹配",配合验证码堵住无门槛枚举
        if (matched.isEmpty()) return AjaxResult.error("学号或姓名不匹配,请核对或联系班级管理人");
        if (matched.size() > 1) return AjaxResult.error("存在相同学号与姓名的多名学生,请联系班级管理人核对");
        CjStudent student = matched.get(0);
        if (!"0".equals(student.getStatus())) return AjaxResult.error("你的账号已停用,请联系班级管理人");
        String existPwd = studentMapper.selectPasswordByStudentId(student.getStudentId());
        if (existPwd != null && !existPwd.isEmpty()) return AjaxResult.error("账号已激活,请使用密码登录");
        // ç»‘定身份:优先用“本次登录”记录下来的微信 openid(真实微信);无登录态时再退回 mock
        String openid = openidOfToken(auth);
        if (openid == null) openid = params.getOrDefault("openid", "mock-openid-" + UUID.randomUUID().toString().substring(0, 8));
        CjStudentBind qb = new CjStudentBind();
        qb.setStudentId(student.getStudentId());
        List<CjStudentBind> existsList = bindMapper.selectCjStudentBindList(qb);
        CjStudentBind exists = existsList.isEmpty() ? null : existsList.get(0);
        if (exists != null) {
            exists.setOpenidHash(openid);
            bindMapper.updateCjStudentBind(exists);
        } else {
            CjStudentBind bind = new CjStudentBind();
            bind.setStudentId(student.getStudentId());
            bind.setOpenidHash(openid);
            bind.setBindChannel("1");
            bind.setStatus("0");
            bindMapper.insertCjStudentBind(bind);
        }
        String token = UUID.randomUUID().toString().replace("-", "");
        redisCache.setCacheObject(TOKEN_PREFIX + token, student.getStudentId(), 24, TimeUnit.HOURS);
        tokenService.registerSession(student.getStudentId(), token); // ç™»è®°åå‘索引,供改密/强制下线作废
        return AjaxResult.success("绑定成功", Map.of("token", token, "studentId", student.getStudentId()));
    }
    // ========== 2.5 å¼€æ”¾ç™»è®°é€šé“(已下线:学生统一经班级码注册,注册自选班级走 /miniapp/account/classes) ==========
    @GetMapping("/registerClasses")
    public AjaxResult registerClasses() {
        return AjaxResult.error("该通道已停用,请通过班级二维码注册并使用账号密码登录");
    }
    /** æ—§å¼€æ”¾ç™»è®°ç­çº§åˆ—表(保留代码备查,不再接流量) */
    private AjaxResult legacyRegisterClasses() {
        java.util.Set<Long> openClassIds = new java.util.HashSet<>();
        CjFillTask q = new CjFillTask();
        q.setStatus("1");
        List<CjFillTask> tasks = taskMapper.selectCjFillTaskList(q);
        if (tasks != null) {
            for (CjFillTask t : tasks) {
                if ("1".equals(t.getRangeMode())) {
                    openClassIds.addAll(scopeClassIds(t));
                }
            }
        }
        List<Map<String, Object>> out = new ArrayList<>();
        if (!openClassIds.isEmpty()) {
            // å…¨é‡ç­çº§/专业/学院做名称映射
            Map<Long, CjClass> classMap = new LinkedHashMap<>();
            List<CjClass> allClasses = classMapper.selectCjClassList(new CjClass());
            if (allClasses != null) for (CjClass cl : allClasses) classMap.put(cl.getClassId(), cl);
            Map<Long, CjMajor> majorMap = new LinkedHashMap<>();
            List<CjMajor> allMajors = majorMapper.selectCjMajorList(new CjMajor());
            if (allMajors != null) for (CjMajor m : allMajors) majorMap.put(m.getMajorId(), m);
            Map<Long, CjCollege> collegeMap = new LinkedHashMap<>();
            List<CjCollege> allColleges = collegeMapper.selectCjCollegeList(new CjCollege());
            if (allColleges != null) for (CjCollege c : allColleges) collegeMap.put(c.getCollegeId(), c);
            for (CjClass cl : classMap.values()) {
                if (!openClassIds.contains(cl.getClassId())) continue;
                CjMajor m = majorMap.get(cl.getMajorId());
                CjCollege co = (m == null) ? null : collegeMap.get(m.getCollegeId());
                String label = (co == null ? "" : co.getCollegeName()) + "·"
                        + (m == null ? "" : m.getMajorName()) + "·" + cl.getClassName();
                Map<String, Object> row = new LinkedHashMap<>();
                row.put("classId", cl.getClassId());
                row.put("label", label);
                out.add(row);
            }
        }
        return AjaxResult.success(Map.of("classes", out));
    }
    /**
     * è‡ªç™»è®°å»ºæ¡£ï¼ˆå¼€æ”¾ç™»è®°å·²ä¸‹çº¿ï¼šæ³¨å†Œç»Ÿä¸€èµ° /miniapp/account/register + ç­çº§ç ï¼‰
     */
    @PostMapping("/register")
    public AjaxResult register(@RequestBody Map<String, String> params) {
        return AjaxResult.error("该通道已停用,请通过班级二维码注册");
    }
    private AjaxResult legacyOpenRegister(Map<String, String> params) {
        String studentNo = params.get("studentNo");
        String name = params.get("name");
        String phone = params.get("phone");
        Long classId = params.get("classId") == null ? null : Long.valueOf(params.get("classId"));
        if (classId == null || isEmpty(studentNo) || isEmpty(name)) {
            return AjaxResult.error("请完整填写 ç­çº§/学号/姓名");
        }
        String capErr = captchaService.verify(params.get("code"), params.get("uuid"));
        if (capErr != null) return AjaxResult.error(capErr);
        CjClass clazz = classId == null ? null : classMapper.selectCjClassByClassId(classId);
        if (clazz == null) return AjaxResult.error("所选班级不存在");
        CjStudent dup = findByClassAndNo(classId, studentNo);
        CjStudent student;
        if (dup != null) {
            if (!name.equals(dup.getName())) return AjaxResult.error("该班已存在该学号且姓名不一致,请核对");
            // å·²è®¾ç½®ç™»å½•密码的学生不能再经开放登记免密拿 token
            String dupPwd = studentMapper.selectPasswordByStudentId(dup.getStudentId());
            if (dupPwd != null && !dupPwd.isEmpty()) return AjaxResult.error("账号已激活,请使用密码登录");
            student = dup;
        } else {
            CjStudent s = new CjStudent();
            s.setClassId(classId);
            s.setStudentNo(studentNo.trim());
            s.setName(name.trim());
            s.setPhone(isEmpty(phone) ? null : phone.trim());
            s.setStatus("0");
            s.setDelFlag("0");
            studentMapper.insertCjStudent(s);
            student = s;
        }
        // å†™å…¥å¾®ä¿¡ç»‘定并下发 token
        CjStudentBind qb = new CjStudentBind();
        qb.setStudentId(student.getStudentId());
        List<CjStudentBind> existsList = bindMapper.selectCjStudentBindList(qb);
        CjStudentBind exists = existsList.isEmpty() ? null : existsList.get(0);
        String openid = "mock-openid-" + UUID.randomUUID().toString().substring(0, 8);
        if (exists != null) {
            exists.setOpenidHash(openid);
            bindMapper.updateCjStudentBind(exists);
        } else {
            CjStudentBind bind = new CjStudentBind();
            bind.setStudentId(student.getStudentId());
            bind.setOpenidHash(openid);
            bind.setBindChannel("1");
            bind.setStatus("0");
            bindMapper.insertCjStudentBind(bind);
        }
        String token = UUID.randomUUID().toString().replace("-", "");
        redisCache.setCacheObject(TOKEN_PREFIX + token, student.getStudentId(), 24, TimeUnit.HOURS);
        tokenService.registerSession(student.getStudentId(), token); // ç™»è®°åå‘索引,供改密/强制下线作废
        return AjaxResult.success("登记成功", Map.of("token", token, "studentId", student.getStudentId()));
    }
    private CjStudent findByClassAndNo(Long classId, String studentNo) {
        CjStudent q = new CjStudent();
        q.setClassId(classId);
        q.setStudentNo(studentNo.trim());
        List<CjStudent> list = studentMapper.selectCjStudentList(q);
        return list.isEmpty() ? null : list.get(0);
    }
    private List<Long> scopeClassIds(CjFillTask task) {
        List<Long> ids = new ArrayList<>();
        try {
            Map<String, Object> root = om.readValue(task.getScopeJson(), new TypeReference<Map<String, Object>>() { });
            Object o = root.get("classIds");
            if (o instanceof List) {
                for (Object it : (List<?>) o) ids.add(((Number) it).longValue());
            }
        } catch (Exception ignore) { }
        return ids;
    }
    private boolean isEmpty(String s) { return s == null || s.trim().isEmpty(); }
    // ========== 3. æˆ‘的信息(含班级/专业/学院 + è´¦å·çŠ¶æ€ï¼‰ ==========
    @GetMapping("/my-info")
    public AjaxResult myInfo(@RequestHeader("Authorization") String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error("未登录");
        Map<String, Object> ctx = studentContext(sid);
        Object v = ctx.get("view");
        if (v instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> view = (Map<String, Object>) v;
            CjStudent s = (CjStudent) ctx.get("student");
            String pwd = studentMapper.selectPasswordByStudentId(sid);
            view.put("hasPassword", pwd != null && !pwd.isEmpty());
            view.put("mustChangePwd", s != null && "1".equals(s.getPwdResetFlag()));
        }
        return AjaxResult.success(v);
    }
    // ========== 4. æˆ‘可填报/已填报的任务列表 ==========
    @GetMapping("/tasks")
    public AjaxResult tasks(@RequestHeader("Authorization") String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error("未登录");
        Map<String, Object> ctx = studentContext(sid);
        Long myClassId = (Long) ctx.get("classId");
        if (myClassId == null) return AjaxResult.error("未找到你的班级信息,请联系老师");
        CjStudent student = (CjStudent) ctx.get("student");
        CjFillTask q = new CjFillTask();
        q.setStatus("1"); // åªåˆ—已发布任务
        List<CjFillTask> tasks = taskMapper.selectCjFillTaskList(q);
        List<Map<String, Object>> out = new ArrayList<>();
        if (tasks != null) {
            for (CjFillTask t : tasks) {
                if (!inScope(t, myClassId)) continue;
                boolean open = isOpen(t);
                CjFillRecord rec = recordMapper.selectByTaskAndStudent(t.getTaskId(), sid);
                // æœªåœ¨æˆ‘的填报窗口且没有记录的任务不展示
                if (!open && rec == null) continue;
                Map<String, Object> m = new LinkedHashMap<>();
                m.put("taskId", t.getTaskId());
                m.put("taskName", t.getTaskName());
                m.put("schoolYear", t.getSchoolYear());
                m.put("semester", t.getSemester());
                m.put("fillStartDate", fmtDate(t.getFillStartDate()));
                m.put("fillEndDate", fmtDate(t.getFillEndDate()));
                m.put("needApprove", t.getNeedApprove());
                m.put("open", open);
                m.put("recordStatus", rec == null ? null : rec.getStatus()); // 0草稿 1已提交
                m.put("submitTime", rec == null ? null : fmtTime(rec.getSubmitTime()));
                out.add(m);
            }
        }
        out.sort((a, b) -> orBlank(a.get("fillEndDate")).compareTo(orBlank(b.get("fillEndDate"))));
        return AjaxResult.success(Map.of("studentName", student.getName(), "studentNo", student.getStudentNo(), "tasks", out));
    }
    // ========== 5. ä»»åŠ¡è¡¨å•ï¼ˆschema + é¢„å¡« + æˆ‘的记录) ==========
    @GetMapping("/task/{taskId}")
    public AjaxResult taskForm(@PathVariable("taskId") Long taskId,
                               @RequestHeader("Authorization") String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error("未登录");
        CjFillTask task = taskMapper.selectCjFillTaskByTaskId(taskId);
        if (task == null) return AjaxResult.error("任务不存在");
        Map<String, Object> ctx = studentContext(sid);
        Long myClassId = (Long) ctx.get("classId");
        if (myClassId == null || !inScope(task, myClassId)) {
            // æ¢ç­åŽå…è®¸å›žçœ‹æ—§ç­çº§ä¸‹è‡ªå·±çš„记录(记录快照保留原班级归属,只读)
            CjFillRecord mine = recordMapper.selectByTaskAndStudent(taskId, sid);
            if (mine == null) return AjaxResult.error("该任务不在你的填报范围");
        }
        Map<String, Object> form = new LinkedHashMap<>();
        fillPrefill(task, ctx, form);
        CjFillRecord rec = recordMapper.selectByTaskAndStudent(taskId, sid);
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("taskId", task.getTaskId());
        data.put("taskName", task.getTaskName());
        data.put("schoolYear", task.getSchoolYear());
        data.put("semester", task.getSemester());
        data.put("termText", termText(task));
        data.put("taskStatus", task.getStatus());
        data.put("fillStartDate", fmtDate(task.getFillStartDate()));
        data.put("fillEndDate", fmtDate(task.getFillEndDate()));
        data.put("needApprove", task.getNeedApprove());
        data.put("open", isOpen(task));
        data.put("readonly", rec != null && "1".equals(rec.getStatus()));
        data.put("recordStatus", rec == null ? null : rec.getStatus());
        data.put("submitTime", rec == null ? null : fmtTime(rec.getSubmitTime()));
        // è‰ç¨¿/提交值覆盖预填
        if (rec != null && rec.getFormData() != null) {
            try {
                Map<String, Object> saved = om.readValue(rec.getFormData(), new TypeReference<Map<String, Object>>() { });
                if (saved != null) form.putAll(saved);
            } catch (Exception ignore) { }
        }
        data.put("form", form);
        data.put("schema", parseSchema(task.getSchemaJson())); // {groups, attachments}
        return AjaxResult.success(data);
    }
    // ========== 6. ä¿å­˜è‰ç¨¿ ==========
    @PostMapping("/task/draft")
    public AjaxResult saveDraft(@RequestBody Map<String, Object> body,
                                @RequestHeader("Authorization") String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error("未登录");
        Long taskId = longOf(body.get("taskId"));
        Map<String, Object> form = castMap(body.get("form"));
        CjFillTask task = checkWritable(sid, taskId, form);
        CjFillRecord rec = buildRecord(task, sid, form, "0", null);
        rec.setRecordId(existingRecordId(taskId, sid));
        if (rec.getRecordId() == null) recordMapper.insertCjFillRecord(rec);
        else recordMapper.updateCjFillRecord(rec);
        return AjaxResult.success("草稿已保存", Map.of("recordId", rec.getRecordId() == null ? 0L : rec.getRecordId()));
    }
    // ========== 7. æ­£å¼æäº¤ ==========
    @PostMapping("/task/submit")
    public AjaxResult submit(@RequestBody Map<String, Object> body,
                             @RequestHeader("Authorization") String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error("未登录");
        Long taskId = longOf(body.get("taskId"));
        Map<String, Object> form = castMap(body.get("form"));
        CjFillTask task = checkWritable(sid, taskId, form);
        String err = validateForm(task, form);
        if (err != null) return AjaxResult.error(err);
        CjFillRecord rec = buildRecord(task, sid, form, "1", new Date());
        rec.setRecordId(existingRecordId(taskId, sid));
        if (rec.getRecordId() == null) recordMapper.insertCjFillRecord(rec);
        else recordMapper.updateCjFillRecord(rec);
        return AjaxResult.success("提交成功", Map.of("recordId", rec.getRecordId() == null ? 0L : rec.getRecordId()));
    }
    // ========== 7.5 æ–‡ä»¶ä¸Šä¼ ï¼ˆè¡¨å•「文件上传」字段用,图片/PDF/Office ææ–™ç»Ÿä¸€å…¥å£ï¼‰ ==========
    /** ä¸Šä¼ åˆ° profile/upload ä¸‹ï¼Œè¿”回相对路径(/profile/upload/...),GET /profile/** å·²åŒ¿åæ”¾è¡Œå¯å›žæ˜¾ */
    @PostMapping("/upload")
    public AjaxResult upload(@RequestParam("file") MultipartFile file,
                             @RequestHeader(value = "Authorization", required = false) String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error(401, "未登录或登录已过期");
        if (file == null || file.isEmpty()) return AjaxResult.error("请选择要上传的文件");
        // è¡¨å•附件统一限制:单个文件不得大于 10MB(与 spring.servlet.multipart.max-file-size ä¸€è‡´ï¼‰
        if (file.getSize() > 10L * 1024 * 1024) return AjaxResult.error("文件不得大于 10MB");
        try {
            String fileName = FileUploadUtils.upload(RuoYiConfig.getUploadPath(), file);
            Map<String, Object> data = new LinkedHashMap<>();
            data.put("fileName", fileName);
            data.put("originalName", file.getOriginalFilename());
            return AjaxResult.success(data);
        } catch (Exception e) {
            return AjaxResult.error("上传失败:" + e.getMessage());
        }
    }
    // =================================================================
    //                      ç§æœ‰å·¥å…·
    // =================================================================
    // ========== 8. æ’¤å›žå·²æäº¤ï¼ˆå›žåˆ°è‰ç¨¿å¯æ”¹ï¼‰ ==========
    @PostMapping("/task/withdraw")
    public AjaxResult withdraw(@RequestBody Map<String, Object> body,
                               @RequestHeader("Authorization") String auth) {
        Long sid = resolveStudentId(auth);
        if (sid == null) return AjaxResult.error("未登录");
        Long taskId = longOf(body.get("taskId"));
        if (taskId == null) return AjaxResult.error("缺少 taskId");
        CjFillTask task = taskMapper.selectCjFillTaskByTaskId(taskId);
        if (task == null) return AjaxResult.error("任务不存在");
        if (!"1".equals(task.getStatus()) || !isOpen(task)) {
            return AjaxResult.error("仅在填报时间内的任务可撤回,超过时间请联系班级管理人退回");
        }
        CjFillRecord rec = recordMapper.selectByTaskAndStudent(taskId, sid);
        if (rec == null || !"1".equals(rec.getStatus())) {
            return AjaxResult.error("当前没有可撤回的已提交记录");
        }
        recordMapper.rollbackDraft(rec.getRecordId());
        return AjaxResult.success("已撤回,可修改后重新提交", Map.of("taskId", taskId));
    }
    /** æ£€æŸ¥ä»»åŠ¡å¯å†™ï¼šä»»åŠ¡å‘å¸ƒ/填报窗口内/范围内/未提交 */
    private CjFillTask checkWritable(Long sid, Long taskId, Map<String, Object> form) {
        if (taskId == null) throw new ServiceException("缺少 taskId");
        CjFillTask task = taskMapper.selectCjFillTaskByTaskId(taskId);
        if (task == null) throw new ServiceException("任务不存在");
        Map<String, Object> ctx = studentContext(sid);
        Long myClassId = (Long) ctx.get("classId");
        if (myClassId == null || !inScope(task, myClassId)) throw new ServiceException("该任务不在你的填报范围");
        if (!"1".equals(task.getStatus())) throw new ServiceException("任务未发布或已关闭");
        if (!isOpen(task)) throw new ServiceException("不在填报时间范围内");
        CjFillRecord existing = recordMapper.selectByTaskAndStudent(taskId, sid);
        if (existing != null && "1".equals(existing.getStatus())) throw new ServiceException("已提交不可修改");
        return task;
    }
    private Long existingRecordId(Long taskId, Long sid) {
        CjFillRecord r = recordMapper.selectByTaskAndStudent(taskId, sid);
        return r == null ? null : r.getRecordId();
    }
    /** ç»„装记录(学生快照 + form ç­”案 + isOutside æœåŠ¡ç«¯è®¡ç®—ï¼‰ */
    private CjFillRecord buildRecord(CjFillTask task, Long sid, Map<String, Object> form, String status, Date submitTime) {
        CjStudent s = studentMapper.selectCjStudentByStudentId(sid);
        Map<String, Object> ctx = studentContext(sid);
        String province = str(form.get("province"));
        form.put("isOutside", computeOutside(task, province));
        CjFillRecord rec = new CjFillRecord();
        rec.setTaskId(task.getTaskId());
        rec.setStudentId(sid);
        rec.setStudentNo(s.getStudentNo());
        rec.setStudentName(s.getName());
        rec.setGenderText(genderText(s.getGender()));
        rec.setPhone(s.getPhone());
        rec.setClassId((Long) ctx.get("classId"));
        rec.setClassName((String) ctx.get("className"));
        rec.setMajorName((String) ctx.get("majorName"));
        rec.setCollegeName((String) ctx.get("collegeName"));
        rec.setStatus(status);
        rec.setSubmitTime(submitTime);
        try {
            rec.setFormData(om.writeValueAsString(form));
        } catch (Exception e) {
            throw new ServiceException("数据序列化失败: " + e.getMessage());
        }
        return rec;
    }
    /** æœåŠ¡ç«¯æŒ‰ä»»åŠ¡æŽ’é™¤é›†è®¡ç®—â€œæ˜¯å¦å¤–çœ/境外”,结果 1/0,写回 form */
    private String computeOutside(CjFillTask task, String province) {
        if (province == null || province.trim().isEmpty()) return "";
        String exclude = task.getOutsideExclude();
        if (exclude != null) {
            for (String s : exclude.split(",")) {
                if (s.trim().equals(province.trim())) return "0";
            }
        }
        return "1";
    }
    /** å®¢æˆ·ç«¯æäº¤å‰çš„æœåŠ¡ç«¯æ ¡éªŒï¼ˆå¿…å¡«/手机号/信用代码/数值区间) */
    private String validateForm(CjFillTask task, Map<String, Object> form) {
        Map<String, Object> schema = parseSchema(task.getSchemaJson());
        Object groupsObj = schema.get("groups");
        if (!(groupsObj instanceof List)) return "表单配置缺失";
        for (Object go : (List<?>) groupsObj) {
            Map<String, Object> g = (Map<String, Object>) go;
            Object fs = g.get("fields");
            if (!(fs instanceof List)) continue;
            for (Object fo : (List<?>) fs) {
                Map<String, Object> f = (Map<String, Object>) fo;
                String type = str(f.get("type"));
                boolean readonly = Boolean.TRUE.equals(f.get("readonly")) || "server".equals(str(f.get("auto")))
                        || "roster".equals(str(f.get("auto"))) || "task".equals(str(f.get("auto")));
                if (readonly) continue;
                String code = str(f.get("code"));
                String label = str(f.get("label"));
                // æ–‡ä»¶ç±»å­—段(图片/PDF/Office ææ–™ç»Ÿä¸€ï¼‰ï¼šå€¼æ˜¯è·¯å¾„数组(兼容逗号拼接字符串与历史 image ç±»åž‹ï¼‰ï¼Œå•独校验
                if ("image".equals(type) || "file".equals(type)) {
                    List<String> files = fileList(form.get(code));
                    if (Boolean.TRUE.equals(f.get("required")) && files.isEmpty()) return "请上传「" + label + "」";
                    int max = 9;
                    Object mc = f.get("maxCount");
                    if (mc instanceof Number) max = ((Number) mc).intValue();
                    else if (mc != null) { try { max = Integer.parseInt(mc.toString().trim()); } catch (NumberFormatException ignore) { } }
                    if (files.size() > max) return "「" + label + "」最多上传 " + max + " ä¸ªæ–‡ä»¶";
                    for (String p : files) {
                        if (!p.startsWith("/profile/upload/")) return "「" + label + "」包含非法文件地址";
                    }
                    continue;
                }
                Object v = form.get(code);
                String val = v == null ? "" : v.toString().trim();
                if (Boolean.TRUE.equals(f.get("required")) && val.isEmpty()) {
                    return "请填写「" + label + "」";
                }
                if (val.isEmpty()) continue;
                if ("phone".equals(type) && !val.matches(PHONE_RE)) return "「" + label + "」格式不正确(11位大陆手机号)";
                if ("creditCode".equals(type) && !val.matches(CREDIT_CODE_RE)) return "「" + label + "」须为18位合法统一社会信用代码";
                if ("number".equals(type)) {
                    try {
                        double d = Double.parseDouble(val);
                        if (f.get("min") != null && d < ((Number) f.get("min")).doubleValue()) return "「" + label + "」不能小于 " + f.get("min");
                        if (f.get("max") != null && d > ((Number) f.get("max")).doubleValue()) return "「" + label + "」不能大于 " + f.get("max");
                    } catch (NumberFormatException e) {
                        return "「" + label + "」必须是数字";
                    }
                }
            }
        }
        return null;
    }
    /** é¢„填系统带出字段(roster/task/server)与手机号 */
    private void fillPrefill(CjFillTask task, Map<String, Object> ctx, Map<String, Object> form) {
        CjStudent s = (CjStudent) ctx.get("student");
        Map<String, Object> schema = parseSchema(task.getSchemaJson());
        Object groupsObj = schema.get("groups");
        if (groupsObj instanceof List) {
            for (Object go : (List<?>) groupsObj) {
                Map<String, Object> g = (Map<String, Object>) go;
                Object fs = g.get("fields");
                if (!(fs instanceof List)) continue;
                for (Object fo : (List<?>) fs) {
                    Map<String, Object> f = (Map<String, Object>) fo;
                    String code = str(f.get("code"));
                    String auto = str(f.get("auto"));
                    if ("roster".equals(auto)) {
                        String val = rosterValue(code, ctx);
                        if (val != null) form.put(code, val);
                    } else if ("task".equals(auto)) {
                        form.put(code, termText(task));
                    } else if ("server".equals(auto)) {
                        form.put(code, "");
                    } else if ("studentPhone".equals(code) && s.getPhone() != null && !s.getPhone().isEmpty()) {
                        form.putIfAbsent(code, s.getPhone());
                    }
                }
            }
        }
    }
    private String rosterValue(String code, Map<String, Object> ctx) {
        CjStudent s = (CjStudent) ctx.get("student");
        switch (code) {
            case "collegeName": return (String) ctx.get("collegeName");
            case "majorName": return (String) ctx.get("majorName");
            case "className": return (String) ctx.get("className");
            case "studentName": return s.getName();
            case "studentNo": return s.getStudentNo();
            case "gender": return genderText(s.getGender());
            default: return null;
        }
    }
    private Map<String, Object> studentContext(Long sid) {
        Map<String, Object> res = new LinkedHashMap<>();
        CjStudent s = studentMapper.selectCjStudentByStudentId(sid);
        res.put("student", s);
        if (s == null) return res;
        Long cid = s.getClassId();
        CjClass cl = cid == null ? null : classMapper.selectCjClassByClassId(cid);
        if (cl != null) {
            res.put("classId", cl.getClassId());
            res.put("className", cl.getClassName());
            CjMajor m = cl.getMajorId() == null ? null : majorMapper.selectCjMajorByMajorId(cl.getMajorId());
            if (m != null) {
                res.put("majorName", m.getMajorName());
                CjCollege col = m.getCollegeId() == null ? null : collegeMapper.selectCjCollegeByCollegeId(m.getCollegeId());
                res.put("collegeName", col == null ? "" : col.getCollegeName());
            } else {
                res.put("majorName", "");
                res.put("collegeName", "");
            }
        }
        // å‰ç«¯ view(去重自 studentContext çš„直接字段)
        Map<String, Object> view = new LinkedHashMap<>();
        view.put("studentId", s.getStudentId());
        view.put("studentNo", s.getStudentNo());
        view.put("name", s.getName());
        view.put("genderText", genderText(s.getGender()));
        view.put("phone", s.getPhone());
        view.put("classId", res.get("classId"));
        view.put("className", res.get("className"));
        view.put("majorName", res.get("majorName"));
        view.put("collegeName", res.get("collegeName"));
        res.put("view", view);
        return res;
    }
    private boolean inScope(CjFillTask task, Long myClassId) {
        String scope = task.getScopeJson();
        if (scope == null) return false;
        try {
            Map<String, Object> root = om.readValue(scope, new TypeReference<Map<String, Object>>() { });
            Object ids = root.get("classIds");
            if (ids instanceof List) {
                for (Object o : (List<?>) ids) {
                    if (((Number) o).longValue() == myClassId.longValue()) return true;
                }
            }
        } catch (Exception ignore) { }
        return false;
    }
    private boolean isOpen(CjFillTask task) {
        if (!"1".equals(task.getStatus())) return false;
        if (task.getFillStartDate() == null || task.getFillEndDate() == null) return false;
        LocalDate today = LocalDate.now();
        LocalDate start = task.getFillStartDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate end = task.getFillEndDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        return !today.isBefore(start) && !today.isAfter(end);
    }
    private Map<String, Object> parseSchema(String schemaJson) {
        Map<String, Object> res = new LinkedHashMap<>();
        res.put("groups", new ArrayList<>());
        res.put("attachments", new ArrayList<>());
        if (schemaJson == null) return res;
        try {
            Map<String, Object> root = om.readValue(schemaJson, new TypeReference<Map<String, Object>>() { });
            if (root.get("groups") != null) res.put("groups", root.get("groups"));
            if (root.get("attachments") != null) res.put("attachments", root.get("attachments"));
        } catch (Exception ignore) { }
        return res;
    }
    private String termText(CjFillTask t) {
        StringBuilder sb = new StringBuilder();
        if (t.getSchoolYear() != null) sb.append(t.getSchoolYear());
        sb.append("学年");
        if ("1".equals(t.getSemester())) sb.append("第一学期");
        else if ("2".equals(t.getSemester())) sb.append("第二学期");
        return sb.toString();
    }
    private String genderText(String code) {
        if (code == null) return "未知";
        switch (code.trim()) {
            case "0": case "男": return "男";
            case "1": case "女": return "女";
            default: return "未知";
        }
    }
    private String orBlank(Object o) { return o == null ? "" : o.toString(); }
    /** H5 ç¨³å®š openid:对设备码取 MD5,保证同一浏览器身份不变 */
    private String md5Hex(String s) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] d = md.digest(s.getBytes(java.nio.charset.StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte b : d) { String h = Integer.toHexString(0xff & b); if (h.length() == 1) sb.append('0'); sb.append(h); }
            return sb.toString();
        } catch (Exception e) {
            return Integer.toHexString(s.hashCode());
        }
    }
    private String fmtDate(Date d) {
        if (d == null) return null;
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
        return sdf.format(d);
    }
    private String fmtTime(Date d) {
        if (d == null) return null;
        java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm");
        return sdf.format(d);
    }
    @SuppressWarnings("unchecked")
    private Map<String, Object> castMap(Object o) {
        if (o instanceof Map) return (Map<String, Object>) o;
        throw new ServiceException("form å‚数格式错误");
    }
    private Long longOf(Object o) {
        if (o == null) return null;
        return Long.valueOf(o.toString());
    }
    private String str(Object o) { return o == null ? null : o.toString(); }
    /** å›¾ç‰‡/文件字段的值:路径数组或逗号拼接字符串 â†’ éžç©ºè·¯å¾„列表 */
    private List<String> fileList(Object v) {
        List<String> out = new ArrayList<>();
        if (v instanceof List) {
            for (Object o : (List<?>) v) {
                String s = str(o);
                if (s != null && !s.trim().isEmpty()) out.add(s.trim());
            }
        } else if (v != null) {
            for (String s : v.toString().split(",")) {
                if (!s.trim().isEmpty()) out.add(s.trim());
            }
        }
        return out;
    }
    private String code2session(String code) {
        try {
            String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + wxAppid
                    + "&secret=" + wxSecret + "&js_code=" + code + "&grant_type=authorization_code";
            HttpClient client = HttpClient.newBuilder().connectTimeout(java.time.Duration.ofSeconds(5)).build();
            HttpResponse<String> resp = client.send(HttpRequest.newBuilder(URI.create(url)).GET().build(),
                    HttpResponse.BodyHandlers.ofString());
            Map<String, Object> json = om.readValue(resp.body(), Map.class);
            if (json.get("openid") != null) return (String) json.get("openid");
            log.warn("code2session å¤±è´¥: {}", json.get("errmsg"));
            return null;
        } catch (Exception e) {
            log.error("调用微信 code2session å¼‚常", e);
            return null;
        }
    }
    private Long resolveStudentId(String auth) {
        if (auth == null || !auth.startsWith("Bearer ")) return null;
        Object val = redisCache.getCacheObject(TOKEN_PREFIX + auth.substring(7));
        if (val instanceof Long) {
            Long sid = (Long) val;
            return sid > 0 ? sid : null;
        }
        return null;
    }
    /** ä»Žç™»å½•态 token è¯»å–“未绑定时暂存的 openid”,用于绑定时关联微信身份 */
    private String openidOfToken(String auth) {
        if (auth == null || !auth.startsWith("Bearer ")) return null;
        Object val = redisCache.getCacheObject(OPENID_PREFIX + auth.substring(7));
        return val == null ? null : val.toString();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysCache;
/**
 * ç¼“存监控
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/cache")
public class CacheController
{
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private final static List<SysCache> caches = new ArrayList<SysCache>();
    {
        caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息"));
        caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"));
        caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"));
        caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
        caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
        caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
        caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));
    }
    @SuppressWarnings("deprecation")
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping()
    public AjaxResult getInfo() throws Exception
    {
        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
        Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
        Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
        Map<String, Object> result = new HashMap<>(3);
        result.put("info", info);
        result.put("dbSize", dbSize);
        List<Map<String, String>> pieList = new ArrayList<>();
        commandStats.stringPropertyNames().forEach(key -> {
            Map<String, String> data = new HashMap<>(2);
            String property = commandStats.getProperty(key);
            data.put("name", StringUtils.removeStart(key, "cmdstat_"));
            data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
            pieList.add(data);
        });
        result.put("commandStats", pieList);
        return AjaxResult.success(result);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getNames")
    public AjaxResult cache()
    {
        return AjaxResult.success(caches);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getKeys/{cacheName}")
    public AjaxResult getCacheKeys(@PathVariable String cacheName)
    {
        Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
        return AjaxResult.success(new TreeSet<>(cacheKeys));
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("/getValue/{cacheName}/{cacheKey}")
    public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
    {
        String cacheValue = redisTemplate.opsForValue().get(cacheKey);
        SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
        return AjaxResult.success(sysCache);
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheName/{cacheName}")
    public AjaxResult clearCacheName(@PathVariable String cacheName)
    {
        Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
        redisTemplate.delete(cacheKeys);
        return AjaxResult.success();
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheKey/{cacheKey}")
    public AjaxResult clearCacheKey(@PathVariable String cacheKey)
    {
        redisTemplate.delete(cacheKey);
        return AjaxResult.success();
    }
    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @DeleteMapping("/clearCacheAll")
    public AjaxResult clearCacheAll()
    {
        Collection<String> cacheKeys = redisTemplate.keys("*");
        redisTemplate.delete(cacheKeys);
        return AjaxResult.success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
package com.ruoyi.web.controller.monitor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.framework.web.domain.Server;
/**
 * æœåŠ¡å™¨ç›‘æŽ§
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/server")
public class ServerController
{
    @PreAuthorize("@ss.hasPermi('monitor:server:list')")
    @GetMapping()
    public AjaxResult getInfo() throws Exception
    {
        Server server = new Server();
        server.copyTo();
        return AjaxResult.success(server);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPasswordService;
import com.ruoyi.system.domain.SysLogininfor;
import com.ruoyi.system.service.ISysLogininforService;
/**
 * ç³»ç»Ÿè®¿é—®è®°å½•
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/logininfor")
public class SysLogininforController extends BaseController
{
    @Autowired
    private ISysLogininforService logininforService;
    @Autowired
    private SysPasswordService passwordService;
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysLogininfor logininfor)
    {
        startPage();
        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
        return getDataTable(list);
    }
    @Log(title = "登录日志", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysLogininfor logininfor)
    {
        List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
        ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
        util.exportExcel(response, list, "登录日志");
    }
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
    @Log(title = "登录日志", businessType = BusinessType.DELETE)
    @DeleteMapping("/{infoIds}")
    public AjaxResult remove(@PathVariable Long[] infoIds)
    {
        return toAjax(logininforService.deleteLogininforByIds(infoIds));
    }
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
    @Log(title = "登录日志", businessType = BusinessType.CLEAN)
    @DeleteMapping("/clean")
    public AjaxResult clean()
    {
        logininforService.cleanLogininfor();
        return success();
    }
    @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
    @Log(title = "账户解锁", businessType = BusinessType.OTHER)
    @GetMapping("/unlock/{userName}")
    public AjaxResult unlock(@PathVariable("userName") String userName)
    {
        passwordService.clearLoginRecordCache(userName);
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.service.ISysOperLogService;
/**
 * æ“ä½œæ—¥å¿—记录
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController
{
    @Autowired
    private ISysOperLogService operLogService;
    @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysOperLog operLog)
    {
        startPage();
        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
        return getDataTable(list);
    }
    @Log(title = "操作日志", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysOperLog operLog)
    {
        List<SysOperLog> list = operLogService.selectOperLogList(operLog);
        ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
        util.exportExcel(response, list, "操作日志");
    }
    @Log(title = "操作日志", businessType = BusinessType.DELETE)
    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
    @DeleteMapping("/{operIds}")
    public AjaxResult remove(@PathVariable Long[] operIds)
    {
        return toAjax(operLogService.deleteOperLogByIds(operIds));
    }
    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
    @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
    @DeleteMapping("/clean")
    public AjaxResult clean()
    {
        operLogService.cleanOperLog();
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,83 @@
package com.ruoyi.web.controller.monitor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysUserOnline;
import com.ruoyi.system.service.ISysUserOnlineService;
/**
 * åœ¨çº¿ç”¨æˆ·ç›‘控
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/monitor/online")
public class SysUserOnlineController extends BaseController
{
    @Autowired
    private ISysUserOnlineService userOnlineService;
    @Autowired
    private RedisCache redisCache;
    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
    @GetMapping("/list")
    public TableDataInfo list(String ipaddr, String userName)
    {
        Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
        for (String key : keys)
        {
            LoginUser user = redisCache.getCacheObject(key);
            if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
            {
                userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
            }
            else if (StringUtils.isNotEmpty(ipaddr))
            {
                userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
            }
            else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
            {
                userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
            }
            else
            {
                userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
            }
        }
        Collections.reverse(userOnlineList);
        userOnlineList.removeAll(Collections.singleton(null));
        return getDataTable(userOnlineList);
    }
    /**
     * å¼ºé€€ç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("/{tokenId}")
    public AjaxResult forceLogout(@PathVariable String tokenId)
    {
        redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,133 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.service.ISysConfigService;
/**
 * å‚数配置 ä¿¡æ¯æ“ä½œå¤„理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/config")
public class SysConfigController extends BaseController
{
    @Autowired
    private ISysConfigService configService;
    /**
     * èŽ·å–å‚æ•°é…ç½®åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:config:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysConfig config)
    {
        startPage();
        List<SysConfig> list = configService.selectConfigList(config);
        return getDataTable(list);
    }
    @Log(title = "参数管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:config:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysConfig config)
    {
        List<SysConfig> list = configService.selectConfigList(config);
        ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
        util.exportExcel(response, list, "参数数据");
    }
    /**
     * æ ¹æ®å‚数编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:config:query')")
    @GetMapping(value = "/{configId}")
    public AjaxResult getInfo(@PathVariable Long configId)
    {
        return success(configService.selectConfigById(configId));
    }
    /**
     * æ ¹æ®å‚数键名查询参数值
     */
    @GetMapping(value = "/configKey/{configKey}")
    public AjaxResult getConfigKey(@PathVariable String configKey)
    {
        return success(configService.selectConfigByKey(configKey));
    }
    /**
     * æ–°å¢žå‚数配置
     */
    @PreAuthorize("@ss.hasPermi('system:config:add')")
    @Log(title = "参数管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysConfig config)
    {
        if (!configService.checkConfigKeyUnique(config))
        {
            return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
        }
        config.setCreateBy(getUsername());
        return toAjax(configService.insertConfig(config));
    }
    /**
     * ä¿®æ”¹å‚数配置
     */
    @PreAuthorize("@ss.hasPermi('system:config:edit')")
    @Log(title = "参数管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysConfig config)
    {
        if (!configService.checkConfigKeyUnique(config))
        {
            return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
        }
        config.setUpdateBy(getUsername());
        return toAjax(configService.updateConfig(config));
    }
    /**
     * åˆ é™¤å‚数配置
     */
    @PreAuthorize("@ss.hasPermi('system:config:remove')")
    @Log(title = "参数管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{configIds}")
    public AjaxResult remove(@PathVariable Long[] configIds)
    {
        configService.deleteConfigByIds(configIds);
        return success();
    }
    /**
     * åˆ·æ–°å‚数缓存
     */
    @PreAuthorize("@ss.hasPermi('system:config:remove')")
    @Log(title = "参数管理", businessType = BusinessType.CLEAN)
    @DeleteMapping("/refreshCache")
    public AjaxResult refreshCache()
    {
        configService.resetConfigCache();
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,147 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
/**
 * éƒ¨é—¨ä¿¡æ¯
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController
{
    @Autowired
    private ISysDeptService deptService;
    /**
     * èŽ·å–éƒ¨é—¨åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list")
    public AjaxResult list(SysDept dept)
    {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return success(depts);
    }
    /**
     * æŸ¥è¯¢éƒ¨é—¨åˆ—表(排除节点)
     */
    @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list/exclude/{deptId}")
    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
    {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return success(depts);
    }
    /**
     * æ ¹æ®éƒ¨é—¨ç¼–号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:dept:query')")
    @GetMapping(value = "/{deptId}")
    public AjaxResult getInfo(@PathVariable Long deptId)
    {
        deptService.checkDeptDataScope(deptId);
        return success(deptService.selectDeptById(deptId));
    }
    /**
     * æ–°å¢žéƒ¨é—¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:add')")
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDept dept)
    {
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
        }
        dept.setCreateBy(getUsername());
        return toAjax(deptService.insertDept(dept));
    }
    /**
     * ä¿®æ”¹éƒ¨é—¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDept dept)
    {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
        }
        else if (dept.getParentId().equals(deptId))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,上级部门不能是自己");
        }
        else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
        {
            return error("该部门包含未停用的子部门!");
        }
        dept.setUpdateBy(getUsername());
        return toAjax(deptService.updateDept(dept));
    }
    /**
     * ä¿å­˜éƒ¨é—¨æŽ’序
     */
    @PreAuthorize("@ss.hasPermi('system:dept:edit')")
    @Log(title = "保存部门排序", businessType = BusinessType.UPDATE)
    @PutMapping("/updateSort")
    public AjaxResult updateSort(@RequestBody Map<String, String> params)
    {
        String[] deptIds = params.get("deptIds").split(",");
        String[] orderNums = params.get("orderNums").split(",");
        deptService.updateDeptSort(deptIds, orderNums);
        return success();
    }
    /**
     * åˆ é™¤éƒ¨é—¨
     */
    @PreAuthorize("@ss.hasPermi('system:dept:remove')")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable Long deptId)
    {
        if (deptService.hasChildByDeptId(deptId))
        {
            return warn("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId))
        {
            return warn("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        return toAjax(deptService.deleteDeptById(deptId));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
/**
 * æ•°æ®å­—典信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/dict/data")
public class SysDictDataController extends BaseController
{
    @Autowired
    private ISysDictDataService dictDataService;
    @Autowired
    private ISysDictTypeService dictTypeService;
    @PreAuthorize("@ss.hasPermi('system:dict:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysDictData dictData)
    {
        startPage();
        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
        return getDataTable(list);
    }
    @Log(title = "字典数据", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:dict:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysDictData dictData)
    {
        List<SysDictData> list = dictDataService.selectDictDataList(dictData);
        ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
        util.exportExcel(response, list, "字典数据");
    }
    /**
     * æŸ¥è¯¢å­—典数据详细
     */
    @PreAuthorize("@ss.hasPermi('system:dict:query')")
    @GetMapping(value = "/{dictCode}")
    public AjaxResult getInfo(@PathVariable Long dictCode)
    {
        return success(dictDataService.selectDictDataById(dictCode));
    }
    /**
     * æ ¹æ®å­—典类型查询字典数据信息
     */
    @GetMapping(value = "/type/{dictType}")
    public AjaxResult dictType(@PathVariable String dictType)
    {
        List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
        if (StringUtils.isNull(data))
        {
            data = new ArrayList<SysDictData>();
        }
        return success(data);
    }
    /**
     * æ–°å¢žå­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:add')")
    @Log(title = "字典数据", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDictData dict)
    {
        dict.setCreateBy(getUsername());
        return toAjax(dictDataService.insertDictData(dict));
    }
    /**
     * ä¿®æ”¹ä¿å­˜å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
    @Log(title = "字典数据", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDictData dict)
    {
        dict.setUpdateBy(getUsername());
        return toAjax(dictDataService.updateDictData(dict));
    }
    /**
     * åˆ é™¤å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{dictCodes}")
    public AjaxResult remove(@PathVariable Long[] dictCodes)
    {
        dictDataService.deleteDictDataByIds(dictCodes);
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,131 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictType;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDictTypeService;
/**
 * æ•°æ®å­—典信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/dict/type")
public class SysDictTypeController extends BaseController
{
    @Autowired
    private ISysDictTypeService dictTypeService;
    @PreAuthorize("@ss.hasPermi('system:dict:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysDictType dictType)
    {
        startPage();
        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
        return getDataTable(list);
    }
    @Log(title = "字典类型", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:dict:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysDictType dictType)
    {
        List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
        ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
        util.exportExcel(response, list, "字典类型");
    }
    /**
     * æŸ¥è¯¢å­—典类型详细
     */
    @PreAuthorize("@ss.hasPermi('system:dict:query')")
    @GetMapping(value = "/{dictId}")
    public AjaxResult getInfo(@PathVariable Long dictId)
    {
        return success(dictTypeService.selectDictTypeById(dictId));
    }
    /**
     * æ–°å¢žå­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:add')")
    @Log(title = "字典类型", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysDictType dict)
    {
        if (!dictTypeService.checkDictTypeUnique(dict))
        {
            return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
        }
        dict.setCreateBy(getUsername());
        return toAjax(dictTypeService.insertDictType(dict));
    }
    /**
     * ä¿®æ”¹å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:edit')")
    @Log(title = "字典类型", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysDictType dict)
    {
        if (!dictTypeService.checkDictTypeUnique(dict))
        {
            return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
        }
        dict.setUpdateBy(getUsername());
        return toAjax(dictTypeService.updateDictType(dict));
    }
    /**
     * åˆ é™¤å­—典类型
     */
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
    @Log(title = "字典类型", businessType = BusinessType.DELETE)
    @DeleteMapping("/{dictIds}")
    public AjaxResult remove(@PathVariable Long[] dictIds)
    {
        dictTypeService.deleteDictTypeByIds(dictIds);
        return success();
    }
    /**
     * åˆ·æ–°å­—典缓存
     */
    @PreAuthorize("@ss.hasPermi('system:dict:remove')")
    @Log(title = "字典类型", businessType = BusinessType.CLEAN)
    @DeleteMapping("/refreshCache")
    public AjaxResult refreshCache()
    {
        dictTypeService.resetDictCache();
        return success();
    }
    /**
     * èŽ·å–å­—å…¸é€‰æ‹©æ¡†åˆ—è¡¨
     */
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
        return success(dictTypes);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
package com.ruoyi.web.controller.system;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysUserService;
/**
 * é¦–页
 *
 * @author ruoyi
 */
@RestController
public class SysIndexController
{
    /** ç³»ç»ŸåŸºç¡€é…ç½® */
    @Autowired
    private RuoYiConfig ruoyiConfig;
    @Autowired
    private ISysUserService userService;
    /**
     * è®¿é—®é¦–页,提示语
     */
    @RequestMapping("/")
    public String index()
    {
        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
    }
    /**
     * è§£é”å±å¹•
     */
    @PostMapping("/unlockscreen")
    public AjaxResult unlockScreen(@RequestBody Map<String, String> body)
    {
        String password = body.get("password");
        if (StringUtils.isEmpty(password))
        {
            return AjaxResult.error("密码不能为空");
        }
        String username = SecurityUtils.getUsername();
        SysUser user = userService.selectUserByUserName(username);
        if (user == null)
        {
            return AjaxResult.error("服务器超时,请重新登录");
        }
        if (!SecurityUtils.matchesPassword(password, user.getPassword()))
        {
            return AjaxResult.error("密码错误,请重新输入");
        }
        return AjaxResult.success("解锁成功");
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,138 @@
package com.ruoyi.web.controller.system;
import java.util.Date;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysMenuService;
/**
 * ç™»å½•验证
 *
 * @author ruoyi
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ISysConfigService configService;
    /**
     * ç™»å½•方法
     *
     * @param loginBody ç™»å½•信息
     * @return ç»“æžœ
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // ç”Ÿæˆä»¤ç‰Œ
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }
    /**
     * èŽ·å–ç”¨æˆ·ä¿¡æ¯
     *
     * @return ç”¨æˆ·ä¿¡æ¯
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        // è§’色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // æƒé™é›†åˆ
        Set<String> permissions = permissionService.getMenuPermission(user);
        if (!loginUser.getPermissions().equals(permissions))
        {
            loginUser.setPermissions(permissions);
            tokenService.refreshToken(loginUser);
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("pwdChrtype", getSysAccountChrtype());
        ajax.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
        ajax.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
        return ajax;
    }
    /**
     * èŽ·å–è·¯ç”±ä¿¡æ¯
     *
     * @return è·¯ç”±ä¿¡æ¯
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
    // èŽ·å–ç”¨æˆ·å¯†ç è‡ªå®šä¹‰é…ç½®è§„åˆ™
    public String getSysAccountChrtype()
    {
        return Convert.toStr(configService.selectConfigByKey("sys.account.chrtype"), "0");
    }
    // æ£€æŸ¥åˆå§‹å¯†ç æ˜¯å¦æé†’修改
    public boolean initPasswordIsModify(Date pwdUpdateDate)
    {
        Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
        return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
    }
    // æ£€æŸ¥å¯†ç æ˜¯å¦è¿‡æœŸ
    public boolean passwordIsExpiration(Date pwdUpdateDate)
    {
        Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
        if (passwordValidateDays != null && passwordValidateDays > 0)
        {
            if (StringUtils.isNull(pwdUpdateDate))
            {
                // å¦‚果从未修改过初始密码,直接提醒过期
                return true;
            }
            Date nowDate = DateUtils.getNowDate();
            return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
        }
        return false;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,165 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysMenuService;
/**
 * èœå•信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/menu")
public class SysMenuController extends BaseController
{
    @Autowired
    private ISysMenuService menuService;
    /**
     * èŽ·å–èœå•åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @GetMapping("/list")
    public AjaxResult list(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return success(menus);
    }
    /**
     * æ ¹æ®èœå•编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:menu:query')")
    @GetMapping(value = "/{menuId}")
    public AjaxResult getInfo(@PathVariable Long menuId)
    {
        return success(menuService.selectMenuById(menuId));
    }
    /**
     * èŽ·å–èœå•ä¸‹æ‹‰æ ‘åˆ—è¡¨
     */
    @GetMapping("/treeselect")
    public AjaxResult treeselect(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return success(menuService.buildMenuTreeSelect(menus));
    }
    /**
     * åŠ è½½å¯¹åº”è§’è‰²èœå•åˆ—è¡¨æ ‘
     */
    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
    {
        List<SysMenu> menus = menuService.selectMenuList(getUserId());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
        return ajax;
    }
    /**
     * æ–°å¢žèœå•
     */
    @PreAuthorize("@ss.hasPermi('system:menu:add')")
    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysMenu menu)
    {
        if (!menuService.checkMenuNameUnique(menu))
        {
            return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
        }
        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
        {
            return error("新增菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
        }
        else if (!menuService.checkRouteConfigUnique(menu))
        {
            return error("新增菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
        }
        menu.setCreateBy(getUsername());
        return toAjax(menuService.insertMenu(menu));
    }
    /**
     * ä¿®æ”¹èœå•
     */
    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
    @Log(title = "菜单管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysMenu menu)
    {
        if (!menuService.checkMenuNameUnique(menu))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
        }
        else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,地址必须以http(s)://开头");
        }
        else if (menu.getMenuId().equals(menu.getParentId()))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,上级菜单不能选择自己");
        }
        else if (!menuService.checkRouteConfigUnique(menu))
        {
            return error("修改菜单'" + menu.getMenuName() + "'失败,路由名称或地址已存在");
        }
        menu.setUpdateBy(getUsername());
        return toAjax(menuService.updateMenu(menu));
    }
    /**
     * ä¿å­˜èœå•排序
     */
    @PreAuthorize("@ss.hasPermi('system:menu:edit')")
    @Log(title = "保存菜单排序", businessType = BusinessType.UPDATE)
    @PutMapping("/updateSort")
    public AjaxResult updateSort(@RequestBody Map<String, String> params)
    {
        String[] menuIds = params.get("menuIds").split(",");
        String[] orderNums = params.get("orderNums").split(",");
        menuService.updateMenuSort(menuIds, orderNums);
        return success();
    }
    /**
     * åˆ é™¤èœå•
     */
    @PreAuthorize("@ss.hasPermi('system:menu:remove')")
    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{menuId}")
    public AjaxResult remove(@PathVariable("menuId") Long menuId)
    {
        if (menuService.hasChildByMenuId(menuId))
        {
            return warn("存在子菜单,不允许删除");
        }
        if (menuService.checkMenuExistRole(menuId))
        {
            return warn("菜单已分配,不允许删除");
        }
        return toAjax(menuService.deleteMenuById(menuId));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,150 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeReadService;
import com.ruoyi.system.service.ISysNoticeService;
/**
 * å…¬å‘Š ä¿¡æ¯æ“ä½œå¤„ç†
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController
{
    @Autowired
    private ISysNoticeService noticeService;
    @Autowired
    private ISysNoticeReadService noticeReadService;
    /**
     * èŽ·å–é€šçŸ¥å…¬å‘Šåˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysNotice notice)
    {
        startPage();
        List<SysNotice> list = noticeService.selectNoticeList(notice);
        return getDataTable(list);
    }
    /**
     * æ ¹æ®é€šçŸ¥å…¬å‘Šç¼–号获取详细信息
     */
    @GetMapping(value = "/{noticeId}")
    public AjaxResult getInfo(@PathVariable Long noticeId)
    {
        return success(noticeService.selectNoticeById(noticeId));
    }
    /**
     * æ–°å¢žé€šçŸ¥å…¬å‘Š
     */
    @PreAuthorize("@ss.hasPermi('system:notice:add')")
    @Log(title = "通知公告", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysNotice notice)
    {
        notice.setCreateBy(getUsername());
        return toAjax(noticeService.insertNotice(notice));
    }
    /**
     * ä¿®æ”¹é€šçŸ¥å…¬å‘Š
     */
    @PreAuthorize("@ss.hasPermi('system:notice:edit')")
    @Log(title = "通知公告", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysNotice notice)
    {
        notice.setUpdateBy(getUsername());
        return toAjax(noticeService.updateNotice(notice));
    }
    /**
     * é¦–页顶部公告列表(返回全部正常公告,带当前用户已读标记,最多5条)
     */
    @GetMapping("/listTop")
    @ResponseBody
    public AjaxResult listTop()
    {
        Long userId = getUserId();
        List<SysNotice> list = noticeReadService.selectNoticeListWithReadStatus(userId, 5);
        long unreadCount = list.stream().filter(n -> !n.getIsRead()).count();
        AjaxResult result = AjaxResult.success(list);
        result.put("unreadCount", unreadCount);
        return result;
    }
    /**
     * æ ‡è®°å…¬å‘Šå·²è¯»
     */
    @PostMapping("/markRead")
    @ResponseBody
    public AjaxResult markRead(Long noticeId)
    {
        Long userId = getUserId();
        noticeReadService.markRead(noticeId, userId);
        return success();
    }
    /**
     * æ‰¹é‡æ ‡è®°å·²è¯»
     */
    @PostMapping("/markReadAll")
    @ResponseBody
    public AjaxResult markReadAll(String ids)
    {
        Long userId = getUserId();
        Long[] noticeIds = Convert.toLongArray(ids);
        noticeReadService.markReadBatch(userId, noticeIds);
        return success();
    }
    /**
     * å·²è¯»ç”¨æˆ·åˆ—表数据
     */
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
    @GetMapping("/readUsers/list")
    @ResponseBody
    public TableDataInfo readUsersList(Long noticeId, String searchValue)
    {
        startPage();
        List<?> list = noticeReadService.selectReadUsersByNoticeId(noticeId, searchValue);
        return getDataTable(list);
    }
    /**
     * åˆ é™¤é€šçŸ¥å…¬å‘Š
     */
    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/{noticeIds}")
    public AjaxResult remove(@PathVariable Long[] noticeIds)
    {
        noticeReadService.deleteByNoticeIds(noticeIds);
        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,129 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.domain.SysPost;
import com.ruoyi.system.service.ISysPostService;
/**
 * å²—位信息操作处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/post")
public class SysPostController extends BaseController
{
    @Autowired
    private ISysPostService postService;
    /**
     * èŽ·å–å²—ä½åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:post:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysPost post)
    {
        startPage();
        List<SysPost> list = postService.selectPostList(post);
        return getDataTable(list);
    }
    @Log(title = "岗位管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:post:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysPost post)
    {
        List<SysPost> list = postService.selectPostList(post);
        ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
        util.exportExcel(response, list, "岗位数据");
    }
    /**
     * æ ¹æ®å²—位编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:post:query')")
    @GetMapping(value = "/{postId}")
    public AjaxResult getInfo(@PathVariable Long postId)
    {
        return success(postService.selectPostById(postId));
    }
    /**
     * æ–°å¢žå²—位
     */
    @PreAuthorize("@ss.hasPermi('system:post:add')")
    @Log(title = "岗位管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysPost post)
    {
        if (!postService.checkPostNameUnique(post))
        {
            return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
        }
        else if (!postService.checkPostCodeUnique(post))
        {
            return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
        }
        post.setCreateBy(getUsername());
        return toAjax(postService.insertPost(post));
    }
    /**
     * ä¿®æ”¹å²—位
     */
    @PreAuthorize("@ss.hasPermi('system:post:edit')")
    @Log(title = "岗位管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysPost post)
    {
        if (!postService.checkPostNameUnique(post))
        {
            return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
        }
        else if (!postService.checkPostCodeUnique(post))
        {
            return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
        }
        post.setUpdateBy(getUsername());
        return toAjax(postService.updatePost(post));
    }
    /**
     * åˆ é™¤å²—位
     */
    @PreAuthorize("@ss.hasPermi('system:post:remove')")
    @Log(title = "岗位管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{postIds}")
    public AjaxResult remove(@PathVariable Long[] postIds)
    {
        return toAjax(postService.deletePostByIds(postIds));
    }
    /**
     * èŽ·å–å²—ä½é€‰æ‹©æ¡†åˆ—è¡¨
     */
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        List<SysPost> posts = postService.selectPostAll();
        return success(posts);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,149 @@
package com.ruoyi.web.controller.system;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
/**
 * ä¸ªäººä¿¡æ¯ ä¸šåŠ¡å¤„ç†
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user/profile")
public class SysProfileController extends BaseController
{
    @Autowired
    private ISysUserService userService;
    @Autowired
    private TokenService tokenService;
    /**
     * ä¸ªäººä¿¡æ¯
     */
    @GetMapping
    public AjaxResult profile()
    {
        LoginUser loginUser = getLoginUser();
        SysUser user = loginUser.getUser();
        AjaxResult ajax = AjaxResult.success(user);
        ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
        ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
        return ajax;
    }
    /**
     * ä¿®æ”¹ç”¨æˆ·
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult updateProfile(@RequestBody SysUser user)
    {
        LoginUser loginUser = getLoginUser();
        SysUser currentUser = loginUser.getUser();
        currentUser.setNickName(user.getNickName());
        currentUser.setEmail(user.getEmail());
        currentUser.setPhonenumber(user.getPhonenumber());
        currentUser.setSex(user.getSex());
        if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
        {
            return error("修改用户'" + loginUser.getUsername() + "'失败,手机号码已存在");
        }
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
        {
            return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
        }
        if (userService.updateUserProfile(currentUser) > 0)
        {
            // æ›´æ–°ç¼“存用户信息
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改个人信息异常,请联系管理员");
    }
    /**
     * é‡ç½®å¯†ç 
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/updatePwd")
    public AjaxResult updatePwd(@RequestBody Map<String, String> params)
    {
        String oldPassword = params.get("oldPassword");
        String newPassword = params.get("newPassword");
        LoginUser loginUser = getLoginUser();
        Long userId = loginUser.getUserId();
        SysUser user = userService.selectUserById(userId);
        String password = user.getPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password))
        {
            return error("修改密码失败,旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password))
        {
            return error("新密码不能与旧密码相同");
        }
        newPassword = SecurityUtils.encryptPassword(newPassword);
        if (userService.resetUserPwd(userId, newPassword) > 0)
        {
            // æ›´æ–°ç¼“存用户密码&密码最后更新时间
            loginUser.getUser().setPwdUpdateDate(DateUtils.getNowDate());
            loginUser.getUser().setPassword(newPassword);
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改密码异常,请联系管理员");
    }
    /**
     * å¤´åƒä¸Šä¼ 
     */
    @Log(title = "用户头像", businessType = BusinessType.UPDATE)
    @PostMapping("/avatar")
    public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
    {
        if (!file.isEmpty())
        {
            LoginUser loginUser = getLoginUser();
            String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION, true);
            if (userService.updateUserAvatar(loginUser.getUserId(), avatar))
            {
                String oldAvatar = loginUser.getUser().getAvatar();
                if (StringUtils.isNotEmpty(oldAvatar))
                {
                    FileUtils.deleteFile(RuoYiConfig.getProfile() + FileUtils.stripPrefix(oldAvatar));
                }
                AjaxResult ajax = AjaxResult.success();
                ajax.put("imgUrl", avatar);
                // æ›´æ–°ç¼“存用户头像
                loginUser.getUser().setAvatar(avatar);
                tokenService.setLoginUser(loginUser);
                return ajax;
            }
        }
        return error("上传图片异常,请联系管理员");
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysRegisterService;
import com.ruoyi.system.service.ISysConfigService;
/**
 * æ³¨å†ŒéªŒè¯
 *
 * @author ruoyi
 */
@RestController
public class SysRegisterController extends BaseController
{
    @Autowired
    private SysRegisterService registerService;
    @Autowired
    private ISysConfigService configService;
    @PostMapping("/register")
    public AjaxResult register(@RequestBody RegisterBody user)
    {
        if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
        {
            return error("当前系统没有开启注册功能!");
        }
        String msg = registerService.register(user);
        return StringUtils.isEmpty(msg) ? success() : error(msg);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,254 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
 * è§’色信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/role")
public class SysRoleController extends BaseController
{
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysDeptService deptService;
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysRole role)
    {
        startPage();
        List<SysRole> list = roleService.selectRoleList(role);
        return getDataTable(list);
    }
    @Log(title = "角色管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:role:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysRole role)
    {
        List<SysRole> list = roleService.selectRoleList(role);
        ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
        util.exportExcel(response, list, "角色数据");
    }
    /**
     * æ ¹æ®è§’色编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping(value = "/{roleId}")
    public AjaxResult getInfo(@PathVariable Long roleId)
    {
        roleService.checkRoleDataScope(roleId);
        return success(roleService.selectRoleById(roleId));
    }
    /**
     * æ–°å¢žè§’色
     */
    @PreAuthorize("@ss.hasPermi('system:role:add')")
    @Log(title = "角色管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysRole role)
    {
        if (!roleService.checkRoleNameUnique(role))
        {
            return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
        }
        else if (!roleService.checkRoleKeyUnique(role))
        {
            return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
        }
        role.setCreateBy(getUsername());
        return toAjax(roleService.insertRole(role));
    }
    /**
     * ä¿®æ”¹ä¿å­˜è§’色
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysRole role)
    {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        if (!roleService.checkRoleNameUnique(role))
        {
            return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
        }
        else if (!roleService.checkRoleKeyUnique(role))
        {
            return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
        }
        role.setUpdateBy(getUsername());
        if (roleService.updateRole(role) > 0)
        {
            // åˆ·æ–°æ‰€æœ‰æŒæœ‰è¯¥è§’色的在线用户权限
            tokenService.refreshPermissionByRoleId(role.getRoleId(), permissionService);
            return success();
        }
        return error("修改角色'" + role.getRoleName() + "'失败,请联系管理员");
    }
    /**
     * ä¿®æ”¹ä¿å­˜æ•°æ®æƒé™
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping("/dataScope")
    public AjaxResult dataScope(@RequestBody SysRole role)
    {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        return toAjax(roleService.authDataScope(role));
    }
    /**
     * çŠ¶æ€ä¿®æ”¹
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysRole role)
    {
        roleService.checkRoleAllowed(role);
        roleService.checkRoleDataScope(role.getRoleId());
        role.setUpdateBy(getUsername());
        return toAjax(roleService.updateRoleStatus(role));
    }
    /**
     * åˆ é™¤è§’色
     */
    @PreAuthorize("@ss.hasPermi('system:role:remove')")
    @Log(title = "角色管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{roleIds}")
    public AjaxResult remove(@PathVariable Long[] roleIds)
    {
        return toAjax(roleService.deleteRoleByIds(roleIds));
    }
    /**
     * èŽ·å–è§’è‰²é€‰æ‹©æ¡†åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        return success(roleService.selectRoleAll());
    }
    /**
     * æŸ¥è¯¢å·²åˆ†é…ç”¨æˆ·è§’色列表
     */
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/allocatedList")
    public TableDataInfo allocatedList(SysUser user)
    {
        startPage();
        List<SysUser> list = userService.selectAllocatedList(user);
        return getDataTable(list);
    }
    /**
     * æŸ¥è¯¢æœªåˆ†é…ç”¨æˆ·è§’色列表
     */
    @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/unallocatedList")
    public TableDataInfo unallocatedList(SysUser user)
    {
        startPage();
        List<SysUser> list = userService.selectUnallocatedList(user);
        return getDataTable(list);
    }
    /**
     * å–消授权用户
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancel")
    public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
    {
        return toAjax(roleService.deleteAuthUser(userRole));
    }
    /**
     * æ‰¹é‡å–消授权用户
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancelAll")
    public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
    {
        return toAjax(roleService.deleteAuthUsers(roleId, userIds));
    }
    /**
     * æ‰¹é‡é€‰æ‹©ç”¨æˆ·æŽˆæƒ
     */
    @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/selectAll")
    public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
    {
        roleService.checkRoleDataScope(roleId);
        return toAjax(roleService.insertAuthUsers(roleId, userIds));
    }
    /**
     * èŽ·å–å¯¹åº”è§’è‰²éƒ¨é—¨æ ‘åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping(value = "/deptTree/{roleId}")
    public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
    {
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
        ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
        return ajax;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,256 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
/**
 * ç”¨æˆ·ä¿¡æ¯
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private ISysPostService postService;
    /**
     * èŽ·å–ç”¨æˆ·åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUser user)
    {
        startPage();
        List<SysUser> list = userService.selectUserList(user);
        return getDataTable(list);
    }
    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysUser user)
    {
        List<SysUser> list = userService.selectUserList(user);
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.exportExcel(response, list, "用户数据");
    }
    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        List<SysUser> userList = util.importExcel(file.getInputStream());
        String operName = getUsername();
        String message = userService.importUser(userList, updateSupport, operName);
        return success(message);
    }
    @PostMapping("/importTemplate")
    public void importTemplate(HttpServletResponse response)
    {
        ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
        util.importTemplateExcel(response, "用户数据");
    }
    /**
     * æ ¹æ®ç”¨æˆ·ç¼–号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = { "/", "/{userId}" })
    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
    {
        AjaxResult ajax = AjaxResult.success();
        if (StringUtils.isNotNull(userId))
        {
            userService.checkUserDataScope(userId);
            SysUser sysUser = userService.selectUserById(userId);
            ajax.put(AjaxResult.DATA_TAG, sysUser);
            ajax.put("postIds", postService.selectPostListByUserId(userId));
            ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
        }
        List<SysRole> roles = roleService.selectRoleAll();
        ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        ajax.put("posts", postService.selectPostAll());
        return ajax;
    }
    /**
     * æ–°å¢žç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysUser user)
    {
        deptService.checkDeptDataScope(user.getDeptId());
        roleService.checkRoleDataScope(user.getRoleIds());
        if (!userService.checkUserNameUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return toAjax(userService.insertUser(user));
    }
    /**
     * ä¿®æ”¹ç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        deptService.checkDeptDataScope(user.getDeptId());
        roleService.checkRoleDataScope(user.getRoleIds());
        if (!userService.checkUserNameUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUser(user));
    }
    /**
     * åˆ é™¤ç”¨æˆ·
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    public AjaxResult remove(@PathVariable Long[] userIds)
    {
        if (ArrayUtils.contains(userIds, getUserId()))
        {
            return error("当前用户不能删除");
        }
        return toAjax(userService.deleteUserByIds(userIds));
    }
    /**
     * é‡ç½®å¯†ç 
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return toAjax(userService.resetPwd(user));
    }
    /**
     * çŠ¶æ€ä¿®æ”¹
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
        userService.checkUserDataScope(user.getUserId());
        user.setUpdateBy(getUsername());
        return toAjax(userService.updateUserStatus(user));
    }
    /**
     * æ ¹æ®ç”¨æˆ·ç¼–号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId)
    {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SecurityUtils.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }
    /**
     * ç”¨æˆ·æŽˆæƒè§’色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
    {
        userService.checkUserDataScope(userId);
        roleService.checkRoleDataScope(roleIds);
        userService.insertUserAuth(userId, roleIds);
        return success();
    }
    /**
     * èŽ·å–éƒ¨é—¨æ ‘åˆ—è¡¨
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept)
    {
        return success(deptService.selectDeptTreeList(dept));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,175 @@
package com.ruoyi.web.controller.tool;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
/**
 * swagger ç”¨æˆ·æµ‹è¯•方法
 *
 * @author ruoyi
 */
@Tag(name = "用户信息管理")
@RestController
@RequestMapping("/test/user")
public class TestController extends BaseController
{
    private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
    {
        users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
        users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
    }
    @Operation(summary = "获取用户列表")
    @GetMapping("/list")
    public R<List<UserEntity>> userList()
    {
        List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
        return R.ok(userList);
    }
    @Operation(summary = "获取用户详细")
    @GetMapping("/{userId}")
    public R<UserEntity> getUser(@PathVariable(name = "userId")
    Integer userId)
    {
        if (!users.isEmpty() && users.containsKey(userId))
        {
            return R.ok(users.get(userId));
        }
        else
        {
            return R.fail("用户不存在");
        }
    }
    @Operation(summary = "新增用户")
    @PostMapping("/save")
    public R<String> save(UserEntity user)
    {
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
        {
            return R.fail("用户ID不能为空");
        }
        users.put(user.getUserId(), user);
        return R.ok();
    }
    @Operation(summary = "更新用户")
    @PutMapping("/update")
    public R<String> update(@RequestBody
    UserEntity user)
    {
        if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
        {
            return R.fail("用户ID不能为空");
        }
        if (users.isEmpty() || !users.containsKey(user.getUserId()))
        {
            return R.fail("用户不存在");
        }
        users.remove(user.getUserId());
        users.put(user.getUserId(), user);
        return R.ok();
    }
    @Operation(summary = "删除用户信息")
    @DeleteMapping("/{userId}")
    public R<String> delete(@PathVariable(name = "userId")
    Integer userId)
    {
        if (!users.isEmpty() && users.containsKey(userId))
        {
            users.remove(userId);
            return R.ok();
        }
        else
        {
            return R.fail("用户不存在");
        }
    }
}
@Schema(description = "用户实体")
class UserEntity
{
    @Schema(title = "用户ID")
    private Integer userId;
    @Schema(title = "用户名称")
    private String username;
    @Schema(title = "用户密码")
    private String password;
    @Schema(title = "用户手机")
    private String mobile;
    public UserEntity()
    {
    }
    public UserEntity(Integer userId, String username, String password, String mobile)
    {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.mobile = mobile;
    }
    public Integer getUserId()
    {
        return userId;
    }
    public void setUserId(Integer userId)
    {
        this.userId = userId;
    }
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getMobile()
    {
        return mobile;
    }
    public void setMobile(String mobile)
    {
        this.mobile = mobile;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,64 @@
package com.ruoyi.web.core.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
/**
 * Swagger2的接口配置
 *
 * @author ruoyi
 */
@Configuration
public class SwaggerConfig
{
    /** ç³»ç»ŸåŸºç¡€é…ç½® */
    @Autowired
    private RuoYiConfig ruoyiConfig;
    /**
     * è‡ªå®šä¹‰çš„ OpenAPI å¯¹è±¡
     */
    @Bean
    public OpenAPI customOpenApi()
    {
        return new OpenAPI().components(new Components()
            // è®¾ç½®è®¤è¯çš„请求头
            .addSecuritySchemes("apikey", securityScheme()))
            .addSecurityItem(new SecurityRequirement().addList("apikey"))
            .info(getApiInfo());
    }
    @Bean
    public SecurityScheme securityScheme()
    {
        return new SecurityScheme()
            .type(SecurityScheme.Type.APIKEY)
            .name("Authorization")
            .in(SecurityScheme.In.HEADER)
            .scheme("Bearer");
    }
    /**
     * æ·»åŠ æ‘˜è¦ä¿¡æ¯
     */
    public Info getApiInfo()
    {
        return new Info()
            // è®¾ç½®æ ‡é¢˜
            .title("标题:产教融合实践教学管理平台_接口文档")
            // æè¿°
            .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
            // ä½œè€…信息
            .contact(new Contact().name(ruoyiConfig.getName()))
            // ç‰ˆæœ¬
            .version("版本号:" + ruoyiConfig.getVersion());
    }
}
ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties
ruoyi-admin/src/main/resources/application-dev.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
# å¼€å‘环境配置
spring:
  data:
    # redis é…ç½®ï¼ˆå¼€å‘环境)
    redis:
      host: 192.168.197.128
      port: 6379
      password: sugaozhixing.cn
      database: 0
      timeout: 10s
      lettuce:
        pool:
          min-idle: 0
          max-idle: 8
          max-active: 8
          max-wait: -1ms
# æ—¥å¿—级别(开发环境)
logging:
  level:
    com.ruoyi: debug
    org.springframework: warn
# æ–‡ä»¶ä¸Šä¼ è·¯å¾„(开发环境 Windows)
ruoyi:
  profile: D:/ruoyi/uploadPath
  addressEnabled: false
ruoyi-admin/src/main/resources/application-druid.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
# æ•°æ®æºé…ç½®
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # ä¸»åº“数据源
            master:
                url: jdbc:mysql://192.168.197.128:3306/cj_practice?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
                username: root
                password: sugaozhixing.cn
            # ä»Žåº“数据源
            slave:
                # ä»Žæ•°æ®æºå¼€å…³/默认关闭
                enabled: false
                url:
                username:
                password:
            # åˆå§‹è¿žæŽ¥æ•°
            initialSize: 5
            # æœ€å°è¿žæŽ¥æ± æ•°é‡
            minIdle: 10
            # æœ€å¤§è¿žæŽ¥æ± æ•°é‡
            maxActive: 20
            # é…ç½®èŽ·å–è¿žæŽ¥ç­‰å¾…è¶…æ—¶çš„æ—¶é—´
            maxWait: 60000
            # é…ç½®è¿žæŽ¥è¶…æ—¶æ—¶é—´
            connectTimeout: 30000
            # é…ç½®ç½‘络超时时间
            socketTimeout: 60000
            # é…ç½®é—´éš”多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å°ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
            minEvictableIdleTimeMillis: 300000
            # é…ç½®ä¸€ä¸ªè¿žæŽ¥åœ¨æ± ä¸­æœ€å¤§ç”Ÿå­˜çš„æ—¶é—´ï¼Œå•位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # é…ç½®æ£€æµ‹è¿žæŽ¥æ˜¯å¦æœ‰æ•ˆ
            validationQuery: SELECT 1 FROM DUAL
            testWhileIdle: true
            testOnBorrow: false
            testOnReturn: false
            webStatFilter:
                enabled: true
            statViewServlet:
                enabled: true
                # è®¾ç½®ç™½åå•,不填则允许所有访问
                allow:
                url-pattern: /druid/*
                # æŽ§åˆ¶å°ç®¡ç†ç”¨æˆ·åå’Œå¯†ç 
                login-username: ruoyi
                login-password: 123456
            filter:
                stat:
                    enabled: true
                    # æ…¢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        multi-statement-allow: true
ruoyi-admin/src/main/resources/application-prod.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
# ç”Ÿäº§çŽ¯å¢ƒé…ç½®
spring:
  data:
    # redis é…ç½®ï¼ˆç”Ÿäº§çŽ¯å¢ƒï¼‰
    redis:
      host: 192.168.197.128
      port: 6379
      password: sugaozhixing.cn
      database: 0
      timeout: 10s
      lettuce:
        pool:
          min-idle: 5
          max-idle: 20
          max-active: 50
          max-wait: 3000ms
# æ—¥å¿—级别(生产环境 - åªè¾“出警告和错误)
logging:
  level:
    com.ruoyi: warn
    org.springframework: error
# æ–‡ä»¶ä¸Šä¼ è·¯å¾„(生产环境 Linux)
ruoyi:
  profile: /home/ruoyi/uploadPath
  addressEnabled: true
ruoyi-admin/src/main/resources/application.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,155 @@
# é¡¹ç›®ç›¸å…³é…ç½®
ruoyi:
  # åç§°
  name: äº§æ•™èžåˆå®žè·µæ•™å­¦ç®¡ç†å¹³å°
  # ç‰ˆæœ¬
  version: 3.9.2
  # ç‰ˆæƒå¹´ä»½
  copyrightYear: 2026
  # æ–‡ä»¶è·¯å¾„ ç¤ºä¾‹ï¼ˆ Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # èŽ·å–ip地址开关
  addressEnabled: false
  # éªŒè¯ç ç±»åž‹ math æ•°å­—计算 char å­—符验证(生产环境建议 char é˜² OCR)
  captchaType: char
# å¾®ä¿¡å°ç¨‹åºé…ç½®ï¼ˆç”Ÿäº§çŽ¯å¢ƒåŠ¡å¿…é€šè¿‡çŽ¯å¢ƒå˜é‡è¦†ç›– secret,勿明文入库/提交)
wechat:
  # å°ç¨‹åº AppID
  appid: wxc52c6347b57afd4b
  # å°ç¨‹åº AppSecret(敏感!生产请用环境变量 ${WECHAT_SECRET} è¦†ç›–)
  secret: 296c838c39e75521c4f6d2e293178c7a
# å¼€å‘环境配置
server:
  # æœåŠ¡å™¨çš„HTTP端口,默认为8080
  port: 18080
  servlet:
    # åº”用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # è¿žæŽ¥æ•°æ»¡åŽçš„æŽ’队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100
# æ—¥å¿—配置
logging:
  level:
    com.ruoyi: debug
    org.springframework: warn
# ç”¨æˆ·é…ç½®
user:
  password:
    # å¯†ç æœ€å¤§é”™è¯¯æ¬¡æ•°
    maxRetryCount: 5
    # å¯†ç é”å®šæ—¶é—´ï¼ˆé»˜è®¤10分钟)
    lockTime: 10
# Spring配置
spring:
  # èµ„源信息
  messages:
    # å›½é™…化资源文件路径
    basename: i18n/messages
  profiles:
    active: dev,druid
  # æ–‡ä»¶ä¸Šä¼ 
  servlet:
    multipart:
      # å•个文件大小
      max-file-size: 10MB
      # è®¾ç½®æ€»ä¸Šä¼ çš„æ–‡ä»¶å¤§å°
      max-request-size: 20MB
  jackson:
    time-zone: GMT+8
    date-format: yyyy-MM-dd HH:mm:ss
  # æœåŠ¡æ¨¡å—
  devtools:
    restart:
      # çƒ­éƒ¨ç½²å¼€å…³
      enabled: true
  data:
    # redis é…ç½®
    redis:
      # åœ°å€
      host: 192.168.197.128
      # ç«¯å£ï¼Œé»˜è®¤ä¸º6379
      port: 6379
      # æ•°æ®åº“索引
      database: 0
      # å¯†ç 
      password: sugaozhixing.cn
      # è¿žæŽ¥è¶…æ—¶æ—¶é—´
      timeout: 10s
      lettuce:
        pool:
          # è¿žæŽ¥æ± ä¸­çš„æœ€å°ç©ºé—²è¿žæŽ¥
          min-idle: 0
          # è¿žæŽ¥æ± ä¸­çš„æœ€å¤§ç©ºé—²è¿žæŽ¥
          max-idle: 8
          # è¿žæŽ¥æ± çš„æœ€å¤§æ•°æ®åº“连接数
          max-active: 8
          # #连接池最大阻塞等待时间(使用负值表示没有限制)
          max-wait: -1ms
# token配置
token:
  # ä»¤ç‰Œè‡ªå®šä¹‰æ ‡è¯†
  header: Authorization
  # ä»¤ç‰Œå¯†é’¥ï¼ˆç”Ÿäº§çº§éšæœºå¯†é’¥ï¼Œå‹¿æ³„露)
  secret: 8Bz5rjBVpqaWsowwvo70YwL441TEnXxi0FmxQ0AhaA763OCh+XjvBnertoTA3MGRcDmstBgzBLEf2z4OW3Cq6w==
  # ä»¤ç‰Œæœ‰æ•ˆæœŸï¼ˆé»˜è®¤30分钟)
  expireTime: 30
# MyBatis配置
mybatis:
  # æœç´¢æŒ‡å®šåŒ…别名
  typeAliasesPackage: com.ruoyi.**.domain
  # é…ç½®mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # åŠ è½½å…¨å±€çš„é…ç½®æ–‡ä»¶
  configLocation: classpath:mybatis/mybatis-config.xml
# PageHelper分页插件
pagehelper:
  helperDialect: mysql
  supportMethodsArguments: true
  params: count=countSql
# Springdoc配置
springdoc:
  api-docs:
    path: /v3/api-docs
  swagger-ui:
    enabled: true
    path: /swagger-ui.html
    tags-sorter: alpha
  group-configs:
    - group: 'default'
      display-name: '测试模块'
      paths-to-match: '/**'
      packages-to-scan: com.ruoyi.web.controller.tool
# é˜²ç›—链配置
referer:
  # é˜²ç›—链开关
  enabled: false
  # å…è®¸çš„域名列表
  allowed-domains: localhost,127.0.0.1,ruoyi.vip,www.ruoyi.vip
# é˜²æ­¢XSS攻击
xss:
  # è¿‡æ»¤å¼€å…³
  enabled: true
  # æŽ’除链接(多个用逗号分隔)
  excludes: /system/notice
  # åŒ¹é…é“¾æŽ¥
  urlPatterns: /system/*,/monitor/*,/tool/*
ruoyi-admin/src/main/resources/banner.txt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
Application Version: ${ruoyi.version}
Spring Boot Version: ${spring-boot.version}
////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O\  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \\|     |//  `.                         //
//                   /  \\|||  :  |||//  \                        //
//                  /  _||||| -:- |||||-  \                       //
//                  |   | \\\  -  /// |   |                       //
//                  | \_|  ''\---/''  |   |                       //
//                  \  .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--\  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//             ä½›ç¥–保佑       æ°¸ä¸å®•机      æ°¸æ— BUG               //
////////////////////////////////////////////////////////////////////
ruoyi-admin/src/main/resources/i18n/messages.properties
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
#错误消息
not.null=* å¿…须填写
user.jcaptcha.error=验证码错误
user.jcaptcha.expire=验证码已失效
user.not.exists=用户不存在/密码错误
user.password.not.match=用户不存在/密码错误
user.password.retry.limit.count=密码输入错误{0}次
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
user.password.delete=对不起,您的账号已被删除
user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员
login.blocked=很遗憾,访问IP已被列入系统黑名单
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间
user.username.not.valid=* 2到20个汉字、字母、数字或下划线组成,且必须以非数字开头
user.password.not.valid=* 5-50个字符
user.email.not.valid=邮箱格式错误
user.mobile.phone.number.not.valid=手机号格式错误
user.login.success=登录成功
user.register.success=注册成功
user.notfound=请重新登录
user.forcelogout=管理员强制退出,请重新登录
user.unknown.error=未知错误,请重新登录
##文件上传消息
upload.exceed.maxSize=上传的文件大小超出限制的文件大小!<br/>允许的文件最大大小是:{0}MB!
upload.filename.exceed.length=上传的文件名最长{0}个字符
##权限
no.permission=您没有数据的权限,请联系管理员添加权限 [{0}]
no.create.permission=您没有创建数据的权限,请联系管理员添加权限 [{0}]
no.update.permission=您没有修改数据的权限,请联系管理员添加权限 [{0}]
no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}]
no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}]
no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}]
ruoyi-admin/src/main/resources/logback.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- æ—¥å¿—存放路径 -->
    <property name="log.path" value="/home/ruoyi/logs" />
    <!-- æ—¥å¿—输出格式 -->
    <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
    <!-- æŽ§åˆ¶å°è¾“出 -->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </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>
    <!-- ç”¨æˆ·è®¿é—®æ—¥å¿—输出  -->
    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/sys-user.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- æŒ‰å¤©å›žæ»š daily -->
            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- æ—¥å¿—最大的历史 60天 -->
            <maxHistory>60</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>${log.pattern}</pattern>
        </encoder>
    </appender>
    <!-- ç³»ç»Ÿæ¨¡å—日志级别控制  -->
    <logger name="com.ruoyi" level="info" />
    <!-- Spring日志级别控制  -->
    <logger name="org.springframework" level="warn" />
    <root level="info">
        <appender-ref ref="console" />
    </root>
    <!--系统操作日志-->
    <root level="info">
        <appender-ref ref="file_info" />
        <appender-ref ref="file_error" />
    </root>
    <!--系统用户操作日志-->
    <logger name="sys-user" level="info">
        <appender-ref ref="sys-user"/>
    </logger>
</configuration>
ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- å…¨å±€å‚æ•° -->
    <settings>
        <!-- ä½¿å…¨å±€çš„æ˜ å°„器启用或禁用缓存 -->
        <setting name="cacheEnabled"             value="true"   />
        <!-- å…è®¸JDBC æ”¯æŒè‡ªåŠ¨ç”Ÿæˆä¸»é”® -->
        <setting name="useGeneratedKeys"         value="true"   />
        <!-- é…ç½®é»˜è®¤çš„æ‰§è¡Œå™¨.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
        <setting name="defaultExecutorType"      value="SIMPLE" />
        <!-- æŒ‡å®š MyBatis æ‰€ç”¨æ—¥å¿—的具体实现 -->
        <setting name="logImpl"                  value="SLF4J"  />
        <!-- ä½¿ç”¨é©¼å³°å‘½åæ³•转换字段 -->
        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
    </settings>
</configuration>
ruoyi-common/pom.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,123 @@
<?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>ruoyi</artifactId>
        <groupId>com.ruoyi</groupId>
        <version>3.9.2</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>ruoyi-common</artifactId>
    <description>
        common通用工具
    </description>
    <dependencies>
        <!-- Spring框架基本的核心工具 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- SpringWeb模块 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <!-- spring security å®‰å…¨è®¤è¯ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- pagehelper åˆ†é¡µæ’ä»¶ -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>
        <!-- è‡ªå®šä¹‰éªŒè¯æ³¨è§£ -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!--常用工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!-- JSON工具类 -->
        <dependency>
            <groupId>tools.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <!-- é˜¿é‡ŒJSON解析器 -->
        <dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
        </dependency>
        <!-- io常用工具类 -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </dependency>
        <!-- excel工具 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>
        <!-- Token生成与解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <!-- Jaxb -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <!-- redis ç¼“存操作 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- pool å¯¹è±¡æ±  -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- è§£æžå®¢æˆ·ç«¯æ“ä½œç³»ç»Ÿã€æµè§ˆå™¨ç­‰ -->
        <dependency>
            <groupId>nl.basjes.parse.useragent</groupId>
            <artifactId>yauaa</artifactId>
        </dependency>
        <!-- servlet包 -->
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
        </dependency>
    </dependencies>
</project>
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * åŒ¿åè®¿é—®ä¸é‰´æƒæ³¨è§£
 *
 * @author ruoyi
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Anonymous
{
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * æ•°æ®æƒé™è¿‡æ»¤æ³¨è§£
 *
 * @author ruoyi
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataScope
{
    /**
     * ç”¨æˆ·è¡¨çš„别名
     */
    public String userAlias() default "";
    /**
     * éƒ¨é—¨è¡¨çš„别名
     */
    public String deptAlias() default "";
    /**
     * ç”¨æˆ·å­—段名
     */
    public String userField() default "user_id";
    /**
     * éƒ¨é—¨å­—段名
     */
    public String deptField() default "dept_id";
    /**
     * æƒé™å­—符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
     */
    public String permission() default "";
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ruoyi.common.enums.DataSourceType;
/**
 * è‡ªå®šä¹‰å¤šæ•°æ®æºåˆ‡æ¢æ³¨è§£
 *
 * ä¼˜å…ˆçº§ï¼šå…ˆæ–¹æ³•,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
 *
 * @author ruoyi
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
    /**
     * åˆ‡æ¢æ•°æ®æºåç§°
     */
    public DataSourceType value() default DataSourceType.MASTER;
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,198 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.math.BigDecimal;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
/**
 * è‡ªå®šä¹‰å¯¼å‡ºExcel数据注解
 *
 * @author ruoyi
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
    /**
     * å¯¼å‡ºæ—¶åœ¨excel中排序
     */
    public int sort() default Integer.MAX_VALUE;
    /**
     * å¯¼å‡ºåˆ°Excel中的名字.
     */
    public String name() default "";
    /**
     * æ—¥æœŸæ ¼å¼, å¦‚: yyyy-MM-dd
     */
    public String dateFormat() default "";
    /**
     * å¦‚果是字典类型,请设置字典的type值 (如: sys_user_sex)
     */
    public String dictType() default "";
    /**
     * è¯»å–内容转表达式 (如: 0=男,1=女,2=未知)
     */
    public String readConverterExp() default "";
    /**
     * åˆ†éš”符,读取字符串组内容
     */
    public String separator() default ",";
    /**
     * BigDecimal ç²¾åº¦ é»˜è®¤:-1(默认不开启BigDecimal格式化)
     */
    public int scale() default -1;
    /**
     * BigDecimal èˆå…¥è§„则 é»˜è®¤:BigDecimal.ROUND_HALF_EVEN
     */
    @SuppressWarnings("deprecation")
    public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
    /**
     * å¯¼å‡ºæ—¶åœ¨excel中每个列的高度
     */
    public double height() default 14;
    /**
     * å¯¼å‡ºæ—¶åœ¨excel中每个列的宽度
     */
    public double width() default 16;
    /**
     * æ–‡å­—后缀,如% 90 å˜æˆ90%
     */
    public String suffix() default "";
    /**
     * å½“值为空时,字段的默认值
     */
    public String defaultValue() default "";
    /**
     * æç¤ºä¿¡æ¯
     */
    public String prompt() default "";
    /**
     * æ˜¯å¦å…è®¸å†…容换行
     */
    public boolean wrapText() default false;
    /**
     * è®¾ç½®åªèƒ½é€‰æ‹©ä¸èƒ½è¾“入的列内容.
     */
    public String[] combo() default {};
    /**
     * æ˜¯å¦ä»Žå­—典读数据到combo,默认不读取,如读取需要设置dictType注解.
     */
    public boolean comboReadDict() default false;
    /**
     * æ˜¯å¦éœ€è¦çºµå‘合并单元格,应对需求:含有list集合单元格)
     */
    public boolean needMerge() default false;
    /**
     * æ˜¯å¦å¯¼å‡ºæ•°æ®,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
     */
    public boolean isExport() default true;
    /**
     * å¦ä¸€ä¸ªç±»ä¸­çš„属性名称,支持多级获取,以小数点隔开
     */
    public String targetAttr() default "";
    /**
     * æ˜¯å¦è‡ªåŠ¨ç»Ÿè®¡æ•°æ®,在最后追加一行统计数据总和
     */
    public boolean isStatistics() default false;
    /**
     * å¯¼å‡ºç±»åž‹ï¼ˆ0数字 1字符串 2图片)
     */
    public ColumnType cellType() default ColumnType.STRING;
    /**
     * å¯¼å‡ºåˆ—头背景颜色
     */
    public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
    /**
     * å¯¼å‡ºåˆ—头字体颜色
     */
    public IndexedColors headerColor() default IndexedColors.WHITE;
    /**
     * å¯¼å‡ºå•元格背景颜色
     */
    public IndexedColors backgroundColor() default IndexedColors.WHITE;
    /**
     * å¯¼å‡ºå•元格字体颜色
     */
    public IndexedColors color() default IndexedColors.BLACK;
    /**
     * å¯¼å‡ºå­—段对齐方式
     */
    public HorizontalAlignment align() default HorizontalAlignment.CENTER;
    /**
     * è‡ªå®šä¹‰æ•°æ®å¤„理器
     */
    public Class<?> handler() default ExcelHandlerAdapter.class;
    /**
     * è‡ªå®šä¹‰æ•°æ®å¤„理器参数
     */
    public String[] args() default {};
    /**
     * å­—段类型(0:导出导入;1:仅导出;2:仅导入)
     */
    Type type() default Type.ALL;
    public enum Type
    {
        ALL(0), EXPORT(1), IMPORT(2);
        private final int value;
        Type(int value)
        {
            this.value = value;
        }
        public int value()
        {
            return this.value;
        }
    }
    public enum ColumnType
    {
        NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
        private final int value;
        ColumnType(int value)
        {
            this.value = value;
        }
        public int value()
        {
            return this.value;
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * Excel注解集
 *
 * @author ruoyi
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Excels
{
    public Excel[] value();
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.OperatorType;
/**
 * è‡ªå®šä¹‰æ“ä½œæ—¥å¿—记录注解
 *
 * @author ruoyi
 *
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * æ¨¡å—
     */
    public String title() default "";
    /**
     * åŠŸèƒ½
     */
    public BusinessType businessType() default BusinessType.OTHER;
    /**
     * æ“ä½œäººç±»åˆ«
     */
    public OperatorType operatorType() default OperatorType.MANAGE;
    /**
     * æ˜¯å¦ä¿å­˜è¯·æ±‚的参数
     */
    public boolean isSaveRequestData() default true;
    /**
     * æ˜¯å¦ä¿å­˜å“åº”的参数
     */
    public boolean isSaveResponseData() default true;
    /**
     * æŽ’除指定的请求参数
     */
    public String[] excludeParamNames() default {};
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.enums.LimitType;
/**
 * é™æµæ³¨è§£
 *
 * @author ruoyi
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiter
{
    /**
     * é™æµkey
     */
    public String key() default CacheConstants.RATE_LIMIT_KEY;
    /**
     * é™æµæ—¶é—´,单位秒
     */
    public int time() default 60;
    /**
     * é™æµæ¬¡æ•°
     */
    public int count() default 100;
    /**
     * é™æµç±»åž‹
     */
    public LimitType limitType() default LimitType.DEFAULT;
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * è‡ªå®šä¹‰æ³¨è§£é˜²æ­¢è¡¨å•重复提交
 *
 * @author ruoyi
 *
 */
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatSubmit
{
    /**
     * é—´é𔿗¶é—´(ms),小于此时间视为重复提交
     */
    public int interval() default 5000;
    /**
     * æç¤ºæ¶ˆæ¯
     */
    public String message() default "不允许重复提交,请稍候再试";
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import tools.jackson.databind.annotation.JsonSerialize;
import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
import com.ruoyi.common.enums.DesensitizedType;
/**
 * æ•°æ®è„±æ•æ³¨è§£
 *
 * @author ruoyi
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD })
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive
{
    DesensitizedType desensitizedType();
}
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
package com.ruoyi.common.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * è¯»å–项目相关配置
 *
 * @author ruoyi
 */
@Component
@ConfigurationProperties(prefix = "ruoyi")
public class RuoYiConfig
{
    /** é¡¹ç›®åç§° */
    private String name;
    /** ç‰ˆæœ¬ */
    private String version;
    /** ç‰ˆæƒå¹´ä»½ */
    private String copyrightYear;
    /** ä¸Šä¼ è·¯å¾„ */
    private static String profile;
    /** èŽ·å–åœ°å€å¼€å…³ */
    private static boolean addressEnabled;
    /** éªŒè¯ç ç±»åž‹ */
    private static String captchaType;
    public String getName()
    {
        return name;
    }
    public void setName(String name)
    {
        this.name = name;
    }
    public String getVersion()
    {
        return version;
    }
    public void setVersion(String version)
    {
        this.version = version;
    }
    public String getCopyrightYear()
    {
        return copyrightYear;
    }
    public void setCopyrightYear(String copyrightYear)
    {
        this.copyrightYear = copyrightYear;
    }
    public static String getProfile()
    {
        return profile;
    }
    public void setProfile(String profile)
    {
        RuoYiConfig.profile = profile;
    }
    public static boolean isAddressEnabled()
    {
        return addressEnabled;
    }
    public void setAddressEnabled(boolean addressEnabled)
    {
        RuoYiConfig.addressEnabled = addressEnabled;
    }
    public static String getCaptchaType() {
        return captchaType;
    }
    public void setCaptchaType(String captchaType) {
        RuoYiConfig.captchaType = captchaType;
    }
    /**
     * èŽ·å–å¯¼å…¥ä¸Šä¼ è·¯å¾„
     */
    public static String getImportPath()
    {
        return getProfile() + "/import";
    }
    /**
     * èŽ·å–å¤´åƒä¸Šä¼ è·¯å¾„
     */
    public static String getAvatarPath()
    {
        return getProfile() + "/avatar";
    }
    /**
     * èŽ·å–ä¸‹è½½è·¯å¾„
     */
    public static String getDownloadPath()
    {
        return getProfile() + "/download/";
    }
    /**
     * èŽ·å–ä¸Šä¼ è·¯å¾„
     */
    public static String getUploadPath()
    {
        return getProfile() + "/upload";
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
package com.ruoyi.common.config.serializer;
import java.util.Objects;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.BeanProperty;
import tools.jackson.databind.DatabindException;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ValueSerializer;
import tools.jackson.databind.ser.std.StdSerializer;
import com.ruoyi.common.annotation.Sensitive;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.DesensitizedType;
import com.ruoyi.common.utils.SecurityUtils;
/**
 * æ•°æ®è„±æ•åºåˆ—化过滤
 *
 * @author ruoyi
 */
public class SensitiveJsonSerializer extends StdSerializer<String>
{
    private final DesensitizedType desensitizedType;
    public SensitiveJsonSerializer()
    {
        super(String.class);
        this.desensitizedType = null;
    }
    public SensitiveJsonSerializer(DesensitizedType desensitizedType)
    {
        super(String.class);
        this.desensitizedType = desensitizedType;
    }
    @Override
    public void serialize(String value, JsonGenerator gen, SerializationContext ctxt) throws JacksonException
    {
        if (desensitizedType != null && desensitization())
        {
            gen.writeString(desensitizedType.desensitizer().apply(value));
        }
        else
        {
            gen.writeString(value);
        }
    }
    @Override
    public ValueSerializer<?> createContextual(SerializationContext ctxt, BeanProperty property) throws DatabindException
    {
        Sensitive annotation = property.getAnnotation(Sensitive.class);
        if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
        {
            return new SensitiveJsonSerializer(annotation.desensitizedType());
        }
        return ctxt.findValueSerializer(property.getType());
    }
    /**
     * æ˜¯å¦éœ€è¦è„±æ•å¤„理
     */
    private boolean desensitization()
    {
        try
        {
            LoginUser securityUser = SecurityUtils.getLoginUser();
            // ç®¡ç†å‘˜ä¸è„±æ•
            return !securityUser.getUser().isAdmin();
        }
        catch (Exception e)
        {
            return true;
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,44 @@
package com.ruoyi.common.constant;
/**
 * ç¼“存的key å¸¸é‡
 *
 * @author ruoyi
 */
public class CacheConstants
{
    /**
     * ç™»å½•用户 redis key
     */
    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
    /**
     * éªŒè¯ç  redis key
     */
    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
    /**
     * å‚数管理 cache key
     */
    public static final String SYS_CONFIG_KEY = "sys_config:";
    /**
     * å­—典管理 cache key
     */
    public static final String SYS_DICT_KEY = "sys_dict:";
    /**
     * é˜²é‡æäº¤ redis key
     */
    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
    /**
     * é™æµ redis key
     */
    public static final String RATE_LIMIT_KEY = "rate_limit:";
    /**
     * ç™»å½•账户密码错误次数 redis key
     */
    public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,204 @@
package com.ruoyi.common.constant;
import java.util.Locale;
import io.jsonwebtoken.Claims;
/**
 * é€šç”¨å¸¸é‡ä¿¡æ¯
 *
 * @author ruoyi
 */
public class Constants
{
    /**
     * UTF-8 å­—符集
     */
    public static final String UTF8 = "UTF-8";
    /**
     * GBK å­—符集
     */
    public static final String GBK = "GBK";
    /**
     * ç³»ç»Ÿè¯­è¨€
     */
    public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
    /**
     * www主域
     */
    public static final String WWW = "www.";
    /**
     * http请求
     */
    public static final String HTTP = "http://";
    /**
     * https请求
     */
    public static final String HTTPS = "https://";
    /**
     * é€šç”¨æˆåŠŸæ ‡è¯†
     */
    public static final String SUCCESS = "0";
    /**
     * é€šç”¨å¤±è´¥æ ‡è¯†
     */
    public static final String FAIL = "1";
    /**
     * ç™»å½•成功
     */
    public static final String LOGIN_SUCCESS = "Success";
    /**
     * æ³¨é”€
     */
    public static final String LOGOUT = "Logout";
    /**
     * æ³¨å†Œ
     */
    public static final String REGISTER = "Register";
    /**
     * ç™»å½•失败
     */
    public static final String LOGIN_FAIL = "Error";
    /**
     * æ‰€æœ‰æƒé™æ ‡è¯†
     */
    public static final String ALL_PERMISSION = "*:*:*";
    /**
     * ç®¡ç†å‘˜è§’色权限标识
     */
    public static final String SUPER_ADMIN = "admin";
    /**
     * è§’色权限分隔符
     */
    public static final String ROLE_DELIMITER = ",";
    /**
     * æƒé™æ ‡è¯†åˆ†éš”符
     */
    public static final String PERMISSION_DELIMITER = ",";
    /**
     * éªŒè¯ç æœ‰æ•ˆæœŸï¼ˆåˆ†é’Ÿï¼‰
     */
    public static final Integer CAPTCHA_EXPIRATION = 2;
    /**
     * ä»¤ç‰Œ
     */
    public static final String TOKEN = "token";
    /**
     * ä»¤ç‰Œå‰ç¼€
     */
    public static final String TOKEN_PREFIX = "Bearer ";
    /**
     * ä»¤ç‰Œå‰ç¼€
     */
    public static final String LOGIN_USER_KEY = "login_user_key";
    /**
     * ç”¨æˆ·ID
     */
    public static final String JWT_USERID = "userid";
    /**
     * ç”¨æˆ·åç§°
     */
    public static final String JWT_USERNAME = Claims.SUBJECT;
    /**
     * ç”¨æˆ·å¤´åƒ
     */
    public static final String JWT_AVATAR = "avatar";
    /**
     * åˆ›å»ºæ—¶é—´
     */
    public static final String JWT_CREATED = "created";
    /**
     * ç”¨æˆ·æƒé™
     */
    public static final String JWT_AUTHORITIES = "authorities";
    /**
     * èµ„源映射路径 å‰ç¼€
     */
    public static final String RESOURCE_PREFIX = "/profile";
    /**
     * RMI è¿œç¨‹æ–¹æ³•调用
     */
    public static final String LOOKUP_RMI = "rmi:";
    /**
     * LDAP è¿œç¨‹æ–¹æ³•调用
     */
    public static final String LOOKUP_LDAP = "ldap:";
    /**
     * LDAPS è¿œç¨‹æ–¹æ³•调用
     */
    public static final String LOOKUP_LDAPS = "ldaps:";
    /**
     * è‡ªåŠ¨è¯†åˆ«json对象白名单配置(仅允许解析的包名,范围越小越安全)
     */
    public static final String[] JSON_WHITELIST_STR = { "com.ruoyi" };
    /**
     * å®šæ—¶ä»»åŠ¡ç™½åå•é…ç½®ï¼ˆä»…å…è®¸è®¿é—®çš„åŒ…åï¼Œå¦‚å…¶ä»–éœ€è¦å¯ä»¥è‡ªè¡Œæ·»åŠ ï¼‰
     */
    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
    /**
     * å®šæ—¶ä»»åŠ¡è¿è§„çš„å­—ç¬¦
     */
    public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
            "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
    /**
     * éƒ¨é—¨ç›¸å…³å¸¸é‡
     */
    public static class Dept
    {
        /**
         * å…¨éƒ¨æ•°æ®æƒé™
         */
        public static final String DATA_SCOPE_ALL = "1";
        /**
         * è‡ªå®šæ•°æ®æƒé™
         */
        public static final String DATA_SCOPE_CUSTOM = "2";
        /**
         * éƒ¨é—¨æ•°æ®æƒé™
         */
        public static final String DATA_SCOPE_DEPT = "3";
        /**
         * éƒ¨é—¨åŠä»¥ä¸‹æ•°æ®æƒé™
         */
        public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
        /**
         * ä»…本人数据权限
         */
        public static final String DATA_SCOPE_SELF = "5";
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,120 @@
package com.ruoyi.common.constant;
/**
 * ä»£ç ç”Ÿæˆé€šç”¨å¸¸é‡
 *
 * @author ruoyi
 */
public class GenConstants
{
    /** å•表(增删改查) */
    public static final String TPL_CRUD = "crud";
    /** æ ‘表(增删改查) */
    public static final String TPL_TREE = "tree";
    /** ä¸»å­è¡¨ï¼ˆå¢žåˆ æ”¹æŸ¥ï¼‰ */
    public static final String TPL_SUB = "sub";
    /** æ ‘编码字段 */
    public static final String TREE_CODE = "treeCode";
    /** æ ‘父编码字段 */
    public static final String TREE_PARENT_CODE = "treeParentCode";
    /** æ ‘名称字段 */
    public static final String TREE_NAME = "treeName";
    /** ä¸Šçº§èœå•ID字段 */
    public static final String PARENT_MENU_ID = "parentMenuId";
    /** ä¸Šçº§èœå•名称字段 */
    public static final String PARENT_MENU_NAME = "parentMenuName";
    /** ç”Ÿæˆè¯¦æƒ…页开关 */
    public static final String GEN_VIEW = "genView";
    /** æ•°æ®åº“字符串类型 */
    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
    /** æ•°æ®åº“文本类型 */
    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
    /** æ•°æ®åº“时间类型 */
    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
    /** æ•°æ®åº“数字类型 */
    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
            "bit", "bigint", "float", "double", "decimal" };
    /** é¡µé¢ä¸éœ€è¦ç¼–辑字段 */
    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
    /** é¡µé¢ä¸éœ€è¦æ˜¾ç¤ºçš„列表字段 */
    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
            "update_time" };
    /** é¡µé¢ä¸éœ€è¦æŸ¥è¯¢å­—段 */
    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
            "update_time", "remark" };
    /** Entity基类字段 */
    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
    /** Tree基类字段 */
    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
    /** æ–‡æœ¬æ¡† */
    public static final String HTML_INPUT = "input";
    /** æ–‡æœ¬åŸŸ */
    public static final String HTML_TEXTAREA = "textarea";
    /** ä¸‹æ‹‰æ¡† */
    public static final String HTML_SELECT = "select";
    /** å•选框 */
    public static final String HTML_RADIO = "radio";
    /** å¤é€‰æ¡† */
    public static final String HTML_CHECKBOX = "checkbox";
    /** æ—¥æœŸæŽ§ä»¶ */
    public static final String HTML_DATETIME = "datetime";
    /** å›¾ç‰‡ä¸Šä¼ æŽ§ä»¶ */
    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
    /** æ–‡ä»¶ä¸Šä¼ æŽ§ä»¶ */
    public static final String HTML_FILE_UPLOAD = "fileUpload";
    /** å¯Œæ–‡æœ¬æŽ§ä»¶ */
    public static final String HTML_EDITOR = "editor";
    /** å­—符串类型 */
    public static final String TYPE_STRING = "String";
    /** æ•´åž‹ */
    public static final String TYPE_INTEGER = "Integer";
    /** é•¿æ•´åž‹ */
    public static final String TYPE_LONG = "Long";
    /** æµ®ç‚¹åž‹ */
    public static final String TYPE_DOUBLE = "Double";
    /** é«˜ç²¾åº¦è®¡ç®—类型 */
    public static final String TYPE_BIGDECIMAL = "BigDecimal";
    /** æ—¶é—´ç±»åž‹ */
    public static final String TYPE_DATE = "Date";
    /** æ¨¡ç³ŠæŸ¥è¯¢ */
    public static final String QUERY_LIKE = "LIKE";
    /** ç›¸ç­‰æŸ¥è¯¢ */
    public static final String QUERY_EQ = "EQ";
    /** éœ€è¦ */
    public static final String REQUIRE = "1";
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.ruoyi.common.constant;
/**
 * è¿”回状态码
 *
 * @author ruoyi
 */
public class HttpStatus
{
    /**
     * æ“ä½œæˆåŠŸ
     */
    public static final int SUCCESS = 200;
    /**
     * å¯¹è±¡åˆ›å»ºæˆåŠŸ
     */
    public static final int CREATED = 201;
    /**
     * è¯·æ±‚已经被接受
     */
    public static final int ACCEPTED = 202;
    /**
     * æ“ä½œå·²ç»æ‰§è¡ŒæˆåŠŸï¼Œä½†æ˜¯æ²¡æœ‰è¿”å›žæ•°æ®
     */
    public static final int NO_CONTENT = 204;
    /**
     * èµ„源已被移除
     */
    public static final int MOVED_PERM = 301;
    /**
     * é‡å®šå‘
     */
    public static final int SEE_OTHER = 303;
    /**
     * èµ„源没有被修改
     */
    public static final int NOT_MODIFIED = 304;
    /**
     * å‚数列表错误(缺少,格式不匹配)
     */
    public static final int BAD_REQUEST = 400;
    /**
     * æœªæŽˆæƒ
     */
    public static final int UNAUTHORIZED = 401;
    /**
     * è®¿é—®å—限,授权过期
     */
    public static final int FORBIDDEN = 403;
    /**
     * èµ„源,服务未找到
     */
    public static final int NOT_FOUND = 404;
    /**
     * ä¸å…è®¸çš„http方法
     */
    public static final int BAD_METHOD = 405;
    /**
     * èµ„源冲突,或者资源被锁
     */
    public static final int CONFLICT = 409;
    /**
     * ä¸æ”¯æŒçš„æ•°æ®ï¼Œåª’体类型
     */
    public static final int UNSUPPORTED_TYPE = 415;
    /**
     * ç³»ç»Ÿå†…部错误
     */
    public static final int ERROR = 500;
    /**
     * æŽ¥å£æœªå®žçް
     */
    public static final int NOT_IMPLEMENTED = 501;
    /**
     * ç³»ç»Ÿè­¦å‘Šæ¶ˆæ¯
     */
    public static final int WARN = 601;
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.ruoyi.common.constant;
/**
 * ä»»åŠ¡è°ƒåº¦é€šç”¨å¸¸é‡
 *
 * @author ruoyi
 */
public class ScheduleConstants
{
    public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
    /** æ‰§è¡Œç›®æ ‡key */
    public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
    /** é»˜è®¤ */
    public static final String MISFIRE_DEFAULT = "0";
    /** ç«‹å³è§¦å‘执行 */
    public static final String MISFIRE_IGNORE_MISFIRES = "1";
    /** è§¦å‘一次执行 */
    public static final String MISFIRE_FIRE_AND_PROCEED = "2";
    /** ä¸è§¦å‘立即执行 */
    public static final String MISFIRE_DO_NOTHING = "3";
    public enum Status
    {
        /**
         * æ­£å¸¸
         */
        NORMAL("0"),
        /**
         * æš‚停
         */
        PAUSE("1");
        private String value;
        private Status(String value)
        {
            this.value = value;
        }
        public String getValue()
        {
            return value;
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
package com.ruoyi.common.constant;
/**
 * ç”¨æˆ·å¸¸é‡ä¿¡æ¯
 *
 * @author ruoyi
 */
public class UserConstants
{
    /**
     * å¹³å°å†…系统用户的唯一标志
     */
    public static final String SYS_USER = "SYS_USER";
    /** æ­£å¸¸çŠ¶æ€ */
    public static final String NORMAL = "0";
    /** å¼‚常状态 */
    public static final String EXCEPTION = "1";
    /** ç”¨æˆ·å°ç¦çŠ¶æ€ */
    public static final String USER_DISABLE = "1";
    /** è§’色正常状态 */
    public static final String ROLE_NORMAL = "0";
    /** è§’色封禁状态 */
    public static final String ROLE_DISABLE = "1";
    /** éƒ¨é—¨æ­£å¸¸çŠ¶æ€ */
    public static final String DEPT_NORMAL = "0";
    /** éƒ¨é—¨åœç”¨çŠ¶æ€ */
    public static final String DEPT_DISABLE = "1";
    /** å­—典正常状态 */
    public static final String DICT_NORMAL = "0";
    /** æ˜¯å¦ä¸ºç³»ç»Ÿé»˜è®¤ï¼ˆæ˜¯ï¼‰ */
    public static final String YES = "Y";
    /** æ˜¯å¦èœå•外链(是) */
    public static final String YES_FRAME = "0";
    /** æ˜¯å¦èœå•外链(否) */
    public static final String NO_FRAME = "1";
    /** èœå•类型(目录) */
    public static final String TYPE_DIR = "M";
    /** èœå•类型(菜单) */
    public static final String TYPE_MENU = "C";
    /** èœå•类型(按钮) */
    public static final String TYPE_BUTTON = "F";
    /** Layout组件标识 */
    public final static String LAYOUT = "Layout";
    /** ParentView组件标识 */
    public final static String PARENT_VIEW = "ParentView";
    /** InnerLink组件标识 */
    public final static String INNER_LINK = "InnerLink";
    /** æ ¡éªŒæ˜¯å¦å”¯ä¸€çš„返回标识 */
    public final static boolean UNIQUE = true;
    public final static boolean NOT_UNIQUE = false;
    /**
     * ç”¨æˆ·åé•¿åº¦é™åˆ¶
     */
    public static final int USERNAME_MIN_LENGTH = 2;
    public static final int USERNAME_MAX_LENGTH = 20;
    /**
     * å¯†ç é•¿åº¦é™åˆ¶
     */
    public static final int PASSWORD_MIN_LENGTH = 5;
    public static final int PASSWORD_MAX_LENGTH = 20;
}
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
package com.ruoyi.common.core.controller;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.sql.SqlUtil;
/**
 * web层通用数据处理
 *
 * @author ruoyi
 */
public class BaseController
{
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * å°†å‰å°ä¼ é€’过来的日期格式的字符串,自动转化为Date类型
     */
    @InitBinder
    public void initBinder(WebDataBinder binder)
    {
        // Date ç±»åž‹è½¬æ¢
        binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
        {
            @Override
            public void setAsText(String text)
            {
                setValue(DateUtils.parseDate(text));
            }
        });
    }
    /**
     * è®¾ç½®è¯·æ±‚分页数据
     */
    protected void startPage()
    {
        PageUtils.startPage();
    }
    /**
     * è®¾ç½®è¯·æ±‚排序数据
     */
    protected void startOrderBy()
    {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
        {
            String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
            PageHelper.orderBy(orderBy);
        }
    }
    /**
     * æ¸…理分页的线程变量
     */
    protected void clearPage()
    {
        PageUtils.clearPage();
    }
    /**
     * å“åº”请求分页数据
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected TableDataInfo getDataTable(List<?> list)
    {
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("查询成功");
        rspData.setRows(list);
        rspData.setTotal(new PageInfo(list).getTotal());
        return rspData;
    }
    /**
     * è¿”回成功
     */
    public AjaxResult success()
    {
        return AjaxResult.success();
    }
    /**
     * è¿”回失败消息
     */
    public AjaxResult error()
    {
        return AjaxResult.error();
    }
    /**
     * è¿”回成功消息
     */
    public AjaxResult success(String message)
    {
        return AjaxResult.success(message);
    }
    /**
     * è¿”回成功消息
     */
    public AjaxResult success(Object data)
    {
        return AjaxResult.success(data);
    }
    /**
     * è¿”回失败消息
     */
    public AjaxResult error(String message)
    {
        return AjaxResult.error(message);
    }
    /**
     * è¿”回警告消息
     */
    public AjaxResult warn(String message)
    {
        return AjaxResult.warn(message);
    }
    /**
     * å“åº”返回结果
     *
     * @param rows å½±å“è¡Œæ•°
     * @return æ“ä½œç»“æžœ
     */
    protected AjaxResult toAjax(int rows)
    {
        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
    }
    /**
     * å“åº”返回结果
     *
     * @param result ç»“æžœ
     * @return æ“ä½œç»“æžœ
     */
    protected AjaxResult toAjax(boolean result)
    {
        return result ? success() : error();
    }
    /**
     * é¡µé¢è·³è½¬
     */
    public String redirect(String url)
    {
        return StringUtils.format("redirect:{}", url);
    }
    /**
     * èŽ·å–ç”¨æˆ·ç¼“å­˜ä¿¡æ¯
     */
    public LoginUser getLoginUser()
    {
        return SecurityUtils.getLoginUser();
    }
    /**
     * èŽ·å–ç™»å½•ç”¨æˆ·id
     */
    public Long getUserId()
    {
        return getLoginUser().getUserId();
    }
    /**
     * èŽ·å–ç™»å½•éƒ¨é—¨id
     */
    public Long getDeptId()
    {
        return getLoginUser().getDeptId();
    }
    /**
     * èŽ·å–ç™»å½•ç”¨æˆ·å
     */
    public String getUsername()
    {
        return getLoginUser().getUsername();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
package com.ruoyi.common.core.domain;
import java.util.HashMap;
import java.util.Objects;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.StringUtils;
/**
 * æ“ä½œæ¶ˆæ¯æé†’
 *
 * @author ruoyi
 */
public class AjaxResult extends HashMap<String, Object>
{
    private static final long serialVersionUID = 1L;
    /** çŠ¶æ€ç  */
    public static final String CODE_TAG = "code";
    /** è¿”回内容 */
    public static final String MSG_TAG = "msg";
    /** æ•°æ®å¯¹è±¡ */
    public static final String DATA_TAG = "data";
    /**
     * åˆå§‹åŒ–一个新创建的 AjaxResult å¯¹è±¡ï¼Œä½¿å…¶è¡¨ç¤ºä¸€ä¸ªç©ºæ¶ˆæ¯ã€‚
     */
    public AjaxResult()
    {
    }
    /**
     * åˆå§‹åŒ–一个新创建的 AjaxResult å¯¹è±¡
     *
     * @param code çŠ¶æ€ç 
     * @param msg è¿”回内容
     */
    public AjaxResult(int code, String msg)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }
    /**
     * åˆå§‹åŒ–一个新创建的 AjaxResult å¯¹è±¡
     *
     * @param code çŠ¶æ€ç 
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     */
    public AjaxResult(int code, String msg, Object data)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (StringUtils.isNotNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }
    /**
     * è¿”回成功消息
     *
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success()
    {
        return AjaxResult.success("操作成功");
    }
    /**
     * è¿”回成功数据
     *
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success(Object data)
    {
        return AjaxResult.success("操作成功", data);
    }
    /**
     * è¿”回成功消息
     *
     * @param msg è¿”回内容
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success(String msg)
    {
        return AjaxResult.success(msg, null);
    }
    /**
     * è¿”回成功消息
     *
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     * @return æˆåŠŸæ¶ˆæ¯
     */
    public static AjaxResult success(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.SUCCESS, msg, data);
    }
    /**
     * è¿”回警告消息
     *
     * @param msg è¿”回内容
     * @return è­¦å‘Šæ¶ˆæ¯
     */
    public static AjaxResult warn(String msg)
    {
        return AjaxResult.warn(msg, null);
    }
    /**
     * è¿”回警告消息
     *
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     * @return è­¦å‘Šæ¶ˆæ¯
     */
    public static AjaxResult warn(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.WARN, msg, data);
    }
    /**
     * è¿”回错误消息
     *
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error()
    {
        return AjaxResult.error("操作失败");
    }
    /**
     * è¿”回错误消息
     *
     * @param msg è¿”回内容
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error(String msg)
    {
        return AjaxResult.error(msg, null);
    }
    /**
     * è¿”回错误消息
     *
     * @param msg è¿”回内容
     * @param data æ•°æ®å¯¹è±¡
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.ERROR, msg, data);
    }
    /**
     * è¿”回错误消息
     *
     * @param code çŠ¶æ€ç 
     * @param msg è¿”回内容
     * @return é”™è¯¯æ¶ˆæ¯
     */
    public static AjaxResult error(int code, String msg)
    {
        return new AjaxResult(code, msg, null);
    }
    /**
     * æ˜¯å¦ä¸ºæˆåŠŸæ¶ˆæ¯
     *
     * @return ç»“æžœ
     */
    public boolean isSuccess()
    {
        return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
    }
    /**
     * æ˜¯å¦ä¸ºè­¦å‘Šæ¶ˆæ¯
     *
     * @return ç»“æžœ
     */
    public boolean isWarn()
    {
        return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
    }
    /**
     * æ˜¯å¦ä¸ºé”™è¯¯æ¶ˆæ¯
     *
     * @return ç»“æžœ
     */
    public boolean isError()
    {
        return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
    }
    /**
     * æ–¹ä¾¿é“¾å¼è°ƒç”¨
     *
     * @param key é”®
     * @param value å€¼
     * @return æ•°æ®å¯¹è±¡
     */
    @Override
    public AjaxResult put(String key, Object value)
    {
        super.put(key, value);
        return this;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,118 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
 * Entity基类
 *
 * @author ruoyi
 */
public class BaseEntity implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** æœç´¢å€¼ */
    @JsonIgnore
    private String searchValue;
    /** åˆ›å»ºè€… */
    private String createBy;
    /** åˆ›å»ºæ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;
    /** æ›´æ–°è€… */
    private String updateBy;
    /** æ›´æ–°æ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    /** å¤‡æ³¨ */
    private String remark;
    /** è¯·æ±‚参数 */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private Map<String, Object> params;
    public String getSearchValue()
    {
        return searchValue;
    }
    public void setSearchValue(String searchValue)
    {
        this.searchValue = searchValue;
    }
    public String getCreateBy()
    {
        return createBy;
    }
    public void setCreateBy(String createBy)
    {
        this.createBy = createBy;
    }
    public Date getCreateTime()
    {
        return createTime;
    }
    public void setCreateTime(Date createTime)
    {
        this.createTime = createTime;
    }
    public String getUpdateBy()
    {
        return updateBy;
    }
    public void setUpdateBy(String updateBy)
    {
        this.updateBy = updateBy;
    }
    public Date getUpdateTime()
    {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime)
    {
        this.updateTime = updateTime;
    }
    public String getRemark()
    {
        return remark;
    }
    public void setRemark(String remark)
    {
        this.remark = remark;
    }
    public Map<String, Object> getParams()
    {
        if (params == null)
        {
            params = new HashMap<>();
        }
        return params;
    }
    public void setParams(Map<String, Object> params)
    {
        this.params = params;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,115 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import com.ruoyi.common.constant.HttpStatus;
/**
 * å“åº”信息主体
 *
 * @author ruoyi
 */
public class R<T> implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** æˆåŠŸ */
    public static final int SUCCESS = HttpStatus.SUCCESS;
    /** å¤±è´¥ */
    public static final int FAIL = HttpStatus.ERROR;
    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(T data, String msg)
    {
        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(T data, String msg)
    {
        return restResult(data, FAIL, msg);
    }
    public static <T> R<T> fail(int code, String msg)
    {
        return restResult(null, code, msg);
    }
    private static <T> R<T> restResult(T data, int code, String msg)
    {
        R<T> apiResult = new R<>();
        apiResult.setCode(code);
        apiResult.setData(data);
        apiResult.setMsg(msg);
        return apiResult;
    }
    public int getCode()
    {
        return code;
    }
    public void setCode(int code)
    {
        this.code = code;
    }
    public String getMsg()
    {
        return msg;
    }
    public void setMsg(String msg)
    {
        this.msg = msg;
    }
    public T getData()
    {
        return data;
    }
    public void setData(T data)
    {
        this.data = data;
    }
    public static <T> Boolean isError(R<T> ret)
    {
        return !isSuccess(ret);
    }
    public static <T> Boolean isSuccess(R<T> ret)
    {
        return R.SUCCESS == ret.getCode();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,79 @@
package com.ruoyi.common.core.domain;
import java.util.ArrayList;
import java.util.List;
/**
 * Tree基类
 *
 * @author ruoyi
 */
public class TreeEntity extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** çˆ¶èœå•名称 */
    private String parentName;
    /** çˆ¶èœå•ID */
    private Long parentId;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** ç¥–级列表 */
    private String ancestors;
    /** å­éƒ¨é—¨ */
    private List<?> children = new ArrayList<>();
    public String getParentName()
    {
        return parentName;
    }
    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }
    public Long getParentId()
    {
        return parentId;
    }
    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }
    public Integer getOrderNum()
    {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }
    public String getAncestors()
    {
        return ancestors;
    }
    public void setAncestors(String ancestors)
    {
        this.ancestors = ancestors;
    }
    public List<?> getChildren()
    {
        return children;
    }
    public void setChildren(List<?> children)
    {
        this.children = children;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,93 @@
package com.ruoyi.common.core.domain;
import java.io.Serializable;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.utils.StringUtils;
/**
 * Treeselect树结构实体类
 *
 * @author ruoyi
 */
public class TreeSelect implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** èŠ‚ç‚¹ID */
    private Long id;
    /** èŠ‚ç‚¹åç§° */
    private String label;
    /** èŠ‚ç‚¹ç¦ç”¨ */
    private boolean disabled = false;
    /** å­èŠ‚ç‚¹ */
    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    private List<TreeSelect> children;
    public TreeSelect()
    {
    }
    public TreeSelect(SysDept dept)
    {
        this.id = dept.getDeptId();
        this.label = dept.getDeptName();
        this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
        this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
    }
    public TreeSelect(SysMenu menu)
    {
        this.id = menu.getMenuId();
        this.label = menu.getMenuName();
        this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
    }
    public Long getId()
    {
        return id;
    }
    public void setId(Long id)
    {
        this.id = id;
    }
    public String getLabel()
    {
        return label;
    }
    public void setLabel(String label)
    {
        this.label = label;
    }
    public boolean isDisabled()
    {
        return disabled;
    }
    public void setDisabled(boolean disabled)
    {
        this.disabled = disabled;
    }
    public List<TreeSelect> getChildren()
    {
        return children;
    }
    public void setChildren(List<TreeSelect> children)
    {
        this.children = children;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,203 @@
package com.ruoyi.common.core.domain.entity;
import java.util.ArrayList;
import java.util.List;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.domain.BaseEntity;
/**
 * éƒ¨é—¨è¡¨ sys_dept
 *
 * @author ruoyi
 */
public class SysDept extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** éƒ¨é—¨ID */
    private Long deptId;
    /** çˆ¶éƒ¨é—¨ID */
    private Long parentId;
    /** ç¥–级列表 */
    private String ancestors;
    /** éƒ¨é—¨åç§° */
    private String deptName;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** è´Ÿè´£äºº */
    private String leader;
    /** è”系电话 */
    private String phone;
    /** é‚®ç®± */
    private String email;
    /** éƒ¨é—¨çŠ¶æ€:0正常,1停用 */
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** çˆ¶éƒ¨é—¨åç§° */
    private String parentName;
    /** å­éƒ¨é—¨ */
    private List<SysDept> children = new ArrayList<SysDept>();
    public Long getDeptId()
    {
        return deptId;
    }
    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }
    public Long getParentId()
    {
        return parentId;
    }
    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }
    public String getAncestors()
    {
        return ancestors;
    }
    public void setAncestors(String ancestors)
    {
        this.ancestors = ancestors;
    }
    @NotBlank(message = "部门名称不能为空")
    @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符")
    public String getDeptName()
    {
        return deptName;
    }
    public void setDeptName(String deptName)
    {
        this.deptName = deptName;
    }
    @NotNull(message = "显示顺序不能为空")
    public Integer getOrderNum()
    {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }
    public String getLeader()
    {
        return leader;
    }
    public void setLeader(String leader)
    {
        this.leader = leader;
    }
    @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符")
    public String getPhone()
    {
        return phone;
    }
    public void setPhone(String phone)
    {
        this.phone = phone;
    }
    @Email(message = "邮箱格式不正确")
    @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
    public String getEmail()
    {
        return email;
    }
    public void setEmail(String email)
    {
        this.email = email;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    public String getDelFlag()
    {
        return delFlag;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }
    public String getParentName()
    {
        return parentName;
    }
    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }
    public List<SysDept> getChildren()
    {
        return children;
    }
    public void setChildren(List<SysDept> children)
    {
        this.children = children;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("deptId", getDeptId())
            .append("parentId", getParentId())
            .append("ancestors", getAncestors())
            .append("deptName", getDeptName())
            .append("orderNum", getOrderNum())
            .append("leader", getLeader())
            .append("phone", getPhone())
            .append("email", getEmail())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
package com.ruoyi.common.core.domain.entity;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.BaseEntity;
/**
 * å­—典数据表 sys_dict_data
 *
 * @author ruoyi
 */
public class SysDictData extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** å­—典编码 */
    @Excel(name = "字典编码", cellType = ColumnType.NUMERIC)
    private Long dictCode;
    /** å­—典排序 */
    @Excel(name = "字典排序", cellType = ColumnType.NUMERIC)
    private Long dictSort;
    /** å­—典标签 */
    @Excel(name = "字典标签")
    private String dictLabel;
    /** å­—典键值 */
    @Excel(name = "字典键值")
    private String dictValue;
    /** å­—典类型 */
    @Excel(name = "字典类型")
    private String dictType;
    /** æ ·å¼å±žæ€§ï¼ˆå…¶ä»–样式扩展) */
    private String cssClass;
    /** è¡¨æ ¼å­—典样式 */
    private String listClass;
    /** æ˜¯å¦é»˜è®¤ï¼ˆY是 N否) */
    @Excel(name = "是否默认", readConverterExp = "Y=是,N=否")
    private String isDefault;
    /** çŠ¶æ€ï¼ˆ0正常 1停用) */
    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
    private String status;
    public Long getDictCode()
    {
        return dictCode;
    }
    public void setDictCode(Long dictCode)
    {
        this.dictCode = dictCode;
    }
    public Long getDictSort()
    {
        return dictSort;
    }
    public void setDictSort(Long dictSort)
    {
        this.dictSort = dictSort;
    }
    @NotBlank(message = "字典标签不能为空")
    @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符")
    public String getDictLabel()
    {
        return dictLabel;
    }
    public void setDictLabel(String dictLabel)
    {
        this.dictLabel = dictLabel;
    }
    @NotBlank(message = "字典键值不能为空")
    @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符")
    public String getDictValue()
    {
        return dictValue;
    }
    public void setDictValue(String dictValue)
    {
        this.dictValue = dictValue;
    }
    @NotBlank(message = "字典类型不能为空")
    @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符")
    public String getDictType()
    {
        return dictType;
    }
    public void setDictType(String dictType)
    {
        this.dictType = dictType;
    }
    @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符")
    public String getCssClass()
    {
        return cssClass;
    }
    public void setCssClass(String cssClass)
    {
        this.cssClass = cssClass;
    }
    public String getListClass()
    {
        return listClass;
    }
    public void setListClass(String listClass)
    {
        this.listClass = listClass;
    }
    public boolean getDefault()
    {
        return UserConstants.YES.equals(this.isDefault);
    }
    public String getIsDefault()
    {
        return isDefault;
    }
    public void setIsDefault(String isDefault)
    {
        this.isDefault = isDefault;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("dictCode", getDictCode())
            .append("dictSort", getDictSort())
            .append("dictLabel", getDictLabel())
            .append("dictValue", getDictValue())
            .append("dictType", getDictType())
            .append("cssClass", getCssClass())
            .append("listClass", getListClass())
            .append("isDefault", getIsDefault())
            .append("status", getStatus())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
package com.ruoyi.common.core.domain.entity;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.core.domain.BaseEntity;
/**
 * å­—典类型表 sys_dict_type
 *
 * @author ruoyi
 */
public class SysDictType extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** å­—典主键 */
    @Excel(name = "字典主键", cellType = ColumnType.NUMERIC)
    private Long dictId;
    /** å­—典名称 */
    @Excel(name = "字典名称")
    private String dictName;
    /** å­—典类型 */
    @Excel(name = "字典类型")
    private String dictType;
    /** çŠ¶æ€ï¼ˆ0正常 1停用) */
    @Excel(name = "状态", readConverterExp = "0=正常,1=停用")
    private String status;
    public Long getDictId()
    {
        return dictId;
    }
    public void setDictId(Long dictId)
    {
        this.dictId = dictId;
    }
    @NotBlank(message = "字典名称不能为空")
    @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符")
    public String getDictName()
    {
        return dictName;
    }
    public void setDictName(String dictName)
    {
        this.dictName = dictName;
    }
    @NotBlank(message = "字典类型不能为空")
    @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符")
    @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
    public String getDictType()
    {
        return dictType;
    }
    public void setDictType(String dictType)
    {
        this.dictType = dictType;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("dictId", getDictId())
            .append("dictName", getDictName())
            .append("dictType", getDictType())
            .append("status", getStatus())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,274 @@
package com.ruoyi.common.core.domain.entity;
import java.util.ArrayList;
import java.util.List;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.core.domain.BaseEntity;
/**
 * èœå•权限表 sys_menu
 *
 * @author ruoyi
 */
public class SysMenu extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** èœå•ID */
    private Long menuId;
    /** èœå•名称 */
    private String menuName;
    /** çˆ¶èœå•名称 */
    private String parentName;
    /** çˆ¶èœå•ID */
    private Long parentId;
    /** æ˜¾ç¤ºé¡ºåº */
    private Integer orderNum;
    /** è·¯ç”±åœ°å€ */
    private String path;
    /** ç»„件路径 */
    private String component;
    /** è·¯ç”±å‚æ•° */
    private String query;
    /** è·¯ç”±åç§°ï¼Œé»˜è®¤å’Œè·¯ç”±åœ°å€ç›¸åŒçš„驼峰格式(注意:因为vue3版本的router会删除名称相同路由,为避免名字的冲突,特殊情况可以自定义) */
    private String routeName;
    /** æ˜¯å¦ä¸ºå¤–链(0是 1否) */
    private String isFrame;
    /** æ˜¯å¦ç¼“存(0缓存 1不缓存) */
    private String isCache;
    /** ç±»åž‹ï¼ˆM目录 C菜单 F按钮) */
    private String menuType;
    /** æ˜¾ç¤ºçŠ¶æ€ï¼ˆ0显示 1隐藏) */
    private String visible;
    /** èœå•状态(0正常 1停用) */
    private String status;
    /** æƒé™å­—符串 */
    private String perms;
    /** èœå•图标 */
    private String icon;
    /** å­èœå• */
    private List<SysMenu> children = new ArrayList<SysMenu>();
    public Long getMenuId()
    {
        return menuId;
    }
    public void setMenuId(Long menuId)
    {
        this.menuId = menuId;
    }
    @NotBlank(message = "菜单名称不能为空")
    @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符")
    public String getMenuName()
    {
        return menuName;
    }
    public void setMenuName(String menuName)
    {
        this.menuName = menuName;
    }
    public String getParentName()
    {
        return parentName;
    }
    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }
    public Long getParentId()
    {
        return parentId;
    }
    public void setParentId(Long parentId)
    {
        this.parentId = parentId;
    }
    @NotNull(message = "显示顺序不能为空")
    public Integer getOrderNum()
    {
        return orderNum;
    }
    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }
    @Size(min = 0, max = 200, message = "路由地址不能超过200个字符")
    public String getPath()
    {
        return path;
    }
    public void setPath(String path)
    {
        this.path = path;
    }
    @Size(min = 0, max = 200, message = "组件路径不能超过255个字符")
    public String getComponent()
    {
        return component;
    }
    public void setComponent(String component)
    {
        this.component = component;
    }
    public String getQuery()
    {
        return query;
    }
    public void setQuery(String query)
    {
        this.query = query;
    }
    public String getRouteName()
    {
        return routeName;
    }
    public void setRouteName(String routeName)
    {
        this.routeName = routeName;
    }
    public String getIsFrame()
    {
        return isFrame;
    }
    public void setIsFrame(String isFrame)
    {
        this.isFrame = isFrame;
    }
    public String getIsCache()
    {
        return isCache;
    }
    public void setIsCache(String isCache)
    {
        this.isCache = isCache;
    }
    @NotBlank(message = "菜单类型不能为空")
    public String getMenuType()
    {
        return menuType;
    }
    public void setMenuType(String menuType)
    {
        this.menuType = menuType;
    }
    public String getVisible()
    {
        return visible;
    }
    public void setVisible(String visible)
    {
        this.visible = visible;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符")
    public String getPerms()
    {
        return perms;
    }
    public void setPerms(String perms)
    {
        this.perms = perms;
    }
    public String getIcon()
    {
        return icon;
    }
    public void setIcon(String icon)
    {
        this.icon = icon;
    }
    public List<SysMenu> getChildren()
    {
        return children;
    }
    public void setChildren(List<SysMenu> children)
    {
        this.children = children;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("menuId", getMenuId())
            .append("menuName", getMenuName())
            .append("parentId", getParentId())
            .append("orderNum", getOrderNum())
            .append("path", getPath())
            .append("component", getComponent())
            .append("query", getQuery())
            .append("routeName", getRouteName())
            .append("isFrame", getIsFrame())
            .append("IsCache", getIsCache())
            .append("menuType", getMenuType())
            .append("visible", getVisible())
            .append("status ", getStatus())
            .append("perms", getPerms())
            .append("icon", getIcon())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,241 @@
package com.ruoyi.common.core.domain.entity;
import java.util.Set;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.core.domain.BaseEntity;
/**
 * è§’色表 sys_role
 *
 * @author ruoyi
 */
public class SysRole extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** è§’色ID */
    @Excel(name = "角色序号", cellType = ColumnType.NUMERIC)
    private Long roleId;
    /** è§’色名称 */
    @Excel(name = "角色名称")
    private String roleName;
    /** è§’色权限 */
    @Excel(name = "角色权限")
    private String roleKey;
    /** è§’色排序 */
    @Excel(name = "角色排序")
    private Integer roleSort;
    /** æ•°æ®èŒƒå›´ï¼ˆ1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
    @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
    private String dataScope;
    /** èœå•树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
    private boolean menuCheckStrictly;
    /** éƒ¨é—¨æ ‘选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ï¼‰ */
    private boolean deptCheckStrictly;
    /** è§’色状态(0正常 1停用) */
    @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** ç”¨æˆ·æ˜¯å¦å­˜åœ¨æ­¤è§’色标识 é»˜è®¤ä¸å­˜åœ¨ */
    private boolean flag = false;
    /** èœå•组 */
    private Long[] menuIds;
    /** éƒ¨é—¨ç»„(数据权限) */
    private Long[] deptIds;
    /** è§’色菜单权限 */
    private Set<String> permissions;
    public SysRole()
    {
    }
    public SysRole(Long roleId)
    {
        this.roleId = roleId;
    }
    public Long getRoleId()
    {
        return roleId;
    }
    public void setRoleId(Long roleId)
    {
        this.roleId = roleId;
    }
    public boolean isAdmin()
    {
        return isAdmin(this.roleId);
    }
    public static boolean isAdmin(Long roleId)
    {
        return roleId != null && 1L == roleId;
    }
    @NotBlank(message = "角色名称不能为空")
    @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符")
    public String getRoleName()
    {
        return roleName;
    }
    public void setRoleName(String roleName)
    {
        this.roleName = roleName;
    }
    @NotBlank(message = "权限字符不能为空")
    @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符")
    public String getRoleKey()
    {
        return roleKey;
    }
    public void setRoleKey(String roleKey)
    {
        this.roleKey = roleKey;
    }
    @NotNull(message = "显示顺序不能为空")
    public Integer getRoleSort()
    {
        return roleSort;
    }
    public void setRoleSort(Integer roleSort)
    {
        this.roleSort = roleSort;
    }
    public String getDataScope()
    {
        return dataScope;
    }
    public void setDataScope(String dataScope)
    {
        this.dataScope = dataScope;
    }
    public boolean isMenuCheckStrictly()
    {
        return menuCheckStrictly;
    }
    public void setMenuCheckStrictly(boolean menuCheckStrictly)
    {
        this.menuCheckStrictly = menuCheckStrictly;
    }
    public boolean isDeptCheckStrictly()
    {
        return deptCheckStrictly;
    }
    public void setDeptCheckStrictly(boolean deptCheckStrictly)
    {
        this.deptCheckStrictly = deptCheckStrictly;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    public String getDelFlag()
    {
        return delFlag;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }
    public boolean isFlag()
    {
        return flag;
    }
    public void setFlag(boolean flag)
    {
        this.flag = flag;
    }
    public Long[] getMenuIds()
    {
        return menuIds;
    }
    public void setMenuIds(Long[] menuIds)
    {
        this.menuIds = menuIds;
    }
    public Long[] getDeptIds()
    {
        return deptIds;
    }
    public void setDeptIds(Long[] deptIds)
    {
        this.deptIds = deptIds;
    }
    public Set<String> getPermissions()
    {
        return permissions;
    }
    public void setPermissions(Set<String> permissions)
    {
        this.permissions = permissions;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("roleId", getRoleId())
            .append("roleName", getRoleName())
            .append("roleKey", getRoleKey())
            .append("roleSort", getRoleSort())
            .append("dataScope", getDataScope())
            .append("menuCheckStrictly", isMenuCheckStrictly())
            .append("deptCheckStrictly", isDeptCheckStrictly())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,338 @@
package com.ruoyi.common.core.domain.entity;
import java.util.Date;
import java.util.List;
import jakarta.validation.constraints.*;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.Excel.Type;
import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.xss.Xss;
/**
 * ç”¨æˆ·å¯¹è±¡ sys_user
 *
 * @author ruoyi
 */
public class SysUser extends BaseEntity
{
    private static final long serialVersionUID = 1L;
    /** ç”¨æˆ·ID */
    @Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
    private Long userId;
    /** éƒ¨é—¨ID */
    @Excel(name = "部门编号", type = Type.IMPORT)
    private Long deptId;
    /** ç”¨æˆ·è´¦å· */
    @Excel(name = "登录名称")
    private String userName;
    /** ç”¨æˆ·æ˜µç§° */
    @Excel(name = "用户名称")
    private String nickName;
    /** ç”¨æˆ·é‚®ç®± */
    @Excel(name = "用户邮箱")
    private String email;
    /** æ‰‹æœºå·ç  */
    @Excel(name = "手机号码", cellType = ColumnType.TEXT)
    private String phonenumber;
    /** ç”¨æˆ·æ€§åˆ« */
    @Excel(name = "用户性别", readConverterExp = "0=男,1=女,2=未知")
    private String sex;
    /** ç”¨æˆ·å¤´åƒ */
    private String avatar;
    /** å¯†ç  */
    private String password;
    /** è´¦å·çŠ¶æ€ï¼ˆ0正常 1停用) */
    @Excel(name = "账号状态", readConverterExp = "0=正常,1=停用")
    private String status;
    /** åˆ é™¤æ ‡å¿—(0代表存在 2代表删除) */
    private String delFlag;
    /** æœ€åŽç™»å½•IP */
    @Excel(name = "最后登录IP", type = Type.EXPORT)
    private String loginIp;
    /** æœ€åŽç™»å½•æ—¶é—´ */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "最后登录时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
    private Date loginDate;
    /** å¯†ç æœ€åŽæ›´æ–°æ—¶é—´ */
    private Date pwdUpdateDate;
    /** éƒ¨é—¨å¯¹è±¡ */
    @Excels({
        @Excel(name = "部门名称", targetAttr = "deptName", type = Type.EXPORT),
        @Excel(name = "部门负责人", targetAttr = "leader", type = Type.EXPORT)
    })
    private SysDept dept;
    /** è§’色对象 */
    private List<SysRole> roles;
    /** è§’色组 */
    private Long[] roleIds;
    /** å²—位组 */
    private Long[] postIds;
    /** è§’色ID */
    private Long roleId;
    public SysUser()
    {
    }
    public SysUser(Long userId)
    {
        this.userId = userId;
    }
    public Long getUserId()
    {
        return userId;
    }
    public void setUserId(Long userId)
    {
        this.userId = userId;
    }
    public boolean isAdmin()
    {
        return SecurityUtils.isAdmin(this.userId);
    }
    public Long getDeptId()
    {
        return deptId;
    }
    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }
    @Xss(message = "用户昵称不能包含脚本字符")
    @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符")
    public String getNickName()
    {
        return nickName;
    }
    public void setNickName(String nickName)
    {
        this.nickName = nickName;
    }
    @Xss(message = "用户账号不能包含脚本字符")
    @NotBlank(message = "用户账号不能为空")
    @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
    public String getUserName()
    {
        return userName;
    }
    public void setUserName(String userName)
    {
        this.userName = userName;
    }
    @Email(message = "邮箱格式不正确")
    @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符")
    public String getEmail()
    {
        return email;
    }
    public void setEmail(String email)
    {
        this.email = email;
    }
    @Size(min = 0, max = 11, message = "手机号码长度不能超过11个字符")
    public String getPhonenumber()
    {
        return phonenumber;
    }
    public void setPhonenumber(String phonenumber)
    {
        this.phonenumber = phonenumber;
    }
    public String getSex()
    {
        return sex;
    }
    public void setSex(String sex)
    {
        this.sex = sex;
    }
    public String getAvatar()
    {
        return avatar;
    }
    public void setAvatar(String avatar)
    {
        this.avatar = avatar;
    }
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getStatus()
    {
        return status;
    }
    public void setStatus(String status)
    {
        this.status = status;
    }
    public String getDelFlag()
    {
        return delFlag;
    }
    public void setDelFlag(String delFlag)
    {
        this.delFlag = delFlag;
    }
    public String getLoginIp()
    {
        return loginIp;
    }
    public void setLoginIp(String loginIp)
    {
        this.loginIp = loginIp;
    }
    public Date getLoginDate()
    {
        return loginDate;
    }
    public void setLoginDate(Date loginDate)
    {
        this.loginDate = loginDate;
    }
    public Date getPwdUpdateDate()
    {
        return pwdUpdateDate;
    }
    public void setPwdUpdateDate(Date pwdUpdateDate)
    {
        this.pwdUpdateDate = pwdUpdateDate;
    }
    public SysDept getDept()
    {
        return dept;
    }
    public void setDept(SysDept dept)
    {
        this.dept = dept;
    }
    public List<SysRole> getRoles()
    {
        return roles;
    }
    public void setRoles(List<SysRole> roles)
    {
        this.roles = roles;
    }
    public Long[] getRoleIds()
    {
        return roleIds;
    }
    public void setRoleIds(Long[] roleIds)
    {
        this.roleIds = roleIds;
    }
    public Long[] getPostIds()
    {
        return postIds;
    }
    public void setPostIds(Long[] postIds)
    {
        this.postIds = postIds;
    }
    public Long getRoleId()
    {
        return roleId;
    }
    public void setRoleId(Long roleId)
    {
        this.roleId = roleId;
    }
    @Override
    public String toString() {
        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
            .append("userId", getUserId())
            .append("deptId", getDeptId())
            .append("userName", getUserName())
            .append("nickName", getNickName())
            .append("email", getEmail())
            .append("phonenumber", getPhonenumber())
            .append("sex", getSex())
            .append("avatar", getAvatar())
            .append("password", getPassword())
            .append("status", getStatus())
            .append("delFlag", getDelFlag())
            .append("loginIp", getLoginIp())
            .append("loginDate", getLoginDate())
            .append("pwdUpdateDate", getPwdUpdateDate())
            .append("createBy", getCreateBy())
            .append("createTime", getCreateTime())
            .append("updateBy", getUpdateBy())
            .append("updateTime", getUpdateTime())
            .append("remark", getRemark())
            .append("dept", getDept())
            .toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,69 @@
package com.ruoyi.common.core.domain.model;
/**
 * ç”¨æˆ·ç™»å½•对象
 *
 * @author ruoyi
 */
public class LoginBody
{
    /**
     * ç”¨æˆ·å
     */
    private String username;
    /**
     * ç”¨æˆ·å¯†ç 
     */
    private String password;
    /**
     * éªŒè¯ç 
     */
    private String code;
    /**
     * å”¯ä¸€æ ‡è¯†
     */
    private String uuid;
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getCode()
    {
        return code;
    }
    public void setCode(String code)
    {
        this.code = code;
    }
    public String getUuid()
    {
        return uuid;
    }
    public void setUuid(String uuid)
    {
        this.uuid = uuid;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,278 @@
package com.ruoyi.common.core.domain.model;
import java.util.Collection;
import java.util.Collections;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.alibaba.fastjson2.annotation.JSONField;
import com.ruoyi.common.core.domain.entity.SysUser;
/**
 * ç™»å½•用户身份权限
 *
 * @author ruoyi
 */
public class LoginUser implements UserDetails
{
    private static final long serialVersionUID = 1L;
    /**
     * ç”¨æˆ·ID
     */
    private Long userId;
    /**
     * éƒ¨é—¨ID
     */
    private Long deptId;
    /**
     * ç”¨æˆ·å”¯ä¸€æ ‡è¯†
     */
    private String token;
    /**
     * ç™»å½•æ—¶é—´
     */
    private Long loginTime;
    /**
     * è¿‡æœŸæ—¶é—´
     */
    private Long expireTime;
    /**
     * ç™»å½•IP地址
     */
    private String ipaddr;
    /**
     * ç™»å½•地点
     */
    private String loginLocation;
    /**
     * æµè§ˆå™¨ç±»åž‹
     */
    private String browser;
    /**
     * æ“ä½œç³»ç»Ÿ
     */
    private String os;
    /**
     * æƒé™åˆ—表
     */
    private Set<String> permissions;
    /**
     * ç”¨æˆ·ä¿¡æ¯
     */
    private SysUser user;
    public LoginUser()
    {
    }
    public LoginUser(SysUser user, Set<String> permissions)
    {
        this.user = user;
        this.permissions = permissions;
    }
    public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
    {
        this.userId = userId;
        this.deptId = deptId;
        this.user = user;
        this.permissions = permissions;
    }
    public Long getUserId()
    {
        return userId;
    }
    public void setUserId(Long userId)
    {
        this.userId = userId;
    }
    public Long getDeptId()
    {
        return deptId;
    }
    public void setDeptId(Long deptId)
    {
        this.deptId = deptId;
    }
    public String getToken()
    {
        return token;
    }
    public void setToken(String token)
    {
        this.token = token;
    }
    @JSONField(serialize = false)
    @Override
    public String getPassword()
    {
        return user.getPassword();
    }
    @Override
    public String getUsername()
    {
        return user.getUserName();
    }
    /**
     * è´¦æˆ·æ˜¯å¦æœªè¿‡æœŸ,过期无法验证
     */
    @JSONField(serialize = false)
    @Override
    public boolean isAccountNonExpired()
    {
        return true;
    }
    /**
     * æŒ‡å®šç”¨æˆ·æ˜¯å¦è§£é”,锁定的用户无法进行身份验证
     *
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public boolean isAccountNonLocked()
    {
        return true;
    }
    /**
     * æŒ‡ç¤ºæ˜¯å¦å·²è¿‡æœŸçš„用户的凭据(密码),过期的凭据防止认证
     *
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public boolean isCredentialsNonExpired()
    {
        return true;
    }
    /**
     * æ˜¯å¦å¯ç”¨ ,禁用的用户不能身份验证
     *
     * @return
     */
    @JSONField(serialize = false)
    @Override
    public boolean isEnabled()
    {
        return true;
    }
    public Long getLoginTime()
    {
        return loginTime;
    }
    public void setLoginTime(Long loginTime)
    {
        this.loginTime = loginTime;
    }
    public String getIpaddr()
    {
        return ipaddr;
    }
    public void setIpaddr(String ipaddr)
    {
        this.ipaddr = ipaddr;
    }
    public String getLoginLocation()
    {
        return loginLocation;
    }
    public void setLoginLocation(String loginLocation)
    {
        this.loginLocation = loginLocation;
    }
    public String getBrowser()
    {
        return browser;
    }
    public void setBrowser(String browser)
    {
        this.browser = browser;
    }
    public String getOs()
    {
        return os;
    }
    public void setOs(String os)
    {
        this.os = os;
    }
    public Long getExpireTime()
    {
        return expireTime;
    }
    public void setExpireTime(Long expireTime)
    {
        this.expireTime = expireTime;
    }
    public Set<String> getPermissions()
    {
        return permissions;
    }
    public void setPermissions(Set<String> permissions)
    {
        this.permissions = permissions;
    }
    public SysUser getUser()
    {
        return user;
    }
    public void setUser(SysUser user)
    {
        this.user = user;
    }
    @Override
    @JSONField(serialize = false)
    public Collection<? extends GrantedAuthority> getAuthorities()
    {
        if (permissions == null || permissions.isEmpty())
        {
            return Collections.emptyList();
        }
        return permissions.stream()
            .filter(Objects::nonNull)
            .map(SimpleGrantedAuthority::new)
            .collect(Collectors.toList());
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package com.ruoyi.common.core.domain.model;
/**
 * ç”¨æˆ·æ³¨å†Œå¯¹è±¡
 *
 * @author ruoyi
 */
public class RegisterBody extends LoginBody
{
}
ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,101 @@
package com.ruoyi.common.core.page;
import com.ruoyi.common.utils.StringUtils;
/**
 * åˆ†é¡µæ•°æ®
 *
 * @author ruoyi
 */
public class PageDomain
{
    /** å½“前记录起始索引 */
    private Integer pageNum;
    /** æ¯é¡µæ˜¾ç¤ºè®°å½•æ•° */
    private Integer pageSize;
    /** æŽ’序列 */
    private String orderByColumn;
    /** æŽ’序的方向desc或者asc */
    private String isAsc = "asc";
    /** åˆ†é¡µå‚数合理化 */
    private Boolean reasonable = true;
    public String getOrderBy()
    {
        if (StringUtils.isEmpty(orderByColumn))
        {
            return "";
        }
        return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
    }
    public Integer getPageNum()
    {
        return pageNum;
    }
    public void setPageNum(Integer pageNum)
    {
        this.pageNum = pageNum;
    }
    public Integer getPageSize()
    {
        return pageSize;
    }
    public void setPageSize(Integer pageSize)
    {
        this.pageSize = pageSize;
    }
    public String getOrderByColumn()
    {
        return orderByColumn;
    }
    public void setOrderByColumn(String orderByColumn)
    {
        this.orderByColumn = orderByColumn;
    }
    public String getIsAsc()
    {
        return isAsc;
    }
    public void setIsAsc(String isAsc)
    {
        if (StringUtils.isNotEmpty(isAsc))
        {
            // å…¼å®¹å‰ç«¯æŽ’序类型
            if ("ascending".equals(isAsc))
            {
                isAsc = "asc";
            }
            else if ("descending".equals(isAsc))
            {
                isAsc = "desc";
            }
            this.isAsc = isAsc;
        }
    }
    public Boolean getReasonable()
    {
        if (StringUtils.isNull(reasonable))
        {
            return Boolean.TRUE;
        }
        return reasonable;
    }
    public void setReasonable(Boolean reasonable)
    {
        this.reasonable = reasonable;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
package com.ruoyi.common.core.page;
import java.io.Serializable;
import java.util.List;
/**
 * è¡¨æ ¼åˆ†é¡µæ•°æ®å¯¹è±¡
 *
 * @author ruoyi
 */
public class TableDataInfo implements Serializable
{
    private static final long serialVersionUID = 1L;
    /** æ€»è®°å½•æ•° */
    private long total;
    /** åˆ—表数据 */
    private List<?> rows;
    /** æ¶ˆæ¯çŠ¶æ€ç  */
    private int code;
    /** æ¶ˆæ¯å†…容 */
    private String msg;
    /**
     * è¡¨æ ¼æ•°æ®å¯¹è±¡
     */
    public TableDataInfo()
    {
    }
    /**
     * åˆ†é¡µ
     *
     * @param list åˆ—表数据
     * @param total æ€»è®°å½•æ•°
     */
    public TableDataInfo(List<?> list, long total)
    {
        this.rows = list;
        this.total = total;
    }
    public long getTotal()
    {
        return total;
    }
    public void setTotal(long total)
    {
        this.total = total;
    }
    public List<?> getRows()
    {
        return rows;
    }
    public void setRows(List<?> rows)
    {
        this.rows = rows;
    }
    public int getCode()
    {
        return code;
    }
    public void setCode(int code)
    {
        this.code = code;
    }
    public String getMsg()
    {
        return msg;
    }
    public void setMsg(String msg)
    {
        this.msg = msg;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.ruoyi.common.core.page;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.ServletUtils;
/**
 * è¡¨æ ¼æ•°æ®å¤„理
 *
 * @author ruoyi
 */
public class TableSupport
{
    /**
     * å½“前记录起始索引
     */
    public static final String PAGE_NUM = "pageNum";
    /**
     * æ¯é¡µæ˜¾ç¤ºè®°å½•æ•°
     */
    public static final String PAGE_SIZE = "pageSize";
    /**
     * æŽ’序列
     */
    public static final String ORDER_BY_COLUMN = "orderByColumn";
    /**
     * æŽ’序的方向 "desc" æˆ–者 "asc".
     */
    public static final String IS_ASC = "isAsc";
    /**
     * åˆ†é¡µå‚数合理化
     */
    public static final String REASONABLE = "reasonable";
    /**
     * å°è£…分页对象
     */
    public static PageDomain getPageDomain()
    {
        PageDomain pageDomain = new PageDomain();
        pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
        pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
        pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
        pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
        pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
        return pageDomain;
    }
    public static PageDomain buildPageRequest()
    {
        return getPageDomain();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,269 @@
package com.ruoyi.common.core.redis;
import java.time.Duration;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
/**
 * spring redis å·¥å…·ç±»
 *
 * @author ruoyi
 **/
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{
    @Autowired
    public RedisTemplate redisTemplate;
    /**
     * ç¼“存基本的对象,Integer、String、实体类等
     *
     * @param key ç¼“存的键值
     * @param value ç¼“存的值
     */
    public <T> void setCacheObject(final String key, final T value)
    {
        redisTemplate.opsForValue().set(key, value);
    }
    /**
     * ç¼“存基本的对象,Integer、String、实体类等
     *
     * @param key ç¼“存的键值
     * @param value ç¼“存的值
     * @param timeout æ—¶é—´
     * @param timeUnit æ—¶é—´é¢—粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
    {
        redisTemplate.opsForValue().set(key, value, Duration.of(timeout, timeUnit.toChronoUnit()));
    }
    /**
     * è®¾ç½®æœ‰æ•ˆæ—¶é—´
     *
     * @param key Redis键
     * @param timeout è¶…æ—¶æ—¶é—´
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout)
    {
        return expire(key, timeout, TimeUnit.SECONDS);
    }
    /**
     * è®¾ç½®æœ‰æ•ˆæ—¶é—´
     *
     * @param key Redis键
     * @param timeout è¶…æ—¶æ—¶é—´
     * @param unit æ—¶é—´å•位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit)
    {
        return redisTemplate.expire(key, Duration.of(timeout, unit.toChronoUnit()));
    }
    /**
     * èŽ·å–æœ‰æ•ˆæ—¶é—´
     *
     * @param key Redis键
     * @return æœ‰æ•ˆæ—¶é—´
     */
    public long getExpire(final String key)
    {
        return redisTemplate.getExpire(key);
    }
    /**
     * åˆ¤æ–­ key是否存在
     *
     * @param key é”®
     * @return true å­˜åœ¨ false不存在
     */
    public Boolean hasKey(String key)
    {
        return redisTemplate.hasKey(key);
    }
    /**
     * èŽ·å¾—ç¼“å­˜çš„åŸºæœ¬å¯¹è±¡ã€‚
     *
     * @param key ç¼“存键值
     * @return ç¼“存键值对应的数据
     */
    public <T> T getCacheObject(final String key)
    {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }
    /**
     * åˆ é™¤å•个对象
     *
     * @param key
     */
    public boolean deleteObject(final String key)
    {
        return redisTemplate.delete(key);
    }
    /**
     * åˆ é™¤é›†åˆå¯¹è±¡
     *
     * @param collection å¤šä¸ªå¯¹è±¡
     * @return
     */
    public boolean deleteObject(final Collection collection)
    {
        return redisTemplate.delete(collection) > 0;
    }
    /**
     * ç¼“å­˜List数据
     *
     * @param key ç¼“存的键值
     * @param dataList å¾…缓存的List数据
     * @return ç¼“存的对象
     */
    public <T> long setCacheList(final String key, final List<T> dataList)
    {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    }
    /**
     * èŽ·å¾—ç¼“å­˜çš„list对象
     *
     * @param key ç¼“存的键值
     * @return ç¼“存键值对应的数据
     */
    public <T> List<T> getCacheList(final String key)
    {
        return redisTemplate.opsForList().range(key, 0, -1);
    }
    /**
     * ç¼“å­˜Set
     *
     * @param key ç¼“存键值
     * @param dataSet ç¼“存的数据
     * @return ç¼“存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
    {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext())
        {
            setOperation.add(it.next());
        }
        return setOperation;
    }
    /**
     * èŽ·å¾—ç¼“å­˜çš„set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(final String key)
    {
        return redisTemplate.opsForSet().members(key);
    }
    /**
     * ç¼“å­˜Map
     *
     * @param key
     * @param dataMap
     */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
    {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }
    /**
     * èŽ·å¾—ç¼“å­˜çš„Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(final String key)
    {
        return redisTemplate.opsForHash().entries(key);
    }
    /**
     * å¾€Hash中存入数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @param value å€¼
     */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value)
    {
        redisTemplate.opsForHash().put(key, hKey, value);
    }
    /**
     * èŽ·å–Hash中的数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public <T> T getCacheMapValue(final String key, final String hKey)
    {
        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    }
    /**
     * èŽ·å–å¤šä¸ªHash中的数据
     *
     * @param key Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
    {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }
    /**
     * åˆ é™¤Hash中的某条数据
     *
     * @param key Redis键
     * @param hKey Hash键
     * @return æ˜¯å¦æˆåŠŸ
     */
    public boolean deleteCacheMapValue(final String key, final String hKey)
    {
        return redisTemplate.opsForHash().delete(key, hKey) > 0;
    }
    /**
     * èŽ·å¾—ç¼“å­˜çš„åŸºæœ¬å¯¹è±¡åˆ—è¡¨
     *
     * @param pattern å­—符串前缀
     * @return å¯¹è±¡åˆ—表
     */
    public Collection<String> keys(final String pattern)
    {
        return redisTemplate.keys(pattern);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,86 @@
package com.ruoyi.common.core.text;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import com.ruoyi.common.utils.StringUtils;
/**
 * å­—符集工具类
 *
 * @author ruoyi
 */
public class CharsetKit
{
    /** ISO-8859-1 */
    public static final String ISO_8859_1 = "ISO-8859-1";
    /** UTF-8 */
    public static final String UTF_8 = "UTF-8";
    /** GBK */
    public static final String GBK = "GBK";
    /** ISO-8859-1 */
    public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
    /** UTF-8 */
    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
    /** GBK */
    public static final Charset CHARSET_GBK = Charset.forName(GBK);
    /**
     * è½¬æ¢ä¸ºCharset对象
     *
     * @param charset å­—符集,为空则返回默认字符集
     * @return Charset
     */
    public static Charset charset(String charset)
    {
        return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
    }
    /**
     * è½¬æ¢å­—符串的字符集编码
     *
     * @param source å­—符串
     * @param srcCharset æºå­—符集,默认ISO-8859-1
     * @param destCharset ç›®æ ‡å­—符集,默认UTF-8
     * @return è½¬æ¢åŽçš„字符集
     */
    public static String convert(String source, String srcCharset, String destCharset)
    {
        return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
    }
    /**
     * è½¬æ¢å­—符串的字符集编码
     *
     * @param source å­—符串
     * @param srcCharset æºå­—符集,默认ISO-8859-1
     * @param destCharset ç›®æ ‡å­—符集,默认UTF-8
     * @return è½¬æ¢åŽçš„字符集
     */
    public static String convert(String source, Charset srcCharset, Charset destCharset)
    {
        if (null == srcCharset)
        {
            srcCharset = StandardCharsets.ISO_8859_1;
        }
        if (null == destCharset)
        {
            destCharset = StandardCharsets.UTF_8;
        }
        if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
        {
            return source;
        }
        return new String(source.getBytes(srcCharset), destCharset);
    }
    /**
     * @return ç³»ç»Ÿå­—符集编码
     */
    public static String systemCharset()
    {
        return Charset.defaultCharset().name();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1018 @@
package com.ruoyi.common.core.text;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.Set;
import com.ruoyi.common.utils.StringUtils;
/**
 * ç±»åž‹è½¬æ¢å™¨
 *
 * @author ruoyi
 */
public class Convert
{
    /**
     * è½¬æ¢ä¸ºå­—符串<br>
     * å¦‚果给定的值为null,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static String toStr(Object value, String defaultValue)
    {
        if (null == value)
        {
            return defaultValue;
        }
        if (value instanceof String)
        {
            return (String) value;
        }
        return value.toString();
    }
    /**
     * è½¬æ¢ä¸ºå­—符串<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String toStr(Object value)
    {
        return toStr(value, null);
    }
    /**
     * è½¬æ¢ä¸ºå­—符<br>
     * å¦‚果给定的值为null,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Character toChar(Object value, Character defaultValue)
    {
        if (null == value)
        {
            return defaultValue;
        }
        if (value instanceof Character)
        {
            return (Character) value;
        }
        final String valueStr = toStr(value, null);
        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
    }
    /**
     * è½¬æ¢ä¸ºå­—符<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Character toChar(Object value)
    {
        return toChar(value, null);
    }
    /**
     * è½¬æ¢ä¸ºbyte<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Byte toByte(Object value, Byte defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Byte)
        {
            return (Byte) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).byteValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Byte.parseByte(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºbyte<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Byte toByte(Object value)
    {
        return toByte(value, null);
    }
    /**
     * è½¬æ¢ä¸ºShort<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Short toShort(Object value, Short defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Short)
        {
            return (Short) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).shortValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Short.parseShort(valueStr.trim());
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºShort<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Short toShort(Object value)
    {
        return toShort(value, null);
    }
    /**
     * è½¬æ¢ä¸ºNumber<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Number toNumber(Object value, Number defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Number)
        {
            return (Number) value;
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return NumberFormat.getInstance().parse(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºNumber<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Number toNumber(Object value)
    {
        return toNumber(value, null);
    }
    /**
     * è½¬æ¢ä¸ºint<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Integer toInt(Object value, Integer defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Integer)
        {
            return (Integer) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).intValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Integer.parseInt(valueStr.trim());
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºint<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer toInt(Object value)
    {
        return toInt(value, null);
    }
    /**
     * è½¬æ¢ä¸ºInteger数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer[] toIntArray(String str)
    {
        return toIntArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºLong数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long[] toLongArray(String str)
    {
        return toLongArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºInteger数组<br>
     *
     * @param split åˆ†éš”符
     * @param split è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Integer[] toIntArray(String split, String str)
    {
        if (StringUtils.isEmpty(str))
        {
            return new Integer[] {};
        }
        String[] arr = str.split(split);
        final Integer[] ints = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++)
        {
            final Integer v = toInt(arr[i], 0);
            ints[i] = v;
        }
        return ints;
    }
    /**
     * è½¬æ¢ä¸ºLong数组<br>
     *
     * @param split åˆ†éš”符
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long[] toLongArray(String split, String str)
    {
        if (StringUtils.isEmpty(str))
        {
            return new Long[] {};
        }
        String[] arr = str.split(split);
        final Long[] longs = new Long[arr.length];
        for (int i = 0; i < arr.length; i++)
        {
            final Long v = toLong(arr[i], null);
            longs[i] = v;
        }
        return longs;
    }
    /**
     * è½¬æ¢ä¸ºString数组<br>
     *
     * @param str è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String[] toStrArray(String str)
    {
        if (StringUtils.isEmpty(str))
        {
            return new String[] {};
        }
        return toStrArray(",", str);
    }
    /**
     * è½¬æ¢ä¸ºString数组<br>
     *
     * @param split åˆ†éš”符
     * @param split è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static String[] toStrArray(String split, String str)
    {
        return str.split(split);
    }
    /**
     * è½¬æ¢ä¸ºlong<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Long toLong(Object value, Long defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Long)
        {
            return (Long) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).longValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            // æ”¯æŒç§‘学计数法
            return new BigDecimal(valueStr.trim()).longValue();
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºlong<br>
     * å¦‚果给定的值为<code>null</code>,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Long toLong(Object value)
    {
        return toLong(value, null);
    }
    /**
     * è½¬æ¢ä¸ºdouble<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Double toDouble(Object value, Double defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Double)
        {
            return (Double) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).doubleValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            // æ”¯æŒç§‘学计数法
            return new BigDecimal(valueStr.trim()).doubleValue();
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºdouble<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Double toDouble(Object value)
    {
        return toDouble(value, null);
    }
    /**
     * è½¬æ¢ä¸ºFloat<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Float toFloat(Object value, Float defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Float)
        {
            return (Float) value;
        }
        if (value instanceof Number)
        {
            return ((Number) value).floatValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Float.parseFloat(valueStr.trim());
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºFloat<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Float toFloat(Object value)
    {
        return toFloat(value, null);
    }
    /**
     * è½¬æ¢ä¸ºboolean<br>
     * String支持的值为:true、false、yes、ok、no、1、0、是、否, å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static Boolean toBool(Object value, Boolean defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof Boolean)
        {
            return (Boolean) value;
        }
        String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        valueStr = valueStr.trim().toLowerCase();
        switch (valueStr)
        {
            case "true":
            case "yes":
            case "ok":
            case "1":
            case "是":
                return true;
            case "false":
            case "no":
            case "0":
            case "否":
                return false;
            default:
                return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºboolean<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static Boolean toBool(Object value)
    {
        return toBool(value, null);
    }
    /**
     * è½¬æ¢ä¸ºEnum对象<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     *
     * @param clazz Enum的Class
     * @param value å€¼
     * @param defaultValue é»˜è®¤å€¼
     * @return Enum
     */
    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (clazz.isAssignableFrom(value.getClass()))
        {
            @SuppressWarnings("unchecked")
            E myE = (E) value;
            return myE;
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return Enum.valueOf(clazz, valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºEnum对象<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     *
     * @param clazz Enum的Class
     * @param value å€¼
     * @return Enum
     */
    public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
    {
        return toEnum(clazz, value, null);
    }
    /**
     * è½¬æ¢ä¸ºBigInteger<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof BigInteger)
        {
            return (BigInteger) value;
        }
        if (value instanceof Long)
        {
            return BigInteger.valueOf((Long) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return new BigInteger(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºBigInteger<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<code>null</code><br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static BigInteger toBigInteger(Object value)
    {
        return toBigInteger(value, null);
    }
    /**
     * è½¬æ¢ä¸ºBigDecimal<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @param defaultValue è½¬æ¢é”™è¯¯æ—¶çš„默认值
     * @return ç»“æžœ
     */
    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
    {
        if (value == null)
        {
            return defaultValue;
        }
        if (value instanceof BigDecimal)
        {
            return (BigDecimal) value;
        }
        if (value instanceof Long)
        {
            return new BigDecimal((Long) value);
        }
        if (value instanceof Double)
        {
            return BigDecimal.valueOf((Double) value);
        }
        if (value instanceof Integer)
        {
            return new BigDecimal((Integer) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr))
        {
            return defaultValue;
        }
        try
        {
            return new BigDecimal(valueStr);
        }
        catch (Exception e)
        {
            return defaultValue;
        }
    }
    /**
     * è½¬æ¢ä¸ºBigDecimal<br>
     * å¦‚果给定的值为空,或者转换失败,返回默认值<br>
     * è½¬æ¢å¤±è´¥ä¸ä¼šæŠ¥é”™
     *
     * @param value è¢«è½¬æ¢çš„值
     * @return ç»“æžœ
     */
    public static BigDecimal toBigDecimal(Object value)
    {
        return toBigDecimal(value, null);
    }
    /**
     * å°†å¯¹è±¡è½¬ä¸ºå­—符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj å¯¹è±¡
     * @return å­—符串
     */
    public static String utf8Str(Object obj)
    {
        return str(obj, CharsetKit.CHARSET_UTF_8);
    }
    /**
     * å°†å¯¹è±¡è½¬ä¸ºå­—符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj å¯¹è±¡
     * @param charsetName å­—符集
     * @return å­—符串
     */
    public static String str(Object obj, String charsetName)
    {
        return str(obj, Charset.forName(charsetName));
    }
    /**
     * å°†å¯¹è±¡è½¬ä¸ºå­—符串<br>
     * 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
     *
     * @param obj å¯¹è±¡
     * @param charset å­—符集
     * @return å­—符串
     */
    public static String str(Object obj, Charset charset)
    {
        if (null == obj)
        {
            return null;
        }
        if (obj instanceof String)
        {
            return (String) obj;
        }
        else if (obj instanceof byte[] || obj instanceof Byte[])
        {
            if (obj instanceof byte[])
            {
                return str((byte[]) obj, charset);
            }
            else
            {
                Byte[] bytes = (Byte[]) obj;
                int length = bytes.length;
                byte[] dest = new byte[length];
                for (int i = 0; i < length; i++)
                {
                    dest[i] = bytes[i];
                }
                return str(dest, charset);
            }
        }
        else if (obj instanceof ByteBuffer)
        {
            return str((ByteBuffer) obj, charset);
        }
        return obj.toString();
    }
    /**
     * å°†byte数组转为字符串
     *
     * @param bytes byte数组
     * @param charset å­—符集
     * @return å­—符串
     */
    public static String str(byte[] bytes, String charset)
    {
        return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
    }
    /**
     * è§£ç å­—节码
     *
     * @param data å­—符串
     * @param charset å­—符集,如果此字段为空,则解码的结果取决于平台
     * @return è§£ç åŽçš„字符串
     */
    public static String str(byte[] data, Charset charset)
    {
        if (data == null)
        {
            return null;
        }
        if (null == charset)
        {
            return new String(data);
        }
        return new String(data, charset);
    }
    /**
     * å°†ç¼–码的byteBuffer数据转换为字符串
     *
     * @param data æ•°æ®
     * @param charset å­—符集,如果为空使用当前系统字符集
     * @return å­—符串
     */
    public static String str(ByteBuffer data, String charset)
    {
        if (data == null)
        {
            return null;
        }
        return str(data, Charset.forName(charset));
    }
    /**
     * å°†ç¼–码的byteBuffer数据转换为字符串
     *
     * @param data æ•°æ®
     * @param charset å­—符集,如果为空使用当前系统字符集
     * @return å­—符串
     */
    public static String str(ByteBuffer data, Charset charset)
    {
        if (null == charset)
        {
            charset = Charset.defaultCharset();
        }
        return charset.decode(data).toString();
    }
    // ----------------------------------------------------------------------- å…¨è§’半角转换
    /**
     * åŠè§’转全角
     *
     * @param input String.
     * @return å…¨è§’字符串.
     */
    public static String toSBC(String input)
    {
        return toSBC(input, null);
    }
    /**
     * åŠè§’转全角
     *
     * @param input String
     * @param notConvertSet ä¸æ›¿æ¢çš„字符集合
     * @return å…¨è§’字符串.
     */
    public static String toSBC(String input, Set<Character> notConvertSet)
    {
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++)
        {
            if (null != notConvertSet && notConvertSet.contains(c[i]))
            {
                // è·³è¿‡ä¸æ›¿æ¢çš„字符
                continue;
            }
            if (c[i] == ' ')
            {
                c[i] = '\u3000';
            }
            else if (c[i] < '\177')
            {
                c[i] = (char) (c[i] + 65248);
            }
        }
        return new String(c);
    }
    /**
     * å…¨è§’转半角
     *
     * @param input String.
     * @return åŠè§’字符串
     */
    public static String toDBC(String input)
    {
        return toDBC(input, null);
    }
    /**
     * æ›¿æ¢å…¨è§’为半角
     *
     * @param text æ–‡æœ¬
     * @param notConvertSet ä¸æ›¿æ¢çš„字符集合
     * @return æ›¿æ¢åŽçš„字符
     */
    public static String toDBC(String text, Set<Character> notConvertSet)
    {
        char[] c = text.toCharArray();
        for (int i = 0; i < c.length; i++)
        {
            if (null != notConvertSet && notConvertSet.contains(c[i]))
            {
                // è·³è¿‡ä¸æ›¿æ¢çš„字符
                continue;
            }
            if (c[i] == '\u3000')
            {
                c[i] = ' ';
            }
            else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
            {
                c[i] = (char) (c[i] - 65248);
            }
        }
        return new String(c);
    }
    /**
     * æ•°å­—金额大写转换 å…ˆå†™ä¸ªå®Œæ•´çš„然后将如零拾替换成零
     *
     * @param n æ•°å­—
     * @return ä¸­æ–‡å¤§å†™æ•°å­—
     */
    public static String digitUppercase(double n)
    {
        String[] fraction = { "角", "分" };
        String[] digit = { "零", "壹", "è´°", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
        String[][] unit = { { "元", "万", "亿" }, { "", "拾", "ä½°", "仟" } };
        String head = n < 0 ? "负" : "";
        n = Math.abs(n);
        String s = "";
        for (int i = 0; i < fraction.length; i++)
        {
            // ä¼˜åŒ–double计算精度丢失问题
            BigDecimal nNum = new BigDecimal(n);
            BigDecimal decimal = new BigDecimal(10);
            BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
            double d = scale.doubleValue();
            s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "");
        }
        if (s.length() < 1)
        {
            s = "整";
        }
        int integerPart = (int) Math.floor(n);
        for (int i = 0; i < unit[0].length && integerPart > 0; i++)
        {
            String p = "";
            for (int j = 0; j < unit[1].length && n > 0; j++)
            {
                p = digit[integerPart % 10] + unit[1][j] + p;
                integerPart = integerPart / 10;
            }
            s = p.replaceAll("(零.)*零$", "").replaceAll("^$", "零") + unit[0][i] + s;
        }
        return head + s.replaceAll("(零.)*零元", "元").replaceFirst("(零.)+", "").replaceAll("(零.)+", "零").replaceAll("^整$", "零元整");
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
package com.ruoyi.common.core.text;
import com.ruoyi.common.utils.StringUtils;
/**
 * å­—符串格式化
 *
 * @author ruoyi
 */
public class StrFormatter
{
    public static final String EMPTY_JSON = "{}";
    public static final char C_BACKSLASH = '\\';
    public static final char C_DELIM_START = '{';
    public static final char C_DELIM_END = '}';
    /**
     * æ ¼å¼åŒ–字符串<br>
     * æ­¤æ–¹æ³•只是简单将占位符 {} æŒ‰ç…§é¡ºåºæ›¿æ¢ä¸ºå‚æ•°<br>
     * å¦‚果想输出 {} ä½¿ç”¨ \\转义 { å³å¯ï¼Œå¦‚果想输出 {} ä¹‹å‰çš„ \ ä½¿ç”¨åŒè½¬ä¹‰ç¬¦ \\\\ å³å¯<br>
     * ä¾‹ï¼š<br>
     * é€šå¸¸ä½¿ç”¨ï¼šformat("this is {} for {}", "a", "b") -> this is a for b<br>
     * è½¬ä¹‰{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * è½¬ä¹‰\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     *
     * @param strPattern å­—符串模板
     * @param argArray å‚数列表
     * @return ç»“æžœ
     */
    public static String format(final String strPattern, final Object... argArray)
    {
        if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
        {
            return strPattern;
        }
        final int strPatternLength = strPattern.length();
        // åˆå§‹åŒ–定义好的长度以获得更好的性能
        StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
        int handledPosition = 0;
        int delimIndex;// å ä½ç¬¦æ‰€åœ¨ä½ç½®
        for (int argIndex = 0; argIndex < argArray.length; argIndex++)
        {
            delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
            if (delimIndex == -1)
            {
                if (handledPosition == 0)
                {
                    return strPattern;
                }
                else
                { // å­—符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
                    sbuf.append(strPattern, handledPosition, strPatternLength);
                    return sbuf.toString();
                }
            }
            else
            {
                if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
                {
                    if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
                    {
                        // è½¬ä¹‰ç¬¦ä¹‹å‰è¿˜æœ‰ä¸€ä¸ªè½¬ä¹‰ç¬¦ï¼Œå ä½ç¬¦ä¾æ—§æœ‰æ•ˆ
                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
                        sbuf.append(Convert.utf8Str(argArray[argIndex]));
                        handledPosition = delimIndex + 2;
                    }
                    else
                    {
                        // å ä½ç¬¦è¢«è½¬ä¹‰
                        argIndex--;
                        sbuf.append(strPattern, handledPosition, delimIndex - 1);
                        sbuf.append(C_DELIM_START);
                        handledPosition = delimIndex + 1;
                    }
                }
                else
                {
                    // æ­£å¸¸å ä½ç¬¦
                    sbuf.append(strPattern, handledPosition, delimIndex);
                    sbuf.append(Convert.utf8Str(argArray[argIndex]));
                    handledPosition = delimIndex + 2;
                }
            }
        }
        // åŠ å…¥æœ€åŽä¸€ä¸ªå ä½ç¬¦åŽæ‰€æœ‰çš„å­—ç¬¦
        sbuf.append(strPattern, handledPosition, strPattern.length());
        return sbuf.toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.ruoyi.common.enums;
/**
 * æ“ä½œçŠ¶æ€
 *
 * @author ruoyi
 *
 */
public enum BusinessStatus
{
    /**
     * æˆåŠŸ
     */
    SUCCESS,
    /**
     * å¤±è´¥
     */
    FAIL,
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package com.ruoyi.common.enums;
/**
 * ä¸šåŠ¡æ“ä½œç±»åž‹
 *
 * @author ruoyi
 */
public enum BusinessType
{
    /**
     * å…¶å®ƒ
     */
    OTHER,
    /**
     * æ–°å¢ž
     */
    INSERT,
    /**
     * ä¿®æ”¹
     */
    UPDATE,
    /**
     * åˆ é™¤
     */
    DELETE,
    /**
     * æŽˆæƒ
     */
    GRANT,
    /**
     * å¯¼å‡º
     */
    EXPORT,
    /**
     * å¯¼å…¥
     */
    IMPORT,
    /**
     * å¼ºé€€
     */
    FORCE,
    /**
     * ç”Ÿæˆä»£ç 
     */
    GENCODE,
    /**
     * æ¸…空数据
     */
    CLEAN,
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.ruoyi.common.enums;
/**
 * æ•°æ®æº
 *
 * @author ruoyi
 */
public enum DataSourceType
{
    /**
     * ä¸»åº“
     */
    MASTER,
    /**
     * ä»Žåº“
     */
    SLAVE
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
package com.ruoyi.common.enums;
import java.util.function.Function;
import com.ruoyi.common.utils.DesensitizedUtil;
/**
 * è„±æ•ç±»åž‹
 *
 * @author ruoyi
 */
public enum DesensitizedType
{
    /**
     * å§“名,第2位星号替换
     */
    USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
    /**
     * å¯†ç ï¼Œå…¨éƒ¨å­—符都用*代替
     */
    PASSWORD(DesensitizedUtil::password),
    /**
     * èº«ä»½è¯ï¼Œä¸­é—´10位星号替换
     */
    ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
    /**
     * æ‰‹æœºå·ï¼Œä¸­é—´4位星号替换
     */
    PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
    /**
     * ç”µå­é‚®ç®±ï¼Œä»…显示第一个字母和@后面的地址显示,其他星号替换
     */
    EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
    /**
     * é“¶è¡Œå¡å·ï¼Œä¿ç•™æœ€åŽ4位,其他星号替换
     */
    BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
    /**
     * è½¦ç‰Œå·ç ï¼ŒåŒ…含普通车辆、新能源车辆
     */
    CAR_LICENSE(DesensitizedUtil::carLicense);
    private final Function<String, String> desensitizer;
    DesensitizedType(Function<String, String> desensitizer)
    {
        this.desensitizer = desensitizer;
    }
    public Function<String, String> desensitizer()
    {
        return desensitizer;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,36 @@
package com.ruoyi.common.enums;
import java.util.HashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
/**
 * è¯·æ±‚方式
 *
 * @author ruoyi
 */
public enum HttpMethod
{
    GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
    private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
    static
    {
        for (HttpMethod httpMethod : values())
        {
            mappings.put(httpMethod.name(), httpMethod);
        }
    }
    @Nullable
    public static HttpMethod resolve(@Nullable String method)
    {
        return (method != null ? mappings.get(method) : null);
    }
    public boolean matches(String method)
    {
        return (this == resolve(method));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
package com.ruoyi.common.enums;
/**
 * é™æµç±»åž‹
 *
 * @author ruoyi
 */
public enum LimitType
{
    /**
     * é»˜è®¤ç­–略全局限流
     */
    DEFAULT,
    /**
     * æ ¹æ®è¯·æ±‚者IP进行限流
     */
    IP
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.common.enums;
/**
 * æ“ä½œäººç±»åˆ«
 *
 * @author ruoyi
 */
public enum OperatorType
{
    /**
     * å…¶å®ƒ
     */
    OTHER,
    /**
     * åŽå°ç”¨æˆ·
     */
    MANAGE,
    /**
     * æ‰‹æœºç«¯ç”¨æˆ·
     */
    MOBILE
}
ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
package com.ruoyi.common.enums;
/**
 * ç”¨æˆ·çŠ¶æ€
 *
 * @author ruoyi
 */
public enum UserStatus
{
    OK("0", "正常"), DISABLE("1", "停用"), DELETED("2", "删除");
    private final String code;
    private final String info;
    UserStatus(String code, String info)
    {
        this.code = code;
        this.info = info;
    }
    public String getCode()
    {
        return code;
    }
    public String getInfo()
    {
        return info;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.ruoyi.common.exception;
/**
 * æ¼”示模式异常
 *
 * @author ruoyi
 */
public class DemoModeException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    public DemoModeException()
    {
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,58 @@
package com.ruoyi.common.exception;
/**
 * å…¨å±€å¼‚常
 *
 * @author ruoyi
 */
public class GlobalException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    /**
     * é”™è¯¯æç¤º
     */
    private String message;
    /**
     * é”™è¯¯æ˜Žç»†ï¼Œå†…部调试错误
     *
     * å’Œ {@link CommonResult#getDetailMessage()} ä¸€è‡´çš„设计
     */
    private String detailMessage;
    /**
     * ç©ºæž„造方法,避免反序列化问题
     */
    public GlobalException()
    {
    }
    public GlobalException(String message)
    {
        this.message = message;
    }
    public String getDetailMessage()
    {
        return detailMessage;
    }
    public GlobalException setDetailMessage(String detailMessage)
    {
        this.detailMessage = detailMessage;
        return this;
    }
    @Override
    public String getMessage()
    {
        return message;
    }
    public GlobalException setMessage(String message)
    {
        this.message = message;
        return this;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
package com.ruoyi.common.exception;
/**
 * ä¸šåС异叏
 *
 * @author ruoyi
 */
public final class ServiceException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    /**
     * é”™è¯¯ç 
     */
    private Integer code;
    /**
     * é”™è¯¯æç¤º
     */
    private String message;
    /**
     * é”™è¯¯æ˜Žç»†ï¼Œå†…部调试错误
     *
     * å’Œ {@link CommonResult#getDetailMessage()} ä¸€è‡´çš„设计
     */
    private String detailMessage;
    /**
     * ç©ºæž„造方法,避免反序列化问题
     */
    public ServiceException()
    {
    }
    public ServiceException(String message)
    {
        this.message = message;
    }
    public ServiceException(String message, Integer code)
    {
        this.message = message;
        this.code = code;
    }
    public String getDetailMessage()
    {
        return detailMessage;
    }
    @Override
    public String getMessage()
    {
        return message;
    }
    public Integer getCode()
    {
        return code;
    }
    public ServiceException setMessage(String message)
    {
        this.message = message;
        return this;
    }
    public ServiceException setDetailMessage(String detailMessage)
    {
        this.detailMessage = detailMessage;
        return this;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.common.exception;
/**
 * å·¥å…·ç±»å¼‚常
 *
 * @author ruoyi
 */
public class UtilException extends RuntimeException
{
    private static final long serialVersionUID = 8247610319171014183L;
    public UtilException(Throwable e)
    {
        super(e.getMessage(), e);
    }
    public UtilException(String message)
    {
        super(message);
    }
    public UtilException(String message, Throwable throwable)
    {
        super(message, throwable);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,97 @@
package com.ruoyi.common.exception.base;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.StringUtils;
/**
 * åŸºç¡€å¼‚常
 *
 * @author ruoyi
 */
public class BaseException extends RuntimeException
{
    private static final long serialVersionUID = 1L;
    /**
     * æ‰€å±žæ¨¡å—
     */
    private String module;
    /**
     * é”™è¯¯ç 
     */
    private String code;
    /**
     * é”™è¯¯ç å¯¹åº”的参数
     */
    private Object[] args;
    /**
     * é”™è¯¯æ¶ˆæ¯
     */
    private String defaultMessage;
    public BaseException(String module, String code, Object[] args, String defaultMessage)
    {
        this.module = module;
        this.code = code;
        this.args = args;
        this.defaultMessage = defaultMessage;
    }
    public BaseException(String module, String code, Object[] args)
    {
        this(module, code, args, null);
    }
    public BaseException(String module, String defaultMessage)
    {
        this(module, null, null, defaultMessage);
    }
    public BaseException(String code, Object[] args)
    {
        this(null, code, args, null);
    }
    public BaseException(String defaultMessage)
    {
        this(null, null, null, defaultMessage);
    }
    @Override
    public String getMessage()
    {
        String message = null;
        if (!StringUtils.isEmpty(code))
        {
            message = MessageUtils.message(code, args);
        }
        if (message == null)
        {
            message = defaultMessage;
        }
        return message;
    }
    public String getModule()
    {
        return module;
    }
    public String getCode()
    {
        return code;
    }
    public Object[] getArgs()
    {
        return args;
    }
    public String getDefaultMessage()
    {
        return defaultMessage;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.ruoyi.common.exception.file;
import com.ruoyi.common.exception.base.BaseException;
/**
 * æ–‡ä»¶ä¿¡æ¯å¼‚常类
 *
 * @author ruoyi
 */
public class FileException extends BaseException
{
    private static final long serialVersionUID = 1L;
    public FileException(String code, Object[] args)
    {
        super("file", code, args, null);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.file;
/**
 * æ–‡ä»¶åç§°è¶…长限制异常类
 *
 * @author ruoyi
 */
public class FileNameLengthLimitExceededException extends FileException
{
    private static final long serialVersionUID = 1L;
    public FileNameLengthLimitExceededException(int defaultFileNameLength)
    {
        super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.file;
/**
 * æ–‡ä»¶åå¤§å°é™åˆ¶å¼‚常类
 *
 * @author ruoyi
 */
public class FileSizeLimitExceededException extends FileException
{
    private static final long serialVersionUID = 1L;
    public FileSizeLimitExceededException(long defaultMaxSize)
    {
        super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,80 @@
package com.ruoyi.common.exception.file;
import java.util.Arrays;
/**
 * æ–‡ä»¶ä¸Šä¼ æ— æ•ˆæ‰©å±•名异常类
 *
 * @author ruoyi
 */
public class InvalidExtensionException extends FileUploadException
{
    private static final long serialVersionUID = 1L;
    private String[] allowedExtension;
    private String extension;
    private String filename;
    public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
    {
        super("文件[" + filename + "]后缀[" + extension + "]不正确,请上传" + Arrays.toString(allowedExtension) + "格式");
        this.allowedExtension = allowedExtension;
        this.extension = extension;
        this.filename = filename;
    }
    public String[] getAllowedExtension()
    {
        return allowedExtension;
    }
    public String getExtension()
    {
        return extension;
    }
    public String getFilename()
    {
        return filename;
    }
    public static class InvalidImageExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
    public static class InvalidFlashExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
    public static class InvalidMediaExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
    public static class InvalidVideoExtensionException extends InvalidExtensionException
    {
        private static final long serialVersionUID = 1L;
        public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
        {
            super(allowedExtension, extension, filename);
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.ruoyi.common.exception.job;
/**
 * è®¡åˆ’策略异常
 *
 * @author ruoyi
 */
public class TaskException extends Exception
{
    private static final long serialVersionUID = 1L;
    private Code code;
    public TaskException(String msg, Code code)
    {
        this(msg, code, null);
    }
    public TaskException(String msg, Code code, Exception nestedEx)
    {
        super(msg, nestedEx);
        this.code = code;
    }
    public Code getCode()
    {
        return code;
    }
    public enum Code
    {
        TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
 * éªŒè¯ç é”™è¯¯å¼‚常类
 *
 * @author ruoyi
 */
public class CaptchaException extends UserException
{
    private static final long serialVersionUID = 1L;
    public CaptchaException()
    {
        super("user.jcaptcha.error", null);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
 * éªŒè¯ç å¤±æ•ˆå¼‚常类
 *
 * @author ruoyi
 */
public class CaptchaExpireException extends UserException
{
    private static final long serialVersionUID = 1L;
    public CaptchaExpireException()
    {
        super("user.jcaptcha.expire", null);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.common.exception.user;
import com.ruoyi.common.exception.base.BaseException;
/**
 * ç”¨æˆ·ä¿¡æ¯å¼‚常类
 *
 * @author ruoyi
 */
public class UserException extends BaseException
{
    private static final long serialVersionUID = 1L;
    public UserException(String code, Object[] args)
    {
        super("user", code, args, null);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
 * ç”¨æˆ·å¯†ç ä¸æ­£ç¡®æˆ–不符合规范异常类
 *
 * @author ruoyi
 */
public class UserPasswordNotMatchException extends UserException
{
    private static final long serialVersionUID = 1L;
    public UserPasswordNotMatchException()
    {
        super("user.password.not.match", null);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.ruoyi.common.exception.user;
/**
 * ç”¨æˆ·é”™è¯¯æœ€å¤§æ¬¡æ•°å¼‚常类
 *
 * @author ruoyi
 */
public class UserPasswordRetryLimitExceedException extends UserException
{
    private static final long serialVersionUID = 1L;
    public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
    {
        super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.common.filter;
import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
/**
 * æŽ’除JSON敏感属性
 *
 * @author ruoyi
 */
public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
{
    public PropertyPreExcludeFilter()
    {
    }
    public PropertyPreExcludeFilter addExcludes(String... filters)
    {
        for (int i = 0; i < filters.length; i++)
        {
            this.getExcludes().add(filters[i]);
        }
        return this;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/filter/RefererFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,77 @@
package com.ruoyi.common.filter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
 * é˜²ç›—链过滤器
 *
 * @author ruoyi
 */
public class RefererFilter implements Filter
{
    /**
     * å…è®¸çš„域名列表
     */
    public List<String> allowedDomains;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        String domains = filterConfig.getInitParameter("allowedDomains");
        this.allowedDomains = Arrays.asList(domains.split(","));
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String referer = req.getHeader("Referer");
        // å¦‚æžœReferer为空,拒绝访问
        if (referer == null || referer.isEmpty())
        {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer header is required");
            return;
        }
        // æ£€æŸ¥Referer是否在允许的域名列表中
        boolean allowed = false;
        for (String domain : allowedDomains)
        {
            if (referer.contains(domain))
            {
                allowed = true;
                break;
            }
        }
        // æ ¹æ®æ£€æŸ¥ç»“果决定是否放行
        if (allowed)
        {
            chain.doFilter(request, response);
        }
        else
        {
            resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied: Referer '" + referer + "' is not allowed");
        }
    }
    @Override
    public void destroy()
    {
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
package com.ruoyi.common.filter;
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType;
import com.ruoyi.common.utils.StringUtils;
/**
 * Repeatable è¿‡æ»¤å™¨
 *
 * @author ruoyi
 */
public class RepeatableFilter implements Filter
{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest
                && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
        {
            requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
        }
        if (null == requestWrapper)
        {
            chain.doFilter(request, response);
        }
        else
        {
            chain.doFilter(requestWrapper, response);
        }
    }
    @Override
    public void destroy()
    {
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.ruoyi.common.filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import com.ruoyi.common.utils.http.HttpHelper;
import com.ruoyi.common.constant.Constants;
/**
 * æž„建可重复读取inputStream的request
 *
 * @author ruoyi
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
{
    private final byte[] body;
    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
    {
        super(request);
        request.setCharacterEncoding(Constants.UTF8);
        response.setCharacterEncoding(Constants.UTF8);
        body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
    }
    @Override
    public BufferedReader getReader() throws IOException
    {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }
    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream()
        {
            @Override
            public int read() throws IOException
            {
                return bais.read();
            }
            @Override
            public int available() throws IOException
            {
                return body.length;
            }
            @Override
            public boolean isFinished()
            {
                return false;
            }
            @Override
            public boolean isReady()
            {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener)
            {
            }
        };
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,75 @@
package com.ruoyi.common.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.enums.HttpMethod;
/**
 * é˜²æ­¢XSS攻击的过滤器
 *
 * @author ruoyi
 */
public class XssFilter implements Filter
{
    /**
     * æŽ’除链接
     */
    public List<String> excludes = new ArrayList<>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        String tempExcludes = filterConfig.getInitParameter("excludes");
        if (StringUtils.isNotEmpty(tempExcludes))
        {
            String[] urls = tempExcludes.split(",");
            for (String url : urls)
            {
                excludes.add(url);
            }
        }
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        if (handleExcludeURL(req, resp))
        {
            chain.doFilter(request, response);
            return;
        }
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(xssRequest, response);
    }
    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
    {
        String url = request.getServletPath();
        String method = request.getMethod();
        // GET DELETE ä¸è¿‡æ»¤
        if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
        {
            return true;
        }
        return StringUtils.matches(url, excludes);
    }
    @Override
    public void destroy()
    {
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
package com.ruoyi.common.filter;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.html.EscapeUtil;
/**
 * XSS过滤处理
 *
 * @author ruoyi
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
    /**
     * @param request
     */
    public XssHttpServletRequestWrapper(HttpServletRequest request)
    {
        super(request);
    }
    @Override
    public String[] getParameterValues(String name)
    {
        String[] values = super.getParameterValues(name);
        if (values != null)
        {
            int length = values.length;
            String[] escapesValues = new String[length];
            for (int i = 0; i < length; i++)
            {
                // é˜²xss攻击和过滤前后空格
                escapesValues[i] = EscapeUtil.clean(values[i]).trim();
            }
            return escapesValues;
        }
        return super.getParameterValues(name);
    }
    @Override
    public ServletInputStream getInputStream() throws IOException
    {
        // éžjson类型,直接返回
        if (!isJsonRequest())
        {
            return super.getInputStream();
        }
        // ä¸ºç©ºï¼Œç›´æŽ¥è¿”回
        String json = IOUtils.toString(super.getInputStream(), "utf-8");
        if (StringUtils.isEmpty(json))
        {
            return super.getInputStream();
        }
        // xss过滤
        json = EscapeUtil.clean(json).trim();
        byte[] jsonBytes = json.getBytes("utf-8");
        final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
        return new ServletInputStream()
        {
            @Override
            public boolean isFinished()
            {
                return true;
            }
            @Override
            public boolean isReady()
            {
                return true;
            }
            @Override
            public int available() throws IOException
            {
                return jsonBytes.length;
            }
            @Override
            public void setReadListener(ReadListener readListener)
            {
            }
            @Override
            public int read() throws IOException
            {
                return bis.read();
            }
        };
    }
    /**
     * æ˜¯å¦æ˜¯Json请求
     *
     * @param request
     */
    public boolean isJsonRequest()
    {
        String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
        return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
package com.ruoyi.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
 * ç²¾ç¡®çš„æµ®ç‚¹æ•°è¿ç®—
 *
 * @author ruoyi
 */
public class Arith
{
    /** é»˜è®¤é™¤æ³•运算精度 */
    private static final int DEF_DIV_SCALE = 10;
    /** è¿™ä¸ªç±»ä¸èƒ½å®žä¾‹åŒ– */
    private Arith()
    {
    }
    /**
     * æä¾›ç²¾ç¡®çš„加法运算。
     * @param v1 è¢«åŠ æ•°
     * @param v2 åŠ æ•°
     * @return ä¸¤ä¸ªå‚数的和
     */
    public static double add(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }
    /**
     * æä¾›ç²¾ç¡®çš„减法运算。
     * @param v1 è¢«å‡æ•°
     * @param v2 å‡æ•°
     * @return ä¸¤ä¸ªå‚数的差
     */
    public static double sub(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }
    /**
     * æä¾›ç²¾ç¡®çš„乘法运算。
     * @param v1 è¢«ä¹˜æ•°
     * @param v2 ä¹˜æ•°
     * @return ä¸¤ä¸ªå‚数的积
     */
    public static double mul(double v1, double v2)
    {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }
    /**
     * æä¾›ï¼ˆç›¸å¯¹ï¼‰ç²¾ç¡®çš„除法运算,当发生除不尽的情况时,精确到
     * å°æ•°ç‚¹ä»¥åŽ10位,以后的数字四舍五入。
     * @param v1 è¢«é™¤æ•°
     * @param v2 é™¤æ•°
     * @return ä¸¤ä¸ªå‚数的商
     */
    public static double div(double v1, double v2)
    {
        return div(v1, v2, DEF_DIV_SCALE);
    }
    /**
     * æä¾›ï¼ˆç›¸å¯¹ï¼‰ç²¾ç¡®çš„除法运算。当发生除不尽的情况时,由scale参数指
     * å®šç²¾åº¦ï¼Œä»¥åŽçš„æ•°å­—四舍五入。
     * @param v1 è¢«é™¤æ•°
     * @param v2 é™¤æ•°
     * @param scale è¡¨ç¤ºè¡¨ç¤ºéœ€è¦ç²¾ç¡®åˆ°å°æ•°ç‚¹ä»¥åŽå‡ ä½ã€‚
     * @return ä¸¤ä¸ªå‚数的商
     */
    public static double div(double v1, double v2, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        if (b1.compareTo(BigDecimal.ZERO) == 0)
        {
            return BigDecimal.ZERO.doubleValue();
        }
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }
    /**
     * æä¾›ç²¾ç¡®çš„小数位四舍五入处理。
     * @param v éœ€è¦å››èˆäº”入的数字
     * @param scale å°æ•°ç‚¹åŽä¿ç•™å‡ ä½
     * @return å››èˆäº”入后的结果
     */
    public static double round(double v, int scale)
    {
        if (scale < 0)
        {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        return b.divide(BigDecimal.ONE, scale, RoundingMode.HALF_UP).doubleValue();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,192 @@
package com.ruoyi.common.utils;
import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
 * æ—¶é—´å·¥å…·ç±»
 *
 * @author ruoyi
 */
@SuppressWarnings("deprecation")
public class DateUtils extends org.apache.commons.lang3.time.DateUtils
{
    public static String YYYY = "yyyy";
    public static String YYYY_MM = "yyyy-MM";
    public static String YYYY_MM_DD = "yyyy-MM-dd";
    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
    /**
     * èŽ·å–å½“å‰Date型日期
     *
     * @return Date() å½“前日期
     */
    public static Date getNowDate()
    {
        return new Date();
    }
    /**
     * èŽ·å–å½“å‰æ—¥æœŸ, é»˜è®¤æ ¼å¼ä¸ºyyyy-MM-dd
     *
     * @return String
     */
    public static String getDate()
    {
        return dateTimeNow(YYYY_MM_DD);
    }
    public static final String getTime()
    {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }
    public static final String dateTimeNow()
    {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }
    public static final String dateTimeNow(final String format)
    {
        return parseDateToStr(format, new Date());
    }
    public static final String dateTime(final Date date)
    {
        return parseDateToStr(YYYY_MM_DD, date);
    }
    public static final String parseDateToStr(final String format, final Date date)
    {
        return new SimpleDateFormat(format).format(date);
    }
    public static final Date dateTime(final String format, final String ts)
    {
        try
        {
            return new SimpleDateFormat(format).parse(ts);
        }
        catch (ParseException e)
        {
            throw new RuntimeException(e);
        }
    }
    /**
     * æ—¥æœŸè·¯å¾„ å³å¹´/月/日 å¦‚2018/08/08
     */
    public static final String datePath()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }
    /**
     * æ—¥æœŸè·¯å¾„ å³å¹´/月/日 å¦‚20180808
     */
    public static final String dateTime()
    {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }
    /**
     * æ—¥æœŸåž‹å­—符串转化为日期 æ ¼å¼
     */
    public static Date parseDate(Object str)
    {
        if (str == null)
        {
            return null;
        }
        try
        {
            return parseDate(str.toString(), parsePatterns);
        }
        catch (ParseException e)
        {
            return null;
        }
    }
    /**
     * èŽ·å–æœåŠ¡å™¨å¯åŠ¨æ—¶é—´
     */
    public static Date getServerStartDate()
    {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }
    /**
     * è®¡ç®—相差天数
     */
    public static int differentDaysByMillisecond(Date date1, Date date2)
    {
        return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
    }
    /**
     * è®¡ç®—æ—¶é—´å·®
     *
     * @param endDate æœ€åŽæ—¶é—´
     * @param startTime å¼€å§‹æ—¶é—´
     * @return æ—¶é—´å·®ï¼ˆå¤©/小时/分钟)
     */
    public static String timeDistance(Date endDate, Date startTime)
    {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // èŽ·å¾—ä¸¤ä¸ªæ—¶é—´çš„æ¯«ç§’æ—¶é—´å·®å¼‚
        long diff = endDate.getTime() - startTime.getTime();
        // è®¡ç®—差多少天
        long day = diff / nd;
        // è®¡ç®—差多少小时
        long hour = diff % nd / nh;
        // è®¡ç®—差多少分钟
        long min = diff % nd % nh / nm;
        // è®¡ç®—差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }
    /**
     * å¢žåŠ  LocalDateTime ==> Date
     */
    public static Date toDate(LocalDateTime temporalAccessor)
    {
        ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
    /**
     * å¢žåŠ  LocalDate ==> Date
     */
    public static Date toDate(LocalDate temporalAccessor)
    {
        LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
        ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,217 @@
package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson2.JSONArray;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
 * å­—典工具类
 *
 * @author ruoyi
 */
public class DictUtils
{
    /**
     * åˆ†éš”符
     */
    public static final String SEPARATOR = ",";
    /**
     * è®¾ç½®å­—典缓存
     *
     * @param key å‚æ•°é”®
     * @param dictDatas å­—典数据列表
     */
    public static void setDictCache(String key, List<SysDictData> dictDatas)
    {
        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
    }
    /**
     * èŽ·å–å­—å…¸ç¼“å­˜
     *
     * @param key å‚æ•°é”®
     * @return dictDatas å­—典数据列表
     */
    public static List<SysDictData> getDictCache(String key)
    {
        JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
        if (StringUtils.isNotNull(arrayCache))
        {
            return arrayCache.toList(SysDictData.class);
        }
        return null;
    }
    /**
     * æ ¹æ®å­—典类型和字典值获取字典标签
     *
     * @param dictType å­—典类型
     * @param dictValue å­—典值
     * @return å­—典标签
     */
    public static String getDictLabel(String dictType, String dictValue)
    {
        if (StringUtils.isEmpty(dictValue))
        {
            return StringUtils.EMPTY;
        }
        return getDictLabel(dictType, dictValue, SEPARATOR);
    }
    /**
     * æ ¹æ®å­—典类型和字典标签获取字典值
     *
     * @param dictType å­—典类型
     * @param dictLabel å­—典标签
     * @return å­—典值
     */
    public static String getDictValue(String dictType, String dictLabel)
    {
        if (StringUtils.isEmpty(dictLabel))
        {
            return StringUtils.EMPTY;
        }
        return getDictValue(dictType, dictLabel, SEPARATOR);
    }
    /**
     * æ ¹æ®å­—典类型和字典值获取字典标签
     *
     * @param dictType å­—典类型
     * @param dictValue å­—典值
     * @param separator åˆ†éš”符
     * @return å­—典标签
     */
    public static String getDictLabel(String dictType, String dictValue, String separator)
    {
        List<SysDictData> datas = getDictCache(dictType);
        if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictValue))
        {
            return StringUtils.EMPTY;
        }
        Map<String, String> dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictValue(), dict.getDictLabel()), Map::putAll);
        if (!StringUtils.contains(dictValue, separator))
        {
            return dictMap.getOrDefault(dictValue, StringUtils.EMPTY);
        }
        StringBuilder labelBuilder = new StringBuilder();
        for (String seperatedValue : dictValue.split(separator))
        {
            if (dictMap.containsKey(seperatedValue))
            {
                labelBuilder.append(dictMap.get(seperatedValue)).append(separator);
            }
        }
        return StringUtils.removeEnd(labelBuilder.toString(), separator);
    }
    /**
     * æ ¹æ®å­—典类型和字典标签获取字典值
     *
     * @param dictType å­—典类型
     * @param dictLabel å­—典标签
     * @param separator åˆ†éš”符
     * @return å­—典值
     */
    public static String getDictValue(String dictType, String dictLabel, String separator)
    {
        List<SysDictData> datas = getDictCache(dictType);
        if (StringUtils.isNull(datas) || StringUtils.isEmpty(dictLabel))
        {
            return StringUtils.EMPTY;
        }
        Map<String, String> dictMap = datas.stream().collect(HashMap::new, (map, dict) -> map.put(dict.getDictLabel(), dict.getDictValue()), Map::putAll);
        if (!StringUtils.contains(dictLabel, separator))
        {
            return dictMap.getOrDefault(dictLabel, StringUtils.EMPTY);
        }
        StringBuilder valueBuilder = new StringBuilder();
        for (String seperatedValue : dictLabel.split(separator))
        {
            if (dictMap.containsKey(seperatedValue))
            {
                valueBuilder.append(dictMap.get(seperatedValue)).append(separator);
            }
        }
        return StringUtils.removeEnd(valueBuilder.toString(), separator);
    }
    /**
     * æ ¹æ®å­—典类型获取字典所有值
     *
     * @param dictType å­—典类型
     * @return å­—典值
     */
    public static String getDictValues(String dictType)
    {
        StringBuilder propertyString = new StringBuilder();
        List<SysDictData> datas = getDictCache(dictType);
        if (StringUtils.isNull(datas))
        {
            return StringUtils.EMPTY;
        }
        for (SysDictData dict : datas)
        {
            propertyString.append(dict.getDictValue()).append(SEPARATOR);
        }
        return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
    }
    /**
     * æ ¹æ®å­—典类型获取字典所有标签
     *
     * @param dictType å­—典类型
     * @return å­—典值
     */
    public static String getDictLabels(String dictType)
    {
        StringBuilder propertyString = new StringBuilder();
        List<SysDictData> datas = getDictCache(dictType);
        if (StringUtils.isNull(datas))
        {
            return StringUtils.EMPTY;
        }
        for (SysDictData dict : datas)
        {
            propertyString.append(dict.getDictLabel()).append(SEPARATOR);
        }
        return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
    }
    /**
     * åˆ é™¤æŒ‡å®šå­—典缓存
     *
     * @param key å­—典键
     */
    public static void removeDictCache(String key)
    {
        SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
    }
    /**
     * æ¸…空字典缓存
     */
    public static void clearDictCache()
    {
        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*");
        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
    }
    /**
     * è®¾ç½®cache key
     *
     * @param configKey å‚æ•°é”®
     * @return ç¼“存键key
     */
    public static String getCacheKey(String configKey)
    {
        return CacheConstants.SYS_DICT_KEY + configKey;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
package com.ruoyi.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.apache.commons.lang3.exception.ExceptionUtils;
/**
 * é”™è¯¯ä¿¡æ¯å¤„理类。
 *
 * @author ruoyi
 */
public class ExceptionUtil
{
    /**
     * èŽ·å–exception的详细错误信息。
     */
    public static String getExceptionMessage(Throwable e)
    {
        StringWriter sw = new StringWriter();
        e.printStackTrace(new PrintWriter(sw, true));
        return sw.toString();
    }
    public static String getRootErrorMessage(Exception e)
    {
        Throwable root = ExceptionUtils.getRootCause(e);
        root = (root == null ? e : root);
        if (root == null)
        {
            return "";
        }
        String msg = root.getMessage();
        if (msg == null)
        {
            return "null";
        }
        return StringUtils.defaultString(msg);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.common.utils;
/**
 * å¤„理并记录日志文件
 *
 * @author ruoyi
 */
public class LogUtils
{
    public static String getBlock(Object msg)
    {
        if (msg == null)
        {
            msg = "";
        }
        return "[" + msg.toString() + "]";
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.common.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.ruoyi.common.utils.spring.SpringUtils;
/**
 * èŽ·å–i18n资源文件
 *
 * @author ruoyi
 */
public class MessageUtils
{
    /**
     * æ ¹æ®æ¶ˆæ¯é”®å’Œå‚æ•° èŽ·å–æ¶ˆæ¯ å§”托给spring messageSource
     *
     * @param code æ¶ˆæ¯é”®
     * @param args å‚æ•°
     * @return èŽ·å–å›½é™…åŒ–ç¿»è¯‘å€¼
     */
    public static String message(String code, Object... args)
    {
        MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
        return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
package com.ruoyi.common.utils;
import com.github.pagehelper.PageHelper;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.sql.SqlUtil;
/**
 * åˆ†é¡µå·¥å…·ç±»
 *
 * @author ruoyi
 */
public class PageUtils extends PageHelper
{
    /**
     * è®¾ç½®è¯·æ±‚分页数据
     */
    public static void startPage()
    {
        PageDomain pageDomain = TableSupport.buildPageRequest();
        Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
        String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
        Boolean reasonable = pageDomain.getReasonable();
        PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
    }
    /**
     * æ¸…理分页的线程变量
     */
    public static void clearPage()
    {
        PageHelper.clearPage();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,188 @@
package com.ruoyi.common.utils;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.util.PatternMatchUtils;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
/**
 * å®‰å…¨æœåŠ¡å·¥å…·ç±»
 *
 * @author ruoyi
 */
public class SecurityUtils
{
    /**
     * ç”¨æˆ·ID
     **/
    public static Long getUserId()
    {
        try
        {
            return getLoginUser().getUserId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–éƒ¨é—¨ID
     **/
    public static Long getDeptId()
    {
        try
        {
            return getLoginUser().getDeptId();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–ç”¨æˆ·è´¦æˆ·
     **/
    public static String getUsername()
    {
        try
        {
            return getLoginUser().getUsername();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–ç”¨æˆ·
     **/
    public static LoginUser getLoginUser()
    {
        try
        {
            return (LoginUser) getAuthentication().getPrincipal();
        }
        catch (Exception e)
        {
            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
        }
    }
    /**
     * èŽ·å–Authentication
     */
    public static Authentication getAuthentication()
    {
        return SecurityContextHolder.getContext().getAuthentication();
    }
    /**
     * ç”ŸæˆBCryptPasswordEncoder密码
     *
     * @param password å¯†ç 
     * @return åŠ å¯†å­—ç¬¦ä¸²
     */
    public static String encryptPassword(String password)
    {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.encode(password);
    }
    /**
     * åˆ¤æ–­å¯†ç æ˜¯å¦ç›¸åŒ
     *
     * @param rawPassword çœŸå®žå¯†ç 
     * @param encodedPassword åŠ å¯†åŽå­—ç¬¦
     * @return ç»“æžœ
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword)
    {
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder.matches(rawPassword, encodedPassword);
    }
    /**
     * æ˜¯å¦ä¸ºç®¡ç†å‘˜
     *
     * @return ç»“æžœ
     */
    public static boolean isAdmin()
    {
        return isAdmin(getUserId());
    }
    /**
     * æ˜¯å¦ä¸ºç®¡ç†å‘˜
     *
     * @param userId ç”¨æˆ·ID
     * @return ç»“æžœ
     */
    public static boolean isAdmin(Long userId)
    {
        return userId != null && 1L == userId;
    }
    /**
     * éªŒè¯ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™
     *
     * @param permission æƒé™å­—符串
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™
     */
    public static boolean hasPermi(String permission)
    {
        return hasPermi(getLoginUser().getPermissions(), permission);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦åŒ…含权限
     *
     * @param authorities æƒé™åˆ—表
     * @param permission æƒé™å­—符串
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸæƒé™
     */
    public static boolean hasPermi(Collection<String> authorities, String permission)
    {
        return authorities.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
    }
    /**
     * éªŒè¯ç”¨æˆ·æ˜¯å¦æ‹¥æœ‰æŸä¸ªè§’色
     *
     * @param role è§’色标识
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸè§’色
     */
    public static boolean hasRole(String role)
    {
        List<SysRole> roleList = getLoginUser().getUser().getRoles();
        Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
        return hasRole(roles, role);
    }
    /**
     * åˆ¤æ–­æ˜¯å¦åŒ…含角色
     *
     * @param roles è§’色列表
     * @param role è§’色
     * @return ç”¨æˆ·æ˜¯å¦å…·å¤‡æŸè§’色权限
     */
    public static boolean hasRole(Collection<String> roles, String role)
    {
        return roles.stream().filter(StringUtils::hasText)
                .anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,218 @@
package com.ruoyi.common.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.Convert;
/**
 * å®¢æˆ·ç«¯å·¥å…·ç±»
 *
 * @author ruoyi
 */
public class ServletUtils
{
    /**
     * èŽ·å–String参数
     */
    public static String getParameter(String name)
    {
        return getRequest().getParameter(name);
    }
    /**
     * èŽ·å–String参数
     */
    public static String getParameter(String name, String defaultValue)
    {
        return Convert.toStr(getRequest().getParameter(name), defaultValue);
    }
    /**
     * èŽ·å–Integer参数
     */
    public static Integer getParameterToInt(String name)
    {
        return Convert.toInt(getRequest().getParameter(name));
    }
    /**
     * èŽ·å–Integer参数
     */
    public static Integer getParameterToInt(String name, Integer defaultValue)
    {
        return Convert.toInt(getRequest().getParameter(name), defaultValue);
    }
    /**
     * èŽ·å–Boolean参数
     */
    public static Boolean getParameterToBool(String name)
    {
        return Convert.toBool(getRequest().getParameter(name));
    }
    /**
     * èŽ·å–Boolean参数
     */
    public static Boolean getParameterToBool(String name, Boolean defaultValue)
    {
        return Convert.toBool(getRequest().getParameter(name), defaultValue);
    }
    /**
     * èŽ·å¾—æ‰€æœ‰è¯·æ±‚å‚æ•°
     *
     * @param request è¯·æ±‚对象{@link ServletRequest}
     * @return Map
     */
    public static Map<String, String[]> getParams(ServletRequest request)
    {
        final Map<String, String[]> map = request.getParameterMap();
        return Collections.unmodifiableMap(map);
    }
    /**
     * èŽ·å¾—æ‰€æœ‰è¯·æ±‚å‚æ•°
     *
     * @param request è¯·æ±‚对象{@link ServletRequest}
     * @return Map
     */
    public static Map<String, String> getParamMap(ServletRequest request)
    {
        Map<String, String> params = new HashMap<>();
        for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
        {
            params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
        }
        return params;
    }
    /**
     * èŽ·å–request
     */
    public static HttpServletRequest getRequest()
    {
        return getRequestAttributes().getRequest();
    }
    /**
     * èŽ·å–response
     */
    public static HttpServletResponse getResponse()
    {
        return getRequestAttributes().getResponse();
    }
    /**
     * èŽ·å–session
     */
    public static HttpSession getSession()
    {
        return getRequest().getSession();
    }
    public static ServletRequestAttributes getRequestAttributes()
    {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        return (ServletRequestAttributes) attributes;
    }
    /**
     * å°†å­—符串渲染到客户端
     *
     * @param response æ¸²æŸ“对象
     * @param string å¾…渲染的字符串
     */
    public static void renderString(HttpServletResponse response, String string)
    {
        try
        {
            response.setStatus(200);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            response.getWriter().print(string);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    /**
     * æ˜¯å¦æ˜¯Ajax异步请求
     *
     * @param request
     */
    public static boolean isAjaxRequest(HttpServletRequest request)
    {
        String accept = request.getHeader("accept");
        if (accept != null && accept.contains("application/json"))
        {
            return true;
        }
        String xRequestedWith = request.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
        {
            return true;
        }
        String uri = request.getRequestURI();
        if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
        {
            return true;
        }
        String ajax = request.getParameter("__ajax");
        return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
    }
    /**
     * å†…容编码
     *
     * @param str å†…容
     * @return ç¼–码后的内容
     */
    public static String urlEncode(String str)
    {
        try
        {
            return URLEncoder.encode(str, Constants.UTF8);
        }
        catch (UnsupportedEncodingException e)
        {
            return StringUtils.EMPTY;
        }
    }
    /**
     * å†…容解码
     *
     * @param str å†…容
     * @return è§£ç åŽçš„内容
     */
    public static String urlDecode(String str)
    {
        try
        {
            return URLDecoder.decode(str, Constants.UTF8);
        }
        catch (UnsupportedEncodingException e)
        {
            return StringUtils.EMPTY;
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,921 @@
package com.ruoyi.common.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.Strings;
import org.springframework.util.AntPathMatcher;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter;
/**
 * å­—符串工具类
 *
 * @author ruoyi
 */
@SuppressWarnings("deprecation")
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
    /** ç©ºå­—符串 */
    private static final String NULLSTR = "";
    /** ä¸‹åˆ’线 */
    private static final char SEPARATOR = '_';
    /** æ˜Ÿå· */
    private static final char ASTERISK = '*';
    /**
     * èŽ·å–å‚æ•°ä¸ä¸ºç©ºå€¼
     *
     * @param value defaultValue è¦åˆ¤æ–­çš„value
     * @return value è¿”回值
     */
    public static <T> T nvl(T value, T defaultValue)
    {
        return value != null ? value : defaultValue;
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªCollection是否为空, åŒ…含List,Set,Queue
     *
     * @param coll è¦åˆ¤æ–­çš„Collection
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(Collection<?> coll)
    {
        return isNull(coll) || coll.isEmpty();
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªCollection是否非空,包含List,Set,Queue
     *
     * @param coll è¦åˆ¤æ–­çš„Collection
     * @return true:非空 false:空
     */
    public static boolean isNotEmpty(Collection<?> coll)
    {
        return !isEmpty(coll);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ•°ç»„是否为空
     *
     * @param objects è¦åˆ¤æ–­çš„对象数组
     ** @return true:为空 false:非空
     */
    public static boolean isEmpty(Object[] objects)
    {
        return isNull(objects) || (objects.length == 0);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ•°ç»„是否非空
     *
     * @param objects è¦åˆ¤æ–­çš„对象数组
     * @return true:非空 false:空
     */
    public static boolean isNotEmpty(Object[] objects)
    {
        return !isEmpty(objects);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªMap是否为空
     *
     * @param map è¦åˆ¤æ–­çš„Map
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(Map<?, ?> map)
    {
        return isNull(map) || map.isEmpty();
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªMap是否为空
     *
     * @param map è¦åˆ¤æ–­çš„Map
     * @return true:非空 false:空
     */
    public static boolean isNotEmpty(Map<?, ?> map)
    {
        return !isEmpty(map);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå­—符串是否为空串
     *
     * @param str String
     * @return true:为空 false:非空
     */
    public static boolean isEmpty(String str)
    {
        return isNull(str) || NULLSTR.equals(str.trim());
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå­—符串是否为非空串
     *
     * @param str String
     * @return true:非空串 false:空串
     */
    public static boolean isNotEmpty(String str)
    {
        return !isEmpty(str);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦ä¸ºç©º
     *
     * @param object Object
     * @return true:为空 false:非空
     */
    public static boolean isNull(Object object)
    {
        return object == null;
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦éžç©º
     *
     * @param object Object
     * @return true:非空 false:空
     */
    public static boolean isNotNull(Object object)
    {
        return !isNull(object);
    }
    /**
     * * åˆ¤æ–­ä¸€ä¸ªå¯¹è±¡æ˜¯å¦æ˜¯æ•°ç»„类型(Java基本型别的数组)
     *
     * @param object å¯¹è±¡
     * @return true:是数组 false:不是数组
     */
    public static boolean isArray(Object object)
    {
        return isNotNull(object) && object.getClass().isArray();
    }
    /**
     * åŽ»ç©ºæ ¼
     */
    public static String trim(String str)
    {
        return (str == null ? "" : str.trim());
    }
    /**
     * æ›¿æ¢æŒ‡å®šå­—符串的指定区间内字符为"*"
     *
     * @param str å­—符串
     * @param startInclude å¼€å§‹ä½ç½®ï¼ˆåŒ…含)
     * @param endExclude ç»“束位置(不包含)
     * @return æ›¿æ¢åŽçš„字符串
     */
    public static String hide(CharSequence str, int startInclude, int endExclude)
    {
        if (isEmpty(str))
        {
            return NULLSTR;
        }
        final int strLength = str.length();
        if (startInclude > strLength)
        {
            return NULLSTR;
        }
        if (endExclude > strLength)
        {
            endExclude = strLength;
        }
        if (startInclude > endExclude)
        {
            // å¦‚果起始位置大于结束位置,不替换
            return NULLSTR;
        }
        final char[] chars = new char[strLength];
        for (int i = 0; i < strLength; i++)
        {
            if (i >= startInclude && i < endExclude)
            {
                chars[i] = ASTERISK;
            }
            else
            {
                chars[i] = str.charAt(i);
            }
        }
        return new String(chars);
    }
    /**
     * æˆªå–字符串
     *
     * @param str å­—符串
     * @param start å¼€å§‹
     * @return ç»“æžœ
     */
    public static String substring(final String str, int start)
    {
        if (str == null)
        {
            return NULLSTR;
        }
        if (start < 0)
        {
            start = str.length() + start;
        }
        if (start < 0)
        {
            start = 0;
        }
        if (start > str.length())
        {
            return NULLSTR;
        }
        return str.substring(start);
    }
    /**
     * æˆªå–字符串
     *
     * @param str å­—符串
     * @param start å¼€å§‹
     * @param end ç»“束
     * @return ç»“æžœ
     */
    public static String substring(final String str, int start, int end)
    {
        if (str == null)
        {
            return NULLSTR;
        }
        if (end < 0)
        {
            end = str.length() + end;
        }
        if (start < 0)
        {
            start = str.length() + start;
        }
        if (end > str.length())
        {
            end = str.length();
        }
        if (start > end)
        {
            return NULLSTR;
        }
        if (start < 0)
        {
            start = 0;
        }
        if (end < 0)
        {
            end = 0;
        }
        return str.substring(start, end);
    }
    /**
     * åœ¨å­—符串中查找第一个出现的 `open` å’Œæœ€åŽä¸€ä¸ªå‡ºçŽ°çš„ `close` ä¹‹é—´çš„子字符串
     *
     * @param str è¦æˆªå–的字符串
     * @param open èµ·å§‹å­—符串
     * @param close ç»“束字符串
     * @return æˆªå–结果
     */
    public static String substringBetweenLast(final String str, final String open, final String close)
    {
        if (isEmpty(str) || isEmpty(open) || isEmpty(close))
        {
            return NULLSTR;
        }
        final int start = str.indexOf(open);
        if (start != INDEX_NOT_FOUND)
        {
            final int end = str.lastIndexOf(close);
            if (end != INDEX_NOT_FOUND)
            {
                return str.substring(start + open.length(), end);
            }
        }
        return NULLSTR;
    }
    /**
     * åˆ¤æ–­æ˜¯å¦ä¸ºç©ºï¼Œå¹¶ä¸”不是空白字符
     *
     * @param str è¦åˆ¤æ–­çš„value
     * @return ç»“æžœ
     */
    public static boolean hasText(String str)
    {
        return (str != null && !str.isEmpty() && containsText(str));
    }
    private static boolean containsText(CharSequence str)
    {
        int strLen = str.length();
        for (int i = 0; i < strLen; i++)
        {
            if (!Character.isWhitespace(str.charAt(i)))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * æ ¼å¼åŒ–文本, {} è¡¨ç¤ºå ä½ç¬¦<br>
     * æ­¤æ–¹æ³•只是简单将占位符 {} æŒ‰ç…§é¡ºåºæ›¿æ¢ä¸ºå‚æ•°<br>
     * å¦‚果想输出 {} ä½¿ç”¨ \\转义 { å³å¯ï¼Œå¦‚果想输出 {} ä¹‹å‰çš„ \ ä½¿ç”¨åŒè½¬ä¹‰ç¬¦ \\\\ å³å¯<br>
     * ä¾‹ï¼š<br>
     * é€šå¸¸ä½¿ç”¨ï¼šformat("this is {} for {}", "a", "b") -> this is a for b<br>
     * è½¬ä¹‰{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
     * è½¬ä¹‰\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
     *
     * @param template æ–‡æœ¬æ¨¡æ¿ï¼Œè¢«æ›¿æ¢çš„部分用 {} è¡¨ç¤º
     * @param params å‚数值
     * @return æ ¼å¼åŒ–后的文本
     */
    public static String format(String template, Object... params)
    {
        if (isEmpty(params) || isEmpty(template))
        {
            return template;
        }
        return StrFormatter.format(template, params);
    }
    /**
     * æ˜¯å¦ä¸ºhttp(s)://开头
     *
     * @param link é“¾æŽ¥
     * @return ç»“æžœ
     */
    public static boolean ishttp(String link)
    {
        return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
    }
    /**
     * å­—符串转set
     *
     * @param str å­—符串
     * @param sep åˆ†éš”符
     * @return set集合
     */
    public static final Set<String> str2Set(String str, String sep)
    {
        return new HashSet<String>(str2List(str, sep, true, false));
    }
    /**
     * å­—符串转list
     *
     * @param str å­—符串
     * @param sep åˆ†éš”符
     * @return list集合
     */
    public static final List<String> str2List(String str, String sep)
    {
        return str2List(str, sep, true, false);
    }
    /**
     * å­—符串转list
     *
     * @param str å­—符串
     * @param sep åˆ†éš”符
     * @param filterBlank è¿‡æ»¤çº¯ç©ºç™½
     * @param trim åŽ»æŽ‰é¦–å°¾ç©ºç™½
     * @return list集合
     */
    public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
    {
        List<String> list = new ArrayList<String>();
        if (StringUtils.isEmpty(str))
        {
            return list;
        }
        // è¿‡æ»¤ç©ºç™½å­—符串
        if (filterBlank && StringUtils.isBlank(str))
        {
            return list;
        }
        String[] split = str.split(sep);
        for (String string : split)
        {
            if (filterBlank && StringUtils.isBlank(string))
            {
                continue;
            }
            if (trim)
            {
                string = string.trim();
            }
            list.add(string);
        }
        return list;
    }
    /**
     * æ£€æŸ¥å­å­—符串是否存在
     *
     * @param seq æ£€æŸ¥çš„字符串
     * @param searchSeq æŸ¥æ‰¾çš„字符串
     * @return ç»“æžœ
     */
    public static boolean contains(final CharSequence seq, final CharSequence searchSeq)
    {
        return Strings.CS.contains(seq, searchSeq);
    }
    /**
     * åˆ¤æ–­ç»™å®šçš„collection列表中是否包含数组array åˆ¤æ–­ç»™å®šçš„æ•°ç»„array中是否包含给定的元素value
     *
     * @param collection ç»™å®šçš„集合
     * @param array ç»™å®šçš„æ•°ç»„
     * @return ç»“æžœ
     */
    public static boolean containsAny(Collection<String> collection, String... array)
    {
        if (isEmpty(collection) || isEmpty(array))
        {
            return false;
        }
        else
        {
            for (String str : array)
            {
                if (collection.contains(str))
                {
                    return true;
                }
            }
            return false;
        }
    }
    /**
     * åˆ¤æ–­æ˜¯å¦åŒ…含给定数组中的任意一个。
     *
     * @param cs è¦åˆ¤æ–­çš„字符串
     * @param searchCharSequences è¦åˆ¤æ–­çš„æ•°ç»„
     * @return ç»“æžœ
     */
    public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences)
    {
        return Strings.CS.containsAny(cs, searchCharSequences);
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
     *
     * @param cs æŒ‡å®šå­—符串
     * @param searchCharSequences éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return æ˜¯å¦åŒ…含任意一个字符串
     */
    public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
    {
        if (isEmpty(cs) || isEmpty(searchCharSequences))
        {
            return false;
        }
        for (CharSequence testStr : searchCharSequences)
        {
            if (containsIgnoreCase(cs, testStr))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * æ£€æŸ¥æ˜¯å¦åŒ…含要搜索的字符串,忽略大小写
     *
     * @param str è¦æ£€æŸ¥çš„字符串
     * @param searchStr è¦æŸ¥æ‰¾çš„字符串
     * @return å¦‚果包含要搜索的字符串(忽略大小写)则返回true,如果不包含或返回false
     */
    public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr)
    {
        return Strings.CI.contains(str, searchStr);
    }
    /**
     * æ£€æŸ¥å­—符串是否以任意前缀开始
     *
     * @param sequence è¦æ£€æŸ¥çš„字符串
     * @param searchStrings åŒºåˆ†å¤§å°å†™çš„字符串前缀数组
     * @return ç»“æžœ
     */
    public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings)
    {
        return Strings.CS.startsWithAny(sequence, searchStrings);
    }
    /**
     * ä¸åŒºåˆ†å¤§å°å†™åœ°æ£€æŸ¥ä¸€ä¸ªå­—符串是否以指定前缀开头。
     *
     * @param str å¾…检查的字符串
     * @param è¦æŸ¥æ‰¾çš„前缀
     * @return ç»“æžœ
     */
    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix)
    {
        return Strings.CI.startsWith(str, prefix);
    }
    /**
     * æ¯”较两个字符串是否相同
     *
     * @param cs1 ç¬¬ä¸€ä¸ªå­—符串
     * @param cs2 ç¬¬äºŒä¸ªå­—符串
     * @return å¦‚果给定对象与字符串相等,则返回 true;否则返回 false
     */
    public static boolean equals(final CharSequence cs1, final CharSequence cs2)
    {
        return Strings.CS.equals(cs1, cs2);
    }
    /**
     * æ›¿æ¢å­—符串中所有匹配的字符
     *
     * @param text è¦æœç´¢å’Œæ›¿æ¢çš„æ–‡æœ¬
     * @param searchString è¦æœç´¢çš„字符串
     * @param replacement  ç”¨äºŽæ›¿æ¢çš„字符串
     * @return å¤„理完所有替换后的文本
     */
    public static String replace(final String text, final String searchString, final String replacement)
    {
        return Strings.CS.replace(text, searchString, replacement);
    }
    /**
     * ä»…当子字符串位于源字符串末尾时才将其移除,否则返回源字符串。
     * @param str è¦æœç´¢çš„æºå­—符串
     * @param remove è¦æœç´¢å¹¶ç§»é™¤çš„字符串
     * @return å¦‚果找到并移除了字符串,则返回移除后的子字符串
     */
    public static String removeEnd(final String str, final String remove)
    {
        return Strings.CS.removeEnd(str, remove);
    }
    /**
     * æŸ¥æ‰¾å­—符串首次出现位置的索引
     *
     * @param seq è¦æ£€æŸ¥çš„字符串
     * @param searchSeq è¦æŸ¥æ‰¾çš„字符串
     * @return è¿”回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1
     */
    public static int indexOf(final CharSequence seq, final CharSequence searchSeq)
    {
        return Strings.CS.indexOf(seq, searchSeq);
    }
    /**
     * æ£€æŸ¥å­—符串是否以指定的后缀结尾
     *
     * @param str è¦æ£€æŸ¥çš„字符
     * @param suffix è¦æ£€æŸ¥çš„后缀
     * @return è‹¥å‚数与该字符串末尾相符 true;否则 false
     */
    public static boolean endsWith(final CharSequence str, final CharSequence suffix)
    {
        return Strings.CS.endsWith(str, suffix);
    }
    /**
     * å°†ç»™å®šçš„字符串与数组进行比较
     *
     * @param string è¦æ¯”较的字符串
     * @param searchStrings å­—符串数组
     * @return å¦‚果字符串等于(区分大小写){@code searchStrings}中的任意其他元素,则返回true;如果{@code searchStrings}为null或不包含匹配项,则返回false
     */
    public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings)
    {
        return Strings.CS.equalsAny(string, searchStrings);
    }
    /**
     * æ£€æŸ¥ä¸€ä¸ªå­—符串是否以任意提供的区分大小写的后缀结尾。
     *
     * @param sequence è¦æ£€æŸ¥çš„字符串
     * @param searchStrings è¦æŸ¥æ‰¾çš„区分大小写的字符串数组
     * @return å¦‚果输入参数{@code sequence}为null且未提供任何{@code searchStrings},或者输入{@code sequence}以任意提供的区分大小写的{@code searchStrings}结尾,则返回{@code true}。
     */
    public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings)
    {
        return Strings.CS.endsWithAny(sequence, searchStrings);
    }
    /**
     * ä¸åŒºåˆ†å¤§å°å†™åœ°æ£€æŸ¥å­—符序列是否以指定的后缀结尾
     *
     * @param str è¦æ£€æŸ¥çš„字符序列
     * @param suffix è¦æŸ¥æ‰¾çš„后缀
     * @return å¦‚果字符序列以该后缀结尾(不区分大小写),或两者均为{@code null},则返回{@code true}
     */
    public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix)
    {
        return Strings.CI.endsWith(str, suffix);
    }
    /**
     * æŒ‡å®šèŒƒå›´å†…查找字符串,忽略大小写
     *
     * @param str è¦æ£€æŸ¥çš„字符串
     * @param searchStr è¦æŸ¥æ‰¾çš„字符串
     * @return æœç´¢å­—符串的第一个索引,如果未找到匹配项则返回 -1
     */
    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr)
    {
        return Strings.CI.indexOf(str, searchStr);
    }
    /**
     * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
     * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.
     *
     * @param string to compare, may be {@code null}.
     * @param searchStrings a vararg of strings, may be {@code null}.
     * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
     */
    public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings)
    {
        return Strings.CI.equalsAny(string, searchStrings);
    }
    /**
     * é©¼å³°è½¬ä¸‹åˆ’线命名
     */
    public static String toUnderScoreCase(String str)
    {
        if (str == null)
        {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        // å‰ç½®å­—符是否大写
        boolean preCharIsUpperCase = true;
        // å½“前字符是否大写
        boolean curreCharIsUpperCase = true;
        // ä¸‹ä¸€å­—符是否大写
        boolean nexteCharIsUpperCase = true;
        for (int i = 0; i < str.length(); i++)
        {
            char c = str.charAt(i);
            if (i > 0)
            {
                preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
            }
            else
            {
                preCharIsUpperCase = false;
            }
            curreCharIsUpperCase = Character.isUpperCase(c);
            if (i < (str.length() - 1))
            {
                nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
            }
            if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
            {
                sb.append(SEPARATOR);
            }
            else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
            {
                sb.append(SEPARATOR);
            }
            sb.append(Character.toLowerCase(c));
        }
        return sb.toString();
    }
    /**
     * æ˜¯å¦åŒ…含字符串
     *
     * @param str éªŒè¯å­—符串
     * @param strs å­—符串组
     * @return åŒ…含返回true
     */
    public static boolean inStringIgnoreCase(String str, String... strs)
    {
        if (str != null && strs != null)
        {
            for (String s : strs)
            {
                if (str.equalsIgnoreCase(trim(s)))
                {
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * åˆ é™¤æœ€åŽä¸€ä¸ªå­—符串
     *
     * @param str è¾“入字符串
     * @param spit ä»¥ä»€ä¹ˆç±»åž‹ç»“尾的
     * @return æˆªå–后的字符串
     */
    public static String lastStringDel(String str, String spit)
    {
        if (!StringUtils.isEmpty(str) && str.endsWith(spit))
        {
            return str.subSequence(0, str.length() - 1).toString();
        }
        return str;
    }
    /**
     * å°†ä¸‹åˆ’线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 ä¾‹å¦‚:HELLO_WORLD->HelloWorld
     *
     * @param name è½¬æ¢å‰çš„下划线大写方式命名的字符串
     * @return è½¬æ¢åŽçš„驼峰式命名的字符串
     */
    public static String convertToCamelCase(String name)
    {
        StringBuilder result = new StringBuilder();
        // å¿«é€Ÿæ£€æŸ¥
        if (name == null || name.isEmpty())
        {
            // æ²¡å¿…要转换
            return "";
        }
        else if (!name.contains("_"))
        {
            // ä¸å«ä¸‹åˆ’线,仅将首字母大写
            return name.substring(0, 1).toUpperCase() + name.substring(1);
        }
        // ç”¨ä¸‹åˆ’线将原始字符串分割
        String[] camels = name.split("_");
        for (String camel : camels)
        {
            // è·³è¿‡åŽŸå§‹å­—ç¬¦ä¸²ä¸­å¼€å¤´ã€ç»“å°¾çš„ä¸‹æ¢çº¿æˆ–åŒé‡ä¸‹åˆ’çº¿
            if (camel.isEmpty())
            {
                continue;
            }
            // é¦–字母大写
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }
    /**
     * é©¼å³°å¼å‘½åæ³•
     * ä¾‹å¦‚:user_name->userName
     */
    public static String toCamelCase(String s)
    {
        if (s == null)
        {
            return null;
        }
        if (s.indexOf(SEPARATOR) == -1)
        {
            return s;
        }
        s = s.toLowerCase();
        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);
            if (c == SEPARATOR)
            {
                upperCase = true;
            }
            else if (upperCase)
            {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            }
            else
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }
    /**
     * æŸ¥æ‰¾æŒ‡å®šå­—符串是否匹配指定字符串列表中的任意一个字符串
     *
     * @param str æŒ‡å®šå­—符串
     * @param strs éœ€è¦æ£€æŸ¥çš„字符串数组
     * @return æ˜¯å¦åŒ¹é…
     */
    public static boolean matches(String str, List<String> strs)
    {
        if (isEmpty(str) || isEmpty(strs))
        {
            return false;
        }
        for (String pattern : strs)
        {
            if (isMatch(pattern, str))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * åˆ¤æ–­url是否与规则配置:
     * ? è¡¨ç¤ºå•个字符;
     * * è¡¨ç¤ºä¸€å±‚路径内的任意字符串,不可跨层级;
     * ** è¡¨ç¤ºä»»æ„å±‚路径;
     *
     * @param pattern åŒ¹é…è§„则
     * @param url éœ€è¦åŒ¹é…çš„url
     * @return
     */
    public static boolean isMatch(String pattern, String url)
    {
        AntPathMatcher matcher = new AntPathMatcher();
        return matcher.match(pattern, url);
    }
    @SuppressWarnings("unchecked")
    public static <T> T cast(Object obj)
    {
        return (T) obj;
    }
    /**
     * æ•°å­—左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 æœ€åŽsize个字符。
     *
     * @param num æ•°å­—对象
     * @param size å­—符串指定长度
     * @return è¿”回数字的字符串格式,该字符串为指定长度。
     */
    public static final String padl(final Number num, final int size)
    {
        return padl(num.toString(), size, '0');
    }
    /**
     * å­—符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
     *
     * @param s åŽŸå§‹å­—ç¬¦ä¸²
     * @param size å­—符串指定长度
     * @param c ç”¨äºŽè¡¥é½çš„字符
     * @return è¿”回指定长度的字符串,由原字符串左补齐或截取得到。
     */
    public static final String padl(final String s, final int size, final char c)
    {
        final StringBuilder sb = new StringBuilder(size);
        if (s != null)
        {
            final int len = s.length();
            if (s.length() <= size)
            {
                for (int i = size - len; i > 0; i--)
                {
                    sb.append(c);
                }
                sb.append(s);
            }
            else
            {
                return s.substring(len - size, len);
            }
        }
        else
        {
            for (int i = size; i > 0; i--)
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,99 @@
package com.ruoyi.common.utils;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * çº¿ç¨‹ç›¸å…³å·¥å…·ç±».
 *
 * @author ruoyi
 */
public class Threads
{
    private static final Logger logger = LoggerFactory.getLogger(Threads.class);
    /**
     * sleep等待,单位为毫秒
     */
    public static void sleep(long milliseconds)
    {
        try
        {
            Thread.sleep(milliseconds);
        }
        catch (InterruptedException e)
        {
            return;
        }
    }
    /**
     * åœæ­¢çº¿ç¨‹æ± 
     * å…ˆä½¿ç”¨shutdown, åœæ­¢æŽ¥æ”¶æ–°ä»»åŠ¡å¹¶å°è¯•å®Œæˆæ‰€æœ‰å·²å­˜åœ¨ä»»åŠ¡.
     * å¦‚果超时, åˆ™è°ƒç”¨shutdownNow, å–消在workQueue中Pending的任务,并中断所有阻塞函数.
     * å¦‚果仍然超時,則強制退出.
     * å¦å¯¹åœ¨shutdown时线程本身被调用中断做了处理.
     */
    public static void shutdownAndAwaitTermination(ExecutorService pool)
    {
        if (pool != null && !pool.isShutdown())
        {
            pool.shutdown();
            try
            {
                if (!pool.awaitTermination(120, TimeUnit.SECONDS))
                {
                    pool.shutdownNow();
                    if (!pool.awaitTermination(120, TimeUnit.SECONDS))
                    {
                        logger.info("Pool did not terminate");
                    }
                }
            }
            catch (InterruptedException ie)
            {
                pool.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    /**
     * æ‰“印线程异常信息
     */
    public static void printException(Runnable r, Throwable t)
    {
        if (t == null && r instanceof Future<?>)
        {
            try
            {
                Future<?> future = (Future<?>) r;
                if (future.isDone())
                {
                    future.get();
                }
            }
            catch (CancellationException ce)
            {
                t = ce;
            }
            catch (ExecutionException ee)
            {
                t = ee.getCause();
            }
            catch (InterruptedException ie)
            {
                Thread.currentThread().interrupt();
            }
        }
        if (t != null)
        {
            logger.error(t.getMessage(), t);
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,110 @@
package com.ruoyi.common.utils.bean;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Bean å·¥å…·ç±»
 *
 * @author ruoyi
 */
public class BeanUtils extends org.springframework.beans.BeanUtils
{
    /** Bean方法名中属性名开始的下标 */
    private static final int BEAN_METHOD_PROP_INDEX = 3;
    /** * åŒ¹é…getter方法的正则表达式 */
    private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
    /** * åŒ¹é…setter方法的正则表达式 */
    private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
    /**
     * Bean属性复制工具方法。
     *
     * @param dest ç›®æ ‡å¯¹è±¡
     * @param src æºå¯¹è±¡
     */
    public static void copyBeanProp(Object dest, Object src)
    {
        try
        {
            copyProperties(src, dest);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    /**
     * èŽ·å–å¯¹è±¡çš„setter方法。
     *
     * @param obj å¯¹è±¡
     * @return å¯¹è±¡çš„setter方法列表
     */
    public static List<Method> getSetterMethods(Object obj)
    {
        // setter方法列表
        List<Method> setterMethods = new ArrayList<Method>();
        // èŽ·å–æ‰€æœ‰æ–¹æ³•
        Method[] methods = obj.getClass().getMethods();
        // æŸ¥æ‰¾setter方法
        for (Method method : methods)
        {
            Matcher m = SET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 1))
            {
                setterMethods.add(method);
            }
        }
        // è¿”回setter方法列表
        return setterMethods;
    }
    /**
     * èŽ·å–å¯¹è±¡çš„getter方法。
     *
     * @param obj å¯¹è±¡
     * @return å¯¹è±¡çš„getter方法列表
     */
    public static List<Method> getGetterMethods(Object obj)
    {
        // getter方法列表
        List<Method> getterMethods = new ArrayList<Method>();
        // èŽ·å–æ‰€æœ‰æ–¹æ³•
        Method[] methods = obj.getClass().getMethods();
        // æŸ¥æ‰¾getter方法
        for (Method method : methods)
        {
            Matcher m = GET_PATTERN.matcher(method.getName());
            if (m.matches() && (method.getParameterTypes().length == 0))
            {
                getterMethods.add(method);
            }
        }
        // è¿”回getter方法列表
        return getterMethods;
    }
    /**
     * æ£€æŸ¥Bean方法名中的属性名是否相等。<br>
     * å¦‚getName()和setName()属性名一样,getName()和setAge()属性名不一样。
     *
     * @param m1 æ–¹æ³•名1
     * @param m2 æ–¹æ³•名2
     * @return å±žæ€§åä¸€æ ·è¿”回true,否则返回false
     */
    public static boolean isMethodPropEquals(String m1, String m2)
    {
        return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.common.utils.bean;
import java.util.Set;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Validator;
/**
 * bean对象属性验证
 *
 * @author ruoyi
 */
public class BeanValidators
{
    public static void validateWithException(Validator validator, Object object, Class<?>... groups)
            throws ConstraintViolationException
    {
        Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
        if (!constraintViolations.isEmpty())
        {
            throw new ConstraintViolationException(constraintViolations);
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
package com.ruoyi.common.utils.file;
import java.io.File;
import org.apache.commons.lang3.StringUtils;
/**
 * æ–‡ä»¶ç±»åž‹å·¥å…·ç±»
 *
 * @author ruoyi
 */
public class FileTypeUtils
{
    /**
     * èŽ·å–æ–‡ä»¶ç±»åž‹
     * <p>
     * ä¾‹å¦‚: ruoyi.txt, è¿”回: txt
     *
     * @param file æ–‡ä»¶å
     * @return åŽç¼€ï¼ˆä¸å«".")
     */
    public static String getFileType(File file)
    {
        if (null == file)
        {
            return StringUtils.EMPTY;
        }
        return getFileType(file.getName());
    }
    /**
     * èŽ·å–æ–‡ä»¶ç±»åž‹
     * <p>
     * ä¾‹å¦‚: ruoyi.txt, è¿”回: txt
     *
     * @param fileName æ–‡ä»¶å
     * @return åŽç¼€ï¼ˆä¸å«".")
     */
    public static String getFileType(String fileName)
    {
        int separatorIndex = fileName.lastIndexOf(".");
        if (separatorIndex < 0)
        {
            return "";
        }
        return fileName.substring(separatorIndex + 1).toLowerCase();
    }
    /**
     * èŽ·å–æ–‡ä»¶ç±»åž‹
     *
     * @param photoByte æ–‡ä»¶å­—节码
     * @return åŽç¼€ï¼ˆä¸å«".")
     */
    public static String getFileExtendName(byte[] photoByte)
    {
        String strFileExtendName = "JPG";
        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
        {
            strFileExtendName = "GIF";
        }
        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
        {
            strFileExtendName = "JPG";
        }
        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
        {
            strFileExtendName = "BMP";
        }
        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
        {
            strFileExtendName = "PNG";
        }
        return strFileExtendName;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,260 @@
package com.ruoyi.common.utils.file;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.uuid.Seq;
/**
 * æ–‡ä»¶ä¸Šä¼ å·¥å…·ç±»
 *
 * @author ruoyi
 */
public class FileUploadUtils
{
    /**
     * é»˜è®¤å¤§å° 50M
     */
    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
    /**
     * é»˜è®¤çš„æ–‡ä»¶åæœ€å¤§é•¿åº¦ 100
     */
    public static final int DEFAULT_FILE_NAME_LENGTH = 100;
    /**
     * é»˜è®¤ä¸Šä¼ çš„地址
     */
    private static String defaultBaseDir = RuoYiConfig.getProfile();
    public static void setDefaultBaseDir(String defaultBaseDir)
    {
        FileUploadUtils.defaultBaseDir = defaultBaseDir;
    }
    public static String getDefaultBaseDir()
    {
        return defaultBaseDir;
    }
    /**
     * ä»¥é»˜è®¤é…ç½®è¿›è¡Œæ–‡ä»¶ä¸Šä¼ 
     *
     * @param file ä¸Šä¼ çš„æ–‡ä»¶
     * @return æ–‡ä»¶åç§°
     * @throws Exception
     */
    public static final String upload(MultipartFile file) throws IOException
    {
        try
        {
            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }
    /**
     * æ ¹æ®æ–‡ä»¶è·¯å¾„上传
     *
     * @param baseDir ç›¸å¯¹åº”用的基目录
     * @param file ä¸Šä¼ çš„æ–‡ä»¶
     * @return æ–‡ä»¶åç§°
     * @throws IOException
     */
    public static final String upload(String baseDir, MultipartFile file) throws IOException
    {
        try
        {
            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }
    /**
     * æ–‡ä»¶ä¸Šä¼ 
     *
     * @param baseDir ç›¸å¯¹åº”用的基目录
     * @param file ä¸Šä¼ çš„æ–‡ä»¶
     * @param allowedExtension ä¸Šä¼ æ–‡ä»¶ç±»åž‹
     * @return è¿”回上传成功的文件名
     * @throws FileSizeLimitExceededException å¦‚果超出最大大小
     * @throws FileNameLengthLimitExceededException æ–‡ä»¶åå¤ªé•¿
     * @throws IOException æ¯”如读写文件出错时
     * @throws InvalidExtensionException æ–‡ä»¶æ ¡éªŒå¼‚常
     */
    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        return upload(baseDir, file, allowedExtension, false);
    }
    /**
     * æ–‡ä»¶ä¸Šä¼ 
     *
     * @param baseDir ç›¸å¯¹åº”用的基目录
     * @param file ä¸Šä¼ çš„æ–‡ä»¶
     * @param useCustomNaming ç³»ç»Ÿè‡ªå®šä¹‰æ–‡ä»¶å
     * @param allowedExtension ä¸Šä¼ æ–‡ä»¶ç±»åž‹
     * @return è¿”回上传成功的文件名
     * @throws FileSizeLimitExceededException å¦‚果超出最大大小
     * @throws FileNameLengthLimitExceededException æ–‡ä»¶åå¤ªé•¿
     * @throws IOException æ¯”如读写文件出错时
     * @throws InvalidExtensionException æ–‡ä»¶æ ¡éªŒå¼‚常
     */
    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension, boolean useCustomNaming)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        int fileNameLength = Objects.requireNonNull(file.getOriginalFilename()).length();
        if (fileNameLength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }
        assertAllowed(file, allowedExtension);
        String fileName = useCustomNaming ? uuidFilename(file) : extractFilename(file);
        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
        file.transferTo(Paths.get(absPath));
        return getPathFileName(baseDir, fileName);
    }
    /**
     * ç¼–码文件名(日期格式目录 + åŽŸæ–‡ä»¶å + åºåˆ—值 + åŽç¼€)
     */
    public static final String extractFilename(MultipartFile file)
    {
        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(), FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
    }
    /**
     * ç¼–编码文件名(日期格式目录 + UUID + åŽç¼€)
     */
    public static final String uuidFilename(MultipartFile file)
    {
        return StringUtils.format("{}/{}.{}", DateUtils.datePath(), IdUtils.fastSimpleUUID(), getExtension(file));
    }
    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
    {
        File desc = new File(uploadDir + File.separator + fileName);
        if (!desc.exists())
        {
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
        }
        return desc;
    }
    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
    {
        int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
        return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
    }
    /**
     * æ–‡ä»¶å¤§å°æ ¡éªŒ
     *
     * @param file ä¸Šä¼ çš„æ–‡ä»¶
     * @return
     * @throws FileSizeLimitExceededException å¦‚果超出最大大小
     * @throws InvalidExtensionException
     */
    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, InvalidExtensionException
    {
        long size = file.getSize();
        if (size > DEFAULT_MAX_SIZE)
        {
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
        }
        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
        {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            }
            else
            {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }
    }
    /**
     * åˆ¤æ–­MIME类型是否是允许的MIME类型
     *
     * @param extension
     * @param allowedExtension
     * @return
     */
    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
    {
        for (String str : allowedExtension)
        {
            if (str.equalsIgnoreCase(extension))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * èŽ·å–æ–‡ä»¶åçš„åŽç¼€
     *
     * @param file è¡¨å•文件
     * @return åŽç¼€å
     */
    public static final String getExtension(MultipartFile file)
    {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        if (StringUtils.isEmpty(extension))
        {
            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
        }
        return extension;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,303 @@
package com.ruoyi.common.utils.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
/**
 * æ–‡ä»¶å¤„理工具类
 *
 * @author ruoyi
 */
public class FileUtils
{
    public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
    /**
     * è¾“出指定文件的byte数组
     *
     * @param filePath æ–‡ä»¶è·¯å¾„
     * @param os è¾“出流
     * @return
     */
    public static void writeBytes(String filePath, OutputStream os) throws IOException
    {
        FileInputStream fis = null;
        try
        {
            File file = new File(filePath);
            if (!file.exists())
            {
                throw new FileNotFoundException(filePath);
            }
            fis = new FileInputStream(file);
            byte[] b = new byte[1024];
            int length;
            while ((length = fis.read(b)) > 0)
            {
                os.write(b, 0, length);
            }
        }
        catch (IOException e)
        {
            throw e;
        }
        finally
        {
            IOUtils.close(os);
            IOUtils.close(fis);
        }
    }
    /**
     * å†™æ•°æ®åˆ°æ–‡ä»¶ä¸­
     *
     * @param data æ•°æ®
     * @return ç›®æ ‡æ–‡ä»¶
     * @throws IOException IO异常
     */
    public static String writeImportBytes(byte[] data) throws IOException
    {
        return writeBytes(data, RuoYiConfig.getImportPath());
    }
    /**
     * å†™æ•°æ®åˆ°æ–‡ä»¶ä¸­
     *
     * @param data æ•°æ®
     * @param uploadDir ç›®æ ‡æ–‡ä»¶
     * @return ç›®æ ‡æ–‡ä»¶
     * @throws IOException IO异常
     */
    public static String writeBytes(byte[] data, String uploadDir) throws IOException
    {
        FileOutputStream fos = null;
        String pathName = "";
        try
        {
            String extension = getFileExtendName(data);
            pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
            File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
            fos = new FileOutputStream(file);
            fos.write(data);
        }
        finally
        {
            IOUtils.close(fos);
        }
        return FileUploadUtils.getPathFileName(uploadDir, pathName);
    }
    /**
     * ç§»é™¤è·¯å¾„中的请求前缀片段
     *
     * @param filePath æ–‡ä»¶è·¯å¾„
     * @return ç§»é™¤åŽçš„æ–‡ä»¶è·¯å¾„
     */
    public static String stripPrefix(String filePath)
    {
        return StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);
    }
    /**
     * åˆ é™¤æ–‡ä»¶
     *
     * @param filePath æ–‡ä»¶
     * @return
     */
    public static boolean deleteFile(String filePath)
    {
        boolean flag = false;
        File file = new File(filePath);
        // è·¯å¾„为文件且不为空则进行删除
        if (file.isFile() && file.exists())
        {
            flag = file.delete();
        }
        return flag;
    }
    /**
     * æ–‡ä»¶åç§°éªŒè¯
     *
     * @param filename æ–‡ä»¶åç§°
     * @return true æ­£å¸¸ false éžæ³•
     */
    public static boolean isValidFilename(String filename)
    {
        return filename.matches(FILENAME_PATTERN);
    }
    /**
     * æ£€æŸ¥æ–‡ä»¶æ˜¯å¦å¯ä¸‹è½½
     *
     * @param resource éœ€è¦ä¸‹è½½çš„æ–‡ä»¶
     * @return true æ­£å¸¸ false éžæ³•
     */
    public static boolean checkAllowDownload(String resource)
    {
        // ç¦æ­¢ç›®å½•上跳级别
        if (StringUtils.contains(resource, ".."))
        {
            return false;
        }
        // æ£€æŸ¥å…è®¸ä¸‹è½½çš„æ–‡ä»¶è§„则
        if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
        {
            return true;
        }
        // ä¸åœ¨å…è®¸ä¸‹è½½çš„æ–‡ä»¶è§„则
        return false;
    }
    /**
     * ä¸‹è½½æ–‡ä»¶åé‡æ–°ç¼–码
     *
     * @param request è¯·æ±‚对象
     * @param fileName æ–‡ä»¶å
     * @return ç¼–码后的文件名
     */
    public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
    {
        final String agent = request.getHeader("USER-AGENT");
        String filename = fileName;
        if (agent.contains("MSIE"))
        {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        }
        else if (agent.contains("Firefox"))
        {
            // ç«ç‹æµè§ˆå™¨
            filename = new String(fileName.getBytes(), "ISO8859-1");
        }
        else if (agent.contains("Chrome"))
        {
            // google浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        else
        {
            // å…¶å®ƒæµè§ˆå™¨
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
    /**
     * ä¸‹è½½æ–‡ä»¶åé‡æ–°ç¼–码
     *
     * @param response å“åº”对象
     * @param realFileName çœŸå®žæ–‡ä»¶å
     */
    public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
    {
        String percentEncodedFileName = percentEncode(realFileName);
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=")
                .append(percentEncodedFileName)
                .append(";")
                .append("filename*=")
                .append("utf-8''")
                .append(percentEncodedFileName);
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
    }
    /**
     * ç™¾åˆ†å·ç¼–码工具方法
     *
     * @param s éœ€è¦ç™¾åˆ†å·ç¼–码的字符串
     * @return ç™¾åˆ†å·ç¼–码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException
    {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }
    /**
     * èŽ·å–å›¾åƒåŽç¼€
     *
     * @param photoByte å›¾åƒæ•°æ®
     * @return åŽç¼€å
     */
    public static String getFileExtendName(byte[] photoByte)
    {
        String strFileExtendName = "jpg";
        if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
                && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
        {
            strFileExtendName = "gif";
        }
        else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
        {
            strFileExtendName = "jpg";
        }
        else if ((photoByte[0] == 66) && (photoByte[1] == 77))
        {
            strFileExtendName = "bmp";
        }
        else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
        {
            strFileExtendName = "png";
        }
        return strFileExtendName;
    }
    /**
     * èŽ·å–æ–‡ä»¶åç§° /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
     *
     * @param fileName è·¯å¾„名称
     * @return æ²¡æœ‰æ–‡ä»¶è·¯å¾„的名称
     */
    public static String getName(String fileName)
    {
        if (fileName == null)
        {
            return null;
        }
        int lastUnixPos = fileName.lastIndexOf('/');
        int lastWindowsPos = fileName.lastIndexOf('\\');
        int index = Math.max(lastUnixPos, lastWindowsPos);
        return fileName.substring(index + 1);
    }
    /**
     * èŽ·å–ä¸å¸¦åŽç¼€æ–‡ä»¶åç§° /profile/upload/2022/04/16/ruoyi.png -- ruoyi
     *
     * @param fileName è·¯å¾„名称
     * @return æ²¡æœ‰æ–‡ä»¶è·¯å¾„和后缀的名称
     */
    public static String getNameNotSuffix(String fileName)
    {
        if (fileName == null)
        {
            return null;
        }
        String baseName = FilenameUtils.getBaseName(fileName);
        return baseName;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,98 @@
package com.ruoyi.common.utils.file;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import org.apache.poi.util.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
/**
 * å›¾ç‰‡å¤„理工具类
 *
 * @author ruoyi
 */
public class ImageUtils
{
    private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
    public static byte[] getImage(String imagePath)
    {
        InputStream is = getFile(imagePath);
        try
        {
            return IOUtils.toByteArray(is);
        }
        catch (Exception e)
        {
            log.error("图片加载异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
    }
    public static InputStream getFile(String imagePath)
    {
        try
        {
            byte[] result = readFile(imagePath);
            result = Arrays.copyOf(result, result.length);
            return new ByteArrayInputStream(result);
        }
        catch (Exception e)
        {
            log.error("获取图片异常 {}", e);
        }
        return null;
    }
    /**
     * è¯»å–文件为字节数据
     *
     * @param url åœ°å€
     * @return å­—节数据
     */
    public static byte[] readFile(String url)
    {
        InputStream in = null;
        try
        {
            if (url.startsWith("http"))
            {
                // ç½‘络地址
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                urlConnection.setConnectTimeout(30 * 1000);
                urlConnection.setReadTimeout(60 * 1000);
                urlConnection.setDoInput(true);
                in = urlConnection.getInputStream();
            }
            else
            {
                // æœ¬æœºåœ°å€
                String localPath = RuoYiConfig.getProfile();
                String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
                in = new FileInputStream(downloadPath);
            }
            return IOUtils.toByteArray(in);
        }
        catch (Exception e)
        {
            log.error("获取文件路径异常 {}", e);
            return null;
        }
        finally
        {
            IOUtils.closeQuietly(in);
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.ruoyi.common.utils.file;
/**
 * åª’体类型工具类
 *
 * @author ruoyi
 */
public class MimeTypeUtils
{
    public static final String IMAGE_PNG = "image/png";
    public static final String IMAGE_JPG = "image/jpg";
    public static final String IMAGE_JPEG = "image/jpeg";
    public static final String IMAGE_BMP = "image/bmp";
    public static final String IMAGE_GIF = "image/gif";
    public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
    public static final String[] FLASH_EXTENSION = { "swf", "flv" };
    public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
            "asf", "rm", "rmvb" };
    public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
    public static final String[] DEFAULT_ALLOWED_EXTENSION = {
            // å›¾ç‰‡
            "bmp", "gif", "jpg", "jpeg", "png",
            // word excel(花名册导入/导出需要)
            "doc", "docx", "xls", "xlsx", "txt",
            // pdf(三方协议/知情书扫描件)
            "pdf" };
    public static String getExtension(String prefix)
    {
        switch (prefix)
        {
            case IMAGE_PNG:
                return "png";
            case IMAGE_JPG:
                return "jpg";
            case IMAGE_JPEG:
                return "jpeg";
            case IMAGE_BMP:
                return "bmp";
            case IMAGE_GIF:
                return "gif";
            default:
                return "";
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
package com.ruoyi.common.utils.html;
import com.ruoyi.common.utils.StringUtils;
/**
 * è½¬ä¹‰å’Œåè½¬ä¹‰å·¥å…·ç±»
 *
 * @author ruoyi
 */
public class EscapeUtil
{
    public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
    private static final char[][] TEXT = new char[64][];
    static
    {
        for (int i = 0; i < 64; i++)
        {
            TEXT[i] = new char[] { (char) i };
        }
        // special HTML characters
        TEXT['\''] = "&#039;".toCharArray(); // å•引号
        TEXT['"'] = "&#34;".toCharArray(); // åŒå¼•号
        TEXT['&'] = "&#38;".toCharArray(); // &符
        TEXT['<'] = "&#60;".toCharArray(); // å°äºŽå·
        TEXT['>'] = "&#62;".toCharArray(); // å¤§äºŽå·
    }
    /**
     * è½¬ä¹‰æ–‡æœ¬ä¸­çš„HTML字符为安全的字符
     *
     * @param text è¢«è½¬ä¹‰çš„æ–‡æœ¬
     * @return è½¬ä¹‰åŽçš„æ–‡æœ¬
     */
    public static String escape(String text)
    {
        return encode(text);
    }
    /**
     * è¿˜åŽŸè¢«è½¬ä¹‰çš„HTML特殊字符
     *
     * @param content åŒ…含转义符的HTML内容
     * @return è½¬æ¢åŽçš„字符串
     */
    public static String unescape(String content)
    {
        return decode(content);
    }
    /**
     * æ¸…除所有HTML标签,但是不删除标签内的内容
     *
     * @param content æ–‡æœ¬
     * @return æ¸…除标签后的文本
     */
    public static String clean(String content)
    {
        return new HTMLFilter().filter(content);
    }
    /**
     * Escape编码
     *
     * @param text è¢«ç¼–码的文本
     * @return ç¼–码后的字符
     */
    private static String encode(String text)
    {
        if (StringUtils.isEmpty(text))
        {
            return StringUtils.EMPTY;
        }
        final StringBuilder tmp = new StringBuilder(text.length() * 6);
        char c;
        for (int i = 0; i < text.length(); i++)
        {
            c = text.charAt(i);
            if (c < 256)
            {
                tmp.append("%");
                if (c < 16)
                {
                    tmp.append("0");
                }
                tmp.append(Integer.toString(c, 16));
            }
            else
            {
                tmp.append("%u");
                if (c <= 0xfff)
                {
                    // issue#I49JU8@Gitee
                    tmp.append("0");
                }
                tmp.append(Integer.toString(c, 16));
            }
        }
        return tmp.toString();
    }
    /**
     * Escape解码
     *
     * @param content è¢«è½¬ä¹‰çš„内容
     * @return è§£ç åŽçš„字符串
     */
    public static String decode(String content)
    {
        if (StringUtils.isEmpty(content))
        {
            return content;
        }
        StringBuilder tmp = new StringBuilder(content.length());
        int lastPos = 0, pos = 0;
        char ch;
        while (lastPos < content.length())
        {
            pos = content.indexOf("%", lastPos);
            if (pos == lastPos)
            {
                if (content.charAt(pos + 1) == 'u')
                {
                    ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
                    tmp.append(ch);
                    lastPos = pos + 6;
                }
                else
                {
                    ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
                    tmp.append(ch);
                    lastPos = pos + 3;
                }
            }
            else
            {
                if (pos == -1)
                {
                    tmp.append(content.substring(lastPos));
                    lastPos = content.length();
                }
                else
                {
                    tmp.append(content.substring(lastPos, pos));
                    lastPos = pos;
                }
            }
        }
        return tmp.toString();
    }
    public static void main(String[] args)
    {
        String html = "<script>alert(1);</script>";
        String escape = EscapeUtil.escape(html);
        // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
        // String html = "<123";
        // String html = "123>";
        System.out.println("clean: " + EscapeUtil.clean(html));
        System.out.println("escape: " + escape);
        System.out.println("unescape: " + EscapeUtil.unescape(escape));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,570 @@
package com.ruoyi.common.utils.html;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * HTML过滤器,用于去除XSS漏洞隐患。
 *
 * @author ruoyi
 */
public final class HTMLFilter
{
    /**
     * regex flag union representing /si modifiers in php
     **/
    private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
    private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
    private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
    private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
    private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
    private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
    private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
    private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
    private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
    private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
    private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
    private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
    private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
    private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
    private static final Pattern P_END_ARROW = Pattern.compile("^>");
    private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
    private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
    private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
    private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
    private static final Pattern P_AMP = Pattern.compile("&");
    private static final Pattern P_QUOTE = Pattern.compile("\"");
    private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
    private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
    private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
    // @xxx could grow large... maybe use sesat's ReferenceMap
    private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
    private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
    /**
     * set of allowed html elements, along with allowed attributes for each element
     **/
    private final Map<String, List<String>> vAllowed;
    /**
     * counts of open tags for each (allowable) html element
     **/
    private final Map<String, Integer> vTagCounts = new HashMap<>();
    /**
     * html elements which must always be self-closing (e.g. "<img />")
     **/
    private final String[] vSelfClosingTags;
    /**
     * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
     **/
    private final String[] vNeedClosingTags;
    /**
     * set of disallowed html elements
     **/
    private final String[] vDisallowed;
    /**
     * attributes which should be checked for valid protocols
     **/
    private final String[] vProtocolAtts;
    /**
     * allowed protocols
     **/
    private final String[] vAllowedProtocols;
    /**
     * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
     **/
    private final String[] vRemoveBlanks;
    /**
     * entities allowed within html markup
     **/
    private final String[] vAllowedEntities;
    /**
     * flag determining whether comments are allowed in input String.
     */
    private final boolean stripComment;
    private final boolean encodeQuotes;
    /**
     * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
     * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
     */
    private final boolean alwaysMakeTags;
    /**
     * Default constructor.
     */
    public HTMLFilter()
    {
        vAllowed = new HashMap<>();
        final ArrayList<String> a_atts = new ArrayList<>();
        a_atts.add("href");
        a_atts.add("target");
        vAllowed.put("a", a_atts);
        final ArrayList<String> img_atts = new ArrayList<>();
        img_atts.add("src");
        img_atts.add("width");
        img_atts.add("height");
        img_atts.add("alt");
        vAllowed.put("img", img_atts);
        final ArrayList<String> no_atts = new ArrayList<>();
        vAllowed.put("b", no_atts);
        vAllowed.put("strong", no_atts);
        vAllowed.put("i", no_atts);
        vAllowed.put("em", no_atts);
        vSelfClosingTags = new String[] { "img" };
        vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
        vDisallowed = new String[] {};
        vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
        vProtocolAtts = new String[] { "src", "href" };
        vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
        vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
        stripComment = true;
        encodeQuotes = true;
        alwaysMakeTags = false;
    }
    /**
     * Map-parameter configurable constructor.
     *
     * @param conf map containing configuration. keys match field names.
     */
    @SuppressWarnings("unchecked")
    public HTMLFilter(final Map<String, Object> conf)
    {
        assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
        assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
        assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
        assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
        assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
        assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
        assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
        assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
        vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
        vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
        vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
        vDisallowed = (String[]) conf.get("vDisallowed");
        vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
        vProtocolAtts = (String[]) conf.get("vProtocolAtts");
        vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
        vAllowedEntities = (String[]) conf.get("vAllowedEntities");
        stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
        encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
        alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
    }
    private void reset()
    {
        vTagCounts.clear();
    }
    // ---------------------------------------------------------------
    // my versions of some PHP library functions
    public static String chr(final int decimal)
    {
        return String.valueOf((char) decimal);
    }
    public static String htmlSpecialChars(final String s)
    {
        String result = s;
        result = regexReplace(P_AMP, "&amp;", result);
        result = regexReplace(P_QUOTE, "&quot;", result);
        result = regexReplace(P_LEFT_ARROW, "&lt;", result);
        result = regexReplace(P_RIGHT_ARROW, "&gt;", result);
        return result;
    }
    // ---------------------------------------------------------------
    /**
     * given a user submitted input String, filter out any invalid or restricted html.
     *
     * @param input text (i.e. submitted by a user) than may contain html
     * @return "clean" version of input, with only valid, whitelisted html elements allowed
     */
    public String filter(final String input)
    {
        reset();
        String s = input;
        s = escapeComments(s);
        s = balanceHTML(s);
        s = checkTags(s);
        s = processRemoveBlanks(s);
        // s = validateEntities(s);
        return s;
    }
    public boolean isAlwaysMakeTags()
    {
        return alwaysMakeTags;
    }
    public boolean isStripComments()
    {
        return stripComment;
    }
    private String escapeComments(final String s)
    {
        final Matcher m = P_COMMENTS.matcher(s);
        final StringBuffer buf = new StringBuffer();
        if (m.find())
        {
            final String match = m.group(1); // (.*?)
            m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
        }
        m.appendTail(buf);
        return buf.toString();
    }
    private String balanceHTML(String s)
    {
        if (alwaysMakeTags)
        {
            //
            // try and form html
            //
            s = regexReplace(P_END_ARROW, "", s);
            // ä¸è¿½åŠ ç»“æŸæ ‡ç­¾
            s = regexReplace(P_BODY_TO_END, "<$1>", s);
            s = regexReplace(P_XML_CONTENT, "$1<$2", s);
        }
        else
        {
            //
            // escape stray brackets
            //
            s = regexReplace(P_STRAY_LEFT_ARROW, "&lt;$1", s);
            s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2&gt;<", s);
            //
            // the last regexp causes '<>' entities to appear
            // (we need to do a lookahead assertion so that the last bracket can
            // be used in the next pass of the regexp)
            //
            s = regexReplace(P_BOTH_ARROWS, "", s);
        }
        return s;
    }
    private String checkTags(String s)
    {
        Matcher m = P_TAGS.matcher(s);
        final StringBuffer buf = new StringBuffer();
        while (m.find())
        {
            String replaceStr = m.group(1);
            replaceStr = processTag(replaceStr);
            m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
        }
        m.appendTail(buf);
        // these get tallied in processTag
        // (remember to reset before subsequent calls to filter method)
        final StringBuilder sBuilder = new StringBuilder(buf.toString());
        for (String key : vTagCounts.keySet())
        {
            for (int ii = 0; ii < vTagCounts.get(key); ii++)
            {
                sBuilder.append("</").append(key).append(">");
            }
        }
        s = sBuilder.toString();
        return s;
    }
    private String processRemoveBlanks(final String s)
    {
        String result = s;
        for (String tag : vRemoveBlanks)
        {
            if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
            {
                P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
            }
            result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
            if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
            {
                P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
            }
            result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
        }
        return result;
    }
    private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
    {
        Matcher m = regex_pattern.matcher(s);
        return m.replaceAll(replacement);
    }
    private String processTag(final String s)
    {
        // ending tags
        Matcher m = P_END_TAG.matcher(s);
        if (m.find())
        {
            final String name = m.group(1).toLowerCase();
            if (allowed(name))
            {
                if (!inArray(name, vSelfClosingTags))
                {
                    if (vTagCounts.containsKey(name))
                    {
                        vTagCounts.put(name, vTagCounts.get(name) - 1);
                        return "</" + name + ">";
                    }
                }
            }
        }
        // starting tags
        m = P_START_TAG.matcher(s);
        if (m.find())
        {
            final String name = m.group(1).toLowerCase();
            final String body = m.group(2);
            String ending = m.group(3);
            // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
            if (allowed(name))
            {
                final StringBuilder params = new StringBuilder();
                final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
                final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
                final List<String> paramNames = new ArrayList<>();
                final List<String> paramValues = new ArrayList<>();
                while (m2.find())
                {
                    paramNames.add(m2.group(1)); // ([a-z0-9]+)
                    paramValues.add(m2.group(3)); // (.*?)
                }
                while (m3.find())
                {
                    paramNames.add(m3.group(1)); // ([a-z0-9]+)
                    paramValues.add(m3.group(3)); // ([^\"\\s']+)
                }
                String paramName, paramValue;
                for (int ii = 0; ii < paramNames.size(); ii++)
                {
                    paramName = paramNames.get(ii).toLowerCase();
                    paramValue = paramValues.get(ii);
                    // debug( "paramName='" + paramName + "'" );
                    // debug( "paramValue='" + paramValue + "'" );
                    // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
                    if (allowedAttribute(name, paramName))
                    {
                        if (inArray(paramName, vProtocolAtts))
                        {
                            paramValue = processParamProtocol(paramValue);
                        }
                        params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\"");
                    }
                }
                if (inArray(name, vSelfClosingTags))
                {
                    ending = " /";
                }
                if (inArray(name, vNeedClosingTags))
                {
                    ending = "";
                }
                if (ending == null || ending.length() < 1)
                {
                    if (vTagCounts.containsKey(name))
                    {
                        vTagCounts.put(name, vTagCounts.get(name) + 1);
                    }
                    else
                    {
                        vTagCounts.put(name, 1);
                    }
                }
                else
                {
                    ending = " /";
                }
                return "<" + name + params + ending + ">";
            }
            else
            {
                return "";
            }
        }
        // comments
        m = P_COMMENT.matcher(s);
        if (!stripComment && m.find())
        {
            return "<" + m.group() + ">";
        }
        return "";
    }
    private String processParamProtocol(String s)
    {
        s = decodeEntities(s);
        final Matcher m = P_PROTOCOL.matcher(s);
        if (m.find())
        {
            final String protocol = m.group(1);
            if (!inArray(protocol, vAllowedProtocols))
            {
                // bad protocol, turn into local anchor link instead
                s = "#" + s.substring(protocol.length() + 1);
                if (s.startsWith("#//"))
                {
                    s = "#" + s.substring(3);
                }
            }
        }
        return s;
    }
    private String decodeEntities(String s)
    {
        StringBuffer buf = new StringBuffer();
        Matcher m = P_ENTITY.matcher(s);
        while (m.find())
        {
            final String match = m.group(1);
            final int decimal = Integer.decode(match).intValue();
            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
        }
        m.appendTail(buf);
        s = buf.toString();
        buf = new StringBuffer();
        m = P_ENTITY_UNICODE.matcher(s);
        while (m.find())
        {
            final String match = m.group(1);
            final int decimal = Integer.valueOf(match, 16).intValue();
            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
        }
        m.appendTail(buf);
        s = buf.toString();
        buf = new StringBuffer();
        m = P_ENCODE.matcher(s);
        while (m.find())
        {
            final String match = m.group(1);
            final int decimal = Integer.valueOf(match, 16).intValue();
            m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
        }
        m.appendTail(buf);
        s = buf.toString();
        s = validateEntities(s);
        return s;
    }
    private String validateEntities(final String s)
    {
        StringBuffer buf = new StringBuffer();
        // validate entities throughout the string
        Matcher m = P_VALID_ENTITIES.matcher(s);
        while (m.find())
        {
            final String one = m.group(1); // ([^&;]*)
            final String two = m.group(2); // (?=(;|&|$))
            m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
        }
        m.appendTail(buf);
        return encodeQuotes(buf.toString());
    }
    private String encodeQuotes(final String s)
    {
        if (encodeQuotes)
        {
            StringBuffer buf = new StringBuffer();
            Matcher m = P_VALID_QUOTES.matcher(s);
            while (m.find())
            {
                final String one = m.group(1); // (>|^)
                final String two = m.group(2); // ([^<]+?)
                final String three = m.group(3); // (<|$)
                // ä¸æ›¿æ¢åŒå¼•号为&quot;,防止json格式无效 regexReplace(P_QUOTE, "&quot;", two)
                m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
            }
            m.appendTail(buf);
            return buf.toString();
        }
        else
        {
            return s;
        }
    }
    private String checkEntity(final String preamble, final String term)
    {
        return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&amp;" + preamble;
    }
    private boolean isValidEntity(final String entity)
    {
        return inArray(entity, vAllowedEntities);
    }
    private static boolean inArray(final String s, final String[] array)
    {
        for (String item : array)
        {
            if (item != null && item.equals(s))
            {
                return true;
            }
        }
        return false;
    }
    private boolean allowed(final String name)
    {
        return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
    }
    private boolean allowedAttribute(final String name, final String paramName)
    {
        return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.ruoyi.common.utils.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import jakarta.servlet.ServletRequest;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * é€šç”¨http工具封装
 *
 * @author ruoyi
 */
public class HttpHelper
{
    private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
    public static String getBodyString(ServletRequest request)
    {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;
        try (InputStream inputStream = request.getInputStream())
        {
            reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
            String line = "";
            while ((line = reader.readLine()) != null)
            {
                sb.append(line);
            }
        }
        catch (IOException e)
        {
            LOGGER.warn("getBodyString出现问题!");
        }
        finally
        {
            if (reader != null)
            {
                try
                {
                    reader.close();
                }
                catch (IOException e)
                {
                    LOGGER.error(ExceptionUtils.getMessage(e));
                }
            }
        }
        return sb.toString();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,293 @@
package com.ruoyi.common.utils.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.http.MediaType;
/**
 * é€šç”¨http发送方法
 *
 * @author ruoyi
 */
public class HttpUtils
{
    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
    /**
     * å‘指定 URL å‘送GET方法的请求
     *
     * @param url å‘送请求的 URL
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendGet(String url)
    {
        return sendGet(url, StringUtils.EMPTY);
    }
    /**
     * å‘指定 URL å‘送GET方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数,请求参数应该是 name1=value1&name2=value2 çš„形式。
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendGet(String url, String param)
    {
        return sendGet(url, param, Constants.UTF8);
    }
    /**
     * å‘指定 URL å‘送GET方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数,请求参数应该是 name1=value1&name2=value2 çš„形式。
     * @param contentType ç¼–码类型
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendGet(String url, String param, String contentType)
    {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try
        {
            String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
            log.info("sendGet - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (Exception ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
    /**
     * å‘指定 URL å‘送POST方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数,请求参数应该是 name1=value1&name2=value2 çš„形式。
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendPost(String url, String param)
    {
        return sendPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
    }
    /**
     * å‘指定 URL å‘送POST方法的请求
     *
     * @param url å‘送请求的 URL
     * @param param è¯·æ±‚参数
     * @param contentType å†…容类型
     * @return æ‰€ä»£è¡¨è¿œç¨‹èµ„源的响应结果
     */
    public static String sendPost(String url, String param, String contentType)
    {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try
        {
            log.info("sendPost - {}", url);
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", contentType);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }
    public static String sendSSLPost(String url, String param)
    {
        return sendSSLPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
    }
    public static String sendSSLPost(String url, String param, String contentType)
    {
        StringBuilder result = new StringBuilder();
        String urlNameString = url + "?" + param;
        try
        {
            log.info("sendSSLPost - {}", urlNameString);
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
            URL console = new URL(urlNameString);
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("Content-Type", contentType);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String ret = "";
            while ((ret = br.readLine()) != null)
            {
                if (ret != null && !"".equals(ret.trim()))
                {
                    result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
                }
            }
            log.info("recv - {}", result);
            conn.disconnect();
            br.close();
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
        }
        return result.toString();
    }
    private static class TrustAnyTrustManager implements X509TrustManager
    {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
        {
        }
        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
        {
        }
        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[] {};
        }
    }
    private static class TrustAnyHostnameVerifier implements HostnameVerifier
    {
        @Override
        public boolean verify(String hostname, SSLSession session)
        {
            return true;
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/UserAgentUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,254 @@
package com.ruoyi.common.utils.http;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.ruoyi.common.utils.StringUtils;
import nl.basjes.parse.useragent.UserAgent;
import nl.basjes.parse.useragent.UserAgentAnalyzer;
/**
 * UserAgent解析工具类
 *
 * @author ruoyi
 */
public class UserAgentUtils
{
    public static final String UNKNOWN = "";
    // æµè§ˆå™¨æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼
    private static final Pattern CHROME_PATTERN = Pattern.compile("Chrome/(\\d+)(?:\\.\\d+)*");
    private static final Pattern FIREFOX_PATTERN = Pattern.compile("Firefox/(\\d+)(?:\\.\\d+)*");
    private static final Pattern EDGE_PATTERN = Pattern.compile("Edg(?:e)?/(\\d+)(?:\\.\\d+)*");
    private static final Pattern SAFARI_PATTERN = Pattern.compile("Version/(\\d+)(?:\\.\\d+)*");
    private static final Pattern OPERA_PATTERN = Pattern.compile("Opera/(\\d+)(?:\\.\\d+)*");
    private static final Pattern IE_PATTERN = Pattern.compile("(?:MSIE |Trident/.*rv:)(\\d+)(?:\\.\\d+)*");
    private static final Pattern SAMSUNG_PATTERN = Pattern.compile("SamsungBrowser/(\\d+)(?:\\.\\d+)*");
    private static final Pattern UC_PATTERN = Pattern.compile("UCBrowser/(\\d+)(?:\\.\\d+)*");
    private static final Pattern QQ_PATTERN = Pattern.compile("QQBrowser/(\\d+)(?:\\.\\d+)*");
    private static final Pattern WECHAT_PATTERN = Pattern.compile("MicroMessenger/(\\d+)(?:\\.\\d+)*");
    private static final Pattern BAIDU_PATTERN = Pattern.compile("baidubrowser/(\\d+)(?:\\.\\d+)*");
    // æ“ä½œç³»ç»Ÿæ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼
    private static final Pattern WINDOWS_PATTERN = Pattern.compile("Windows NT (\\d+\\.\\d+)");
    private static final Pattern MACOS_PATTERN = Pattern.compile("Mac OS X (\\d+[_\\d]*)");
    private static final Pattern ANDROID_PATTERN = Pattern.compile("Android (\\d+)(?:\\.\\d+)*");
    private static final Pattern IOS_PATTERN = Pattern.compile("OS[\\s_](\\d+)(?:_\\d+)*");
    private static final Pattern LINUX_PATTERN = Pattern.compile("Linux");
    private static final Pattern CHROMEOS_PATTERN = Pattern.compile("CrOS");
    private static final UserAgentAnalyzer userAgentAnalyzer = UserAgentAnalyzer
            .newBuilder().hideMatcherLoadStats()
            .withCache(5000)
            .showMinimalVersion()
            .withField(UserAgent.AGENT_NAME_VERSION)
            .withField(UserAgent.OPERATING_SYSTEM_NAME_VERSION)
            .build();
    /**
     * èŽ·å–å®¢æˆ·ç«¯æµè§ˆå™¨
     */
    public static String getBrowser(String userAgent)
    {
        UserAgent.ImmutableUserAgent iua = userAgentAnalyzer.parse(userAgent);
        String agentNameVersion = iua.get(UserAgent.AGENT_NAME_VERSION).getValue();
        if (StringUtils.isBlank(agentNameVersion) || agentNameVersion.contains("??"))
        {
            return formatBrowser(userAgent);
        }
        return agentNameVersion;
    }
    /**
     * èŽ·å–å®¢æˆ·ç«¯æ“ä½œç³»ç»Ÿ
     */
    public static String getOperatingSystem(String userAgent)
    {
        UserAgent.ImmutableUserAgent iua = userAgentAnalyzer.parse(userAgent);
        String operatingSystemNameVersion = iua.get(UserAgent.OPERATING_SYSTEM_NAME_VERSION).getValue();
        if (StringUtils.isBlank(operatingSystemNameVersion) || operatingSystemNameVersion.contains("??"))
        {
            return formatOperatingSystem(userAgent);
        }
        return operatingSystemNameVersion;
    }
    /**
     * å…¨é¢æµè§ˆå™¨æ£€æµ‹
     */
    private static String formatBrowser(String browser)
    {
        // Chrome系列浏览器
        Matcher chromeMatcher = CHROME_PATTERN.matcher(browser);
        if (chromeMatcher.find() && (browser.contains("Chrome") || browser.contains("CriOS")))
        {
            return "Chrome" + chromeMatcher.group(1);
        }
        // Firefox
        Matcher firefoxMatcher = FIREFOX_PATTERN.matcher(browser);
        if (firefoxMatcher.find())
        {
            return "Firefox" + firefoxMatcher.group(1);
        }
        // Edge浏览器
        Matcher edgeMatcher = EDGE_PATTERN.matcher(browser);
        if (edgeMatcher.find())
        {
            return "Edge" + edgeMatcher.group(1);
        }
        // Safari浏览器(需排除Chrome)
        Matcher safariMatcher = SAFARI_PATTERN.matcher(browser);
        if (safariMatcher.find() && !browser.contains("Chrome"))
        {
            return "Safari" + safariMatcher.group(1);
        }
        // å¾®ä¿¡å†…置浏览器
        Matcher wechatMatcher = WECHAT_PATTERN.matcher(browser);
        if (wechatMatcher.find())
        {
            return "WeChat" + wechatMatcher.group(1);
        }
        // UC浏览器
        Matcher ucMatcher = UC_PATTERN.matcher(browser);
        if (ucMatcher.find())
        {
            return "UC Browser" + ucMatcher.group(1);
        }
        // QQ浏览器
        Matcher qqMatcher = QQ_PATTERN.matcher(browser);
        if (qqMatcher.find())
        {
            return "QQ Browser" + qqMatcher.group(1);
        }
        // ç™¾åº¦æµè§ˆå™¨
        Matcher baiduMatcher = BAIDU_PATTERN.matcher(browser);
        if (baiduMatcher.find())
        {
            return "Baidu Browser" + baiduMatcher.group(1);
        }
        // Samsung浏览器
        Matcher samsungMatcher = SAMSUNG_PATTERN.matcher(browser);
        if (samsungMatcher.find())
        {
            return "Samsung Browser" + samsungMatcher.group(1);
        }
        // Opera浏览器
        Matcher operaMatcher = OPERA_PATTERN.matcher(browser);
        if (operaMatcher.find())
        {
            return "Opera" + operaMatcher.group(1);
        }
        // IE浏览器
        Matcher ieMatcher = IE_PATTERN.matcher(browser);
        if (ieMatcher.find())
        {
            return "Internet Explorer" + ieMatcher.group(1);
        }
        return UNKNOWN;
    }
    /**
     * æ£€æµ‹æ“ä½œç³»ç»Ÿ
     */
    private static String formatOperatingSystem(String operatingSystem)
    {
        // Windows系统
        Matcher windowsMatcher = WINDOWS_PATTERN.matcher(operatingSystem);
        if (windowsMatcher.find())
        {
            return "Windows" + getWindowsVersionDisplay(windowsMatcher.group(1));
        }
        // macOS系统
        Matcher macMatcher = MACOS_PATTERN.matcher(operatingSystem);
        if (macMatcher.find())
        {
            String version = macMatcher.group(1).replace("_", ".");
            return "macOS" + extractMajorVersion(version);
        }
        // Android系统
        Matcher androidMatcher = ANDROID_PATTERN.matcher(operatingSystem);
        if (androidMatcher.find())
        {
            return "Android" + extractMajorVersion(androidMatcher.group(1));
        }
        // iOS系统
        Matcher iosMatcher = IOS_PATTERN.matcher(operatingSystem);
        if (iosMatcher.find() && (operatingSystem.contains("iPhone") || operatingSystem.contains("iPad")))
        {
            return "iOS" + extractMajorVersion(iosMatcher.group(1));
        }
        // Linux系统
        if (LINUX_PATTERN.matcher(operatingSystem).find() && !operatingSystem.contains("Android"))
        {
            return "Linux";
        }
        // Chrome OS
        if (CHROMEOS_PATTERN.matcher(operatingSystem).find())
        {
            return "Chrome OS";
        }
        return UNKNOWN;
    }
    /**
     * æå–优化的主版本号
     */
    private static String extractMajorVersion(String fullVersion)
    {
        if (StringUtils.isEmpty(fullVersion))
        {
            return StringUtils.EMPTY;
        }
        try
        {
            // æ¸…理版本号中的非数字字符
            String cleanVersion = fullVersion.replaceAll("[^0-9.]", "");
            String[] parts = cleanVersion.split("\\.");
            if (parts.length > 0)
            {
                String firstPart = parts[0];
                if (firstPart.matches("\\d+"))
                {
                    int version = Integer.parseInt(firstPart);
                    // å¤„理三位数版本号(如142 -> 14)
                    if (version >= 100)
                    {
                        return String.valueOf(version / 10);
                    }
                    return firstPart;
                }
            }
        }
        catch (NumberFormatException e)
        {
            // ç‰ˆæœ¬å·è§£æžå¤±è´¥ï¼Œè¿”回原始值
        }
        return fullVersion;
    }
    /**
     * Windows版本号显示优化
     */
    private static String getWindowsVersionDisplay(String version)
    {
        switch (version)
        {
            case "10.0":
                return "10";
            case "6.3":
                return "8.1";
            case "6.2":
                return "8";
            case "6.1":
                return "7";
            case "6.0":
                return "Vista";
            case "5.1":
                return "XP";
            case "5.0":
                return "2000";
            default:
                return extractMajorVersion(version);
        }
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,56 @@
package com.ruoyi.common.utils.ip;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
/**
 * èŽ·å–åœ°å€ç±»
 *
 * @author ruoyi
 */
public class AddressUtils
{
    private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
    // IP地址查询
    public static final String IP_URL = "https://whois.pconline.com.cn/ipJson.jsp";
    // æœªçŸ¥åœ°å€
    public static final String UNKNOWN = "XX XX";
    public static String getRealAddressByIP(String ip)
    {
        // å†…网不查询
        if (IpUtils.internalIp(ip))
        {
            return "内网IP";
        }
        if (RuoYiConfig.isAddressEnabled())
        {
            try
            {
                String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
                if (StringUtils.isEmpty(rspStr))
                {
                    log.error("获取地理位置异常 {}", ip);
                    return UNKNOWN;
                }
                JSONObject obj = JSON.parseObject(rspStr);
                String region = obj.getString("pro");
                String city = obj.getString("city");
                return String.format("%s %s", region, city);
            }
            catch (Exception e)
            {
                log.error("获取地理位置异常 {}", ip);
            }
        }
        return UNKNOWN;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,382 @@
package com.ruoyi.common.utils.ip;
import java.net.InetAddress;
import java.net.UnknownHostException;
import jakarta.servlet.http.HttpServletRequest;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
/**
 * èŽ·å–IP方法
 *
 * @author ruoyi
 */
public class IpUtils
{
    public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
    // åŒ¹é… ip
    public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
    public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
    // åŒ¹é…ç½‘段
    public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
    /**
     * èŽ·å–å®¢æˆ·ç«¯IP
     *
     * @return IP地址
     */
    public static String getIpAddr()
    {
        return getIpAddr(ServletUtils.getRequest());
    }
    /**
     * èŽ·å–å®¢æˆ·ç«¯IP
     *
     * @param request è¯·æ±‚对象
     * @return IP地址
     */
    public static String getIpAddr(HttpServletRequest request)
    {
        if (request == null)
        {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
        {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
    }
    /**
     * æ£€æŸ¥æ˜¯å¦ä¸ºå†…部IP地址
     *
     * @param ip IP地址
     * @return ç»“æžœ
     */
    public static boolean internalIp(String ip)
    {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }
    /**
     * æ£€æŸ¥æ˜¯å¦ä¸ºå†…部IP地址
     *
     * @param addr byte地址
     * @return ç»“æžœ
     */
    private static boolean internalIp(byte[] addr)
    {
        if (StringUtils.isNull(addr) || addr.length < 2)
        {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0)
        {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4)
                {
                    return true;
                }
            case SECTION_5:
                switch (b1)
                {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }
    /**
     * å°†IPv4地址转换成字节
     *
     * @param text IPv4地址
     * @return byte å­—节
     */
    public static byte[] textToNumericFormatV4(String text)
    {
        if (text.length() == 0)
        {
            return null;
        }
        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try
        {
            long l;
            int i;
            switch (elements.length)
            {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                    {
                        return null;
                    }
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                    {
                        return null;
                    }
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        }
        catch (NumberFormatException e)
        {
            return null;
        }
        return bytes;
    }
    /**
     * èŽ·å–IP地址
     *
     * @return æœ¬åœ°IP地址
     */
    public static String getHostIp()
    {
        try
        {
            return InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException e)
        {
        }
        return "127.0.0.1";
    }
    /**
     * èŽ·å–ä¸»æœºå
     *
     * @return æœ¬åœ°ä¸»æœºå
     */
    public static String getHostName()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e)
        {
        }
        return "未知";
    }
    /**
     * ä»Žå¤šçº§åå‘代理中获得第一个非unknown IP地址
     *
     * @param ip èŽ·å¾—çš„IP地址
     * @return ç¬¬ä¸€ä¸ªéžunknown IP地址
     */
    public static String getMultistageReverseProxyIp(String ip)
    {
        // å¤šçº§åå‘代理检测
        if (ip != null && ip.indexOf(",") > 0)
        {
            final String[] ips = ip.trim().split(",");
            for (String subIp : ips)
            {
                if (false == isUnknown(subIp))
                {
                    ip = subIp;
                    break;
                }
            }
        }
        return StringUtils.substring(ip, 0, 255);
    }
    /**
     * æ£€æµ‹ç»™å®šå­—符串是否为未知,多用于检测HTTP请求相关
     *
     * @param checkString è¢«æ£€æµ‹çš„字符串
     * @return æ˜¯å¦æœªçŸ¥
     */
    public static boolean isUnknown(String checkString)
    {
        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
    }
    /**
     * æ˜¯å¦ä¸ºIP
     */
    public static boolean isIP(String ip)
    {
        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
    }
    /**
     * æ˜¯å¦ä¸ºIP,或 *为间隔的通配符地址
     */
    public static boolean isIpWildCard(String ip)
    {
        return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
    }
    /**
     * æ£€æµ‹å‚数是否在ip通配符里
     */
    public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
    {
        String[] s1 = ipWildCard.split("\\.");
        String[] s2 = ip.split("\\.");
        boolean isMatchedSeg = true;
        for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
        {
            if (!s1[i].equals(s2[i]))
            {
                isMatchedSeg = false;
                break;
            }
        }
        return isMatchedSeg;
    }
    /**
     * æ˜¯å¦ä¸ºç‰¹å®šæ ¼å¼å¦‚:“10.10.10.1-10.10.10.99”的ip段字符串
     */
    public static boolean isIPSegment(String ipSeg)
    {
        return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
    }
    /**
     * åˆ¤æ–­ip是否在指定网段中
     */
    public static boolean ipIsInNetNoCheck(String iparea, String ip)
    {
        int idx = iparea.indexOf('-');
        String[] sips = iparea.substring(0, idx).split("\\.");
        String[] sipe = iparea.substring(idx + 1).split("\\.");
        String[] sipt = ip.split("\\.");
        long ips = 0L, ipe = 0L, ipt = 0L;
        for (int i = 0; i < 4; ++i)
        {
            ips = ips << 8 | Integer.parseInt(sips[i]);
            ipe = ipe << 8 | Integer.parseInt(sipe[i]);
            ipt = ipt << 8 | Integer.parseInt(sipt[i]);
        }
        if (ips > ipe)
        {
            long t = ips;
            ips = ipe;
            ipe = t;
        }
        return ips <= ipt && ipt <= ipe;
    }
    /**
     * æ ¡éªŒip是否符合过滤串规则
     *
     * @param filter è¿‡æ»¤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99`
     * @param ip æ ¡éªŒIP地址
     * @return boolean ç»“æžœ
     */
    public static boolean isMatchedIp(String filter, String ip)
    {
        if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
        {
            return false;
        }
        String[] ips = filter.split(";");
        for (String iStr : ips)
        {
            if (isIP(iStr) && iStr.equals(ip))
            {
                return true;
            }
            else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
            {
                return true;
            }
            else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
            {
                return true;
            }
        }
        return false;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.common.utils.poi;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Workbook;
/**
 * Excel数据格式处理适配器
 *
 * @author ruoyi
 */
public interface ExcelHandlerAdapter
{
    /**
     * æ ¼å¼åŒ–
     *
     * @param value å•元格数据值
     * @param args excel注解args参数组
     * @param cell å•元格对象
     * @param wb å·¥ä½œç°¿å¯¹è±¡
     *
     * @return å¤„理后的值
     */
    Object format(Object value, String[] args, Cell cell, Workbook wb);
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelSheet.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
package com.ruoyi.common.utils.poi;
import java.util.ArrayList;
import java.util.List;
/**
 * å¤š Sheet å¯¼å‡ºæ—¶çš„æ•°æ®ä¿¡æ¯
 *
 * ä½¿ç”¨ç¤ºä¾‹ï¼š
 * <pre>
 *   List<ExcelSheet<?>> sheets = new ArrayList<>();
 *   sheets.add(new ExcelSheet<>("参数数据", configList, Config.class, "参数信息"));
 *   sheets.add(new ExcelSheet<>("岗位数据", postList, Post.class, "岗位信息"));
 *   return ExcelUtil.exportMultiSheet(sheets);
 * </pre>
 *
 * @author ruoyi
 */
public class ExcelSheet<T>
{
    /** Sheet åç§° */
    private String sheetName;
    /** å¯¼å‡ºæ•°æ®é›†åˆ */
    private List<T> list;
    /** æ•°æ®å¯¹åº”的实体 Class */
    private Class<T> clazz;
    /** Sheet é¡¶éƒ¨å¤§æ ‡é¢˜ï¼ˆå¯ä¸ºç©ºï¼‰ */
    private String title;
    public ExcelSheet(String sheetName, List<T> list, Class<T> clazz)
    {
        this(sheetName, list, clazz, "");
    }
    public ExcelSheet(String sheetName, List<T> list, Class<T> clazz, String title)
    {
        this.sheetName = sheetName;
        this.list = list != null ? list : new ArrayList<>();
        this.clazz = clazz;
        this.title = title != null ? title : "";
    }
    public String getSheetName()
    {
        return sheetName;
    }
    public List<T> getList()
    {
        return list;
    }
    public Class<T> getClazz()
    {
        return clazz;
    }
    public String getTitle()
    {
        return title;
    }
    public void setSheetName(String sheetName)
    {
        this.sheetName = sheetName;
    }
    public void setList(List<T> list)
    {
        this.list = list;
    }
    public void setClazz(Class<T> clazz)
    {
        this.clazz = clazz;
    }
    public void setTitle(String title)
    {
        this.title = title;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,2067 @@
package com.ruoyi.common.utils.poi;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFPicture;
import org.apache.poi.hssf.usermodel.HSSFPictureData;
import org.apache.poi.hssf.usermodel.HSSFShape;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.DataValidation;
import org.apache.poi.ss.usermodel.DataValidationConstraint;
import org.apache.poi.ss.usermodel.DataValidationHelper;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.annotation.Excel.ColumnType;
import com.ruoyi.common.annotation.Excel.Type;
import com.ruoyi.common.annotation.Excels;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileTypeUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.ImageUtils;
import com.ruoyi.common.utils.reflect.ReflectUtils;
/**
 * Excel相关处理
 *
 * @author ruoyi
 */
public class ExcelUtil<T>
{
    private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
    public static final String SEPARATOR = ",";
    public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
    public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
    /**
     * ç”¨äºŽdictType属性数据存储,避免重复查缓存
     */
    public Map<String, String> sysDictMap = new HashMap<String, String>();
    /**
     * å•元格样式缓存
     */
    private Map<String, CellStyle> cellStyleCache = new HashMap<String, CellStyle>();
    /**
     * Excel sheet最大行数,默认65536
     */
    public static final int sheetSize = 65536;
    /**
     * å·¥ä½œè¡¨åç§°
     */
    private String sheetName;
    /**
     * å¯¼å‡ºç±»åž‹ï¼ˆEXPORT:导出数据;IMPORT:导入模板)
     */
    private Type type;
    /**
     * å·¥ä½œè–„对象
     */
    private Workbook wb;
    /**
     * å·¥ä½œè¡¨å¯¹è±¡
     */
    private Sheet sheet;
    /**
     * æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> styles;
    /**
     * å¯¼å…¥å¯¼å‡ºæ•°æ®åˆ—表
     */
    private List<T> list;
    /**
     * æ³¨è§£åˆ—表
     */
    private List<Object[]> fields;
    /**
     * å½“前行号
     */
    private int rownum;
    /**
     * æ ‡é¢˜
     */
    private String title;
    /**
     * æœ€å¤§é«˜åº¦
     */
    private short maxHeight;
    /**
     * åˆå¹¶åŽæœ€åŽè¡Œæ•°
     */
    private int subMergedLastRowNum = 0;
    /**
     * åˆå¹¶åŽå¼€å§‹è¡Œæ•°
     */
    private int subMergedFirstRowNum = 1;
    /**
     * å¯¹è±¡çš„子列表方法
     */
    private Map<String, Method> subMethods;
    /**
     * å¯¹è±¡çš„子列表属性
     */
    private Map<String, List<Field>> subFieldsMap;
    /**
     * ç»Ÿè®¡åˆ—表
     */
    private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
    /**
     * å®žä½“对象
     */
    public Class<T> clazz;
    /**
     * éœ€è¦æ˜¾ç¤ºåˆ—属性
     */
    public String[] includeFields;
    /**
     * éœ€è¦æŽ’除列属性
     */
    public String[] excludeFields;
    public ExcelUtil(Class<T> clazz)
    {
        this.clazz = clazz;
    }
    /**
     * ä»…在Excel中显示列属性
     *
     * @param fields åˆ—属性名 ç¤ºä¾‹[单个"name"/多个"id","name"]
     */
    public void showColumn(String... fields)
    {
        this.includeFields = fields;
    }
    /**
     * éšè—Excel中列属性
     *
     * @param fields åˆ—属性名 ç¤ºä¾‹[单个"name"/多个"id","name"]
     */
    public void hideColumn(String... fields)
    {
        this.excludeFields = fields;
    }
    public void init(List<T> list, String sheetName, String title, Type type)
    {
        if (list == null)
        {
            list = new ArrayList<T>();
        }
        this.list = list;
        this.sheetName = sheetName;
        this.type = type;
        this.title = title;
        createExcelField();
        createWorkbook();
        createTitle();
        createSubHead();
    }
    /**
     * åˆ›å»ºexcel第一行标题
     */
    public void createTitle()
    {
        if (StringUtils.isNotEmpty(title))
        {
            int titleLastCol = this.fields.size() - 1;
            if (isSubList())
            {
                for (List<Field> currentSubFields : subFieldsMap.values())
                {
                    titleLastCol = titleLastCol + currentSubFields.size() - 1;
                }
            }
            Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
            titleRow.setHeightInPoints(30);
            Cell titleCell = titleRow.createCell(0);
            titleCell.setCellStyle(styles.get("title"));
            titleCell.setCellValue(title);
            sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
        }
    }
    /**
     * åˆ›å»ºå¯¹è±¡çš„子列表名称
     */
    public void createSubHead()
    {
        if (isSubList())
        {
            Row subRow = sheet.createRow(rownum);
            int column = 0;
            for (Object[] objects : fields)
            {
                Field field = (Field) objects[0];
                Excel attr = (Excel) objects[1];
                CellStyle cellStyle = styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor()));
                if (Collection.class.isAssignableFrom(field.getType()))
                {
                    Cell cell = subRow.createCell(column);
                    cell.setCellValue(attr.name());
                    cell.setCellStyle(cellStyle);
                    int subFieldSize = subFieldsMap != null ? subFieldsMap.get(field.getName()).size() : 0;
                    if (subFieldSize > 1)
                    {
                        CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
                        sheet.addMergedRegion(cellAddress);
                    }
                    column += subFieldSize;
                }
                else
                {
                    Cell cell = subRow.createCell(column++);
                    cell.setCellValue(attr.name());
                    cell.setCellStyle(cellStyle);
                }
            }
            rownum++;
        }
    }
    /**
     * å¯¹excel表单默认第一个索引名转换成list
     *
     * @param is è¾“入流
     * @return è½¬æ¢åŽé›†åˆ
     */
    public List<T> importExcel(InputStream is)
    {
        return importExcel(is, 0);
    }
    /**
     * å¯¹excel表单默认第一个索引名转换成list
     *
     * @param is è¾“入流
     * @param titleNum æ ‡é¢˜å ç”¨è¡Œæ•°
     * @return è½¬æ¢åŽé›†åˆ
     */
    public List<T> importExcel(InputStream is, int titleNum)
    {
        List<T> list = null;
        try
        {
            list = importExcel(StringUtils.EMPTY, is, titleNum);
        }
        catch (Exception e)
        {
            log.error("导入Excel异常{}", e.getMessage());
            throw new UtilException(e.getMessage());
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
        return list;
    }
    /**
     * å¯¹excel表单指定表格索引名转换成list
     *
     * @param sheetName è¡¨æ ¼ç´¢å¼•名
     * @param titleNum æ ‡é¢˜å ç”¨è¡Œæ•°
     * @param is è¾“入流
     * @return è½¬æ¢åŽé›†åˆ
     */
    public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
    {
        this.type = Type.IMPORT;
        this.wb = WorkbookFactory.create(is);
        List<T> list = new ArrayList<T>();
        // å¦‚果指定sheet名,则取指定sheet中的内容 å¦åˆ™é»˜è®¤æŒ‡å‘第1个sheet
        Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
        if (sheet == null)
        {
            throw new IOException("文件sheet不存在");
        }
        boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
        Map<String, List<PictureData>> pictures = null;
        if (isXSSFWorkbook)
        {
            pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
        }
        else
        {
            pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
        }
        // èŽ·å–æœ€åŽä¸€ä¸ªéžç©ºè¡Œçš„è¡Œä¸‹æ ‡ï¼Œæ¯”å¦‚æ€»è¡Œæ•°ä¸ºn,则返回的为n-1
        int rows = sheet.getLastRowNum();
        if (rows > 0)
        {
            // å®šä¹‰ä¸€ä¸ªmap用于存放excel列的序号和field.
            Map<String, Integer> cellMap = new HashMap<String, Integer>();
            // èŽ·å–è¡¨å¤´
            Row heard = sheet.getRow(titleNum);
            if (heard == null)
            {
                throw new UtilException("文件标题行为空,请检查Excel文件格式");
            }
            for (int i = 0; i < heard.getLastCellNum(); i++)
            {
                Cell cell = heard.getCell(i);
                if (StringUtils.isNotNull(cell))
                {
                    String value = this.getCellValue(heard, i).toString();
                    cellMap.put(value, i);
                }
            }
            // æœ‰æ•°æ®æ—¶æ‰å¤„理 å¾—到类的所有field.
            List<Object[]> fields = this.getFields();
            Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
            for (Object[] objects : fields)
            {
                Excel attr = (Excel) objects[1];
                Integer column = cellMap.get(attr.name());
                if (column != null)
                {
                    fieldsMap.put(column, objects);
                }
            }
            for (int i = titleNum + 1; i <= rows; i++)
            {
                // ä»Žç¬¬2行开始取数据,默认第一行是表头.
                Row row = sheet.getRow(i);
                // åˆ¤æ–­å½“前行是否是空行
                if (isRowEmpty(row))
                {
                    continue;
                }
                T entity = null;
                for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
                {
                    Object val = this.getCellValue(row, entry.getKey());
                    // å¦‚果不存在实例则新建.
                    entity = (entity == null ? clazz.getDeclaredConstructor().newInstance() : entity);
                    // ä»Žmap中得到对应列的field.
                    Field field = (Field) entry.getValue()[0];
                    Excel attr = (Excel) entry.getValue()[1];
                    // å–得类型,并根据对象类型设置值.
                    Class<?> fieldType = field.getType();
                    if (String.class == fieldType)
                    {
                        String s = Convert.toStr(val);
                        if (s.matches("^\\d+\\.0$"))
                        {
                            val = StringUtils.substringBefore(s, ".0");
                        }
                        else
                        {
                            String dateFormat = field.getAnnotation(Excel.class).dateFormat();
                            if (StringUtils.isNotEmpty(dateFormat))
                            {
                                val = parseDateToStr(dateFormat, val);
                            }
                            else
                            {
                                val = Convert.toStr(val);
                            }
                        }
                    }
                    else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
                    {
                        val = Convert.toInt(val);
                    }
                    else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
                    {
                        val = Convert.toLong(val);
                    }
                    else if (Double.TYPE == fieldType || Double.class == fieldType)
                    {
                        val = Convert.toDouble(val);
                    }
                    else if (Float.TYPE == fieldType || Float.class == fieldType)
                    {
                        val = Convert.toFloat(val);
                    }
                    else if (BigDecimal.class == fieldType)
                    {
                        val = Convert.toBigDecimal(val);
                    }
                    else if (Date.class == fieldType)
                    {
                        if (val instanceof String)
                        {
                            val = DateUtils.parseDate(val);
                        }
                        else if (val instanceof Double)
                        {
                            val = DateUtil.getJavaDate((Double) val);
                        }
                    }
                    else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
                    {
                        val = Convert.toBool(val, false);
                    }
                    if (StringUtils.isNotNull(fieldType))
                    {
                        String propertyName = field.getName();
                        if (StringUtils.isNotEmpty(attr.targetAttr()))
                        {
                            propertyName = field.getName() + "." + attr.targetAttr();
                        }
                        if (StringUtils.isNotEmpty(attr.readConverterExp()))
                        {
                            val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
                        }
                        else if (StringUtils.isNotEmpty(attr.dictType()))
                        {
                            if (!sysDictMap.containsKey(attr.dictType() + val))
                            {
                                String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
                                sysDictMap.put(attr.dictType() + val, dictValue);
                            }
                            val = sysDictMap.get(attr.dictType() + val);
                        }
                        else if (!attr.handler().equals(ExcelHandlerAdapter.class))
                        {
                            val = dataFormatHandlerAdapter(val, attr, null);
                        }
                        else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
                        {
                            StringBuilder propertyString = new StringBuilder();
                            List<PictureData> images = pictures.get(row.getRowNum() + "_" + entry.getKey());
                            for (PictureData picture : images)
                            {
                                byte[] data = picture.getData();
                                String fileName = FileUtils.writeImportBytes(data);
                                propertyString.append(fileName).append(SEPARATOR);
                            }
                            val = StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
                        }
                        ReflectUtils.invokeSetter(entity, propertyName, val);
                    }
                }
                list.add(entity);
            }
        }
        return list;
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public AjaxResult exportExcel(List<T> list, String sheetName)
    {
        return exportExcel(list, sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public AjaxResult exportExcel(List<T> list, String sheetName, String title)
    {
        this.init(list, sheetName, title, Type.EXPORT);
        return exportExcel();
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param response è¿”回数据
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
    {
        exportExcel(response, list, sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param response è¿”回数据
     * @param list å¯¼å‡ºæ•°æ®é›†åˆ
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
    {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        this.init(list, sheetName, title, Type.EXPORT);
        exportExcel(response);
    }
    /**
     * å¤š Sheet å¯¼å‡º â€”— å°†å¤šä¸ªä¸åŒç±»åž‹çš„æ•°æ®é›†åˆå†™å…¥åŒä¸€ Excel,直接输出到 HttpServletResponse
     *
     * @param response HTTP å“åº”
     * @param sheets   Sheet æè¿°åˆ—表
     */
    public static void exportMultiSheet(HttpServletResponse response, List<ExcelSheet<?>> sheets)
    {
        if (sheets == null || sheets.isEmpty())
        {
            return;
        }
        SXSSFWorkbook wb = buildWorkbook(sheets);
        try
        {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            wb.write(response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("多Sheet导出Excel异常{}", e.getMessage());
        }
        finally
        {
            IOUtils.closeQuietly(wb);
        }
    }
    /**
     * å¤š Sheet å¯¼å‡º â€”— å°†å¤šä¸ªä¸åŒç±»åž‹çš„æ•°æ®é›†åˆå†™å…¥åŒä¸€ Excel,生成文件并返回下载地址
     *
     * @param sheets Sheet æè¿°åˆ—表
     * @return AjaxResult(含文件下载地址)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static AjaxResult exportMultiSheet(List<ExcelSheet<?>> sheets)
    {
        if (sheets == null || sheets.isEmpty())
        {
            return AjaxResult.error("导出数据不能为空");
        }
        SXSSFWorkbook wb = buildWorkbook(sheets);
        OutputStream out = null;
        try
        {
            ExcelUtil firstUtil = new ExcelUtil(sheets.get(0).getClazz());
            String filename = firstUtil.encodingFilename(sheets.get(0).getSheetName());
            out = new FileOutputStream(firstUtil.getAbsoluteFile(filename));
            wb.write(out);
            return AjaxResult.success(filename);
        }
        catch (Exception e)
        {
            log.error("多Sheet导出Excel异常{}", e.getMessage());
            throw new UtilException("导出Excel失败,请联系网站管理员!");
        }
        finally
        {
            IOUtils.closeQuietly(wb);
            IOUtils.closeQuietly(out);
        }
    }
    /**
     * æž„建多 Sheet Workbook â€”— åˆ›å»º SXSSFWorkbook å¹¶å°†æ‰€æœ‰ Sheet æ•°æ®å†™å…¥
     *
     * @param sheets Sheet æè¿°åˆ—表
     * @return å·²å†™å…¥æ‰€æœ‰ Sheet æ•°æ®çš„ SXSSFWorkbook
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static SXSSFWorkbook buildWorkbook(List<ExcelSheet<?>> sheets)
    {
        SXSSFWorkbook wb = new SXSSFWorkbook(500);
        for (ExcelSheet<?> excelSheet : sheets)
        {
            ExcelUtil util = new ExcelUtil(excelSheet.getClazz());
            util.initWithWorkbook(wb, excelSheet.getList(), excelSheet.getSheetName(), excelSheet.getTitle());
            util.writeSheet();
        }
        return wb;
    }
    /**
     * ä½¿ç”¨å¤–部传入的 Workbook åˆå§‹åŒ–(多 Sheet å¯¼å‡ºä¸“用)
     * ä¸Ž init() çš„区别:不新建 Workbook,而是在已有 wb ä¸Šè¿½åŠ æ–° Sheet
     *
     * @param wb        å·²æœ‰å·¥ä½œç°¿
     * @param list      æ•°æ®é›†åˆ
     * @param sheetName Sheet åç§°
     * @param title     å¤§æ ‡é¢˜ï¼ˆå¯ä¸ºç©ºï¼‰
     */
    public void initWithWorkbook(SXSSFWorkbook wb, List<T> list, String sheetName, String title)
    {
        if (list == null)
        {
            list = new ArrayList<T>();
        }
        this.list      = list;
        this.sheetName = sheetName;
        this.title     = title != null ? title : "";
        this.type      = Type.EXPORT;
        this.rownum    = 0;
        this.wb        = wb;
        this.sheet     = wb.createSheet(sheetName);
        createExcelField();
        this.styles    = createStyles(wb);
        createTitle();
        createSubHead();
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public AjaxResult importTemplateExcel(String sheetName)
    {
        return importTemplateExcel(sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public AjaxResult importTemplateExcel(String sheetName, String title)
    {
        this.init(null, sheetName, title, Type.IMPORT);
        return exportExcel();
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @return ç»“æžœ
     */
    public void importTemplateExcel(HttpServletResponse response, String sheetName)
    {
        importTemplateExcel(response, sheetName, StringUtils.EMPTY);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @param sheetName å·¥ä½œè¡¨çš„名称
     * @param title æ ‡é¢˜
     * @return ç»“æžœ
     */
    public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
    {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        this.init(null, sheetName, title, Type.IMPORT);
        exportExcel(response);
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @return ç»“æžœ
     */
    public void exportExcel(HttpServletResponse response)
    {
        try
        {
            writeSheet();
            wb.write(response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
        }
        finally
        {
            IOUtils.closeQuietly(wb);
        }
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单
     *
     * @return ç»“æžœ
     */
    public AjaxResult exportExcel()
    {
        OutputStream out = null;
        try
        {
            writeSheet();
            String filename = encodingFilename(sheetName);
            out = new FileOutputStream(getAbsoluteFile(filename));
            wb.write(out);
            return AjaxResult.success(filename);
        }
        catch (Exception e)
        {
            log.error("导出Excel异常{}", e.getMessage());
            throw new UtilException("导出Excel失败,请联系网站管理员!");
        }
        finally
        {
            IOUtils.closeQuietly(wb);
            IOUtils.closeQuietly(out);
        }
    }
    /**
     * åˆ›å»ºå†™å…¥æ•°æ®åˆ°Sheet
     */
    public void writeSheet()
    {
        // å–出一共有多少个sheet.
        int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
        for (int index = 0; index < sheetNo; index++)
        {
            createSheet(sheetNo, index);
            // äº§ç”Ÿä¸€è¡Œ
            Row row = sheet.createRow(rownum);
            int column = 0;
            // å†™å…¥å„个字段的列头名称
            for (Object[] os : fields)
            {
                Field field = (Field) os[0];
                Excel excel = (Excel) os[1];
                if (Collection.class.isAssignableFrom(field.getType()))
                {
                    List<Field> currentSubFields = subFieldsMap.get(field.getName());
                    for (Field subField : currentSubFields)
                    {
                        Excel subExcel = subField.getAnnotation(Excel.class);
                        this.createHeadCell(subExcel, row, column++);
                    }
                }
                else
                {
                    this.createHeadCell(excel, row, column++);
                }
            }
            if (Type.EXPORT.equals(type))
            {
                fillExcelData(index);
                addStatisticsRow();
            }
        }
    }
    /**
     * å¡«å……excel数据
     *
     * @param index åºå·
     */
    @SuppressWarnings("unchecked")
    public void fillExcelData(int index)
    {
        int startNo = index * sheetSize;
        int endNo = Math.min(startNo + sheetSize, list.size());
        int currentRowNum = rownum + 1; // ä»Žæ ‡é¢˜è¡ŒåŽå¼€å§‹
        for (int i = startNo; i < endNo; i++)
        {
            Row row = sheet.createRow(currentRowNum);
            T vo = (T) list.get(i);
            int column = 0;
            int maxSubListSize = getCurrentMaxSubListSize(vo);
            for (Object[] os : fields)
            {
                Field field = (Field) os[0];
                Excel excel = (Excel) os[1];
                if (Collection.class.isAssignableFrom(field.getType()))
                {
                    try
                    {
                        Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
                        List<Field> currentSubFields = subFieldsMap.get(field.getName());
                        if (subList != null && !subList.isEmpty())
                        {
                            int subIndex = 0;
                            for (Object subVo : subList)
                            {
                                Row subRow = sheet.getRow(currentRowNum + subIndex);
                                if (subRow == null)
                                {
                                    subRow = sheet.createRow(currentRowNum + subIndex);
                                }
                                int subColumn = column;
                                for (Field subField : currentSubFields)
                                {
                                    Excel subExcel = subField.getAnnotation(Excel.class);
                                    addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
                                }
                                subIndex++;
                            }
                        }
                        column += currentSubFields.size();
                    }
                    catch (Exception e)
                    {
                        log.error("填充集合数据失败", e);
                    }
                }
                else
                {
                    // åˆ›å»ºå•元格并设置值
                    addCell(excel, row, vo, field, column);
                    if (maxSubListSize > 1 && excel.needMerge())
                    {
                        sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
                    }
                    column++;
                }
            }
            currentRowNum += maxSubListSize;
        }
    }
    /**
     * èŽ·å–å­åˆ—è¡¨æœ€å¤§æ•°
     */
    private int getCurrentMaxSubListSize(T vo)
    {
        int maxSubListSize = 1;
        for (Object[] os : fields)
        {
            Field field = (Field) os[0];
            if (Collection.class.isAssignableFrom(field.getType()))
            {
                try
                {
                    Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
                    if (subList != null && !subList.isEmpty())
                    {
                        maxSubListSize = Math.max(maxSubListSize, subList.size());
                    }
                }
                catch (Exception e)
                {
                    log.error("获取集合大小失败", e);
                }
            }
        }
        return maxSubListSize;
    }
    /**
     * åˆ›å»ºè¡¨æ ¼æ ·å¼
     *
     * @param wb å·¥ä½œè–„对象
     * @return æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> createStyles(Workbook wb)
    {
        // å†™å…¥å„条记录,每条记录对应excel表中的一行
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
        CellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        Font titleFont = wb.createFont();
        titleFont.setFontName("Arial");
        titleFont.setFontHeightInPoints((short) 16);
        titleFont.setBold(true);
        style.setFont(titleFont);
        DataFormat dataFormat = wb.createDataFormat();
        style.setDataFormat(dataFormat.getFormat("@"));
        styles.put("title", style);
        style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
        Font dataFont = wb.createFont();
        dataFont.setFontName("Arial");
        dataFont.setFontHeightInPoints((short) 10);
        style.setFont(dataFont);
        styles.put("data", style);
        style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setDataFormat(dataFormat.getFormat("######0.00"));
        Font totalFont = wb.createFont();
        totalFont.setFontName("Arial");
        totalFont.setFontHeightInPoints((short) 10);
        style.setFont(totalFont);
        styles.put("total", style);
        styles.putAll(annotationHeaderStyles(wb, styles));
        styles.putAll(annotationDataStyles(wb));
        return styles;
    }
    /**
     * æ ¹æ®Excel注解创建表格头样式
     *
     * @param wb å·¥ä½œè–„对象
     * @return è‡ªå®šä¹‰æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
    {
        Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
        for (Object[] os : fields)
        {
            Excel excel = (Excel) os[1];
            String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
            if (!headerStyles.containsKey(key))
            {
                CellStyle style = wb.createCellStyle();
                style.cloneStyleFrom(styles.get("data"));
                style.setAlignment(HorizontalAlignment.CENTER);
                style.setVerticalAlignment(VerticalAlignment.CENTER);
                style.setFillForegroundColor(excel.headerBackgroundColor().getIndex());
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                Font headerFont = wb.createFont();
                headerFont.setFontName("Arial");
                headerFont.setFontHeightInPoints((short) 10);
                headerFont.setBold(true);
                headerFont.setColor(excel.headerColor().getIndex());
                style.setFont(headerFont);
                // è®¾ç½®è¡¨æ ¼å¤´å•元格文本形式
                DataFormat dataFormat = wb.createDataFormat();
                style.setDataFormat(dataFormat.getFormat("@"));
                headerStyles.put(key, style);
            }
        }
        return headerStyles;
    }
    /**
     * æ ¹æ®Excel注解创建表格列样式
     *
     * @param wb å·¥ä½œè–„对象
     * @return è‡ªå®šä¹‰æ ·å¼åˆ—表
     */
    private Map<String, CellStyle> annotationDataStyles(Workbook wb)
    {
        Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
        for (Object[] os : fields)
        {
            Field field = (Field) os[0];
            Excel excel = (Excel) os[1];
            if (Collection.class.isAssignableFrom(field.getType()))
            {
                ParameterizedType pt = (ParameterizedType) field.getGenericType();
                Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
                List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
                for (Field subField : subFields)
                {
                    Excel subExcel = subField.getAnnotation(Excel.class);
                    annotationDataStyles(styles, subField, subExcel);
                }
            }
            else
            {
                annotationDataStyles(styles, field, excel);
            }
        }
        return styles;
    }
    /**
     * æ ¹æ®Excel注解创建表格列样式
     *
     * @param styles è‡ªå®šä¹‰æ ·å¼åˆ—表
     * @param field  å±žæ€§åˆ—信息
     * @param excel  æ³¨è§£ä¿¡æ¯
     */
    public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
    {
        String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
        if (!styles.containsKey(key))
        {
            CellStyle style = wb.createCellStyle();
            style.setAlignment(excel.align());
            style.setVerticalAlignment(VerticalAlignment.CENTER);
            style.setBorderRight(BorderStyle.THIN);
            style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            style.setBorderLeft(BorderStyle.THIN);
            style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            style.setBorderTop(BorderStyle.THIN);
            style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            style.setBorderBottom(BorderStyle.THIN);
            style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            style.setFillForegroundColor(excel.backgroundColor().getIndex());
            style.setWrapText(excel.wrapText());
            Font dataFont = wb.createFont();
            dataFont.setFontName("Arial");
            dataFont.setFontHeightInPoints((short) 10);
            dataFont.setColor(excel.color().getIndex());
            style.setFont(dataFont);
            if (ColumnType.TEXT == excel.cellType())
            {
                DataFormat dataFormat = wb.createDataFormat();
                style.setDataFormat(dataFormat.getFormat("@"));
            }
            styles.put(key, style);
        }
    }
    /**
     * åˆ›å»ºå•元格
     */
    public Cell createHeadCell(Excel attr, Row row, int column)
    {
        // åˆ›å»ºåˆ—
        Cell cell = row.createCell(column);
        // å†™å…¥åˆ—信息
        cell.setCellValue(attr.name());
        setDataValidation(attr, row, column);
        cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
        if (isSubList())
        {
            // å¡«å……默认样式,防止合并单元格样式失效
            sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
            if (attr.needMerge())
            {
                sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
            }
        }
        return cell;
    }
    /**
     * è®¾ç½®å•元格信息
     *
     * @param value å•元格值
     * @param attr æ³¨è§£ç›¸å…³
     * @param cell å•元格信息
     */
    public void setCellVo(Object value, Excel attr, Cell cell)
    {
        if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
        {
            String cellValue = Convert.toStr(value);
            // å¯¹äºŽä»»ä½•以表达式触发字符 =-+@开头的单元格,直接使用tab字符作为前缀,防止CSV注入。
            if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
            {
                cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
            }
            if (value instanceof Collection && StringUtils.equals("[]", cellValue))
            {
                cellValue = StringUtils.EMPTY;
            }
            cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
        }
        else if (ColumnType.NUMERIC == attr.cellType())
        {
            if (StringUtils.isNotNull(value))
            {
                cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
            }
        }
        else if (ColumnType.IMAGE == attr.cellType())
        {
            ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
            String propertyValue = Convert.toStr(value);
            if (StringUtils.isNotEmpty(propertyValue))
            {
                List<String> imagePaths = StringUtils.str2List(propertyValue, SEPARATOR);
                for (String imagePath : imagePaths)
                {
                    byte[] data = ImageUtils.getImage(imagePath);
                    getDrawingPatriarch(cell.getSheet()).createPicture(anchor, cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
                }
            }
        }
    }
    /**
     * èŽ·å–ç”»å¸ƒ
     */
    public static Drawing<?> getDrawingPatriarch(Sheet sheet)
    {
        if (sheet.getDrawingPatriarch() == null)
        {
            sheet.createDrawingPatriarch();
        }
        return sheet.getDrawingPatriarch();
    }
    /**
     * èŽ·å–å›¾ç‰‡ç±»åž‹,设置图片插入类型
     */
    public int getImageType(byte[] value)
    {
        String type = FileTypeUtils.getFileExtendName(value);
        if ("JPG".equalsIgnoreCase(type))
        {
            return Workbook.PICTURE_TYPE_JPEG;
        }
        else if ("PNG".equalsIgnoreCase(type))
        {
            return Workbook.PICTURE_TYPE_PNG;
        }
        return Workbook.PICTURE_TYPE_JPEG;
    }
    /**
     * åˆ›å»ºè¡¨æ ¼æ ·å¼
     */
    public void setDataValidation(Excel attr, Row row, int column)
    {
        if (attr.name().indexOf("注:") >= 0)
        {
            sheet.setColumnWidth(column, 6000);
        }
        else
        {
            // è®¾ç½®åˆ—宽
            sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
        }
        if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict())
        {
            String[] comboArray = attr.combo();
            if (attr.comboReadDict())
            {
                if (!sysDictMap.containsKey("combo_" + attr.dictType()))
                {
                    String labels = DictUtils.getDictLabels(attr.dictType());
                    sysDictMap.put("combo_" + attr.dictType(), labels);
                }
                String val = sysDictMap.get("combo_" + attr.dictType());
                comboArray = StringUtils.split(val, DictUtils.SEPARATOR);
            }
            if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
            {
                // å¦‚果下拉数大于15或字符串长度大于255,则使用一个新sheet存储,避免生成的模板下拉值获取不到
                setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
            }
            else
            {
                // æç¤ºä¿¡æ¯æˆ–只能选择不能输入的列内容.
                setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column);
            }
        }
    }
    /**
     * æ·»åŠ å•å…ƒæ ¼
     */
    @SuppressWarnings("deprecation")
    public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
    {
        Cell cell = null;
        try
        {
            // è®¾ç½®è¡Œé«˜
            row.setHeight(maxHeight);
            // æ ¹æ®Excel中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
            if (attr.isExport())
            {
                // åˆ›å»ºcell
                cell = row.createCell(column);
                if (isSubListValue(vo) && getListCellValue(vo) > 1 && attr.needMerge())
                {
                    if (subMergedLastRowNum >= subMergedFirstRowNum)
                    {
                        sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
                    }
                }
                cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
                // ç”¨äºŽè¯»å–对象中的属性
                Object value = getTargetValue(vo, field, attr);
                String dateFormat = attr.dateFormat();
                String readConverterExp = attr.readConverterExp();
                String separator = attr.separator();
                String dictType = attr.dictType();
                if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
                {
                    cell.setCellStyle(createCellStyle(cell.getCellStyle(), dateFormat));
                    cell.setCellValue(parseDateToStr(dateFormat, value));
                }
                else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
                {
                    cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
                }
                else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
                {
                    if (!sysDictMap.containsKey(dictType + value))
                    {
                        String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
                        sysDictMap.put(dictType + value, lable);
                    }
                    cell.setCellValue(sysDictMap.get(dictType + value));
                }
                else if (value instanceof BigDecimal && -1 != attr.scale())
                {
                    cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
                }
                else if (!attr.handler().equals(ExcelHandlerAdapter.class))
                {
                    cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
                }
                else
                {
                    // è®¾ç½®åˆ—类型
                    setCellVo(value, attr, cell);
                }
                addStatisticsData(column, Convert.toStr(value), attr);
            }
        }
        catch (Exception e)
        {
            log.error("导出Excel失败{}", e);
        }
        return cell;
    }
    /**
     * ä½¿ç”¨è‡ªå®šä¹‰æ ¼å¼ï¼ŒåŒæ—¶é¿å…æ ·å¼æ±¡æŸ“
     *
     * @param cellStyle ä»Žæ­¤æ ·å¼å¤åˆ¶
     * @param format æ ¼å¼åŒ¹é…çš„字符串
     * @return æ ¼å¼åŒ–后CellStyle对象
     */
    private CellStyle createCellStyle(CellStyle cellStyle, String format)
    {
        String key = cellStyle.getIndex() + "|" + format;
        CellStyle cached = cellStyleCache.get(key);
        if (cached != null)
        {
            return cached;
        }
        CellStyle style = wb.createCellStyle();
        style.cloneStyleFrom(cellStyle);
        style.setDataFormat(wb.getCreationHelper().createDataFormat().getFormat(format));
        cellStyleCache.put(key, style);
        return style;
    }
    /**
     * è®¾ç½® POI XSSFSheet å•元格提示或选择框
     *
     * @param sheet è¡¨å•
     * @param textlist ä¸‹æ‹‰æ¡†æ˜¾ç¤ºçš„内容
     * @param promptContent æç¤ºå†…容
     * @param firstRow å¼€å§‹è¡Œ
     * @param endRow ç»“束行
     * @param firstCol å¼€å§‹åˆ—
     * @param endCol ç»“束列
     */
    public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
            int firstCol, int endCol)
    {
        DataValidationHelper helper = sheet.getDataValidationHelper();
        DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        DataValidation dataValidation = helper.createValidation(constraint, regions);
        if (StringUtils.isNotEmpty(promptContent))
        {
            // å¦‚果设置了提示信息则鼠标放上去提示
            dataValidation.createPromptBox("", promptContent);
            dataValidation.setShowPromptBox(true);
        }
        // å¤„理Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation)
        {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        }
        else
        {
            dataValidation.setSuppressDropDownArrow(false);
        }
        sheet.addValidationData(dataValidation);
    }
    /**
     * è®¾ç½®æŸäº›åˆ—的值只能输入预制的数据,显示下拉框(兼容超出一定数量的下拉框).
     *
     * @param sheet è¦è®¾ç½®çš„sheet.
     * @param textlist ä¸‹æ‹‰æ¡†æ˜¾ç¤ºçš„内容
     * @param promptContent æç¤ºå†…容
     * @param firstRow å¼€å§‹è¡Œ
     * @param endRow ç»“束行
     * @param firstCol å¼€å§‹åˆ—
     * @param endCol ç»“束列
     */
    public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
    {
        String hideSheetName = "combo_" + firstCol + "_" + endCol;
        Sheet hideSheet = null;
        String hideSheetDataName = hideSheetName + "_data";
        Name name = wb.getName(hideSheetDataName);
        if (name != null)
        {
            // åç§°å·²å­˜åœ¨ï¼Œå°è¯•从名称的引用中找到sheet名称
            String refersToFormula = name.getRefersToFormula();
            if (StringUtils.isNotEmpty(refersToFormula) && refersToFormula.contains("!"))
            {
                String sheetNameFromFormula = refersToFormula.substring(0, refersToFormula.indexOf("!"));
                hideSheet = wb.getSheet(sheetNameFromFormula);
            }
        }
        if (hideSheet == null)
        {
            hideSheet = wb.createSheet(hideSheetName); // ç”¨äºŽå­˜å‚¨ ä¸‹æ‹‰èœå•数据
            for (int i = 0; i < textlist.length; i++)
            {
                hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
            }
            // åˆ›å»ºåç§°ï¼Œå¯è¢«å…¶ä»–单元格引用
            name = wb.createName();
            name.setNameName(hideSheetDataName);
            name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
        }
        DataValidationHelper helper = sheet.getDataValidationHelper();
        // åŠ è½½ä¸‹æ‹‰åˆ—è¡¨å†…å®¹
        DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetDataName);
        // è®¾ç½®æ•°æ®æœ‰æ•ˆæ€§åŠ è½½åœ¨å“ªä¸ªå•å…ƒæ ¼ä¸Š,四个参数分别是:起始行、终止行、起始列、终止列
        CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
        // æ•°æ®æœ‰æ•ˆæ€§å¯¹è±¡
        DataValidation dataValidation = helper.createValidation(constraint, regions);
        if (StringUtils.isNotEmpty(promptContent))
        {
            // å¦‚果设置了提示信息则鼠标放上去提示
            dataValidation.createPromptBox("", promptContent);
            dataValidation.setShowPromptBox(true);
        }
        // å¤„理Excel兼容性问题
        if (dataValidation instanceof XSSFDataValidation)
        {
            dataValidation.setSuppressDropDownArrow(true);
            dataValidation.setShowErrorBox(true);
        }
        else
        {
            dataValidation.setSuppressDropDownArrow(false);
        }
        sheet.addValidationData(dataValidation);
        // è®¾ç½®hiddenSheet隐藏
        wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
    }
    /**
     * è§£æžå¯¼å‡ºå€¼ 0=男,1=女,2=未知
     *
     * @param propertyValue å‚数值
     * @param converterExp ç¿»è¯‘注解
     * @param separator åˆ†éš”符
     * @return è§£æžåŽå€¼
     */
    public static String convertByExp(String propertyValue, String converterExp, String separator)
    {
        StringBuilder propertyString = new StringBuilder();
        String[] convertSource = converterExp.split(SEPARATOR);
        for (String item : convertSource)
        {
            String[] itemArray = item.split("=");
            if (StringUtils.containsAny(propertyValue, separator))
            {
                for (String value : propertyValue.split(separator))
                {
                    if (itemArray[0].equals(value))
                    {
                        propertyString.append(itemArray[1] + separator);
                        break;
                    }
                }
            }
            else
            {
                if (itemArray[0].equals(propertyValue))
                {
                    return itemArray[1];
                }
            }
        }
        return StringUtils.stripEnd(propertyString.toString(), separator);
    }
    /**
     * åå‘解析值 ç”·=0,女=1,未知=2
     *
     * @param propertyValue å‚数值
     * @param converterExp ç¿»è¯‘注解
     * @param separator åˆ†éš”符
     * @return è§£æžåŽå€¼
     */
    public static String reverseByExp(String propertyValue, String converterExp, String separator)
    {
        StringBuilder propertyString = new StringBuilder();
        String[] convertSource = converterExp.split(SEPARATOR);
        for (String item : convertSource)
        {
            String[] itemArray = item.split("=");
            if (StringUtils.containsAny(propertyValue, separator))
            {
                for (String value : propertyValue.split(separator))
                {
                    if (itemArray[1].equals(value))
                    {
                        propertyString.append(itemArray[0] + separator);
                        break;
                    }
                }
            }
            else
            {
                if (itemArray[1].equals(propertyValue))
                {
                    return itemArray[0];
                }
            }
        }
        return StringUtils.stripEnd(propertyString.toString(), separator);
    }
    /**
     * è§£æžå­—典值
     *
     * @param dictValue å­—典值
     * @param dictType å­—典类型
     * @param separator åˆ†éš”符
     * @return å­—典标签
     */
    public static String convertDictByExp(String dictValue, String dictType, String separator)
    {
        return DictUtils.getDictLabel(dictType, dictValue, separator);
    }
    /**
     * åå‘解析值字典值
     *
     * @param dictLabel å­—典标签
     * @param dictType å­—典类型
     * @param separator åˆ†éš”符
     * @return å­—典值
     */
    public static String reverseDictByExp(String dictLabel, String dictType, String separator)
    {
        return DictUtils.getDictValue(dictType, dictLabel, separator);
    }
    /**
     * æ•°æ®å¤„理器
     *
     * @param value æ•°æ®å€¼
     * @param excel æ•°æ®æ³¨è§£
     * @return
     */
    public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
    {
        try
        {
            Object instance = excel.handler().getDeclaredConstructor().newInstance();
            Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
            value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
        }
        catch (Exception e)
        {
            log.error("不能格式化数据 " + excel.handler(), e.getMessage());
        }
        return Convert.toStr(value);
    }
    /**
     * åˆè®¡ç»Ÿè®¡ä¿¡æ¯
     */
    private void addStatisticsData(Integer index, String text, Excel entity)
    {
        if (entity != null && entity.isStatistics())
        {
            Double temp = 0D;
            if (!statistics.containsKey(index))
            {
                statistics.put(index, temp);
            }
            try
            {
                temp = Double.valueOf(text);
            }
            catch (NumberFormatException e)
            {
            }
            statistics.put(index, statistics.get(index) + temp);
        }
    }
    /**
     * åˆ›å»ºç»Ÿè®¡è¡Œ
     */
    public void addStatisticsRow()
    {
        if (statistics.size() > 0)
        {
            Row row = sheet.createRow(sheet.getLastRowNum() + 1);
            Set<Integer> keys = statistics.keySet();
            Cell cell = row.createCell(0);
            cell.setCellStyle(styles.get("total"));
            cell.setCellValue("合计");
            for (Integer key : keys)
            {
                cell = row.createCell(key);
                cell.setCellStyle(styles.get("total"));
                cell.setCellValue(statistics.get(key));
            }
            statistics.clear();
        }
    }
    /**
     * ç¼–码文件名
     */
    public String encodingFilename(String filename)
    {
        return UUID.randomUUID() + "_" + filename + ".xlsx";
    }
    /**
     * èŽ·å–ä¸‹è½½è·¯å¾„
     *
     * @param filename æ–‡ä»¶åç§°
     */
    public String getAbsoluteFile(String filename)
    {
        String downloadPath = RuoYiConfig.getDownloadPath() + filename;
        File desc = new File(downloadPath);
        if (!desc.getParentFile().exists())
        {
            desc.getParentFile().mkdirs();
        }
        return downloadPath;
    }
    /**
     * èŽ·å–bean中的属性值
     *
     * @param vo å®žä½“对象
     * @param field å­—段
     * @param excel æ³¨è§£
     * @return æœ€ç»ˆçš„属性值
     * @throws Exception
     */
    private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
    {
        field.setAccessible(true);
        Object o = field.get(vo);
        if (StringUtils.isNotEmpty(excel.targetAttr()))
        {
            String target = excel.targetAttr();
            if (target.contains("."))
            {
                String[] targets = target.split("[.]");
                for (String name : targets)
                {
                    o = getValue(o, name);
                }
            }
            else
            {
                o = getValue(o, target);
            }
        }
        return o;
    }
    /**
     * ä»¥ç±»çš„属性的get方法方法形式获取值
     *
     * @param o
     * @param name
     * @return value
     * @throws Exception
     */
    private Object getValue(Object o, String name) throws Exception
    {
        if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
        {
            Class<?> clazz = o.getClass();
            Field field = clazz.getDeclaredField(name);
            field.setAccessible(true);
            o = field.get(o);
        }
        return o;
    }
    /**
     * å¾—到所有定义字段
     */
    private void createExcelField()
    {
        this.fields = getFields();
        this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
        this.maxHeight = getRowHeight();
    }
    /**
     * èŽ·å–å­—æ®µæ³¨è§£ä¿¡æ¯
     */
    public List<Object[]> getFields()
    {
        List<Object[]> fields = new ArrayList<Object[]>();
        List<Field> tempFields = new ArrayList<>();
        subFieldsMap = new HashMap<>();
        subMethods = new HashMap<>();
        tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
        tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        if (StringUtils.isNotEmpty(includeFields))
        {
            for (Field field : tempFields)
            {
                if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
                {
                    addField(fields, field);
                }
            }
        }
        else if (StringUtils.isNotEmpty(excludeFields))
        {
            for (Field field : tempFields)
            {
                if (!ArrayUtils.contains(this.excludeFields, field.getName()))
                {
                    addField(fields, field);
                }
            }
        }
        else
        {
            for (Field field : tempFields)
            {
                addField(fields, field);
            }
        }
        return fields;
    }
    /**
     * æ·»åŠ å­—æ®µä¿¡æ¯
     */
    public void addField(List<Object[]> fields, Field field)
    {
        // å•注解
        if (field.isAnnotationPresent(Excel.class))
        {
            Excel attr = field.getAnnotation(Excel.class);
            if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
            {
                fields.add(new Object[] { field, attr });
            }
            if (Collection.class.isAssignableFrom(field.getType()))
            {
                String fieldName = field.getName();
                subMethods.put(fieldName, getSubMethod(fieldName, clazz));
                ParameterizedType pt = (ParameterizedType) field.getGenericType();
                Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
                subFieldsMap.put(fieldName, FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class));
            }
        }
        // å¤šæ³¨è§£
        if (field.isAnnotationPresent(Excels.class))
        {
            Excels attrs = field.getAnnotation(Excels.class);
            Excel[] excels = attrs.value();
            for (Excel attr : excels)
            {
                if (StringUtils.isNotEmpty(includeFields))
                {
                    if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
                            && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
                    {
                        fields.add(new Object[] { field, attr });
                    }
                }
                else
                {
                    if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
                            && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
                    {
                        fields.add(new Object[] { field, attr });
                    }
                }
            }
        }
    }
    /**
     * æ ¹æ®æ³¨è§£èŽ·å–æœ€å¤§è¡Œé«˜
     */
    public short getRowHeight()
    {
        double maxHeight = 0;
        for (Object[] os : this.fields)
        {
            Excel excel = (Excel) os[1];
            maxHeight = Math.max(maxHeight, excel.height());
        }
        return (short) (maxHeight * 20);
    }
    /**
     * åˆ›å»ºä¸€ä¸ªå·¥ä½œç°¿
     */
    public void createWorkbook()
    {
        this.wb = new SXSSFWorkbook(500);
        this.sheet = wb.createSheet();
        wb.setSheetName(0, sheetName);
        this.styles = createStyles(wb);
    }
    /**
     * åˆ›å»ºå·¥ä½œè¡¨
     *
     * @param sheetNo sheet数量
     * @param index åºå·
     */
    public void createSheet(int sheetNo, int index)
    {
        // è®¾ç½®å·¥ä½œè¡¨çš„名称.
        if (sheetNo > 1 && index > 0)
        {
            this.sheet = wb.createSheet();
            this.createTitle();
            int actualIndex = wb.getSheetIndex(this.sheet);
            wb.setSheetName(actualIndex, sheetName + index);
        }
    }
    /**
     * èŽ·å–å•å…ƒæ ¼å€¼
     *
     * @param row èŽ·å–çš„è¡Œ
     * @param column èŽ·å–å•å…ƒæ ¼åˆ—å·
     * @return å•元格值
     */
    public Object getCellValue(Row row, int column)
    {
        if (row == null)
        {
            return row;
        }
        Object val = "";
        try
        {
            Cell cell = row.getCell(column);
            if (StringUtils.isNotNull(cell))
            {
                if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
                {
                    val = cell.getNumericCellValue();
                    if (DateUtil.isCellDateFormatted(cell))
                    {
                        val = DateUtil.getJavaDate((Double) val); // POI Excel æ—¥æœŸæ ¼å¼è½¬æ¢
                    }
                    else
                    {
                        if ((Double) val % 1 != 0)
                        {
                            val = new BigDecimal(val.toString());
                        }
                        else
                        {
                            val = new DecimalFormat("0").format(val);
                        }
                    }
                }
                else if (cell.getCellType() == CellType.STRING)
                {
                    val = cell.getStringCellValue();
                }
                else if (cell.getCellType() == CellType.BOOLEAN)
                {
                    val = cell.getBooleanCellValue();
                }
                else if (cell.getCellType() == CellType.ERROR)
                {
                    val = cell.getErrorCellValue();
                }
            }
        }
        catch (Exception e)
        {
            return val;
        }
        return val;
    }
    /**
     * åˆ¤æ–­æ˜¯å¦æ˜¯ç©ºè¡Œ
     *
     * @param row åˆ¤æ–­çš„行
     * @return
     */
    private boolean isRowEmpty(Row row)
    {
        if (row == null)
        {
            return true;
        }
        for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
        {
            Cell cell = row.getCell(i);
            if (cell != null && cell.getCellType() != CellType.BLANK)
            {
                return false;
            }
        }
        return true;
    }
    /**
     * èŽ·å–Excel2003图片
     *
     * @param sheet å½“前sheet对象
     * @param workbook å·¥ä½œç°¿å¯¹è±¡
     * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData
     */
    public static Map<String, List<PictureData>> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
    {
        Map<String, List<PictureData>> sheetIndexPicMap = new HashMap<>();
        List<HSSFPictureData> pictures = workbook.getAllPictures();
        if (!pictures.isEmpty() && sheet.getDrawingPatriarch() != null)
        {
            for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
            {
                if (shape instanceof HSSFPicture)
                {
                    HSSFPicture pic = (HSSFPicture) shape;
                    HSSFClientAnchor anchor = (HSSFClientAnchor) pic.getAnchor();
                    String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
                    sheetIndexPicMap.computeIfAbsent(picIndex, k -> new ArrayList<>()).add(pic.getPictureData());
                }
            }
        }
        return sheetIndexPicMap;
    }
    /**
     * èŽ·å–Excel2007图片
     *
     * @param sheet å½“前sheet对象
     * @param workbook å·¥ä½œç°¿å¯¹è±¡
     * @return Map key:图片单元格索引(1_1)String,value:图片流PictureData
     */
    public static Map<String, List<PictureData>> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
    {
        Map<String, List<PictureData>> sheetIndexPicMap = new HashMap<>();
        for (POIXMLDocumentPart dr : sheet.getRelations())
        {
            if (dr instanceof XSSFDrawing)
            {
                XSSFDrawing drawing = (XSSFDrawing) dr;
                for (XSSFShape shape : drawing.getShapes())
                {
                    if (shape instanceof XSSFPicture)
                    {
                        XSSFPicture pic = (XSSFPicture) shape;
                        XSSFClientAnchor anchor = pic.getPreferredSize();
                        CTMarker ctMarker = anchor.getFrom();
                        String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
                        sheetIndexPicMap.computeIfAbsent(picIndex, k -> new ArrayList<>()).add(pic.getPictureData());
                    }
                }
            }
        }
        return sheetIndexPicMap;
    }
    /**
     * æ ¼å¼åŒ–不同类型的日期对象
     *
     * @param dateFormat æ—¥æœŸæ ¼å¼
     * @param val è¢«æ ¼å¼åŒ–的日期对象
     * @return æ ¼å¼åŒ–后的日期字符
     */
    public String parseDateToStr(String dateFormat, Object val)
    {
        if (val == null)
        {
            return "";
        }
        String str;
        if (val instanceof Date)
        {
            str = DateUtils.parseDateToStr(dateFormat, (Date) val);
        }
        else if (val instanceof LocalDateTime)
        {
            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
        }
        else if (val instanceof LocalDate)
        {
            str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
        }
        else
        {
            str = val.toString();
        }
        return str;
    }
    /**
     * æ˜¯å¦æœ‰å¯¹è±¡çš„子列表
     */
    public boolean isSubList()
    {
        return !StringUtils.isEmpty(subFieldsMap);
    }
    /**
     * æ˜¯å¦æœ‰å¯¹è±¡çš„子列表,集合不为空
     */
    public boolean isSubListValue(T vo)
    {
        return !StringUtils.isEmpty(subFieldsMap) && getListCellValue(vo) > 0;
    }
    /**
     * èŽ·å–é›†åˆçš„å€¼
     */
    public int getListCellValue(Object obj)
    {
        Collection<?> value;
        int max = 0;
        try
        {
            for (String s : subMethods.keySet())
            {
                value = (Collection<?>) subMethods.get(s).invoke(obj);
                if (value.size() > max)
                {
                    max = value.size();
                }
            }
        }
        catch (Exception e)
        {
            return 0;
        }
        return max;
    }
    /**
     * èŽ·å–å¯¹è±¡çš„å­åˆ—è¡¨æ–¹æ³•
     *
     * @param name åç§°
     * @param pojoClass ç±»å¯¹è±¡
     * @return å­åˆ—表方法
     */
    public Method getSubMethod(String name, Class<?> pojoClass)
    {
        StringBuffer getMethodName = new StringBuffer("get");
        getMethodName.append(name.substring(0, 1).toUpperCase());
        getMethodName.append(name.substring(1));
        Method method = null;
        try
        {
            method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
        }
        catch (Exception e)
        {
            log.error("获取对象异常{}", e.getMessage());
        }
        return method;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,412 @@
package com.ruoyi.common.utils.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import org.apache.commons.lang3.Validate;
import org.apache.poi.ss.usermodel.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
/**
 * åå°„工具类. æä¾›è°ƒç”¨getter/setter方法, è®¿é—®ç§æœ‰å˜é‡, è°ƒç”¨ç§æœ‰æ–¹æ³•, èŽ·å–æ³›åž‹ç±»åž‹Class, è¢«AOP过的真实类等工具函数.
 *
 * @author ruoyi
 */
@SuppressWarnings("rawtypes")
public class ReflectUtils
{
    private static final String SETTER_PREFIX = "set";
    private static final String GETTER_PREFIX = "get";
    private static final String CGLIB_CLASS_SEPARATOR = "$$";
    private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
    /**
     * è°ƒç”¨Getter方法.
     * æ”¯æŒå¤šçº§ï¼Œå¦‚:对象名.对象名.方法
     */
    @SuppressWarnings("unchecked")
    public static <E> E invokeGetter(Object obj, String propertyName)
    {
        Object object = obj;
        for (String name : StringUtils.split(propertyName, "."))
        {
            String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
            object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
        }
        return (E) object;
    }
    /**
     * è°ƒç”¨Setter方法, ä»…匹配方法名。
     * æ”¯æŒå¤šçº§ï¼Œå¦‚:对象名.对象名.方法
     */
    public static <E> void invokeSetter(Object obj, String propertyName, E value)
    {
        Object object = obj;
        String[] names = StringUtils.split(propertyName, ".");
        for (int i = 0; i < names.length; i++)
        {
            if (i < names.length - 1)
            {
                String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
            }
            else
            {
                String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
                invokeMethodByName(object, setterMethodName, new Object[] { value });
            }
        }
    }
    /**
     * ç›´æŽ¥è¯»å–对象属性值, æ— è§†private/protected修饰符, ä¸ç»è¿‡getter函数.
     */
    @SuppressWarnings("unchecked")
    public static <E> E getFieldValue(final Object obj, final String fieldName)
    {
        Field field = getAccessibleField(obj, fieldName);
        if (field == null)
        {
            logger.debug("在 [" + obj.getClass() + "] ä¸­ï¼Œæ²¡æœ‰æ‰¾åˆ° [" + fieldName + "] å­—段 ");
            return null;
        }
        E result = null;
        try
        {
            result = (E) field.get(obj);
        }
        catch (IllegalAccessException e)
        {
            logger.error("不可能抛出的异常{}", e.getMessage());
        }
        return result;
    }
    /**
     * ç›´æŽ¥è®¾ç½®å¯¹è±¡å±žæ€§å€¼, æ— è§†private/protected修饰符, ä¸ç»è¿‡setter函数.
     */
    public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
    {
        Field field = getAccessibleField(obj, fieldName);
        if (field == null)
        {
            // throw new IllegalArgumentException("在 [" + obj.getClass() + "] ä¸­ï¼Œæ²¡æœ‰æ‰¾åˆ° [" + fieldName + "] å­—段 ");
            logger.debug("在 [" + obj.getClass() + "] ä¸­ï¼Œæ²¡æœ‰æ‰¾åˆ° [" + fieldName + "] å­—段 ");
            return;
        }
        try
        {
            field.set(obj, value);
        }
        catch (IllegalAccessException e)
        {
            logger.error("不可能抛出的异常: {}", e.getMessage());
        }
    }
    /**
     * ç›´æŽ¥è°ƒç”¨å¯¹è±¡æ–¹æ³•, æ— è§†private/protected修饰符.
     * ç”¨äºŽä¸€æ¬¡æ€§è°ƒç”¨çš„æƒ…况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
     * åŒæ—¶åŒ¹é…æ–¹æ³•名+参数类型,
     */
    @SuppressWarnings("unchecked")
    public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
            final Object[] args)
    {
        if (obj == null || methodName == null)
        {
            return null;
        }
        Method method = getAccessibleMethod(obj, methodName, parameterTypes);
        if (method == null)
        {
            logger.debug("在 [" + obj.getClass() + "] ä¸­ï¼Œæ²¡æœ‰æ‰¾åˆ° [" + methodName + "] æ–¹æ³• ");
            return null;
        }
        try
        {
            return (E) method.invoke(obj, args);
        }
        catch (Exception e)
        {
            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
            throw convertReflectionExceptionToUnchecked(msg, e);
        }
    }
    /**
     * ç›´æŽ¥è°ƒç”¨å¯¹è±¡æ–¹æ³•, æ— è§†private/protected修饰符,
     * ç”¨äºŽä¸€æ¬¡æ€§è°ƒç”¨çš„æƒ…况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
     * åªåŒ¹é…å‡½æ•°åï¼Œå¦‚果有多个同名函数调用第一个。
     */
    @SuppressWarnings("unchecked")
    public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
    {
        Method method = getAccessibleMethodByName(obj, methodName, args.length);
        if (method == null)
        {
            // å¦‚果为空不报错,直接返回空。
            logger.debug("在 [" + obj.getClass() + "] ä¸­ï¼Œæ²¡æœ‰æ‰¾åˆ° [" + methodName + "] æ–¹æ³• ");
            return null;
        }
        try
        {
            // ç±»åž‹è½¬æ¢ï¼ˆå°†å‚数数据类型转换为目标方法参数类型)
            Class<?>[] cs = method.getParameterTypes();
            for (int i = 0; i < cs.length; i++)
            {
                if (args[i] != null && !args[i].getClass().equals(cs[i]))
                {
                    if (cs[i] == String.class)
                    {
                        args[i] = Convert.toStr(args[i]);
                        if (StringUtils.endsWith((String) args[i], ".0"))
                        {
                            args[i] = StringUtils.substringBefore((String) args[i], ".0");
                        }
                    }
                    else if (cs[i] == Integer.class)
                    {
                        args[i] = Convert.toInt(args[i]);
                    }
                    else if (cs[i] == Long.class)
                    {
                        args[i] = Convert.toLong(args[i]);
                    }
                    else if (cs[i] == Double.class)
                    {
                        args[i] = Convert.toDouble(args[i]);
                    }
                    else if (cs[i] == Float.class)
                    {
                        args[i] = Convert.toFloat(args[i]);
                    }
                    else if (cs[i] == Date.class)
                    {
                        if (args[i] instanceof String)
                        {
                            args[i] = DateUtils.parseDate(args[i]);
                        }
                        else
                        {
                            args[i] = DateUtil.getJavaDate((Double) args[i]);
                        }
                    }
                    else if (cs[i] == boolean.class || cs[i] == Boolean.class)
                    {
                        args[i] = Convert.toBool(args[i]);
                    }
                }
            }
            return (E) method.invoke(obj, args);
        }
        catch (Exception e)
        {
            String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
            throw convertReflectionExceptionToUnchecked(msg, e);
        }
    }
    /**
     * å¾ªçŽ¯å‘ä¸Šè½¬åž‹, èŽ·å–å¯¹è±¡çš„DeclaredField, å¹¶å¼ºåˆ¶è®¾ç½®ä¸ºå¯è®¿é—®.
     * å¦‚向上转型到Object仍无法找到, è¿”回null.
     */
    public static Field getAccessibleField(final Object obj, final String fieldName)
    {
        // ä¸ºç©ºä¸æŠ¥é”™ã€‚直接返回 null
        if (obj == null)
        {
            return null;
        }
        Validate.notBlank(fieldName, "fieldName can't be blank");
        for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
        {
            try
            {
                Field field = superClass.getDeclaredField(fieldName);
                makeAccessible(field);
                return field;
            }
            catch (NoSuchFieldException e)
            {
                continue;
            }
        }
        return null;
    }
    /**
     * å¾ªçŽ¯å‘ä¸Šè½¬åž‹, èŽ·å–å¯¹è±¡çš„DeclaredMethod,并强制设置为可访问.
     * å¦‚向上转型到Object仍无法找到, è¿”回null.
     * åŒ¹é…å‡½æ•°å+参数类型。
     * ç”¨äºŽæ–¹æ³•需要被多次调用的情况. å…ˆä½¿ç”¨æœ¬å‡½æ•°å…ˆå–å¾—Method,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method getAccessibleMethod(final Object obj, final String methodName,
            final Class<?>... parameterTypes)
    {
        // ä¸ºç©ºä¸æŠ¥é”™ã€‚直接返回 null
        if (obj == null)
        {
            return null;
        }
        Validate.notBlank(methodName, "methodName can't be blank");
        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
        {
            try
            {
                Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
                makeAccessible(method);
                return method;
            }
            catch (NoSuchMethodException e)
            {
                continue;
            }
        }
        return null;
    }
    /**
     * å¾ªçŽ¯å‘ä¸Šè½¬åž‹, èŽ·å–å¯¹è±¡çš„DeclaredMethod,并强制设置为可访问.
     * å¦‚向上转型到Object仍无法找到, è¿”回null.
     * åªåŒ¹é…å‡½æ•°åã€‚
     * ç”¨äºŽæ–¹æ³•需要被多次调用的情况. å…ˆä½¿ç”¨æœ¬å‡½æ•°å…ˆå–å¾—Method,然后调用Method.invoke(Object obj, Object... args)
     */
    public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
    {
        // ä¸ºç©ºä¸æŠ¥é”™ã€‚直接返回 null
        if (obj == null)
        {
            return null;
        }
        Validate.notBlank(methodName, "methodName can't be blank");
        for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
        {
            Method[] methods = searchType.getDeclaredMethods();
            for (Method method : methods)
            {
                if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
                {
                    makeAccessible(method);
                    return method;
                }
            }
        }
        return null;
    }
    /**
     * æ”¹å˜private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
     */
    @SuppressWarnings("deprecation")
    public static void makeAccessible(Method method)
    {
        if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
                && !method.isAccessible())
        {
            method.setAccessible(true);
        }
    }
    /**
     * æ”¹å˜private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
     */
    @SuppressWarnings("deprecation")
    public static void makeAccessible(Field field)
    {
        if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
                || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
        {
            field.setAccessible(true);
        }
    }
    /**
     * é€šè¿‡åå°„, èŽ·å¾—Class定义中声明的泛型参数的类型, æ³¨æ„æ³›åž‹å¿…须定义在父类处
     * å¦‚无法找到, è¿”回Object.class.
     */
    @SuppressWarnings("unchecked")
    public static <T> Class<T> getClassGenricType(final Class clazz)
    {
        return getClassGenricType(clazz, 0);
    }
    /**
     * é€šè¿‡åå°„, èŽ·å¾—Class定义中声明的父类的泛型参数的类型.
     * å¦‚无法找到, è¿”回Object.class.
     */
    public static Class getClassGenricType(final Class clazz, final int index)
    {
        Type genType = clazz.getGenericSuperclass();
        if (!(genType instanceof ParameterizedType))
        {
            logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
            return Object.class;
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        if (index >= params.length || index < 0)
        {
            logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                    + params.length);
            return Object.class;
        }
        if (!(params[index] instanceof Class))
        {
            logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
            return Object.class;
        }
        return (Class) params[index];
    }
    public static Class<?> getUserClass(Object instance)
    {
        if (instance == null)
        {
            throw new RuntimeException("Instance must not be null");
        }
        Class clazz = instance.getClass();
        if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
        {
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && !Object.class.equals(superClass))
            {
                return superClass;
            }
        }
        return clazz;
    }
    /**
     * å°†åå°„æ—¶çš„checked exception转换为unchecked exception.
     */
    public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
    {
        if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
                || e instanceof NoSuchMethodException)
        {
            return new IllegalArgumentException(msg, e);
        }
        else if (e instanceof InvocationTargetException)
        {
            return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
        }
        return new RuntimeException(msg, e);
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,291 @@
package com.ruoyi.common.utils.sign;
/**
 * Base64工具类
 *
 * @author ruoyi
 */
public final class Base64
{
    static private final int     BASELENGTH           = 128;
    static private final int     LOOKUPLENGTH         = 64;
    static private final int     TWENTYFOURBITGROUP   = 24;
    static private final int     EIGHTBIT             = 8;
    static private final int     SIXTEENBIT           = 16;
    static private final int     FOURBYTE             = 4;
    static private final int     SIGN                 = -128;
    static private final char    PAD                  = '=';
    static final private byte[]  base64Alphabet       = new byte[BASELENGTH];
    static final private char[]  lookUpBase64Alphabet = new char[LOOKUPLENGTH];
    static
    {
        for (int i = 0; i < BASELENGTH; ++i)
        {
            base64Alphabet[i] = -1;
        }
        for (int i = 'Z'; i >= 'A'; i--)
        {
            base64Alphabet[i] = (byte) (i - 'A');
        }
        for (int i = 'z'; i >= 'a'; i--)
        {
            base64Alphabet[i] = (byte) (i - 'a' + 26);
        }
        for (int i = '9'; i >= '0'; i--)
        {
            base64Alphabet[i] = (byte) (i - '0' + 52);
        }
        base64Alphabet['+'] = 62;
        base64Alphabet['/'] = 63;
        for (int i = 0; i <= 25; i++)
        {
            lookUpBase64Alphabet[i] = (char) ('A' + i);
        }
        for (int i = 26, j = 0; i <= 51; i++, j++)
        {
            lookUpBase64Alphabet[i] = (char) ('a' + j);
        }
        for (int i = 52, j = 0; i <= 61; i++, j++)
        {
            lookUpBase64Alphabet[i] = (char) ('0' + j);
        }
        lookUpBase64Alphabet[62] = (char) '+';
        lookUpBase64Alphabet[63] = (char) '/';
    }
    private static boolean isWhiteSpace(char octect)
    {
        return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
    }
    private static boolean isPad(char octect)
    {
        return (octect == PAD);
    }
    private static boolean isData(char octect)
    {
        return (octect < BASELENGTH && base64Alphabet[octect] != -1);
    }
    /**
     * Encodes hex octects into Base64
     *
     * @param binaryData Array containing binaryData
     * @return Encoded Base64 array
     */
    public static String encode(byte[] binaryData)
    {
        if (binaryData == null)
        {
            return null;
        }
        int lengthDataBits = binaryData.length * EIGHTBIT;
        if (lengthDataBits == 0)
        {
            return "";
        }
        int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
        int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
        int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
        char encodedData[] = null;
        encodedData = new char[numberQuartet * 4];
        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        for (int i = 0; i < numberTriplets; i++)
        {
            b1 = binaryData[dataIndex++];
            b2 = binaryData[dataIndex++];
            b3 = binaryData[dataIndex++];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
            byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
        }
        // form integral number of 6-bit groups
        if (fewerThan24bits == EIGHTBIT)
        {
            b1 = binaryData[dataIndex];
            k = (byte) (b1 & 0x03);
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
            encodedData[encodedIndex++] = PAD;
            encodedData[encodedIndex++] = PAD;
        }
        else if (fewerThan24bits == SIXTEENBIT)
        {
            b1 = binaryData[dataIndex];
            b2 = binaryData[dataIndex + 1];
            l = (byte) (b2 & 0x0f);
            k = (byte) (b1 & 0x03);
            byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
            byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
            encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
            encodedData[encodedIndex++] = PAD;
        }
        return new String(encodedData);
    }
    /**
     * Decodes Base64 data into octects
     *
     * @param encoded string containing Base64 data
     * @return Array containind decoded data.
     */
    public static byte[] decode(String encoded)
    {
        if (encoded == null)
        {
            return null;
        }
        char[] base64Data = encoded.toCharArray();
        // remove white spaces
        int len = removeWhiteSpace(base64Data);
        if (len % FOURBYTE != 0)
        {
            return null;// should be divisible by four
        }
        int numberQuadruple = (len / FOURBYTE);
        if (numberQuadruple == 0)
        {
            return new byte[0];
        }
        byte decodedData[] = null;
        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
        char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
        int i = 0;
        int encodedIndex = 0;
        int dataIndex = 0;
        decodedData = new byte[(numberQuadruple) * 3];
        for (; i < numberQuadruple - 1; i++)
        {
            if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
                    || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
            {
                return null;
            } // if found "no data" just return null
            b1 = base64Alphabet[d1];
            b2 = base64Alphabet[d2];
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }
        if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
        {
            return null;// if found "no data" just return null
        }
        b1 = base64Alphabet[d1];
        b2 = base64Alphabet[d2];
        d3 = base64Data[dataIndex++];
        d4 = base64Data[dataIndex++];
        if (!isData((d3)) || !isData((d4)))
        {// Check if they are PAD characters
            if (isPad(d3) && isPad(d4))
            {
                if ((b2 & 0xf) != 0)// last 4 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 1];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
                return tmp;
            }
            else if (!isPad(d3) && isPad(d4))
            {
                b3 = base64Alphabet[d3];
                if ((b3 & 0x3) != 0)// last 2 bits should be zero
                {
                    return null;
                }
                byte[] tmp = new byte[i * 3 + 2];
                System.arraycopy(decodedData, 0, tmp, 0, i * 3);
                tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
                tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
                return tmp;
            }
            else
            {
                return null;
            }
        }
        else
        { // No PAD e.g 3cQl
            b3 = base64Alphabet[d3];
            b4 = base64Alphabet[d4];
            decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
            decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
            decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
        }
        return decodedData;
    }
    /**
     * remove WhiteSpace from MIME containing encoded Base64 data.
     *
     * @param data the byte array of base64 data (with WS)
     * @return the new length
     */
    private static int removeWhiteSpace(char[] data)
    {
        if (data == null)
        {
            return 0;
        }
        // count characters that's not whitespace
        int newSize = 0;
        int len = data.length;
        for (int i = 0; i < len; i++)
        {
            if (!isWhiteSpace(data[i]))
            {
                data[newSize++] = data[i];
            }
        }
        return newSize;
    }
}
在上述文件截断后对比
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java ruoyi-framework/pom.xml ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/MyBatisConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java ruoyi-generator/pom.xml ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java ruoyi-generator/src/main/resources/generator.yml ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml ruoyi-generator/src/main/resources/vm/java/controller.java.vm ruoyi-generator/src/main/resources/vm/java/domain.java.vm ruoyi-generator/src/main/resources/vm/java/mapper.java.vm ruoyi-generator/src/main/resources/vm/java/service.java.vm ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm ruoyi-generator/src/main/resources/vm/js/api.js.vm ruoyi-generator/src/main/resources/vm/sql/sql.vm ruoyi-generator/src/main/resources/vm/ts/api.ts.vm ruoyi-generator/src/main/resources/vm/ts/index.ts.vm ruoyi-generator/src/main/resources/vm/ts/type.ts.vm ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm ruoyi-generator/src/main/resources/vm/vue/index.vue.vm ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm ruoyi-generator/src/main/resources/vm/vue/v3/view.vue.vm ruoyi-generator/src/main/resources/vm/vue/v3ts/index-tree.vue.vm ruoyi-generator/src/main/resources/vm/vue/v3ts/index.vue.vm ruoyi-generator/src/main/resources/vm/vue/v3ts/view.vue.vm ruoyi-generator/src/main/resources/vm/vue/view.vue.vm ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm ruoyi-quartz/pom.xml ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml ruoyi-system/pom.xml ruoyi-system/src/main/java/com/ruoyi/system/controller/CjClassController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjCollegeController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjFillTaskController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjFormConfigController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjMajorController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjStudentBindController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjStudentController.java ruoyi-system/src/main/java/com/ruoyi/system/controller/CjWorkbenchController.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjClass.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjCollege.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjFillRecord.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjFillTask.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjFormConfig.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjMajor.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjStudent.java ruoyi-system/src/main/java/com/ruoyi/system/domain/CjStudentBind.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNoticeRead.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjClassMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjCollegeMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjFillRecordMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjFillTaskMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjFormConfigMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjMajorMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjStudentBindMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/CjStudentMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeReadMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjClassService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjCollegeService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjFillTaskService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjFormConfigService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjMajorService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjStudentBindService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ICjStudentService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeReadService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java ruoyi-system/src/main/java/com/ruoyi/system/service/MiniappTokenService.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjClassServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjCollegeServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjFillTaskServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjFormConfigServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjMajorServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjStudentBindServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CjStudentServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeReadServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java ruoyi-system/src/main/resources/form/builtinDefault.json ruoyi-system/src/main/resources/mapper/system/CjClassMapper.xml ruoyi-system/src/main/resources/mapper/system/CjCollegeMapper.xml ruoyi-system/src/main/resources/mapper/system/CjFillRecordMapper.xml ruoyi-system/src/main/resources/mapper/system/CjFillTaskMapper.xml ruoyi-system/src/main/resources/mapper/system/CjFormConfigMapper.xml ruoyi-system/src/main/resources/mapper/system/CjMajorMapper.xml ruoyi-system/src/main/resources/mapper/system/CjStudentBindMapper.xml ruoyi-system/src/main/resources/mapper/system/CjStudentMapper.xml ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml ruoyi-system/src/main/resources/mapper/system/SysNoticeReadMapper.xml ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml ruoyi-ui/.env.development ruoyi-ui/.env.production ruoyi-ui/.env.staging ruoyi-ui/.github/FUNDING.yml ruoyi-ui/.gitignore ruoyi-ui/LICENSE ruoyi-ui/README.md ruoyi-ui/bin/build.bat ruoyi-ui/bin/package.bat ruoyi-ui/bin/run-web.bat ruoyi-ui/html/ie.html ruoyi-ui/index.html ruoyi-ui/package.json ruoyi-ui/public/favicon.ico ruoyi-ui/src/App.vue ruoyi-ui/src/api/login.js ruoyi-ui/src/api/menu.js ruoyi-ui/src/api/monitor/cache.js ruoyi-ui/src/api/monitor/job.js ruoyi-ui/src/api/monitor/jobLog.js ruoyi-ui/src/api/monitor/logininfor.js ruoyi-ui/src/api/monitor/online.js ruoyi-ui/src/api/monitor/operlog.js ruoyi-ui/src/api/monitor/server.js ruoyi-ui/src/api/system/class.js ruoyi-ui/src/api/system/college.js ruoyi-ui/src/api/system/config.js ruoyi-ui/src/api/system/dept.js ruoyi-ui/src/api/system/dict/data.js ruoyi-ui/src/api/system/dict/type.js ruoyi-ui/src/api/system/formConfig.js ruoyi-ui/src/api/system/formTask.js ruoyi-ui/src/api/system/major.js ruoyi-ui/src/api/system/menu.js ruoyi-ui/src/api/system/notice.js ruoyi-ui/src/api/system/post.js ruoyi-ui/src/api/system/role.js ruoyi-ui/src/api/system/student.js ruoyi-ui/src/api/system/user.js ruoyi-ui/src/api/system/workbench.js ruoyi-ui/src/api/tool/gen.js ruoyi-ui/src/assets/401_images/401.gif ruoyi-ui/src/assets/404_images/404.png ruoyi-ui/src/assets/404_images/404_cloud.png ruoyi-ui/src/assets/icons/svg/404.svg ruoyi-ui/src/assets/icons/svg/bell.svg ruoyi-ui/src/assets/icons/svg/bug.svg ruoyi-ui/src/assets/icons/svg/build.svg ruoyi-ui/src/assets/icons/svg/button.svg ruoyi-ui/src/assets/icons/svg/cascader.svg ruoyi-ui/src/assets/icons/svg/chart.svg ruoyi-ui/src/assets/icons/svg/checkbox.svg ruoyi-ui/src/assets/icons/svg/clipboard.svg ruoyi-ui/src/assets/icons/svg/code.svg ruoyi-ui/src/assets/icons/svg/color.svg ruoyi-ui/src/assets/icons/svg/component.svg ruoyi-ui/src/assets/icons/svg/dashboard.svg ruoyi-ui/src/assets/icons/svg/date-range.svg ruoyi-ui/src/assets/icons/svg/date.svg ruoyi-ui/src/assets/icons/svg/dict.svg ruoyi-ui/src/assets/icons/svg/documentation.svg ruoyi-ui/src/assets/icons/svg/download.svg ruoyi-ui/src/assets/icons/svg/drag.svg ruoyi-ui/src/assets/icons/svg/druid.svg ruoyi-ui/src/assets/icons/svg/edit.svg ruoyi-ui/src/assets/icons/svg/education.svg ruoyi-ui/src/assets/icons/svg/email.svg ruoyi-ui/src/assets/icons/svg/enter.svg ruoyi-ui/src/assets/icons/svg/example.svg ruoyi-ui/src/assets/icons/svg/excel.svg ruoyi-ui/src/assets/icons/svg/exit-fullscreen.svg ruoyi-ui/src/assets/icons/svg/eye-open.svg ruoyi-ui/src/assets/icons/svg/eye.svg ruoyi-ui/src/assets/icons/svg/form.svg ruoyi-ui/src/assets/icons/svg/fullscreen.svg ruoyi-ui/src/assets/icons/svg/github.svg ruoyi-ui/src/assets/icons/svg/guide.svg ruoyi-ui/src/assets/icons/svg/icon.svg ruoyi-ui/src/assets/icons/svg/input.svg ruoyi-ui/src/assets/icons/svg/international.svg ruoyi-ui/src/assets/icons/svg/job.svg ruoyi-ui/src/assets/icons/svg/language.svg ruoyi-ui/src/assets/icons/svg/link.svg ruoyi-ui/src/assets/icons/svg/list.svg ruoyi-ui/src/assets/icons/svg/lock.svg ruoyi-ui/src/assets/icons/svg/log.svg ruoyi-ui/src/assets/icons/svg/logininfor.svg ruoyi-ui/src/assets/icons/svg/message.svg ruoyi-ui/src/assets/icons/svg/money.svg ruoyi-ui/src/assets/icons/svg/monitor.svg ruoyi-ui/src/assets/icons/svg/moon.svg ruoyi-ui/src/assets/icons/svg/more-up.svg ruoyi-ui/src/assets/icons/svg/nested.svg ruoyi-ui/src/assets/icons/svg/number.svg ruoyi-ui/src/assets/icons/svg/online.svg ruoyi-ui/src/assets/icons/svg/password.svg ruoyi-ui/src/assets/icons/svg/pdf.svg ruoyi-ui/src/assets/icons/svg/people.svg ruoyi-ui/src/assets/icons/svg/peoples.svg ruoyi-ui/src/assets/icons/svg/phone.svg ruoyi-ui/src/assets/icons/svg/post.svg ruoyi-ui/src/assets/icons/svg/qq.svg ruoyi-ui/src/assets/icons/svg/question.svg ruoyi-ui/src/assets/icons/svg/radio.svg ruoyi-ui/src/assets/icons/svg/rate.svg ruoyi-ui/src/assets/icons/svg/redis-list.svg ruoyi-ui/src/assets/icons/svg/redis.svg ruoyi-ui/src/assets/icons/svg/row.svg ruoyi-ui/src/assets/icons/svg/search.svg ruoyi-ui/src/assets/icons/svg/select.svg ruoyi-ui/src/assets/icons/svg/server.svg ruoyi-ui/src/assets/icons/svg/shopping.svg ruoyi-ui/src/assets/icons/svg/size.svg ruoyi-ui/src/assets/icons/svg/skill.svg ruoyi-ui/src/assets/icons/svg/slider.svg ruoyi-ui/src/assets/icons/svg/star.svg ruoyi-ui/src/assets/icons/svg/sunny.svg ruoyi-ui/src/assets/icons/svg/swagger.svg ruoyi-ui/src/assets/icons/svg/switch.svg ruoyi-ui/src/assets/icons/svg/system.svg ruoyi-ui/src/assets/icons/svg/tab.svg ruoyi-ui/src/assets/icons/svg/table.svg ruoyi-ui/src/assets/icons/svg/textarea.svg ruoyi-ui/src/assets/icons/svg/theme.svg ruoyi-ui/src/assets/icons/svg/time-range.svg ruoyi-ui/src/assets/icons/svg/time.svg ruoyi-ui/src/assets/icons/svg/tool.svg ruoyi-ui/src/assets/icons/svg/tree-table.svg ruoyi-ui/src/assets/icons/svg/tree.svg ruoyi-ui/src/assets/icons/svg/upload.svg ruoyi-ui/src/assets/icons/svg/user.svg ruoyi-ui/src/assets/icons/svg/validCode.svg ruoyi-ui/src/assets/icons/svg/wechat.svg ruoyi-ui/src/assets/icons/svg/zip.svg ruoyi-ui/src/assets/images/brand/logo-navy.png ruoyi-ui/src/assets/images/brand/logo-white.png ruoyi-ui/src/assets/images/dark.svg ruoyi-ui/src/assets/images/light.svg ruoyi-ui/src/assets/images/login-background.jpg ruoyi-ui/src/assets/images/pay.png ruoyi-ui/src/assets/images/profile.jpg ruoyi-ui/src/assets/logo/logo-white.png ruoyi-ui/src/assets/logo/logo.png ruoyi-ui/src/assets/styles/btn.scss ruoyi-ui/src/assets/styles/element-ui.scss ruoyi-ui/src/assets/styles/index.scss ruoyi-ui/src/assets/styles/mixin.scss ruoyi-ui/src/assets/styles/ruoyi.scss ruoyi-ui/src/assets/styles/sidebar.scss ruoyi-ui/src/assets/styles/transition.scss ruoyi-ui/src/assets/styles/variables.module.scss ruoyi-ui/src/components/Breadcrumb/index.vue ruoyi-ui/src/components/Crontab/day.vue ruoyi-ui/src/components/Crontab/hour.vue ruoyi-ui/src/components/Crontab/index.vue ruoyi-ui/src/components/Crontab/min.vue ruoyi-ui/src/components/Crontab/month.vue ruoyi-ui/src/components/Crontab/result.vue ruoyi-ui/src/components/Crontab/second.vue ruoyi-ui/src/components/Crontab/week.vue ruoyi-ui/src/components/Crontab/year.vue ruoyi-ui/src/components/DictTag/index.vue ruoyi-ui/src/components/Editor/index.vue ruoyi-ui/src/components/ExcelImportDialog/index.vue ruoyi-ui/src/components/FileUpload/index.vue ruoyi-ui/src/components/Hamburger/index.vue ruoyi-ui/src/components/HeaderSearch/index.vue ruoyi-ui/src/components/IconSelect/index.vue ruoyi-ui/src/components/IconSelect/requireIcons.js ruoyi-ui/src/components/ImagePreview/index.vue ruoyi-ui/src/components/ImageUpload/index.vue ruoyi-ui/src/components/Pagination/index.vue ruoyi-ui/src/components/ParentView/index.vue ruoyi-ui/src/components/RightToolbar/index.vue ruoyi-ui/src/components/RuoYi/Doc/index.vue ruoyi-ui/src/components/RuoYi/Git/index.vue ruoyi-ui/src/components/Screenfull/index.vue ruoyi-ui/src/components/SizeSelect/index.vue ruoyi-ui/src/components/SvgIcon/index.vue ruoyi-ui/src/components/SvgIcon/svgicon.js ruoyi-ui/src/components/TreePanel/index.vue ruoyi-ui/src/components/iFrame/index.vue ruoyi-ui/src/directive/common/copyText.js ruoyi-ui/src/directive/index.js ruoyi-ui/src/directive/permission/hasPermi.js ruoyi-ui/src/directive/permission/hasRole.js ruoyi-ui/src/layout/components/AppMain.vue ruoyi-ui/src/layout/components/Copyright/index.vue ruoyi-ui/src/layout/components/HeaderNotice/DetailView.vue ruoyi-ui/src/layout/components/HeaderNotice/index.vue ruoyi-ui/src/layout/components/IframeToggle/index.vue ruoyi-ui/src/layout/components/InnerLink/index.vue ruoyi-ui/src/layout/components/Navbar.vue ruoyi-ui/src/layout/components/Settings/index.vue ruoyi-ui/src/layout/components/Sidebar/Link.vue ruoyi-ui/src/layout/components/Sidebar/Logo.vue ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue ruoyi-ui/src/layout/components/Sidebar/index.vue ruoyi-ui/src/layout/components/TagsView/ScrollPane.vue ruoyi-ui/src/layout/components/TagsView/index.vue ruoyi-ui/src/layout/components/TopBar/index.vue ruoyi-ui/src/layout/components/TopNav/index.vue ruoyi-ui/src/layout/components/index.js ruoyi-ui/src/layout/index.vue ruoyi-ui/src/main.js ruoyi-ui/src/permission.js ruoyi-ui/src/plugins/auth.js ruoyi-ui/src/plugins/cache.js ruoyi-ui/src/plugins/download.js ruoyi-ui/src/plugins/index.js ruoyi-ui/src/plugins/modal.js ruoyi-ui/src/plugins/tab.js ruoyi-ui/src/router/index.js ruoyi-ui/src/settings.js ruoyi-ui/src/store/index.js ruoyi-ui/src/store/modules/app.js ruoyi-ui/src/store/modules/dict.js ruoyi-ui/src/store/modules/lock.js ruoyi-ui/src/store/modules/permission.js ruoyi-ui/src/store/modules/settings.js ruoyi-ui/src/store/modules/tagsView.js ruoyi-ui/src/store/modules/user.js ruoyi-ui/src/utils/auth.js ruoyi-ui/src/utils/dict.js ruoyi-ui/src/utils/dynamicTitle.js ruoyi-ui/src/utils/errorCode.js ruoyi-ui/src/utils/generator/config.js ruoyi-ui/src/utils/generator/css.js ruoyi-ui/src/utils/generator/drawingDefault.js ruoyi-ui/src/utils/generator/html.js ruoyi-ui/src/utils/generator/icon.json ruoyi-ui/src/utils/generator/js.js ruoyi-ui/src/utils/generator/render.js ruoyi-ui/src/utils/index.js ruoyi-ui/src/utils/jsencrypt.js ruoyi-ui/src/utils/passwordRule.js ruoyi-ui/src/utils/permission.js ruoyi-ui/src/utils/qrcode-lite.js ruoyi-ui/src/utils/region.js ruoyi-ui/src/utils/request.js ruoyi-ui/src/utils/ruoyi.js ruoyi-ui/src/utils/scroll-to.js ruoyi-ui/src/utils/theme.js ruoyi-ui/src/utils/validate.js ruoyi-ui/src/views/error/401.vue ruoyi-ui/src/views/error/404.vue ruoyi-ui/src/views/index.vue ruoyi-ui/src/views/lock.vue ruoyi-ui/src/views/login.vue ruoyi-ui/src/views/monitor/logininfor/index.vue ruoyi-ui/src/views/redirect/index.vue ruoyi-ui/src/views/system/class/index.vue ruoyi-ui/src/views/system/college/index.vue ruoyi-ui/src/views/system/config/index.vue ruoyi-ui/src/views/system/dept/index.vue ruoyi-ui/src/views/system/dict/data.vue ruoyi-ui/src/views/system/dict/detail.vue ruoyi-ui/src/views/system/dict/index.vue ruoyi-ui/src/views/system/fillData/index.vue ruoyi-ui/src/views/system/formConfig/index.vue ruoyi-ui/src/views/system/formTask/index.vue ruoyi-ui/src/views/system/major/index.vue ruoyi-ui/src/views/system/menu/index.vue ruoyi-ui/src/views/system/notice/ReadUsers.vue ruoyi-ui/src/views/system/notice/index.vue ruoyi-ui/src/views/system/post/index.vue ruoyi-ui/src/views/system/role/authUser.vue ruoyi-ui/src/views/system/role/index.vue ruoyi-ui/src/views/system/role/selectUser.vue ruoyi-ui/src/views/system/student/index.vue ruoyi-ui/src/views/system/user/authRole.vue ruoyi-ui/src/views/system/user/index.vue ruoyi-ui/src/views/system/user/profile/index.vue ruoyi-ui/src/views/system/user/profile/resetPwd.vue ruoyi-ui/src/views/system/user/profile/userAvatar.vue ruoyi-ui/src/views/system/user/profile/userInfo.vue ruoyi-ui/src/views/system/user/view.vue ruoyi-ui/src/views/tool/gen/basicInfoForm.vue ruoyi-ui/src/views/tool/gen/createTable.vue ruoyi-ui/src/views/tool/gen/editTable.vue ruoyi-ui/src/views/tool/gen/genInfoForm.vue ruoyi-ui/src/views/tool/gen/importTable.vue ruoyi-ui/src/views/tool/gen/index.vue ruoyi-ui/vite.config.js ruoyi-ui/vite/plugins/auto-import.js ruoyi-ui/vite/plugins/compression.js ruoyi-ui/vite/plugins/index.js ruoyi-ui/vite/plugins/setup-extend.js ruoyi-ui/vite/plugins/svg-icon.js ry.bat ry.sh sql/quartz.sql sql/ry_20260417.sql src/main/java/com/ruoyi/RuoYiApplication.java (已删除) src/main/java/com/ruoyi/RuoYiServletInitializer.java (已删除) src/main/java/com/ruoyi/account/controller/AccountExpenseController.java (已删除) src/main/java/com/ruoyi/account/controller/AccountFileController.java (已删除) src/main/java/com/ruoyi/account/controller/AccountIncomeController.java (已删除) src/main/java/com/ruoyi/account/dto/AccountDto.java (已删除) src/main/java/com/ruoyi/account/dto/AccountDto2.java (已删除) src/main/java/com/ruoyi/account/dto/AccountDto3.java (已删除) src/main/java/com/ruoyi/account/mapper/AccountExpenseMapper.java (已删除) src/main/java/com/ruoyi/account/mapper/AccountFileMapper.java (已删除) src/main/java/com/ruoyi/account/mapper/AccountIncomeMapper.java (已删除) src/main/java/com/ruoyi/account/pojo/AccountExpense.java (已删除) src/main/java/com/ruoyi/account/pojo/AccountFile.java (已删除) src/main/java/com/ruoyi/account/pojo/AccountIncome.java (已删除) src/main/java/com/ruoyi/account/service/AccountExpenseService.java (已删除) src/main/java/com/ruoyi/account/service/AccountFileService.java (已删除) src/main/java/com/ruoyi/account/service/AccountIncomeService.java (已删除) src/main/java/com/ruoyi/account/service/impl/AccountExpenseServiceImpl.java (已删除) src/main/java/com/ruoyi/account/service/impl/AccountFileServiceImpl.java (已删除) src/main/java/com/ruoyi/account/service/impl/AccountIncomeServiceImpl.java (已删除) src/main/java/com/ruoyi/aftersalesservice/controller/AfterSalesServiceController.java (已删除) src/main/java/com/ruoyi/aftersalesservice/dto/AfterSalesServiceDto.java (已删除) src/main/java/com/ruoyi/aftersalesservice/mapper/AfterSalesServiceMapper.java (已删除) src/main/java/com/ruoyi/aftersalesservice/pojo/AfterSalesService.java (已删除) src/main/java/com/ruoyi/aftersalesservice/service/AfterSalesServiceService.java (已删除) src/main/java/com/ruoyi/aftersalesservice/service/impl/AfterSalesServiceServiceImpl.java (已删除) src/main/java/com/ruoyi/api/Api.java (已删除) src/main/java/com/ruoyi/api/ScheduledApi.java (已删除) src/main/java/com/ruoyi/api/dto/ApiProperties.java (已删除) src/main/java/com/ruoyi/api/dto/DataRequest.java (已删除) src/main/java/com/ruoyi/api/dto/ElectricityDto.java (已删除) src/main/java/com/ruoyi/api/dto/LoggingDto.java (已删除) src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java (已删除) src/main/java/com/ruoyi/approve/controller/ApproveProcessController.java (已删除) src/main/java/com/ruoyi/approve/controller/HolidaySettingsController.java (已删除) src/main/java/com/ruoyi/approve/controller/KnowledgeBaseController.java (已删除) src/main/java/com/ruoyi/approve/controller/NotificationManagementController.java (已删除) src/main/java/com/ruoyi/approve/controller/RpaProcessAutomationController.java (已删除) src/main/java/com/ruoyi/approve/mapper/AnnualLeaveSettingMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/ApproveLogMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/ApproveNodeMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/ApproveProcessMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/FileSharingMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/HolidaySettingsMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/KnowledgeBaseMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/NotificationManagementMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/OnlineMeetingMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/OvertimeSettingMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/RpaProcessAutomationMapper.java (已删除) src/main/java/com/ruoyi/approve/mapper/WorkingHoursSettingMapper.java (已删除) src/main/java/com/ruoyi/approve/pojo/AnnualLeaveSetting.java (已删除) src/main/java/com/ruoyi/approve/pojo/ApproveLog.java (已删除) src/main/java/com/ruoyi/approve/pojo/ApproveNode.java (已删除) src/main/java/com/ruoyi/approve/pojo/ApproveProcess.java (已删除) src/main/java/com/ruoyi/approve/pojo/FileSharing.java (已删除) src/main/java/com/ruoyi/approve/pojo/HolidaySettings.java (已删除) src/main/java/com/ruoyi/approve/pojo/KnowledgeBase.java (已删除) src/main/java/com/ruoyi/approve/pojo/NotificationManagement.java (已删除) src/main/java/com/ruoyi/approve/pojo/OnlineMeeting.java (已删除) src/main/java/com/ruoyi/approve/pojo/OvertimeSetting.java (已删除) src/main/java/com/ruoyi/approve/pojo/RpaProcessAutomation.java (已删除) src/main/java/com/ruoyi/approve/pojo/WorkingHoursSetting.java (已删除) src/main/java/com/ruoyi/approve/service/HolidaySettingsService.java (已删除) src/main/java/com/ruoyi/approve/service/IApproveNodeService.java (已删除) src/main/java/com/ruoyi/approve/service/IApproveProcessService.java (已删除) src/main/java/com/ruoyi/approve/service/KnowledgeBaseService.java (已删除) src/main/java/com/ruoyi/approve/service/NotificationManagementService.java (已删除) src/main/java/com/ruoyi/approve/service/RpaProcessAutomationService.java (已删除) src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java (已删除) src/main/java/com/ruoyi/approve/service/impl/ApproveProcessServiceImpl.java (已删除) src/main/java/com/ruoyi/approve/service/impl/HolidaySettingsServiceImpl.java (已删除) src/main/java/com/ruoyi/approve/service/impl/KnowledgeBaseServiceImpl.java (已删除) src/main/java/com/ruoyi/approve/service/impl/NotificationManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/approve/service/impl/RpaProcessAutomationServiceImpl.java (已删除) src/main/java/com/ruoyi/approve/utils/DailyRedisCounter.java (已删除) src/main/java/com/ruoyi/approve/utils/ListToStringTypeHandler.java (已删除) src/main/java/com/ruoyi/approve/utils/StartAndEndDateDto.java (已删除) src/main/java/com/ruoyi/approve/vo/ApproveGetAndUpdateVo.java (已删除) src/main/java/com/ruoyi/approve/vo/ApproveProcessVO.java (已删除) src/main/java/com/ruoyi/basic/controller/CustomerController.java (已删除) src/main/java/com/ruoyi/basic/controller/ProductController.java (已删除) src/main/java/com/ruoyi/basic/controller/SupplierManageController.java (已删除) src/main/java/com/ruoyi/basic/dto/ProductDto.java (已删除) src/main/java/com/ruoyi/basic/dto/ProductModelDto.java (已删除) src/main/java/com/ruoyi/basic/dto/ProductTreeDto.java (已删除) src/main/java/com/ruoyi/basic/dto/StorageBlobDTO.java (已删除) src/main/java/com/ruoyi/basic/dto/SupplierManageDto.java (已删除) src/main/java/com/ruoyi/basic/excel/SupplierManageExcelDto.java (已删除) src/main/java/com/ruoyi/basic/mapper/CustomerMapper.java (已删除) src/main/java/com/ruoyi/basic/mapper/ProductMapper.java (已删除) src/main/java/com/ruoyi/basic/mapper/ProductModelMapper.java (已删除) src/main/java/com/ruoyi/basic/mapper/StorageAttachmentMapper.java (已删除) src/main/java/com/ruoyi/basic/mapper/StorageBlobMapper.java (已删除) src/main/java/com/ruoyi/basic/mapper/SupplierManageMapper.java (已删除) src/main/java/com/ruoyi/basic/pojo/Customer.java (已删除) src/main/java/com/ruoyi/basic/pojo/Product.java (已删除) src/main/java/com/ruoyi/basic/pojo/ProductModel.java (已删除) src/main/java/com/ruoyi/basic/pojo/StorageAttachment.java (已删除) src/main/java/com/ruoyi/basic/pojo/StorageBlob.java (已删除) src/main/java/com/ruoyi/basic/pojo/SupplierManage.java (已删除) src/main/java/com/ruoyi/basic/service/ICustomerService.java (已删除) src/main/java/com/ruoyi/basic/service/IProductModelService.java (已删除) src/main/java/com/ruoyi/basic/service/IProductService.java (已删除) src/main/java/com/ruoyi/basic/service/ISupplierService.java (已删除) src/main/java/com/ruoyi/basic/service/StorageAttachmentService.java (已删除) src/main/java/com/ruoyi/basic/service/StorageBlobService.java (已删除) src/main/java/com/ruoyi/basic/service/impl/CustomerServiceImpl.java (已删除) src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java (已删除) src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java (已删除) src/main/java/com/ruoyi/basic/service/impl/StorageAttachmentServiceImpl.java (已删除) src/main/java/com/ruoyi/basic/service/impl/StorageBlobServiceImpl.java (已删除) src/main/java/com/ruoyi/basic/service/impl/SupplierServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/controller/DutyPlanController.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/controller/MeetingController.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/controller/NoticeController.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/controller/RulesRegulationsManagementController.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/controller/SealApplicationManagementController.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/controller/StaffContactsPersonalController.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/DutyPlanDTO.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/MeetSummaryDto.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/MeetUseDto.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/MeetingItem.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/MeetingSimpleDto.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/NoticeDTO.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/RulesRegulationsManagementDTO.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/SealApplicationManagementDTO.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/dto/StaffContactsPersonalDTO.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/DutyPlanMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetApplicationMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetDraftMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetingMinutesMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/MeetingRoomMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/NoticeMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/ReadingStatusMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/RulesRegulationsManagementMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/SealApplicationManagementMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/mapper/StaffContactsPersonalMapper.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/DutyPlan.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetApplication.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetDraft.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingMinutes.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/MeetingRoom.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/Notice.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/ReadingStatus.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/RulesRegulationsManagement.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/SealApplicationManagement.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/pojo/StaffContactsPersonal.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/DutyPlanService.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/MeetingService.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/NoticeService.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/RulesRegulationsManagementService.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/SealApplicationManagementService.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/StaffContactsPersonalService.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/impl/DutyPlanServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/impl/MeetingServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/impl/NoticeServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/impl/RulesRegulationsManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/impl/SealApplicationManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/service/impl/StaffContactsPersonalServiceImpl.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingApplicationVo.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingDraftVo.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingRoomVo.java (已删除) src/main/java/com/ruoyi/collaborativeApproval/vo/SearchMeetingUseVo.java (已删除) src/main/java/com/ruoyi/common/config/IgnoreTableConfig.java (已删除) src/main/java/com/ruoyi/common/config/MinioConfig.java (已删除) src/main/java/com/ruoyi/common/config/MyBaseMapper.java (已删除) src/main/java/com/ruoyi/common/config/MybatisHandler.java (已删除) src/main/java/com/ruoyi/common/config/TomcatConfig.java (已删除) src/main/java/com/ruoyi/common/constant/CacheConstants.java (已删除) src/main/java/com/ruoyi/common/constant/Constants.java (已删除) src/main/java/com/ruoyi/common/constant/GenConstants.java (已删除) src/main/java/com/ruoyi/common/constant/HttpStatus.java (已删除) src/main/java/com/ruoyi/common/constant/ScheduleConstants.java (已删除) src/main/java/com/ruoyi/common/constant/StorageAttachmentConstants.java (已删除) src/main/java/com/ruoyi/common/constant/UserConstants.java (已删除) src/main/java/com/ruoyi/common/core/text/CharsetKit.java (已删除) src/main/java/com/ruoyi/common/core/text/Convert.java (已删除) src/main/java/com/ruoyi/common/core/text/StrFormatter.java (已删除) src/main/java/com/ruoyi/common/enums/FileNameType.java (已删除) src/main/java/com/ruoyi/common/enums/HttpMethod.java (已删除) src/main/java/com/ruoyi/common/enums/SalesLedgerType.java (已删除) src/main/java/com/ruoyi/common/enums/StorageAttachmentRecordType.java (已删除) src/main/java/com/ruoyi/common/enums/UserStatus.java (已删除) src/main/java/com/ruoyi/common/exception/DemoModeException.java (已删除) src/main/java/com/ruoyi/common/exception/GlobalException.java (已删除) src/main/java/com/ruoyi/common/exception/ServiceException.java (已删除) src/main/java/com/ruoyi/common/exception/UtilException.java (已删除) src/main/java/com/ruoyi/common/exception/base/BaseException.java (已删除) src/main/java/com/ruoyi/common/exception/file/FileException.java (已删除) src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java (已删除) src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java (已删除) src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java (已删除) src/main/java/com/ruoyi/common/exception/job/TaskException.java (已删除) src/main/java/com/ruoyi/common/exception/user/CaptchaException.java (已删除) src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java (已删除) src/main/java/com/ruoyi/common/exception/user/UserException.java (已删除) src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java (已删除) src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java (已删除) src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java (已删除) src/main/java/com/ruoyi/common/filter/RepeatableFilter.java (已删除) src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java (已删除) src/main/java/com/ruoyi/common/filter/XssFilter.java (已删除) src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java (已删除) src/main/java/com/ruoyi/common/handler/CustomTenantLineHandler.java (已删除) src/main/java/com/ruoyi/common/utils/Arith.java (已删除) src/main/java/com/ruoyi/common/utils/DateUtils.java (已删除) src/main/java/com/ruoyi/common/utils/DictUtils.java (已删除) src/main/java/com/ruoyi/common/utils/ExceptionUtil.java (已删除) src/main/java/com/ruoyi/common/utils/HackLoopTableRenderPolicy.java (已删除) src/main/java/com/ruoyi/common/utils/LogUtils.java (已删除) src/main/java/com/ruoyi/common/utils/MessageUtils.java (已删除) src/main/java/com/ruoyi/common/utils/MinioUtils.java (已删除) src/main/java/com/ruoyi/common/utils/OrderUtils.java (已删除) src/main/java/com/ruoyi/common/utils/PageUtils.java (已删除) src/main/java/com/ruoyi/common/utils/SecurityUtils.java (已删除) src/main/java/com/ruoyi/common/utils/ServletUtils.java (已删除) src/main/java/com/ruoyi/common/utils/StringUtils.java (已删除) src/main/java/com/ruoyi/common/utils/Threads.java (已删除) src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java (已删除) src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java (已删除) src/main/java/com/ruoyi/common/utils/excel/ConfigurableMergeStrategy.java (已删除) src/main/java/com/ruoyi/common/utils/excel/CustomCellStyleHandler.java (已删除) src/main/java/com/ruoyi/common/utils/excel/ExcelClassField.java (已删除) src/main/java/com/ruoyi/common/utils/excel/ExcelExport.java (已删除) src/main/java/com/ruoyi/common/utils/excel/ExcelImport.java (已删除) src/main/java/com/ruoyi/common/utils/excel/ExcelUtils.java (已删除) src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java (已删除) src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java (已删除) src/main/java/com/ruoyi/common/utils/file/FileUtils.java (已删除) src/main/java/com/ruoyi/common/utils/file/ImageUtils.java (已删除) src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java (已删除) src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java (已删除) src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java (已删除) src/main/java/com/ruoyi/common/utils/http/HttpHelper.java (已删除) src/main/java/com/ruoyi/common/utils/http/HttpUtils.java (已删除) src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java (已删除) src/main/java/com/ruoyi/common/utils/ip/IpUtils.java (已删除) src/main/java/com/ruoyi/common/utils/job/AbstractQuartzJob.java (已删除) src/main/java/com/ruoyi/common/utils/job/CronUtils.java (已删除) src/main/java/com/ruoyi/common/utils/job/JobInvokeUtil.java (已删除) src/main/java/com/ruoyi/common/utils/job/QuartzDisallowConcurrentExecution.java (已删除) src/main/java/com/ruoyi/common/utils/job/QuartzJobExecution.java (已删除) src/main/java/com/ruoyi/common/utils/job/ScheduleUtils.java (已删除) src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java (已删除) src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java (已删除) src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java (已删除) src/main/java/com/ruoyi/common/utils/sign/Base64.java (已删除) src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java (已删除) src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java (已删除) src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java (已删除) src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java (已删除) src/main/java/com/ruoyi/common/utils/uuid/Seq.java (已删除) src/main/java/com/ruoyi/common/utils/uuid/UUID.java (已删除) src/main/java/com/ruoyi/common/vo/FileVo.java (已删除) src/main/java/com/ruoyi/common/xss/Xss.java (已删除) src/main/java/com/ruoyi/common/xss/XssValidator.java (已删除) src/main/java/com/ruoyi/compensationperformance/controller/CompensationPerformanceController.java (已删除) src/main/java/com/ruoyi/compensationperformance/mapper/CompensationPerformanceMapper.java (已删除) src/main/java/com/ruoyi/compensationperformance/pojo/CompensationPerformance.java (已删除) src/main/java/com/ruoyi/compensationperformance/service/CompensationPerformanceService.java (已删除) src/main/java/com/ruoyi/compensationperformance/service/impl/CompensationPerformanceServiceImpl.java (已删除) src/main/java/com/ruoyi/customervisits/controller/CustomerVisitsController.java (已删除) src/main/java/com/ruoyi/customervisits/mapper/CustomerVisitsMapper.java (已删除) src/main/java/com/ruoyi/customervisits/pojo/CustomerVisits.java (已删除) src/main/java/com/ruoyi/customervisits/service/CustomerVisitsService.java (已删除) src/main/java/com/ruoyi/customervisits/service/impl/CustomerVisitsServiceImpl.java (已删除) src/main/java/com/ruoyi/device/controller/DeviceDefectRecordController.java (已删除) src/main/java/com/ruoyi/device/controller/DeviceLedgerController.java (已删除) src/main/java/com/ruoyi/device/controller/DeviceMaintenanceController.java (已删除) src/main/java/com/ruoyi/device/controller/DeviceMaintenanceFileController.java (已删除) src/main/java/com/ruoyi/device/controller/DeviceRepairController.java (已删除) src/main/java/com/ruoyi/device/controller/MaintenanceTaskController.java (已删除) src/main/java/com/ruoyi/device/dto/DeviceDefectRecordDto.java (已删除) src/main/java/com/ruoyi/device/dto/DeviceLedgerDto.java (已删除) src/main/java/com/ruoyi/device/dto/DeviceMaintenanceDto.java (已删除) src/main/java/com/ruoyi/device/dto/DeviceMonthlyRepairTableDTO.java (已删除) src/main/java/com/ruoyi/device/dto/DeviceRepairDto.java (已删除) src/main/java/com/ruoyi/device/dto/RepairAmountGroupDTO.java (已删除) src/main/java/com/ruoyi/device/execl/DeviceLedgerExeclDto.java (已删除) src/main/java/com/ruoyi/device/execl/DeviceMaintenanceExeclDto.java (已删除) src/main/java/com/ruoyi/device/execl/DeviceRepairExeclDto.java (已删除) src/main/java/com/ruoyi/device/mapper/DeviceDefectRecordMapper.java (已删除) src/main/java/com/ruoyi/device/mapper/DeviceLedgerMapper.java (已删除) src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceFileMapper.java (已删除) src/main/java/com/ruoyi/device/mapper/DeviceMaintenanceMapper.java (已删除) src/main/java/com/ruoyi/device/mapper/DeviceRepairMapper.java (已删除) src/main/java/com/ruoyi/device/mapper/MaintenanceTaskMapper.java (已删除) src/main/java/com/ruoyi/device/pojo/DeviceDefectRecord.java (已删除) src/main/java/com/ruoyi/device/pojo/DeviceLedger.java (已删除) src/main/java/com/ruoyi/device/pojo/DeviceMaintenance.java (已删除) src/main/java/com/ruoyi/device/pojo/DeviceMaintenanceFile.java (已删除) src/main/java/com/ruoyi/device/pojo/DeviceRepair.java (已删除) src/main/java/com/ruoyi/device/pojo/MaintenanceTask.java (已删除) src/main/java/com/ruoyi/device/service/DeviceDefectRecordService.java (已删除) src/main/java/com/ruoyi/device/service/DeviceMaintenanceFileService.java (已删除) src/main/java/com/ruoyi/device/service/IDeviceLedgerService.java (已删除) src/main/java/com/ruoyi/device/service/IDeviceMaintenanceService.java (已删除) src/main/java/com/ruoyi/device/service/IDeviceRepairService.java (已删除) src/main/java/com/ruoyi/device/service/MaintenanceTaskService.java (已删除) src/main/java/com/ruoyi/device/service/impl/DeviceDefectRecordServiceImpl.java (已删除) src/main/java/com/ruoyi/device/service/impl/DeviceLedgerServiceImpl.java (已删除) src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceFileServiceImpl.java (已删除) src/main/java/com/ruoyi/device/service/impl/DeviceMaintenanceServiceImpl.java (已删除) src/main/java/com/ruoyi/device/service/impl/DeviceRepairServiceImpl.java (已删除) src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskJob.java (已删除) src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskScheduler.java (已删除) src/main/java/com/ruoyi/device/service/impl/MaintenanceTaskServiceImpl.java (已删除) src/main/java/com/ruoyi/dto/DateQueryDto.java (已删除) src/main/java/com/ruoyi/dto/MapDto.java (已删除) src/main/java/com/ruoyi/dto/PageDto.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/controller/ElectricityConsumptionAreaController.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EnergyPeriodController.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/controller/EquipmentEnergyConsumptionController.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/dto/ElectricityConsumptionAreaTreeDto.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/dto/EquipmentEnergyConsumptionDto.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/mapper/ElectricityConsumptionAreaMapper.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/mapper/EnergyPeriodMapper.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/mapper/EquipmentEnergyConsumptionMapper.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/ElectricityConsumptionArea.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EnergyPeriod.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/pojo/EquipmentEnergyConsumption.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/service/ElectricityConsumptionAreaService.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/service/EnergyPeriodService.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/service/EquipmentEnergyConsumptionService.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/ElectricityConsumptionAreaServiceImpl.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EnergyPeriodServiceImpl.java (已删除) src/main/java/com/ruoyi/equipmentenergyconsumption/service/impl/EquipmentEnergyConsumptionServiceImpl.java (已删除) src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java (已删除) src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java (已删除) src/main/java/com/ruoyi/framework/aspectj/LogAspect.java (已删除) src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Anonymous.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataScope.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/DataSource.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excel.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Excels.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Log.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/RateLimiter.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/annotation/Sensitive.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessStatus.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/enums/BusinessType.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/enums/DataSourceType.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/enums/DesensitizedType.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/enums/LimitType.java (已删除) src/main/java/com/ruoyi/framework/aspectj/lang/enums/OperatorType.java (已删除) src/main/java/com/ruoyi/framework/config/ApplicationConfig.java (已删除) src/main/java/com/ruoyi/framework/config/CaptchaConfig.java (已删除) src/main/java/com/ruoyi/framework/config/DruidConfig.java (已删除) src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java (已删除) src/main/java/com/ruoyi/framework/config/FilterConfig.java (已删除) src/main/java/com/ruoyi/framework/config/GenConfig.java (已删除) src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java (已删除) src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java (已删除) src/main/java/com/ruoyi/framework/config/RedisConfig.java (已删除) src/main/java/com/ruoyi/framework/config/ResourcesConfig.java (已删除) src/main/java/com/ruoyi/framework/config/RuoYiConfig.java (已删除) src/main/java/com/ruoyi/framework/config/ScheduleConfig.java (已删除) src/main/java/com/ruoyi/framework/config/SecurityConfig.java (已删除) src/main/java/com/ruoyi/framework/config/SensitiveJsonSerializer.java (已删除) src/main/java/com/ruoyi/framework/config/ServerConfig.java (已删除) src/main/java/com/ruoyi/framework/config/SwaggerConfig.java (已删除) src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java (已删除) src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java (已删除) src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java (已删除) src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java (已删除) src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java (已删除) src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java (已删除) src/main/java/com/ruoyi/framework/interceptor/annotation/RepeatSubmit.java (已删除) src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java (已删除) src/main/java/com/ruoyi/framework/manager/AsyncManager.java (已删除) src/main/java/com/ruoyi/framework/manager/ShutdownManager.java (已删除) src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java (已删除) src/main/java/com/ruoyi/framework/redis/RedisCache.java (已删除) src/main/java/com/ruoyi/framework/security/LoginBody.java (已删除) src/main/java/com/ruoyi/framework/security/LoginUser.java (已删除) src/main/java/com/ruoyi/framework/security/RegisterBody.java (已删除) src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java (已删除) src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java (已删除) src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java (已删除) src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java (已删除) src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java (已删除) src/main/java/com/ruoyi/framework/security/service/PermissionService.java (已删除) src/main/java/com/ruoyi/framework/security/service/SysLoginService.java (已删除) src/main/java/com/ruoyi/framework/security/service/SysPasswordService.java (已删除) src/main/java/com/ruoyi/framework/security/service/SysPermissionService.java (已删除) src/main/java/com/ruoyi/framework/security/service/SysRegisterService.java (已删除) src/main/java/com/ruoyi/framework/security/service/TokenService.java (已删除) src/main/java/com/ruoyi/framework/security/service/UserDetailsServiceImpl.java (已删除) src/main/java/com/ruoyi/framework/task/RyTask.java (已删除) src/main/java/com/ruoyi/framework/web/controller/BaseController.java (已删除) src/main/java/com/ruoyi/framework/web/domain/AjaxResult.java (已删除) src/main/java/com/ruoyi/framework/web/domain/BaseEntity.java (已删除) src/main/java/com/ruoyi/framework/web/domain/MinioResult.java (已删除) src/main/java/com/ruoyi/framework/web/domain/R.java (已删除) src/main/java/com/ruoyi/framework/web/domain/Server.java (已删除) src/main/java/com/ruoyi/framework/web/domain/TreeEntity.java (已删除) src/main/java/com/ruoyi/framework/web/domain/TreeSelect.java (已删除) src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java (已删除) src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java (已删除) src/main/java/com/ruoyi/framework/web/domain/server/Mem.java (已删除) src/main/java/com/ruoyi/framework/web/domain/server/Sys.java (已删除) src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java (已删除) src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java (已删除) src/main/java/com/ruoyi/framework/web/page/PageDomain.java (已删除) src/main/java/com/ruoyi/framework/web/page/TableDataInfo.java (已删除) src/main/java/com/ruoyi/framework/web/page/TableSupport.java (已删除) src/main/java/com/ruoyi/home/controller/HomeController.java (已删除) src/main/java/com/ruoyi/home/dto/AnalysisCustomerContractAmountsDto.java (已删除) src/main/java/com/ruoyi/home/dto/HomeBusinessDto.java (已删除) src/main/java/com/ruoyi/home/dto/QualityStatisticsDto.java (已删除) src/main/java/com/ruoyi/home/dto/QualityStatisticsItem.java (已删除) src/main/java/com/ruoyi/home/dto/StatisticsReceivablePayableDto.java (已删除) src/main/java/com/ruoyi/home/service/HomeService.java (已删除) src/main/java/com/ruoyi/home/service/impl/HomeServiceImpl.java (已删除) src/main/java/com/ruoyi/inspectiontask/StorageAttachmentRecordType.java (已删除) src/main/java/com/ruoyi/inspectiontask/controller/InspectionTaskController.java (已删除) src/main/java/com/ruoyi/inspectiontask/controller/QrCodeController.java (已删除) src/main/java/com/ruoyi/inspectiontask/controller/QrCodeScanRecordController.java (已删除) src/main/java/com/ruoyi/inspectiontask/controller/TimingTaskController.java (已删除) src/main/java/com/ruoyi/inspectiontask/dto/InspectionTaskDto.java (已删除) src/main/java/com/ruoyi/inspectiontask/dto/QrCodeDto.java (已删除) src/main/java/com/ruoyi/inspectiontask/dto/QrCodeScanRecordDto.java (已删除) src/main/java/com/ruoyi/inspectiontask/dto/TimingTaskDto.java (已删除) src/main/java/com/ruoyi/inspectiontask/mapper/InspectionTaskMapper.java (已删除) src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeMapper.java (已删除) src/main/java/com/ruoyi/inspectiontask/mapper/QrCodeScanRecordMapper.java (已删除) src/main/java/com/ruoyi/inspectiontask/mapper/TimingTaskMapper.java (已删除) src/main/java/com/ruoyi/inspectiontask/pojo/InspectionTask.java (已删除) src/main/java/com/ruoyi/inspectiontask/pojo/QrCode.java (已删除) src/main/java/com/ruoyi/inspectiontask/pojo/QrCodeScanRecord.java (已删除) src/main/java/com/ruoyi/inspectiontask/pojo/TimingTask.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/InspectionTaskService.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/QrCodeScanRecordService.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/QrCodeService.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/TimingTaskService.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/InspectionTaskServiceImpl.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeScanRecordServiceImpl.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/QrCodeServiceImpl.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/QuartzConfig.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/SpringContextHolder.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskJob.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskScheduler.java (已删除) src/main/java/com/ruoyi/inspectiontask/service/impl/TimingTaskServiceImpl.java (已删除) src/main/java/com/ruoyi/lavorissue/controller/LavorIssueController.java (已删除) src/main/java/com/ruoyi/lavorissue/dto/StatisticsLaborIssue.java (已删除) src/main/java/com/ruoyi/lavorissue/mapper/LavorIssueMapper.java (已删除) src/main/java/com/ruoyi/lavorissue/pojo/LaborIssue.java (已删除) src/main/java/com/ruoyi/lavorissue/service/LavorIssueService.java (已删除) src/main/java/com/ruoyi/lavorissue/service/impl/LavorIssueServiceImpl.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerController.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/controller/MeasuringInstrumentLedgerRecordController.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/controller/SparePartsController.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/dto/MeasuringInstrumentLedgerDto.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/dto/SparePartsDto.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/mapper/MeasuringInstrumentLedgerMapper.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/mapper/MeasuringInstrumentLedgerRecordMapper.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/mapper/SparePartsMapper.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedger.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/pojo/MeasuringInstrumentLedgerRecord.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/pojo/SpareParts.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerRecordService.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/service/MeasuringInstrumentLedgerService.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/service/SparePartsService.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerRecordServiceImpl.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/MeasuringInstrumentLedgerServiceImpl.java (已删除) src/main/java/com/ruoyi/measuringinstrumentledger/service/impl/SparePartsServiceImpl.java (已删除) src/main/java/com/ruoyi/oA/controller/OaProjectController.java (已删除) src/main/java/com/ruoyi/oA/controller/OaProjectPhaseController.java (已删除) src/main/java/com/ruoyi/oA/controller/OaProjectPhaseTaskController.java (已删除) src/main/java/com/ruoyi/oA/dto/OaProjectDto.java (已删除) src/main/java/com/ruoyi/oA/dto/OaProjectPhaseDto.java (已删除) src/main/java/com/ruoyi/oA/mapper/OaProjectMapper.java (已删除) src/main/java/com/ruoyi/oA/mapper/OaProjectPhaseMapper.java (已删除) src/main/java/com/ruoyi/oA/mapper/OaProjectPhaseTaskMapper.java (已删除) src/main/java/com/ruoyi/oA/pojo/OaProject.java (已删除) src/main/java/com/ruoyi/oA/pojo/OaProjectPhase.java (已删除) src/main/java/com/ruoyi/oA/pojo/OaProjectPhaseTask.java (已删除) src/main/java/com/ruoyi/oA/service/OaProjectPhaseService.java (已删除) src/main/java/com/ruoyi/oA/service/OaProjectPhaseTaskService.java (已删除) src/main/java/com/ruoyi/oA/service/OaProjectService.java (已删除) src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseServiceImpl.java (已删除) src/main/java/com/ruoyi/oA/service/impl/OaProjectPhaseTaskServiceImpl.java (已删除) src/main/java/com/ruoyi/oA/service/impl/OaProjectServiceImpl.java (已删除) src/main/java/com/ruoyi/officesupplies/controller/OfficeSuppliesController.java (已删除) src/main/java/com/ruoyi/officesupplies/mapper/OfficeSuppliesMapper.java (已删除) src/main/java/com/ruoyi/officesupplies/pojo/OfficeSupplies.java (已删除) src/main/java/com/ruoyi/officesupplies/service/OfficeSuppliesService.java (已删除) src/main/java/com/ruoyi/officesupplies/service/impl/OfficeSuppliesServiceImpl.java (已删除) src/main/java/com/ruoyi/other/controller/TempFileController.java (已删除) src/main/java/com/ruoyi/other/mapper/TempFileMapper.java (已删除) src/main/java/com/ruoyi/other/pojo/TempFile.java (已删除) src/main/java/com/ruoyi/other/service/TempFileService.java (已删除) src/main/java/com/ruoyi/other/service/impl/TempFileServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/GasTankWarningController.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/InboundManagementController.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPlanController.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/ProcurementPriceManagementController.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordController.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/ProcurementRecordOutController.java (已删除) src/main/java/com/ruoyi/procurementrecord/controller/ReturnManagementController.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/Details.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementAddDto.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementDto.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementManagementUpdateDto.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDto.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementPageDtoCopy.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutAdd.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementRecordOutPageDto.java (已删除) src/main/java/com/ruoyi/procurementrecord/dto/ProcurementUpdateDto.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/GasTankWarningMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/InboundManagementMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPlanMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementPriceManagementMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementRecordMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/ProcurementRecordOutMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/mapper/ReturnManagementMapper.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/GasTankWarning.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/InboundManagement.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPlan.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementPriceManagement.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordOut.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/ProcurementRecordStorage.java (已删除) src/main/java/com/ruoyi/procurementrecord/pojo/ReturnManagement.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/GasTankWarningService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/InboundManagementService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/ProcurementPlanService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/ProcurementPriceManagementService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordOutService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/ProcurementRecordService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/ReturnManagementService.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/GasTankWarningServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/InboundManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPlanServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementPriceManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordServiceImpl.java (已删除) src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/production/controller/SalesLedgerProductionAccountingController.java (已删除) src/main/java/com/ruoyi/production/controller/SalesLedgerSchedulingController.java (已删除) src/main/java/com/ruoyi/production/controller/SalesLedgerWorkController.java (已删除) src/main/java/com/ruoyi/production/dto/DaiDto.java (已删除) src/main/java/com/ruoyi/production/dto/ProcessSchedulingDto.java (已删除) src/main/java/com/ruoyi/production/dto/ProductionDispatchAddDto.java (已删除) src/main/java/com/ruoyi/production/dto/ProductionReportDto.java (已删除) src/main/java/com/ruoyi/production/dto/SalesLedgerProductDto.java (已删除) src/main/java/com/ruoyi/production/dto/SalesLedgerProductionAccountingDto.java (已删除) src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingDto.java (已删除) src/main/java/com/ruoyi/production/dto/SalesLedgerSchedulingProcessDto.java (已删除) src/main/java/com/ruoyi/production/dto/SalesLedgerWorkDto.java (已删除) src/main/java/com/ruoyi/production/mapper/SalesLedgerProductionAccountingMapper.java (已删除) src/main/java/com/ruoyi/production/mapper/SalesLedgerSchedulingMapper.java (已删除) src/main/java/com/ruoyi/production/mapper/SalesLedgerWorkMapper.java (已删除) src/main/java/com/ruoyi/production/pojo/SalesLedgerProductionAccounting.java (已删除) src/main/java/com/ruoyi/production/pojo/SalesLedgerScheduling.java (已删除) src/main/java/com/ruoyi/production/pojo/SalesLedgerWork.java (已删除) src/main/java/com/ruoyi/production/service/SalesLedgerProductionAccountingService.java (已删除) src/main/java/com/ruoyi/production/service/SalesLedgerSchedulingService.java (已删除) src/main/java/com/ruoyi/production/service/SalesLedgerWorkService.java (已删除) src/main/java/com/ruoyi/production/service/impl/SalesLedgerProductionAccountingServiceImpl.java (已删除) src/main/java/com/ruoyi/production/service/impl/SalesLedgerSchedulingServiceImpl.java (已删除) src/main/java/com/ruoyi/production/service/impl/SalesLedgerWorkServiceImpl.java (已删除) src/main/java/com/ruoyi/project/common/CaptchaController.java (已删除) src/main/java/com/ruoyi/project/common/CommonController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/CacheController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/ServerController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/SysJobController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/SysJobLogController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/SysLogininforController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/SysOperlogController.java (已删除) src/main/java/com/ruoyi/project/monitor/controller/SysUserOnlineController.java (已删除) src/main/java/com/ruoyi/project/monitor/domain/SysCache.java (已删除) src/main/java/com/ruoyi/project/monitor/domain/SysJob.java (已删除) src/main/java/com/ruoyi/project/monitor/domain/SysJobLog.java (已删除) src/main/java/com/ruoyi/project/monitor/domain/SysLogininfor.java (已删除) src/main/java/com/ruoyi/project/monitor/domain/SysOperLog.java (已删除) src/main/java/com/ruoyi/project/monitor/domain/SysUserOnline.java (已删除) src/main/java/com/ruoyi/project/monitor/mapper/SysJobLogMapper.java (已删除) src/main/java/com/ruoyi/project/monitor/mapper/SysJobMapper.java (已删除) src/main/java/com/ruoyi/project/monitor/mapper/SysLogininforMapper.java (已删除) src/main/java/com/ruoyi/project/monitor/mapper/SysOperLogMapper.java (已删除) src/main/java/com/ruoyi/project/monitor/service/ISysJobLogService.java (已删除) src/main/java/com/ruoyi/project/monitor/service/ISysJobService.java (已删除) src/main/java/com/ruoyi/project/monitor/service/ISysLogininforService.java (已删除) src/main/java/com/ruoyi/project/monitor/service/ISysOperLogService.java (已删除) src/main/java/com/ruoyi/project/monitor/service/impl/SysJobLogServiceImpl.java (已删除) src/main/java/com/ruoyi/project/monitor/service/impl/SysJobServiceImpl.java (已删除) src/main/java/com/ruoyi/project/monitor/service/impl/SysLogininforServiceImpl.java (已删除) src/main/java/com/ruoyi/project/monitor/service/impl/SysOperLogServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysConfigController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysDeptController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysDictDataController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysDictTypeController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysIndexController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysLoginController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysMenuController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysNoticeController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysPostController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysProfileController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysRegisterController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysRoleController.java (已删除) src/main/java/com/ruoyi/project/system/controller/SysUserController.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysConfig.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysDept.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysDictData.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysDictType.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysMenu.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysNotice.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysPost.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysRole.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysRoleDept.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysRoleMenu.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysUser.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysUserDept.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysUserPost.java (已删除) src/main/java/com/ruoyi/project/system/domain/SysUserRole.java (已删除) src/main/java/com/ruoyi/project/system/domain/vo/MetaVo.java (已删除) src/main/java/com/ruoyi/project/system/domain/vo/RouterVo.java (已删除) src/main/java/com/ruoyi/project/system/domain/vo/SysUserDeptVo.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysConfigMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysDeptMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysDictDataMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysDictTypeMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysMenuMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysNoticeMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysPostMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysRoleDeptMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysRoleMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysRoleMenuMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysUserMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysUserPostMapper.java (已删除) src/main/java/com/ruoyi/project/system/mapper/SysUserRoleMapper.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysConfigService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysDeptService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysDictDataService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysDictTypeService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysMenuService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysNoticeService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysPostService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysRoleService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysUserDeptService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysUserOnlineService.java (已删除) src/main/java/com/ruoyi/project/system/service/ISysUserService.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysConfigServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysDeptServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysDictDataServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysDictTypeServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysMenuServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysNoticeServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysPostServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysRoleServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysUserDeptServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysUserOnlineServiceImpl.java (已删除) src/main/java/com/ruoyi/project/system/service/impl/SysUserServiceImpl.java (已删除) src/main/java/com/ruoyi/project/tool/gen/controller/GenController.java (已删除) src/main/java/com/ruoyi/project/tool/gen/domain/GenTable.java (已删除) src/main/java/com/ruoyi/project/tool/gen/domain/GenTableColumn.java (已删除) src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableColumnMapper.java (已删除) src/main/java/com/ruoyi/project/tool/gen/mapper/GenTableMapper.java (已删除) src/main/java/com/ruoyi/project/tool/gen/service/GenTableColumnServiceImpl.java (已删除) src/main/java/com/ruoyi/project/tool/gen/service/GenTableServiceImpl.java (已删除) src/main/java/com/ruoyi/project/tool/gen/service/IGenTableColumnService.java (已删除) src/main/java/com/ruoyi/project/tool/gen/service/IGenTableService.java (已删除) src/main/java/com/ruoyi/project/tool/gen/util/GenUtils.java (已删除) src/main/java/com/ruoyi/project/tool/gen/util/VelocityInitializer.java (已删除) src/main/java/com/ruoyi/project/tool/gen/util/VelocityUtils.java (已删除) src/main/java/com/ruoyi/project/tool/swagger/TestController.java (已删除) src/main/java/com/ruoyi/purchase/controller/AccountingReportController.java (已删除) src/main/java/com/ruoyi/purchase/controller/InvoicePurchaseController.java (已删除) src/main/java/com/ruoyi/purchase/controller/PaymentRegistrationController.java (已删除) src/main/java/com/ruoyi/purchase/controller/PurchaseLedgerController.java (已删除) src/main/java/com/ruoyi/purchase/controller/TicketRegistrationController.java (已删除) src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/InvoicePurchaseReportDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/PaymentHistoryRecordVo.java (已删除) src/main/java/com/ruoyi/purchase/dto/PaymentLedgerDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/PaymentRegistrationDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/ProductRecordDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/PurchaseLedgerDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/TicketRegistrationDto.java (已删除) src/main/java/com/ruoyi/purchase/dto/VatDto.java (已删除) src/main/java/com/ruoyi/purchase/mapper/InvoicePurchaseMapper.java (已删除) src/main/java/com/ruoyi/purchase/mapper/PaymentRegistrationMapper.java (已删除) src/main/java/com/ruoyi/purchase/mapper/ProductRecordMapper.java (已删除) src/main/java/com/ruoyi/purchase/mapper/PurchaseLedgerMapper.java (已删除) src/main/java/com/ruoyi/purchase/mapper/TicketRegistrationMapper.java (已删除) src/main/java/com/ruoyi/purchase/pojo/InvoicePurchase.java (已删除) src/main/java/com/ruoyi/purchase/pojo/PaymentRegistration.java (已删除) src/main/java/com/ruoyi/purchase/pojo/ProductRecord.java (已删除) src/main/java/com/ruoyi/purchase/pojo/PurchaseLedger.java (已删除) src/main/java/com/ruoyi/purchase/pojo/TicketRegistration.java (已删除) src/main/java/com/ruoyi/purchase/service/IInvoicePurchaseService.java (已删除) src/main/java/com/ruoyi/purchase/service/IPaymentRegistrationService.java (已删除) src/main/java/com/ruoyi/purchase/service/IProductRecordService.java (已删除) src/main/java/com/ruoyi/purchase/service/IPurchaseLedgerService.java (已删除) src/main/java/com/ruoyi/purchase/service/ITicketRegistrationService.java (已删除) src/main/java/com/ruoyi/purchase/service/impl/InvoicePurchaseServiceImpl.java (已删除) src/main/java/com/ruoyi/purchase/service/impl/PaymentRegistrationServiceImpl.java (已删除) src/main/java/com/ruoyi/purchase/service/impl/ProductRecordServiceImpl.java (已删除) src/main/java/com/ruoyi/purchase/service/impl/PurchaseLedgerServiceImpl.java (已删除) src/main/java/com/ruoyi/purchase/service/impl/TicketRegistrationServiceImpl.java (已删除) src/main/java/com/ruoyi/quality/controller/QualityInspectController.java (已删除) src/main/java/com/ruoyi/quality/controller/QualityInspectFileController.java (已删除) src/main/java/com/ruoyi/quality/controller/QualityInspectParamController.java (已删除) src/main/java/com/ruoyi/quality/controller/QualityTestStandardController.java (已删除) src/main/java/com/ruoyi/quality/controller/QualityUnqualifiedController.java (已删除) src/main/java/com/ruoyi/quality/dto/QualityInspectDto.java (已删除) src/main/java/com/ruoyi/quality/mapper/QualityInspectFileMapper.java (已删除) src/main/java/com/ruoyi/quality/mapper/QualityInspectMapper.java (已删除) src/main/java/com/ruoyi/quality/mapper/QualityInspectParamMapper.java (已删除) src/main/java/com/ruoyi/quality/mapper/QualityTestStandardMapper.java (已删除) src/main/java/com/ruoyi/quality/mapper/QualityUnqualifiedMapper.java (已删除) src/main/java/com/ruoyi/quality/pojo/QualityInspect.java (已删除) src/main/java/com/ruoyi/quality/pojo/QualityInspectFile.java (已删除) src/main/java/com/ruoyi/quality/pojo/QualityInspectParam.java (已删除) src/main/java/com/ruoyi/quality/pojo/QualityTestStandard.java (已删除) src/main/java/com/ruoyi/quality/pojo/QualityUnqualified.java (已删除) src/main/java/com/ruoyi/quality/service/IQualityInspectFileService.java (已删除) src/main/java/com/ruoyi/quality/service/IQualityInspectParamService.java (已删除) src/main/java/com/ruoyi/quality/service/IQualityInspectService.java (已删除) src/main/java/com/ruoyi/quality/service/IQualityTestStandardService.java (已删除) src/main/java/com/ruoyi/quality/service/IQualityUnqualifiedService.java (已删除) src/main/java/com/ruoyi/quality/service/impl/QualityInspectFileServiceImpl.java (已删除) src/main/java/com/ruoyi/quality/service/impl/QualityInspectParamServiceImpl.java (已删除) src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java (已删除) src/main/java/com/ruoyi/quality/service/impl/QualityTestStandardServiceImpl.java (已删除) src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/controller/CommonFileController.java (已删除) src/main/java/com/ruoyi/sales/controller/InvoiceLedgerController.java (已删除) src/main/java/com/ruoyi/sales/controller/InvoiceRegistrationController.java (已删除) src/main/java/com/ruoyi/sales/controller/PaymentShippingController.java (已删除) src/main/java/com/ruoyi/sales/controller/ReceiptPaymentController.java (已删除) src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java (已删除) src/main/java/com/ruoyi/sales/controller/SalesLedgerProductController.java (已删除) src/main/java/com/ruoyi/sales/controller/SalesQuotationController.java (已删除) src/main/java/com/ruoyi/sales/controller/SalespersonManagementController.java (已删除) src/main/java/com/ruoyi/sales/controller/ShippingInfoController.java (已删除) src/main/java/com/ruoyi/sales/dto/CustomerInteractionDto.java (已删除) src/main/java/com/ruoyi/sales/dto/InvoiceLedgerDto.java (已删除) src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationDto.java (已删除) src/main/java/com/ruoyi/sales/dto/InvoiceRegistrationProductDto.java (已删除) src/main/java/com/ruoyi/sales/dto/MonthlyAmountDto.java (已删除) src/main/java/com/ruoyi/sales/dto/ReceiptPaymentDto.java (已删除) src/main/java/com/ruoyi/sales/dto/ReceiptPaymentExeclDto.java (已删除) src/main/java/com/ruoyi/sales/dto/ReceiptPaymentRecordDto.java (已删除) src/main/java/com/ruoyi/sales/dto/SalesLedgerDto.java (已删除) src/main/java/com/ruoyi/sales/dto/SalesLedgerProductDto.java (已删除) src/main/java/com/ruoyi/sales/dto/SalesQuotationDto.java (已删除) src/main/java/com/ruoyi/sales/excel/InvoiceLedgerExcelDto.java (已删除) src/main/java/com/ruoyi/sales/excel/InvoiceRegisAndProductExcelDto.java (已删除) src/main/java/com/ruoyi/sales/mapper/CommonFileMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerFileMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/InvoiceLedgerMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/InvoiceRegistrationProductMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/PaymentShippingMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/ReceiptPaymentMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/SalesLedgerMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/SalesLedgerProductMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/SalesQuotationMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/SalesQuotationProductMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/SalespersonManagementMapper.java (已删除) src/main/java/com/ruoyi/sales/mapper/ShippingInfoMapper.java (已删除) src/main/java/com/ruoyi/sales/pojo/CommonFile.java (已删除) src/main/java/com/ruoyi/sales/pojo/InvoiceLedger.java (已删除) src/main/java/com/ruoyi/sales/pojo/InvoiceLedgerFile.java (已删除) src/main/java/com/ruoyi/sales/pojo/InvoiceRegistration.java (已删除) src/main/java/com/ruoyi/sales/pojo/InvoiceRegistrationProduct.java (已删除) src/main/java/com/ruoyi/sales/pojo/PaymentShipping.java (已删除) src/main/java/com/ruoyi/sales/pojo/PurchaseLedgerFile.java (已删除) src/main/java/com/ruoyi/sales/pojo/ReceiptPayment.java (已删除) src/main/java/com/ruoyi/sales/pojo/SalesLedger.java (已删除) src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java (已删除) src/main/java/com/ruoyi/sales/pojo/SalesQuotation.java (已删除) src/main/java/com/ruoyi/sales/pojo/SalesQuotationProduct.java (已删除) src/main/java/com/ruoyi/sales/pojo/SalespersonManagement.java (已删除) src/main/java/com/ruoyi/sales/pojo/ShippingInfo.java (已删除) src/main/java/com/ruoyi/sales/service/ICommonFileService.java (已删除) src/main/java/com/ruoyi/sales/service/ISalesLedgerProductService.java (已删除) src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java (已删除) src/main/java/com/ruoyi/sales/service/InvoiceLedgerService.java (已删除) src/main/java/com/ruoyi/sales/service/InvoiceRegistrationService.java (已删除) src/main/java/com/ruoyi/sales/service/PaymentShippingService.java (已删除) src/main/java/com/ruoyi/sales/service/ReceiptPaymentService.java (已删除) src/main/java/com/ruoyi/sales/service/SalesQuotationProductService.java (已删除) src/main/java/com/ruoyi/sales/service/SalesQuotationService.java (已删除) src/main/java/com/ruoyi/sales/service/SalespersonManagementService.java (已删除) src/main/java/com/ruoyi/sales/service/ShippingInfoService.java (已删除) src/main/java/com/ruoyi/sales/service/impl/CommonFileServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/InvoiceLedgerServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/InvoiceRegistrationServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/PaymentShippingServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/ReceiptPaymentServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/SalesQuotationProductServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/SalesQuotationServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/SalespersonManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java (已删除) src/main/java/com/ruoyi/sales/vo/SalesLedgerProductVo.java (已删除) src/main/java/com/ruoyi/sales/vo/ShippingInfoVo.java (已删除) src/main/java/com/ruoyi/staff/controller/HolidayApplicationController.java (已删除) src/main/java/com/ruoyi/staff/controller/PersonalAttendanceRecordsController.java (已删除) src/main/java/com/ruoyi/staff/controller/StaffJoinLeaveRecordController.java (已删除) src/main/java/com/ruoyi/staff/controller/StaffOnJobController.java (已删除) src/main/java/com/ruoyi/staff/controller/StaffSchedulingController.java (已删除) src/main/java/com/ruoyi/staff/dto/SaveStaffSchedulingDto.java (已删除) src/main/java/com/ruoyi/staff/dto/StaffOnJobDto.java (已删除) src/main/java/com/ruoyi/staff/dto/StaffSchedulingDto.java (已删除) src/main/java/com/ruoyi/staff/mapper/HolidayApplicationMapper.java (已删除) src/main/java/com/ruoyi/staff/mapper/PersonalAttendanceRecordsMapper.java (已删除) src/main/java/com/ruoyi/staff/mapper/StaffJoinLeaveRecordMapper.java (已删除) src/main/java/com/ruoyi/staff/mapper/StaffOnJobMapper.java (已删除) src/main/java/com/ruoyi/staff/mapper/StaffSchedulingMapper.java (已删除) src/main/java/com/ruoyi/staff/pojo/HolidayApplication.java (已删除) src/main/java/com/ruoyi/staff/pojo/PersonalAttendanceRecords.java (已删除) src/main/java/com/ruoyi/staff/pojo/StaffJoinLeaveRecord.java (已删除) src/main/java/com/ruoyi/staff/pojo/StaffOnJob.java (已删除) src/main/java/com/ruoyi/staff/pojo/StaffScheduling.java (已删除) src/main/java/com/ruoyi/staff/service/HolidayApplicationService.java (已删除) src/main/java/com/ruoyi/staff/service/IStaffJoinLeaveRecordService.java (已删除) src/main/java/com/ruoyi/staff/service/IStaffOnJobService.java (已删除) src/main/java/com/ruoyi/staff/service/PersonalAttendanceRecordsService.java (已删除) src/main/java/com/ruoyi/staff/service/StaffSchedulingService.java (已删除) src/main/java/com/ruoyi/staff/service/impl/HolidayApplicationServiceImpl.java (已删除) src/main/java/com/ruoyi/staff/service/impl/PersonalAttendanceRecordsServiceImpl.java (已删除) src/main/java/com/ruoyi/staff/service/impl/StaffJoinLeaveRecordServiceImpl.java (已删除) src/main/java/com/ruoyi/staff/service/impl/StaffOnJobServiceImpl.java (已删除) src/main/java/com/ruoyi/staff/service/impl/StaffSchedulingServiceImpl.java (已删除) src/main/java/com/ruoyi/staff/vo/SearchSchedulingVo.java (已删除) src/main/java/com/ruoyi/warehouse/controller/DocumentClassificationController.java (已删除) src/main/java/com/ruoyi/warehouse/controller/DocumentationBorrowManagementController.java (已删除) src/main/java/com/ruoyi/warehouse/controller/DocumentationController.java (已删除) src/main/java/com/ruoyi/warehouse/controller/DocumentationFileController.java (已删除) src/main/java/com/ruoyi/warehouse/controller/WarehouseController.java (已删除) src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesController.java (已删除) src/main/java/com/ruoyi/warehouse/controller/WarehouseGoodsShelvesRowcolController.java (已删除) src/main/java/com/ruoyi/warehouse/dto/DocumentClassificationDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/DocumentClassificationTreeDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/DocumentationBorrowManagementDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/DocumentationDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/DocumentationReturnManagementDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/ReturnExportDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/WarehouseDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/WarehouseGoodsShelvesDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/WarehouseGoodsShelvesRowcolDto.java (已删除) src/main/java/com/ruoyi/warehouse/dto/WarehouseTreeDto.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/DocumentClassificationMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/DocumentationBorrowManagementMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/DocumentationFileMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/DocumentationMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/DocumentationReturnManagementMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/WarehouseGoodsShelvesMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/WarehouseGoodsShelvesRowcolMapper.java (已删除) src/main/java/com/ruoyi/warehouse/mapper/WarehouseMapper.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/DocumentClassification.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/Documentation.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/DocumentationBorrowManagement.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/DocumentationFile.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/DocumentationReturnManagement.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/Warehouse.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelves.java (已删除) src/main/java/com/ruoyi/warehouse/pojo/WarehouseGoodsShelvesRowcol.java (已删除) src/main/java/com/ruoyi/warehouse/service/DocumentClassificationService.java (已删除) src/main/java/com/ruoyi/warehouse/service/DocumentationBorrowManagementService.java (已删除) src/main/java/com/ruoyi/warehouse/service/DocumentationFileService.java (已删除) src/main/java/com/ruoyi/warehouse/service/DocumentationService.java (已删除) src/main/java/com/ruoyi/warehouse/service/WarehouseGoodsShelvesRowcolService.java (已删除) src/main/java/com/ruoyi/warehouse/service/WarehouseGoodsShelvesService.java (已删除) src/main/java/com/ruoyi/warehouse/service/WarehouseService.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/DocumentClassificationServiceImpl.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/DocumentationBorrowManagementServiceImpl.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/DocumentationFileServiceImpl.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/DocumentationServiceImpl.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesRowcolServiceImpl.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/WarehouseGoodsShelvesServiceImpl.java (已删除) src/main/java/com/ruoyi/warehouse/service/impl/WarehouseServiceImpl.java (已删除) src/main/java/com/ruoyi/waterrecord/controller/WaterRecordController.java (已删除) src/main/java/com/ruoyi/waterrecord/mapper/WaterRecordMapper.java (已删除) src/main/java/com/ruoyi/waterrecord/pojo/WaterRecord.java (已删除) src/main/java/com/ruoyi/waterrecord/service/WaterRecordService.java (已删除) src/main/java/com/ruoyi/waterrecord/service/impl/WaterRecordServiceImpl.java (已删除) src/main/resources/application-aynm.yml (已删除) src/main/resources/application-bdsm.yml (已删除) src/main/resources/application-bhmy.yml (已删除) src/main/resources/application-cjny.yml (已删除) src/main/resources/application-cmny.yml (已删除) src/main/resources/application-demo.yml (已删除) src/main/resources/application-dev.yml (已删除) src/main/resources/application-dhdc.yml (已删除) src/main/resources/application-druid.yml (已删除) src/main/resources/application-dzys.yml (已删除) src/main/resources/application-hbkj.yml (已删除) src/main/resources/application-hbxm.yml (已删除) src/main/resources/application-hckx.yml (已删除) src/main/resources/application-hcmy.yml (已删除) src/main/resources/application-hhkj.yml (已删除) src/main/resources/application-hsmy.yml (已删除) src/main/resources/application-hsxny.yml (已删除) src/main/resources/application-hxgy.yml (已删除) src/main/resources/application-hxsj.yml (已删除) src/main/resources/application-hysn.yml (已删除) src/main/resources/application-jjxm.yml (已删除) src/main/resources/application-jlsn.yml (已删除) src/main/resources/application-jmsl.yml (已删除) src/main/resources/application-jsmy.yml (已删除) src/main/resources/application-jsyny.yml (已删除) src/main/resources/application-jyhj.yml (已删除) src/main/resources/application-khl.yml (已删除) src/main/resources/application-mkzs.yml (已删除) src/main/resources/application-mqsp.yml (已删除) src/main/resources/application-mxsc.yml (已删除) src/main/resources/application-nydl.yml (已删除) src/main/resources/application-phmk.yml (已删除) src/main/resources/application-prod.yml (已删除) src/main/resources/application-qlmc.yml (已删除) src/main/resources/application-rzny.yml (已删除) src/main/resources/application-test.yml (已删除) src/main/resources/application-test1.yml (已删除) src/main/resources/application-tjxm.yml (已删除) src/main/resources/application-trsw.yml (已删除) src/main/resources/application-tymk.yml (已删除) src/main/resources/application-wdsy.yml (已删除) src/main/resources/application-xyhb.yml (已删除) src/main/resources/application-zjyj.yml (已删除) src/main/resources/application-zqhx.yml (已删除) src/main/resources/application-zyrq.yml (已删除) src/main/resources/application-zyrqCopy.yml (已删除) src/main/resources/application.yml (已删除) src/main/resources/banner.txt (已删除) src/main/resources/i18n/messages.properties (已删除) src/main/resources/logback.xml (已删除) src/main/resources/mapper/account/AccountExpenseMapper.xml (已删除) src/main/resources/mapper/account/AccountFileMapper.xml (已删除) src/main/resources/mapper/account/AccountIncomeMapper.xml (已删除) src/main/resources/mapper/aftersalesservice/AfterSalesServiceMapper.xml (已删除) src/main/resources/mapper/approve/AnnualLeaveSettingMapper.xml (已删除) src/main/resources/mapper/approve/ApproveLogMapper.xml (已删除) src/main/resources/mapper/approve/ApproveNodeMapper.xml (已删除) src/main/resources/mapper/approve/ApproveProcessMapper.xml (已删除) src/main/resources/mapper/approve/FileSharingMapper.xml (已删除) src/main/resources/mapper/approve/HolidaySettingsMapper.xml (已删除) src/main/resources/mapper/approve/KnowledgeBaseMapper.xml (已删除) src/main/resources/mapper/approve/NotificationManagementMapper.xml (已删除) src/main/resources/mapper/approve/OnlineMeetingMapper.xml (已删除) src/main/resources/mapper/approve/OvertimeSettingMapper.xml (已删除) src/main/resources/mapper/approve/RpaProcessAutomationMapper.xml (已删除) src/main/resources/mapper/approve/WorkingHoursSettingMapper.xml (已删除) src/main/resources/mapper/basic/StorageAttachmentMapper.xml (已删除) src/main/resources/mapper/basic/StorageBlobMapper.xml (已删除) src/main/resources/mapper/basic/SupplierManageMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/DutyPlanMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/MeetApplicationMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/MeetDraftMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/MeetingMinutesMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/MeetingRoomMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/NoticeMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/ReadingStatusMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/RulesRegulationsManagementMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/SealApplicationManagementMapper.xml (已删除) src/main/resources/mapper/collaborativeApproval/StaffContactsPersonalMapper.xml (已删除) src/main/resources/mapper/compensationperformance/CompensationPerformanceMapper.xml (已删除) src/main/resources/mapper/customervisits/CustomerVisitsMapper.xml (已删除) src/main/resources/mapper/device/DeviceDefectRecordMapper.xml (已删除) src/main/resources/mapper/device/DeviceLedgerMapper.xml (已删除) src/main/resources/mapper/device/DeviceMaintenanceMapper.xml (已删除) src/main/resources/mapper/device/DeviceRepairMapper.xml (已删除) src/main/resources/mapper/equipmentenergyconsumption/EnergyPeriodMapper.xml (已删除) src/main/resources/mapper/equipmentenergyconsumption/EquipmentEnergyConsumptionMapper.xml (已删除) src/main/resources/mapper/equipmentenergyconsumption/electricityConsumptionAreaMapper.xml (已删除) src/main/resources/mapper/inspectiontask/TimingTaskMapper.xml (已删除) src/main/resources/mapper/lavorissue/LavorIssueMapper.xml (已删除) src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerMapper.xml (已删除) src/main/resources/mapper/measuringinstrumentledger/MeasuringInstrumentLedgerRecordMapper.xml (已删除) src/main/resources/mapper/measuringinstrumentledger/SparePartsMapper.xml (已删除) src/main/resources/mapper/monitor/SysLogininforMapper.xml (已删除) src/main/resources/mapper/monitor/SysOperLogMapper.xml (已删除) src/main/resources/mapper/oA/OaProjectMapper.xml (已删除) src/main/resources/mapper/oA/OaProjectPhaseMapper.xml (已删除) src/main/resources/mapper/oA/OaProjectPhaseTaskMapper.xml (已删除) src/main/resources/mapper/officesupplies/OfficeSuppliesMapper.xml (已删除) src/main/resources/mapper/procurementrecord/GasTankWarningMapper.xml (已删除) src/main/resources/mapper/procurementrecord/InboundManagementMapper.xml (已删除) src/main/resources/mapper/procurementrecord/ProcurementPlanMapper.xml (已删除) src/main/resources/mapper/procurementrecord/ProcurementPriceManagementMapper.xml (已删除) src/main/resources/mapper/procurementrecord/ProcurementRecordMapper.xml (已删除) src/main/resources/mapper/procurementrecord/ProcurementRecordOutMapper.xml (已删除) src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml (已删除) src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml (已删除) src/main/resources/mapper/production/SalesLedgerSchedulingMapper.xml (已删除) src/main/resources/mapper/production/SalesLedgerWorkMapper.xml (已删除) src/main/resources/mapper/purchase/InvoicePurchaseMapper.xml (已删除) src/main/resources/mapper/purchase/PaymentRegistrationMapper.xml (已删除) src/main/resources/mapper/purchase/ProductRecordMapper.xml (已删除) src/main/resources/mapper/purchase/PurchaseLedgerMapper.xml (已删除) src/main/resources/mapper/quality/QualityInspectFileMapper.xml (已删除) src/main/resources/mapper/quality/QualityInspectMapper.xml (已删除) src/main/resources/mapper/quality/QualityInspectParamMapper.xml (已删除) src/main/resources/mapper/quality/QualityTestStandardMapper.xml (已删除) src/main/resources/mapper/quality/QualityUnqualifiedMapper.xml (已删除) src/main/resources/mapper/sales/InvoiceLedgerMapper.xml (已删除) src/main/resources/mapper/sales/InvoiceRegistrationMapper.xml (已删除) src/main/resources/mapper/sales/InvoiceRegistrationProductMapper.xml (已删除) src/main/resources/mapper/sales/PaymentShippingMapper.xml (已删除) src/main/resources/mapper/sales/ReceiptPaymentMapper.xml (已删除) src/main/resources/mapper/sales/SalesLedgerMapper.xml (已删除) src/main/resources/mapper/sales/SalesQuotationMapper.xml (已删除) src/main/resources/mapper/sales/SalesQuotationProductMapper.xml (已删除) src/main/resources/mapper/sales/SalespersonManagementMapper.xml (已删除) src/main/resources/mapper/sales/ShippingInfoMapper.xml (已删除) src/main/resources/mapper/staff/HolidayApplicationMapper.xml (已删除) src/main/resources/mapper/staff/PersonalAttendanceRecordsMapper.xml (已删除) src/main/resources/mapper/staff/StaffJoinLeaveRecordMapper.xml (已删除) src/main/resources/mapper/staff/StaffOnJobMapper.xml (已删除) src/main/resources/mapper/staff/StaffSchedulingMapper.xml (已删除) src/main/resources/mapper/system/SysConfigMapper.xml (已删除) src/main/resources/mapper/system/SysDeptMapper.xml (已删除) src/main/resources/mapper/system/SysDictDataMapper.xml (已删除) src/main/resources/mapper/system/SysDictTypeMapper.xml (已删除) src/main/resources/mapper/system/SysJobLogMapper.xml (已删除) src/main/resources/mapper/system/SysJobMapper.xml (已删除) src/main/resources/mapper/system/SysMenuMapper.xml (已删除) src/main/resources/mapper/system/SysNoticeMapper.xml (已删除) src/main/resources/mapper/system/SysPostMapper.xml (已删除) src/main/resources/mapper/system/SysRoleDeptMapper.xml (已删除) src/main/resources/mapper/system/SysRoleMapper.xml (已删除) src/main/resources/mapper/system/SysRoleMenuMapper.xml (已删除) src/main/resources/mapper/system/SysUserDeptMapper.xml (已删除) src/main/resources/mapper/system/SysUserMapper.xml (已删除) src/main/resources/mapper/system/SysUserPostMapper.xml (已删除) src/main/resources/mapper/system/SysUserRoleMapper.xml (已删除) src/main/resources/mapper/tool/GenTableColumnMapper.xml (已删除) src/main/resources/mapper/tool/GenTableMapper.xml (已删除) src/main/resources/mapper/warehouse/DocumentClassificationMapper.xml (已删除) src/main/resources/mapper/warehouse/DocumentationBorrowManagementMapper.xml (已删除) src/main/resources/mapper/warehouse/DocumentationFileMapper.xml (已删除) src/main/resources/mapper/warehouse/DocumentationMapper.xml (已删除) src/main/resources/mapper/warehouse/DocumentationReturnManagementMapper.xml (已删除) src/main/resources/mapper/warehouse/WarehouseGoodsShelvesMapper.xml (已删除) src/main/resources/mapper/warehouse/WarehouseGoodsShelvesRowcolMapper.xml (已删除) src/main/resources/mapper/warehouse/WarehouseMapper.xml (已删除) src/main/resources/mapper/waterrecord/WaterRecordMapper.xml (已删除) src/main/resources/mybatis/mybatis-config.xml (已删除) src/main/resources/static/report-template.docx (已删除) src/main/resources/vm/java/controller.java.vm (已删除) src/main/resources/vm/java/domain.java.vm (已删除) src/main/resources/vm/java/mapper.java.vm (已删除) src/main/resources/vm/java/service.java.vm (已删除) src/main/resources/vm/java/serviceImpl.java.vm (已删除) src/main/resources/vm/java/sub-domain.java.vm (已删除) src/main/resources/vm/js/api.js.vm (已删除) src/main/resources/vm/sql/sql.vm (已删除) src/main/resources/vm/vue/index-tree.vue.vm (已删除) src/main/resources/vm/vue/index.vue.vm (已删除) src/main/resources/vm/vue/v3/index-tree.vue.vm (已删除) src/main/resources/vm/vue/v3/index.vue.vm (已删除) src/main/resources/vm/xml/mapper.xml.vm (已删除) start-dev.cmd