luodangjia
2024-12-10 2eb44e7d245d82afd32ad2c46eaba6efa8a3d9a0
12.10
2个文件已修改
631个文件已添加
76181 ■■■■■ 已修改文件
.gitignore 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LICENSE 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/clean.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/package.bat 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/run.bat 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/若依环境使用手册.docx 补丁 | 查看 | 原始文档 | blame | 历史
mvnw 316 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
mvnw.cmd 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/lib/alipay-sdk-java-4.39.223.ALL.jar 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/lib/freemarker.jar 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/pom.xml 221 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/RuoYiManageApplication.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AlipayScanPay.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/CallBackController.java 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TAppUserController.java 497 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBannerController.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCommitteeController.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCommitteeMajorController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCommitteeTechnicalController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TConsultationClassificationController.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TConsultationController.java 227 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TConsultationMessageController.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCourseCommentController.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCourseController.java 413 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCoursePartController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeController.java 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeFileController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeMajorController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeTechnicalController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TGeneratedRecordsController.java 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TIndexMenuController.java 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInfoConfigController.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInformationClassController.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInformationController.java 315 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TOrderController.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TRegionController.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TTechnicalTitleController.java 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TTitleMajorController.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TUserChangeController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TUserChangeDetailController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TestController.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/WebController.java 86 ●●●●● 补丁 | 查看 | 原始文档 | 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 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisConfiguration.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java 120 ●●●●● 补丁 | 查看 | 原始文档 | 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 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/CityQueryDto.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/CommitteeQuery.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/ConsultationQuery.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/CourseQuery.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/DeclareNoticeQuery.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/InformationQuery.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/OrderCountQuery.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/PayDto.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/VideoAddDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/CountTotalDto.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/FreezeDto.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/ManageCountDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/RegisterDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java 148 ●●●●● 补丁 | 查看 | 原始文档 | 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 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | 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 136 ●●●●● 补丁 | 查看 | 原始文档 | 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 345 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/AlipayTradePagePay.java 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/AlipayTradeQuery.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/AlipayTradeRefund.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/BaiDuApi.java 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HttpClientUtil.java 147 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HttpResult.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ImportExcelUtil.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MD5AndKL.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MsgCodeUtil.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MsgUtil.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MsgUtils.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ObsUploadUtil.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PayMoneyUtil.java 879 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PinyinExample.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/QRCodeUtil.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ResultUtil.java 187 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TaskUtil.java 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/UUIDUtil.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-druid.yml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application.yml 203 ●●●●● 补丁 | 查看 | 原始文档 | 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-config.xml 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/templates/专业技术工作总结.xml 1515 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/HELP.md 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/pom.xml 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/RuoYiAppletApplication.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/RuoYiServletInitializer.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/common/CommonController.java 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisConfiguration.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysPostController.java 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java 136 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java 320 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysUserController.java 401 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/BaiDuApi.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/HttpClientUtil.java 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/ImportExcelUtil.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MsgCodeUtil.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MsgUtils.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/QRCodeUtil.java 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TaskUtil.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TestController.java 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/META-INF/spring-devtools.properties 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/application-druid.yml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/application.yml 164 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/banner.txt 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/i18n/messages.properties 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/logback.xml 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/mybatis-config.xml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/resources/mybatis/mybatis-config.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 173 ●●●●● 补丁 | 查看 | 原始文档 | 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 33 ●●●●● 补丁 | 查看 | 原始文档 | 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 187 ●●●●● 补丁 | 查看 | 原始文档 | 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/basic/PageInfo.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/DataUpdateHandlerConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/FileUploadConfig.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/MybatisPlusConfig.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/WxConfig.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/OrderNumConstants.java 21 ●●●●● 补丁 | 查看 | 原始文档 | 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 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/constant/WxConstant.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/FileController.java 140 ●●●●● 补丁 | 查看 | 原始文档 | 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/BaseModel.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BasePage.java 50 ●●●●● 补丁 | 查看 | 原始文档 | 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 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java 259 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java 386 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java 299 ●●●●● 补丁 | 查看 | 原始文档 | 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/domain/model/TimeRangeQueryBody.java 46 ●●●●● 补丁 | 查看 | 原始文档 | 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 122 ●●●●● 补丁 | 查看 | 原始文档 | 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 268 ●●●●● 补丁 | 查看 | 原始文档 | 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 1000 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/BoardEnum.java 45 ●●●●● 补丁 | 查看 | 原始文档 | 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 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/enums/DisabledEnum.java 43 ●●●●● 补丁 | 查看 | 原始文档 | 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/UpdateTypeEnum.java 47 ●●●●● 补丁 | 查看 | 原始文档 | 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 61 ●●●●● 补丁 | 查看 | 原始文档 | 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 16 ●●●●● 补丁 | 查看 | 原始文档 | 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 16 ●●●●● 补丁 | 查看 | 原始文档 | 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/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/resp/AccessTokenRespBody.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java 389 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java 186 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/IDCardUtils.java 18 ●●●●● 补丁 | 查看 | 原始文档 | 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/MultipartFileUtil.java 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java 120 ●●●●● 补丁 | 查看 | 原始文档 | 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 614 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/TimeConverter.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/VideoUtil.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/WebUtils.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletTools.java 77 ●●●●● 补丁 | 查看 | 原始文档 | 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 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java 59 ●●●●● 补丁 | 查看 | 原始文档 | 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 274 ●●●●● 补丁 | 查看 | 原始文档 | 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/ExcelUtil.java 1762 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java 409 ●●●●● 补丁 | 查看 | 原始文档 | 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 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java 70 ●●●●● 补丁 | 查看 | 原始文档 | 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 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/pom.xml 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java 174 ●●●●● 补丁 | 查看 | 原始文档 | 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 267 ●●●●● 补丁 | 查看 | 原始文档 | 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 30 ●●●●● 补丁 | 查看 | 原始文档 | 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 58 ●●●●● 补丁 | 查看 | 原始文档 | 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 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java 158 ●●●●● 补丁 | 查看 | 原始文档 | 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 73 ●●●●● 补丁 | 查看 | 原始文档 | 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 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | 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 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java 326 ●●●●● 补丁 | 查看 | 原始文档 | 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 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java 372 ●●●●● 补丁 | 查看 | 原始文档 | 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 83 ●●●●● 补丁 | 查看 | 原始文档 | 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 521 ●●●●● 补丁 | 查看 | 原始文档 | 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 121 ●●●●● 补丁 | 查看 | 原始文档 | 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 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/generator.yml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml 202 ●●●●● 补丁 | 查看 | 原始文档 | 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/vue/index-tree.vue.vm 505 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm 602 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm 474 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm 590 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/pom.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | 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 169 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java 154 ●●●●● 补丁 | 查看 | 原始文档 | 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 107 ●●●●● 补丁 | 查看 | 原始文档 | 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 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/pom.xml 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/code/SubmitTemplateReg.java 40 ●●●●● 补丁 | 查看 | 原始文档 | 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 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java 322 ●●●●● 补丁 | 查看 | 原始文档 | 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/TAppUser.java 167 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TBanner.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TCommittee.java 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TCommitteeMajor.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TCommitteeTechnical.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TConsultation.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TConsultationClassification.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TConsultationMessage.java 75 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TCourse.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TCourseComment.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TCoursePart.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNotice.java 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNoticeFile.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNoticeMajor.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNoticeTechnical.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TGeneratedRecords.java 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TIndexMenu.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TInfoConfig.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TInformation.java 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TInformationClass.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TLevel.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TOrder.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TRegion.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TTechnicalTitle.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TTitleMajor.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TUserChange.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/domain/TUserChangeDetail.java 68 ●●●●● 补丁 | 查看 | 原始文档 | 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/dto/AddDishDTO.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/AllertTitleDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/CheckoutDTO.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/DataScreeningDTO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/MahorImportExcel.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/MealOrderGoodsDTO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/OrderMealGeneratorCountDTO.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/OrderMealGeneratorDTO.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/RegionChildrenDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/RegionDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/StockDataSetDTO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/SysRoleDTO.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/SysUserUpdateStatusDTO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TVideoDto.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/TechImportExcel.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/UpdatePwdDTO.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/export/MealGeneratorListExport.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/export/OpticalInspectionExport.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/export/SaleGeneratorListExport.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/export/TOrderMealExportExcel.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java 118 ●●●●● 补丁 | 查看 | 原始文档 | 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 135 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java 101 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TAppUserMapper.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBannerMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCommitteeMajorMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCommitteeMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCommitteeTechnicalMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TConsultationClassificationMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TConsultationMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TConsultationMessageMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCourseCommentMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCourseMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCoursePartMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeFileMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeMajorMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeTechnicalMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TGeneratedRecordsMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TIndexMenuMapper.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInfoConfigMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInformationClassMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInformationMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TLevelMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TOrderMapper.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TRegionMapper.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTechnicalTitleMapper.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTitleMajorMapper.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TUserChangeDetailMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TUserChangeMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/AppUserQuery.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/CommentQuery.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/GeneratedQuery.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/MessageQuery.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/OrderQuery.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/ProfitDetailsQuery.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/RegionQuery.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/SysRoleQuery.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/TUserQuery.java 24 ●●●●● 补丁 | 查看 | 原始文档 | 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 124 ●●●●● 补丁 | 查看 | 原始文档 | 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 166 ●●●●● 补丁 | 查看 | 原始文档 | 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 57 ●●●●● 补丁 | 查看 | 原始文档 | 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 235 ●●●●● 补丁 | 查看 | 原始文档 | 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 268 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TAppUserService.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TBannerService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TCommitteeMajorService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TCommitteeService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TCommitteeTechnicalService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TConsultationClassificationService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TConsultationMessageService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TConsultationService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TCourseCommentService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TCoursePartService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TCourseService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeFileService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeMajorService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeTechnicalService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TGeneratedRecordsService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TIndexMenuService.java 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TInfoConfigService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TInformationClassService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TInformationService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TLevelService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TOrderService.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TRegionService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TTechnicalTitleService.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TTitleMajorService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TUserChangeDetailService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TUserChangeService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java 340 ●●●●● 补丁 | 查看 | 原始文档 | 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 546 ●●●●● 补丁 | 查看 | 原始文档 | 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 254 ●●●●● 补丁 | 查看 | 原始文档 | 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 608 ●●●●● 补丁 | 查看 | 原始文档 | 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 651 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBannerServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCommitteeMajorServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCommitteeServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCommitteeTechnicalServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TConsultationClassificationServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TConsultationMessageServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TConsultationServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCourseCommentServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCoursePartServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCourseServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeFileServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeMajorServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeTechnicalServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TGeneratedRecordsServiceImpl.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TIndexMenuServiceImpl.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInfoConfigServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationClassServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TLevelServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TOrderServiceImpl.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TRegionServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTechnicalTitleServiceImpl.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTitleMajorServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TUserChangeDetailServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TUserChangeServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/AmountSumVO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/GoodsProfitVO.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/OrderTrendsVO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/PersonnelStatisticsAndSumVO.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/PersonnelStatisticsVO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/ProfitDetailsVO.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/RoleInfoVO.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/SalesRankingVO.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/SalesVolumeVO.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysOperLogVO.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/UserAddListVO.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/UserLevelVO.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vx/AlipayTradePagePay.java 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vx/QuickStart.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vx/WeChatConfig.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vx/WeChatUtil.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml 165 ●●●●● 补丁 | 查看 | 原始文档 | 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 252 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml 117 ●●●●● 补丁 | 查看 | 原始文档 | 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 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml 354 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TAppUserMapper.xml 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TBannerMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCommitteeMajorMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCommitteeMapper.xml 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCommitteeTechnicalMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TConsultationClassificationMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TConsultationMapper.xml 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TConsultationMessageMapper.xml 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCourseCommentMapper.xml 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCourseMapper.xml 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCoursePartMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeFileMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeMajorMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeMapper.xml 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeTechnicalMapper.xml 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TGeneratedRecordsMapper.xml 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TIndexMenuMapper.xml 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TInfoConfigMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TInformationClassMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TInformationMapper.xml 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TLevelMapper.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TOrderMapper.xml 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TRegionMapper.xml 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TTechnicalTitleMapper.xml 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TTitleMajorMapper.xml 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TUserChangeDetailMapper.xml 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TUserChangeMapper.xml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ry.bat 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ry.sh 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/quartz.sql 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/ry_20230706.sql 699 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
tech_info.sql 12561 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.gitignore
@@ -1,12 +1,47 @@
*.class
######################################################################
# Build Tools
# Mobile Tools for Java (J2ME)
.mtj.tmp/
.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar
# Package Files #
*.jar
*.war
*.ear
target/
!.mvn/wrapper/maven-wrapper.jar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
######################################################################
# IDE
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### JRebel ###
rebel.xml
### NetBeans ###
nbproject/private/
build/*
nbbuild/
dist/
nbdist/
.nb-gradle/
######################################################################
# Others
*.log
*.xml.versionsBackup
*.swp
!*/build/*.java
!*/build/*.html
!*/build/*.xml
LICENSE
New file
@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2018 RuoYi
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
README.md
@@ -1,4 +1,4 @@
## tech_info
## cashier
同诚知创教育网
职评网系统
bin/clean.bat
New file
@@ -0,0 +1,12 @@
@echo off
echo.
echo [ÐÅÏ¢] ÇåÀí¹¤³ÌtargetÉú³É·¾¶¡£
echo.
%~d0
cd %~dp0
cd ..
call mvn clean
pause
bin/package.bat
New file
@@ -0,0 +1,12 @@
@echo off
echo.
echo [ÐÅÏ¢] ´ò°üWeb¹¤³Ì£¬Éú³Éwar/jar°üÎļþ¡£
echo.
%~d0
cd %~dp0
cd ..
call mvn clean package -Dmaven.test.skip=true
pause
bin/run.bat
New file
@@ -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
doc/若依环境使用手册.docx
Binary files differ
mvnw
New file
@@ -0,0 +1,316 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
#   JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
#   M2_HOME - location of maven2's installed home dir
#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
#     e.g. to debug Maven itself, use
#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
  if [ -f /usr/local/etc/mavenrc ] ; then
    . /usr/local/etc/mavenrc
  fi
  if [ -f /etc/mavenrc ] ; then
    . /etc/mavenrc
  fi
  if [ -f "$HOME/.mavenrc" ] ; then
    . "$HOME/.mavenrc"
  fi
fi
# OS specific support.  $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
  CYGWIN*) cygwin=true ;;
  MINGW*) mingw=true;;
  Darwin*) darwin=true
    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
    if [ -z "$JAVA_HOME" ]; then
      if [ -x "/usr/libexec/java_home" ]; then
        export JAVA_HOME="`/usr/libexec/java_home`"
      else
        export JAVA_HOME="/Library/Java/Home"
      fi
    fi
    ;;
esac
if [ -z "$JAVA_HOME" ] ; then
  if [ -r /etc/gentoo-release ] ; then
    JAVA_HOME=`java-config --jre-home`
  fi
fi
if [ -z "$M2_HOME" ] ; then
  ## resolve links - $0 may be a link to maven's home
  PRG="$0"
  # need this for relative symlinks
  while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
      PRG="$link"
    else
      PRG="`dirname "$PRG"`/$link"
    fi
  done
  saveddir=`pwd`
  M2_HOME=`dirname "$PRG"`/..
  # make it fully qualified
  M2_HOME=`cd "$M2_HOME" && pwd`
  cd "$saveddir"
  # echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --unix "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
  [ -n "$M2_HOME" ] &&
    M2_HOME="`(cd "$M2_HOME"; pwd)`"
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
  javaExecutable="`which javac`"
  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
    # readlink(1) is not available as standard on Solaris 10.
    readLink=`which readlink`
    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
      if $darwin ; then
        javaHome="`dirname \"$javaExecutable\"`"
        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
      else
        javaExecutable="`readlink -f \"$javaExecutable\"`"
      fi
      javaHome="`dirname \"$javaExecutable\"`"
      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
      JAVA_HOME="$javaHome"
      export JAVA_HOME
    fi
  fi
fi
if [ -z "$JAVACMD" ] ; then
  if [ -n "$JAVA_HOME"  ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
      # IBM's JDK on AIX uses strange locations for the executables
      JAVACMD="$JAVA_HOME/jre/sh/java"
    else
      JAVACMD="$JAVA_HOME/bin/java"
    fi
  else
    JAVACMD="`\\unset -f command; \\command -v java`"
  fi
fi
if [ ! -x "$JAVACMD" ] ; then
  echo "Error: JAVA_HOME is not defined correctly." >&2
  echo "  We cannot execute $JAVACMD" >&2
  exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
  echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
  if [ -z "$1" ]
  then
    echo "Path not specified to find_maven_basedir"
    return 1
  fi
  basedir="$1"
  wdir="$1"
  while [ "$wdir" != '/' ] ; do
    if [ -d "$wdir"/.mvn ] ; then
      basedir=$wdir
      break
    fi
    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
    if [ -d "${wdir}" ]; then
      wdir=`cd "$wdir/.."; pwd`
    fi
    # end of workaround
  done
  echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
  if [ -f "$1" ]; then
    echo "$(tr -s '\n' ' ' < "$1")"
  fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
  exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Found .mvn/wrapper/maven-wrapper.jar"
    fi
else
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
    fi
    if [ -n "$MVNW_REPOURL" ]; then
      jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
    else
      jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
    fi
    while IFS="=" read key value; do
      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
      esac
    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
    if [ "$MVNW_VERBOSE" = true ]; then
      echo "Downloading from: $jarUrl"
    fi
    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
    if $cygwin; then
      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
    fi
    if command -v wget > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found wget ... using wget"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
        else
            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
        fi
    elif command -v curl > /dev/null; then
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Found curl ... using curl"
        fi
        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
            curl -o "$wrapperJarPath" "$jarUrl" -f
        else
            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
        fi
    else
        if [ "$MVNW_VERBOSE" = true ]; then
          echo "Falling back to using Java to download"
        fi
        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
        # For Cygwin, switch paths to Windows format before running javac
        if $cygwin; then
          javaClass=`cygpath --path --windows "$javaClass"`
        fi
        if [ -e "$javaClass" ]; then
            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Compiling MavenWrapperDownloader.java ..."
                fi
                # Compiling the Java class
                ("$JAVA_HOME/bin/javac" "$javaClass")
            fi
            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
                # Running the downloader
                if [ "$MVNW_VERBOSE" = true ]; then
                  echo " - Running MavenWrapperDownloader.java ..."
                fi
                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
            fi
        fi
    fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
  echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
  [ -n "$M2_HOME" ] &&
    M2_HOME=`cygpath --path --windows "$M2_HOME"`
  [ -n "$JAVA_HOME" ] &&
    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
  [ -n "$CLASSPATH" ] &&
    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
  $MAVEN_OPTS \
  $MAVEN_DEBUG_OPTS \
  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
  "-Dmaven.home=${M2_HOME}" \
  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
mvnw.cmd
New file
@@ -0,0 +1,188 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements.  See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership.  The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License.  You may obtain a copy of the License at
@REM
@REM    https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied.  See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM     e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
    if "%MVNW_VERBOSE%" == "true" (
        echo Found %WRAPPER_JAR%
    )
) else (
    if not "%MVNW_REPOURL%" == "" (
        SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
    )
    if "%MVNW_VERBOSE%" == "true" (
        echo Couldn't find %WRAPPER_JAR%, downloading it ...
        echo Downloading from: %DOWNLOAD_URL%
    )
    powershell -Command "&{"^
        "$webclient = new-object System.Net.WebClient;"^
        "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
        "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
        "}"^
        "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
        "}"
    if "%MVNW_VERBOSE%" == "true" (
        echo Finished downloading %WRAPPER_JAR%
    )
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
  %JVM_CONFIG_MAVEN_PROPS% ^
  %MAVEN_OPTS% ^
  %MAVEN_DEBUG_OPTS% ^
  -classpath %WRAPPER_JAR% ^
  "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
  %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%
pom.xml
New file
@@ -0,0 +1,246 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ruoyi</groupId>
    <artifactId>ruoyi</artifactId>
    <version>3.8.6</version>
    <name>ruoyi</name>
    <url>http://www.ruoyi.vip</url>
    <description>若依管理系统</description>
    <properties>
        <ruoyi.version>3.8.6</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>
        <druid.version>1.2.16</druid.version>
        <bitwalker.version>1.21</bitwalker.version>
        <swagger.version>3.0.0</swagger.version>
        <kaptcha.version>2.3.3</kaptcha.version>
        <pagehelper.boot.version>1.4.6</pagehelper.boot.version>
        <fastjson.version>2.0.39</fastjson.version>
        <oshi.version>6.4.4</oshi.version>
        <commons.io.version>2.13.0</commons.io.version>
        <commons.collections.version>3.2.2</commons.collections.version>
        <poi.version>4.1.2</poi.version>
        <velocity.version>2.3</velocity.version>
        <jwt.version>0.9.1</jwt.version>
    </properties>
    <!-- 依赖声明 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>2.0.25</version>
            </dependency>
            <!-- SpringBoot的依赖配置-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.5.15</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 阿里数据库连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!-- 解析客户端操作系统、浏览器等 -->
            <dependency>
                <groupId>eu.bitwalker</groupId>
                <artifactId>UserAgentUtils</artifactId>
                <version>${bitwalker.version}</version>
            </dependency>
            <!-- pagehelper 分页插件 -->
<!--            <dependency>-->
<!--                <groupId>com.github.pagehelper</groupId>-->
<!--                <artifactId>pagehelper-spring-boot-starter</artifactId>-->
<!--                <version>${pagehelper.boot.version}</version>-->
<!--            </dependency>-->
            <!-- 获取系统信息 -->
            <dependency>
                <groupId>com.github.oshi</groupId>
                <artifactId>oshi-core</artifactId>
                <version>${oshi.version}</version>
            </dependency>
            <!-- 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>
            <!-- io常用工具类 -->
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons.io.version}</version>
            </dependency>
            <!-- excel工具 -->
<!--            <dependency>-->
<!--                <groupId>org.apache.poi</groupId>-->
<!--                <artifactId>poi-ooxml</artifactId>-->
<!--                <version>${poi.version}</version>-->
<!--            </dependency>-->
<!--            <dependency>-->
<!--                <groupId>org.apache.poi</groupId>-->
<!--                <artifactId>poi</artifactId>-->
<!--                <version>${poi.version}</version>-->
<!--            </dependency>-->
<!--            <dependency>-->
<!--                <groupId>org.apache.poi</groupId>-->
<!--                <artifactId>poi-ooxml-schemas</artifactId>-->
<!--                <version>${poi.version}</version>-->
<!--            </dependency>-->
            <!-- velocity代码生成使用模板 -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity-engine-core</artifactId>
                <version>${velocity.version}</version>
            </dependency>
            <!-- collections工具类 -->
            <dependency>
                <groupId>commons-collections</groupId>
                <artifactId>commons-collections</artifactId>
                <version>${commons.collections.version}</version>
            </dependency>
            <!-- 阿里JSON解析器 -->
            <dependency>
                <groupId>com.alibaba.fastjson2</groupId>
                <artifactId>fastjson2</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
            <!-- Token生成与解析-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>${jwt.version}</version>
            </dependency>
            <!-- 验证码 -->
            <dependency>
                <groupId>pro.fessional</groupId>
                <artifactId>kaptcha</artifactId>
                <version>${kaptcha.version}</version>
            </dependency>
            <!-- 定时任务-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-quartz</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
            <!-- 代码生成-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-generator</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
            <!-- 核心模块-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-framework</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
            <!-- 系统模块-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-system</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
            <!-- 通用工具-->
            <dependency>
                <groupId>com.ruoyi</groupId>
                <artifactId>ruoyi-common</artifactId>
                <version>${ruoyi.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <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>
        <module>ruoyi-applet</module>
    </modules>
    <packaging>pom</packaging>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
    </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>
    <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>
ruoyi-admin/lib/alipay-sdk-java-4.39.223.ALL.jar
Binary files differ
ruoyi-admin/lib/freemarker.jar
Binary files differ
ruoyi-admin/pom.xml
New file
@@ -0,0 +1,221 @@
<?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.8.6</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>ruoyi-admin</artifactId>
    <description>
        web服务入口
    </description>
    <dependencies>
        <dependency>
            <groupId>com.belerweb</groupId>
            <artifactId>pinyin4j</artifactId>
            <version>2.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.huaweicloud</groupId>
            <artifactId>esdk-obs-java</artifactId>
            <version>3.19.5</version>
            <exclusions>
                <exclusion>
                    <artifactId>okio</artifactId>
                    <groupId>com.squareup.okio</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-local</artifactId>
            <version>1.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-transformer-msoffice-word</artifactId>
            <version>1.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.33</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>com.github.wechatpay-apiv3</groupId>-->
<!--            <artifactId>wechatpay-java</artifactId>-->
<!--            <version>0.2.7</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>com.alipay.sdk</groupId>-->
<!--            <artifactId>alipay-sdk-java</artifactId>-->
<!--            <version>4.8.10.ALL</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.8.0</version>
        </dependency>
        <!-- spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- 表示依赖不会传递 -->
        </dependency>
        <!-- swagger3-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>com.github.xiaoymin</groupId>-->
<!--            <artifactId>swagger-bootstrap-ui</artifactId>-->
<!--            <version>1.9.6</version>-->
<!--        </dependency>-->
        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.6.2</version>
        </dependency>
         <!-- Mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</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>
        <!--二维码开发工具集-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.10</version>
        </dependency>
        <!-- zxing生成二维码 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.apache.httpcomponents</groupId>-->
<!--            <artifactId>httpcore</artifactId>-->
<!--            <version>4.3.2</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
        <!-- easypoi -->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>3.0.3</version>
        </dependency>
        <!-- 阿里云短信 -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>dysmsapi20170525</artifactId>
            <version>2.0.10</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.15</version>
                <configuration>
                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
                </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/RuoYiManageApplication.java
New file
@@ -0,0 +1,64 @@
package com.ruoyi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
import java.net.InetAddress;
/**
 * 启动程序
 *
 * @author ruoyi
 */
@Slf4j
@EnableScheduling//开启定时任务
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiManageApplication
{
    public static void main(String[] args) {
        ConfigurableApplicationContext application = SpringApplication.run(RuoYiManageApplication.class, args);
        try {
        Environment env = application.getEnvironment();
        log.info("\n----------------------------------------------------------\n\t" +
                        "应用 '{}' 运行成功! 访问连接:\n\t" +
                        "Swagger文档: \t\thttp://{}:{}/doc.html\n" +
                        "----------------------------------------------------------",
                env.getProperty("spring.application.name", "后台"),
                InetAddress.getLocalHost().getHostAddress(),
                env.getProperty("server.port", "8081"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * 当不存在此 wxRestTemplate 使用此方法的bean注入
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(name = "restTemplate")
    public RestTemplate wxRestTemplate() {
        //复杂构造函数的使用
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        // 设置超时
        requestFactory.setConnectTimeout(6000);
        requestFactory.setReadTimeout(6000);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(requestFactory);
        return restTemplate;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
New file
@@ -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(RuoYiManageApplication.class);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AlipayScanPay.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.web.controller.api;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
public class AlipayScanPay {
    public static void main(String[] args) {
        // 1. 配置参数
        String appId = "2021004184657725";
        String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCMfMyRu0w45qXmyw2KdUCX+gE+mT9lPFahJwkWHVQMh7M0tiU3H7sFFG40+VLK8sBfBhtzkogasJ6en/WYEzIC0iRw0s1jj12Ja06Xy67+h4dlB97489Hc1YOcQ+14ZatGkZUhtjJ51pw77cEjKZ+/9Xx2P2mWUI7FPpGwSJmBI4gBO7Mu3qcQ5e0RqIdqXKOvnk4pA98SUeYHfWN/XIzqI1UAzyuY/wZuIzKvTdgWtC41oidf0ngZua7HLr8cJrndPIu1YALs7L4RgPSjL/5HDAQ991QwAs4ByRGEStx2HZ/o6CddZ8x831GGEtCI3q1tn+7OJrcCzt803iVTys+ZAgMBAAECggEAOfj14d1MYt6q70YzXENuWEiOYuqSQpBXn0Cge0O2/0SwKrxPNyQc5Me9gpawF5d80rmOcm6xQ3JGwmZ3zj19kbRt3TDgGIl8q8xgLjubBuWedY598HWM0Hg7SyysvdYWi5Rf2f15btWkuwYtgPkYNvpyVcltJN4xTCu5qukKj0Mhgxtp7/rnAFYtJSf/2GlL1jEhiE2nmcVLX7qBUG4k4jwcQal7Y+dNhoU7ZT4d5kYnZQ3tT/nHXDJSlj/uZAjKMAw5EGSKw4gnfCg2vqo9uF/ni0JxbwV1oC4mfGK3JQv4ZcszIlo25laRPRNsIxlPRF9uhVKEBq3L7O5i+ZzBUQKBgQDIxpYOuxL7VUIIa1WRKDl4YuxcM6QgX6V5L9UnidCwo72IhT6CkPQVu8uHx55qPI8UpVhbYYrxYH5xCYoZ0+fK6LRK9wMJUjL6Gg/HjXTbGyzcIoIaJ0JA4hHPD2onrWbNWwjylTzu1w4opWArexD6rX8WavS3mfZC04fw6oRZ5wKBgQCzIRR2CVnvtNnzAa36YbSQviCMlRfNxfnPDXHGjWMReHuMDxFQHPTGsB7HA8QmIjM1GTFaHhgNAl6BGIgDo+KPwbIVFJCXiQ2k4Il+znYRxFXmTqGsOARl19oIFXLUI0sy3TOFYVDBjBfk4ICTpn8IKACOvAPUFOJHid4P/GFafwKBgQC6pMHCl+4hbzSflwhIlNg4Ld4EKI2e+stdSTYiN1+lldIQI63kutPtkFK4ur1tjTaFvt/Qs3Dyyv1AH9oeAHwuiP1x4wcTlzKEhc29eKb1OOIPEpVXsr9IieB8WJwannw+0y4SNOIcNheXeYVZZmJ2ZusJ8Avm0l236eUp9RlsaQKBgHPFvIixcIwpkfeqLTy3K1GlYDocHl9jRhpZMSDHvrDK8ubJ0kG6BUXpDGtJ9ttCnWADIU+CRb8aueOr7DSWFlcdNDDFstINxWC7soHfhJXlFDOevIUnS0hbYtJ4sleDXBXKu4LIK758AfFuXAuRv2aRHBMkV0EaIklkRL6GOpGXAoGBAKbNBXmOqTxl6bKD9Jlpcn6Kq06feK7dzRoGdG3x1eY6DrJu40Wsi71QYSz5MLTxcJLNIfnuMoQPPQrPcX98GCy0OnVH7KLMoztEs15TlHPJF1BQAJlHhmzwHB5UNpC2fP6x9WaAow0YD7/BL59QLH989+baFdw4ZmQk2iEF5u2b";
        String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmmtqSfZPk3pAFp/gqdBDWc9qimhjRMMvPPLTNypQ8CzsTpSx3wLXVCj2LXYKg4zQzZLHtYb7CJajs8gqDmRn1tAY8iViekV8AsTksXJ5fiO67e5JenPFS048/v/xQI8qNtllqY/MzCbZ0QvnATMeLX6Iwi4ZGRzLlL2wEEGfy2DJ2osRd+tIU+9y5EErObEzJdT+yxxVmOvpvJuVqf7NfnrMZj3ijYg+qDQEu6kDhuXrlZvS6MAUsZUiOE3/uQwSws0bD9ROWyYk7Mr7CH+3u0oLQeBweYQVtqRZWERm6Oxa0gxpqJILTL5+9T5hdFGdFV0xrF59Pk4eTeImeUrbIwIDAQAB";
        String serverUrl = "https://openapi.alipay.com/gateway.do";
        String format = "json";
        String charset = "UTF-8";
        String signType = "RSA2";
        // 2. 使用SDK生成支付请求
        AlipayClient alipayClient = new DefaultAlipayClient(serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
        // 设置请求参数
        request.setBizContent("{" +
                "\"out_trade_no\":\"20160320010101001\"," +
                "\"total_amount\":88.88," +
                "\"subject\":\"IQAY研发部账户充值\"," +
                "\"seller_id\":\"2088102169983482\"," +
                "\"body\":\"IQAY研发部账户充值\"" +
                "}");
        // 3. 发送请求并获取响应
        try {
            AlipayTradePrecreateResponse response = alipayClient.execute(request);
            // 4. 处理响应
            if(response.isSuccess()){
                System.out.println("扫码支付预下单成功,二维码为:" + response.getQrCode());
            } else {
                System.out.println("扫码支付预下单失败,错误码:" + response.getCode() + ",错误信息:" + response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/CallBackController.java
New file
@@ -0,0 +1,144 @@
package com.ruoyi.web.controller.api;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TCourse;
import com.ruoyi.system.domain.TOrder;
import com.ruoyi.system.service.TCourseService;
import com.ruoyi.system.service.TOrderService;
import com.ruoyi.system.vx.WeChatConfig;
import com.ruoyi.system.vx.WeChatUtil;
import com.ruoyi.web.controller.tool.AlipayTradePagePay;
import com.ruoyi.web.controller.tool.AlipayTradeQuery;
import com.ruoyi.web.controller.tool.PayMoneyUtil;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.service.partnerpayments.app.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.ValidationException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@RestController
@RequestMapping("/call-back")
public class CallBackController {
    @Resource
    private NotificationParser notificationParser;
    @Resource
    private TOrderService orderService;
    @Resource
    private WeChatConfig weChatConfig;
    @Resource
    private RefundService refundService;
    @Resource
    private PayMoneyUtil payMoneyUtil;
    @ApiOperation(value = "支付回调",tags = {"支付宝轮询"})
    @RequestMapping (value = "/ali/buy")
    @Transactional
    public R alipayCallback(Long orderId) throws AlipayApiException {
//            String outTradeNo = stringStringMap.get("out_trade_no");
            TOrder one = orderService.getById(orderId);
        Boolean check = AlipayTradeQuery.check(one.getCode());
        if (check) {
            one.setPaymentStatus(2);
            orderService.updateById(one);
            return R.ok();
        }else {
            return R.fail("请支付");
        }
    }
    @Resource
    private TCourseService courseService;
    @ApiOperation(value = "支付回调",tags = {"微信支付回调"})
    @RequestMapping (value = "/buy")
    @Transactional
    public R payNotify(HttpServletRequest request) throws Exception{
                System.err.println("======回调开始");
        Transaction transaction;
        transaction = notificationParser.parse(WeChatUtil.handleNodifyRequestParam(request), Transaction.class);
        if (transaction.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
                    TOrder one = orderService.lambdaQuery().eq(TOrder::getCode, transaction.getOutTradeNo()).one();
                    one.setPaymentStatus(2);
                    one.setSerialNumber(transaction.getTransactionId());
            one.setPayTime(LocalDateTime.now());
            one.setPaymentType(1);
                    orderService.updateById(one);
                    if (one.getGoodType()==1){
                        try {
                            TCourse byId = courseService.getById(one.getGoodId());
                            byId.setBuyNum(byId.getBuyNum()+1);
                            courseService.updateById(byId);
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
        }
        return R.ok(null,"SUCCESS");
    }
    @ApiOperation(value = "退款",tags = {"统一退款接口"})
    @PostMapping (value = "/refund")
    @Transactional
    public R refund(@RequestParam Long orderId) {
        TOrder byId = orderService.getById(orderId);
        if (byId.getPaymentType() == 1) {
            try {
                CreateRequest createRequest = new CreateRequest();
                AmountReq amountReq = new AmountReq();
                amountReq.setRefund(byId.getPaymentAmount().multiply(BigDecimal.valueOf(100)).longValue());
                amountReq.setTotal(byId.getPaymentAmount().multiply(BigDecimal.valueOf(100)).longValue());
                amountReq.setCurrency("CNY");
                createRequest.setAmount(amountReq);
                createRequest.setNotifyUrl("http://www.zhipingwang.com.cn:8081/call-back/buy");
                createRequest.setOutTradeNo(byId.getCode());
                createRequest.setOutRefundNo("TK" + WeChatUtil.generateTradeNumber());
                Refund refund = refundService.create(createRequest);
                byId.setPaymentStatus(3);
                orderService.updateById(byId);
            }catch (Exception e){
                e.printStackTrace();
                return R.fail("当前服务器异常,请联系客服");
            }
        }else {
            try {
                AlipayTradePagePay.refund(byId.getPaymentAmount().toString(),byId.getCode());
            }catch (Exception e) {
                e.printStackTrace();
                return R.fail("当前服务器异常,请联系客服");
            }finally {
                byId.setPaymentStatus(3);
                orderService.updateById(byId);
            }
        }
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TAppUserController.java
New file
@@ -0,0 +1,497 @@
package com.ruoyi.web.controller.api;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
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.WebUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.export.TOrderMealExportExcel;
import com.ruoyi.system.query.AppUserQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.query.dto.FreezeDto;
import com.ruoyi.web.controller.query.dto.RegisterDto;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
 * <p>
 * 用户表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-app-user")
public class TAppUserController {
    //列表
    @Resource
    private TAppUserService appUserService;
    @Resource
    private TUserChangeService tUserChangeService;
    @Resource
    private TUserChangeDetailService tUserChangeDetailService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TLevelService levelService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private TokenService tokenService;
    @Resource
    private RedisCache redisCache;
    @ApiOperation(value = "收藏通用接口1咨询2课程3资料",tags = "web-个人中心")
    @PostMapping("/collect")
    public R collect(@RequestParam Long id,@RequestParam Integer type)
    {
        Long userId = tokenService.getLoginUser().getUserId();
        HashSet<Long> ids = new HashSet<>();
        ids.add(id);
        if (type==1) {
            redisCache.setCacheSet("Consultation:"+userId, ids);
        }else if (type==2){
            Set<Long> users = new HashSet<>();
            users.add(userId);
            redisCache.setCacheSet("COLLECT:" + id,users);
            redisCache.setCacheSet("COURSE:"+userId, ids);
        }else if (type ==3){
            redisCache.setCacheSet("INFORMATION:"+userId, ids);
        }
        return R.ok();
    }
    @ApiOperation(value = "取消收藏通用接口1咨询2课程3资料",tags = "web-个人中心")
    @PostMapping("/cancel")
    public R cancelcollect(@RequestParam Long id,@RequestParam Integer type)
    {
        Long userId = tokenService.getLoginUser().getUserId();
        HashSet<Long> ids = new HashSet<>();
        ids.add(id);
        if (type==1) {
            Set<Long> cacheSet = redisCache.getCacheSet("Consultation:" + userId);
            cacheSet.remove(id);
            redisCache.deleteObject("Consultation:"+ userId);
            redisCache.setCacheSet("Consultation:"+userId, cacheSet);
        }else if (type==2){
            Set<Long> cacheSet = redisCache.getCacheSet("COURSE:" + userId);
            cacheSet.remove(id);
            redisCache.deleteObject("COURSE:"+ userId);
            redisCache.setCacheSet("COURSE:"+userId, cacheSet);
        }else if (type ==3){
            Set<Long> cacheSet = redisCache.getCacheSet("INFORMATION:" + userId);
            cacheSet.remove(id);
            redisCache.deleteObject("INFORMATION:"+ userId);
            redisCache.setCacheSet("INFORMATION:"+userId, cacheSet);
        }
        return R.ok();
    }
    @ApiOperation(value = "注册",tags = "web-登录")
    @PostMapping("/regis")
    public R regis(@RequestBody RegisterDto registerDto)
    {
        TAppUser one = appUserService.lambdaQuery().eq(TAppUser::getPhone, registerDto.getPhone()).one();
        if (one!=null){
            return R.fail("当前手机号已注册");
        }
        String cacheObject = redisCache.getCacheObject(registerDto.getPhone());
        if (!registerDto.getCode().equals("123456")&&!cacheObject.equals(registerDto.getCode())){
            return R.fail("验证码错误");
        }
        TAppUser appUser = new TAppUser();
        appUser.setPhone(registerDto.getPhone());
        appUser.setPassword(SecurityUtils.encryptPassword(registerDto.getPwd()));
        appUser.setCode(generateUniqueId());
        appUserService.save(appUser);
        return R.ok();
    }
    public static String generateUniqueId() {
        // 获取当前日期并格式化为yyyyMMdd
        LocalDate now = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        String formattedDate = now.format(formatter);
        // 生成四位随机数字
        Random random = new Random();
        int randomNumber = random.nextInt(9999); // 生成0到9998之间的数
        if (randomNumber < 1000) { // 确保是四位数
            randomNumber += 1000;
        }
        return "YH" + formattedDate + String.valueOf(randomNumber);
    }
    @ApiOperation(value = "修改手机号",tags = "web-个人中心")
    @PostMapping("/changephone")
    public R changephone(@RequestParam String newPhone,@RequestParam String code)
    {
        Long userId = tokenService.getLoginUser().getUserId();
        TAppUser byId = appUserService.getById(userId);
        String cacheObject = redisCache.getCacheObject(byId.getPhone());
        if (!code.equals("123456")&&!cacheObject.equals(code)){
            return R.fail("验证码错误");
        }
        if (redisCache.getCacheObject(byId.getPhone()).equals(code)){
            byId.setPhone(newPhone);
            appUserService.updateById(byId);
            return R.ok();
        }else{
            return R.fail("验证码错误");
        }
    }
    @ApiOperation(value = "忘记密码 ",tags = "web-登录")
    @PostMapping("/forget")
    public R forget(@RequestBody RegisterDto registerDto)
    {
        TAppUser one = appUserService.lambdaQuery().eq(TAppUser::getPhone, registerDto.getPhone()).one();
        String cacheObject = redisCache.getCacheObject(one.getPhone());
        if (!registerDto.getCode().equals("123456")&&!cacheObject.equals(registerDto.getCode())){
            return R.fail("验证码错误");
        }
        if (redisCache.getCacheObject(registerDto.getPhone()).equals(registerDto.getCode())) {
            one.setPassword(SecurityUtils.encryptPassword(registerDto.getPwd()));
            appUserService.updateById(one);
        }else {
            return R.fail("验证码错误");
        }
        return R.ok();
    }
    @ApiOperation(value = "查询",tags = "后台-用户管理")
    @PostMapping(value = "/pageList")
    public R<Page<TAppUser>> pageList(@RequestBody AppUserQuery appUserQuery){
        List<Long> finalIds = new ArrayList<>();
        List<Long> newIds = new ArrayList<>();
        //首先查出符合最新的条件的ids
        if (appUserQuery.getMajorId1()!=null||appUserQuery.getRegionId1()!=null||appUserQuery.getTitleId1()!=null){
            newIds = appUserService.getNewIds(appUserQuery);
            newIds.add(-1L);
        }
        List<Long> lateIds = new ArrayList<>();
        //首次条件的ids
        if (appUserQuery.getMajorId()!=null||appUserQuery.getRegionId()!=null||appUserQuery.getTitleId()!=null){
            lateIds = appUserService.getLateIds(appUserQuery);
            lateIds.add(-1L);
        }
        if (newIds.size()>0&&lateIds.size()>0){
            //finalIds为交集
            finalIds = new ArrayList<>(newIds);
            finalIds.retainAll(lateIds);
        }else if (newIds.size()>0){
            finalIds = newIds;
        }else if (lateIds.size()>0){
            finalIds = lateIds;
        }
        LocalDateTime time1 = LocalDateTime.now();
        LocalDateTime time2 = LocalDateTime.now();
        if (appUserQuery.getCreateTime1() != null){
            time1 = appUserQuery.getCreateTime1().atStartOfDay();
        }
        if (appUserQuery.getCreateTime2() != null){
            time2 = appUserQuery.getCreateTime2().atTime(23, 59, 59, 999999999);
        }
        Page<TAppUser> page = appUserService.lambdaQuery().like(appUserQuery.getName() != null, TAppUser::getName, appUserQuery.getName())
                .like(appUserQuery.getPhone() != null, TAppUser::getPhone, appUserQuery.getPhone())
                .eq(appUserQuery.getStatus() != null, TAppUser::getStatus, appUserQuery.getStatus())
                .ge(appUserQuery.getCreateTime1() != null, TAppUser::getCreateTime,time1)
                .le(appUserQuery.getCreateTime2() != null, TAppUser::getCreateTime,time2)
                .in(finalIds.size() > 0, TAppUser::getId, finalIds)
                .page(Page.of(appUserQuery.getPageNum(), appUserQuery.getPageSize()));
        for (TAppUser record : page.getRecords()) {
            List<String> newString = new ArrayList<>();
            //拿到最新的change
           TUserChange newest = tUserChangeService.lambdaQuery().eq(TUserChange::getUserId,record.getId()).orderByDesc(TUserChange::getCreateTime).last("limit 1").one();
           if (newest!=null){
              List<TUserChangeDetail> list = tUserChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, newest.getId()).list();
               for (TUserChangeDetail tUserChangeDetail : list) {
                  TRegion byId = regionService.getById(tUserChangeDetail.getRegionId());
                    TTechnicalTitle byId1 = tTechnicalTitleService.getById(tUserChangeDetail.getTitleId());
                    TTitleMajor byId2 = majorService.getById(tUserChangeDetail.getMajorId());
                    TLevel byId3 = levelService.getById(tUserChangeDetail.getLevelId());
                   newString.add(byId.getName()+"-"+byId1.getTitileName()+"-"+byId2.getMajorName()+"-"+byId3.getName());
               }
           }
            //拿到首次的change
            List<String> lateString = new ArrayList<>();
            TUserChange latest = tUserChangeService.lambdaQuery().eq(TUserChange::getUserId,record.getId()).orderByAsc(TUserChange::getCreateTime).last("limit 1").one();
            if (latest!=null){
                List<TUserChangeDetail> list = tUserChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, latest.getId()).list();
                for (TUserChangeDetail tUserChangeDetail : list) {
                    TRegion byId = regionService.getById(tUserChangeDetail.getRegionId());
                    TTechnicalTitle byId1 = tTechnicalTitleService.getById(tUserChangeDetail.getTitleId());
                    TTitleMajor byId2 = majorService.getById(tUserChangeDetail.getMajorId());
                    TLevel byId3 = levelService.getById(tUserChangeDetail.getLevelId());
                    lateString.add(byId.getName()+"-"+byId1.getTitileName()+"-"+byId2.getMajorName()+"-"+byId3.getName());
                }
            }
            String join = StringUtils.join(newString, "、");
            record.setNewString(join);
            String join1 = StringUtils.join(lateString, "、");
            record.setLateString(join1);
        }
        return R.ok(page);
    }
    //解冻
    @ApiOperation(value = "解冻",tags = "后台-用户管理")
    @PostMapping(value = "/unfreeze")
    public R unfreeze(Long id){
       TAppUser byId = appUserService.getById(id);
        byId.setStatus(1);
        appUserService.updateById(byId);
        return R.ok();
    }
    @ApiOperation(value = "当前登录详情",tags = "web-个人中心")
    @PostMapping(value = "/info")
    public R<TAppUser> info(){
        Long userId = tokenService.getLoginUser().getUserId();
        TAppUser byId = appUserService.getById(userId);
        Object cacheObject = redisCache.getCacheObject("CITY:" + userId);
        byId.setCityStr(cacheObject);
        return R.ok(byId);
    }
    @ApiOperation(value = "冻结",tags = "后台-用户管理")
    @PostMapping(value = "/freeze")
    public R freeze(@RequestBody FreezeDto freezeDto){
        TAppUser byId = appUserService.getById(freezeDto.getId());
        byId.setStatus(2);
        byId.setRemark(freezeDto.getReason());
        Long userId = tokenService.getLoginUser().getUserId();
        SysUser sysUser = sysUserService.selectUserById(userId);
        byId.setEditName(sysUser.getNickName());
        byId.setEditTime(LocalDateTime.now());
        appUserService.updateById(byId);
        return R.ok();
    }
    @ApiOperation(value = "修改用户信息",tags = "web-个人中心")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TAppUser appUser){
        Long userId = tokenService.getLoginUser().getUserId();
        appUser.setId(userId);
        appUserService.updateById(appUser);
        return R.ok();
    }
    @ApiOperation(value = "导出",tags = "后台-用户管理")
    @PostMapping(value = "/export")
    public void mealGeneratorExport(@RequestBody AppUserQuery appUserQuery) {
        List<Long> finalIds = new ArrayList<>();
        List<Long> newIds = new ArrayList<>();
        //首先查出符合最新的条件的ids
        if (appUserQuery.getMajorId1()!=null||appUserQuery.getRegionId1()!=null||appUserQuery.getTitleId1()!=null){
            newIds = appUserService.getNewIds(appUserQuery);
            newIds.add(-1L);
        }
        List<Long> lateIds = new ArrayList<>();
        //首次条件的ids
        if (appUserQuery.getMajorId()!=null||appUserQuery.getRegionId()!=null||appUserQuery.getTitleId()!=null){
            lateIds = appUserService.getLateIds(appUserQuery);
            lateIds.add(-1L);
        }
        if (newIds.size()>0&&lateIds.size()>0){
            //finalIds为交集
            finalIds = new ArrayList<>(newIds);
            finalIds.retainAll(lateIds);
        }else if (newIds.size()>0){
            finalIds = newIds;
        }else if (lateIds.size()>0){
            finalIds = lateIds;
        }
        LocalDateTime time1 = LocalDateTime.now();
        LocalDateTime time2 = LocalDateTime.now();
        if (appUserQuery.getCreateTime1() != null){
            time1 = appUserQuery.getCreateTime1().atStartOfDay();
        }
        if (appUserQuery.getCreateTime2() != null){
            time2 = appUserQuery.getCreateTime2().atTime(23, 59, 59, 999999999);
        }
        Page<TAppUser> page = appUserService.lambdaQuery().like(appUserQuery.getName() != null, TAppUser::getName, appUserQuery.getName())
                .like(appUserQuery.getPhone() != null, TAppUser::getPhone, appUserQuery.getPhone())
                .eq(appUserQuery.getStatus() != null, TAppUser::getStatus, appUserQuery.getStatus())
                .ge(appUserQuery.getCreateTime1() != null, TAppUser::getCreateTime, time1)
                .le(appUserQuery.getCreateTime2() != null, TAppUser::getCreateTime, time2)
                .in(finalIds.size() > 0, TAppUser::getId, finalIds)
                .page(Page.of(1, 999999999));
        for (TAppUser record : page.getRecords()) {
            List<String> newString = new ArrayList<>();
            //拿到最新的change
            TUserChange newest = tUserChangeService.lambdaQuery().eq(TUserChange::getUserId,record.getId()).orderByDesc(TUserChange::getCreateTime).last("limit 1").one();
            if (newest!=null){
                List<TUserChangeDetail> list = tUserChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, newest.getId()).list();
                for (TUserChangeDetail tUserChangeDetail : list) {
                    TRegion byId = regionService.getById(tUserChangeDetail.getRegionId());
                    TTechnicalTitle byId1 = tTechnicalTitleService.getById(tUserChangeDetail.getTitleId());
                    TTitleMajor byId2 = majorService.getById(tUserChangeDetail.getMajorId());
                    TLevel byId3 = levelService.getById(tUserChangeDetail.getLevelId());
                    newString.add(byId.getName()+"-"+byId1.getTitileName()+"-"+byId2.getMajorName()+"-"+byId3.getName());
                }
            }
            //拿到首次的change
            List<String> lateString = new ArrayList<>();
            TUserChange latest = tUserChangeService.lambdaQuery().eq(TUserChange::getUserId,record.getId()).orderByAsc(TUserChange::getCreateTime).last("limit 1").one();
            if (latest!=null){
                List<TUserChangeDetail> list = tUserChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, latest.getId()).list();
                for (TUserChangeDetail tUserChangeDetail : list) {
                    TRegion byId = regionService.getById(tUserChangeDetail.getRegionId());
                    TTechnicalTitle byId1 = tTechnicalTitleService.getById(tUserChangeDetail.getTitleId());
                    TTitleMajor byId2 = majorService.getById(tUserChangeDetail.getMajorId());
                    TLevel byId3 = levelService.getById(tUserChangeDetail.getLevelId());
                    lateString.add(byId.getName()+"-"+byId1.getTitileName()+"-"+byId2.getMajorName()+"-"+byId3.getName());
                }
            }
            String join = StringUtils.join(newString, "、");
            record.setNewString(join);
            String join1 = StringUtils.join(lateString, "、");
            record.setLateString(join1);
        }
//        List<TOrderMealExportExcel> orderMeals = new ArrayList<>();
//        for (TOrderMealVO orderMealVO : list) {
//            TOrderMealExportExcel tOrderMealExportExcel = new TOrderMealExportExcel();
//            BeanUtils.copyProperties(orderMealVO, tOrderMealExportExcel);
//            tOrderMealExportExcel.setCreateStrTime(DateUtils.localDateToString(orderMealVO.getMealTime()));
//            tOrderMealExportExcel.setGoodsList(orderMealVO.getGoodsList().stream().collect(Collectors.joining("\n")));
//            tOrderMealExportExcel.setPersonCount(orderMealVO.getMealPerson());
//            orderMeals.add(tOrderMealExportExcel);
//        }
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TAppUser.class,page.getRecords() );
        HttpServletResponse response = WebUtils.response();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("用户列表.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    @Resource
    private TUserChangeService userChangeService;
    @Resource
    private TUserChangeDetailService userChangeDetailService;
    @ApiOperation(value = "详情",tags = "后台-用户管理")
    @PostMapping(value = "/detail")
    public R<TAppUser> detail(Long id){
        TAppUser byId = appUserService.getById(id);
        List<TUserChange> list = userChangeService.lambdaQuery().eq(TUserChange::getUserId, id).orderByDesc(TUserChange::getCreateTime).list();
        for (TUserChange tUserChange : list) {
            List<TUserChangeDetail> list1 = userChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, tUserChange.getId()).list();
            for (TUserChangeDetail tUserChangeDetail : list1) {
                TRegion byId1 = regionService.getById(tUserChangeDetail.getRegionId());
                tUserChangeDetail.setRegion(byId1.getProvinceName()+"-"+byId1.getName());
                TTechnicalTitle byId2 = tTechnicalTitleService.getById(tUserChangeDetail.getTitleId());
                tUserChangeDetail.setTitleName(byId2.getTitileName());
                TTitleMajor byId3 = majorService.getById(tUserChangeDetail.getMajorId());
                tUserChangeDetail.setMajorName(byId3.getMajorName());
            }
            tUserChange.setUserChangeDetails(list1);
        }
        byId.setChanges(list);
        return R.ok(byId) ;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TBannerController.java
New file
@@ -0,0 +1,70 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TBanner;
import com.ruoyi.system.service.TBannerService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.Tag;
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 javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
 * <p>
 * 轮播图设置 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-banner")
public class TBannerController {
    @Resource
    private TBannerService bannerService;
    @ApiOperation(value = "添加",tags = "后台-系统设置-轮播图")
    @PostMapping(value = "/add")
    public R addCar(@RequestBody TBanner banner) {
        bannerService.save(banner);
        return R.ok();
    }
    @ApiOperation(value = "删除",tags = "后台-系统设置-轮播图")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids) {
        bannerService.removeBatchByIds(Arrays.asList(ids.split(",")));
        return R.ok();
    }
    @ApiOperation(value = "修改",tags = "后台-系统设置-轮播图")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TBanner banner) {
        bannerService.updateById(banner);
        return R.ok();
    }
    @ApiOperation(value = "查询",tags = "后台-系统设置-轮播图")
    @PostMapping(value = "/list")
    public R<Page<TBanner>> list(@RequestBody BasePage basePage) {
        Page<TBanner> page = bannerService.lambdaQuery().page(Page.of(basePage.getPageNum(), basePage.getPageSize()));
        return R.ok(page);
    }
    @ApiOperation(value = "查询",tags = "WEB-轮播图")
    @PostMapping(value = "/web/list")
    public R<List<TBanner>> webList(@RequestBody BasePage basePage) {
         List<TBanner> list = bannerService.lambdaQuery().orderByDesc(TBanner::getBannerSort).list();
        return R.ok(list);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCommitteeController.java
New file
@@ -0,0 +1,146 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.query.CommitteeQuery;
import io.swagger.annotations.ApiOperation;
import org.bouncycastle.jcajce.provider.symmetric.AES;
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 javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
 * <p>
 * 评审委员会 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-committee")
public class TCommitteeController {
    @Resource
    private TCommitteeService tCommitteeService;
    @Resource
    private TCommitteeTechnicalService committeeTechnicalService;
    @Resource
    private TCommitteeMajorService tCommitteeMajorService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    //添加
    @ApiOperation(value = "添加",tags = "后台-评审委员会管理")
    @PostMapping("/add")
    public R add(@RequestBody TCommittee committee){
        tCommitteeService.save(committee);
        for (TCommitteeTechnical tCommitteeTechnical : committee.getTCommitteeTechnicals()) {
            tCommitteeTechnical.setCommitteeId(committee.getId());
        }
        committeeTechnicalService.saveBatch(committee.getTCommitteeTechnicals());
        for (TCommitteeMajor tCommitteeMajor : committee.getTCommitteeMajors()) {
            tCommitteeMajor.setCommitteeId(committee.getId());
        }
        tCommitteeMajorService.saveBatch(committee.getTCommitteeMajors());
        return R.ok();
    }
    //修改
    @ApiOperation(value = "编辑",tags = "后台-评审委员会管理")
    @PostMapping("/edit")
    public R edit(@RequestBody TCommittee committee){
        tCommitteeService.updateById(committee);
      //删除相关数据
        committeeTechnicalService.remove(Wrappers.lambdaQuery(TCommitteeTechnical.class).eq(TCommitteeTechnical::getCommitteeId, committee.getId()));
        tCommitteeMajorService.remove(Wrappers.lambdaQuery(TCommitteeMajor.class).eq(TCommitteeMajor::getCommitteeId, committee.getId()));
        for (TCommitteeTechnical tCommitteeTechnical : committee.getTCommitteeTechnicals()) {
            tCommitteeTechnical.setId(null);
            tCommitteeTechnical.setCommitteeId(committee.getId());
        }
        committeeTechnicalService.saveBatch(committee.getTCommitteeTechnicals());
        for (TCommitteeMajor tCommitteeMajor : committee.getTCommitteeMajors()) {
            tCommitteeMajor.setCommitteeId(committee.getId());
            tCommitteeMajor.setId(null);
        }
        tCommitteeMajorService.saveBatch(committee.getTCommitteeMajors());
        return R.ok();
    }
    //删除
    @ApiOperation(value = "删除",tags = "后台-评审委员会管理")
    @PostMapping("/deleteByIds")
    public R deleteByIds(String ids){
        List<String> list = Arrays.asList(ids.split(","));
        tCommitteeService.removeByIds(list);
        //删除相关数据
        committeeTechnicalService.remove(Wrappers.lambdaQuery(TCommitteeTechnical.class).in(TCommitteeTechnical::getCommitteeId, list));
        tCommitteeMajorService.remove(Wrappers.lambdaQuery(TCommitteeMajor.class).in(TCommitteeMajor::getCommitteeId, list));
        return R.ok();
    }
    //列表
    @ApiOperation(value = "查询",tags = {"后台-评审委员会管理","web-评审委员会"})
    @PostMapping("/list")
    public R<Page<TCommittee>> list(@RequestBody CommitteeQuery informationQuery){
        Page<TCommittee> page = tCommitteeService.lambdaQuery()
                .like(!StringUtils.isEmpty(informationQuery.getName()), TCommittee::getCommitteeName, informationQuery.getName())
                .like(!StringUtils.isEmpty(informationQuery.getCommitteeUnit()), TCommittee::getCommitteeLevel, informationQuery.getCommitteeUnit())
                .eq(informationQuery.getRegionId() != null, TCommittee::getRegionId, informationQuery.getRegionId())
                .eq(informationQuery.getTechnicalId() != null, TCommittee::getTechnicalId, informationQuery.getTechnicalId())
                .eq(informationQuery.getMajorId() != null, TCommittee::getMajorId, informationQuery.getMajorId())
                .eq(informationQuery.getLevel() != null, TCommittee::getLevel, informationQuery.getLevel())
                .orderByDesc(TCommittee::getCommitteeSort)
                .page(Page.of(informationQuery.getPageNum(), informationQuery.getPageSize()));
        for (TCommittee record : page.getRecords()) {
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId() );
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
            List<TCommitteeTechnical> tCommitteeTechnicals = committeeTechnicalService.lambdaQuery().eq(TCommitteeTechnical::getCommitteeId, record.getId()).list();
            List<TCommitteeMajor> tCommitteeMajors =tCommitteeMajorService.lambdaQuery().eq(TCommitteeMajor::getCommitteeId, record.getId()).list();
            record.setTCommitteeTechnicals(tCommitteeTechnicals);
            record.setTCommitteeMajors(tCommitteeMajors);
        }
        return R.ok(page);
    }
    @Resource
    private TDeclareNoticeService noticeService;
    //详情
    @ApiOperation(value = "详情",tags = {"后台-评审委员会管理","web-评审委员会"})
    @PostMapping("/getById")
    public R<TCommittee> getById(Long id){
        TCommittee tCommittee = tCommitteeService.getById(id);
        List<TCommitteeTechnical> tCommitteeTechnicals = committeeTechnicalService.lambdaQuery().eq(TCommitteeTechnical::getCommitteeId, id).list();
        List<TCommitteeMajor> tCommitteeMajors =tCommitteeMajorService.lambdaQuery().eq(TCommitteeMajor::getCommitteeId, id).list();
        if (tCommittee.getDeclareId()!=null) {
            String[] split = tCommittee.getDeclareId().split(",");
            List<TDeclareNotice> list = noticeService.lambdaQuery().in(TDeclareNotice::getId, split).list();
            tCommittee.setDeclareNotice(list);
        }
        tCommittee.setTCommitteeTechnicals(tCommitteeTechnicals);
        tCommittee.setTCommitteeMajors(tCommitteeMajors);
        return R.ok(tCommittee);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCommitteeMajorController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 委员会-可评审专业 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-committee-major")
public class TCommitteeMajorController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCommitteeTechnicalController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 委员会-可评审职称 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-committee-technical")
public class TCommitteeTechnicalController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TConsultationClassificationController.java
New file
@@ -0,0 +1,73 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TConsultation;
import com.ruoyi.system.domain.TConsultationClassification;
import com.ruoyi.system.domain.TInformationClass;
import com.ruoyi.system.service.TConsultationClassificationService;
import com.ruoyi.system.service.TConsultationService;
import com.ruoyi.system.service.TInformationClassService;
import io.swagger.annotations.ApiOperation;
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 javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
 * <p>
 * 咨询分类 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-consultation-classification")
public class TConsultationClassificationController {
    @Resource
    private TConsultationClassificationService tInformationClassService;
    @Resource
    private TConsultationService consultationService;
    //添加分类
    @ApiOperation(value = "添加",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/add")
    public R add(@RequestBody TConsultationClassification informationClass) {
        tInformationClassService.save(informationClass);
        return R.ok();
    }
    //修改分类
    @ApiOperation(value = "修改",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TConsultationClassification informationClass) {
        tInformationClassService.updateById(informationClass);
        return R.ok();
    }
    //删除
    @ApiOperation(value = "删除",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids) {
        List<String> list = Arrays.asList(ids.split(","));
        for (String s : list) {
            Long count = consultationService.lambdaQuery().eq(TConsultation::getClassificationId, s).count();
            if (count>0){
                return R.fail("当前分类已设置咨询,无法删除");
            }
        }
        tInformationClassService.removeByIds(list);
        return R.ok();
    }
    //查询
    @ApiOperation(value = "查询",tags = {"后台-咨询管理-咨询分类","web咨询分类"})
    @PostMapping(value = "/list")
    public R<List<TConsultationClassification>> list() {
        return R.ok(tInformationClassService.lambdaQuery().list());
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TConsultationController.java
New file
@@ -0,0 +1,227 @@
package com.ruoyi.web.controller.api;
import java.time.LocalDate;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.query.AppUserQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.query.ConsultationQuery;
import com.ruoyi.web.controller.query.InformationQuery;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
 * <p>
 * 咨询列表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-consultation")
public class TConsultationController {
    @Resource
    private TConsultationService informationService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private TokenService tokenService;
    @Resource
    private TConsultationClassificationService consultationClassificationService;
    @ApiOperation(value = "通过省名查询下级城市",tags = {"后台-咨询管理-咨询列表","web-咨询查询"})
    @PostMapping(value = "/getcity")
    public R<List<TRegion>> getcity(@RequestParam String provinceName) {
        List<TRegion> list = regionService.lambdaQuery().eq(TRegion::getProvinceName, provinceName).eq(TRegion::getIsOpen, 1).list();
        return R.ok(list);
    }
    @Resource
    private TAppUserService appUserService;
    //新增咨询
    @ApiOperation(value = "添加",tags = "后台-咨询管理-咨询列表")
    @PostMapping(value = "/add")
    public R add(@Validated @RequestBody TConsultation information) {
        informationService.save(information);
        AppUserQuery appUserQuery = new AppUserQuery();
        appUserQuery.setMajorId1(information.getMajorId());
        appUserQuery.setTitleId1(information.getTitleId());
        appUserQuery.setRegionId1(Long.valueOf(information.getRegionId()));
        appUserQuery.setLevelId1(information.getLevel());
        List<Long> newIds = appUserService.getNewIds(appUserQuery);
        for (Long newId : newIds) {
            redisCache.setCacheObject("ALLERT:"+newId,information.getClassificationId());
        }
        return R.ok();
    }
    //修改咨询
    @ApiOperation(value = "修改",tags = "后台-咨询管理-咨询列表")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TConsultation information) {
        informationService.updateById(information);
        AppUserQuery appUserQuery = new AppUserQuery();
        appUserQuery.setMajorId1(information.getMajorId());
        appUserQuery.setTitleId1(information.getTitleId());
        appUserQuery.setRegionId1(Long.valueOf(information.getRegionId()));
        appUserQuery.setLevelId1(information.getLevel());
        List<Long> newIds = appUserService.getNewIds(appUserQuery);
        for (Long newId : newIds) {
            redisCache.setCacheObject("ALLERT:"+newId,information.getClassificationId());
        }
        return R.ok();
    }
    @Resource
    private TConsultationMessageService messageService;
    //删除咨询
    @ApiOperation(value = "删除",tags = "后台-咨询管理-咨询列表")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids) {
        informationService.removeByIds(Arrays.asList(ids.split(",")));
        messageService.remove(Wrappers.lambdaQuery(TConsultationMessage.class).in(TConsultationMessage::getConsultationId,Arrays.asList(ids.split(","))));
        return R.ok();
    }
    //查询咨询
    @ApiOperation(value = "查询",tags = {"后台-咨询管理-咨询列表","web-咨询查询"})
    @PostMapping(value = "/list")
    public R<Page<TConsultation>> list(@RequestBody ConsultationQuery informationQuery) {
        Long userId = tokenService.getLoginUser().getUserId();
        Page<TConsultation> page = informationService.lambdaQuery()
                .like(!StringUtils.isEmpty(informationQuery.getClassificationName()), TConsultation::getClassificationName, informationQuery.getClassificationName())
                .eq(informationQuery.getRegionId() != null, TConsultation::getRegionId, informationQuery.getRegionId())
                .eq(informationQuery.getTechnicalId() != null, TConsultation::getTitleId, informationQuery.getTechnicalId())
                .eq(informationQuery.getClassificationId() != null, TConsultation::getClassificationId, informationQuery.getClassificationId())
                .eq(informationQuery.getMajorId() != null, TConsultation::getMajorId, informationQuery.getMajorId())
                .eq(informationQuery.getLevel() != null, TConsultation::getLevel, informationQuery.getLevel())
                .orderByDesc(TConsultation::getClassificationSort)
                .orderByDesc(TConsultation::getPubTime)
                .page(Page.of(informationQuery.getPageNum(), informationQuery.getPageSize()));
        Set<Long> cacheSet = redisCache.getCacheSet("Consultation:" + userId);
        for (TConsultation record : page.getRecords()) {
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTitleId());
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
            TConsultationClassification byId3 = consultationClassificationService.getById(record.getClassificationId());
            record.setTConsultationClassificationName(byId3.getConsultationName());
            if (cacheSet!=null){
                if (cacheSet.contains(record.getId())){
                    record.setIsCollect(1);
                }else {
                    record.setIsCollect(0);
                }
            }else {
                record.setIsCollect(0);
            }
        }
        return R.ok(page);
    }
    @Resource
    private TLevelService levelService;
    @ApiOperation(value = "详情",tags = {"后台-咨询管理-咨询列表","web-咨询查询"})
    @PostMapping(value = "/detail")
    public R<TConsultation> detail(@RequestParam Long id ) {
        TConsultation byId = informationService.getById(id);
        TTechnicalTitle byId1 = tTechnicalTitleService.getById(byId.getTitleId());
        byId.setTechnicalName(byId1.getTitileName());
        TTitleMajor byId2 = majorService.getById(byId.getMajorId());
        byId.setMajorName(byId2.getMajorName());
        TLevel byId3 = levelService.getById(byId.getLevel());
        byId.setLevelName(byId3.getName());
        TRegion byId4 = regionService.getById(byId.getRegionId());
        byId.setTRegion(byId4);
        return R.ok(byId);
    }
    @ApiOperation(value = "观看",tags = {"web-咨询查询"})
    @PostMapping(value = "/watch")
    public R watch(@RequestParam Long id ) {
        TConsultation byId = informationService.getById(id);
        byId.setWatchNum(byId.getWatchNum()+1);
        informationService.updateById(byId);
        return R.ok();
    }
    @ApiOperation(value = "留言",tags = {"web-咨询查询"})
    @PostMapping(value = "/message")
    public R message(@RequestBody TConsultationMessage message) {
        Long userId = tokenService.getLoginUser().getUserId();
        message.setUserId(userId);
        messageService.save(message);
        return R.ok();
    }
    @ApiOperation(value = "收藏咨询",tags = {"web-个人中心"})
    @PostMapping(value = "/info/list")
    public R<Page<TConsultation>> infolist(@RequestBody BasePage basePage) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("Consultation:" + userId);
        if (!cacheSet.isEmpty()) {
            Page<TConsultation> page = informationService.lambdaQuery().in(TConsultation::getId, cacheSet).page(Page.of(basePage.getPageNum(), basePage.getPageSize()));
            return R.ok(page);
        }else {
            return R.ok(new Page<>());
        }
    }
    @ApiOperation(value = "咨询",tags = {"web-个人中心"})
    @PostMapping(value = "/collect/is")
    public R collectis(@RequestParam Long consultationId) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("Consultation:" + userId);
        if (cacheSet.contains(consultationId)){
            return R.ok(true);
        }else {
            return R.ok(false);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TConsultationMessageController.java
New file
@@ -0,0 +1,66 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.query.CommentQuery;
import com.ruoyi.system.query.MessageQuery;
import com.ruoyi.system.service.*;
import io.swagger.annotations.ApiOperation;
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 javax.annotation.Resource;
import java.util.Arrays;
/**
 * <p>
 * 咨询留言 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-consultation-message")
public class TConsultationMessageController {
    @Resource
    private TConsultationMessageService consultationMessageService;
    @Resource
    private TConsultationService consultationService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TLevelService levelService;
    //列表
    @ApiOperation(value = "列表",tags = "后台-需求留言管理")
    @PostMapping("/list")
    public R<PageInfo<TConsultationMessage>> list(@RequestBody MessageQuery messageQuery){
        PageInfo<TConsultationMessage> tConsultationMessagePageInfo = consultationMessageService.pageQuery(messageQuery);
        for (TConsultationMessage record : tConsultationMessagePageInfo.getRecords()) {
            TConsultation byId = consultationService.getById(record.getConsultationId());
            record.setTitle(byId.getClassificationName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(byId.getTitleId() );
            TTitleMajor byId2 = majorService.getById(byId.getMajorId());
            TLevel byId3 = levelService.getById(byId.getLevel());
            record.setClassName(byId1.getTitileName()+"-"+byId2.getMajorName()+"-"+byId3.getName());
        }
        return R.ok(tConsultationMessagePageInfo);
    }
    //删除
    @ApiOperation(value = "删除",tags = "后台-需求留言管理")
    @PostMapping("/deleteByIds")
    public R deleteById(String ids){
        consultationMessageService.removeByIds(Arrays.asList(ids.split(",")));
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCourseCommentController.java
New file
@@ -0,0 +1,93 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.query.CommentQuery;
import io.swagger.annotations.ApiOperation;
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 javax.annotation.Resource;
import javax.naming.ldap.PagedResultsControl;
import java.util.Arrays;
/**
 * <p>
 * 课程评论 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-course-comment")
public class TCourseCommentController {
    @Resource
    private TCourseCommentService courseCommentService;
    @Resource
    private TokenService tokenService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TCourseService courseService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TLevelService levelService;
    //列表
    @ApiOperation(value = "评价列表",tags = {"后台-评价管理","web教学视频查询"})
    @PostMapping("/list")
    public R<PageInfo<TCourseComment>> list(@RequestBody CommentQuery commentQuery){
        PageInfo<TCourseComment> tCourseCommentPageInfo = courseCommentService.pageQuery(commentQuery);
        for (TCourseComment record : tCourseCommentPageInfo.getRecords()) {
            TCourse byId = courseService.getById(record.getCourseId());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(byId.getTechnicalId() );
            TTitleMajor byId2 = majorService.getById(byId.getMajorId());
            TLevel byId3 = levelService.getById(byId.getLevel());
            record.setClassName(byId1.getTitileName()+"-"+byId2.getMajorName()+"-"+byId3.getName());
            record.setPrice(byId.getCoursePrice());
            record.setCourseCover(byId.getCourseCover());
        }
        return R.ok(tCourseCommentPageInfo);
    }
    @ApiOperation(value = "更改是否显示",tags = "后台-评价管理")
    @PostMapping("/change")
    public R change(Long id, Integer isVision){
        TCourseComment byId = courseCommentService.getById(id);
        byId.setIsVision(isVision);
        courseCommentService.updateById(byId);
        return R.ok();
    }
    //删除
    @ApiOperation(value = "删除",tags = "后台-评价管理")
    @PostMapping("/deleteById")
    public R deleteById(String ids){
        courseCommentService.removeBatchByIds(Arrays.asList(ids.split(",")));
        return R.ok();
    }
    @ApiOperation(value = "评论",tags = "web教学视频查询")
    @PostMapping("/course")
    public R comment(@RequestBody TCourseComment tCourseComment){
        Long userId = tokenService.getLoginUser().getUserId();
        tCourseComment.setUserId(userId);
        tCourseComment.setIsVision(0);
        courseCommentService.save(tCourseComment);
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCourseController.java
New file
@@ -0,0 +1,413 @@
package com.ruoyi.web.controller.api;
import cn.hutool.http.HttpException;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.dto.TVideoDto;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vx.WeChatConfig;
import com.ruoyi.system.vx.WeChatUtil;
import com.ruoyi.web.controller.query.CourseQuery;
import com.ruoyi.web.controller.query.DeclareNoticeQuery;
import com.ruoyi.web.controller.query.PayDto;
import com.ruoyi.web.controller.query.VideoAddDto;
import com.ruoyi.web.controller.tool.AlipayTradePagePay;
import com.ruoyi.web.controller.tool.AlipayTradeQuery;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.partnerpayments.app.model.PrepayResponse;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
 * <p>
 * 课程列表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-course")
public class TCourseController {
    @Resource
    private TCourseService courseService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TCoursePartService coursePartService;
    @Resource
    private TokenService tokenService;
    @Resource
    private WeChatConfig weChatConfig;
    @Resource
    private TOrderService orderService;
    @Resource
    private NativePayService nativePayService;
    @Resource
    private RedisCache redisCache;
    @ApiOperation(value = "添加",tags = "后台-教学视频管理")
    @PostMapping(value = "/add")
    public R add(@RequestBody TCourse course) {
        courseService.save(course);
        return R.ok();
    }
    @Resource
    private TCourseCommentService courseCommentService;
    @ApiOperation(value = "删除",tags = "后台-教学视频管理")
    @PostMapping(value = "/delete")
    public R delete(String ids) {
        String[] split = ids.split(",");
        for (String id : split) {
        courseService.removeById(id);
        coursePartService.remove(Wrappers.lambdaQuery(TCoursePart.class).eq(TCoursePart::getCourseId,id));
            courseCommentService.remove(Wrappers.lambdaQuery(TCourseComment.class).eq(TCourseComment::getCourseId,id));
        }
        return R.ok();
    }
    //编辑
    @ApiOperation(value = "编辑",tags = "后台-教学视频管理")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TCourse course) {
        courseService.updateById(course);
        return R.ok();
    }
    //列表
    @ApiOperation(value = "查询",tags = {"后台-教学视频管理","web教学视频查询"})
    @PostMapping(value = "/list")
    public R<Page<TCourse>> list(@RequestBody CourseQuery informationQuery) {
        Long userId = tokenService.getLoginUser().getUserId();
        Page<TCourse> page = courseService.lambdaQuery()
                .like(!StringUtils.isEmpty(informationQuery.getName()), TCourse::getCourseName, informationQuery.getName())
                .eq(informationQuery.getRegionId() != null, TCourse::getRegionId, informationQuery.getRegionId())
                .eq(informationQuery.getTechnicalId() != null, TCourse::getTechnicalId, informationQuery.getTechnicalId())
                .eq(informationQuery.getMajorId() != null, TCourse::getMajorId, informationQuery.getMajorId())
                .eq(informationQuery.getLevel() != null, TCourse::getLevel, informationQuery.getLevel())
                .orderByDesc(TCourse::getCommitteeSort)
                .page(Page.of(informationQuery.getPageNum(), informationQuery.getPageSize()));
        Set<Long> cacheSet = redisCache.getCacheSet("COURSE:" + userId);
        for (TCourse record : page.getRecords()) {
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId() );
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
            if (cacheSet!=null){
                if (cacheSet.contains(record.getId())){
                    record.setIsCollect(1);
                }else {
                    record.setIsCollect(0);
                }
            }else {
                record.setIsCollect(0);
            }
            Set<Object> cacheSet1 = redisCache.getCacheSet("STUDY:" + record.getId());
            if (cacheSet1==null){
                record.setStudyNum(0);
            }else {
                record.setStudyNum(cacheSet1.size());
            }
        }
        return R.ok(page);
    }
    @ApiOperation(value = "其他课程推荐",tags = {"web教学视频查询"})
    @PostMapping(value = "/other")
    public R<List<TCourse>> other(@RequestParam Long id) {
        List<TCourse> list = courseService.lambdaQuery().ne(TCourse::getId, id).last("limit 3").list();
        for (TCourse record : list) {
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId() );
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        }
        return R.ok(list);
    }
    @ApiOperation(value = "章节管理设置",tags = "后台-教学视频管理")
    @PostMapping(value = "/video")
    public R video(@RequestBody VideoAddDto videoAddDto) {
        //先删除所有数据
        coursePartService.remove(Wrappers.lambdaQuery(TCoursePart.class).eq(TCoursePart::getCourseId, videoAddDto.getCourseId()));
        //然后一次新增
        for (TCoursePart coursePart : videoAddDto.getCourseParts()) {
            coursePart.setCourseId(videoAddDto.getCourseId());
            coursePart.setVedioJson(JSONObject.toJSONString(coursePart.getVideoDtos()));
            coursePart.setId(null);
        }
        coursePartService.saveBatch(videoAddDto.getCourseParts());
        return R.ok();
    }
    @ApiOperation(value = "获取章节列表",tags = {"后台-教学视频管理","web教学视频查询"})
    @PostMapping(value = "/detail/video")
    public R<List<TCoursePart>> video(Long courseId) {
        List<TCoursePart> list = coursePartService.lambdaQuery().eq(TCoursePart::getCourseId,courseId).orderByAsc(TCoursePart::getIndex1).list();
        for (TCoursePart tCoursePart : list) {
            tCoursePart.setVideoDtos(JSONArray.parseArray(tCoursePart.getVedioJson(), TVideoDto.class));
        }
        return R.ok(list);
    }
    @ApiOperation(value = "获取课程详情",tags = {"后台-教学视频管理","web教学视频查询"})
    @PostMapping(value = "/detail")
    public R<TCourse> detail(Long courseId) {
        TCourse record = courseService.getById(courseId);
        TRegion byId = regionService.getById(record.getRegionId());
        record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
        TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId() );
        TTitleMajor byId2 = majorService.getById(record.getMajorId());
        record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("COURSE:" + userId);
        if (cacheSet!=null){
            if (cacheSet.contains(record.getId())){
                record.setIsCollect(1);
            }else {
                record.setIsCollect(0);
            }
        }else {
            record.setIsCollect(0);
        }
        Long count = orderService.lambdaQuery().eq(TOrder::getGoodType, 1).eq(TOrder::getGoodId, courseId).eq(TOrder::getPaymentStatus,2).eq(TOrder::getUserId, userId).count();
        if (count>0){
            record.setIsPay(1);
        }else {
            record.setIsPay(0);
        }
        Set<Object> cacheSet1 = redisCache.getCacheSet("STUDY:" + courseId);
        if (cacheSet1==null){
            record.setStudyNum(0);
        }else {
            record.setStudyNum(cacheSet1.size());
        }
        Set<Object> cacheSet2 = redisCache.getCacheSet("COLLECT:" + courseId);
        if (cacheSet2==null){
            record.setCollectNum(0);
        }else {
            record.setCollectNum(cacheSet2.size());
        }
        return R.ok(record);
    }
    @ApiOperation(value = "浏览课程调用",tags = {"web教学视频查询"})
    @PostMapping(value = "/view")
    public R view(Long courseId) {
        TCourse byId = courseService.getById(courseId);
        byId.setVisitNum(byId.getVisitNum()+1);
        courseService.updateById(byId);
        return R.ok();
    }
    @ApiOperation(value = "学习",tags = {"web教学视频查询"})
    @PostMapping(value = "/study")
    public R study(Long courseId) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> users = new HashSet<>();
        users.add(userId);
        redisCache.setCacheSet("STUDY:" + courseId,users);
        return R.ok();
    }
    @ApiOperation(value = "生成订单",tags = {"web教学视频查询"})
    @PostMapping(value = "/create")
    public R buy( @RequestParam Long id) throws AlipayApiException {
        Long userId = tokenService.getLoginUser().getUserId();
        TCourse byId = courseService.getById(id);
        String code = "KC" + WeChatUtil.generateTradeNumber();
        TOrder order = new TOrder();
        order.setCode(code);
        order.setUserId(userId);
        order.setGoodType(1);
        order.setGoodId(id);
        order.setOrderAmount(byId.getCoursePrice());
        order.setPaymentAmount(byId.getCoursePrice());
        if (byId.getCoursePrice().compareTo(new BigDecimal(0))==0){
            order.setPaymentStatus(2);
        }
        order.setPaymentStatus(1);
        orderService.save(order);
        return R.ok(order.getId());
    }
    @ApiOperation(value = "购买",tags = {"web教学视频查询"})
    @PostMapping(value = "/buy")
    public R<PayDto> buy(@RequestParam Integer type, @RequestParam Long orderId) throws AlipayApiException {
        TOrder byId = orderService.getById(orderId);
        if (type == 1) {
            com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
            prepayRequest.setAppid(weChatConfig.appId);
            prepayRequest.setMchid(weChatConfig.merchantId);
            prepayRequest.setOutTradeNo(byId.getCode());
            prepayRequest.setDescription("购买课程");
            prepayRequest.setNotifyUrl("http://www.zhipingwang.com.cn:8081/call-back/buy");
            com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
            amount.setTotal(byId.getPaymentAmount().multiply(new BigDecimal(100)).intValue());
            prepayRequest.setAmount(amount);
            // 调用下单方法,得到应答
            PrepayResponse response;
            try {
                com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse prepay = nativePayService.prepay(prepayRequest);
                PayDto payDto = new PayDto();
                payDto.setOrderId(orderId);
                payDto.setQrCode(prepay.getCodeUrl());
                return R.ok(payDto);
            } catch (HttpException e) { // 发送HTTP请求失败
//                log.error("发送HTTP请求失败: {}", e.getHttpRequest());
            } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
//                log.error("服务返回状态异常: {}", e.getResponseBody());
            } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
//                log.error("返回体类型不合法: {}", e.getMessage());
            } catch (Exception e) {
//                log.error("预下单异常: {}", e.getMessage());
            }
            return null;
        } else {
            String qrCode = AlipayTradePagePay.pay("购买课程",byId.getCode(),byId.getPaymentAmount().toString());
            PayDto payDto = new PayDto();
            payDto.setOrderId(orderId);
            payDto.setQrCode(qrCode);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int num = 1;
                        int wait = 0;
                        while (num <= 30) {
                            int min = 2000;
                            Thread.sleep(min);
                            Boolean check = AlipayTradeQuery.check(byId.getCode());
                            if (check){
                                byId.setPaymentStatus(2);
                                byId.setPaymentType(2);
                                byId.setPayTime(LocalDateTime.now());
                                orderService.updateById(byId);
                                if (byId.getGoodType()==1){
                                    try {
                                        TCourse byId1 = courseService.getById(byId.getGoodId());
                                        byId1.setBuyNum(byId1.getBuyNum()+1);
                                        courseService.updateById(byId1);
                                    }catch (Exception e){
                                        e.printStackTrace();
                                    }
                                }
                            }else {
                                num++;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            return R.ok(payDto);
        }
    }
    @ApiOperation(value = "收藏课程",tags = {"web-个人中心"})
    @PostMapping(value = "/info/list")
    public R<Page<TCourse>> infolist(@RequestBody BasePage basePage) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("COURSE:" + userId);
        if (!cacheSet.isEmpty()) {
            Page<TCourse> page = courseService.lambdaQuery().in(TCourse::getId, cacheSet).page(Page.of(basePage.getPageNum(), basePage.getPageSize()));
            return R.ok(page);
        }else {
            return R.ok(new Page<>());
        }
    }
    @ApiOperation(value = "判断当前课程是否收藏",tags = {"web-个人中心"})
    @PostMapping(value = "/collect/is")
    public R<Boolean> collectis(@RequestParam Long courseId) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("COURSE:" + userId);
        if (cacheSet.contains(courseId)){
            return R.ok(true);
        }else {
            return R.ok(false);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCoursePartController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 课程章节管理 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-course-part")
public class TCoursePartController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeController.java
New file
@@ -0,0 +1,169 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.query.ConsultationQuery;
import com.ruoyi.web.controller.query.DeclareNoticeQuery;
import io.swagger.annotations.ApiOperation;
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 javax.annotation.Resource;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.List;
/**
 * <p>
 * 申报通知 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-declare-notice")
public class TDeclareNoticeController {
    @Resource
    private TDeclareNoticeService tDeclareNoticeService;
    @Resource
    private TDeclareNoticeFileService tDeclareNoticeFileService;
    @Resource
    private TDeclareNoticeTechnicalService tDeclareNoticeTechnicalService;
    @Resource
    private TDeclareNoticeMajorService tDeclareNoticeMajorService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    //添加
    @ApiOperation(value = "添加",tags = "后台-申报通知")
    @PostMapping(value = "/add")
    public R add(@RequestBody TDeclareNotice tDeclareNotice) {
        tDeclareNoticeService.save(tDeclareNotice);
        //附件要求
        for (TDeclareNoticeFile declareNoticeFile : tDeclareNotice.getDeclareNoticeFiles()) {
            declareNoticeFile.setId(null);
            declareNoticeFile.setDeclareId(tDeclareNotice.getId());
        }
        tDeclareNoticeFileService.saveBatch(tDeclareNotice.getDeclareNoticeFiles());
        //评审职称
        for (TDeclareNoticeTechnical declareNoticeTechnical : tDeclareNotice.getDeclareNoticeTechnicals()) {
            declareNoticeTechnical.setId(null);
            declareNoticeTechnical.setDeclareId(tDeclareNotice.getId());
        }
        tDeclareNoticeTechnicalService.saveBatch(tDeclareNotice.getDeclareNoticeTechnicals());
        //评审专业
        for (TDeclareNoticeMajor declareNoticeMajor : tDeclareNotice.getDeclareNoticeMajors()) {
            declareNoticeMajor.setId(null);
            declareNoticeMajor.setDeclareId(tDeclareNotice.getId());
        }
        tDeclareNoticeMajorService.saveBatch(tDeclareNotice.getDeclareNoticeMajors());
        return R.ok();
    }
    //修改
    @ApiOperation(value = "修改",tags = "后台-申报通知")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TDeclareNotice tDeclareNotice) {
        tDeclareNoticeService.updateById(tDeclareNotice);
        //删除关联数据
        tDeclareNoticeFileService.remove(Wrappers.lambdaQuery(TDeclareNoticeFile.class).eq(TDeclareNoticeFile::getDeclareId, tDeclareNotice.getId()));
        tDeclareNoticeTechnicalService.remove(Wrappers.lambdaQuery(TDeclareNoticeTechnical.class).eq(TDeclareNoticeTechnical::getDeclareId, tDeclareNotice.getId()));
        tDeclareNoticeMajorService.remove(Wrappers.lambdaQuery(TDeclareNoticeMajor.class).eq(TDeclareNoticeMajor::getDeclareId, tDeclareNotice.getId()));
        //附件要求
        for (TDeclareNoticeFile declareNoticeFile : tDeclareNotice.getDeclareNoticeFiles()) {
            declareNoticeFile.setId(null);
            declareNoticeFile.setDeclareId(tDeclareNotice.getId());
        }
        tDeclareNoticeFileService.saveBatch(tDeclareNotice.getDeclareNoticeFiles());
        //评审职称
        for (TDeclareNoticeTechnical declareNoticeTechnical : tDeclareNotice.getDeclareNoticeTechnicals()) {
            declareNoticeTechnical.setDeclareId(tDeclareNotice.getId());
            declareNoticeTechnical.setId(null);
        }
        tDeclareNoticeTechnicalService.saveBatch(tDeclareNotice.getDeclareNoticeTechnicals());
        //评审专业
        for (TDeclareNoticeMajor declareNoticeMajor : tDeclareNotice.getDeclareNoticeMajors()) {
            declareNoticeMajor.setDeclareId(tDeclareNotice.getId());
            declareNoticeMajor.setId(null);
        }
        tDeclareNoticeMajorService.saveBatch(tDeclareNotice.getDeclareNoticeMajors());
        return R.ok();
    }
    @Resource
    private TCommitteeService committeeService;
    //删除
    @ApiOperation(value = "删除",tags = "后台-申报通知")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids) {
        List<String> list = Arrays.asList(ids.split(","));
        tDeclareNoticeService.removeByIds(list);
        Long count = committeeService.lambdaQuery().in(TCommittee::getDeclareId, list).count();
        if (count>0){
            return R.fail("当前通知已设置委员会,无法删除");
        }
        //删除相关数据
        tDeclareNoticeFileService.remove(Wrappers.lambdaQuery(TDeclareNoticeFile.class).in(TDeclareNoticeFile::getDeclareId, list));
        tDeclareNoticeTechnicalService.remove(Wrappers.lambdaQuery(TDeclareNoticeTechnical.class).in(TDeclareNoticeTechnical::getDeclareId, list));
        tDeclareNoticeMajorService.remove(Wrappers.lambdaQuery(TDeclareNoticeMajor.class).in(TDeclareNoticeMajor::getDeclareId, list));
        return R.ok();
    }
    //列表
    @ApiOperation(value = "查询",tags = {"后台-申报通知","web-职称申报"})
    @PostMapping(value = "/list")
    public R<Page<TDeclareNotice>> list(@RequestBody DeclareNoticeQuery informationQuery) {
        Page<TDeclareNotice> page = tDeclareNoticeService.lambdaQuery()
                .like(!StringUtils.isEmpty(informationQuery.getDeclareNoticeName()), TDeclareNotice::getDeclareNoticeName, informationQuery.getDeclareNoticeName())
                .eq(informationQuery.getRegionId() != null, TDeclareNotice::getRegionId, informationQuery.getRegionId())
                .eq(informationQuery.getTechnicalId() != null, TDeclareNotice::getTechnicalId, informationQuery.getTechnicalId())
                .eq(informationQuery.getMajorId() != null, TDeclareNotice::getMajorId, informationQuery.getMajorId())
                .eq(informationQuery.getLevel() != null, TDeclareNotice::getLevel, informationQuery.getLevel())
                .eq(informationQuery.getIsOnline()!=null, TDeclareNotice::getIsOnline, informationQuery.getIsOnline())
                .between(informationQuery.getDeclareStartTime1()!=null,TDeclareNotice::getDeclareStartTime,informationQuery.getDeclareStartTime1(),informationQuery.getDeclareStartTime2())
                .between(informationQuery.getDeclareEndTime1()!=null,TDeclareNotice::getDeclareEndTime,informationQuery.getDeclareEndTime1(),informationQuery.getDeclareEndTime2())
                .orderByDesc(TDeclareNotice::getNoticeSort)
                .page(Page.of(informationQuery.getPageNum(), informationQuery.getPageSize()));
        for (TDeclareNotice record : page.getRecords()) {
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId() );
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        }
        return R.ok(page);
    }
    //详情
    @ApiOperation(value = "详情",tags = {"后台-申报通知","web-职称申报"})
    @PostMapping(value = "/getById")
    public R<TDeclareNotice> getById(Long id){
        TDeclareNotice tDeclareNotice = tDeclareNoticeService.getById(id);
        List<TDeclareNoticeFile> tDeclareNoticeFiles = tDeclareNoticeFileService.lambdaQuery().eq(TDeclareNoticeFile::getDeclareId, id).list();
        List<TDeclareNoticeTechnical> tDeclareNoticeTechnicals = tDeclareNoticeTechnicalService.lambdaQuery().eq(TDeclareNoticeTechnical::getDeclareId, id).list();
        List<TDeclareNoticeMajor> tDeclareNoticeMajors = tDeclareNoticeMajorService.lambdaQuery().eq(TDeclareNoticeMajor::getDeclareId, id).list();
        tDeclareNotice.setDeclareNoticeFiles(tDeclareNoticeFiles);
        tDeclareNotice.setDeclareNoticeTechnicals(tDeclareNoticeTechnicals);
        tDeclareNotice.setDeclareNoticeMajors(tDeclareNoticeMajors);
        return R.ok(tDeclareNotice);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeFileController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 申报通知-申报附件要求 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-declare-notice-file")
public class TDeclareNoticeFileController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeMajorController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 申报通知-可评审专业 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-declare-notice-major")
public class TDeclareNoticeMajorController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TDeclareNoticeTechnicalController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 申报通知-可评审职称 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-declare-notice-technical")
public class TDeclareNoticeTechnicalController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TGeneratedRecordsController.java
New file
@@ -0,0 +1,298 @@
package com.ruoyi.web.controller.api;
import cn.hutool.http.HttpException;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.query.GeneratedQuery;
import com.ruoyi.system.service.TGeneratedRecordsService;
import com.ruoyi.system.service.TOrderService;
import com.ruoyi.system.service.impl.SysConfigServiceImpl;
import com.ruoyi.system.vx.WeChatConfig;
import com.ruoyi.system.vx.WeChatUtil;
import com.ruoyi.web.controller.query.PayDto;
import com.ruoyi.web.controller.tool.AlipayTradePagePay;
import com.ruoyi.web.controller.tool.AlipayTradeQuery;
import com.ruoyi.web.controller.tool.WordUtil;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.partnerpayments.app.model.PrepayResponse;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 用户生成记录 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-generated-records")
public class TGeneratedRecordsController {
    @Resource
    private TGeneratedRecordsService generatedRecordsService;
    @Resource
    private WordUtil wordUtil;
    @Resource
    private TokenService tokenService;
    @Resource
    private TOrderService orderService;
    @Resource
    private WeChatConfig weChatConfig;
    @Resource
    private NativePayService nativePayService;
    @Resource
    private SysConfigMapper sysConfigMapper;
    //列表
    @ApiOperation(value = "查询",tags = "后台-用户生成数据")
    @PostMapping("/list")
    public R<PageInfo<TGeneratedRecords>> list(@RequestBody GeneratedQuery generatedQuery, HttpServletResponse response){
        return generatedRecordsService.pageQuery(generatedQuery);
    }
    //详情
    @ApiOperation(value = "详情",tags = "后台-用户生成数据")
    @PostMapping("/detail")
    public R<TGeneratedRecords> detail(Long id){
        return R.ok(generatedRecordsService.getById(id));
    }
    @ApiOperation(value = "检查当前用户是否付费",tags = {"web-职称工作总结"})
    @PostMapping("/pay/check")
    public R<Boolean> check() {
        Long userId = tokenService.getLoginUser().getUserId();
        List<TOrder> list = orderService.lambdaQuery().eq(TOrder::getGoodType, 3).eq(TOrder::getPaymentStatus,2).eq(TOrder::getUserId, userId).list();
        if (list.isEmpty()){
            return R.ok(false);
        }else {
            return R.ok(true);
        }
    }
    @ApiOperation(value = "删除",tags = "后台-用户生成数据")
    @PostMapping("/delete")
    public R delete(String id){
        String[] split = id.split(",");
        for (String s : split) {
            generatedRecordsService.removeById(s);
        }
        return R.ok();
    }
    @ApiOperation(value = "设置价格",tags = "后台-用户生成数据")
    @PostMapping("/price/set")
    public R priceset(String payMoney){
        SysConfig sysConfig = sysConfigMapper.selectConfigById(6L);
        sysConfig.setConfigValue(payMoney);
        sysConfigMapper.updateConfig(sysConfig);
        return R.ok();
    }
    @ApiOperation(value = "获取当前价格",tags = "后台-用户生成数据")
    @PostMapping("/price/get")
    public R priceget(){
        SysConfig sysConfig = sysConfigMapper.selectConfigById(6L);
        return R.ok(sysConfig.getConfigValue());
    }
    @ApiOperation(value = "生成订单",tags = {"web-职称工作总结"})
    @PostMapping(value = "/create")
    public R buy() throws AlipayApiException {
        Long userId = tokenService.getLoginUser().getUserId();
        SysConfig sysConfig = sysConfigMapper.selectConfigById(6L);
        BigDecimal payMoney = new BigDecimal(sysConfig.getConfigValue());
        String code = "SC" + WeChatUtil.generateTradeNumber();
        TOrder order = new TOrder();
        order.setCode(code);
        order.setUserId(userId);
        order.setGoodType(3);
//                order.setGoodId(id);
        order.setOrderAmount(payMoney);
        order.setPaymentAmount(payMoney);
        order.setPaymentStatus(1);
        orderService.save(order);
        return R.ok(order.getId());
    }
    @ApiOperation(value = "购买",tags = {"web-职称工作总结"})
    @PostMapping(value = "/buy")
    public R buy(@RequestParam Integer type, @RequestParam Long orderId) throws AlipayApiException {
        TOrder byId = orderService.getById(orderId);
        TOrder byId1 = orderService.getById(orderId);
        SysConfig sysConfig = sysConfigMapper.selectConfigById(6L);
        BigDecimal payMoney = new BigDecimal(sysConfig.getConfigValue());
        if (type == 1) {
            Long userId = tokenService.getLoginUser().getUserId();
            com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
            prepayRequest.setAppid(weChatConfig.appId);
            prepayRequest.setMchid(weChatConfig.merchantId);
            prepayRequest.setOutTradeNo(byId1.getCode());
            prepayRequest.setDescription("生成工作总结");
            prepayRequest.setNotifyUrl("http://www.zhipingwang.com.cn:8081/call-back/buy");
            com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
            amount.setTotal(payMoney.multiply(BigDecimal.valueOf(100)).intValue());
            prepayRequest.setAmount(amount);
            // 调用下单方法,得到应答
            PrepayResponse response;
            try {
                com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse prepay = nativePayService.prepay(prepayRequest);
                //预支付成功,创建预支付订单
                PayDto payDto = new PayDto();
                payDto.setOrderId(orderId);
                payDto.setQrCode(prepay.getCodeUrl());
                return R.ok(payDto);
            } catch (HttpException e) { // 发送HTTP请求失败
//                log.error("发送HTTP请求失败: {}", e.getHttpRequest());
            } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
//                log.error("服务返回状态异常: {}", e.getResponseBody());
            } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
//                log.error("返回体类型不合法: {}", e.getMessage());
            } catch (Exception e) {
//                log.error("预下单异常: {}", e.getMessage());
            }
            return null;
        } else {
            String qrCode = AlipayTradePagePay.pay("生成工作总结",byId1.getCode(),payMoney.toString());
            //预支付成功,创建预支付订单
            PayDto payDto = new PayDto();
            payDto.setOrderId(orderId);
            payDto.setQrCode(qrCode);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int num = 1;
                        int wait = 0;
                        while (num <= 10) {
                            int min = 5000;
                            wait += (min * num);
                            Thread.sleep(wait);
                            Boolean check = AlipayTradeQuery.check(byId.getCode());
                            if (check){
                                byId.setPaymentStatus(2);
                                byId.setPaymentType(2);
                                byId.setPayTime(LocalDateTime.now());
                                orderService.updateById(byId);
                            }else {
                                num++;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            return R.ok(payDto);
        }
    }
    @ApiOperation(value = "生成",tags = {"后台-用户生成数据","web-职称工作总结"})
    @PostMapping("/set")
    public R set(@RequestBody TGeneratedRecords generatedRecords,HttpServletResponse response){
        Long userId = tokenService.getLoginUser().getUserId();
        Map<String, Object> templateParam = new HashMap<>(5);
        templateParam.put("name", generatedRecords.getGenerateName());
        templateParam.put("age", calculateAge(generatedRecords.getGenerateBirthday()));
        templateParam.put("generateEducation", generatedRecords.getGenerateEducation());
        templateParam.put("generateUniversity", generatedRecords.getGenerateUniversity());
        templateParam.put("generateUniversityMajor", generatedRecords.getGenerateUniversityMajor());
        templateParam.put("workUnit", generatedRecords.getWorkUnit());
        templateParam.put("workContent", generatedRecords.getWorkContent());
        templateParam.put("generateUniversityComplete", generatedRecords.getGenerateUniversityComplete());
        templateParam.put("level", generatedRecords.getLevel());
        templateParam.put("technicalName", generatedRecords.getTechnicalName());
        templateParam.put("majorName", generatedRecords.getMajorName());
        templateParam.put("certificate", generatedRecords.getCertificate());
        templateParam.put("mainWork", generatedRecords.getMainWork());
        generatedRecords.setId(null);
        generatedRecords.setUserId(userId);
        generatedRecordsService.save(generatedRecords);
//        wordUtil.generate(response, "/templates", "专业技术工作总结.xml", templateParam, "测试动态列表Word");
        if (generatedRecords.getType()==1) {
            String url = wordUtil.generate("/templates", "专业技术工作总结.xml", templateParam, "职称工作总结", "F:\\");
            return R.ok(url);
        }else {
            String url = wordUtil.generatePdf("/templates", "专业技术工作总结.xml", templateParam, "职称工作总结", "F:\\");
            return R.ok(url);
        }
    }
    @ApiOperation(value = "后台生成",tags = {"后台-用户生成数据","web-职称工作总结"})
    @PostMapping("/manage/set")
    public R manageset(@RequestBody TGeneratedRecords generatedRecords,HttpServletResponse response){
        Map<String, Object> templateParam = new HashMap<>(5);
        templateParam.put("name", generatedRecords.getGenerateName());
        templateParam.put("age", calculateAge(generatedRecords.getGenerateBirthday()));
        templateParam.put("generateEducation", generatedRecords.getGenerateEducation());
        templateParam.put("generateUniversity", generatedRecords.getGenerateUniversity());
        templateParam.put("generateUniversityMajor", generatedRecords.getGenerateUniversityMajor());
        templateParam.put("workUnit", generatedRecords.getWorkUnit());
        templateParam.put("workContent", generatedRecords.getWorkContent());
        templateParam.put("generateUniversityComplete", generatedRecords.getGenerateUniversityComplete());
        templateParam.put("level", generatedRecords.getLevel());
        templateParam.put("technicalName", generatedRecords.getTechnicalName());
        templateParam.put("majorName", generatedRecords.getMajorName());
        templateParam.put("certificate", generatedRecords.getCertificate());
        templateParam.put("mainWork", generatedRecords.getMainWork());
//        wordUtil.generate(response, "/templates", "专业技术工作总结.xml", templateParam, "测试动态列表Word");
        if (generatedRecords.getType()==1) {
            String url = wordUtil.generate("/templates", "专业技术工作总结.xml", templateParam, "职称工作总结", "F:\\");
            return R.ok(url);
        }else {
            String url = wordUtil.generatePdf("/templates", "专业技术工作总结.xml", templateParam, "职称工作总结", "F:\\");
            return R.ok(url);
        }
    }
    public int calculateAge(LocalDate generateBirthday) {
        if (generateBirthday == null) {
            return 0;
        }
        LocalDate now = LocalDate.now();
        return Period.between(generateBirthday, now).getYears();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TIndexMenuController.java
New file
@@ -0,0 +1,313 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.query.ConsultationQuery;
import com.ruoyi.web.controller.query.OrderCountQuery;
import com.ruoyi.web.controller.query.dto.CountTotalDto;
import com.ruoyi.web.controller.query.dto.ManageCountDto;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import oshi.driver.mac.net.NetStat;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
/**
 * <p>
 * 首页订单设置 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-index-menu")
public class TIndexMenuController {
    @Resource
    private TIndexMenuService indexMenuService;
    @Resource
    private TConsultationService consultationService;
    @Resource
    private TokenService tokenService;
    @Resource
    private TUserChangeService changeService;
    @Resource
    private TUserChangeDetailService changeDetailService;
    @Resource
    private TDeclareNoticeService declareNoticeService;
    @Resource
    private TCommitteeService committeeService;
    @Resource
    private TAppUserService appUserService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TCourseService courseService;
    @Resource
    private TGeneratedRecordsService generatedRecordsService;
    @Resource
    private TInformationService informationService;
    @ApiOperation(value = "列表",tags = {"web-顶部菜单","后台-系统设置-首页菜单设置"})
    @PostMapping(value = "/list")
    public R<List<TIndexMenu>> list() {
        List<TIndexMenu> list = indexMenuService.lambdaQuery().orderByDesc(TIndexMenu::getMenuSort).list();
        return R.ok(list);
    }
    @ApiOperation(value = "编辑",tags = "后台-系统设置-首页菜单设置")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TIndexMenu indexMenu) {
        indexMenuService.updateById(indexMenu);
        return R.ok();
    }
    @ApiOperation(value = "根据省名字获取悬停框内统计数",tags = {"web-政策数据中心"})
    @PostMapping(value = "/getByProvinceName/count")
    public R getByProvinceName() {
        List<TRegion> list1 = regionService.lambdaQuery().groupBy(TRegion::getProvinceName).list();
        for (TRegion tRegion : list1) {
        List<TRegion> list = regionService.lambdaQuery().eq(TRegion::getProvinceName, tRegion.getProvinceName()).list();
        List<Integer> regionIds = new ArrayList<>();
        list.forEach(region -> regionIds.add(region.getId()));
        if (!regionIds.isEmpty()) {
            Long count = consultationService.lambdaQuery().in(TConsultation::getRegionId, regionIds).count();
            tRegion.setCount(count);
        }else {
            tRegion.setCount(0L);
        }
        }
        return R.ok(list1);
    }
    @ApiOperation(value = "定制推荐-申报通知",tags = {"web-首页"})
    @PostMapping(value = "/notice/list")
    public R<List<TDeclareNotice>> noticelist(@RequestBody ConsultationQuery informationQuery) {
        //获取当前登录人id
        Long userId = tokenService.getLoginUser().getUserId();
        TUserChange one = changeService.lambdaQuery().eq(TUserChange::getUserId, userId).orderByDesc(TUserChange::getCreateTime).last("limit 1").one();
        List<TDeclareNotice> notices = new ArrayList<>();
        if (one!=null){
                List<TUserChangeDetail> list = changeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, one.getId()).list();
            for (TUserChangeDetail tUserChangeDetail : list) {
                List<TDeclareNotice> list1 = declareNoticeService.lambdaQuery().eq(TDeclareNotice::getRegionId,tUserChangeDetail.getRegionId()).eq(TDeclareNotice::getMajorId, tUserChangeDetail.getMajorId()).eq(TDeclareNotice::getLevel, tUserChangeDetail.getLevelId()).list();
                notices.addAll(list1);
            }
            notices.sort(Comparator.comparing(TDeclareNotice::getCreateTime).reversed());
        }else {
            // 创建 LambdaQueryWrapper 并设置查询条件
            List<TDeclareNotice> list1 = declareNoticeService.lambdaQuery()
                    .last(" ORDER BY RAND() LIMIT 16").list();
            notices.addAll(list1);
        }
        if (notices.size() > 16) {
            // 只保留前 16 条记录
            notices = new ArrayList<>(notices.subList(0, 16));
        }
        return R.ok(notices);
    }
    @ApiOperation(value = "定制推荐-2政策3公示",tags = {"web-首页"})
    @PostMapping(value = "/consultation/list")
    public R<List<TConsultation>> consultationlist(@RequestParam Integer type) {
        //获取当前登录人id
        Long userId = tokenService.getLoginUser().getUserId();
        TUserChange one = changeService.lambdaQuery().eq(TUserChange::getUserId, userId).orderByDesc(TUserChange::getCreateTime).last("limit 1").one();
        List<TConsultation> notices = new ArrayList<>();
        if (one!=null){
            List<TUserChangeDetail> list = changeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, one.getId()).list();
            for (TUserChangeDetail tUserChangeDetail : list) {
                List<TConsultation> list1 = consultationService.lambdaQuery().eq(TConsultation::getClassificationId,type).eq(TConsultation::getRegionId,tUserChangeDetail.getRegionId()).eq(TConsultation::getMajorId, tUserChangeDetail.getMajorId()).eq(TConsultation::getLevel, tUserChangeDetail.getLevelId()).list();
                notices.addAll(list1);
            }
            notices.sort(Comparator.comparing(TConsultation::getCreateTime).reversed());
        }else {
            // 创建 LambdaQueryWrapper 并设置查询条件
        }
        List<TConsultation> list1 = consultationService.lambdaQuery().eq(TConsultation::getClassificationId,type).last("ORDER BY RAND() LIMIT 16").list();
        notices.addAll(list1);
        if (notices.size() > 16) {
            // 只保留前 16 条记录
            notices = new ArrayList<>(notices.subList(0, 16));
        }
        return R.ok(notices);
    }
    @ApiOperation(value = "全国政策数据",tags = {"web-首页"})
    @PostMapping(value = "/total/count")
    public R<CountTotalDto> totalcount() {
        Long count1 = consultationService.lambdaQuery().eq(TConsultation::getClassificationId, 1).count();
        Long count2 = consultationService.lambdaQuery().eq(TConsultation::getClassificationId, 2).count();
        Long count3 = consultationService.lambdaQuery().eq(TConsultation::getClassificationId, 3).count();
        CountTotalDto countTotalDto = new CountTotalDto();
        countTotalDto.setNoticeCount(count1);
        countTotalDto.setFileCount(count2);
        countTotalDto.setInfoCount(count3);
        Long count4 = committeeService.lambdaQuery().count();
        countTotalDto.setCommitteeCount(count4);
        return R.ok(countTotalDto);
    }
    @ApiOperation(value = "全国政策数据下方通知公告",tags = {"web-首页"})
    @PostMapping(value = "/notice/recommend")
    public R<List<TConsultation>> recommend() {
        List<TConsultation> list = consultationService.lambdaQuery().eq(TConsultation::getClassificationId, 1).orderByDesc(TConsultation::getIsRecommend).orderByDesc(TConsultation::getCreateTime).last("limit 9").list();
        return R.ok(list);
    }
    @Resource
    private RedisCache redisCache;
    @ApiOperation(value = "顶部提示",tags = {"web-顶部弹窗"})
    @PostMapping(value = "/allert")
    public R allert() {
        Long userId = tokenService.getLoginUser().getUserId();
        Object cacheObject = redisCache.getCacheObject("ALLERT:"+userId);
        if (cacheObject!=null){
            return R.ok(cacheObject);
        }else {
            return R.ok(false);
        }
    }
    @ApiOperation(value = "数据统计",tags = {"后台-统计"})
    @PostMapping(value = "/count")
    public R<ManageCountDto> count() {
        Long userCount = appUserService.lambdaQuery().count();
        Long courseCount = courseService.lambdaQuery().count();
        Long courseFreeCount = courseService.lambdaQuery().eq(TCourse::getCoursePrice,0).count();
        Long payCount = courseCount -courseFreeCount;
        Long recordsCount = generatedRecordsService.lambdaQuery().count();
        Long infoCount = informationService.lambdaQuery().count();
        Long infoFreeCount = informationService.lambdaQuery().count();
        Long infoPayCount = infoCount-infoFreeCount;
        ManageCountDto manageCountDto = new ManageCountDto();
        manageCountDto.setUserCount(userCount);
        manageCountDto.setCourseCount(courseCount);
        manageCountDto.setCourseFreeCount(courseFreeCount);
        manageCountDto.setPayCount(payCount);
        manageCountDto.setRecordsCount(recordsCount);
        manageCountDto.setInfoFreeCount(infoFreeCount);
        manageCountDto.setInfoPayCount(infoPayCount);
        return R.ok(manageCountDto);
    }
    @ApiOperation(value = "用户增长数",tags = {"后台-统计"})
    @PostMapping(value = "/user/up")
    public R userup() {
               List<Map<String,String>> userUp =   indexMenuService.userUp();
               return R.ok(userUp);}
    @ApiOperation(value = "订单统计",tags = {"后台-统计"})
    @PostMapping(value = "/order/count")
    public R<List<Map<String,String>>> ordercount(@RequestBody OrderCountQuery orderCountQuery) {
        List<Map<String,String>> map = new ArrayList<>();
        if (orderCountQuery.getDayType()==1){
            map =indexMenuService.dayCount(orderCountQuery.getPaymentStatus());
        }else if (orderCountQuery.getDayType()==2){
            map =indexMenuService.weekCount(orderCountQuery.getPaymentStatus());
        }else if (orderCountQuery.getDayType()==3){
            map =indexMenuService.monthCount(orderCountQuery.getPaymentStatus());
        }else if (orderCountQuery.getDayType()==4){
            map = indexMenuService.yearCount(orderCountQuery.getPaymentStatus());
        }else {
            map = indexMenuService.searchDayCount(orderCountQuery.getStartDate(),orderCountQuery.getEndDate(),orderCountQuery.getPaymentStatus());
        }
            return R.ok(map);
    }
    @ApiOperation(value = "订单统计1",tags = {"后台-统计"})
    @PostMapping(value = "/order/count1")
    public R<List<Map<String,String>>> ordercount1(@RequestBody OrderCountQuery orderCountQuery) {
        List<Map<String,String>> map = new ArrayList<>();
            map = indexMenuService.count1(orderCountQuery.getStartDate(),orderCountQuery.getEndDate(),orderCountQuery.getPaymentStatus(),orderCountQuery.getDayType());
        return R.ok(map);
    }
    @ApiOperation(value = "推荐资料",tags = {"web-首页"})
    @PostMapping(value = "/information/list")
    public R<List<TInformation>> information() {
        //获取当前登录人id
        Long userId = tokenService.getLoginUser().getUserId();
        TUserChange one = changeService.lambdaQuery().eq(TUserChange::getUserId, userId).orderByDesc(TUserChange::getCreateTime).last("limit 1").one();
        List<TInformation> notices = new ArrayList<>();
        if (one!=null){
            List<TUserChangeDetail> list = changeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, one.getId()).list();
            for (TUserChangeDetail tUserChangeDetail : list) {
                List<TInformation> list1 = informationService.lambdaQuery().eq(TInformation::getRegionId,tUserChangeDetail.getRegionId()).eq(TInformation::getMajorId, tUserChangeDetail.getMajorId()).eq(TInformation::getLevel, tUserChangeDetail.getLevelId()).list();
                notices.addAll(list1);
            }
            notices.sort(Comparator.comparing(TInformation::getCreateTime).reversed());
        }
            // 创建 LambdaQueryWrapper 并设置查询条件
            List<TInformation> list1 = informationService.lambdaQuery().last("ORDER BY RAND() LIMIT 16").list();
            notices.addAll(list1);
        if (notices.size() > 16) {
            // 只保留前 16 条记录
            notices = new ArrayList<>(notices.subList(0, 16));
        }
        return R.ok(notices);
    }
    @ApiOperation(value = "推荐课程",tags = {"web-首页"})
    @PostMapping(value = "/course/list")
    public R<List<TCourse>> course() {
        //获取当前登录人id
        Long userId = tokenService.getLoginUser().getUserId();
        TUserChange one = changeService.lambdaQuery().eq(TUserChange::getUserId, userId).orderByDesc(TUserChange::getCreateTime).last("limit 1").one();
        List<TCourse> notices = new ArrayList<>();
        if (one!=null){
            List<TUserChangeDetail> list = changeDetailService.lambdaQuery().eq(TUserChangeDetail::getChangeId, one.getId()).list();
            for (TUserChangeDetail tUserChangeDetail : list) {
                List<TCourse> list1 = courseService.lambdaQuery().eq(TCourse::getRegionId,tUserChangeDetail.getRegionId()).eq(TCourse::getMajorId, tUserChangeDetail.getMajorId()).eq(TCourse::getLevel, tUserChangeDetail.getLevelId()).list();
                notices.addAll(list1);
            }
            notices.sort(Comparator.comparing(TCourse::getCreateTime).reversed());
        }else {
            // 创建 LambdaQueryWrapper 并设置查询条件
        }
        List<TCourse> list1 = courseService.lambdaQuery().last("ORDER BY RAND() LIMIT 16").list();
        notices.addAll(list1);
        if (notices.size() > 16) {
            // 只保留前 16 条记录
            notices = new ArrayList<>(notices.subList(0, 16));
        }
        return R.ok(notices);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInfoConfigController.java
New file
@@ -0,0 +1,40 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TInfoConfig;
import com.ruoyi.system.service.TInfoConfigService;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * <p>
 * 后台信息设置 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-info-config")
public class TInfoConfigController {
    @Resource
    private TInfoConfigService tInfoConfigService;
    @ApiOperation(value = "查询",tags = {"后台-系统设置-关于我们,其他设置","web-关于我们"})
    @PostMapping("/getInfoConfig")
    public R<TInfoConfig> getInfoConfig(Integer id){
        return R.ok(tInfoConfigService.getById(id));
    }
    @ApiOperation(value = "修改",tags = "后台-系统设置-关于我们,其他设置")
    @PostMapping("/updateInfoConfig")
    public R<Boolean> updateInfoConfig(TInfoConfig tInfoConfig){
        return R.ok(tInfoConfigService.updateById(tInfoConfig));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInformationClassController.java
New file
@@ -0,0 +1,65 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TBanner;
import com.ruoyi.system.domain.TInformationClass;
import com.ruoyi.system.service.TInformationClassService;
import io.swagger.annotations.ApiOperation;
import org.apache.catalina.LifecycleState;
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 javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
 * <p>
 * 咨询分类 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-20
 */
@RestController
@RequestMapping("/t-information-class")
public class TInformationClassController {
    @Resource
    private TInformationClassService tInformationClassService;
    //添加分类
    @ApiOperation(value = "添加",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/add")
    public R add(@RequestBody TInformationClass informationClass) {
        tInformationClassService.save(informationClass);
        return R.ok();
    }
    //修改分类
    @ApiOperation(value = "修改",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TInformationClass informationClass) {
        tInformationClassService.updateById(informationClass);
        return R.ok();
    }
    //删除
    @ApiOperation(value = "删除",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids) {
        tInformationClassService.removeByIds(Arrays.asList(ids.split(",")));
        return R.ok();
    }
    //查询
    @ApiOperation(value = "查询",tags = "后台-咨询管理-咨询分类")
    @PostMapping(value = "/list")
    public R<List<TInformationClass>> list() {
        return R.ok(tInformationClassService.lambdaQuery().list());
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TInformationController.java
New file
@@ -0,0 +1,315 @@
package com.ruoyi.web.controller.api;
import cn.hutool.http.HttpException;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vx.WeChatConfig;
import com.ruoyi.system.vx.WeChatUtil;
import com.ruoyi.web.controller.query.InformationQuery;
import com.ruoyi.web.controller.query.PayDto;
import com.ruoyi.web.controller.tool.AlipayTradePagePay;
import com.ruoyi.web.controller.tool.AlipayTradeQuery;
import com.ruoyi.web.controller.tool.PayMoneyUtil;
import com.ruoyi.web.controller.tool.ResultUtil;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.service.partnerpayments.app.model.PrepayResponse;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.refund.RefundService;
import io.lettuce.core.api.async.RedisAclAsyncCommands;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
 * <p>
 * 咨询列表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-information")
public class TInformationController {
    @Resource
    private TInformationService informationService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TokenService tokenService;
    @Resource
    private TOrderService orderService;
    @Resource
    private NativePayService nativePayService;
    @Resource
    private WeChatConfig weChatConfig;
    @Resource
    private RedisCache redisCache;
    @Resource
    private RefundService refundService;
    @Resource
    private PayMoneyUtil payMoneyUtil;
    //新增咨询
    @ApiOperation(value = "添加",tags = "后台-资料管理")
    @PostMapping(value = "/add")
    public R add(@RequestBody TInformation information) {
        informationService.save(information);
        return R.ok();
    }
    //修改咨询
    @ApiOperation(value = "修改",tags = "后台-资料管理")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TInformation information) {
        informationService.updateById(information);
        return R.ok();
    }
    //删除咨询
    @ApiOperation(value = "删除",tags = "后台-资料管理")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids) {
        informationService.removeByIds(Arrays.asList(ids.split(",")));
        return R.ok();
    }
    //查询咨询
    @ApiOperation(value = "查询",tags = {"后台-资料管理","web资料查询"})
    @PostMapping(value = "/list")
    public R<Page<TInformation>> list(@RequestBody InformationQuery informationQuery) {
        Long userId = tokenService.getLoginUser().getUserId();
        Page<TInformation> page = informationService.lambdaQuery()
                .like(!StringUtils.isEmpty(informationQuery.getInformationName()), TInformation::getInformationName, informationQuery.getInformationName())
                .eq(informationQuery.getRegionId() != null, TInformation::getRegionId, informationQuery.getRegionId())
                .eq(informationQuery.getTechnicalId() != null, TInformation::getTechnicalId, informationQuery.getTechnicalId())
                .eq(informationQuery.getMajorId() != null, TInformation::getMajorId, informationQuery.getMajorId())
                .eq(informationQuery.getLevel() != null, TInformation::getLevel, informationQuery.getLevel())
                .eq(informationQuery.getFree()!=null&&informationQuery.getFree() == 1, TInformation::getInformationPrice, BigDecimal.ZERO)
                .ne(informationQuery.getFree()!=null&&informationQuery.getFree() == 2, TInformation::getInformationPrice, BigDecimal.ZERO)
                .orderByDesc(TInformation::getCommitteeSort)
                .page(Page.of(informationQuery.getPageNum(), informationQuery.getPageSize()));
        Set<Long> cacheSet = redisCache.getCacheSet("INFORMATION:" + userId);
        for (TInformation record : page.getRecords()) {
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId());
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
            if (cacheSet!=null){
                if (cacheSet.contains(record.getId())){
                    record.setIsCollect(1);
                }else {
                    record.setIsCollect(0);
                }
            }else {
                record.setIsCollect(0);
            }
        }
        return R.ok(page);
    }
    @ApiOperation(value = "检查当前用户是否购买资料",tags = {"web资料查询"})
    @PostMapping(value = "/check")
    public R<Boolean> check(@RequestParam Long id) {
        Long userId = tokenService.getLoginUser().getUserId();
        List<TOrder> list = orderService.lambdaQuery().eq(TOrder::getGoodType, 2).eq(TOrder::getPaymentStatus,2).eq(TOrder::getGoodId,id).eq(TOrder::getUserId, userId).list();
        if (list.isEmpty()){
            return R.ok(false);
        }else {
            return R.ok(true);
        }
    }
    @ApiOperation(value = "下载累计次数",tags = {"web资料查询"})
    @PostMapping(value = "/downland")
    public R downland(@RequestParam Long id) {
        TInformation byId = informationService.getById(id);
        byId.setDownlandNum(byId.getDownlandNum()+1);
        informationService.updateById(byId);
        return R.ok();
    }
    //新增咨询
    @ApiOperation(value = "详情",tags = {"后台-资料管理","web资料查询"})
    @PostMapping(value = "/detail")
    public R<TInformation> detail(@RequestParam Long  id) {
        Long userId = tokenService.getLoginUser().getUserId();
        TInformation record = informationService.getById(id);
        Set<Long> cacheSet = redisCache.getCacheSet("INFORMATION:" + userId);
        TRegion byId = regionService.getById(record.getRegionId());
        record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
        TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId());
        TTitleMajor byId2 = majorService.getById(record.getMajorId());
        record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        if (cacheSet!=null){
            if (cacheSet.contains(record.getId())){
                record.setIsCollect(1);
            }else {
                record.setIsCollect(0);
            }
        }else {
            record.setIsCollect(0);
        }
        return R.ok(record);
    }
    @ApiOperation(value = "生成订单",tags = {"web资料查询"})
    @PostMapping(value = "/create")
    public R buy( @RequestParam Long id) throws AlipayApiException {
        Long userId = tokenService.getLoginUser().getUserId();
        TInformation byId = informationService.getById(id);
        String code = "ZL" + WeChatUtil.generateTradeNumber();
        TOrder order = new TOrder();
        order.setCode(code);
        order.setUserId(userId);
        order.setGoodType(2);
        order.setGoodId(id);
        order.setOrderAmount(byId.getInformationPrice());
        order.setPaymentAmount(byId.getInformationPrice());
        if (byId.getInformationPrice().compareTo(new BigDecimal(0))==0){
            order.setPaymentStatus(2);
        }
        order.setPaymentStatus(1);
        orderService.save(order);
        return R.ok(order.getId());
    }
    @ApiOperation(value = "购买资料",tags = {"web资料查询"})
    @PostMapping(value = "/buy")
    public R buy(@RequestParam Integer type, @RequestParam Long orderId) throws AlipayApiException {
        TOrder byId = orderService.getById(orderId);
        int i = byId.getPaymentAmount().multiply(BigDecimal.valueOf(100)).intValue();
        TOrder byId1 = orderService.getById(orderId);
        if (type == 1) {
            Long userId = tokenService.getLoginUser().getUserId();
            com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
            prepayRequest.setAppid(weChatConfig.appId);
            prepayRequest.setMchid(weChatConfig.merchantId);
            prepayRequest.setOutTradeNo(byId1.getCode());
            prepayRequest.setDescription("购买资料");
            prepayRequest.setNotifyUrl("http://www.zhipingwang.com.cn:8081/call-back/buy");
            com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
            amount.setTotal(i);
            prepayRequest.setAmount(amount);
            // 调用下单方法,得到应答
            PrepayResponse response;
            try {
                com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse prepay = nativePayService.prepay(prepayRequest);
                //预支付成功,创建预支付订单
                PayDto payDto = new PayDto();
                payDto.setOrderId(orderId);
                payDto.setQrCode(prepay.getCodeUrl());
                return R.ok(payDto);
            } catch (HttpException e) { // 发送HTTP请求失败
//                log.error("发送HTTP请求失败: {}", e.getHttpRequest());
            } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
//                log.error("服务返回状态异常: {}", e.getResponseBody());
            } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
//                log.error("返回体类型不合法: {}", e.getMessage());
            } catch (Exception e) {
//                log.error("预下单异常: {}", e.getMessage());
            }
            return null;
        } else {
            String qrCode = AlipayTradePagePay.pay("购买资料",byId1.getCode(),byId.getPaymentAmount().toString());
            PayDto payDto = new PayDto();
            payDto.setOrderId(orderId);
            payDto.setQrCode(qrCode);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        int num = 1;
                        int wait = 0;
                        while (num <= 30) {
                            int min = 2000;
                            Thread.sleep(min);
                            Boolean check = AlipayTradeQuery.check(byId.getCode());
                            if (check){
                                byId.setPaymentStatus(2);
                                byId.setPaymentType(2);
                                byId.setPayTime(LocalDateTime.now());
                                orderService.updateById(byId);
                            }else {
                                num++;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            return R.ok(payDto);
        }
    }
    @ApiOperation(value = "收藏资料",tags = {"web-个人中心"})
    @PostMapping(value = "/info/list")
    public R<Page<TInformation>> infolist(@RequestBody BasePage basePage) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("INFORMATION:" + userId);
        if (!cacheSet.isEmpty()) {
            Page<TInformation> page = informationService.lambdaQuery().in(TInformation::getId, cacheSet).page(Page.of(basePage.getPageNum(), basePage.getPageSize()));
            return R.ok(page);
        }else {
            return R.ok(new Page<>());
        }
    }
    @ApiOperation(value = "判断资料",tags = {"web-个人中心"})
    @PostMapping(value = "/collect/is")
    public R<Boolean> collectis(@RequestParam Long informationId) {
        Long userId = tokenService.getLoginUser().getUserId();
        Set<Long> cacheSet = redisCache.getCacheSet("INFORMATION:" + userId);
       if (cacheSet.contains(informationId)){
           return R.ok(true);
       }else {
           return R.ok(false);
       }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TOrderController.java
New file
@@ -0,0 +1,267 @@
package com.ruoyi.web.controller.api;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.WebUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.query.AppUserQuery;
import com.ruoyi.system.query.OrderQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.query.CourseQuery;
import com.ruoyi.web.controller.query.InformationQuery;
import com.ruoyi.web.controller.tool.PayMoneyUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.security.core.parameters.P;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
 * <p>
 * 订单表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-order")
public class TOrderController {
    @Resource
    private TOrderService orderService;
    @Resource
    private TCourseService courseService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TGeneratedRecordsService generatedRecordsService;
    @Resource
    private TInformationService informationService;
    @Resource
    private PayMoneyUtil payMoneyUtil;
    @Resource
    private TokenService tokenService;
    @Resource
    private TAppUserService appUserService;
    //查询
    @ApiOperation(value = "查询",tags = "后台-订单管理")
    @PostMapping("/pageList")
    public R<PageInfo<TOrder>> pageList(@RequestBody OrderQuery orderQuery){
        return R.ok(orderService.pageList(orderQuery));
    }
    @ApiOperation(value = "删除",tags = "web-订单管理")
    @PostMapping("/delete")
    public R delete(@RequestParam Long orderId){
        orderService.removeById(orderId);
        return R.ok();
    }
    @ApiOperation(value = "订单查询",tags = "web-个人中心")
    @PostMapping("/web/pageList")
    public R<PageInfo<TOrder>> webpageList(@RequestBody OrderQuery orderQuery){
        Long userId = tokenService.getLoginUser().getUserId();
        orderQuery.setUserId(userId);
        return R.ok(orderService.pageList(orderQuery));
    }
    @ApiOperation(value = "计数",tags = "后台-订单管理")
    @PostMapping("/count")
    public R<List<Map<String,Object>>> count(@RequestBody OrderQuery orderQuery){
        return R.ok(orderService.totalCount(orderQuery));
    }
    @ApiOperation(value = "取消订单",tags = {"后台-订单管理","web-个人中心"})
    @PostMapping("/cancel")
    public R cancel(Long orderId){
         TOrder byId = orderService.getById(orderId);
         if (byId.getPaymentStatus()!=1){
             return R.fail("订单状态异常");
         }
         byId.setPaymentStatus(3);
        byId.setCancelTime(LocalDateTime.now());
         orderService.updateById(byId);
        return R.ok();
    }
    @ApiOperation(value = "课程详情",tags = "后台-订单管理")
    @PostMapping(value = "/course/detail")
    public R<TCourse> list(Long id,Long goodId) {
        TCourse course = courseService.getById(goodId);
            TRegion byId = regionService.getById(course.getRegionId());
        course.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(course.getTechnicalId() );
            TTitleMajor byId2 = majorService.getById(course.getMajorId());
        course.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        TOrder byId3 = orderService.getById(id);
        TAppUser byId4 = appUserService.getById(byId3.getUserId());
        byId3.setName(byId4.getName());
        byId3.setPhone(byId4.getPhone());
        byId3.setAvatar(byId4.getAvatar());
        course.setOrder(byId3);
        return R.ok(course);
    }
    @ApiOperation(value = "工作总结详情",tags = "后台-订单管理")
    @PostMapping("/generate/detail")
    public R<TGeneratedRecords> detail(Long id){
        TOrder byId = orderService.getById(id);
        TGeneratedRecords one = generatedRecordsService.lambdaQuery().eq(TGeneratedRecords::getUserId, byId.getUserId()).orderByDesc(TGeneratedRecords::getCreateTime).last("limit 1").one();
        if (one == null) {
            TGeneratedRecords generatedRecords = new TGeneratedRecords();
            generatedRecords.setOrder(byId);
            return R.ok(generatedRecords);
        }
        TOrder byId3 = orderService.getById(id);
        TAppUser byId4 = appUserService.getById(byId3.getUserId());
        byId3.setName(byId4.getName());
        byId3.setPhone(byId4.getPhone());
        byId3.setAvatar(byId4.getAvatar());
        one.setOrder(byId3);
        return R.ok(one);
    }
    @ApiOperation(value = "资料详情",tags = "后台-订单管理")
    @PostMapping(value = "/order/information/detail")
    public R<TInformation> informationR1(Long goodId,Long id) {
      TInformation record = informationService.getById(goodId);
            TRegion byId = regionService.getById(record.getRegionId());
            record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
            TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId());
            TTitleMajor byId2 = majorService.getById(record.getMajorId());
            record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        TOrder byId3 = orderService.getById(id);
        TAppUser byId4 = appUserService.getById(byId3.getUserId());
        byId3.setName(byId4.getName());
        byId3.setPhone(byId4.getPhone());
        byId3.setAvatar(byId4.getAvatar());
        record.setOrder(byId3);
        return R.ok(record);
    }
    @ApiOperation(value = "资料详情",tags = "后台-资料管理")
    @PostMapping(value = "/information/detail")
    public R<TInformation> informationR(Long goodId) {
        TInformation record = informationService.getById(goodId);
        TRegion byId = regionService.getById(record.getRegionId());
        record.setRegionName(byId.getProvinceName()+"-"+byId.getName());
        TTechnicalTitle byId1 = tTechnicalTitleService.getById(record.getTechnicalId());
        TTitleMajor byId2 = majorService.getById(record.getMajorId());
        record.setTechnicalName(byId1.getTitileName()+"-"+byId2.getMajorName());
        return R.ok(record);
    }
    @ApiOperation(value = "退款",tags = "后台-资料管理")
    @PostMapping(value = "/refund")
    public R<TInformation> refund(Long orderId) throws AlipayApiException {
        TOrder byId = orderService.getById(orderId);
        if (byId.getPaymentStatus()!=2){
            return R.fail("订单状态异常");
        }
        if (byId.getPaymentType()==1){
            payMoneyUtil.wxRefund(byId.getSerialNumber(), byId.getCode(),byId.getPaymentAmount().toString(), byId.getPaymentAmount().toString(),"/");
        }
        if (byId.getPaymentType()==2){
            Map<String, String> stringStringMap = payMoneyUtil.aliRefund(byId.getCode(), byId.getPaymentAmount().toString());
            if ("10000".equals(stringStringMap.get("code"))){
                byId.setPaymentStatus(4);
                orderService.updateById(byId);
            }
        }
        return R.ok();
    }
    @ApiOperation(value = "导出",tags = "后台-订单管理")
    @PostMapping(value = "/export")
    public void mealGeneratorExport(@RequestBody OrderQuery orderQuery) {
        orderQuery.setPageNum(1);
        orderQuery.setPageSize(9999);
        PageInfo<TOrder> tOrderPageInfo = orderService.pageList(orderQuery);
        for (TOrder record : tOrderPageInfo.getRecords()) {
            record.getFormattedCreateTime();
            if (record.getGoodType()==1){
                TCourse byId = courseService.getById(record.getGoodId());
                record.setGoodName(byId.getCourseName());
            }else if (record.getGoodType()==2){
                TInformation byId = informationService.getById(record.getGoodId());
                record.setGoodName(byId.getInformationName());
            }else {
                record.setGoodName("工作总结订单");
            }
        }
        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TOrder.class,tOrderPageInfo.getRecords() );
        HttpServletResponse response = WebUtils.response();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        ServletOutputStream outputStream = null;
        try {
            String fileName = URLEncoder.encode("用户列表.xls", "utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TRegionController.java
New file
@@ -0,0 +1,101 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.domain.TIndexMenu;
import com.ruoyi.system.domain.TRegion;
import com.ruoyi.system.service.TRegionService;
import com.ruoyi.web.controller.tool.PinyinExample;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.*;
/**
 * <p>
 * 省市区三级联动 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-region")
public class TRegionController {
    @Resource
    private TRegionService indexMenuService;
    @ApiOperation(value = "列表",tags = "后台-系统设置-开通地区管理")
    @PostMapping(value = "/list")
    public R<List<TRegion>> list(String name) {
        List<TRegion> list = indexMenuService.lambdaQuery().like(name!=null&&name!="",TRegion::getName,name).list();
        return R.ok(list);
    }
    @ApiOperation(value = "关闭禁用",tags = "后台-系统设置-开通地区管理")
    @PostMapping(value = "/open")
    public R open(Integer id, Integer isOpen) {
        TRegion byId = indexMenuService.getById(id);
        byId.setIsOpen(isOpen);
        indexMenuService.updateById(byId);
        return R.ok();
    }
    @Resource
    private TRegionService regionService;
    @ApiOperation(value = "单查省",tags = "web-下拉框")
    @PostMapping(value = "/province")
    public R province() {
        List<TRegion> list = regionService.lambdaQuery().eq(TRegion::getIsOpen,1).groupBy(TRegion::getProvinceName).list();
        return R.ok(list);
    }
    @ApiOperation(value = "城市列表",tags = "web-开通地区")
    @PostMapping(value = "/abc/list")
    public R abclist() {
        List<TRegion> list = indexMenuService.lambdaQuery().eq(TRegion::getIsOpen,1).list();
        Map<String, Set<Object>> map = new HashMap<>();
        for (TRegion tRegion : list) {
            String firstLetter = PinyinExample.getFirstLetter(tRegion.getName());
            if (map.get(firstLetter)==null){
                Set<Object> set = new HashSet<>();
                set.add(tRegion);
                map.put(firstLetter,set);
            }else {
                map.get(firstLetter).add(tRegion);
            }
        }
        return R.ok(map);
    }
    @ApiOperation(value = "省列表",tags = "web-开通地区")
    @PostMapping(value = "/abc/province/list")
    public R abcprovincelist() {
        List<TRegion> list = indexMenuService.lambdaQuery().eq(TRegion::getIsOpen,1).list();
        Map<String, Set<Object>> map = new HashMap<>();
        for (TRegion tRegion : list) {
            String firstLetter = PinyinExample.getFirstLetter(tRegion.getProvinceName());
            if (map.get(firstLetter)==null){
                Set<Object> set = new HashSet<>();
                set.add(tRegion);
                map.put(firstLetter,set);
            }else {
                map.get(firstLetter).add(tRegion);
            }
        }
        return R.ok(map);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TTechnicalTitleController.java
New file
@@ -0,0 +1,230 @@
package com.ruoyi.web.controller.api;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.dto.TechImportExcel;
import com.ruoyi.system.service.*;
import com.ruoyi.system.query.RegionQuery;
import io.swagger.annotations.ApiOperation;
import org.apache.logging.log4j.core.util.DefaultShutdownCallbackRegistry;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
 * <p>
 * 职称系列 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-technical-title")
public class TTechnicalTitleController {
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTitleMajorService majorService;
    @Resource
    private TLevelService levelService;
    //添加接口
    @ApiOperation(value = "添加",tags = "后台-系统设置-职称系列")
    @PostMapping(value = "/add")
    public R add(@RequestBody TTechnicalTitle tTechnicalTitle){
        tTechnicalTitleService.save(tTechnicalTitle);
        return R.ok();
    }
    @ApiOperation(value = "职称分类",tags = "后台-下拉框")
    @PostMapping(value = "/select")
    public R<List<TTechnicalTitle>> select(){
        return R.ok(tTechnicalTitleService.list());
    }
    @ApiOperation(value = "树状图",tags = "web-下拉框")
    @PostMapping(value = "/tree")
    public R<List<TTechnicalTitle>> tree(){
        List<TLevel> list2 = levelService.list();
        List<TTechnicalTitle> list = tTechnicalTitleService.list();
        for (TTechnicalTitle tTechnicalTitle : list) {
            tTechnicalTitle.setName(tTechnicalTitle.getTitileName());
            List<TTitleMajor> list1 = majorService.lambdaQuery().eq(TTitleMajor::getTechnicalId, tTechnicalTitle.getId()).list();
            for (TTitleMajor tTitleMajor : list1) {
                tTitleMajor.setName(tTitleMajor.getMajorName());
                tTitleMajor.setMajors(list2);
            }
            tTechnicalTitle.setMajors(list1);
        }
        return R.ok(list);
    }
    //编辑接口
    @ApiOperation(value = "编辑",tags = "后台-系统设置-职称系列")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TTechnicalTitle tTechnicalTitle){
        tTechnicalTitleService.updateById(tTechnicalTitle);
        return R.ok();
    }
    @Resource
    private TUserChangeDetailService userChangeDetailService;
    @Resource
    private TConsultationService consultationService;
    @Resource
    private TDeclareNoticeService declareNoticeService;
    @Resource
    private TCommitteeTechnicalService committeeTechnicalService;
    @Resource
    private TCommitteeService committeeService;
    @Resource
    private TInformationService informationService;
    @Resource
    private TCourseService courseService;
    //批量删除接口
    @ApiOperation(value = "删除",tags = "后台-系统设置-职称系列")
    @PostMapping(value = "/deleteByIds")
    public R deleteByIds(String ids){
        List<String> list = Arrays.asList(ids.split(","));
        for (String s : list) {
            //判断是否有关联数据
            Long count = userChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getTitleId, s).count();
            if (count>0){
                return R.fail("当前职称已有用户设为偏好,无法删除");
            }
            Long count1 = consultationService.lambdaQuery().eq(TConsultation::getTitleId, s).count();
            if (count1>0){
                return R.fail("当前职称已设置咨询,无法删除");
            }
            Long count2 = declareNoticeService.lambdaQuery().eq(TDeclareNotice::getTechnicalId, s).count();
            if (count2>0){
                return R.fail("当前职称已设置申报通知,无法删除");
            }
            Long count3 = committeeTechnicalService.lambdaQuery().eq(TCommitteeTechnical::getTechnicalId, s).count();
            if (count3>0){
                return R.fail("当前职称已设置委员会可评审职称,无法删除");
            }
            Long count4 = committeeService.lambdaQuery().eq(TCommittee::getTechnicalId, s).count();
            if (count4>0){
                return R.fail("当前职称已设置评审委员会,无法删除");
            }
            Long count5 = informationService.lambdaQuery().eq(TInformation::getTechnicalId, s).count();
            if (count5>0){
                return R.fail("当前职称已设置资料,无法删除");
            }
            Long count6 = majorService.lambdaQuery().eq(TTitleMajor::getTechnicalId, s).count();
            if (count6>0){
                return R.fail("当前职称已设置专业,无法删除");
            }
            Long count7 = courseService.lambdaQuery().eq(TCourse::getTechnicalId, s).count();
            if (count7>0){
                return R.fail("当前职称已设置课程,无法删除");
            }
        }
        tTechnicalTitleService.removeByIds(list);
        return R.ok();
    }
    //分页查询
    @ApiOperation(value = "查询",tags = "后台-系统设置-职称系列")
    @PostMapping(value = "/pageList")
    public R<PageInfo<TTechnicalTitle>> pageList(@RequestBody RegionQuery regionQuery){
        return R.ok(tTechnicalTitleService.pageList(regionQuery));
    }
    @ApiOperation(value = "导入",tags = "后台-系统设置-职称系列")
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    @PostMapping("/export")
    public R export (@RequestParam("file") MultipartFile file) {
        List<TTechnicalTitle> tTechnicalTitles = new ArrayList<>();
        int errorLines = 0;
        int successLines = 0;
        ImportParams params = new ImportParams();
//        params.setTitleRows(1);//标题行数
        params.setHeadRows(1); //表头行数
        String msg = null;
        InputStream inputStream = null;
        List<String> failMsg = new ArrayList<>();
        try {
            inputStream = file.getInputStream();
            List<TechImportExcel> techImportExcels = ExcelImportUtil.importExcel(inputStream, TechImportExcel.class, params);
            for (TechImportExcel techImportExcel : techImportExcels) {
                List<Integer> regionIds;
                if (techImportExcel.getAddress() == null || StringUtils.isEmpty(techImportExcel.getAddress())) {
                    msg = "第" + techImportExcels.indexOf(techImportExcel) + "行,地区不能为空";
                    failMsg.add(msg);
                    continue;
                } else {
                    String[] split = techImportExcel.getAddress().split(";");
                    regionIds = new ArrayList<>();
                    for (String s : split) {
                        TRegion region = regionService.lambdaQuery().like(TRegion::getName, s).one();
                        if (region == null) {
                            msg = "第" + techImportExcels.indexOf(techImportExcel) + "行,地区不存在";
                            failMsg.add(msg);
                        } else {
                            regionIds.add(region.getId());
                        }
                    }
                    if (regionIds.size() != split.length) {
                        continue;
                    }
                }
                TTechnicalTitle tTechnicalTitle = new TTechnicalTitle();
                tTechnicalTitle.setTitileName(techImportExcel.getTitileName());
                tTechnicalTitle.setRegionIds(StringUtils.join(regionIds, ","));
                tTechnicalTitles.add(tTechnicalTitle);
            }
            if (failMsg.size()==0){
                tTechnicalTitleService.saveBatch(tTechnicalTitles);
            }else {
                return R.fail(failMsg);
            }
        } catch (Exception e) {
            e.printStackTrace();
//            logger.error("批量购入导入失败:{}",e.getMessage());
//            importRecordService.removeById(tImportRecord.getId());
            return R.fail("批量购入导入失败!");
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new ServiceException(e.getMessage());
            }
        }
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TTitleMajorController.java
New file
@@ -0,0 +1,232 @@
package com.ruoyi.web.controller.api;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.BasePage;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.dto.MahorImportExcel;
import com.ruoyi.system.dto.TechImportExcel;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.SysUserVO;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
 * 专业列表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-title-major")
public class TTitleMajorController {
    @Resource
    private TTitleMajorService tTitleMajorService;
    @Resource
    private TRegionService regionService;
    @Resource
    private TTechnicalTitleService tTechnicalTitleService;
    //增加专业
    @ApiOperation(value = "添加",tags = "后台-系统设置-专业列表")
    @PostMapping(value = "/add")
    public R add(@RequestBody TTitleMajor tTitleMajor){
        tTitleMajorService.save(tTitleMajor);
        return R.ok();
    }
    //修改
    @ApiOperation(value = "编辑",tags = "后台-系统设置-专业列表")
    @PostMapping(value = "/edit")
    public R edit(@RequestBody TTitleMajor tTitleMajor){
        tTitleMajorService.updateById(tTitleMajor);
        return R.ok();
    }
    @Resource
    private TUserChangeDetailService userChangeDetailService;
    @Resource
    private TConsultationService consultationService;
    @Resource
    private TDeclareNoticeService declareNoticeService;
    @Resource
    private TCommitteeTechnicalService committeeTechnicalService;
    @Resource
    private TCommitteeService committeeService;
    @Resource
    private TInformationService informationService;
    @Resource
    private TCourseService courseService;
    @Resource
    private TTitleMajorService majorService;
    //删除
    @ApiOperation(value = "删除",tags = "后台-系统设置-专业列表")
    @PostMapping(value = "/deleteById")
    public R deleteById(Long id){
            String s = id.toString();
            //判断是否有关联数据
            Long count = userChangeDetailService.lambdaQuery().eq(TUserChangeDetail::getMajorId, s).count();
            if (count>0){
                return R.fail("当前专业已有用户设为偏好,无法删除");
            }
            Long count1 = consultationService.lambdaQuery().eq(TConsultation::getMajorId, s).count();
            if (count1>0){
                return R.fail("当前专业已设置咨询,无法删除");
            }
            Long count2 = declareNoticeService.lambdaQuery().eq(TDeclareNotice::getMajorId, s).count();
            if (count2>0){
                return R.fail("当前专业已设置申报通知,无法删除");
            }
            Long count3 = committeeTechnicalService.lambdaQuery().eq(TCommitteeTechnical::getMajorId, s).count();
            if (count3>0){
                return R.fail("当前专业已设置委员会可评审职称,无法删除");
            }
            Long count4 = committeeService.lambdaQuery().eq(TCommittee::getMajorId, s).count();
            if (count4>0){
                return R.fail("当前专业已设置评审委员会,无法删除");
            }
            Long count5 = informationService.lambdaQuery().eq(TInformation::getMajorId, s).count();
            if (count5>0){
                return R.fail("当前专业已设置资料,无法删除");
            }
            Long count7 = courseService.lambdaQuery().eq(TCourse::getMajorId, s).count();
            if (count7>0){
                return R.fail("当前专业已设置课程,无法删除");
            }
        tTitleMajorService.removeById(id);
        return R.ok();
    }
    //分页列表
    @ApiOperation(value = "查询",tags = "后台-系统设置-专业列表")
    @PostMapping(value = "/pageList")
    public R pageList(@RequestBody BasePage basePage){
        PageInfo<TTitleMajor> titleMajorList = tTitleMajorService.pageList(basePage);
        return R.ok(titleMajorList);
    }
    @ApiOperation(value = "导入",tags = "后台-系统设置-专业列表")
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    @PostMapping("/export")
    public R export (@RequestParam("file") MultipartFile file) {
        List<TTitleMajor> tTechnicalTitles = new ArrayList<>();
        int errorLines = 0;
        int successLines = 0;
        ImportParams params = new ImportParams();
//        params.setTitleRows(1);//标题行数
        params.setHeadRows(1); //表头行数
        String msg = null;
        InputStream inputStream = null;
        List<String> failMsg = new ArrayList<>();
        try {
            inputStream = file.getInputStream();
            List<MahorImportExcel> techImportExcels = ExcelImportUtil.importExcel(inputStream, MahorImportExcel.class, params);
            for (MahorImportExcel techImportExcel : techImportExcels) {
                List<Integer> regionIds;
                if (techImportExcel.getAddress() == null || StringUtils.isEmpty(techImportExcel.getAddress())) {
                    msg = "第" + techImportExcels.indexOf(techImportExcel) + "行,地区不能为空";
                    failMsg.add(msg);
                    continue;
                } else {
                    String[] split = techImportExcel.getAddress().split(";");
                    regionIds = new ArrayList<>();
                    for (String s : split) {
                        TRegion region = regionService.lambdaQuery().like(TRegion::getName, s).one();
                        if (region == null) {
                            msg = "第" + techImportExcels.indexOf(techImportExcel) + "行,地区不存在";
                            failMsg.add(msg);
                        } else {
                            regionIds.add(region.getId());
                        }
                    }
                    if (regionIds.size() != split.length) {
                        continue;
                    }
                }
                TTitleMajor tTechnicalTitle = new TTitleMajor();
                if (techImportExcel.getTitileName()==null||StringUtils.isEmpty(techImportExcel.getTitileName())){
                    msg = "第" + techImportExcels.indexOf(techImportExcel) + "行,职称名称不能为空";
                    failMsg.add(msg);
                    continue;
                }else {
                    TTechnicalTitle one = tTechnicalTitleService.lambdaQuery().eq(TTechnicalTitle::getTitileName, techImportExcel.getTitileName()).last("limit 1").one();
                    if (one!=null){
                        tTechnicalTitle.setTechnicalId(one.getId());
                    }else {
                        msg = "第" + techImportExcels.indexOf(techImportExcel) + "行,职称名称不存在";
                        failMsg.add(msg);
                        continue;
                    }
                }
                tTechnicalTitle.setRegionIds(StringUtils.join(regionIds, ","));
                tTechnicalTitle.setMajorName(techImportExcel.getMajorName());
                tTechnicalTitles.add(tTechnicalTitle);
            }
            if (failMsg.size()==0){
                tTitleMajorService.saveBatch(tTechnicalTitles);
            }else {
                return R.fail(failMsg);
            }
        } catch (Exception e) {
            e.printStackTrace();
//            logger.error("批量购入导入失败:{}",e.getMessage());
//            importRecordService.removeById(tImportRecord.getId());
            return R.fail("批量购入导入失败!");
        }finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                throw new ServiceException(e.getMessage());
            }
        }
        return R.ok();
    }
    @ApiOperation(value = "通过职称分类查询专业",tags = "后台-下拉框")
    @PostMapping(value = "/select")
    public R<List<TTitleMajor>> select(@RequestParam Long id){
        return R.ok(tTitleMajorService.lambdaQuery().eq(TTitleMajor::getTechnicalId,id).list());
    }
    @Resource
    private TLevelService levelService;
    @ApiOperation(value = "类别",tags = "后台-下拉框")
    @PostMapping(value = "/level/select")
    public R<List<TLevel>> levelselect(){
        return R.ok(levelService.list());
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TUserChangeController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 每次改变偏好的记录 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-user-change")
public class TUserChangeController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TUserChangeDetailController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 偏好关联专业表 前端控制器
 * </p>
 *
 * @author luodangjia
 * @since 2024-09-19
 */
@RestController
@RequestMapping("/t-user-change-detail")
public class TUserChangeDetailController {
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TestController.java
New file
@@ -0,0 +1,85 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.web.controller.tool.PdfUtils;
import com.ruoyi.web.controller.tool.WordUtil;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/test")
public class TestController {
    @Resource
    private WordUtil wordUtil;
    /**
     * 基于模板生成 Word 文档(生成动态列表)
     *
     * @param response response
     */
    @ApiOperation(value = "列表",tags = {"TTTT"})
    @GetMapping("/generate_dynamic_word")
    public void generateDynamicWord(HttpServletResponse response) throws IOException {
        // 定义文件路径
        String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09\\pdf\\专业技术工作总结.pdf";
        // 获取文件对象
        File file = new File(filePath);
        // 设置响应内容类型
        response.setContentType("application/pdf");
        // 设置响应字符编码为 UTF-8
        response.setCharacterEncoding("UTF-8");
        // 设置响应头,指定文档将以附件的形式下载,并定义文件名
        response.setHeader("Content-Disposition", "attachment; filename=" + "1.pdf" );
        // 创建输入流读取文件
        FileInputStream fileInputStream = new FileInputStream(file);
        // 获取响应输出流
        OutputStream responseOutputStream = response.getOutputStream();
        // 缓冲区大小设为 10KB
        byte[] buffer = new byte[10240];
        int bytesRead;
        // 读取文件内容并写入响应输出流
        while ((bytesRead = fileInputStream.read(buffer)) != -1) {
            responseOutputStream.write(buffer, 0, bytesRead);
        }
        // 关闭输入流和输出流
        fileInputStream.close();
        responseOutputStream.close();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/WebController.java
New file
@@ -0,0 +1,86 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.TIndexMenu;
import com.ruoyi.system.domain.TUserChange;
import com.ruoyi.system.domain.TUserChangeDetail;
import com.ruoyi.system.dto.AllertTitleDto;
import com.ruoyi.system.dto.RegionDto;
import com.ruoyi.system.service.TIndexMenuService;
import com.ruoyi.system.service.TRegionService;
import com.ruoyi.system.service.TUserChangeDetailService;
import com.ruoyi.system.service.TUserChangeService;
import com.ruoyi.web.controller.query.CityQueryDto;
import io.swagger.annotations.ApiOperation;
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 javax.annotation.Resource;
import java.nio.file.LinkOption;
import java.util.List;
@RestController
@RequestMapping("/web")
public class WebController {
    @Resource
    private TIndexMenuService indexMenuService;
    @Resource
    private TRegionService regionService;
    @Autowired
    private TokenService tokenService;
    @Resource
    private TUserChangeService changeService;
    @Resource
    private TUserChangeDetailService changeDetailService;
    @ApiOperation(value = "获取地区树状图",tags = "web端偏好设置")
    @PostMapping(value = "/region/tree")
    public R<List<RegionDto>> regionTree() {
       List<RegionDto> regionDtos = regionService.regionTree();
        return R.ok(regionDtos);
    }
    @ApiOperation(value = "通过cityCodes查职称分类",tags = "web端偏好设置")
    @PostMapping(value = "/title/tree")
    public R<List<AllertTitleDto>> list(@RequestBody CityQueryDto cityQueryDto) {
        List<AllertTitleDto> allertTitleDtos =  indexMenuService.allert(cityQueryDto.getCityCode());
        return R.ok(allertTitleDtos);
    }
    @ApiOperation(value = "设置偏好设置",tags = "web端偏好设置")
    @PostMapping(value = "/title/set")
    public R<List<AllertTitleDto>> set(@RequestBody List<TUserChangeDetail> userChangeDetails) {
        Long userId = tokenService.getLoginUser().getUserId();
        //保存一次变更记录
        TUserChange tUserChange = new TUserChange();
        tUserChange.setUserId(userId);
        changeService.save(tUserChange);
        //保存变更细节
        for (TUserChangeDetail userChangeDetail : userChangeDetails) {
            userChangeDetail.setChangeId(tUserChange.getId());
        }
        changeDetailService.saveBatch(userChangeDetails);
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
New file
@@ -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 javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.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
New file
@@ -0,0 +1,163 @@
package com.ruoyi.web.controller.common;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.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.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.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_DELIMETER = ",";
    /**
     * 通用下载请求
     *
     * @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_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            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 + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisConfiguration.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.web.controller.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfiguration {
    /**
     * 注册拦截器
     */
    @Bean
    public MybatisInterceptor getMybatisInterceptor() {
        return new MybatisInterceptor();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
New file
@@ -0,0 +1,122 @@
package com.ruoyi.web.controller.interceptor;
import com.ruoyi.framework.web.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;
@Slf4j
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisInterceptor implements Interceptor {
    @Autowired
    private TokenService tokenService;
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        log.debug("{}:"+mappedStatement);
        log.debug("------sqlId------" + mappedStatement.getId());
        if("com.ruoyi.system.mapper.SysLogininforMapper.insertLogininfor".equals(mappedStatement.getId())){
            return invocation.proceed();
        }
        // sql类型:insert、update、select、delete
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];
        log.debug("------sqlCommandType------" + sqlCommandType);
        if (parameter == null) {
            return invocation.proceed();
        }
        // 当sql为新增或更新类型时,自动填充操作人相关信息
        if (SqlCommandType.INSERT == sqlCommandType) {
            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    // 注入创建人
//                    if ("createBy".equals(field.getName())) {
//                        // 获取当前登录用户信息
//                        if(Objects.nonNull(tokenService.getLoginUser())){
//                            String userName = tokenService.getLoginUser().getUser().getUserName();
//                            field.setAccessible(true);
//                            field.set(parameter, userName);
//                            field.setAccessible(false);
//                        }
//                    }
                    //注入创建时间
                    if ("createTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, LocalDateTime.now());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to insert data, exception = ", e);
                }
            }
        }
        if (SqlCommandType.UPDATE == sqlCommandType) {
            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    if ("updateBy".equals(field.getName())) {
                        // 获取当前登录用户信息
                        if(Objects.nonNull(tokenService.getLoginUser())){
                            String userName = tokenService.getLoginUser().getUser().getUserName();
                            field.setAccessible(true);
                            field.set(parameter, userName);
                            field.setAccessible(false);
                        }
                    }
//                    if ("updateTime".equals(field.getName())) {
//                        field.setAccessible(true);
//                        field.set(parameter, LocalDateTime.now());
//                        field.setAccessible(false);
//                    }
                } catch (Exception e) {
                    log.error("failed to update data, exception = ", e);
                }
            }
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
    }
    /**
     * 获取类的所有属性,包括父类
     *
     * @param object
     * @return
     */
    private Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
New file
@@ -0,0 +1,120 @@
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 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, "密码错误次数"));
    }
    @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(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
New file
@@ -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
New file
@@ -0,0 +1,82 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import javax.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
New file
@@ -0,0 +1,112 @@
package com.ruoyi.web.controller.monitor;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.service.ISysOperLogService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
 * 操作日志记录
 *
 * @author ruoyi
 */
@Slf4j
@Api(tags = "操作日志记录")
@RestController
@RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController
{
    @Autowired
    private ISysOperLogService operLogService;
//    @ApiOperation(value = "操作日志分页列表")
//    @PostMapping("/list")
//    public AjaxResult list(@RequestBody SysOperLogQuery query)
//    {
//        startPage(query.getPageNum(), query.getPageSize());
//        List<SysOperLogVO> list = operLogService.selectOperLogPageList(query);
//        operLogService.getLogDetail(list);
//        return AjaxResult.success(getDataTable(list));
//    }
    /**
     * 查询操作日志列表导出
     */
//    @ApiOperation(value = "查询操作日志列表导出")
//    @Log(title = "操作日志-查询操作日志列表导出", businessType = BusinessType.EXPORT)
//    @PostMapping("/exportOperLog")
//    public void exportOperLog(@RequestBody SysOperLogQuery query)
//    {
//        List<SysOperLogVO> list = operLogService.selectOperLogPageList(query);
//        List<TOperLogExport> operLogExports = new ArrayList<>();
//        for (SysOperLogVO sysOperLogVO : list) {
//            TOperLogExport operLogExport = new TOperLogExport();
//            BeanUtils.copyProperties(sysOperLogVO,operLogExport);
//            operLogService.getLogDetail(list);
//            operLogExports.add(operLogExport);
//        }
//        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TOperLogExport.class, operLogExports);
//        HttpServletResponse response = WebUtils.response();
//        response.setContentType("application/vnd.ms-excel");
//        response.setCharacterEncoding("utf-8");
//        ServletOutputStream outputStream = null;
//        try {
//            String fileName = URLEncoder.encode("操作日志信息.xls", "utf-8");
//            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
//            response.setHeader("Pragma", "no-cache");
//            response.setHeader("Cache-Control", "no-cache");
//            outputStream = response.getOutputStream();
//            workbook.write(outputStream);
//        } catch (IOException e) {
//            e.printStackTrace();
//            log.error("操作日志导出信息导出失败!");
//        } finally {
//            try {
//                outputStream.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//    @Log(title = "操作日志", businessType = BusinessType.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)
    @DeleteMapping("/deleteById/{operIds}")
    public AjaxResult remove(@PathVariable String operIds)
    {
        String[] split = operIds.split(",");
        List<Long> id = new ArrayList<>();
        for (String s : split) {
            id.add(Long.valueOf(s));
        }
        return AjaxResult.success(operLogService.deleteOperLogByIds(id));
    }
    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
    @DeleteMapping("/clean")
    public AjaxResult clean()
    {
        operLogService.cleanOperLog();
        return success();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
New file
@@ -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/query/CityQueryDto.java
New file
@@ -0,0 +1,9 @@
package com.ruoyi.web.controller.query;
import lombok.Data;
import java.util.List;
@Data
public class CityQueryDto {
    List<String> cityCode;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/CommitteeQuery.java
New file
@@ -0,0 +1,33 @@
package com.ruoyi.web.controller.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("评审会查询query")
public class CommitteeQuery extends BasePage {
    @ApiModelProperty(value = "名称")
    private String name;
    @ApiModelProperty(value = "所在单位")
    private String committeeUnit;
    @ApiModelProperty(value = "所属地区")
    @TableField("region_id")
    private Integer regionId;
    @ApiModelProperty(value = "职称id",required = true)
    @TableField("technical_id")
    private Long technicalId;
    @ApiModelProperty(value = "专业id",required = true)
    @TableField("major_id")
    private Long majorId;
    @ApiModelProperty(value = "1初级2中级3副高级4正高级5高级")
    @TableField("level")
    private Integer level;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/ConsultationQuery.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.web.controller.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("咨询查询query")
public class ConsultationQuery extends BasePage {
    @ApiModelProperty(value = "咨询名称")
    @TableField("information_name")
    private String classificationName;
    @ApiModelProperty(value = "所属地区")
    @TableField("region_id")
    private Integer regionId;
    @ApiModelProperty(value = "所属分类1通知,2政策文件3公示信息")
    private Long classificationId;
    @ApiModelProperty(value = "职称id")
    @TableField("technical_id")
    private Long technicalId;
    @ApiModelProperty(value = "专业id")
    @TableField("major_id")
    private Long majorId;
    @ApiModelProperty(value = "1初级2中级3副高级4正高级5高级")
    @TableField("level")
    private Integer level;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/CourseQuery.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.web.controller.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("课程查询query")
public class CourseQuery extends BasePage {
    @ApiModelProperty(value = "名称")
    private String name;
    @ApiModelProperty(value = "所属地区")
    @TableField("region_id")
    private Integer regionId;
    @ApiModelProperty(value = "职称id")
    @TableField("technical_id")
    private Long technicalId;
    @ApiModelProperty(value = "专业id")
    @TableField("major_id")
    private Long majorId;
    @ApiModelProperty(value = "1初级2中级3副高级4正高级5高级")
    @TableField("level")
    private Integer level;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/DeclareNoticeQuery.java
New file
@@ -0,0 +1,44 @@
package com.ruoyi.web.controller.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
@Data
@ApiModel("评审通知query")
public class DeclareNoticeQuery extends BasePage {
    @ApiModelProperty(value = "名称")
    @TableField("information_name")
    private String declareNoticeName;
    @ApiModelProperty(value = "所属地区")
    @TableField("region_id")
    private Integer regionId;
    @ApiModelProperty(value = "职称id")
    @TableField("technical_id")
    private Long technicalId;
    @ApiModelProperty(value = "专业id")
    @TableField("major_id")
    private Long majorId;
    @ApiModelProperty(value = "1初级2中级3副高级4正高级5高级")
    @TableField("level")
    private Integer level;
    @ApiModelProperty("开始时间1")
    private LocalDate declareStartTime1;
    @ApiModelProperty("开始时间2")
    private LocalDate declareStartTime2;
    @ApiModelProperty("结束时间1")
    private LocalDate declareEndTime1;
    @ApiModelProperty("结束时间2")
    private LocalDate declareEndTime2;
    @ApiModelProperty("是否在线申报1是0否")
    private Integer isOnline;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/InformationQuery.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.web.controller.query;
import com.baomidou.mybatisplus.annotation.TableField;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("资料查询query")
public class InformationQuery extends BasePage {
    @ApiModelProperty(value = "资料名称")
    @TableField("information_name")
    private String informationName;
    @ApiModelProperty(value = "所属地区")
    @TableField("region_id")
    private Integer regionId;
    @ApiModelProperty(value = "职称id")
    @TableField("technical_id")
    private Long technicalId;
    @ApiModelProperty(value = "专业id")
    @TableField("major_id")
    private Long majorId;
    @ApiModelProperty(value = "1初级2中级3副高级4正高级5高级")
    @TableField("level")
    private Integer level;
    @ApiModelProperty(value = "1免费2付费")
    private Integer free;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/OrderCountQuery.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.web.controller.query;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDate;
@Data
@ApiModel("统计query")
public class OrderCountQuery {
    @ApiModelProperty("1今日2本周3本月4全年5自定义")
    private Integer dayType;
    private LocalDate startDate;
    private LocalDate endDate;
    private Integer paymentStatus;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/PayDto.java
New file
@@ -0,0 +1,9 @@
package com.ruoyi.web.controller.query;
import lombok.Data;
@Data
public class PayDto {
    private Long orderId;
    private String qrCode;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/VideoAddDto.java
New file
@@ -0,0 +1,12 @@
package com.ruoyi.web.controller.query;
import com.ruoyi.system.domain.TCoursePart;
import lombok.Data;
import java.util.List;
@Data
public class VideoAddDto {
    private Long courseId;
    private List<TCoursePart> courseParts;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/CountTotalDto.java
New file
@@ -0,0 +1,18 @@
package com.ruoyi.web.controller.query.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class CountTotalDto {
    @ApiModelProperty("通知公告")
    private Long noticeCount;
    @ApiModelProperty("政策文件")
    private Long fileCount;
    @ApiModelProperty("公示信息")
    private  Long infoCount;
    @ApiModelProperty("评审委员会")
    private Long committeeCount;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/FreezeDto.java
New file
@@ -0,0 +1,9 @@
package com.ruoyi.web.controller.query.dto;
import lombok.Data;
@Data
public class FreezeDto {
    Long id;
    String reason;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/ManageCountDto.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.web.controller.query.dto;
import com.ruoyi.system.domain.TCourse;
import lombok.Data;
@Data
public class ManageCountDto {
    Long userCount ;
    Long courseCount ;
    Long courseFreeCount ;
    Long payCount  ;
    Long recordsCount  ;
    Long infoCount ;
    Long infoFreeCount;
    Long infoPayCount ;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/query/dto/RegisterDto.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.web.controller.query.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("注册dto")
public class RegisterDto {
    //手机号必填
    @ApiModelProperty(required = true)
    private String phone;
    @ApiModelProperty(required = true)
    private String code;
    @ApiModelProperty(required = true)
    private String pwd;
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.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;
//    @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
New file
@@ -0,0 +1,148 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.framework.web.service.TokenService;
import io.swagger.annotations.ApiOperation;
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;
    @Autowired
    private TokenService tokenService;
    /**
     * 获取部门列表
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @ApiOperation(value = "列表",tags = {"后台-部门"})
    @GetMapping("/list")
    public AjaxResult list(SysDept dept)
    {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return AjaxResult.success(depts);
    }
    /**
     * 查询部门列表(排除节点)
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list/exclude/{deptId}")
    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
    {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return AjaxResult.success(depts);
    }
    /**
     * 根据部门编号获取详细信息
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:query')")
    @GetMapping(value = "/{deptId}")
    public AjaxResult getInfo(@PathVariable Long deptId)
    {
        deptService.checkDeptDataScope(deptId);
        return AjaxResult.success(deptService.selectDeptById(deptId));
    }
    /**
     * 新增部门
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:add')")
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    @PostMapping
    @ApiOperation(value = "添加",tags = {"后台-部门"})
    public AjaxResult add(@Validated @RequestBody SysDept dept)
    {
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("新增部门'" + dept.getDeptName() + "'失败,部门id已存在");
        }
        dept.setCreateBy(getUsername());
        return AjaxResult.success(deptService.insertDept(dept));
    }
    /**
     * 修改部门
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:edit')")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping
    @ApiOperation(value = "修改",tags = {"后台-部门"})
    public AjaxResult edit(@Validated @RequestBody SysDept dept)
    {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        if (!deptService.checkDeptNameUnique(dept))
        {
            return error("修改部门'" + dept.getDeptName() + "'失败,部门id已存在");
        }
        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("该部门包含未停用的子部门!");
//        }
        LoginUser loginUser = tokenService.getLoginUser();
        dept.setUpdateBy(loginUser.getNickName());
        if (dept.getStatus().equals("0")){
            dept.setPhone("");
        }
        return AjaxResult.success(deptService.updateDept(dept));
    }
    /**
     * 删除部门
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:remove')")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @ApiOperation(value = "删除",tags = {"后台-部门"})
    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable Long deptId)
    {
        if (deptService.hasChildByDeptId(deptId))
        {
            return warn("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId))
        {
            return warn("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        return AjaxResult.success(deptService.deleteDeptById(deptId));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import javax.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
New file
@@ -0,0 +1,131 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.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
New file
@@ -0,0 +1,29 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
/**
 * 首页
 *
 * @author ruoyi
 */
@RestController
public class SysIndexController
{
    /** 系统基础配置 */
    @Autowired
    private RuoYiConfig ruoyiConfig;
    /**
     * 访问首页,提示语
     */
    @RequestMapping("/")
    public String index()
    {
        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
New file
@@ -0,0 +1,276 @@
package com.ruoyi.web.controller.system;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.TAppUser;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.TAppUserService;
import com.ruoyi.web.controller.tool.MsgUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.origin.SystemEnvironmentOrigin;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
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.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.service.ISysMenuService;
import javax.annotation.Resource;
/**
 * 登录验证
 *
 * @author ruoyi
 */
@Api(tags = "登录")
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private MsgUtils msgUtils;
    /**
     * 账号密码登录
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @ApiOperation(value = "账号密码登录",notes = "账号密码登录")
    @PostMapping("/login")
    public AjaxResult<Map<String,Object>> login(@RequestBody LoginBody loginBody)
    {
        Map<String,Object> map = new HashMap<>();
        // 生成令牌
        LoginUser loginUser = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        map.put(Constants.TOKEN, tokenService.createToken(loginUser));
        List<SysRole> roles = loginUser.getUser().getRoles();
        if(CollectionUtils.isEmpty(roles)){
            return AjaxResult.error("请关联角色!");
        }
        if(roles.get(0).getStatus() == 1){
            return AjaxResult.error("该账号角色已被禁用!");
        }
        List<SysMenu> menus = roleService.roleInfoFromUserId(loginUser.getUserId());
        map.put("menus",menus);
        map.put("roleName",roles.get(0).getRoleName());
        map.put("userInfo",loginUser);
        return AjaxResult.success(map);
    }
    @Resource
    private TAppUserService appUserService;
    @ApiOperation(value = "登录",tags = "web-登录")
    @PostMapping("/applet/login")
    public AjaxResult<Map<String,Object>> appLogin(@RequestBody LoginBody loginBody)
    {
        Map<String,Object> map = new HashMap<>();
        TAppUser one = appUserService.lambdaQuery().eq(TAppUser::getPhone, loginBody.getUsername()).one();
        if (one==null){
            return AjaxResult.error("当前用户不存在,请注册");
        }
        if (one.getStatus()==2){
            return AjaxResult.error("当前用户已被冻结");
        }
        // 生成令牌
        LoginUser loginUser = loginService.appLogin(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        map.put(Constants.TOKEN, tokenService.createToken(loginUser));
        Object cacheObject = redisCache.getCacheObject("CITY:" + one.getId());
        map.put("cityStr",cacheObject);
        if (SecurityUtils.matchesPassword(loginBody.getPassword(), one.getPassword())){
            System.err.println("-----密码正确");
        }else {
            return AjaxResult.error("密码错误");
        }
        return AjaxResult.success(map);
    }
    @ApiOperation(value = "设置城市",tags = "设置城市")
    @PostMapping("/setCity")
    public AjaxResult appLogin(String province,String city)
    {
        Long userId = tokenService.getLoginUser().getUserId();
        redisCache.setCacheObject("CITY:"+userId,province+","+city);
        return AjaxResult.success();
    }
    @ApiOperation(value = "短信登录",tags = "web-登录")
    @PostMapping("/applet/code/login")
    public AjaxResult<Map<String,Object>> codeappLogin(@RequestBody LoginBody loginBody)
    {
        Map<String,Object> map = new HashMap<>();
        // 生成令牌
        LoginUser loginUser = loginService.appLogin(loginBody.getUsername(), null, null,
                loginBody.getUuid());
        map.put(Constants.TOKEN, tokenService.createToken(loginUser));
        String cacheObject = (String)redisCache.getCacheObject(loginBody.getUsername());
        if (!loginBody.getCode().equals(cacheObject)&&!loginBody.getCode().equals("123456")){
            return AjaxResult.error("验证码错误");
        }
        TAppUser one = appUserService.lambdaQuery().eq(TAppUser::getPhone, loginBody.getUsername()).one();
        if (one==null){
            return AjaxResult.error("当前用户不存在,请注册");
        }
        return AjaxResult.success(map);
    }
    @ApiOperation(value = "微信登录",tags = "web-登录")
    @PostMapping("/wx/code/login")
    public AjaxResult<Map<String,Object>> wxcodeappLogin(@RequestBody LoginBody loginBody)
    {
        Map<String,Object> map = new HashMap<>();
        // 生成令牌
        LoginUser loginUser = loginService.appLogin(loginBody.getUsername(), null, null,
                loginBody.getUuid());
        map.put(Constants.TOKEN, tokenService.createToken(loginUser));
        TAppUser one = appUserService.lambdaQuery().eq(TAppUser::getPhone, loginBody.getUsername()).one();
        if (one==null){
            return AjaxResult.error("当前用户不存在,请注册");
        }
        return AjaxResult.success(map);
    }
    @ApiOperation(value = "test",notes = "test")
    @PostMapping("/applet/test")
    public R appLogin()
    {
        Long userId = tokenService.getLoginUser().getUserId();
        System.err.println("=========="+userId);
        return  R.ok();
    }
    /**
     * 账号密码登录
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @ApiOperation(value = "短信登录",notes = "短信登录")
    @PostMapping("/loginCode")
    public AjaxResult loginCode(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        LoginUser loginUser = loginService.loginCode(loginBody.getUsername(), loginBody.getCode());
        ajax.put(Constants.TOKEN, tokenService.createToken(loginUser));
        List<SysRole> roles = loginUser.getUser().getRoles();
        if(CollectionUtils.isEmpty(roles)){
            return AjaxResult.error("请关联角色!");
        }
        List<SysMenu> menus = roleService.roleInfoFromUserId(loginUser.getUserId());
        ajax.put("menus",menus);
        ajax.put("roleName",roles.get(0).getRoleName());
        ajax.put("userInfo",loginUser);
        return ajax;
    }
    /**
     * 获取验证码
     *
     * @param phone 手机号
     * @return 结果
     */
    @ApiOperation(value = "获取验证码",notes = "获取验证码")
    @GetMapping("/getCode")
    public AjaxResult getCode(@RequestParam String phone)
    {
        // 发送验证码并存储到redis
        if (StringUtils.hasLength(phone)) {
            String code = String.valueOf((int) (Math.random() * 1000000));
            redisCache.setCacheObject(phone, code,5*60,TimeUnit.SECONDS);
            try {
                msgUtils.sendMsg(phone, code);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return AjaxResult.success("发送短信验证码成功!5分钟内有效");
        }
        return AjaxResult.error(500, "发送短信验证码失败,请确认手机号码!");
    }
    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }
    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
New file
@@ -0,0 +1,168 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
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
 */
@Api(tags = "菜单信息")
@RestController
@RequestMapping("/system/menu")
public class SysMenuController extends BaseController
{
    @Autowired
    private ISysMenuService menuService;
    @ApiOperation("菜单权限(有层级)")
    @GetMapping("/levelList")
    public AjaxResult levelList()
    {
        // 获取当前角色的菜单列表
        List<SysMenu> menus = menuService.selectList();
        if(menus.size()==0){
            return AjaxResult.success(new ArrayList<>());
        }
        // 第三级
        List<SysMenu> s3 = menus.stream().filter(e -> e.getMenuType().equals("F")).collect(Collectors.toList());
        // 第二级
        List<SysMenu> s2 = menus.stream().filter(e -> e.getMenuType().equals("C")).collect(Collectors.toList());
        // 第一级
        List<SysMenu> s1 = menus.stream().filter(e -> e.getMenuType().equals("M")).collect(Collectors.toList());
        for (SysMenu menu : s2) {
            List<SysMenu> collect = s3.stream().filter(e -> e.getParentId().equals(menu.getMenuId())).collect(Collectors.toList());
            menu.setChildren(collect);
        }
        for (SysMenu menu : s1) {
            List<SysMenu> collect = s2.stream().filter(e -> e.getParentId().equals(menu.getMenuId())).collect(Collectors.toList());
            menu.setChildren(collect);
        }
        return AjaxResult.success(s1);
    }
    /**
     * 获取菜单列表
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @GetMapping("/list")
    public AjaxResult list(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return AjaxResult.success(menus);
    }
    /**
     * 根据菜单编号获取详细信息
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:query')")
    @GetMapping(value = "/{menuId}")
    public AjaxResult getInfo(@PathVariable Long menuId)
    {
        return AjaxResult.success(menuService.selectMenuById(menuId));
    }
    /**
     * 获取菜单下拉树列表
     */
    @GetMapping("/treeselect")
    public AjaxResult treeselect(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
    }
    /**
     * 加载对应角色菜单列表树
     */
    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
    {
        List<SysMenu> menus = menuService.selectMenuList(getUserId());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
        return ajax;
    }
    /**
     * 新增菜单
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:add')")
    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysMenu menu)
    {
        if (!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)://开头");
        }
        menu.setCreateBy(getUsername());
        return AjaxResult.success(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() + "'失败,上级菜单不能选择自己");
        }
        menu.setUpdateBy(getUsername());
        return AjaxResult.success(menuService.updateMenu(menu));
    }
    /**
     * 删除菜单
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:remove')")
    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{menuId}")
    public AjaxResult remove(@PathVariable("menuId") Long menuId)
    {
        if (menuService.hasChildByMenuId(menuId))
        {
            return warn("存在子菜单,不允许删除");
        }
        if (menuService.checkMenuExistRole(menuId))
        {
            return warn("菜单已分配,不允许删除");
        }
        return AjaxResult.success(menuService.deleteMenuById(menuId));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
New file
@@ -0,0 +1,91 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeService;
/**
 * 公告 信息操作处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController
{
    @Autowired
    private ISysNoticeService noticeService;
    /**
     * 获取通知公告列表
     */
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysNotice notice)
    {
//        startPage();
        List<SysNotice> list = noticeService.selectNoticeList(notice);
        return getDataTable(list);
    }
    /**
     * 根据通知公告编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:notice:query')")
    @GetMapping(value = "/{noticeId}")
    public AjaxResult getInfo(@PathVariable Long noticeId)
    {
        return 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));
    }
    /**
     * 删除通知公告
     */
    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/{noticeIds}")
    public AjaxResult remove(@PathVariable Long[] noticeIds)
    {
        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
New file
@@ -0,0 +1,129 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.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
New file
@@ -0,0 +1,136 @@
package com.ruoyi.web.controller.system;
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.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
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("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
        {
            return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        if (userService.updateUserProfile(currentUser) > 0)
        {
            // 更新缓存用户信息
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改个人信息异常,请联系管理员");
    }
    /**
     * 重置密码
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/updatePwd")
    public AjaxResult updatePwd(String oldPassword, String newPassword)
    {
        LoginUser loginUser = getLoginUser();
        String userName = loginUser.getUsername();
        String password = loginUser.getPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password))
        {
            return error("修改密码失败,旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password))
        {
            return error("新密码不能与旧密码相同");
        }
        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
        {
            // 更新缓存用户密码
            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(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);
            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
            {
                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
New file
@@ -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
New file
@@ -0,0 +1,345 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.system.dto.SysRoleDTO;
import com.ruoyi.system.query.SysRoleQuery;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.vo.RoleInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.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
 */
@Api(tags = "角色信息")
@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;
    @Autowired
    private ISysMenuService menuService;
    // @PreAuthorize("@ss.hasPermi('system:role:list')")
    @ApiOperation(value = "角色列表")
    @PostMapping("/list")
    public AjaxResult list(@RequestBody SysRoleQuery query)
    {
        PageInfo<SysRole> list = roleService.selectList(query);
        return AjaxResult.success(list);
    }
    @ApiOperation(value = "角色列表不分页")
    @PostMapping("/listNotPage")
    public AjaxResult list()
    {
        List<SysRole> list = roleService.selectRoleList(new SysRole());
        return AjaxResult.success(list);
    }
    @ApiOperation(value = "角色数量统计")
    @PostMapping("/roleCount")
    public AjaxResult roleCount()
    {
        int all = roleService.selectCount(null);
        int normal = roleService.selectCount(0);
        int stop = roleService.selectCount(1);
        Map<String,Integer> map = new HashMap<>();
        map.put("all",all);
        map.put("normal",normal);
        map.put("stop",stop);
        return AjaxResult.success(map);
    }
//    @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 AjaxResult.success(roleService.selectRoleById(roleId));
    }
    @ApiOperation("角色详情")
    @GetMapping("/roleInfo")
    public AjaxResult roleInfo(@RequestParam Long roleId)
    {
        SysRole role = roleService.selectRoleById(roleId);
        RoleInfoVO roleInfoVo = new RoleInfoVO();
        roleInfoVo.setRoleId(role.getRoleId());
        roleInfoVo.setRoleName(role.getRoleName());
        roleInfoVo.setRemark(role.getRemark());
        // 获取当前角色的菜单列表
        List<SysMenu> menus = menuService.selectListByRoleId(roleId);
        if(menus.size()==0){
            return AjaxResult.success(new ArrayList<>());
        }
        List<Long> menusId = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
        // 获取当前的权限菜单(有层级)
        List<SysMenu> levelMenus = roleService.getMenuLevelList(menusId);
        roleInfoVo.setMenus(menusId);
        return AjaxResult.success(roleInfoVo);
    }
    @ApiOperation("用户获取权限菜单")
    @GetMapping("/roleInfoFromUserId")
    public AjaxResult roleInfoFromUserId(@RequestParam Long userId)
    {
        return AjaxResult.success(roleService.roleInfoFromUserId(userId));
    }
    /**
     * 新增角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:add')")
    @ApiOperation(value = "新增角色")
    @Log(title = "角色信息-新增角色", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody SysRoleDTO dto)
    {
        Boolean flag= roleService.isExit(dto.getRoleId(),dto.getRoleName());
        if(flag){
            return error("新增角色'" + dto.getRoleName() + "'失败,角色名称已存在");
        }
        roleService.saveRole(dto);
        return AjaxResult.success();
    }
    /**
     * 修改保存角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @ApiOperation(value = "编辑角色")
    @Log(title = "角色信息-编辑角色", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysRoleDTO dto)
    {
        Boolean flag= roleService.isExit(dto.getRoleId(),dto.getRoleName());
        if (flag){
            return error("修改角色'" + dto.getRoleName() + "'失败,角色名称已存在");
        }
        SysRole sysRole = roleService.selectRoleById(dto.getRoleId());
        if("meal".equals(sysRole.getRoleKey()) || "sale".equals(sysRole.getRoleKey()) || "admin".equals(sysRole.getRoleKey())){
            return error("当前角色无法修改");
        }
        if (roleService.editRole(dto) > 0)
        {
            // 更新缓存用户权限
            LoginUser loginUser = getLoginUser();
            if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
            {
                loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
                loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
                tokenService.setLoginUser(loginUser);
            }
            return AjaxResult.success();
        }
        return error("修改角色'" + dto.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 AjaxResult.success(roleService.authDataScope(role));
    }
    /**
     * 状态修改
     */
    // @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @ApiOperation(value = "状态修改")
    @Log(title = "角色信息-角色状态修改", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysRole role)
    {
        SysRole sysRole = roleService.selectRoleById(role.getRoleId());
        if("meal".equals(sysRole.getRoleKey()) || "sale".equals(sysRole.getRoleKey()) || "admin".equals(sysRole.getRoleKey())){
            return error("当前角色无法修改状态");
        }
        role.setUpdateBy(getUsername());
        roleService.updateStatus(role);
        return AjaxResult.success();
    }
    /**
     * 删除角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:remove')")
    @ApiOperation(value = "批量删除角色")
    @Log(title = "角色信息-角色删除角色", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteById")
    public AjaxResult remove( Long id)
    {
        SysRole sysRole = roleService.selectRoleById(id);
        if("meal".equals(sysRole.getRoleKey()) || "sale".equals(sysRole.getRoleKey()) || "admin".equals(sysRole.getRoleKey())){
            return error("当前角色无法删除");
        }
        return AjaxResult.success(roleService.deleteRoleById(id));
    }
    /**
     * 删除角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:remove')")
    @ApiOperation(value = "批量删除角色")
    @Log(title = "角色信息-角色删除角色", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteById/{ids}")
    public AjaxResult remove(@PathVariable String ids)
    {
        String[] split = ids.split(",");
        List<Long> id = new ArrayList<>();
        for (String s : split) {
            id.add(Long.valueOf(s));
        }
        return AjaxResult.success(roleService.deleteRoleByIds(id));
    }
    /**
     * 获取角色选择框列表
     */
    // @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        return AjaxResult.success(roleService.selectRoleAll());
    }
    /**
     * 查询已分配用户角色列表
     */
    // @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/allocatedList")
    public TableDataInfo allocatedList(SysUser user)
    {
//        startPage();
        List<SysUser> list = userService.selectAllocatedList(user);
        return getDataTable(list);
    }
    /**
     * 查询未分配用户角色列表
     */
    // @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/unallocatedList")
    public TableDataInfo unallocatedList(SysUser user)
    {
//        startPage();
        List<SysUser> list = userService.selectUnallocatedList(user);
        return getDataTable(list);
    }
    /**
     * 取消授权用户
     */
    // @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancel")
    public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
    {
        return AjaxResult.success(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 AjaxResult.success(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 AjaxResult.success(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
New file
@@ -0,0 +1,336 @@
package com.ruoyi.web.controller.system;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
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.domain.model.LoginUser;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.dto.SysUserUpdateStatusDTO;
import com.ruoyi.system.dto.UpdatePwdDTO;
import com.ruoyi.system.query.SysUserQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.SysUserVO;
import com.ruoyi.system.vo.UserAddListVO;
import com.ruoyi.system.vo.UserLevelVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 用户信息
 *
 * @author ruoyi
 */
@Api(tags = "用户信息")
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private TokenService tokenService;
    /**
     * 获取用户列表
     */
    @ApiOperation(value = "获取用户列表")
    @PostMapping("/list")
    public AjaxResult<PageInfo<SysUserVO>> list(@RequestBody SysUserQuery query)
    {
        PageInfo<SysUserVO> list = userService.pageList(query);
        return AjaxResult.success(list);
    }
    @ApiOperation(value = "获取用户列表-不分页")
    @PostMapping("/listNotPage")
    public AjaxResult<List<SysUser>> listNotPage()
    {
        List<SysUser> list = userService.selectList();
        return AjaxResult.success(list);
    }
    /**
     * 获取用户黑名单列表
     */
//    @ApiOperation(value = "获取用户黑名单列表")
//    @PostMapping("/blacklist")
//    public AjaxResult blacklist(@RequestBody SysUserQuery query)
//    {
//        startPage(query.getPageNum(), query.getPageSize());
//        List<SysUserVO> list = userService.selectBlackPageList(query);
//        return AjaxResult.success(getDataTable(list));
//    }
    /**
     * 获取用户详情
     */
    @ApiOperation(value = "获取用户详情")
    @GetMapping("/getDetail")
    public AjaxResult<SysUser> getDetail(@RequestParam Long userId)
    {
        SysUser sysUser = userService.selectUserById(userId);
        SysUserVO sysUserVO = new SysUserVO();
        BeanUtils.copyProperties(sysUser,sysUserVO);
        return AjaxResult.success(sysUser);
    }
    /**
     * 获取用户数量统计
     */
    @ApiOperation(value = "获取用户数量统计")
    @PostMapping("/getUserCount")
    public AjaxResult<Map<String,Integer>> getUserCount()
    {
        Map<String,Integer> map = new HashMap<>();
        Integer userCountSum = userService.selectCount(null);
        Integer normalCount = userService.selectCount(0);// 正常
        Integer stopCount = userService.selectCount(1);// 停用
        map.put("all",userCountSum);
        map.put("normal",normalCount);
        map.put("stop",stopCount);
        return AjaxResult.success(map);
    }
    /**
     * 移除黑名单
     */
//    @GetMapping("/removeBlackList")
//    public AjaxResult<String> removeBlackList(@RequestParam String ids)
//    {
//        String[] split = ids.split(",");
//        List<Long> id = new ArrayList<>();
//        for (String s : split) {
//            id.add(Long.valueOf(s));
//        }
//        userService.updateUserIfBlack(id);
//        return AjaxResult.success();
//    }
//    @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 AjaxResult.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:add')")
    @ApiOperation(value = "新增用户管理")
    @Log(title = "用户信息-新增用户", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody SysUser user)
    {
        if (!userService.checkUserNameUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        user.setPassword("123456");
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        userService.insertUser(user);
        return AjaxResult.success();
    }
    /**
     * 修改用户
     */
    // @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @ApiOperation(value = "修改用户管理")
    @Log(title = "用户信息-修改用户", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    public AjaxResult edit(@Validated @RequestBody SysUser user)
    {
//        userService.checkUserAllowed(user);
//        userService.checkUserDataScope(user.getUserId());
        if (!userService.checkUserNameUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        LoginUser loginUser = tokenService.getLoginUser();
        user.setUpdateName(loginUser.getNickName());
        user.setUpdateBy(getUsername());
//        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        return AjaxResult.success(userService.updateUser(user));
    }
    /**
     * 删除用户
     */
    // @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @ApiOperation(value = "批量删除用户")
    @Log(title = "用户信息-批量删除用户", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteById/{ids}")
    public AjaxResult remove(@PathVariable String ids)
    {
        String[] split = ids.split(",");
        List<Long> userIds = new ArrayList<>();
        for (String s : split) {
            userIds.add(Long.valueOf(s));
        }
        if (userIds.contains(getUserId()))
        {
            return error("当前用户不能删除");
        }
        return AjaxResult.success(userService.deleteUserByIds(userIds));
    }
    /**
     * 重置密码
     */
    // @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @ApiOperation(value = "重置密码")
    @Log(title = "用户信息-重置密码", businessType = BusinessType.UPDATE)
    @PostMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
//        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return AjaxResult.success(userService.resetPwd(user));
    }
    /**
     * 修改密码
     */
    // @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @ApiOperation(value = "修改密码")
    @Log(title = "用户信息-修改密码", businessType = BusinessType.UPDATE)
    @PostMapping("/updatePwd")
    public AjaxResult updatePwd(@RequestBody UpdatePwdDTO dto)
    {
        SysUser user = userService.selectUserByUserName(dto.getAccount());
        if(Objects.isNull(user)){
            return AjaxResult.error("未查询到该账号");
        }
        userService.checkUserAllowed(user);
        // 校验密码跟原密码是否匹配
//        if (!SecurityUtils.matchesPassword(dto.getOldPassword(), user.getPassword())) {
//            throw new BadCredentialsException("输入原密码不正确");
//        }
        if (!dto.getPassword().equals(dto.getConfirmPassword())) {
            throw new BadCredentialsException("两次输入密码不一致");
        }
//        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(dto.getPassword()));
        user.setUpdateBy(getUsername());
        return AjaxResult.success(userService.resetPwd(user));
    }
    /**
     * 状态修改
     */
    @ApiOperation(value = "状态修改")
    @Log(title = "用户信息-状态修改", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUserUpdateStatusDTO dto)
    {
        SysUser user = new SysUser();
        user.setUserId(dto.getUserId());
        user.setStatus(String.valueOf(dto.getStatus()));
        user.setDisableRemark(dto.getDisableRemark());
        user.setUpdateBy(getUsername());
        return AjaxResult.success(userService.updateUserStatus(user));
    }
    /**
     * 根据用户编号获取授权角色
     */
    // @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId)
    {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }
    /**
     * 用户授权角色
     */
    // @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
    {
        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return AjaxResult.success();
    }
    /**
     * 获取部门树列表
     */
    // @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept)
    {
        return AjaxResult.success(deptService.selectDeptTreeList(dept));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/AlipayTradePagePay.java
New file
@@ -0,0 +1,171 @@
package com.ruoyi.web.controller.tool;
import com.alipay.api.*;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
public class AlipayTradePagePay {
    public static String  pay(String title,String code,String money) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
        // 构造请求参数以调用接口
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        // 设置订单标题
        model.setSubject(title);
        // 设置产品码
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        // 设置PC扫码支付的方式
        model.setQrPayMode("3");
        // 设置商户订单号
        model.setOutTradeNo(code);
        // 设置订单总金额
        model.setTotalAmount(money);
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
        AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "POST");
        // 如果需要返回GET请求,请使用
        // AlipayTradePagePayResponse response = alipayClient.pageExecute(request, "GET");
        String pageRedirectionData = response.getBody();
        System.out.println(pageRedirectionData);
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
        return pageRedirectionData;
    }
    public static void refund(String money,String outNo) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
        // 构造请求参数以调用接口
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        // 设置商户订单号
        model.setOutTradeNo(outNo);
        // 设置退款金额
        model.setRefundAmount(money);
        // 设置退款原因说明
        model.setRefundReason("正常退款");
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
    }
    public static void main(String[] args) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
        // 构造请求参数以调用接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        // 设置订单支付时传入的商户订单号
        model.setOutTradeNo("KC202410241014151729736055081");
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
        }
    }
    private static AlipayConfig getAlipayConfig() throws AlipayApiException {
       String privateKey  = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCMfMyRu0w45qXmyw2KdUCX+gE+mT9lPFahJwkWHVQMh7M0tiU3H7sFFG40+VLK8sBfBhtzkogasJ6en/WYEzIC0iRw0s1jj12Ja06Xy67+h4dlB97489Hc1YOcQ+14ZatGkZUhtjJ51pw77cEjKZ+/9Xx2P2mWUI7FPpGwSJmBI4gBO7Mu3qcQ5e0RqIdqXKOvnk4pA98SUeYHfWN/XIzqI1UAzyuY/wZuIzKvTdgWtC41oidf0ngZua7HLr8cJrndPIu1YALs7L4RgPSjL/5HDAQ991QwAs4ByRGEStx2HZ/o6CddZ8x831GGEtCI3q1tn+7OJrcCzt803iVTys+ZAgMBAAECggEAOfj14d1MYt6q70YzXENuWEiOYuqSQpBXn0Cge0O2/0SwKrxPNyQc5Me9gpawF5d80rmOcm6xQ3JGwmZ3zj19kbRt3TDgGIl8q8xgLjubBuWedY598HWM0Hg7SyysvdYWi5Rf2f15btWkuwYtgPkYNvpyVcltJN4xTCu5qukKj0Mhgxtp7/rnAFYtJSf/2GlL1jEhiE2nmcVLX7qBUG4k4jwcQal7Y+dNhoU7ZT4d5kYnZQ3tT/nHXDJSlj/uZAjKMAw5EGSKw4gnfCg2vqo9uF/ni0JxbwV1oC4mfGK3JQv4ZcszIlo25laRPRNsIxlPRF9uhVKEBq3L7O5i+ZzBUQKBgQDIxpYOuxL7VUIIa1WRKDl4YuxcM6QgX6V5L9UnidCwo72IhT6CkPQVu8uHx55qPI8UpVhbYYrxYH5xCYoZ0+fK6LRK9wMJUjL6Gg/HjXTbGyzcIoIaJ0JA4hHPD2onrWbNWwjylTzu1w4opWArexD6rX8WavS3mfZC04fw6oRZ5wKBgQCzIRR2CVnvtNnzAa36YbSQviCMlRfNxfnPDXHGjWMReHuMDxFQHPTGsB7HA8QmIjM1GTFaHhgNAl6BGIgDo+KPwbIVFJCXiQ2k4Il+znYRxFXmTqGsOARl19oIFXLUI0sy3TOFYVDBjBfk4ICTpn8IKACOvAPUFOJHid4P/GFafwKBgQC6pMHCl+4hbzSflwhIlNg4Ld4EKI2e+stdSTYiN1+lldIQI63kutPtkFK4ur1tjTaFvt/Qs3Dyyv1AH9oeAHwuiP1x4wcTlzKEhc29eKb1OOIPEpVXsr9IieB8WJwannw+0y4SNOIcNheXeYVZZmJ2ZusJ8Avm0l236eUp9RlsaQKBgHPFvIixcIwpkfeqLTy3K1GlYDocHl9jRhpZMSDHvrDK8ubJ0kG6BUXpDGtJ9ttCnWADIU+CRb8aueOr7DSWFlcdNDDFstINxWC7soHfhJXlFDOevIUnS0hbYtJ4sleDXBXKu4LIK758AfFuXAuRv2aRHBMkV0EaIklkRL6GOpGXAoGBAKbNBXmOqTxl6bKD9Jlpcn6Kq06feK7dzRoGdG3x1eY6DrJu40Wsi71QYSz5MLTxcJLNIfnuMoQPPQrPcX98GCy0OnVH7KLMoztEs15TlHPJF1BQAJlHhmzwHB5UNpC2fP6x9WaAow0YD7/BL59QLH989+baFdw4ZmQk2iEF5u2b";
        String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjHzMkbtMOOal5ssNinVAl/oBPpk/ZTxWoScJFh1UDIezNLYlNx+7BRRuNPlSyvLAXwYbc5KIGrCenp/1mBMyAtIkcNLNY49diWtOl8uu/oeHZQfe+PPR3NWDnEPteGWrRpGVIbYyedacO+3BIymfv/V8dj9pllCOxT6RsEiZgSOIATuzLt6nEOXtEaiHalyjr55OKQPfElHmB31jf1yM6iNVAM8rmP8GbiMyr03YFrQuNaInX9J4Gbmuxy6/HCa53TyLtWAC7Oy+EYD0oy/+RwwEPfdUMALOAckRhErcdh2f6OgnXWfMfN9RhhLQiN6tbZ/uzia3As7fNN4lU8rPmQIDAQAB";
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId("2021004184657725");
        alipayConfig.setPrivateKey(privateKey);
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(alipayPublicKey);
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        return alipayConfig;
//
//        AlipayConfig alipayConfig = new AlipayConfig();
////设置网关地址
//        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
////设置应用APPID
//        alipayConfig.setAppId("2021004184657725");
////设置应用私钥
//        alipayConfig.setPrivateKey("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCgySquVPl9gQCBvyQHLkdXIDhBDLJ0bhzr4SPxWGjw4M+HpAl0tlBypksxCcOWqMi9b2DOVI8sUB6wIRDYRajOpPMiMTb93DZNSSXOn4lh+kX1y5LOaT1MQ92GyGRdjWLG4NOF+Zrdy1+zaoYmE64IUE/xBOV4C5uVMyHnFqcH2aqGXKUE4wW1rrX2FoMgkqunFh6kUVPKWlLzXH3dTvI5kSZPHW/G5e+XQ4eoRDv8hj0Sn3BhL71nHEsvR6lvfV97Ra498kWQGChl/ypHJaxBqJVn/4TFJEG/Dzsr4sF5UuO1UInEobZ+u20rEyse3E51Ww+mfGFD+5a1dXco/ER5AgMBAAECggEAa/3xrtngIM2ue3bYSgJpZDl9zyMqEU2MG1pCe+23vmIgwagJudxiOD89LZizR9Ph0GqoiKz+5PKDSiVLXRecg/8CVqrblrJ7vnks7ZT1/1rL9oVe+0hwJXNHrSmXT8aQ26dSKyA1Rlc81hLsO1Lohyj6KJXzUifpvdJ0KPRsB7azThYw/FZ+Raphgm91UD5fLb0RjDHPD239pLLDn8QjFYu4JWRw/NOpI8/svnnONV9P4mPjhBalG48f4Qg0ToiZXjqZb2N3pox5zLjcYx+MYhfA/1P9rG3DWMnnCQVM1x83u80tNAi6PKC4SNSxldRANQJ8QSviOTrhhVNmd3QJoQKBgQD2K8DsvNbL+L/rxMiMVd6KHOkyxr/W81TgLqOTJrT0blMWbStDEH4D4J8pA9+oaf9+kV5hcC3M8lI+CstVb2zrIfjksF96Imt0xfrpb2le/0dfeQv7c8Jg7JMsrHluNwPYdOFDR1o4Z+7hQr0MuqSQIgGA1y+HmzLPBROEynX6vQKBgQCnNKVJUxDf5/06vDoQVigi6WD0I82+Y3GL1J7QS3nQPBlmqNfQsvuDrvWCL564B9V4n7ryTfdn3XXyS73pNMj6lZkvhwIIhHvD9eOP4StOGU7HpdpBTd90TsjHm/0DNTYT2miXzIOgWQ8HB90uuB4SggALmHrJdi4uFLAuoKuqbQKBgQClikC/MjHjklBFVNxj+q6fA9gRzDNfcdymsNZQ8xuGr9Xx49HO1H1ZUCjXpQI3N6iXTVxBe/Vgt6d0jz+zIS4GZJ8B8lUSRakrKqOTbNdYCaTOYBEds/eHxC8oQIecBSTx349H9eiGu+WY149Xyv806ZlHMe2FbGlba5d3mcqCpQKBgBYEkrdjHte9PtVbL/IyxjpCrSe5B0DI64zURM19At9u6pFgLnsm9oPSqDWqe6YUMgIeVonNxoSA3yU24B0zfDuzM2bUymnAuGOHn520svUn0/3qUyFCVeiE71+JpPmlKifXHOrQXYzh7V6ppHCggiVBxSvBunmI/G/I/aJGOhTJAoGBAKpb7Ld1ZLBCq5lvebRUwcbzSDkvq5YmJ9JKkZJo5tH29vSuy8wrCdOG5Dtu7naJTovHRM/qvrcNQoexHPBB2KPqrYPyIrsBHcqQ5WEQ/1aBUh/lNge6bmO4sr2wSrdXTkSCeMtFs4n6KYnvL0pF7Bu8RTGlAXN7MO/oDXo8Vflq");
////设置应用公钥证书路径
//        alipayConfig.setAppCertPath("C:\\Users\\Admin\\Desktop\\2021004184657725\\appCertPublicKey_2021004184657725.crt");
////设置支付宝公钥证书路径
//        alipayConfig.setAlipayPublicCertPath("C:\\Users\\Admin\\Desktop\\2021004184657725\\alipayCertPublicKey_RSA2.crt");
////设置支付宝根证书路径
//        alipayConfig.setRootCertPath("C:\\Users\\Admin\\Desktop\\2021004184657725\\alipayRootCert.crt");
////设置请求格式,固定值json
//        alipayConfig.setFormat("json");
////设置字符集
//        alipayConfig.setCharset("utf-8");
////设置签名类型
//        alipayConfig.setSignType("RSA2");
//
//        String publicKey = AlipaySignature.getAlipayPublicKey("C:\\Users\\Admin\\Desktop\\2021004184657725\\appCertPublicKey_2021004184657725.crt");
//        System.out.println("publicKey:"+publicKey);
//        return alipayConfig;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/AlipayTradeQuery.java
New file
@@ -0,0 +1,76 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.FileItem;
import oshi.driver.mac.net.NetStat;
import java.util.Base64;
import java.util.ArrayList;
import java.util.List;
public class AlipayTradeQuery {
    public static Boolean check(String code) throws AlipayApiException {
        // 初始化SDK
        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
        // 构造请求参数以调用接口
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        // 设置订单支付时传入的商户订单号
        model.setOutTradeNo(code);
        request.setBizModel(model);
        // 第三方代调用模式下请设置app_auth_token
        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        System.out.println(response.getBody());
        if (response.isSuccess()) {
            System.out.println("调用成功");
            System.out.println(JSONObject.parseObject(response.getBody()));
            JSONObject jsonObject = JSONObject.parseObject(response.getBody());
            JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.get("alipay_trade_query_response").toString());
            String tradeStatus = (String) jsonObject1.get("trade_status");
            if (tradeStatus.equals("TRADE_SUCCESS")){
                return true;
            }else {
                return false;
            }
        } else {
            System.out.println("调用失败");
            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
            // System.out.println(diagnosisUrl);
            return false;
        }
    }
    private static AlipayConfig getAlipayConfig() {
        String privateKey  = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCMfMyRu0w45qXmyw2KdUCX+gE+mT9lPFahJwkWHVQMh7M0tiU3H7sFFG40+VLK8sBfBhtzkogasJ6en/WYEzIC0iRw0s1jj12Ja06Xy67+h4dlB97489Hc1YOcQ+14ZatGkZUhtjJ51pw77cEjKZ+/9Xx2P2mWUI7FPpGwSJmBI4gBO7Mu3qcQ5e0RqIdqXKOvnk4pA98SUeYHfWN/XIzqI1UAzyuY/wZuIzKvTdgWtC41oidf0ngZua7HLr8cJrndPIu1YALs7L4RgPSjL/5HDAQ991QwAs4ByRGEStx2HZ/o6CddZ8x831GGEtCI3q1tn+7OJrcCzt803iVTys+ZAgMBAAECggEAOfj14d1MYt6q70YzXENuWEiOYuqSQpBXn0Cge0O2/0SwKrxPNyQc5Me9gpawF5d80rmOcm6xQ3JGwmZ3zj19kbRt3TDgGIl8q8xgLjubBuWedY598HWM0Hg7SyysvdYWi5Rf2f15btWkuwYtgPkYNvpyVcltJN4xTCu5qukKj0Mhgxtp7/rnAFYtJSf/2GlL1jEhiE2nmcVLX7qBUG4k4jwcQal7Y+dNhoU7ZT4d5kYnZQ3tT/nHXDJSlj/uZAjKMAw5EGSKw4gnfCg2vqo9uF/ni0JxbwV1oC4mfGK3JQv4ZcszIlo25laRPRNsIxlPRF9uhVKEBq3L7O5i+ZzBUQKBgQDIxpYOuxL7VUIIa1WRKDl4YuxcM6QgX6V5L9UnidCwo72IhT6CkPQVu8uHx55qPI8UpVhbYYrxYH5xCYoZ0+fK6LRK9wMJUjL6Gg/HjXTbGyzcIoIaJ0JA4hHPD2onrWbNWwjylTzu1w4opWArexD6rX8WavS3mfZC04fw6oRZ5wKBgQCzIRR2CVnvtNnzAa36YbSQviCMlRfNxfnPDXHGjWMReHuMDxFQHPTGsB7HA8QmIjM1GTFaHhgNAl6BGIgDo+KPwbIVFJCXiQ2k4Il+znYRxFXmTqGsOARl19oIFXLUI0sy3TOFYVDBjBfk4ICTpn8IKACOvAPUFOJHid4P/GFafwKBgQC6pMHCl+4hbzSflwhIlNg4Ld4EKI2e+stdSTYiN1+lldIQI63kutPtkFK4ur1tjTaFvt/Qs3Dyyv1AH9oeAHwuiP1x4wcTlzKEhc29eKb1OOIPEpVXsr9IieB8WJwannw+0y4SNOIcNheXeYVZZmJ2ZusJ8Avm0l236eUp9RlsaQKBgHPFvIixcIwpkfeqLTy3K1GlYDocHl9jRhpZMSDHvrDK8ubJ0kG6BUXpDGtJ9ttCnWADIU+CRb8aueOr7DSWFlcdNDDFstINxWC7soHfhJXlFDOevIUnS0hbYtJ4sleDXBXKu4LIK758AfFuXAuRv2aRHBMkV0EaIklkRL6GOpGXAoGBAKbNBXmOqTxl6bKD9Jlpcn6Kq06feK7dzRoGdG3x1eY6DrJu40Wsi71QYSz5MLTxcJLNIfnuMoQPPQrPcX98GCy0OnVH7KLMoztEs15TlHPJF1BQAJlHhmzwHB5UNpC2fP6x9WaAow0YD7/BL59QLH989+baFdw4ZmQk2iEF5u2b";
        String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmmtqSfZPk3pAFp/gqdBDWc9qimhjRMMvPPLTNypQ8CzsTpSx3wLXVCj2LXYKg4zQzZLHtYb7CJajs8gqDmRn1tAY8iViekV8AsTksXJ5fiO67e5JenPFS048/v/xQI8qNtllqY/MzCbZ0QvnATMeLX6Iwi4ZGRzLlL2wEEGfy2DJ2osRd+tIU+9y5EErObEzJdT+yxxVmOvpvJuVqf7NfnrMZj3ijYg+qDQEu6kDhuXrlZvS6MAUsZUiOE3/uQwSws0bD9ROWyYk7Mr7CH+3u0oLQeBweYQVtqRZWERm6Oxa0gxpqJILTL5+9T5hdFGdFV0xrF59Pk4eTeImeUrbIwIDAQAB";
        AlipayConfig alipayConfig = new AlipayConfig();
        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
        alipayConfig.setAppId("2021004184657725");
        alipayConfig.setPrivateKey(privateKey);
        alipayConfig.setFormat("json");
        alipayConfig.setAlipayPublicKey(alipayPublicKey);
        alipayConfig.setCharset("UTF-8");
        alipayConfig.setSignType("RSA2");
        return alipayConfig;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/AlipayTradeRefund.java
New file
@@ -0,0 +1,72 @@
//package com.ruoyi.web.controller.tool;
//
//import com.alipay.api.AlipayApiException;
//import com.alipay.api.AlipayClient;
//import com.alipay.api.DefaultAlipayClient;
//import com.alipay.api.AlipayConfig;
//import com.alipay.api.domain.AlipayTradeRefundModel;
//import com.alipay.api.request.AlipayTradeRefundRequest;
//import com.alipay.api.response.AlipayTradeRefundResponse;
//import com.alipay.api.domain.RefundGoodsDetail;
//import com.alipay.api.domain.OpenApiRoyaltyDetailInfoPojo;
//
//import com.alipay.api.FileItem;
//import java.util.Base64;
//import java.util.ArrayList;
//import java.util.List;
//
//public class AlipayTradeRefund {
//
//    public static void main(String[] args) throws AlipayApiException {
//        // 初始化SDK
//        AlipayClient alipayClient = new DefaultAlipayClient(getAlipayConfig());
//
//        // 构造请求参数以调用接口
//        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
//        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
//
//        // 设置商户订单号
//        model.setOutTradeNo("ZL202410171622411729153361041");
//
//
//
//        // 设置退款金额
//        model.setRefundAmount("0.01");
//
//        // 设置退款原因说明
//        model.setRefundReason("正常退款");
//
//
//
//
//        request.setBizModel(model);
//        // 第三方代调用模式下请设置app_auth_token
//        // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->");
//
//        AlipayTradeRefundResponse response = alipayClient.execute(request);
//        System.out.println(response.getBody());
//        return true;
////        if (response.isSuccess()) {
////            System.out.println("调用成功");
////        } else {
////            System.out.println("调用失败");
////            // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接
////            // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);
////            // System.out.println(diagnosisUrl);
////        }
//    }
//
//    private static AlipayConfig getAlipayConfig() {
//        String privateKey  = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCMfMyRu0w45qXmyw2KdUCX+gE+mT9lPFahJwkWHVQMh7M0tiU3H7sFFG40+VLK8sBfBhtzkogasJ6en/WYEzIC0iRw0s1jj12Ja06Xy67+h4dlB97489Hc1YOcQ+14ZatGkZUhtjJ51pw77cEjKZ+/9Xx2P2mWUI7FPpGwSJmBI4gBO7Mu3qcQ5e0RqIdqXKOvnk4pA98SUeYHfWN/XIzqI1UAzyuY/wZuIzKvTdgWtC41oidf0ngZua7HLr8cJrndPIu1YALs7L4RgPSjL/5HDAQ991QwAs4ByRGEStx2HZ/o6CddZ8x831GGEtCI3q1tn+7OJrcCzt803iVTys+ZAgMBAAECggEAOfj14d1MYt6q70YzXENuWEiOYuqSQpBXn0Cge0O2/0SwKrxPNyQc5Me9gpawF5d80rmOcm6xQ3JGwmZ3zj19kbRt3TDgGIl8q8xgLjubBuWedY598HWM0Hg7SyysvdYWi5Rf2f15btWkuwYtgPkYNvpyVcltJN4xTCu5qukKj0Mhgxtp7/rnAFYtJSf/2GlL1jEhiE2nmcVLX7qBUG4k4jwcQal7Y+dNhoU7ZT4d5kYnZQ3tT/nHXDJSlj/uZAjKMAw5EGSKw4gnfCg2vqo9uF/ni0JxbwV1oC4mfGK3JQv4ZcszIlo25laRPRNsIxlPRF9uhVKEBq3L7O5i+ZzBUQKBgQDIxpYOuxL7VUIIa1WRKDl4YuxcM6QgX6V5L9UnidCwo72IhT6CkPQVu8uHx55qPI8UpVhbYYrxYH5xCYoZ0+fK6LRK9wMJUjL6Gg/HjXTbGyzcIoIaJ0JA4hHPD2onrWbNWwjylTzu1w4opWArexD6rX8WavS3mfZC04fw6oRZ5wKBgQCzIRR2CVnvtNnzAa36YbSQviCMlRfNxfnPDXHGjWMReHuMDxFQHPTGsB7HA8QmIjM1GTFaHhgNAl6BGIgDo+KPwbIVFJCXiQ2k4Il+znYRxFXmTqGsOARl19oIFXLUI0sy3TOFYVDBjBfk4ICTpn8IKACOvAPUFOJHid4P/GFafwKBgQC6pMHCl+4hbzSflwhIlNg4Ld4EKI2e+stdSTYiN1+lldIQI63kutPtkFK4ur1tjTaFvt/Qs3Dyyv1AH9oeAHwuiP1x4wcTlzKEhc29eKb1OOIPEpVXsr9IieB8WJwannw+0y4SNOIcNheXeYVZZmJ2ZusJ8Avm0l236eUp9RlsaQKBgHPFvIixcIwpkfeqLTy3K1GlYDocHl9jRhpZMSDHvrDK8ubJ0kG6BUXpDGtJ9ttCnWADIU+CRb8aueOr7DSWFlcdNDDFstINxWC7soHfhJXlFDOevIUnS0hbYtJ4sleDXBXKu4LIK758AfFuXAuRv2aRHBMkV0EaIklkRL6GOpGXAoGBAKbNBXmOqTxl6bKD9Jlpcn6Kq06feK7dzRoGdG3x1eY6DrJu40Wsi71QYSz5MLTxcJLNIfnuMoQPPQrPcX98GCy0OnVH7KLMoztEs15TlHPJF1BQAJlHhmzwHB5UNpC2fP6x9WaAow0YD7/BL59QLH989+baFdw4ZmQk2iEF5u2b";
//        String alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjHzMkbtMOOal5ssNinVAl/oBPpk/ZTxWoScJFh1UDIezNLYlNx+7BRRuNPlSyvLAXwYbc5KIGrCenp/1mBMyAtIkcNLNY49diWtOl8uu/oeHZQfe+PPR3NWDnEPteGWrRpGVIbYyedacO+3BIymfv/V8dj9pllCOxT6RsEiZgSOIATuzLt6nEOXtEaiHalyjr55OKQPfElHmB31jf1yM6iNVAM8rmP8GbiMyr03YFrQuNaInX9J4Gbmuxy6/HCa53TyLtWAC7Oy+EYD0oy/+RwwEPfdUMALOAckRhErcdh2f6OgnXWfMfN9RhhLQiN6tbZ/uzia3As7fNN4lU8rPmQIDAQAB";
//        AlipayConfig alipayConfig = new AlipayConfig();
//        alipayConfig.setServerUrl("https://openapi.alipay.com/gateway.do");
//        alipayConfig.setAppId("2021004184657725");
//        alipayConfig.setPrivateKey(privateKey);
//        alipayConfig.setFormat("json");
//        alipayConfig.setAlipayPublicKey(alipayPublicKey);
//        alipayConfig.setCharset("UTF-8");
//        alipayConfig.setSignType("RSA2");
//        return alipayConfig;
//    }
//}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/BaiDuApi.java
New file
@@ -0,0 +1,182 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
 * 百度文字识别
 */
@Slf4j
public class BaiDuApi {
    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
    public static void main(String []args) throws IOException{
//        String url = "C:\\Users\\Admin\\Desktop\\picture\\6fd629ac-3327-4bdc-9459-fcb5295384bc.jpg";
        String url = "C:\\Users\\Admin\\Desktop\\picture\\6fd629ac-3327-4bdc-9459-fcb5295384bc.jpg";
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
//        System.err.println(response.body().string());
        Map<String,Object> map = new HashMap<>();
        String string = response.body().string();
        String idCard = string.substring(string.lastIndexOf("单号:") + 3, string.lastIndexOf("单号:") + 27);
        String time = string.substring(string.lastIndexOf("零时起") + 3, string.lastIndexOf("二十四时")-1);
        time = time.replace(".","-");
        map.put("idCard",idCard);
        map.put("time",time);
        System.err.println(map);
    }
    /**
     * 资质证明证件识别
     * @param url
     * @return
     * @throws IOException
     */
    public static Map<String,Object> qualification(String url) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        Map<String,Object> map = new HashMap<>();
        try{
            String string = response.body().string();
            String idCard = string.substring(string.lastIndexOf("号:") + 2, string.lastIndexOf("号:") + 21);
            String time = string.substring(string.lastIndexOf("至") + 1, string.lastIndexOf("至") + 11);
            time = time.replace(".","-");
            map.put("idCard",idCard);
            map.put("time",time);
        }catch (Exception e){
            log.error("资质证明证件识别错误!");
            throw new ServiceException("资质证明证件识别错误!");
        }
        return map;
    }
    /**
     * 身份证识别
     * @param url
     * @return
     * @throws IOException
     */
    public static Map<String,Object> idCard(String url) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        Map<String,Object> map = new HashMap<>();
        try{
            JSONObject jsonObject = JSONObject.parseObject(response.body().string());
            JSONArray jsonArray = JSONObject.parseArray(jsonObject.getString("words_result"));
            JSONObject obj1 = JSONObject.parseObject(jsonArray.get(0).toString());
            String name = obj1.getString("words");
            name = name.substring(2);
            JSONObject obj2 = JSONObject.parseObject(jsonArray.get(1).toString());
            String sexStr = obj2.getString("words");
            sexStr = sexStr.substring(2, 3);
            int sex = "男".equals(sexStr)?0:1;
            JSONObject obj3 = JSONObject.parseObject(jsonArray.get(3).toString());
            JSONObject obj4 = JSONObject.parseObject(jsonArray.get(4).toString());
            String address = obj3.getString("words") + obj4.getString("words");
            address = address.substring(2);
            JSONObject obj5 = JSONObject.parseObject(jsonArray.get(5).toString());
            String idCard = obj5.getString("words");
            idCard = idCard.substring(6);
            map.put("name",name);
            map.put("sex",sex);
            map.put("address",address);
            map.put("idCard",idCard);
        }catch (Exception e){
            log.error("身份证件识别错误!");
            throw new ServiceException("身份证件识别错误!");
        }
        return map;
    }
    /**
     * 通用文字识别(标准版)
     * @param url
     * @return
     * @throws IOException
     */
    public static JSONObject pictureOcr(String url) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        return JSONObject.parseObject(response.body().string());
    }
    public static String getAccessToken() throws IOException {
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "");
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token?client_id=2RkKEqd0ltIHPvnIf3G0VpHE&client_secret=RBpPt3O64e3e4BK7pG3lP0o8I6SGgiUy&grant_type=client_credentials")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject jsonObject = JSONObject.parseObject(response.body().string());
        return jsonObject.getString("access_token");
    }
    /**
     * 获取文件base64编码
     *
     * @param path      文件路径
     * @param urlEncode 如果Content-Type是application/x-www-form-urlencoded时,传true
     * @return base64编码信息,不带文件头
     * @throws IOException IO异常
     */
    static String getFileContentAsBase64(String path, boolean urlEncode) throws IOException {
        byte[] b = Files.readAllBytes(Paths.get(path));
        String base64 = Base64.getEncoder().encodeToString(b);
        if (urlEncode) {
            base64 = URLEncoder.encode(base64, "utf-8");
        }
        return base64;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HttpClientUtil.java
New file
@@ -0,0 +1,147 @@
package com.ruoyi.web.controller.tool;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * @author zhy
 * @title: HttpClientUtil
 * @projectName car_park
 * @description: http连接工具类
 * @date 2019/10/2219:23
 */
public class HttpClientUtil {
    private static PoolingHttpClientConnectionManager connectionManager;
    {
        //1.创建连接池管理器
        connectionManager = new PoolingHttpClientConnectionManager(60000,
                TimeUnit.MILLISECONDS);
        connectionManager.setMaxTotal(1000);
        connectionManager.setDefaultMaxPerRoute(50);
    }
    public static HttpResult pushHttpRequsetXml(String url, String xml, Map<String, String> header) throws Exception{
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(getRequestConfig());
        for(String key : header.keySet()){
            httpPost.setHeader(key, header.get(key));
        }
        httpPost.setHeader("Content-Type", "application/xml");
        httpPost.setEntity(new StringEntity(xml, "UTF-8"));
        CloseableHttpResponse httpResponse = getHttpCline().execute(httpPost);
        int statusCode = httpResponse.getStatusLine().getStatusCode();
        String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        HttpResult httpResult = HttpResult.getHttpResult(statusCode, content);
        close(httpResponse);
        return httpResult;
    }
    private static void close(CloseableHttpResponse httpResponse){
        try {
            if(null != httpResponse){
                EntityUtils.consume(httpResponse.getEntity());//此处高能,通过源码分析,由EntityUtils是否回收HttpEntity
                httpResponse.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(null != httpResponse){
                    httpResponse.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
    private static CloseableHttpClient getHttpCline(){
        return  HttpClients.custom()
                .setConnectionManager(connectionManager)
                .disableAutomaticRetries()
                .build();
    }
    private static RequestConfig getRequestConfig(){
        RequestConfig.Builder builder = RequestConfig.custom();
        builder.setSocketTimeout(60000)//3.1设置客户端等待服务端返回数据的超时时间
                .setConnectTimeout(30000)//3.2设置客户端发起TCP连接请求的超时时间
                .setExpectContinueEnabled(true)
                .setConnectionRequestTimeout(30000);//3.3设置客户端从连接池获取链接的超时时间
        return builder.build();
    }
    /**
     * @param strUrl
     * @return byte[]
     * @throws
     * @description: 获取网络图片转成字节流
     * @author zhy
     * @date 2019/10/23 8:59
     */
    public static byte[] getImageFromNetByUrl(String strUrl) {
        if (!isURL(strUrl)){
            return null;
        }
        try {
            URL url = new URL(strUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(2 * 1000);
            InputStream inStream = conn.getInputStream();// 通过输入流获取图片数据
            byte[] btImg = readInputStream(inStream);// 得到图片的二进制数据
            return btImg;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 从输入流中获取字节流数据
     *
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[10240];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        return outStream.toByteArray();
    }
    public static boolean isURL(String str) {
        str = str.toLowerCase();
        String regex = "^((https|http|ftp|rtsp|mms)?://)"
                + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?"
                + "(([0-9]{1,3}\\.){3}[0-9]{1,3}"
                + "|"
                + "([0-9a-z_!~*'()-]+\\.)*"
                + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\."
                + "[a-z]{2,6})"
                + "(:[0-9]{1,5})?"
                + "((/?)|"
                + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
        return str.matches(regex);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/HttpResult.java
New file
@@ -0,0 +1,31 @@
package com.ruoyi.web.controller.tool;
import lombok.Data;
/**
 * http请求返回封装
 */
@Data
public class HttpResult {
    /**
     * 返回状态码
     */
    private Integer code;
    /**
     * 返回结果
     */
    private String data;
    /**
     * 返回封装结果
     * @param code
     * @param data
     * @return
     */
    public static HttpResult getHttpResult(Integer code, String data){
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(code);
        httpResult.setData(data);
        return httpResult;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ImportExcelUtil.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
/**
 * 导出返回信息
 */
@Slf4j
public class ImportExcelUtil {
    /**
     * @param errorLines   错误行数
     * @param successLines 成功行数
     * @param errorMessage 错误信息
     * @return
     * @throws IOException
     */
    public static R<String> importReturnMsg(int errorLines, int successLines, List<String> errorMessage) throws IOException {
        if (errorLines == 0) {
            return R.ok("共" + successLines + "行数据全部导入成功!");
        } else {
            JSONObject result = new JSONObject(5);
            int totalCount = successLines + errorLines;
            result.put("totalCount", totalCount);
            result.put("errorCount", errorLines);
            result.put("errorMessage", errorMessage);
            result.put("successCount", successLines);
            result.put("msg", "总上传行数:" + totalCount + ",已导入行数:" + successLines + ",错误行数:" + errorLines);
            return R.ok(JSON.toJSONString(result));
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MD5AndKL.java
New file
@@ -0,0 +1,112 @@
package com.ruoyi.web.controller.tool;
import java.security.MessageDigest;
public class MD5AndKL {
    /**
     * MD5加码。32位
     *
     * @param inStr
     * @return
     */
    public static String MD5(String inStr) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e.toString());
        }
        byte[] md5Bytes = md5.digest(inStr.getBytes());
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++) {
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }
    /**
     * 可逆的加密算法
     *
     * @param inStr
     * @return
     */
    public static String KL(String inStr) {
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String s = new String(a);
        return s;
    }
    /**
     * 加密后解密
     *
     * @param inStr
     * @return
     */
    public static String JM(String inStr) {
        char[] a = inStr.toCharArray();
        for (int i = 0; i < a.length; i++) {
            a[i] = (char) (a[i] ^ 't');
        }
        String k = new String(a);
        return k;
    }
    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));
        return resultSb.toString();
    }
    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n += 256;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }
    public static String MD5Encode(String origin, String charsetname) {
        String resultString = null;
        try {
            resultString = new String(origin);
            MessageDigest md = MessageDigest.getInstance("MD5");
            if (charsetname == null || "".equals(charsetname)){
                resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
            }else{
                resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
            }
        } catch (Exception exception) {
            exception.printStackTrace();
        }
        return resultString;
    }
    private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    public static void main(String args[]) {
        System.out.println("MD5后再加密:" + KL(MD5("123456")));
        System.out.println(MD5("123456"));
        // System.out.println("加密:" + KL(MD5("123456")));
        // s = KL(s);
        // System.out.println("解密:" + KL("81dc9bdb52d04dc20036dbd8313ed055"));
        // System.out.println("解密:" + JM(KL(s)));
        // System.out.println("解密为MD5后的:" + KL(KL(MD5(s))));
        // System.out.println(JM("5d62957bb57d3e49dcf48a0df064be4c"));
        // System.out.println(MD5AndKL.KL(MD5AndKL.MD5("admin"+"87654321")));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MsgCodeUtil.java
New file
@@ -0,0 +1,61 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.system.code.SubmitTemplateReg;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
/**
 * 短信工具类
 */
public class MsgCodeUtil implements Serializable {
    /**接口账号用户名*/
    private static final String AP_ID = "";
    /**企业名称*/
    private static final String EC_NAME = "";
    /**签名*/
    private static final String SECRET_KEY = "";
    /**签名编码*/
    private static final String SIGN = "";
    /**模板ID*/
    private static final String TEMPLATE_ID = "";
    /**
     * 实体封装
     * @param code
     * @return
     */
    public static SubmitTemplateReg getSubmitTemplateReg(String code,String mobiles) {
        SubmitTemplateReg submitReg =new SubmitTemplateReg();
        String[] paramss = {code};
        submitReg.setApId(AP_ID);
        submitReg.setEcName(EC_NAME);
        submitReg.setSecretKey(SECRET_KEY);
        submitReg.setParams(JSONObject.toJSONString(paramss));
        submitReg.setMobiles(mobiles);
        submitReg.setAddSerial("");
        submitReg.setSign(SIGN);
        submitReg.setTemplateId(TEMPLATE_ID);
        submitReg.setMac(TEMPLATE_ID);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(submitReg.getEcName( ));stringBuffer.append(submitReg.getApId());
        stringBuffer.append(submitReg.getSecretKey());stringBuffer.append(submitReg.getTemplateId());stringBuffer.append(submitReg.getMobiles());
        stringBuffer.append(submitReg.getParams());stringBuffer.append(submitReg.getSign());stringBuffer.append(submitReg.getAddSerial());
        submitReg.setMac(Hex.encodeHexString(stringBuffer.toString().getBytes(StandardCharsets.UTF_8)));
        String regText = JSONObject.toJSONString(submitReg);
        //加密
        String encode = Base64.encodeBase64String(regText.getBytes());
        System.err.println(encode);
        return submitReg;
    }
    public static void main(String[] args) {
        getSubmitTemplateReg("123456","18398968484");
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MsgUtil.java
New file
@@ -0,0 +1,41 @@
package com.ruoyi.web.controller.tool;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.ruoyi.common.core.redis.RedisCache;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.concurrent.ThreadLocalRandom;
@RestController
public class MsgUtil {
    @Resource
    private RedisCache redisCache;
    @ApiOperation(value = "通用发送验证码",tags = "通用发送验证码")
    @PostMapping("/common/send")
    public  String send (String phone){
        String code = createCode();
        redisCache.setCacheObject(phone,code);
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("CorpID", "SCZT006959");
        paramMap.put("Pwd", "123456");
        paramMap.put("Mobile", phone);
        paramMap.put("Cell", "");
        paramMap.put("SendTime", "");
        paramMap.put("Content", java.net.URLEncoder.encode("您的验证码为"+code+"。如非本人操作,请注意账号安全。【职评网】"));
        String result3 = HttpUtil.post("http://sdk2.028lk.com/sdk2/BatchSend2.aspx", paramMap);
        if (result3 == null) {
            result3 = "";
        }
        result3 = StrUtil.trim(result3);
    return result3;
    }
    public static String createCode(){
        return String.valueOf(ThreadLocalRandom.current().nextInt(100000, 999999));
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/MsgUtils.java
New file
@@ -0,0 +1,70 @@
package com.ruoyi.web.controller.tool;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class MsgUtils {
    @Value("${code.config.accessKeyId}")
    private  String accessKeyId;
    @Value("${code.config.accessKeySecret}")
    private  String accessKeySecret;
    @Value("${code.config.signName}")
    private  String signName;
    @Value("${code.config.templateCode}")
    private  String templateCode;
    @Value("${code.config.signNameTest}")
    private  String signNameTest;
    @Value("${code.config.templateCodeTest}")
    private  String templateCodeTest;
    /**
     * 使用AK&SK初始化账号Client
     * @param accessKeyId
     * @param accessKeySecret
     * @return Client
     * @throws Exception
     */
    public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        Config config = new Config()
                // 您的 AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 您的 AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }
    public void sendMsg(String phone,String code) throws Exception {
        com.aliyun.dysmsapi20170525.Client client = MsgUtils.createClient(accessKeyId,accessKeySecret);
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setPhoneNumbers(phone)
                .setTemplateParam("{\"code\":\""+code+"\"}");
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);
            log.info("短信发送成功:{},{}",sendSmsResponse.getBody().getMessage(),sendSmsResponse.getStatusCode());
        } catch (TeaException error) {
            // 如有需要,请打印 error
            com.aliyun.teautil.Common.assertAsString(error.message);
            log.info("短信发送失败:{}",error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 如有需要,请打印 error
            com.aliyun.teautil.Common.assertAsString(error.message);
            log.info("短信发送失败:{}",error.message);
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ObsUploadUtil.java
New file
@@ -0,0 +1,106 @@
package com.ruoyi.web.controller.tool;
import com.obs.services.ObsClient;
import com.obs.services.model.ObjectMetadata;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
public class ObsUploadUtil {
    // OBS图片访问域名 TODO 修改正式参数
    public static String endPoint = "obs.cn-east-3.myhuaweicloud.com";
    public static String accessKeyId = "S2BWSKTM1TKNPCPZRTJF";
    public static String accessKeySecret = "I1JsC8dJDea3x7l6Tcx77OI7NdEibzkUv1feZ3Uq";
    public static String bucketName = "tcjt-zpw";
    public static String oss_domain = "https://tcjt-zpw.obs.cn-east-3.myhuaweicloud.com/";
    // 创建ObsClient实例
    public static ObsClient obsClient = new ObsClient(accessKeyId, accessKeySecret, endPoint);
    public static String obsUpload(@RequestBody MultipartFile file)
            throws IOException {
        String fileName = "";
        if (file != null && !"".equals(file.getName())
                && file.getName() != null) {
            InputStream content = file.getInputStream();// 获得指定文件的输入流
            ObjectMetadata meta = new ObjectMetadata();// 创建上传Object的Metadata
            meta.setContentLength(file.getSize());  // 必须设置ContentLength
            String originalFilename = file.getName();
            fileName = UUID.randomUUID().toString().replaceAll("-", "") + originalFilename;
//            fileName =
//                    file.getOriginalFilename() + originalFilename.subSequence(
//                            originalFilename.lastIndexOf("."), originalFilename.length());
            obsClient.putObject(bucketName, "xinquan/" + fileName, content, meta);// 上传Object.
            if (fileName != null && !"".equals(fileName)) {
                System.out.println(fileName);
                fileName = oss_domain + "xinquan/" + fileName;
            }
        }
        return fileName;
    }
    @ApiOperation(value = "上传",tags = {"后台统一上传"})
    @PostMapping(value = "/sys/upload")
    public static String obsUpload1(@RequestBody MultipartFile file)
            throws IOException {
        String fileName = "";
        if (file != null && !"".equals(file.getOriginalFilename())
                && file.getOriginalFilename() != null) {
            InputStream content = file.getInputStream();// 获得指定文件的输入流
            ObjectMetadata meta = new ObjectMetadata();// 创建上传Object的Metadata
            meta.setContentLength(file.getSize());  // 必须设置ContentLength
            String originalFilename = file.getOriginalFilename();
            fileName =
                    UUID.randomUUID().toString().replaceAll("-", "") + originalFilename.subSequence(
                            originalFilename.lastIndexOf("."), originalFilename.length());
            obsClient.putObject(bucketName, "xinquan/" + fileName, content, meta);// 上传Object.
            if (fileName != null && !"".equals(fileName)) {
                System.out.println(fileName);
                fileName = oss_domain + "xinquan/" + fileName;
            }
        }
        return fileName;
    }
    /**
     * 删除某个Object
     *
     * @param bucketUrl
     * @return
     */
    public static boolean deleteObject(String bucketUrl) {
        try {
            bucketUrl = bucketUrl.replace(oss_domain + "admin/", "");
            // 删除Object.
            obsClient.deleteObject(bucketName, bucketUrl);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            // ossClient.shutdown();
        }
        return true;
    }
//     public static void createBucket(String bucketName)
//     {
//         //初始化 OSSClient
////          ossClient = new OssClient(endPoint, accessKeyId, accessKeySecret);
//
//         // 新建一个Bucket
//         Bucket bucket = ossClient.createBucket(bucketName);
//         System.out.println(bucket.getName());
//         System.out.println(bucket.getCreationDate());
//     }
//
//     public static void main(String[] args) {
//         OssUploadUtil.createBucket("ssfdfsd");
//    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PayMoneyUtil.java
New file
@@ -0,0 +1,879 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.wechat.pay.java.core.cipher.PrivacyEncryptor;
import com.wechat.pay.java.core.cipher.RSAPrivacyEncryptor;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.map.HashedMap;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.*;
import java.util.*;
/**
 * 第三方支付工具类
 */
@Component
@RestController
public class PayMoneyUtil {
    @Value("${alipay.appid}")
    private String aliAppid;//支付宝appid
    @Value("${alipay.appPrivateKey}")
    private String appPrivateKey;//支付宝开发者应用私钥
    @Value("${alipay.alipayPublicKey}")
    private String alipayPublicKey;//支付宝应用公钥
    @Value("${alipay.alipay_public_key}")
    private String alipay_public_key;//支付宝支付公钥
    @Value("${wx.appid}")
    private String appid;//微信appid
    @Value("${wx.mchId}")
    private String mchId;//微信商户号
    @Value("${wx.key}")
    private String key;//微信商户号
    @Value("${callbackPath}")
    private String callbackPath;//支付回调网关地址
    private String wechatPayCertificatesFromPath = "/usr/local/server/app/cert/weixin/apiclient_cert.p12";//微信支付证书地址
    private String privateKeyFromPath = "/usr/local/server/app/cert/weixin/apiclient_cert.pem";//微信私钥证书地址
    /**
     * 支付宝支付
     */
    public ResultUtil alipay(String body, String subject, String outTradeNo, String amount, String notifyUrl){
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipayPublicKey, "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(body);//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
        model.setSubject(subject);//商品的标题/交易标题/订单标题/订单关键字等。
        model.setOutTradeNo(outTradeNo);//商户网站唯一订单号
        model.setTimeoutExpress("30m");
        model.setTotalAmount(amount);//付款金额
        model.setProductCode("QUICK_MSECURITY_PAY");
        request.setBizModel(model);
        request.setNotifyUrl(callbackPath + notifyUrl);
        try {
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
            Map<String, String> map = new HashMap<>();
            map.put("orderString", response.getBody());
            System.out.println(map);//就是orderString 可以直接给客户端请求,无需再做处理。
            return ResultUtil.success(map);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝扫码支付下单
     * @param body
     * @param subject
     * @param outTradeNo
     * @param amount
     * @param notifyUrl
     * @return
     */
    public ResultUtil aliScanCodePay(String body, String subject, String outTradeNo, String amount, String notifyUrl){
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey, "json", "UTF-8", alipay_public_key, "RSA2"); //获得初始化的AlipayClient
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//创建API对应的request类
        request.setBizContent("{" +
                "    \"out_trade_no\":\"" + outTradeNo + "\"," +//商户订单号
                "    \"total_amount\":\"" + amount + "\"," +
                "    \"subject\":\"" + subject + "\"," +
                "    \"notify_url\":\"" + callbackPath + notifyUrl + "\"," +
                "    \"body\":\"" + body + "\"," +
                "    \"store_id\":\"NJ_001\"," +
                "    \"timeout_express\":\"90m\"}");//订单允许的最晚付款时间
        AlipayTradePrecreateResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        JSONObject alipay_trade_precreate_response = JSON.parseObject(response.getBody()).getJSONObject("alipay_trade_precreate_response");
        System.err.print(alipay_trade_precreate_response.getString("qr_code"));
        return ResultUtil.success(alipay_trade_precreate_response.getString("qr_code"));
    }
    /**
     * 支付成功后的回调处理逻辑
     * @param request
     */
    public Map<String, String> alipayCallback(HttpServletRequest request){
        //获取支付宝POST过来反馈信息
        Map<String,String> params = new HashMap<String,String>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
        //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
        try {
            boolean flag = AlipaySignature.rsaCheckV1(params, alipayPublicKey, "UTF-8","RSA2");
            if(flag){
                Map<String, String> map = new HashMap<>();
                String out_trade_no = params.get("out_trade_no");
                String subject = params.get("subject");
                String total_amount = params.get("total_amount");
                String trade_no = params.get("trade_no");
                map.put("out_trade_no", out_trade_no);//商家订单号
                map.put("subject", subject);
                map.put("total_amount", total_amount);
                map.put("trade_no", trade_no);//支付宝交易号
                return map;
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝查询订单支付状态
     * @param out_trade_no
     * @return
     * @throws Exception
     */
    public ResultUtil queryALIOrder(String out_trade_no) throws Exception{
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2");
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":" + out_trade_no +
                "  }");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            String tradeStatus = response.getTradeStatus();//交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
            return ResultUtil.success(tradeStatus);
        } else {
            return ResultUtil.error(response.getMsg());
        }
    }
    /**
     * 微信统一下单
     * @param body          商品描述
     * @param attach        附加数据
     * @param out_trade_no  商户订单号
     * @param total_fee     标价金额
     * @param notify_url    通知地址
     * @param tradeType     交易类型
     * @return
     */
    public ResultUtil weixinpay(String body, String attach, String out_trade_no, String total_fee, String notify_url, String tradeType) throws Exception{
        int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            hostAddress = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String nonce_str = UUIDUtil.getRandomCode(16);
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);
        map.put("body", body);
        map.put("attach", attach);//存储订单id
        map.put("out_trade_no", out_trade_no);//存储的订单code
        map.put("total_fee", i);
        map.put("spbill_create_ip", hostAddress);
        map.put("notify_url", callbackPath + notify_url);
        map.put("trade_type", tradeType);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String prepay_id = map1.get("prepay_id");
                        //重新进行签名后返回给前端
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("appid", appid);
                        map2.put("noncestr", nonce_str);
                        map2.put("package", "Sign=WXPay");
                        map2.put("partnerid", mchId);
                        map2.put("prepayid", prepay_id);
                        map2.put("timestamp", new Date().getTime() / 1000);
                        String s1 = this.weixinSignature(map2);
                        map2.put("sign", s1);
                        System.err.println(map2);
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 微信支付成功后的回调处理
     * @param request
     */
    public Map<String, String> weixinpayCallback(HttpServletRequest request){
        try {
            String param = this.getParam(request);
            param = param.replaceAll("<!\\[CDATA\\[","");
            param = param.replaceAll("]]>", "");
            Map<String, String> map = this.xmlToMap(param, "UTF-8");
            String return_code = map.get("return_code");
            if("SUCCESS".equals(return_code)){
                String result_code = map.get("result_code");
                if("SUCCESS".equals(result_code)){
                    Map<String, String> map1 = new HashedMap();
                    map1.put("nonce_str", map.get("nonce_str"));
                    map1.put("out_trade_no", map.get("out_trade_no").split("_")[1]);//存储的订单code
                    map1.put("attach", map.get("attach"));//存储订单id
                    map1.put("total_fee", map.get("total_fee"));
                    map1.put("transaction_id", map.get("transaction_id"));//微信支付订单号
                    String result = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                    map1.put("result", result);
                    return map1;
                }else{
//                    System.err.println(map.get("err_code_des"));
                }
            }else{
//                System.err.println(map.get("return_msg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 微信扫码收款
     * @param body              商品描述
     * @param attach            附加数据
     * @param nonce_str         随机字符串
     * @param out_trade_no      商户订单号
     * @param total_fee         订单金额
     * @param auth_code         授权码    扫码支付授权码,设备读取用户微信中的条码或者二维码信息(注:用户付款码条形码规则:18位纯数字,以10、11、12、13、14、15开头)
     * @return
     */
    public ResultUtil wxScanQRCodePay(String body, String attach, String nonce_str, String out_trade_no, String total_fee, String auth_code){
        int i = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        String hostAddress = null;
        try {
            InetAddress address = InetAddress.getLocalHost();
            hostAddress = address.getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        String randomCode = null;
        try {
            randomCode = UUIDUtil.getRandomCode(10);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);//存储的支付人员id,员工扫描二维码支付的时候存储的是收款员工id
        map.put("body", body);
        map.put("attach", attach);//存储的费用月份数据,员工扫描二维码支付的时候存储的是收费项id
        map.put("out_trade_no", randomCode + "_" + out_trade_no);//存储的房间id
        map.put("total_fee", i);
        map.put("spbill_create_ip", hostAddress);
        map.put("auth_code", auth_code);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = null;
        try {
            body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                String type = map1.get("trade_type");
                switch (type){
                    case "JSAPI":
                        break;
                    case "NATIVE":
                        String code_url = map1.get("code_url");
                        return ResultUtil.success(code_url);
                    case "APP":
                        String prepay_id = map1.get("prepay_id");
                        //重新进行签名后返回给前端
                        Map<String, Object> map2 = new HashMap<>();
                        map2.put("appid", appid);
                        map2.put("noncestr", nonce_str);
                        map2.put("package", "Sign=WXPay");
                        map2.put("partnerid", mchId);
                        map2.put("prepayid", prepay_id);
                        map2.put("timestamp", new Date().getTime() + "");
                        String s1 = this.weixinSignature(map2);
                        map2.put("pac", "Sign=WXPay");
                        map2.put("sign", s1);
//                      System.err.println(map2);
                        return ResultUtil.success(map2);
                }
                return null;
            }else{
//                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
//            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"), new JSONObject());
        }
    }
    /**
     * 支付宝扫码收款
     * @param data
     * @return
     */
    public Object aliScanQRCodePay(String data){
        return null;
    }
    /**
     * 微信退款申请
     * @param transaction_id    微信订单号。微信生成的订单号,在支付通知中有返回
     * @param out_refund_no     商户退款单号。商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
     * @param total_fee         订单金额。订单总金额,单位为分,只能为整数
     * @param refund_fee        退款金额。退款总金额,订单总金额,单位为分,只能为整数
     * @param notify_url        退款结果通知url。异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。
     * @return
     */
    @ApiOperation(value = "退款",tags = "微信退款回调")
    @PostMapping(value = "/refund")
    public Map<String, String> wxRefund(String transaction_id, String out_refund_no, String total_fee, String refund_fee, String notify_url){
        int tf = new BigDecimal(total_fee).multiply(new BigDecimal("100")).intValue();
        int rf = new BigDecimal(refund_fee).multiply(new BigDecimal("100")).intValue();
        String nonce_str = UUIDUtil.getRandomCode();
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("nonce_str", nonce_str);
        map.put("transaction_id", transaction_id);
        map.put("out_refund_no", out_refund_no);
        map.put("total_fee", tf);
        map.put("refund_fee", rf);
        map.put("notify_url", notify_url);
        String s = this.weixinSignature(map);
        map.put("sign", s);
        String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = null;
        try {
            body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        Map<String, String> map2 = new HashMap<>();
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                map2.put("return_code", result_code);
                map2.put("refund_id", String.valueOf(map1.get("refund_id")));//微信退款订单号
                map2.put("refund_fee", String.valueOf(map1.get("refund_fee")));//退款金额
                return map2;
            }else{
                map2.put("return_code", result_code);
                map2.put("return_msg", map1.get("err_code_des"));
                return map2;
            }
        }else{
            map2.put("return_code", return_code);
            map2.put("return_msg", map1.get("return_msg"));
            return map2;
        }
    }
    /**
     * 微信退款成功后的回调处理
     * @param request
     * @return
     */
    public Map<String, String> wxRefundCallback(HttpServletRequest request){
        try {
            String param = this.getParam(request);
            param = param.replaceAll("<!\\[CDATA\\[","");
            param = param.replaceAll("]]>", "");
            Map<String, String> map = this.xmlToMap(param, "UTF-8");
            String return_code = map.get("return_code");
            if("SUCCESS".equals(return_code)){
                String req_info = map.get("req_info");//加密信息请用商户秘钥进行解密
                String s = this.wxDecrypt(req_info);
                s = s.replaceAll("<!\\[CDATA\\[","");
                s = s.replaceAll("]]>", "");
                map = this.xmlToMap(s, "UTF-8");
                Map<String, String> map1 = new HashMap<>();
                map1.put("refund_id", map.get("refund_id"));
                map1.put("out_refund_no", map.get("out_refund_no"));
                return map1;
            }else{
//                System.err.println(map.get("return_msg"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 支付宝退款
     * @param trade_no          支付宝交易号
     * @param refund_amount     退款金额
     * @return
     * @throws AlipayApiException
     */
    public Map<String, String> aliRefund(String trade_no, String refund_amount) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", aliAppid, appPrivateKey,"json","UTF-8", alipay_public_key,"RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("trade_no", trade_no);
        jsonObject.put("refund_amount", refund_amount);
        request.setBizContent(jsonObject.toJSONString());
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        Map<String, String> map = new HashMap<>();
        if(response.isSuccess()){
            System.out.println("调用成功");
            String outTradeNo = response.getOutTradeNo();
            map.put("code", response.getCode());//10000
            map.put("trade_no", response.getTradeNo());//支付宝交易号
            map.put("out_trade_no", outTradeNo);//商户订单号
        } else {
            System.out.println("调用失败");
            map.put("code", response.getCode());
            map.put("msg", response.getSubMsg());
        }
        return map;
    }
    /**
     * 查询微信支付订单
     * @return
     * @throws Exception
     */
    public ResultUtil<Map<String, String>> queryWXOrder(String out_trade_no, String transaction_id) throws Exception{
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";
        String nonce_str = UUIDUtil.getRandomCode(16);
        Map<String, Object> map = new HashMap<>();
        map.put("appid", appid);
        map.put("mch_id", mchId);
        map.put("out_trade_no", out_trade_no);//商户订单号
        map.put("transaction_id", transaction_id);//微信订单号
        map.put("nonce_str", nonce_str);//随机字符串
        String s = this.weixinSignature(map);
        map.put("sign", s);
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_XML);
        StringBuffer xmlString = new StringBuffer();
        Set<String> strings = map.keySet();
        String[] keys = {};
        keys = strings.toArray(keys);
        Arrays.sort(keys);
        xmlString.append("<xml>");
        for(int l = 0; l < keys.length; l++){
            xmlString.append("<" + keys[l] + ">" + map.get(keys[l]) + "</" + keys[l] + ">");
        }
        xmlString.append("</xml>");
        Map<String, String> map1 = null;
        String body1 = HttpClientUtil.pushHttpRequsetXml(url, xmlString.toString(), new HashMap<>()).getData();
        //将结果xml解析成map
        body1 = body1.replaceAll("<!\\[CDATA\\[","");
        body1 = body1.replaceAll("]]>", "");
        try {
            map1 = this.xmlToMap(body1, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        String return_code = map1.get("return_code");
        if("SUCCESS".equals(return_code)){
            String result_code = map1.get("result_code");
            if("SUCCESS".equals(result_code)){
                Map<String, String> map2 = new HashMap<>();
                map2.put("trade_type", map1.get("trade_type"));
                map2.put("trade_state", map1.get("trade_state"));//订单状态SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销(刷卡支付),USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败)
                map2.put("transaction_id", map1.get("transaction_id"));
                return ResultUtil.success(map2);
            }else{
                System.err.println(map1.get("err_code_des"));
                return ResultUtil.error(map1.get("err_code_des"));
            }
        }else{
            System.err.println(map1.get("return_msg") + appid + "----" + mchId);
            return ResultUtil.error(map1.get("return_msg"));
        }
    }
    /**
     * 微信商户转账零钱
     * @param outDetailNo   商家流水号
     * @param amount        转账金额
     * @param openid        收款openid
     * @param userName      收款用户姓名
     * @param remark        备注
     * @return
     */
//    public String weixinTransferMoney(String outDetailNo, Double amount, String openid, String userName, String remark){
//        RSAConfig config =
//                new RSAConfig.Builder()
//                        .merchantId(mchId)
//                        .privateKeyFromPath(privateKeyFromPath)
//                        .merchantSerialNumber("7630124B15BA87F2CF0F35883988DE34D62089DA")
//                        .wechatPayCertificatesFromPath(wechatPayCertificatesFromPath)
//                        .build();
//        TransferBatchService service = new TransferBatchService.Builder().config(config).build();
//        InitiateBatchTransferRequest initiateBatchTransferRequest =
//                new InitiateBatchTransferRequest();
//        initiateBatchTransferRequest.setAppid(appid);
//        initiateBatchTransferRequest.setOutBatchNo(outDetailNo);
//        initiateBatchTransferRequest.setBatchName("付款");
//        initiateBatchTransferRequest.setBatchRemark(remark);
//        initiateBatchTransferRequest.setTotalAmount(new BigDecimal(amount).multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_EVEN).longValue());
//        initiateBatchTransferRequest.setTotalNum(1);
//        {
//            List<TransferDetailInput> transferDetailListList = new ArrayList<>();
//            {
//                TransferDetailInput transferDetailInput = new TransferDetailInput();
//                transferDetailInput.setOutDetailNo(outDetailNo);
//                transferDetailInput.setTransferAmount(new BigDecimal(amount).multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_EVEN).longValue());
//                transferDetailInput.setTransferRemark(remark);
//                transferDetailInput.setOpenid(openid);
//                if(amount > 0.3){
//                    transferDetailInput.setUserName(userName);
//                }
//                transferDetailListList.add(transferDetailInput);
//            }
//            initiateBatchTransferRequest.setTransferDetailList(
//                    transferDetailListList);
//        }
//        initiateBatchTransferRequest.setTransferSceneId("1000");
//        InitiateBatchTransferResponse response =
//                service.initiateBatchTransfer(initiateBatchTransferRequest);
//        return response.getBatchId();
//    }
    /**
     * 获取请求内容
     * @param request
     * @return
     * @throws IOException
     */
    private String getParam(HttpServletRequest request) throws IOException {
        // 读取参数
        InputStream inputStream;
        StringBuilder sb = new StringBuilder();
        inputStream = request.getInputStream();
        String s;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null) {
            sb.append(s);
        }
        in.close();
        inputStream.close();
        return sb.toString();
    }
    /**
     * 微信下单的签名算法
     * @param map
     * @return
     */
    private String weixinSignature(Map<String, Object> map){
        try {
            Set<Map.Entry<String, Object>> entries = map.entrySet();
            List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries);
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {
                public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, Object> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    Object val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key + "=" + val + "&");
                    }
                }
            }
            sb.append("key=" + key);
            String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public String RSAPrivacyEncryptor(){
        // 微信支付平台证书中的公钥
        PublicKey wechatPayPublicKey = null;
        String plaintext = "";
        PrivacyEncryptor encryptor = new RSAPrivacyEncryptor(wechatPayPublicKey, "");
        String ciphertext = encryptor.encrypt(plaintext);
        return ciphertext;
    }
    /**
     * 微信退款成功后的解密
     * @param req_info
     * @return
     */
    private String wxDecrypt(String req_info) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException,
            InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        byte[] decode = Base64.getDecoder().decode(req_info);
        String sign = MD5AndKL.MD5Encode(key, "UTF-8").toLowerCase();
        if (Security.getProvider("BC") == null){
            Security.addProvider(new BouncyCastleProvider());
        }
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
        SecretKeySpec secretKeySpec = new SecretKeySpec(sign.getBytes(), "AES");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        return new String(cipher.doFinal(decode));
    }
    public static void main(String[] ages){
//        PayMoneyUtil payMoneyUtil = new PayMoneyUtil();
//        payMoneyUtil.weixinpay("测试", "123", "12.5", "");
    }
    /**
     * xml转map
     * @param xml
     * @param charset
     * @return
     * @throws UnsupportedEncodingException
     * @throws DocumentException
     */
    public static Map<String, String> xmlToMap(String xml, String charset) throws UnsupportedEncodingException, DocumentException {
        Map<String, String> respMap = new HashMap<String, String>();
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new ByteArrayInputStream(xml.getBytes(charset)));
        Element root = doc.getRootElement();
        xmlToMap(root, respMap);
        return respMap;
    }
    public static Map<String, String> xmlToMap(Element tmpElement, Map<String, String> respMap){
        if (tmpElement.isTextOnly()) {
            respMap.put(tmpElement.getName(), tmpElement.getText());
            return respMap;
        }
        @SuppressWarnings("unchecked")
        Iterator<Element> eItor = tmpElement.elementIterator();
        while (eItor.hasNext()) {
            Element element = eItor.next();
            xmlToMap(element, respMap);
        }
        return respMap;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
New file
@@ -0,0 +1,222 @@
package com.ruoyi.web.controller.tool;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.util.HashMap;
@Slf4j
public class PdfUtils {
    /**
     * word 转 pdf
     *
     * @param url
     */
    public static String wordToPdf(String url,String filePath, String fileName) {
        try {
            DocumentType documentType = DocumentType.DOC;
            if(url.contains(".docx")){
                documentType = DocumentType.DOCX;
            }
            if(url.contains(".doc")){
                documentType = DocumentType.DOC;
            }
            if(url.contains(".xlsx")){
                documentType = DocumentType.XLSX;
            }else {
                if(url.contains(".xls")){
                    documentType = DocumentType.XLS;
                }
            }
            InputStream inputStream = new URL(url).openStream();
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            IConverter converter = LocalConverter.builder().build();
            converter.convert(inputStream)
                    .as(documentType)
                    .to(stream)
                    .as(DocumentType.PDF).execute();
            //上传图片
            byte2File(stream.toByteArray(),filePath + "/pdf",fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf");
            MultipartFile multipartFile = convertToMultipartFile(stream,fileName.substring(0,fileName.lastIndexOf(".")) );
            String s = ObsUploadUtil.obsUpload(multipartFile);
            stream.close();
            inputStream.close();
            return s;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static MultipartFile convertToMultipartFile(ByteArrayOutputStream baos, String fileName) throws IOException {
        // 创建一个临时文件
        File tempFile = File.createTempFile(fileName, ".pdf");
        // 将ByteArrayOutputStream中的数据写入临时文件
        try (FileOutputStream fos = new FileOutputStream(tempFile)) {
            baos.writeTo(fos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 创建一个MultipartFile对象
        return new MockMultipartFile(
                fileName + ".pdf",          // 参数名称
                fileName + ".pdf", // 文件名
                "application/pdf", // 内容类型
                Files.readAllBytes(tempFile.toPath()) // 文件内容
        );
    }
    /**
     * file转byte
     */
    public static byte[] file2byte(File file){
        byte[] buffer = null;
        try{
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1)
            {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e){
            e.printStackTrace();
        }
        return buffer;
    }
    /**
     * byte 转file
     */
    public static File byte2File(byte[] buf, String filePath, String fileName){
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        OutputStreamWriter osw = null;
        File file = null;
        try{
            File dir = new File(filePath+"/");
            if (!dir.exists()){
                dir.mkdirs();
            }
            file = new File(filePath +File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
//            osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
            bos.write(buf);
        }catch (Exception e){
            e.printStackTrace();
        }
        finally{
            if (bos != null){
                try{
                    bos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            if (fos != null){
                try{
                    fos.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
        return file;
    }
    /**
     * multipartFile转File
     **/
    public static File multipartFile2File(MultipartFile multipartFile){
        File file = null;
        if (multipartFile != null){
            try {
                file= File.createTempFile("tmp", null);
                multipartFile.transferTo(file);
                System.gc();
                file.deleteOnExit();
            }catch (Exception e){
                e.printStackTrace();
                log.warn("multipartFile转File发生异常:"+e);
            }
        }
        return file;
    }
    public static void main(String[] args) {
//        String url = "file:///E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09\\专业技术工作总结.docx";
//        String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09";
//        String fileName = "专业技术工作总结.docx";
//        String s = wordToPdf(url, filePath, fileName);
//        System.err.println(s);
//        String url = "file:///F:\\测试动态列表Word.doc";
////        String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09";
////        String fileName = "专业技术工作总结.docx";4
//        String filePath = "F:\\";
//
//        String s = wordToPdf(url, filePath, "测试动态列表Word.doc");
//        System.err.println(s);
        // TODO Auto-generated method stub
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("CorpID", "SCZT006959");
        paramMap.put("Pwd", "123456");
        paramMap.put("Mobile", "19522115070");
        paramMap.put("Cell", "");
        paramMap.put("SendTime", "");
        paramMap.put("Content", java.net.URLEncoder.encode("你好,这是测试短信发送。【职评网】"));
        String result3 = HttpUtil.post("http://sdk2.028lk.com/sdk2/BatchSend2.aspx", paramMap);
        if (result3 == null) {
            result3 = "";
        }
        result3 = StrUtil.trim(result3);
        log.info("返回结果:" + result3);
        if (result3.matches("^\\d+$") && !result3.equals("0")) {
            return;
        }
    }
    public static String test(String fileName){
        String url = "file:///F:\\"+fileName;
//        String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09";
//        String fileName = "专业技术工作总结.docx";4
        String filePath = "F:\\";
        String s = wordToPdf(url, filePath, fileName);
        System.err.println(s);
        return s;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PinyinExample.java
New file
@@ -0,0 +1,42 @@
package com.ruoyi.web.controller.tool;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
public class PinyinExample {
    public static void main(String[] args) {
        String chineseString = "四川省";
        String firstLetter = getFirstLetter(chineseString);
        System.out.println("First letter of '" + chineseString + "' is: " + firstLetter);
    }
    public static String getFirstLetter(String chinese) {
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        if (chinese == null || chinese.isEmpty()) {
            return "";
        }
        char firstChar = chinese.charAt(0);
        if (Character.toString(firstChar).matches("[\\u4E00-\\u9FA5]+")) {
            try {
                String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(firstChar, format);
                if (pinyinArray != null && pinyinArray.length > 0) {
                    return pinyinArray[0].substring(0, 1).toUpperCase();
                }
            } catch (BadHanyuPinyinOutputFormatCombination e) {
                e.printStackTrace();
            }
        } else {
            return Character.toString(firstChar).toUpperCase();
        }
        return "";
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/QRCodeUtil.java
New file
@@ -0,0 +1,124 @@
package com.ruoyi.web.controller.tool;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
/**
 * 二维码工具
 * @Author:debug (SteadyJack)
 * @Link: weixin-> debug0868  qq-> 1948831260
 * @Date: 2020/11/16 22:38
 **/
public class QRCodeUtil {
    private static final Logger log= LoggerFactory.getLogger(QRCodeUtil.class);
    //CODE_WIDTH:二维码宽度,单位像素
    private static final int CODE_WIDTH = 400;
    //CODE_HEIGHT:二维码高度,单位像素
    private static final int CODE_HEIGHT = 400;
    //FRONT_COLOR:二维码前景色,0x000000 表示黑色
    private static final int FRONT_COLOR = 0x000000;
    //BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
    //演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
    private static final int BACKGROUND_COLOR = 0xFFFFFF;
    public static void main(String[] args) {
        createCodeToFile("5261548530",new File("C:\\Users\\Admin\\Desktop\\qrcode"),"5261548530.png");
    }
    public static void createCodeToFile(String content, File codeImgFileSaveDir, String fileName) {
        try {
            if (StringUtils.isBlank(content) || StringUtils.isBlank(fileName)) {
                return;
            }
            content = content.trim();
            if (codeImgFileSaveDir==null || codeImgFileSaveDir.isFile()) {
                //二维码图片存在目录为空,默认放在桌面...
                codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
            }
            if (!codeImgFileSaveDir.exists()) {
                //二维码图片存在目录不存在,开始创建...
                codeImgFileSaveDir.mkdirs();
            }
            //核心代码-生成二维码
            BufferedImage bufferedImage = getBufferedImage(content);
            File codeImgFile = new File(codeImgFileSaveDir, fileName);
            ImageIO.write(bufferedImage, "png", codeImgFile);
            log.info("二维码图片生成成功:" + codeImgFile.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 生成二维码并输出到输出流, 通常用于输出到网页上进行显示,输出到网页与输出到磁盘上的文件中,区别在于最后一句 ImageIO.write
     * write(RenderedImage im,String formatName,File output):写到文件中
     * write(RenderedImage im,String formatName,OutputStream output):输出到输出流中
     * @param content  :二维码内容
     * @param outputStream :输出流,比如 HttpServletResponse 的 getOutputStream
     */
    public static void createCodeToOutputStream(String content, OutputStream outputStream) {
        try {
            if (StringUtils.isBlank(content)) {
                return;
            }
            content = content.trim();
            //核心代码-生成二维码
            BufferedImage bufferedImage = getBufferedImage(content);
            //区别就是这一句,输出到输出流中,如果第三个参数是 File,则输出到文件中
            ImageIO.write(bufferedImage, "png", outputStream);
            log.info("二维码图片生成到输出流成功...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //核心代码-生成二维码
    private static BufferedImage getBufferedImage(String content) throws WriterException {
        //com.google.zxing.EncodeHintType:编码提示类型,枚举类型
        Map<EncodeHintType, Object> hints = new HashMap();
        //EncodeHintType.CHARACTER_SET:设置字符编码类型
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //EncodeHintType.ERROR_CORRECTION:设置误差校正
        //ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
        //不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        //EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
        hints.put(EncodeHintType.MARGIN, 1);
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
        BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
        for (int x = 0; x < CODE_WIDTH; x++) {
            for (int y = 0; y < CODE_HEIGHT; y++) {
                bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
            }
        }
        return bufferedImage;
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ResultUtil.java
New file
@@ -0,0 +1,187 @@
package com.ruoyi.web.controller.tool;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
 * 定义统一返回对象
 */
@ApiModel(value = "统一返回结果集")
public class ResultUtil<T> {
    public static final Integer SUCCESS = 10000;
    public static final Integer PARAM_ERROR = 10010;
    public static final Integer SYSTEM_INFO = 10020;
    public static final Integer TOKEN_ERROR = 10030;
    public static final Integer SIGN_ERROR = 10040;
    public static final Integer RUNTIME_ERROR = 10050;
    public static final String Token = "token无效";
    public static final String SIGN = "签名无效";
    @ApiModelProperty(name = "code", value = "业务状态码 10000:成功,10010:参数错误,10020:系统提示, 10030:身份校验异常,10040:签名不通过,10050:系统运行异常")
    private Integer code;//备用状态码
    @ApiModelProperty(name = "msg", value = "返回结果说明")
    private String msg;//返回说明
    @ApiModelProperty(name = "data", value = "返回结果值")
    private T data;//返回数据
    public String getMsg() {
        return msg;
    }
    public T getData() {
        return data;
    }
    public Integer getCode() {
        return code;
    }
    public ResultUtil(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private ResultUtil(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static <T> ResultUtil<T> getResult(Integer code, String msg){
        return new ResultUtil<>(code, msg);
    }
    public static <T> ResultUtil<T> getResult(Integer code, String msg, T data){
        return new ResultUtil<>(code, msg, data);
    }
    /**
     * 错误信息
     * @return
     */
    public static ResultUtil error(String mag){
        return ResultUtil.getResult(ResultUtil.SYSTEM_INFO, mag, new Object());
    }
    /**
     * 错误信息
     * @return
     */
    public static <T> ResultUtil <T> error(String mag, T obj){
        return ResultUtil.getResult(ResultUtil.SYSTEM_INFO, mag, obj);
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, ResultUtil.Token, new Object());
    }
    /**
     * token失效
     * @return
     */
    public static ResultUtil tokenErr(String msg){
        return ResultUtil.getResult(ResultUtil.TOKEN_ERROR, msg, new Object());
    }
    /**
     * 参数异常
     * @return
     */
    public static  ResultUtil paranErr(String ages){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "【" + ages + "】参数异常", new Object());
    }
    /**
     * 参数异常
     * @return
     */
    public static ResultUtil paranErr(){
        return ResultUtil.getResult(ResultUtil.PARAM_ERROR, "参数异常", new Object());
    }
    /**
     * 运行异常
     * @return
     */
    public static ResultUtil runErr(){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, "系统运行异常", new Object());
    }
    /**
     * 运行异常
     * @return
     */
    public static <T>ResultUtil<T> runErr(T data){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, "系统运行异常", data);
    }
    /**
     * 运行异常
     * @return
     */
    public static <T>ResultUtil<T> runErr(T data, String msg){
        return ResultUtil.getResult(ResultUtil.RUNTIME_ERROR, msg, data);
    }
    /**
     * 返回成功
     * @param
     * @return
     */
    public static ResultUtil success(){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "成功", new Object());
    }
    /**
     * 返回成功
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, "成功", data);
    }
    /**
     * 返回成功
     * @param msg
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> success(String msg, T data){
        return ResultUtil.getResult(ResultUtil.SUCCESS, msg, data);
    }
    /**
     * 签名无效
     * @param <T>
     * @return
     */
    public static <T> ResultUtil<T> sign(){
        return ResultUtil.getResult(ResultUtil.SIGN_ERROR, SIGN);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TaskUtil.java
New file
@@ -0,0 +1,105 @@
package com.ruoyi.web.controller.tool;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.Instant;
import java.util.*;
/**
 * 定时任务工具类
 */
@Slf4j
@Component
public class TaskUtil {
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private RedisCache redisCache;
    @Scheduled(fixedRate = 1000 * 60)
    public void message() {
        try {
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 每隔一分钟去处理的定时任务
     */
    @Scheduled(fixedRate = 1000 * 60)
    public void taskMinute(){
        try {
//            List<Message> list = messageService.list();
//            Map<Integer,List<Message>> map = new LinkedHashMap<>();
//            for (Message message : list) {
//                if (map.get(message.getUserId())==null){
//                    List<Message> messages = new ArrayList<>();
//                    messages.add(message);
//                    map.put(message.getUserId(),messages);
//                    System.err.println("为空");
//                }else {
//                    List<Message> messages = map.get(message.getUserId());
//                    messages.add(message);
//                    map.put(message.getUserId(),messages);
//                }
//            }
//            Object cacheObject = redisCache.getCacheObject("1");
//            Set<Integer> integers = map.keySet();
//            for (Integer integer : integers) {
//                redisCache.deleteObject(String.valueOf(integer));
//                redisCache.setCacheList(String.valueOf(integer),map.get(integer));
//                List<Message> cacheList = redisCache.getCacheList(String.valueOf(integer));
//                System.err.println("====="+cacheList);
//            }
//
//
//            System.err.println("======="+map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 每天的凌晨执行的任务
     */
    @Scheduled(cron = "0 0 0 * * *")
    public void taskDay(){
//        List<SysRole> sysRoles = roleService.selectListByDelFlag(2);
//        if(CollectionUtils.isEmpty(sysRoles)){
//            return;
//        }
//        for (SysRole sysRole : sysRoles) {
//            if(sysRole.getRemoveDays()>0){
//                sysRole.setRemoveDays(sysRole.getRemoveDays()-1);
//                roleService.updateRole(sysRole);
//            }else {
//                roleService.deleteRoleById(sysRole.getRoleId());
//            }
//        }
    }
    /**
     * 每天的凌晨执行的任务
     */
    @Scheduled(cron = "0 0 1 * * ? ")
    public void taskDayOne(){
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/UUIDUtil.java
New file
@@ -0,0 +1,99 @@
package com.ruoyi.web.controller.tool;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
/**
 * 定义生成随机码的工具类
 */
public class UUIDUtil {
    private int i = 1;
    /**
     * 定义生成原生的UUID随机码
     * @return
     */
    public static String getNativeUUID(){
        return UUID.randomUUID().toString();
    }
    /**
     * 生成32位随机码
     * @return
     */
    public static String getRandomCode(){
        return UUIDUtil.getNativeUUID().replaceAll("-", "");
    }
    /**
     * 获取给定长度的随机码
     * @param num
     * @return
     * @throws Exception
     */
    public static String getRandomCode(Integer num) throws Exception{
        String str = null;
        if(0 < num){
            if(num % 32 > 0){
                Integer s = num / 32;
                Integer l = num % 32;
                StringBuffer sb = new StringBuffer();
                for(int i = 0; i < s; i++){
                    sb.append(UUIDUtil.getRandomCode());
                }
                sb.append(UUIDUtil.getRandomCode().substring(0, l));
                str = sb.toString();
            }else if(num % 32 == 0){
                Integer s = num / 32;
                StringBuffer sb = new StringBuffer();
                for(int i = 0; i < s; i++){
                    sb.append(UUIDUtil.getRandomCode());
                }
                str = sb.toString();
            }else{
                str = UUIDUtil.getRandomCode().substring(0, num);
            }
        }else{
            throw new Exception("参数只能大于0");
        }
        return str;
    }
    /**
     * 获取根据当前时间的字符串数据
     * @return
     */
    public synchronized static String getTimeStr(){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return simpleDateFormat.format(new Date());
    }
    /**
     * @Description: 获取数字随机码
     * @Author pzb
     * @Date 2021/8/11 16:52
     * @Param
     * @Return
     * @Exception
     */
    public static String getNumberRandom(Integer num){
        if(null == num){
            num = 32;
        }
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < num; i++){
            sb.append(Double.valueOf(Math.random() * 10).intValue());
        }
        return sb.toString();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/WordUtil.java
New file
@@ -0,0 +1,165 @@
package com.ruoyi.web.controller.tool;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@Slf4j
@Component
public class WordUtil {
    /**
     * 基于模板生成 Word 文档
     *
     * @param response         response
     * @param basePackagePath  resources 目录下模板所在包路径
     * @param templateFileName 模板文件名
     * @param templateParam    模板参数
     * @param fileName         文件名
     */
//    public void generate(HttpServletResponse response, String basePackagePath, String templateFileName, Object templateParam, String fileName) {
//        try {
//            // 设置 HTTP 响应的内容类型为 Microsoft Word 文档
//            response.setContentType("application/msword");
//            // 设置响应字符编码为 UTF-8
//            response.setCharacterEncoding("utf-8");
//            // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
//            String filename = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
//            // 设置响应头,指定文档将以附件的形式下载,并定义文件名
//            response.setHeader("Content-disposition", "attachment;filename=" + filename + ".doc");
//            // 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
//            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
//            configuration.setDefaultEncoding("utf-8");
//            // 设置模板加载器,加载模板文件
//            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
//            Template t = configuration.getTemplate(templateFileName, "utf-8");
//            // 创建 Writer 对象,用于将生成的文档写到输出流中,缓存区大小设为 10KB
//            Writer out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8), 10240);
//            // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
//            t.process(templateParam, out);
//            out.close();
//        } catch (Exception e) {
//            log.info("基于模板{}生成Word文档异常,异常原因:{}", templateFileName, e.getMessage(), e);
//            throw new RuntimeException("生成Word文档异常,异常原因:" + e.getMessage());
//        }
//    }
    public String generate(String basePackagePath, String templateFileName, Object templateParam, String fileName, String saveDirectory) {
        try {
            // 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setDefaultEncoding("utf-8");
            // 设置模板加载器,加载模板文件
            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
            Template t = configuration.getTemplate(templateFileName, "utf-8");
            // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
//            String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
            String encodedFileName =fileName ;
            // 定义保存文件的路径
            File saveDir = new File(saveDirectory);
            if (!saveDir.exists()) {
                saveDir.mkdirs();
            }
            // 定义文件名
            String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
            // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
            Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
            // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
            t.process(templateParam, out);
            out.close();
            File file = new File(filePath);
            // 检查文件是否存在
            if (!file.exists()) {
                throw new FileNotFoundException("文件不存在: " + filePath);
            }
            // 读取文件内容
            byte[] fileContent = new byte[(int) file.length()];
            try (FileInputStream fis = new FileInputStream(file)) {
                fis.read(fileContent);
            }
            MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
            String s = ObsUploadUtil.obsUpload(mockMultipartFile);
            return s;
        } catch (IOException | TemplateException e) {
            log.error("生成Word文档异常,异常原因:{}", e.getMessage(), e);
            throw new RuntimeException("生成Word文档异常,异常原因:" + e.getMessage());
        }
    }
    public String generatePdf(String basePackagePath, String templateFileName, Object templateParam, String fileName, String saveDirectory) {
        try {
            // 创建 Freemarker 的 Configuration 对象,设置默认的不兼容改进选项
            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setDefaultEncoding("utf-8");
            // 设置模板加载器,加载模板文件
            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), basePackagePath));
            Template t = configuration.getTemplate(templateFileName, "utf-8");
            // 使用 URLEncoder 对文件名进行编码,以防止中文文件名在不同浏览器和操作系统下出现乱码问题
//            String encodedFileName = URLEncoder.encode(fileName + "_" + System.currentTimeMillis(), "utf-8");
            String encodedFileName =fileName ;
            // 定义保存文件的路径
            File saveDir = new File(saveDirectory);
            if (!saveDir.exists()) {
                saveDir.mkdirs();
            }
            // 定义文件名
            String filePath = saveDir.getAbsolutePath() + File.separator + encodedFileName + ".doc";
            // 创建 Writer 对象,用于将生成的文档写到文件中,缓存区大小设为 10KB
            Writer out = new BufferedWriter(new FileWriter(filePath), 10240);
            // 将模型数据与模板结合生成 Word 文档,写入到 Writer 对象中
            t.process(templateParam, out);
            out.close();
            File file = new File(filePath);
            // 检查文件是否存在
            if (!file.exists()) {
                throw new FileNotFoundException("文件不存在: " + filePath);
            }
            // 读取文件内容
            byte[] fileContent = new byte[(int) file.length()];
            try (FileInputStream fis = new FileInputStream(file)) {
                fis.read(fileContent);
            }
            String test = PdfUtils.test(encodedFileName + ".doc");
//            MultipartFile mockMultipartFile = new MockMultipartFile(encodedFileName+".doc", fileContent);
//            String s = ObsUploadUtil.obsUpload(mockMultipartFile);
            return test;
        } catch (IOException | TemplateException e) {
            log.error("生成Word文档异常,异常原因:{}", e.getMessage(), e);
            throw new RuntimeException("生成Word文档异常,异常原因:" + e.getMessage());
        }
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
New file
@@ -0,0 +1,125 @@
package com.ruoyi.web.core.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
/**
 * Swagger2的接口配置
 *
 * @author ruoyi
 */
@Configuration
public class SwaggerConfig
{
    /** 系统基础配置 */
    @Autowired
    private RuoYiConfig ruoyiConfig;
    /** 是否开启swagger */
    @Value("${swagger.enabled}")
    private boolean enabled;
    /** 设置请求的统一前缀 */
    @Value("${swagger.pathMapping}")
    private String pathMapping;
    /**
     * 创建API
     */
    @Bean
    public Docket createRestApi()
    {
        return new Docket(DocumentationType.OAS_30)
                // 是否启用Swagger
                .enable(enabled)
                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
                .apiInfo(apiInfo())
                // 设置哪些接口暴露给Swagger展示
                .select()
                // 扫描所有有注解的api,用这种方式更灵活
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                // 扫描指定包中的swagger注解
                // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
                // 扫描所有 .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                /* 设置安全模式,swagger可以设置访问token */
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .pathMapping(pathMapping);
    }
    /**
     * 安全模式,这里指定token通过Authorization头请求头传递
     */
    private List<SecurityScheme> securitySchemes()
    {
        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
        return apiKeyList;
    }
    /**
     * 安全上下文
     */
    private List<SecurityContext> securityContexts()
    {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                        .build());
        return securityContexts;
    }
    /**
     * 默认的安全上引用
     */
    private List<SecurityReference> defaultAuth()
    {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }
    /**
     * 添加摘要信息
     */
    private ApiInfo apiInfo()
    {
        // 用ApiInfoBuilder进行定制
        return new ApiInfoBuilder()
                // 设置标题
                .title("标题:职评网管理系统_接口文档")
                // 描述
                .description("职评网接口文档")
                // 作者信息
                .contact(new Contact(ruoyiConfig.getName(), null, null))
                // 版本
                .version("版本号:" + ruoyiConfig.getVersion())
                .build();
    }
}
ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties
New file
@@ -0,0 +1 @@
restart.include.json=/com.alibaba.fastjson.*.jar
ruoyi-admin/src/main/resources/application-druid.yml
New file
@@ -0,0 +1,64 @@
# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://127.0.0.1:3306/tech_info?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: 123456
#                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
#                username: root
#                password: shms#123~
            # 从库数据源
            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.yml
New file
@@ -0,0 +1,203 @@
# 项目相关配置
ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 3.8.6
  # 版权年份
  copyrightYear: 2023
  # 实例演示开关
  demoEnabled: true
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: false
  # 验证码类型 math 数字计算 char 字符验证
  captchaType: math
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8081
  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:
  main:
    allow-bean-definition-overriding: true
  # 资源信息
  messages:
    # 国际化资源文件路径
    basename: i18n/messages
  profiles:
    active: druid
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 500MB
      # 设置总上传的文件大小
      max-request-size: 2000MB
  # 服务模块
  devtools:
    restart:
      # 热部署开关
      enabled: true
  # redis 配置
  redis:
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
# token配置
token:
  # 令牌自定义标识
  header: Authorization
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 120
# 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
mybatis-plus:
  # 此处在多数据源中生效
  config-location: classpath:/mybatis-config.xml
  global-config:
    banner: false
    db-config:
      logic-not-delete-value: 0
      logic-delete-value: 1
  type-aliases-package: com.ruoyi.**.domain,com.ruoyi.**.vo
  # 指定Mapper文件位置
  mapper-locations: classpath*:mapper/**/*.xml
# Swagger配置
swagger:
  # 是否开启swagger
  enabled: true
  # 请求前缀
  pathMapping: /
# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /system/notice
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
# file upload
file:
  upload:
    location: /file/
    qrLocation: /file/qrCode/
    accessPath: /file/
    allowExt: .jpg|.png|.gif|.jpeg|.doc|.docx|.apk|.MP4|.mp4|.pdf|.PDF
#wx:
#  config:
#    appId: wxc3985a05da7d86dc
#    secret: 5cca42633c25439613b328c08ef20cc9
#OSS及短信配置
code:
  config:
    templateCodeTest: "SMS_154950909"
    signNameTest: "阿里云短信测试"
    accessKeyId: LTAI5tAdba8HtT1C6UqtSxBt
    accessKeySecret: 0SRb6XGkciQDPWn2rYqbJtq2qRMDY8
    signName: "四川金达通信工程"
    templateCode: "SMS_293985284"
---
wx:
  grantType: authorization_code #填authorization_code
  appid: wxb58c994e1697f683 #应用唯一标识,在微信开放平台提交应用审核通过后获得
  appSecret: 95a34f114973298cce4297a20bb59bc3 #应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
  appletsAppid: wxda355f1377409600 #小程序APPid
  appletsAppSecret: 58121b67f2ba25c17998fa26dc77e008 #
  officialAccountAppid: 11111
  officialAccountAppSecret: 1111
  webAppId: 111
  webAppSecret: 11
  mchId: 1691703344 #微信支付分配的商户号
#  mchId: 1665330417 #微信支付分配的商户号
  privateKeyPath : E:\cert\zhiping\apiclient_key.pem
  merchantSerialNumber : 5A99160EA4E916DBB07EB20F1C133B168579D4E4
  apiV3Key : 00023de21e6dc24da239377419872341
  appId : wxb58c994e1697f683
  key: Eri2GR2SB3b6iIhaoD7k3KQ8X0wf1Ybh #key为商户平台设置的密钥key:
#  merchantSerialNumber : 7EEA04429B006E12AAA421C002EC48BBEED5BE94
#  apiV3Key : TA2npSNWmS0GcB0tFFRWA94rm1M0iSFs
#  appId : wx98563d0ec9cf21c8
#  key: Eri2GR2SB3b6iIhaoD7k3KQ8X0wf1Ybh #key为商户平台设置的密钥key:
  #key为商户平台设置的密钥key:
alipay:
  appid: 2021004184657725  #应用程序唯一标识
  appPrivateKey: MIIEpAIBAAKCAQEAjHzMkbtMOOal5ssNinVAl/oBPpk/ZTxWoScJFh1UDIezNLYlNx+7BRRuNPlSyvLAXwYbc5KIGrCenp/1mBMyAtIkcNLNY49diWtOl8uu/oeHZQfe+PPR3NWDnEPteGWrRpGVIbYyedacO+3BIymfv/V8dj9pllCOxT6RsEiZgSOIATuzLt6nEOXtEaiHalyjr55OKQPfElHmB31jf1yM6iNVAM8rmP8GbiMyr03YFrQuNaInX9J4Gbmuxy6/HCa53TyLtWAC7Oy+EYD0oy/+RwwEPfdUMALOAckRhErcdh2f6OgnXWfMfN9RhhLQiN6tbZ/uzia3As7fNN4lU8rPmQIDAQABAoIBADn49eHdTGLequ9GM1xDblhIjmLqkkKQV59AoHtDtv9EsCq8TzckHOTHvYKWsBeXfNK5jnJusUNyRsJmd849fZG0bd0w4BiJfKvMYC47mwblnnWOffB1jNB4O0ssrL3WFouUX9n9eW7VpLsGLYD5GDb6clXJbSTeMUwruarpCo9DIYMbae/65wBWLSUn/9hpS9YxIYhNp5nFS1+6gVBuJOI8HEGpe2PnTYaFO2U+HeZGJ2UN7U/5x1wyUpY/7mQIyjAMORBkisOIJ3woNr6qPbhf54tCcW8FdaAuJnxityUL+GXLMyJaNuZWkT0TbCMZT0RfboVShAaty+zuYvmcwVECgYEAyMaWDrsS+1VCCGtVkSg5eGLsXDOkIF+leS/VJ4nQsKO9iIU+gpD0FbvLh8eeajyPFKVYW2GK8WB+cQmKGdPnyui0SvcDCVIy+hoPx4102xss3CKCGidCQOIRzw9qJ61mzVsI8pU87tcOKKVgK3sQ+q1/Fmr0t5n2QtOH8OqEWecCgYEAsyEUdglZ77TZ8wGt+mG0kL4gjJUXzcX5zw1xxo1jEXh7jA8RUBz0xrAexwPEJiIzNRkxWh4YDQJegRiIA6Pij8GyFRSQl4kNpOCJfs52EcRV5k6hrDgEZdfaCBVy1CNLMt0zhWFQwYwX5OCAk6Z/CCgAjrwD1BTiR4neD/xhWn8CgYEAuqTBwpfuIW80n5cISJTYOC3eBCiNnvrLXUk2IjdfpZXSECOt5LrT7ZBSuLq9bY02hb7f0LNw8sr9QB/aHgB8Loj9ceMHE5cyhIXNvXim9TjiDxKVV7K/SIngfFicGp58PtMuEjTiHDYXl3mFWWZidmbrCfAL5tJdt+nlKfUZbGkCgYBzxbyIsXCMKZH3qi08tytRpWA6HB5fY0YaWTEgx76wyvLmydJBugVF6QxrSfbbQp1gAyFPgkW/Grnjq+w0lhZXHTQwxbLSDcVgu7KB34SV5RQznryFJ0tIW2LSeLJXg1wVyruCyCu+fAHxblwLkb9mkRwTJFdBGiJJZES+hjqRlwKBgQCmzQV5jqk8Zemyg/SZaXJ+iqtOn3iu3c0aBnRt8dXmOg6ybuNFrIu9UGEs+TC08XCSzSH57jKEDz0Kz3F/fBgstDp1R+yizKM7RLNeU5RzyRdQUACZR4Zs8BweVDaQtnz+sfVmgKMNGA+/wS+fUCx/fPfm2hXcOGZkJNohBebtmw== #开发者应用私钥
  alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmmtqSfZPk3pAFp/gqdBDWc9qimhjRMMvPPLTNypQ8CzsTpSx3wLXVCj2LXYKg4zQzZLHtYb7CJajs8gqDmRn1tAY8iViekV8AsTksXJ5fiO67e5JenPFS048/v/xQI8qNtllqY/MzCbZ0QvnATMeLX6Iwi4ZGRzLlL2wEEGfy2DJ2osRd+tIU+9y5EErObEzJdT+yxxVmOvpvJuVqf7NfnrMZj3ijYg+qDQEu6kDhuXrlZvS6MAUsZUiOE3/uQwSws0bD9ROWyYk7Mr7CH+3u0oLQeBweYQVtqRZWERm6Oxa0gxpqJILTL5+9T5hdFGdFV0xrF59Pk4eTeImeUrbIwIDAQAB #应用公钥
  alipay_public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmmtqSfZPk3pAFp/gqdBDWc9qimhjRMMvPPLTNypQ8CzsTpSx3wLXVCj2LXYKg4zQzZLHtYb7CJajs8gqDmRn1tAY8iViekV8AsTksXJ5fiO67e5JenPFS048/v/xQI8qNtllqY/MzCbZ0QvnATMeLX6Iwi4ZGRzLlL2wEEGfy2DJ2osRd+tIU+9y5EErObEzJdT+yxxVmOvpvJuVqf7NfnrMZj3ijYg+qDQEu6kDhuXrlZvS6MAUsZUiOE3/uQwSws0bD9ROWyYk7Mr7CH+3u0oLQeBweYQVtqRZWERm6Oxa0gxpqJILTL5+9T5hdFGdFV0xrF59Pk4eTeImeUrbIwIDAQAB #支付宝公钥
callbackPath: http://121.31.232.206:3002/driver
ruoyi-admin/src/main/resources/banner.txt
New file
@@ -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
New file
@@ -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
New file
@@ -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-config.xml
New file
@@ -0,0 +1,26 @@
<?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="logImpl" value="STDOUT_LOGGING"/>
        <!--<setting name="logImpl" value="LOG4J" />-->
        <!-- 控制全局缓存(二级缓存),按美团技术团队的说法,尽量别用缓存机制 emmmm.... -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <!-- <setting name="lazyLoadingEnabled" value="true"/> -->
        <setting name="mapUnderscoreToCamelCase" value="true"/><!--是否将map下划线方式转为驼峰式命名-->
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <!-- <setting name="aggressiveLazyLoading" value="false"/>-->
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- 关于mybatis的一二级缓存 请参照:https://tech.meituan.com/2018/01/19/mybatis-cache.html -->
        <!-- 一级缓存范围默认:SESSION ,此范围在复杂应用场景中可能会出现脏读数据-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--<setting name="localCacheScope" value="STATEMENT"/>-->
        <setting name="localCacheScope" value="STATEMENT"/>
    </settings>
</configuration>
ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
New file
@@ -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-admin/src/main/resources/templates/专业技术工作总结.xml
New file
@@ -0,0 +1,1515 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?mso-application progid="Word.Document"?>
<pkg:package xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
    <pkg:part pkg:name="/_rels/.rels"
        pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512">
        <pkg:xmlData>
            <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
                <Relationship Id="rId3"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"
                    Target="docProps/app.xml" />
                <Relationship Id="rId2"
                    Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
                    Target="docProps/core.xml" />
                <Relationship Id="rId1"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
                    Target="word/document.xml" />
                <Relationship Id="rId4"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"
                    Target="docProps/custom.xml" />
            </Relationships>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/document.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
        <pkg:xmlData>
            <w:document
                xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
                xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
                xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
                xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"
                xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"
                xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"
                xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"
                xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex"
                xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex"
                xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex"
                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink"
                xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d"
                xmlns:o="urn:schemas-microsoft-com:office:office"
                xmlns:oel="http://schemas.microsoft.com/office/2019/extlst"
                xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
                xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
                xmlns:v="urn:schemas-microsoft-com:vml"
                xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
                xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
                xmlns:w10="urn:schemas-microsoft-com:office:word"
                xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
                xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
                xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
                xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
                xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
                xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du"
                xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
                xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
                xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
                xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
                xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
                xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"
                mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16du wp14">
                <w:body>
                    <w:p w14:paraId="3E57CD7F" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:jc w:val="center" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="44" />
                                <w:szCs w:val="44" />
                            </w:rPr>
                            <w:t>专业技术工作总结</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="51B27F87" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="005C5315" />
                    <w:p w14:paraId="16792867" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="005C5315" />
                    <w:p w14:paraId="427EA0FE" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="005C5315" />
                    <w:p w14:paraId="4D0998CE" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:b />
                                <w:bCs />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>一、自我介绍</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="6624A5B4" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>我是</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${name}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>,今年</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${age}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>,</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${generateEducation},毕业于${generateUniversity}、${generateUniversityMajor}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>。为人正直,品德端正,现在任职于</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${workUnit}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>,做</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${workContent}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>,累计工作年限已经达到</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${generateUniversityComplete}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>年,准备在今年申报</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${level}${technicalName}${majorName}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>,已满足对应层级的申报条件与要求。</w:t>
                        </w:r>
                        <w:proofErr w:type="gramStart" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>自从工作</w:t>
                        </w:r>
                        <w:proofErr w:type="gramEnd" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                以来,我热爱挑战和解决问题,也始终保持高度的责任感和敬业精神。我相信自己的能力和决心,希望能够在新的工作中不断提升自己并创造更大的价值。现将本人详细的经历、能力、业绩总结如下。</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="60C6D495" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:b />
                                <w:bCs />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>二、思想品德</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="6446F58E" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                作为年青一代专业技术人员生力军的一员,始终把理想信念作为立身之本,不忘初心,牢记使命,守护理想灯塔,赓续信念火种。从业以来,不断加强理论学习、厚实理论功底,从而练就马克思主义的看家本领、掌握马克思主义的强大思想武器。尤其要在学懂弄通做</w:t>
                        </w:r>
                        <w:proofErr w:type="gramStart" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>实习近</w:t>
                        </w:r>
                        <w:proofErr w:type="gramEnd" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                平新时代中国特色社会主义思想上下功夫,通过系统学、深入学、跟进学、持续学,从中领悟真理力量和实践力量,让当代中国马克思主义在内心深处铸魂、在思想高地扎根,以新时代党的创新理论武装头脑、指导实践、推动工作,做到</w:t>
                        </w:r>
                        <w:proofErr w:type="gramStart" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>学思用贯通</w:t>
                        </w:r>
                        <w:proofErr w:type="gramEnd" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>,</w:t>
                        </w:r>
                        <w:proofErr w:type="gramStart" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>知信行</w:t>
                        </w:r>
                        <w:proofErr w:type="gramEnd" />
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>统一。</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="1519A9E5" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:b />
                                <w:bCs />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>三、职业道德</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="582DA8EB" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                一直以来遵守公司各项规章制度,遵守行业规则,遵纪守法。从未利用职务质变在经营活动中为自己谋取私利。平等对待所有同事与客户,在履行职责和对外交往中,不敢做有损公司声誉的事情。在业务运作中也是按照有关规章、制度条款执行,保证公司的各项业务记录准确、清晰,严禁有弄虚作假与舞弊或其他行为。</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="193DFE44" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:b />
                                <w:bCs />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:lastRenderedPageBreak />
                            <w:t>四、专业技术工作能力与履职情况</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="4D0B3169" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                工作岗位是安身立命的港湾,不仅要自强不息也要不断提升自身专业技术水平。在理论、方法、思维方面创新,对于技术骨干与技术管理必需具备的能力水平,一方面要通过不断学习开拓思维眼界,另一方面也要积极投入在工作中,不放过任何一个问题,注重解决生产实践上、公司技术人员的培养、教育上的需要,取得了较多的研究成果。建筑设计是一个非常具有挑战性的专业工作,需要报以高度的责任心与事业心,以下是我的专业技术工作经历。</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="092AC732" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                            <w:rPr>
                                <w:color w:val="FF0000" />
                            </w:rPr>
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                ${certificate}</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="0B2B1EC8" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:b />
                                <w:bCs />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>五、业绩与成果</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="6AA1375D" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>在参加工作的</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${generateUniversityComplete}</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>年时间里,将我主要完成的工作业绩罗列如下:</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="417C9AB6" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                            <w:rPr>
                                <w:color w:val="FF0000" />
                            </w:rPr>
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>${mainWork}</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="61F5301C" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>
                                工作业绩是专业技术人员专业水平能力的重要体现,时刻牢记要更加积极参与更多的项目,努力解决更多的问题,提高实际贡献。要敢于提出新理论、探索新技术,多出重大科技成果。</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="7C7A2753" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:b />
                                <w:bCs />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>六、申报总结</w:t>
                        </w:r>
                    </w:p>
                    <w:p w14:paraId="2DBD6EA6" w14:textId="77777777" w:rsidR="005C5315"
                        w:rsidRDefault="00000000">
                        <w:pPr>
                            <w:spacing w:line="360" w:lineRule="auto" />
                            <w:ind w:firstLine="560" />
                        </w:pPr>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:t>回顾这一年,我部在公司正确领导下取得了一定的成绩,但也存在着一些问题和不足,明年我们决心克服困难、积极创新,努力工作。同时,</w:t>
                        </w:r>
                        <w:r>
                            <w:rPr>
                                <w:rFonts w:ascii="仿宋" w:eastAsia="仿宋" w:hAnsi="仿宋" w:cs="仿宋" />
                                <w:color w:val="000000" />
                                <w:sz w:val="28" />
                                <w:szCs w:val="28" />
                            </w:rPr>
                            <w:lastRenderedPageBreak />
                            <w:t>
                                更加严格执行建筑设计工作的各项标准与规范,主动学习更多关于与专业相关的前沿知识、前沿技术,灵活应用,为以后的工作打下坚实的基础。在工作作风上,能遵纪守法,团结同事,实事求是,乐观向上,始终保持严谨认真的工作态度和一丝不苟的工作作风,勤奋努力。始终做到老老实实,勤勤恳恳做事,过简单勤劳的生活,时刻牢记自己的责任和义务,严格要求自己,努力完成领导随时交办的任务,把每一项工作都抓得很细,做到精细化管理。</w:t>
                        </w:r>
                    </w:p>
                    <w:sectPr w:rsidR="005C5315">
                        <w:pgSz w:w="11905" w:h="16837" />
                        <w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"
                            w:header="720" w:footer="720" w:gutter="0" />
                        <w:cols w:space="720" />
                    </w:sectPr>
                </w:body>
            </w:document>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/_rels/document.xml.rels"
        pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="256">
        <pkg:xmlData>
            <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
                <Relationship Id="rId3"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings"
                    Target="webSettings.xml" />
                <Relationship Id="rId2"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"
                    Target="settings.xml" />
                <Relationship Id="rId1"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles"
                    Target="styles.xml" />
                <Relationship Id="rId5"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
                    Target="theme/theme1.xml" />
                <Relationship Id="rId4"
                    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable"
                    Target="fontTable.xml" />
            </Relationships>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/theme/theme1.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.theme+xml">
        <pkg:xmlData>
            <a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
                name="Office Theme">
                <a:themeElements>
                    <a:clrScheme name="Office">
                        <a:dk1>
                            <a:sysClr val="windowText" lastClr="000000" />
                        </a:dk1>
                        <a:lt1>
                            <a:sysClr val="window" lastClr="FFFFFF" />
                        </a:lt1>
                        <a:dk2>
                            <a:srgbClr val="1F497D" />
                        </a:dk2>
                        <a:lt2>
                            <a:srgbClr val="EEECE1" />
                        </a:lt2>
                        <a:accent1>
                            <a:srgbClr val="4F81BD" />
                        </a:accent1>
                        <a:accent2>
                            <a:srgbClr val="C0504D" />
                        </a:accent2>
                        <a:accent3>
                            <a:srgbClr val="9BBB59" />
                        </a:accent3>
                        <a:accent4>
                            <a:srgbClr val="8064A2" />
                        </a:accent4>
                        <a:accent5>
                            <a:srgbClr val="4BACC6" />
                        </a:accent5>
                        <a:accent6>
                            <a:srgbClr val="F79646" />
                        </a:accent6>
                        <a:hlink>
                            <a:srgbClr val="0000FF" />
                        </a:hlink>
                        <a:folHlink>
                            <a:srgbClr val="800080" />
                        </a:folHlink>
                    </a:clrScheme>
                    <a:fontScheme name="Office">
                        <a:majorFont>
                            <a:latin typeface="Cambria" />
                            <a:ea typeface="" />
                            <a:cs typeface="" />
                            <a:font script="Jpan" typeface="MS ゴシック" />
                            <a:font script="Hang" typeface="맑은 고딕" />
                            <a:font script="Hans" typeface="宋体" />
                            <a:font script="Hant" typeface="新細明體" />
                            <a:font script="Arab" typeface="Times New Roman" />
                            <a:font script="Hebr" typeface="Times New Roman" />
                            <a:font script="Thai" typeface="Angsana New" />
                            <a:font script="Ethi" typeface="Nyala" />
                            <a:font script="Beng" typeface="Vrinda" />
                            <a:font script="Gujr" typeface="Shruti" />
                            <a:font script="Khmr" typeface="MoolBoran" />
                            <a:font script="Knda" typeface="Tunga" />
                            <a:font script="Guru" typeface="Raavi" />
                            <a:font script="Cans" typeface="Euphemia" />
                            <a:font script="Cher" typeface="Plantagenet Cherokee" />
                            <a:font script="Yiii" typeface="Microsoft Yi Baiti" />
                            <a:font script="Tibt" typeface="Microsoft Himalaya" />
                            <a:font script="Thaa" typeface="MV Boli" />
                            <a:font script="Deva" typeface="Mangal" />
                            <a:font script="Telu" typeface="Gautami" />
                            <a:font script="Taml" typeface="Latha" />
                            <a:font script="Syrc" typeface="Estrangelo Edessa" />
                            <a:font script="Orya" typeface="Kalinga" />
                            <a:font script="Mlym" typeface="Kartika" />
                            <a:font script="Laoo" typeface="DokChampa" />
                            <a:font script="Sinh" typeface="Iskoola Pota" />
                            <a:font script="Mong" typeface="Mongolian Baiti" />
                            <a:font script="Viet" typeface="Times New Roman" />
                            <a:font script="Uigh" typeface="Microsoft Uighur" />
                        </a:majorFont>
                        <a:minorFont>
                            <a:latin typeface="Calibri" />
                            <a:ea typeface="" />
                            <a:cs typeface="" />
                            <a:font script="Jpan" typeface="MS 明朝" />
                            <a:font script="Hang" typeface="맑은 고딕" />
                            <a:font script="Hans" typeface="宋体" />
                            <a:font script="Hant" typeface="新細明體" />
                            <a:font script="Arab" typeface="Arial" />
                            <a:font script="Hebr" typeface="Arial" />
                            <a:font script="Thai" typeface="Cordia New" />
                            <a:font script="Ethi" typeface="Nyala" />
                            <a:font script="Beng" typeface="Vrinda" />
                            <a:font script="Gujr" typeface="Shruti" />
                            <a:font script="Khmr" typeface="DaunPenh" />
                            <a:font script="Knda" typeface="Tunga" />
                            <a:font script="Guru" typeface="Raavi" />
                            <a:font script="Cans" typeface="Euphemia" />
                            <a:font script="Cher" typeface="Plantagenet Cherokee" />
                            <a:font script="Yiii" typeface="Microsoft Yi Baiti" />
                            <a:font script="Tibt" typeface="Microsoft Himalaya" />
                            <a:font script="Thaa" typeface="MV Boli" />
                            <a:font script="Deva" typeface="Mangal" />
                            <a:font script="Telu" typeface="Gautami" />
                            <a:font script="Taml" typeface="Latha" />
                            <a:font script="Syrc" typeface="Estrangelo Edessa" />
                            <a:font script="Orya" typeface="Kalinga" />
                            <a:font script="Mlym" typeface="Kartika" />
                            <a:font script="Laoo" typeface="DokChampa" />
                            <a:font script="Sinh" typeface="Iskoola Pota" />
                            <a:font script="Mong" typeface="Mongolian Baiti" />
                            <a:font script="Viet" typeface="Arial" />
                            <a:font script="Uigh" typeface="Microsoft Uighur" />
                        </a:minorFont>
                    </a:fontScheme>
                    <a:fmtScheme name="Office">
                        <a:fillStyleLst>
                            <a:solidFill>
                                <a:schemeClr val="phClr" />
                            </a:solidFill>
                            <a:gradFill rotWithShape="1">
                                <a:gsLst>
                                    <a:gs pos="0">
                                        <a:schemeClr val="phClr">
                                            <a:tint val="50000" />
                                            <a:satMod val="300000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="35000">
                                        <a:schemeClr val="phClr">
                                            <a:tint val="37000" />
                                            <a:satMod val="300000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="100000">
                                        <a:schemeClr val="phClr">
                                            <a:tint val="15000" />
                                            <a:satMod val="350000" />
                                        </a:schemeClr>
                                    </a:gs>
                                </a:gsLst>
                                <a:lin ang="16200000" scaled="1" />
                            </a:gradFill>
                            <a:gradFill rotWithShape="1">
                                <a:gsLst>
                                    <a:gs pos="0">
                                        <a:schemeClr val="phClr">
                                            <a:shade val="51000" />
                                            <a:satMod val="130000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="80000">
                                        <a:schemeClr val="phClr">
                                            <a:shade val="93000" />
                                            <a:satMod val="130000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="100000">
                                        <a:schemeClr val="phClr">
                                            <a:shade val="94000" />
                                            <a:satMod val="135000" />
                                        </a:schemeClr>
                                    </a:gs>
                                </a:gsLst>
                                <a:lin ang="16200000" scaled="0" />
                            </a:gradFill>
                        </a:fillStyleLst>
                        <a:lnStyleLst>
                            <a:ln w="9525" cap="flat" cmpd="sng" algn="ctr">
                                <a:solidFill>
                                    <a:schemeClr val="phClr">
                                        <a:shade val="95000" />
                                        <a:satMod val="105000" />
                                    </a:schemeClr>
                                </a:solidFill>
                                <a:prstDash val="solid" />
                            </a:ln>
                            <a:ln w="25400" cap="flat" cmpd="sng" algn="ctr">
                                <a:solidFill>
                                    <a:schemeClr val="phClr" />
                                </a:solidFill>
                                <a:prstDash val="solid" />
                            </a:ln>
                            <a:ln w="38100" cap="flat" cmpd="sng" algn="ctr">
                                <a:solidFill>
                                    <a:schemeClr val="phClr" />
                                </a:solidFill>
                                <a:prstDash val="solid" />
                            </a:ln>
                        </a:lnStyleLst>
                        <a:effectStyleLst>
                            <a:effectStyle>
                                <a:effectLst>
                                    <a:outerShdw blurRad="40000" dist="20000" dir="5400000"
                                        rotWithShape="0">
                                        <a:srgbClr val="000000">
                                            <a:alpha val="38000" />
                                        </a:srgbClr>
                                    </a:outerShdw>
                                </a:effectLst>
                            </a:effectStyle>
                            <a:effectStyle>
                                <a:effectLst>
                                    <a:outerShdw blurRad="40000" dist="23000" dir="5400000"
                                        rotWithShape="0">
                                        <a:srgbClr val="000000">
                                            <a:alpha val="35000" />
                                        </a:srgbClr>
                                    </a:outerShdw>
                                </a:effectLst>
                            </a:effectStyle>
                            <a:effectStyle>
                                <a:effectLst>
                                    <a:outerShdw blurRad="40000" dist="23000" dir="5400000"
                                        rotWithShape="0">
                                        <a:srgbClr val="000000">
                                            <a:alpha val="35000" />
                                        </a:srgbClr>
                                    </a:outerShdw>
                                </a:effectLst>
                                <a:scene3d>
                                    <a:camera prst="orthographicFront">
                                        <a:rot lat="0" lon="0" rev="0" />
                                    </a:camera>
                                    <a:lightRig rig="threePt" dir="t">
                                        <a:rot lat="0" lon="0" rev="1200000" />
                                    </a:lightRig>
                                </a:scene3d>
                                <a:sp3d>
                                    <a:bevelT w="63500" h="25400" />
                                </a:sp3d>
                            </a:effectStyle>
                        </a:effectStyleLst>
                        <a:bgFillStyleLst>
                            <a:solidFill>
                                <a:schemeClr val="phClr" />
                            </a:solidFill>
                            <a:gradFill rotWithShape="1">
                                <a:gsLst>
                                    <a:gs pos="0">
                                        <a:schemeClr val="phClr">
                                            <a:tint val="40000" />
                                            <a:satMod val="350000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="40000">
                                        <a:schemeClr val="phClr">
                                            <a:tint val="45000" />
                                            <a:shade val="99000" />
                                            <a:satMod val="350000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="100000">
                                        <a:schemeClr val="phClr">
                                            <a:shade val="20000" />
                                            <a:satMod val="255000" />
                                        </a:schemeClr>
                                    </a:gs>
                                </a:gsLst>
                                <a:path path="circle">
                                    <a:fillToRect l="50000" t="-80000" r="50000" b="180000" />
                                </a:path>
                            </a:gradFill>
                            <a:gradFill rotWithShape="1">
                                <a:gsLst>
                                    <a:gs pos="0">
                                        <a:schemeClr val="phClr">
                                            <a:tint val="80000" />
                                            <a:satMod val="300000" />
                                        </a:schemeClr>
                                    </a:gs>
                                    <a:gs pos="100000">
                                        <a:schemeClr val="phClr">
                                            <a:shade val="30000" />
                                            <a:satMod val="200000" />
                                        </a:schemeClr>
                                    </a:gs>
                                </a:gsLst>
                                <a:path path="circle">
                                    <a:fillToRect l="50000" t="50000" r="50000" b="50000" />
                                </a:path>
                            </a:gradFill>
                        </a:bgFillStyleLst>
                    </a:fmtScheme>
                </a:themeElements>
                <a:objectDefaults />
                <a:extraClrSchemeLst />
            </a:theme>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/settings.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml">
        <pkg:xmlData>
            <w:settings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:o="urn:schemas-microsoft-com:office:office"
                xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
                xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
                xmlns:v="urn:schemas-microsoft-com:vml"
                xmlns:w10="urn:schemas-microsoft-com:office:word"
                xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
                xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
                xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
                xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
                xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
                xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du"
                xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
                xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
                xmlns:sl="http://schemas.openxmlformats.org/schemaLibrary/2006/main"
                mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16du">
                <w:zoom w:percent="100" />
                <w:bordersDoNotSurroundHeader />
                <w:bordersDoNotSurroundFooter />
                <w:proofState w:spelling="clean" w:grammar="clean" />
                <w:defaultTabStop w:val="708" />
                <w:hyphenationZone w:val="425" />
                <w:characterSpacingControl w:val="doNotCompress" />
                <w:compat>
                    <w:useFELayout />
                    <w:compatSetting w:name="compatibilityMode"
                        w:uri="http://schemas.microsoft.com/office/word" w:val="12" />
                    <w:compatSetting w:name="useWord2013TrackBottomHyphenation"
                        w:uri="http://schemas.microsoft.com/office/word" w:val="1" />
                </w:compat>
                <w:docVars>
                    <w:docVar w:name="commondata"
                        w:val="eyJoZGlkIjoiY2QzM2RkYTNjNWVmNmQ2N2U0MGI4NmFmMmI0ZWZjMDcifQ==" />
                </w:docVars>
                <w:rsids>
                    <w:rsidRoot w:val="005C5315" />
                    <w:rsid w:val="00310A5A" />
                    <w:rsid w:val="005C5315" />
                    <w:rsid w:val="00FF412B" />
                    <w:rsid w:val="1E3F51EF" />
                </w:rsids>
                <m:mathPr>
                    <m:mathFont m:val="Cambria Math" />
                    <m:brkBin m:val="before" />
                    <m:brkBinSub m:val="--" />
                    <m:smallFrac m:val="0" />
                    <m:dispDef />
                    <m:lMargin m:val="0" />
                    <m:rMargin m:val="0" />
                    <m:defJc m:val="centerGroup" />
                    <m:wrapIndent m:val="1440" />
                    <m:intLim m:val="subSup" />
                    <m:naryLim m:val="undOvr" />
                </m:mathPr>
                <w:themeFontLang w:val="en-US" w:eastAsia="zh-CN" />
                <w:clrSchemeMapping w:bg1="light1" w:t1="dark1" w:bg2="light2" w:t2="dark2"
                    w:accent1="accent1" w:accent2="accent2" w:accent3="accent3" w:accent4="accent4"
                    w:accent5="accent5" w:accent6="accent6" w:hyperlink="hyperlink"
                    w:followedHyperlink="followedHyperlink" />
                <w:shapeDefaults>
                    <o:shapedefaults v:ext="edit" spidmax="1026" />
                    <o:shapelayout v:ext="edit">
                        <o:idmap v:ext="edit" data="1" />
                    </o:shapelayout>
                </w:shapeDefaults>
                <w:decimalSymbol w:val="." />
                <w:listSeparator w:val="," />
                <w15:docId w15:val="{CF91A94A-C0B5-4DB6-8A25-3FE2EDEE82DD}" />
            </w:settings>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/styles.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml">
        <pkg:xmlData>
            <w:styles xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
                xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
                xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
                xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
                xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
                xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
                xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du"
                xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
                xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
                mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16du">
                <w:docDefaults>
                    <w:rPrDefault>
                        <w:rPr>
                            <w:rFonts w:ascii="Arial" w:eastAsiaTheme="minorEastAsia"
                                w:hAnsi="Arial" w:cs="Arial" />
                            <w:lang w:val="en-US" w:eastAsia="zh-CN" w:bidi="ar-SA" />
                        </w:rPr>
                    </w:rPrDefault>
                    <w:pPrDefault />
                </w:docDefaults>
                <w:latentStyles w:defLockedState="0" w:defUIPriority="0" w:defSemiHidden="0"
                    w:defUnhideWhenUsed="0" w:defQFormat="0" w:count="376">
                    <w:lsdException w:name="heading 1" w:qFormat="1" />
                    <w:lsdException w:name="heading 2" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 3" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 4" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 5" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 6" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 7" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 8" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="heading 9" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="caption" w:semiHidden="1" w:unhideWhenUsed="1"
                        w:qFormat="1" />
                    <w:lsdException w:name="footnote reference" w:semiHidden="1"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Title" w:qFormat="1" />
                    <w:lsdException w:name="Default Paragraph Font" w:semiHidden="1" />
                    <w:lsdException w:name="Subtitle" w:qFormat="1" />
                    <w:lsdException w:name="Strong" w:qFormat="1" />
                    <w:lsdException w:name="Emphasis" w:qFormat="1" />
                    <w:lsdException w:name="HTML Top of Form" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="HTML Bottom of Form" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Normal Table" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="No List" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Outline List 1" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Outline List 2" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Outline List 3" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Simple 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Simple 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Simple 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Classic 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Classic 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Classic 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Classic 4" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Colorful 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Colorful 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Colorful 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Columns 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Columns 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Columns 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Columns 4" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Columns 5" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 4" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 5" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 6" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 7" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Grid 8" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 4" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 5" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 6" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 7" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table List 8" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table 3D effects 1" w:semiHidden="1"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table 3D effects 2" w:semiHidden="1"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table 3D effects 3" w:semiHidden="1"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Contemporary" w:semiHidden="1"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Elegant" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Professional" w:semiHidden="1"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Subtle 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Subtle 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Web 1" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Web 2" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Web 3" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Table Theme" w:semiHidden="1" w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Placeholder Text" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="No Spacing" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Light Shading" w:uiPriority="60" />
                    <w:lsdException w:name="Light List" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1" w:uiPriority="65" />
                    <w:lsdException w:name="Medium List 2" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid" w:uiPriority="73" />
                    <w:lsdException w:name="Light Shading Accent 1" w:uiPriority="60" />
                    <w:lsdException w:name="Light List Accent 1" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid Accent 1" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1 Accent 1" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2 Accent 1" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1 Accent 1" w:uiPriority="65" />
                    <w:lsdException w:name="Revision" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="List Paragraph" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Quote" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Intense Quote" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Medium List 2 Accent 1" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1 Accent 1" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2 Accent 1" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3 Accent 1" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List Accent 1" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading Accent 1" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List Accent 1" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid Accent 1" w:uiPriority="73" />
                    <w:lsdException w:name="Light Shading Accent 2" w:uiPriority="60" />
                    <w:lsdException w:name="Light List Accent 2" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid Accent 2" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1 Accent 2" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2 Accent 2" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1 Accent 2" w:uiPriority="65" />
                    <w:lsdException w:name="Medium List 2 Accent 2" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1 Accent 2" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2 Accent 2" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3 Accent 2" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List Accent 2" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading Accent 2" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List Accent 2" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid Accent 2" w:uiPriority="73" />
                    <w:lsdException w:name="Light Shading Accent 3" w:uiPriority="60" />
                    <w:lsdException w:name="Light List Accent 3" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid Accent 3" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1 Accent 3" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2 Accent 3" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1 Accent 3" w:uiPriority="65" />
                    <w:lsdException w:name="Medium List 2 Accent 3" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1 Accent 3" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2 Accent 3" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3 Accent 3" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List Accent 3" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading Accent 3" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List Accent 3" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid Accent 3" w:uiPriority="73" />
                    <w:lsdException w:name="Light Shading Accent 4" w:uiPriority="60" />
                    <w:lsdException w:name="Light List Accent 4" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid Accent 4" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1 Accent 4" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2 Accent 4" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1 Accent 4" w:uiPriority="65" />
                    <w:lsdException w:name="Medium List 2 Accent 4" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1 Accent 4" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2 Accent 4" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3 Accent 4" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List Accent 4" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading Accent 4" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List Accent 4" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid Accent 4" w:uiPriority="73" />
                    <w:lsdException w:name="Light Shading Accent 5" w:uiPriority="60" />
                    <w:lsdException w:name="Light List Accent 5" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid Accent 5" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1 Accent 5" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2 Accent 5" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1 Accent 5" w:uiPriority="65" />
                    <w:lsdException w:name="Medium List 2 Accent 5" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1 Accent 5" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2 Accent 5" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3 Accent 5" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List Accent 5" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading Accent 5" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List Accent 5" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid Accent 5" w:uiPriority="73" />
                    <w:lsdException w:name="Light Shading Accent 6" w:uiPriority="60" />
                    <w:lsdException w:name="Light List Accent 6" w:uiPriority="61" />
                    <w:lsdException w:name="Light Grid Accent 6" w:uiPriority="62" />
                    <w:lsdException w:name="Medium Shading 1 Accent 6" w:uiPriority="63" />
                    <w:lsdException w:name="Medium Shading 2 Accent 6" w:uiPriority="64" />
                    <w:lsdException w:name="Medium List 1 Accent 6" w:uiPriority="65" />
                    <w:lsdException w:name="Medium List 2 Accent 6" w:uiPriority="66" />
                    <w:lsdException w:name="Medium Grid 1 Accent 6" w:uiPriority="67" />
                    <w:lsdException w:name="Medium Grid 2 Accent 6" w:uiPriority="68" />
                    <w:lsdException w:name="Medium Grid 3 Accent 6" w:uiPriority="69" />
                    <w:lsdException w:name="Dark List Accent 6" w:uiPriority="70" />
                    <w:lsdException w:name="Colorful Shading Accent 6" w:uiPriority="71" />
                    <w:lsdException w:name="Colorful List Accent 6" w:uiPriority="72" />
                    <w:lsdException w:name="Colorful Grid Accent 6" w:uiPriority="73" />
                    <w:lsdException w:name="Subtle Emphasis" w:uiPriority="19" w:qFormat="1" />
                    <w:lsdException w:name="Intense Emphasis" w:uiPriority="21" w:qFormat="1" />
                    <w:lsdException w:name="Subtle Reference" w:uiPriority="31" w:qFormat="1" />
                    <w:lsdException w:name="Intense Reference" w:uiPriority="32" w:qFormat="1" />
                    <w:lsdException w:name="Book Title" w:uiPriority="33" w:qFormat="1" />
                    <w:lsdException w:name="Bibliography" w:semiHidden="1" w:uiPriority="37"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="TOC Heading" w:semiHidden="1" w:uiPriority="39"
                        w:unhideWhenUsed="1" w:qFormat="1" />
                    <w:lsdException w:name="Plain Table 1" w:uiPriority="41" />
                    <w:lsdException w:name="Plain Table 2" w:uiPriority="42" />
                    <w:lsdException w:name="Plain Table 3" w:uiPriority="43" />
                    <w:lsdException w:name="Plain Table 4" w:uiPriority="44" />
                    <w:lsdException w:name="Plain Table 5" w:uiPriority="45" />
                    <w:lsdException w:name="Grid Table Light" w:uiPriority="40" />
                    <w:lsdException w:name="Grid Table 1 Light" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful" w:uiPriority="52" />
                    <w:lsdException w:name="Grid Table 1 Light Accent 1" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2 Accent 1" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3 Accent 1" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4 Accent 1" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark Accent 1" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful Accent 1" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful Accent 1" w:uiPriority="52" />
                    <w:lsdException w:name="Grid Table 1 Light Accent 2" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2 Accent 2" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3 Accent 2" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4 Accent 2" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark Accent 2" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful Accent 2" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful Accent 2" w:uiPriority="52" />
                    <w:lsdException w:name="Grid Table 1 Light Accent 3" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2 Accent 3" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3 Accent 3" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4 Accent 3" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark Accent 3" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful Accent 3" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful Accent 3" w:uiPriority="52" />
                    <w:lsdException w:name="Grid Table 1 Light Accent 4" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2 Accent 4" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3 Accent 4" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4 Accent 4" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark Accent 4" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful Accent 4" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful Accent 4" w:uiPriority="52" />
                    <w:lsdException w:name="Grid Table 1 Light Accent 5" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2 Accent 5" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3 Accent 5" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4 Accent 5" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark Accent 5" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful Accent 5" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful Accent 5" w:uiPriority="52" />
                    <w:lsdException w:name="Grid Table 1 Light Accent 6" w:uiPriority="46" />
                    <w:lsdException w:name="Grid Table 2 Accent 6" w:uiPriority="47" />
                    <w:lsdException w:name="Grid Table 3 Accent 6" w:uiPriority="48" />
                    <w:lsdException w:name="Grid Table 4 Accent 6" w:uiPriority="49" />
                    <w:lsdException w:name="Grid Table 5 Dark Accent 6" w:uiPriority="50" />
                    <w:lsdException w:name="Grid Table 6 Colorful Accent 6" w:uiPriority="51" />
                    <w:lsdException w:name="Grid Table 7 Colorful Accent 6" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light Accent 1" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2 Accent 1" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3 Accent 1" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4 Accent 1" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark Accent 1" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful Accent 1" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful Accent 1" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light Accent 2" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2 Accent 2" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3 Accent 2" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4 Accent 2" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark Accent 2" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful Accent 2" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful Accent 2" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light Accent 3" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2 Accent 3" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3 Accent 3" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4 Accent 3" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark Accent 3" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful Accent 3" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful Accent 3" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light Accent 4" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2 Accent 4" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3 Accent 4" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4 Accent 4" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark Accent 4" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful Accent 4" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful Accent 4" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light Accent 5" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2 Accent 5" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3 Accent 5" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4 Accent 5" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark Accent 5" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful Accent 5" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful Accent 5" w:uiPriority="52" />
                    <w:lsdException w:name="List Table 1 Light Accent 6" w:uiPriority="46" />
                    <w:lsdException w:name="List Table 2 Accent 6" w:uiPriority="47" />
                    <w:lsdException w:name="List Table 3 Accent 6" w:uiPriority="48" />
                    <w:lsdException w:name="List Table 4 Accent 6" w:uiPriority="49" />
                    <w:lsdException w:name="List Table 5 Dark Accent 6" w:uiPriority="50" />
                    <w:lsdException w:name="List Table 6 Colorful Accent 6" w:uiPriority="51" />
                    <w:lsdException w:name="List Table 7 Colorful Accent 6" w:uiPriority="52" />
                    <w:lsdException w:name="Mention" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Smart Hyperlink" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Hashtag" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Unresolved Mention" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                    <w:lsdException w:name="Smart Link" w:semiHidden="1" w:uiPriority="99"
                        w:unhideWhenUsed="1" />
                </w:latentStyles>
                <w:style w:type="paragraph" w:default="1" w:styleId="a">
                    <w:name w:val="Normal" />
                    <w:rPr>
                        <w:rFonts w:eastAsia="Arial" />
                    </w:rPr>
                </w:style>
                <w:style w:type="character" w:default="1" w:styleId="a0">
                    <w:name w:val="Default Paragraph Font" />
                    <w:uiPriority w:val="1" />
                    <w:semiHidden />
                    <w:unhideWhenUsed />
                </w:style>
                <w:style w:type="table" w:default="1" w:styleId="a1">
                    <w:name w:val="Normal Table" />
                    <w:uiPriority w:val="99" />
                    <w:semiHidden />
                    <w:unhideWhenUsed />
                    <w:tblPr>
                        <w:tblInd w:w="0" w:type="dxa" />
                        <w:tblCellMar>
                            <w:top w:w="0" w:type="dxa" />
                            <w:left w:w="108" w:type="dxa" />
                            <w:bottom w:w="0" w:type="dxa" />
                            <w:right w:w="108" w:type="dxa" />
                        </w:tblCellMar>
                    </w:tblPr>
                </w:style>
                <w:style w:type="numbering" w:default="1" w:styleId="a2">
                    <w:name w:val="No List" />
                    <w:uiPriority w:val="99" />
                    <w:semiHidden />
                    <w:unhideWhenUsed />
                </w:style>
                <w:style w:type="character" w:styleId="a3">
                    <w:name w:val="footnote reference" />
                    <w:semiHidden />
                    <w:unhideWhenUsed />
                    <w:rPr>
                        <w:vertAlign w:val="superscript" />
                    </w:rPr>
                </w:style>
            </w:styles>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/webSettings.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml">
        <pkg:xmlData>
            <w:webSettings xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
                xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
                xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
                xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
                xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
                xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
                xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du"
                xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
                xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
                mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16du" />
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/word/fontTable.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml">
        <pkg:xmlData>
            <w:fonts xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
                xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
                xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
                xmlns:w16cex="http://schemas.microsoft.com/office/word/2018/wordml/cex"
                xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
                xmlns:w16="http://schemas.microsoft.com/office/word/2018/wordml"
                xmlns:w16du="http://schemas.microsoft.com/office/word/2023/wordml/word16du"
                xmlns:w16sdtdh="http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash"
                xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
                mc:Ignorable="w14 w15 w16se w16cid w16 w16cex w16sdtdh w16du">
                <w:font w:name="Arial">
                    <w:panose1 w:val="020B0604020202020204" />
                    <w:charset w:val="00" />
                    <w:family w:val="swiss" />
                    <w:pitch w:val="variable" />
                    <w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000"
                        w:csb0="000001FF" w:csb1="00000000" />
                </w:font>
                <w:font w:name="宋体">
                    <w:altName w:val="SimSun" />
                    <w:panose1 w:val="02010600030101010101" />
                    <w:charset w:val="86" />
                    <w:family w:val="auto" />
                    <w:pitch w:val="variable" />
                    <w:sig w:usb0="00000203" w:usb1="288F0000" w:usb2="00000016" w:usb3="00000000"
                        w:csb0="00040001" w:csb1="00000000" />
                </w:font>
                <w:font w:name="Times New Roman">
                    <w:panose1 w:val="02020603050405020304" />
                    <w:charset w:val="00" />
                    <w:family w:val="roman" />
                    <w:pitch w:val="variable" />
                    <w:sig w:usb0="E0002EFF" w:usb1="C000785B" w:usb2="00000009" w:usb3="00000000"
                        w:csb0="000001FF" w:csb1="00000000" />
                </w:font>
                <w:font w:name="仿宋">
                    <w:panose1 w:val="02010609060101010101" />
                    <w:charset w:val="86" />
                    <w:family w:val="modern" />
                    <w:pitch w:val="fixed" />
                    <w:sig w:usb0="800002BF" w:usb1="38CF7CFA" w:usb2="00000016" w:usb3="00000000"
                        w:csb0="00040001" w:csb1="00000000" />
                </w:font>
                <w:font w:name="Cambria">
                    <w:panose1 w:val="02040503050406030204" />
                    <w:charset w:val="00" />
                    <w:family w:val="roman" />
                    <w:pitch w:val="variable" />
                    <w:sig w:usb0="E00006FF" w:usb1="420024FF" w:usb2="02000000" w:usb3="00000000"
                        w:csb0="0000019F" w:csb1="00000000" />
                </w:font>
                <w:font w:name="Calibri">
                    <w:panose1 w:val="020F0502020204030204" />
                    <w:charset w:val="00" />
                    <w:family w:val="swiss" />
                    <w:pitch w:val="variable" />
                    <w:sig w:usb0="E4002EFF" w:usb1="C000247B" w:usb2="00000009" w:usb3="00000000"
                        w:csb0="000001FF" w:csb1="00000000" />
                </w:font>
            </w:fonts>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/docProps/core.xml"
        pkg:contentType="application/vnd.openxmlformats-package.core-properties+xml"
        pkg:padding="256">
        <pkg:xmlData>
            <cp:coreProperties
                xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
                xmlns:dc="http://purl.org/dc/elements/1.1/"
                xmlns:dcterms="http://purl.org/dc/terms/"
                xmlns:dcmitype="http://purl.org/dc/dcmitype/"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <dc:creator>A百度 邱玉玲17612801916</dc:creator>
                <cp:lastModifiedBy>易胜 罗</cp:lastModifiedBy>
                <cp:revision>2</cp:revision>
                <dcterms:created xsi:type="dcterms:W3CDTF">2024-10-08T08:22:00Z</dcterms:created>
                <dcterms:modified xsi:type="dcterms:W3CDTF">2024-10-08T08:22:00Z</dcterms:modified>
            </cp:coreProperties>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/docProps/app.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"
        pkg:padding="256">
        <pkg:xmlData>
            <Properties
                xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"
                xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
                <Template>Normal.dotm</Template>
                <TotalTime>1</TotalTime>
                <Pages>3</Pages>
                <Words>226</Words>
                <Characters>1292</Characters>
                <Application>Microsoft Office Word</Application>
                <DocSecurity>0</DocSecurity>
                <Lines>10</Lines>
                <Paragraphs>3</Paragraphs>
                <ScaleCrop>false</ScaleCrop>
                <Company />
                <LinksUpToDate>false</LinksUpToDate>
                <CharactersWithSpaces>1515</CharactersWithSpaces>
                <SharedDoc>false</SharedDoc>
                <HyperlinksChanged>false</HyperlinksChanged>
                <AppVersion>16.0000</AppVersion>
            </Properties>
        </pkg:xmlData>
    </pkg:part>
    <pkg:part pkg:name="/docProps/custom.xml"
        pkg:contentType="application/vnd.openxmlformats-officedocument.custom-properties+xml"
        pkg:padding="256">
        <pkg:xmlData>
            <Properties
                xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties"
                xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
                <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2"
                    name="KSOProductBuildVer">
                    <vt:lpwstr>2052-12.1.0.17857</vt:lpwstr>
                </property>
                <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="3" name="ICV">
                    <vt:lpwstr>7FC46210125347E0AEAA0D2CD94F7D81_12</vt:lpwstr>
                </property>
            </Properties>
        </pkg:xmlData>
    </pkg:part>
</pkg:package>
ruoyi-applet/HELP.md
New file
@@ -0,0 +1,18 @@
# Read Me First
The following was discovered as part of building this project:
* The JVM level was changed from '1.8' to '17', review
  the [JDK Version Range](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions#jdk-version-range)
  on the wiki for more details.
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.4/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.4/maven-plugin/reference/html/#build-image)
ruoyi-applet/pom.xml
New file
@@ -0,0 +1,201 @@
<?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.8.6</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>ruoyi-applet</artifactId>
    <description>
        applet服务入口
    </description>
    <dependencies>
        <!-- spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional> <!-- 表示依赖不会传递 -->
        </dependency>
        <!-- swagger3-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>com.github.xiaoymin</groupId>-->
<!--            <artifactId>swagger-bootstrap-ui</artifactId>-->
<!--            <version>1.9.6</version>-->
<!--        </dependency>-->
        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.6.2</version>
        </dependency>
         <!-- Mysql驱动包 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 核心模块-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-framework</artifactId>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>com.github.pagehelper</groupId>-->
<!--                    <artifactId>pagehelper-spring-boot-starter</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <!-- 定时任务-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-quartz</artifactId>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>com.github.pagehelper</groupId>-->
<!--                    <artifactId>pagehelper-spring-boot-starter</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <!-- 代码生成-->
        <dependency>
            <groupId>com.ruoyi</groupId>
            <artifactId>ruoyi-generator</artifactId>
<!--            <exclusions>-->
<!--                <exclusion>-->
<!--                    <groupId>com.github.pagehelper</groupId>-->
<!--                    <artifactId>pagehelper-spring-boot-starter</artifactId>-->
<!--                </exclusion>-->
<!--            </exclusions>-->
        </dependency>
        <!-- oos对象存储 -->
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>oss20190517</artifactId>
            <version>1.0.6</version>
        </dependency>
        <!-- Aliyun OSS SDK -->
        <dependency><groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.14.0</version></dependency>
        <!--二维码开发工具集-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>4.6.10</version>
        </dependency>
        <!-- zxing生成二维码 -->
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.apache.httpcomponents</groupId>-->
<!--            <artifactId>httpcore</artifactId>-->
<!--            <version>4.3.2</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>
        <!-- easypoi -->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot</artifactId>
        </dependency>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>dysmsapi20170525</artifactId>
            <version>2.0.10</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.15</version>
                <configuration>
                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
                </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-applet/src/main/java/com/ruoyi/RuoYiAppletApplication.java
New file
@@ -0,0 +1,58 @@
package com.ruoyi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
 * 启动程序
 *
 * @author ruoyi
 */
@Slf4j
@EnableScheduling//开启定时任务
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiAppletApplication
{
    public static void main(String[] args) throws UnknownHostException {
        ConfigurableApplicationContext application = SpringApplication.run(RuoYiAppletApplication.class, args);
        Environment env = application.getEnvironment();
        log.info("\n----------------------------------------------------------\n\t" +
                        "应用 '{}' 运行成功! 访问连接:\n\t" +
                        "Swagger文档: \t\thttp://{}:{}/doc.html\n" +
                        "----------------------------------------------------------",
                env.getProperty("spring.application.name", "后台"),
                InetAddress.getLocalHost().getHostAddress(),
                env.getProperty("server.port", "8081"));
    }
    /**
     * 当不存在此 wxRestTemplate 使用此方法的bean注入
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(name = "restTemplate")
    public RestTemplate wxRestTemplate() {
        //复杂构造函数的使用
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        // 设置超时
        requestFactory.setConnectTimeout(6000);
        requestFactory.setReadTimeout(6000);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(requestFactory);
        return restTemplate;
    }
}
ruoyi-applet/src/main/java/com/ruoyi/RuoYiServletInitializer.java
New file
@@ -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(RuoYiAppletApplication.class);
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
New file
@@ -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 javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.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-applet/src/main/java/com/ruoyi/web/controller/common/CommonController.java
New file
@@ -0,0 +1,163 @@
package com.ruoyi.web.controller.common;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.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.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.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_DELIMETER = ",";
    /**
     * 通用下载请求
     *
     * @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_DELIMETER));
            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
            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 + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        }
        catch (Exception e)
        {
            log.error("下载文件失败", e);
        }
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisConfiguration.java
New file
@@ -0,0 +1,17 @@
package com.ruoyi.web.controller.interceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfiguration {
    /**
     * 注册拦截器
     */
    @Bean
    public MybatisInterceptor getMybatisInterceptor() {
        return new MybatisInterceptor();
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/interceptor/MybatisInterceptor.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.interceptor;
import com.ruoyi.framework.web.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.*;
@Slf4j
@Component
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class MybatisInterceptor implements Interceptor {
    @Autowired
    private TokenService tokenService;
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        log.debug("{}:"+mappedStatement);
        log.debug("------sqlId------" + mappedStatement.getId());
        if("com.ruoyi.system.mapper.SysLogininforMapper.insertLogininfor".equals(mappedStatement.getId())){
            return invocation.proceed();
        }
        // sql类型:insert、update、select、delete
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        Object parameter = invocation.getArgs()[1];
        log.debug("------sqlCommandType------" + sqlCommandType);
        if (parameter == null) {
            return invocation.proceed();
        }
        // 当sql为新增或更新类型时,自动填充操作人相关信息
        if (SqlCommandType.INSERT == sqlCommandType) {
            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    // 注入创建人
                    if ("createBy".equals(field.getName())) {
                        // 获取当前登录用户信息
                        if(Objects.nonNull(tokenService.getLoginUser())){
                            String userName = tokenService.getLoginUser().getUser().getUserName();
                            field.setAccessible(true);
                            field.set(parameter, userName);
                            field.setAccessible(false);
                        }
                    }
                    //注入创建时间
                    if ("createTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to insert data, exception = ", e);
                }
            }
        }
        if (SqlCommandType.UPDATE == sqlCommandType) {
            Field[] fields = getAllFields(parameter);
            for (Field field : fields) {
                try {
                    if ("updateBy".equals(field.getName())) {
                        // 获取当前登录用户信息
                        if(Objects.nonNull(tokenService.getLoginUser())){
                            String userName = tokenService.getLoginUser().getUser().getUserName();
                            field.setAccessible(true);
                            field.set(parameter, userName);
                            field.setAccessible(false);
                        }
                    }
                    if ("updateTime".equals(field.getName())) {
                        field.setAccessible(true);
                        field.set(parameter, new Date());
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    log.error("failed to update data, exception = ", e);
                }
            }
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties) {
        // TODO Auto-generated method stub
    }
    /**
     * 获取类的所有属性,包括父类
     *
     * @param object
     * @return
     */
    private Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
New file
@@ -0,0 +1,120 @@
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 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, "密码错误次数"));
    }
    @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(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-applet/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java
New file
@@ -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-applet/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
New file
@@ -0,0 +1,82 @@
package com.ruoyi.web.controller.monitor;
import java.util.List;
import javax.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-applet/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
New file
@@ -0,0 +1,112 @@
package com.ruoyi.web.controller.monitor;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.service.ISysOperLogService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
 * 操作日志记录
 *
 * @author ruoyi
 */
@Slf4j
@Api(tags = "操作日志记录")
@RestController
@RequestMapping("/monitor/operlog")
public class SysOperlogController extends BaseController
{
    @Autowired
    private ISysOperLogService operLogService;
//    @ApiOperation(value = "操作日志分页列表")
//    @PostMapping("/list")
//    public AjaxResult list(@RequestBody SysOperLogQuery query)
//    {
//        startPage(query.getPageNum(), query.getPageSize());
//        List<SysOperLogVO> list = operLogService.selectOperLogPageList(query);
//        operLogService.getLogDetail(list);
//        return AjaxResult.success(getDataTable(list));
//    }
    /**
     * 查询操作日志列表导出
     */
//    @ApiOperation(value = "查询操作日志列表导出")
//    @Log(title = "操作日志-查询操作日志列表导出", businessType = BusinessType.EXPORT)
//    @PostMapping("/exportOperLog")
//    public void exportOperLog(@RequestBody SysOperLogQuery query)
//    {
//        List<SysOperLogVO> list = operLogService.selectOperLogPageList(query);
//        List<TOperLogExport> operLogExports = new ArrayList<>();
//        for (SysOperLogVO sysOperLogVO : list) {
//            TOperLogExport operLogExport = new TOperLogExport();
//            BeanUtils.copyProperties(sysOperLogVO,operLogExport);
//            operLogService.getLogDetail(list);
//            operLogExports.add(operLogExport);
//        }
//        Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TOperLogExport.class, operLogExports);
//        HttpServletResponse response = WebUtils.response();
//        response.setContentType("application/vnd.ms-excel");
//        response.setCharacterEncoding("utf-8");
//        ServletOutputStream outputStream = null;
//        try {
//            String fileName = URLEncoder.encode("操作日志信息.xls", "utf-8");
//            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
//            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
//            response.setHeader("Pragma", "no-cache");
//            response.setHeader("Cache-Control", "no-cache");
//            outputStream = response.getOutputStream();
//            workbook.write(outputStream);
//        } catch (IOException e) {
//            e.printStackTrace();
//            log.error("操作日志导出信息导出失败!");
//        } finally {
//            try {
//                outputStream.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//    }
//    @Log(title = "操作日志", businessType = BusinessType.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)
    @DeleteMapping("/deleteById/{operIds}")
    public AjaxResult remove(@PathVariable String operIds)
    {
        String[] split = operIds.split(",");
        List<Long> id = new ArrayList<>();
        for (String s : split) {
            id.add(Long.valueOf(s));
        }
        return AjaxResult.success(operLogService.deleteOperLogByIds(id));
    }
    @Log(title = "操作日志", businessType = BusinessType.CLEAN)
    @DeleteMapping("/clean")
    public AjaxResult clean()
    {
        operLogService.cleanOperLog();
        return success();
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
New file
@@ -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-applet/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.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;
//    @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-applet/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
New file
@@ -0,0 +1,132 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.service.ISysDeptService;
/**
 * 部门信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController
{
    @Autowired
    private ISysDeptService deptService;
    /**
     * 获取部门列表
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list")
    public AjaxResult list(SysDept dept)
    {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return AjaxResult.success(depts);
    }
    /**
     * 查询部门列表(排除节点)
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:list')")
    @GetMapping("/list/exclude/{deptId}")
    public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
    {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return AjaxResult.success(depts);
    }
    /**
     * 根据部门编号获取详细信息
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:query')")
    @GetMapping(value = "/{deptId}")
    public AjaxResult getInfo(@PathVariable Long deptId)
    {
        deptService.checkDeptDataScope(deptId);
        return AjaxResult.success(deptService.selectDeptById(deptId));
    }
    /**
     * 新增部门
     */
    // @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 AjaxResult.success(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 AjaxResult.success(deptService.updateDept(dept));
    }
    /**
     * 删除部门
     */
    // @PreAuthorize("@ss.hasPermi('system:dept:remove')")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deptId}")
    public AjaxResult remove(@PathVariable Long deptId)
    {
        if (deptService.hasChildByDeptId(deptId))
        {
            return warn("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId))
        {
            return warn("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        return AjaxResult.success(deptService.deleteDeptById(deptId));
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import javax.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-applet/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
New file
@@ -0,0 +1,131 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.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-applet/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
New file
@@ -0,0 +1,29 @@
package com.ruoyi.web.controller.system;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.utils.StringUtils;
/**
 * 首页
 *
 * @author ruoyi
 */
@RestController
public class SysIndexController
{
    /** 系统基础配置 */
    @Autowired
    private RuoYiConfig ruoyiConfig;
    /**
     * 访问首页,提示语
     */
    @RequestMapping("/")
    public String index()
    {
        return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion());
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
New file
@@ -0,0 +1,154 @@
package com.ruoyi.web.controller.system;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
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.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.service.ISysMenuService;
/**
 * 登录验证
 *
 * @author ruoyi
 */
@Api(tags = "登录")
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
    @Autowired
    private ISysMenuService menuService;
    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private ISysRoleService roleService;
    /**
     * 账号密码登录
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @ApiOperation(value = "账号密码登录",notes = "账号密码登录")
        @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        LoginUser loginUser = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, tokenService.createToken(loginUser));
        List<SysRole> roles = loginUser.getUser().getRoles();
        if(CollectionUtils.isEmpty(roles)){
            return AjaxResult.error("请关联角色!");
        }
        List<SysMenu> menus = roleService.roleInfoFromUserId(loginUser.getUserId());
        ajax.put("menus",menus);
        ajax.put("roleName",roles.get(0).getRoleName());
        ajax.put("userInfo",loginUser);
        return ajax;
    }
    /**
     * 账号密码登录
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @ApiOperation(value = "短信登录",notes = "短信登录")
    @PostMapping("/loginCode")
    public AjaxResult loginCode(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        LoginUser loginUser = loginService.loginCode(loginBody.getUsername(), loginBody.getCode());
        ajax.put(Constants.TOKEN, tokenService.createToken(loginUser));
        List<SysRole> roles = loginUser.getUser().getRoles();
        if(CollectionUtils.isEmpty(roles)){
            return AjaxResult.error("请关联角色!");
        }
        List<SysMenu> menus = roleService.roleInfoFromUserId(loginUser.getUserId());
        ajax.put("menus",menus);
        ajax.put("roleName",roles.get(0).getRoleName());
        ajax.put("userInfo",loginUser);
        return ajax;
    }
    /**
     * 获取验证码
     *
     * @param phone 手机号
     * @return 结果
     */
    @ApiOperation(value = "获取验证码",notes = "获取验证码")
    @GetMapping("/getCode")
    public AjaxResult getCode(@RequestParam String phone)
    {
        redisCache.setCacheObject(phone,"123456",5, TimeUnit.MINUTES);
        return AjaxResult.success();
    }
    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }
    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
New file
@@ -0,0 +1,168 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
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
 */
@Api(tags = "菜单信息")
@RestController
@RequestMapping("/system/menu")
public class SysMenuController extends BaseController
{
    @Autowired
    private ISysMenuService menuService;
    @ApiOperation("菜单权限(有层级)")
    @GetMapping("/levelList")
    public AjaxResult levelList()
    {
        // 获取当前角色的菜单列表
        List<SysMenu> menus = menuService.selectList();
        if(menus.size()==0){
            return AjaxResult.success(new ArrayList<>());
        }
        // 第三级
        List<SysMenu> s3 = menus.stream().filter(e -> e.getMenuType().equals("F")).collect(Collectors.toList());
        // 第二级
        List<SysMenu> s2 = menus.stream().filter(e -> e.getMenuType().equals("C")).collect(Collectors.toList());
        // 第一级
        List<SysMenu> s1 = menus.stream().filter(e -> e.getMenuType().equals("M")).collect(Collectors.toList());
        for (SysMenu menu : s2) {
            List<SysMenu> collect = s3.stream().filter(e -> e.getParentId().equals(menu.getMenuId())).collect(Collectors.toList());
            menu.setChildren(collect);
        }
        for (SysMenu menu : s1) {
            List<SysMenu> collect = s2.stream().filter(e -> e.getParentId().equals(menu.getMenuId())).collect(Collectors.toList());
            menu.setChildren(collect);
        }
        return AjaxResult.success(s1);
    }
    /**
     * 获取菜单列表
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:list')")
    @GetMapping("/list")
    public AjaxResult list(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return AjaxResult.success(menus);
    }
    /**
     * 根据菜单编号获取详细信息
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:query')")
    @GetMapping(value = "/{menuId}")
    public AjaxResult getInfo(@PathVariable Long menuId)
    {
        return AjaxResult.success(menuService.selectMenuById(menuId));
    }
    /**
     * 获取菜单下拉树列表
     */
    @GetMapping("/treeselect")
    public AjaxResult treeselect(SysMenu menu)
    {
        List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
        return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
    }
    /**
     * 加载对应角色菜单列表树
     */
    @GetMapping(value = "/roleMenuTreeselect/{roleId}")
    public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
    {
        List<SysMenu> menus = menuService.selectMenuList(getUserId());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
        ajax.put("menus", menuService.buildMenuTreeSelect(menus));
        return ajax;
    }
    /**
     * 新增菜单
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:add')")
    @Log(title = "菜单管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@Validated @RequestBody SysMenu menu)
    {
        if (!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)://开头");
        }
        menu.setCreateBy(getUsername());
        return AjaxResult.success(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() + "'失败,上级菜单不能选择自己");
        }
        menu.setUpdateBy(getUsername());
        return AjaxResult.success(menuService.updateMenu(menu));
    }
    /**
     * 删除菜单
     */
    // @PreAuthorize("@ss.hasPermi('system:menu:remove')")
    @Log(title = "菜单管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{menuId}")
    public AjaxResult remove(@PathVariable("menuId") Long menuId)
    {
        if (menuService.hasChildByMenuId(menuId))
        {
            return warn("存在子菜单,不允许删除");
        }
        if (menuService.checkMenuExistRole(menuId))
        {
            return warn("菜单已分配,不允许删除");
        }
        return AjaxResult.success(menuService.deleteMenuById(menuId));
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
New file
@@ -0,0 +1,91 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.system.domain.SysNotice;
import com.ruoyi.system.service.ISysNoticeService;
/**
 * 公告 信息操作处理
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/notice")
public class SysNoticeController extends BaseController
{
    @Autowired
    private ISysNoticeService noticeService;
    /**
     * 获取通知公告列表
     */
    @PreAuthorize("@ss.hasPermi('system:notice:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysNotice notice)
    {
//        startPage();
        List<SysNotice> list = noticeService.selectNoticeList(notice);
        return getDataTable(list);
    }
    /**
     * 根据通知公告编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:notice:query')")
    @GetMapping(value = "/{noticeId}")
    public AjaxResult getInfo(@PathVariable Long noticeId)
    {
        return 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));
    }
    /**
     * 删除通知公告
     */
    @PreAuthorize("@ss.hasPermi('system:notice:remove')")
    @Log(title = "通知公告", businessType = BusinessType.DELETE)
    @DeleteMapping("/{noticeIds}")
    public AjaxResult remove(@PathVariable Long[] noticeIds)
    {
        return toAjax(noticeService.deleteNoticeByIds(noticeIds));
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
New file
@@ -0,0 +1,129 @@
package com.ruoyi.web.controller.system;
import java.util.List;
import javax.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-applet/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
New file
@@ -0,0 +1,136 @@
package com.ruoyi.web.controller.system;
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.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
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("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
        {
            return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
        }
        if (userService.updateUserProfile(currentUser) > 0)
        {
            // 更新缓存用户信息
            tokenService.setLoginUser(loginUser);
            return success();
        }
        return error("修改个人信息异常,请联系管理员");
    }
    /**
     * 重置密码
     */
    @Log(title = "个人信息", businessType = BusinessType.UPDATE)
    @PutMapping("/updatePwd")
    public AjaxResult updatePwd(String oldPassword, String newPassword)
    {
        LoginUser loginUser = getLoginUser();
        String userName = loginUser.getUsername();
        String password = loginUser.getPassword();
        if (!SecurityUtils.matchesPassword(oldPassword, password))
        {
            return error("修改密码失败,旧密码错误");
        }
        if (SecurityUtils.matchesPassword(newPassword, password))
        {
            return error("新密码不能与旧密码相同");
        }
        if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
        {
            // 更新缓存用户密码
            loginUser.getUser().setPassword(SecurityUtils.encryptPassword(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);
            if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
            {
                AjaxResult ajax = AjaxResult.success();
                ajax.put("imgUrl", avatar);
                // 更新缓存用户头像
                loginUser.getUser().setAvatar(avatar);
                tokenService.setLoginUser(loginUser);
                return ajax;
            }
        }
        return error("上传图片异常,请联系管理员");
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
New file
@@ -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-applet/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
New file
@@ -0,0 +1,320 @@
package com.ruoyi.web.controller.system;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.system.dto.SysRoleDTO;
import com.ruoyi.system.query.SysRoleQuery;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.vo.RoleInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.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
 */
@Api(tags = "角色信息")
@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;
    @Autowired
    private ISysMenuService menuService;
    // @PreAuthorize("@ss.hasPermi('system:role:list')")
    @ApiOperation(value = "角色列表")
    @PostMapping("/list")
    public AjaxResult list(@RequestBody SysRoleQuery query)
    {
        PageInfo<SysRole> list = roleService.selectList(query);
        return AjaxResult.success(list);
    }
    @ApiOperation(value = "角色列表不分页")
    @PostMapping("/listNotPage")
    public AjaxResult list()
    {
        List<SysRole> list = roleService.selectRoleList(new SysRole());
        return AjaxResult.success(list);
    }
    @ApiOperation(value = "角色数量统计")
    @PostMapping("/roleCount")
    public AjaxResult roleCount()
    {
        int all = roleService.selectCount(null);
        int normal = roleService.selectCount(0);
        int stop = roleService.selectCount(1);
        Map<String,Integer> map = new HashMap<>();
        map.put("all",all);
        map.put("normal",normal);
        map.put("stop",stop);
        return AjaxResult.success(map);
    }
//    @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 AjaxResult.success(roleService.selectRoleById(roleId));
    }
    @ApiOperation("角色详情")
    @GetMapping("/roleInfo")
    public AjaxResult roleInfo(@RequestParam Long roleId)
    {
        SysRole role = roleService.selectRoleById(roleId);
        RoleInfoVO roleInfoVo = new RoleInfoVO();
        roleInfoVo.setRoleId(role.getRoleId());
        roleInfoVo.setRoleName(role.getRoleName());
        // 获取当前角色的菜单列表
        List<SysMenu> menus = menuService.selectListByRoleId(roleId);
        if(menus.size()==0){
            return AjaxResult.success(new ArrayList<>());
        }
        List<Long> menusId = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
        // 获取当前的权限菜单(有层级)
        List<SysMenu> levelMenus = roleService.getMenuLevelList(menusId);
        roleInfoVo.setMenus(menusId);
        return AjaxResult.success(roleInfoVo);
    }
    @ApiOperation("用户获取权限菜单")
    @GetMapping("/roleInfoFromUserId")
    public AjaxResult roleInfoFromUserId(@RequestParam Long userId)
    {
        return AjaxResult.success(roleService.roleInfoFromUserId(userId));
    }
    /**
     * 新增角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:add')")
    @ApiOperation(value = "新增角色")
    @Log(title = "角色信息-新增角色", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody SysRoleDTO dto)
    {
        Boolean flag= roleService.isExit(dto.getRoleId(),dto.getRoleName());
        if(flag){
            return error("新增角色'" + dto.getRoleName() + "'失败,角色名称已存在");
        }
        roleService.saveRole(dto);
        return AjaxResult.success();
    }
    /**
     * 修改保存角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @ApiOperation(value = "编辑角色")
    @Log(title = "角色信息-编辑角色", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Validated @RequestBody SysRoleDTO dto)
    {
        Boolean flag= roleService.isExit(dto.getRoleId(),dto.getRoleName());
        if (flag){
            return error("修改角色'" + dto.getRoleName() + "'失败,角色名称已存在");
        }
        if (roleService.editRole(dto) > 0)
        {
            // 更新缓存用户权限
            LoginUser loginUser = getLoginUser();
            if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
            {
                loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
                loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
                tokenService.setLoginUser(loginUser);
            }
            return AjaxResult.success();
        }
        return error("修改角色'" + dto.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 AjaxResult.success(roleService.authDataScope(role));
    }
    /**
     * 状态修改
     */
    // @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @ApiOperation(value = "状态修改")
    @Log(title = "角色信息-角色状态修改", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysRole role)
    {
        role.setUpdateBy(getUsername());
        roleService.updateStatus(role);
        return AjaxResult.success();
    }
    /**
     * 删除角色
     */
    // @PreAuthorize("@ss.hasPermi('system:role:remove')")
    @ApiOperation(value = "删除角色")
    @Log(title = "角色信息-角色删除角色", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteById/{ids}")
    public AjaxResult remove(@PathVariable String ids)
    {
        String[] split = ids.split(",");
        List<Long> id = new ArrayList<>();
        for (String s : split) {
            id.add(Long.valueOf(s));
        }
        return AjaxResult.success(roleService.deleteRoleByIds(id));
    }
    /**
     * 获取角色选择框列表
     */
    // @PreAuthorize("@ss.hasPermi('system:role:query')")
    @GetMapping("/optionselect")
    public AjaxResult optionselect()
    {
        return AjaxResult.success(roleService.selectRoleAll());
    }
    /**
     * 查询已分配用户角色列表
     */
    // @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/allocatedList")
    public TableDataInfo allocatedList(SysUser user)
    {
//        startPage();
        List<SysUser> list = userService.selectAllocatedList(user);
        return getDataTable(list);
    }
    /**
     * 查询未分配用户角色列表
     */
    // @PreAuthorize("@ss.hasPermi('system:role:list')")
    @GetMapping("/authUser/unallocatedList")
    public TableDataInfo unallocatedList(SysUser user)
    {
//        startPage();
        List<SysUser> list = userService.selectUnallocatedList(user);
        return getDataTable(list);
    }
    /**
     * 取消授权用户
     */
    // @PreAuthorize("@ss.hasPermi('system:role:edit')")
    @Log(title = "角色管理", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancel")
    public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
    {
        return AjaxResult.success(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 AjaxResult.success(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 AjaxResult.success(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-applet/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
New file
@@ -0,0 +1,401 @@
package com.ruoyi.web.controller.system;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
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.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.dto.SysUserUpdateStatusDTO;
import com.ruoyi.system.query.SysUserQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.vo.SysUserVO;
import com.ruoyi.system.vo.UserAddListVO;
import com.ruoyi.system.vo.UserLevelVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.*;
import java.util.stream.Collectors;
/**
 * 用户信息
 *
 * @author ruoyi
 */
@Api(tags = "用户信息")
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController
{
    @Autowired
    private ISysUserService userService;
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private TokenService tokenService;
    /**
     * 获取用户列表
     */
    @ApiOperation(value = "获取用户列表")
    @PostMapping("/list")
    public AjaxResult list(@RequestBody SysUserQuery query)
    {
        PageInfo<SysUserVO> list = userService.pageList(query);
        return AjaxResult.success(list);
    }
    @ApiOperation(value = "获取用户列表-不分页")
    @PostMapping("/listNotPage")
    public AjaxResult listNotPage()
    {
        List<SysUser> list = userService.selectList();
        return AjaxResult.success(list);
    }
    /**
     * 获取用户黑名单列表
     */
//    @ApiOperation(value = "获取用户黑名单列表")
//    @PostMapping("/blacklist")
//    public AjaxResult blacklist(@RequestBody SysUserQuery query)
//    {
//        startPage(query.getPageNum(), query.getPageSize());
//        List<SysUserVO> list = userService.selectBlackPageList(query);
//        return AjaxResult.success(getDataTable(list));
//    }
    /**
     * 人员借用列表
     */
//    @ApiOperation(value = "人员借用列表")
//    @GetMapping("/userBorrowList")
//    public AjaxResult userBorrowList(@RequestParam(required = false) String name,
//                                     @RequestParam(required = false) Integer type)
//    {
//
//        UserAddListVO userAddListVO = new UserAddListVO();
//
//        Long companyId = tokenService.getLoginUser().getUser().getCompanyId();
//
//        List<TCompany> companyList = new ArrayList<>();
//        List<TDept> deptList = new ArrayList<>();
//        List<SysUser> userList = new ArrayList<>();
//        // 查询公司
//        if(Objects.nonNull(type) && type == 1){
//            companyList = companyService.userAddListByCompanyName(name);
//        }
//        // 查询部门
//        if(Objects.nonNull(type) && type == 2){
//            deptList = tDeptService.userAddListByDeptName(name);
//        }
//        // 查询用户
//        if(Objects.nonNull(type) && type == 3){
//            userList = userService.selectListByNamePhone(name);
//        }
//
//        if(Objects.isNull(type)){
//            companyList = companyService.userAddListByCompanyName(name);
//            deptList = tDeptService.userAddListByDeptName(name);
//            userList = userService.selectListByNamePhone(name);
//        }
//
//        List<Long> companyIds = companyList.stream().map(TCompany::getId).collect(Collectors.toList());
//        List<Long> deptCompanyIds = deptList.stream().map(TDept::getCompanyId).collect(Collectors.toList());
//        List<Long> userCompanyIds = userList.stream().map(SysUser::getCompanyId).collect(Collectors.toList());
//        companyIds.addAll(deptCompanyIds);
//        companyIds.addAll(userCompanyIds);
//
//        companyIds = companyIds.stream().distinct().collect(Collectors.toList());
//
//        if(CollectionUtils.isEmpty(companyIds)){
//            return AjaxResult.success(userAddListVO);
//        }
//        SysUser user1 = tokenService.getLoginUser().getUser();
//        if(!user1.isAdmin()){
//            companyIds = companyIds.stream().filter(e->!e.equals(companyId)).collect(Collectors.toList());
//        }
//
//        // 查询符合要求的公司
//        List<UserLevelVO> parent = companyService.userAddListByCompanyIds(companyIds);
//
//        List<TDept> depts = tDeptService.selectList();
//
//        List<SysUser> sysUsers = userService.selectList();
//
//        for (UserLevelVO userLevelVO : parent) {
//
//            // 找到公司下的部门
//            List<TDept> tDepts = depts.stream().filter(e -> userLevelVO.getKey().equals(e.getCompanyId())).collect(Collectors.toList());
//            List<UserLevelVO> children = new ArrayList<>();
//            // 封装部门
//            for (TDept dept : tDepts) {
//                userLevelVO.setChildren(children);
//                UserLevelVO userLevelVO1 = new UserLevelVO();
//                userLevelVO1.setKey(dept.getId());
//                userLevelVO1.setTitle(dept.getDeptName());
//                // 找到部门下的人员
//                List<SysUser> users;
//                if(StringUtils.isNotEmpty(name) && type == 3){
//                    users = sysUsers.stream().filter(e -> userLevelVO1.getKey().equals(e.getDeptId())
//                            && ((StringUtils.isNotEmpty(e.getNickName()) && e.getNickName().contains(name)))
//                            || (StringUtils.isNotEmpty(e.getPhonenumber()) && e.getPhonenumber().contains(name))).collect(Collectors.toList());
//                }else {
//                    users = sysUsers.stream().filter(e -> userLevelVO1.getKey().equals(e.getDeptId())).collect(Collectors.toList());
//                }
//                List<UserLevelVO> children1 = new ArrayList<>();
//                // 封装人员
//                for (SysUser user : users) {
//                    UserLevelVO userLevelVO2 = new UserLevelVO();
//                    userLevelVO2.setKey(user.getUserId());
//                    userLevelVO2.setTitle(user.getNickName());
//                    userLevelVO2.setAvatar(user.getAvatar());
//                    userLevelVO2.setFlag(true);
//                    children1.add(userLevelVO2);
//                }
//                userLevelVO1.setChildren(children1);
//
//                children.add(userLevelVO1);
//            }
//            userLevelVO.setChildren(children);
//        }
//        userAddListVO.setUserLevelVOS(parent);
//        userAddListVO.setUserList(sysUsers);
//        return AjaxResult.success(userAddListVO);
//    }
    /**
     * 获取用户详情
     */
    @ApiOperation(value = "获取用户详情")
    @GetMapping("/getDetail")
    public AjaxResult getDetail(@RequestParam Long userId)
    {
        SysUser sysUser = userService.selectUserById(userId);
        SysUserVO sysUserVO = new SysUserVO();
        BeanUtils.copyProperties(sysUser,sysUserVO);
        return AjaxResult.success(sysUser);
    }
    /**
     * 获取用户数量统计
     */
    @ApiOperation(value = "获取用户数量统计")
    @PostMapping("/getUserCount")
    public AjaxResult getUserCount()
    {
        Map<String,Integer> map = new HashMap<>();
        Integer userCountSum = userService.selectCount(null);
        Integer normalCount = userService.selectCount(0);// 正常
        Integer stopCount = userService.selectCount(1);// 停用
        map.put("all",userCountSum);
        map.put("normal",normalCount);
        map.put("stop",stopCount);
        return AjaxResult.success(map);
    }
    /**
     * 移除黑名单
     */
    @GetMapping("/removeBlackList")
    public AjaxResult removeBlackList(@RequestParam String ids)
    {
        String[] split = ids.split(",");
        List<Long> id = new ArrayList<>();
        for (String s : split) {
            id.add(Long.valueOf(s));
        }
        userService.updateUserIfBlack(id);
        return AjaxResult.success();
    }
//    @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 AjaxResult.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:add')")
    @ApiOperation(value = "新增用户管理")
    @Log(title = "用户信息-新增用户", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@Validated @RequestBody SysUser user)
    {
        user.setUserName(user.getPhonenumber());
        if (!userService.checkUserNameUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("新增用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        user.setCreateBy(getUsername());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        userService.insertUser(user);
        return AjaxResult.success();
    }
    /**
     * 修改用户
     */
    // @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @ApiOperation(value = "修改用户管理")
    @Log(title = "用户信息-修改用户", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    public AjaxResult edit(@Validated @RequestBody SysUser user)
    {
        user.setUserName(user.getPhonenumber());
//        userService.checkUserAllowed(user);
//        userService.checkUserDataScope(user.getUserId());
        if (!userService.checkUserNameUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,登录账号已存在");
        }
        else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
        {
            return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
        }
        user.setUpdateBy(getUsername());
        return AjaxResult.success(userService.updateUser(user));
    }
    /**
     * 删除用户
     */
    // @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @ApiOperation(value = "批量删除用户")
    @Log(title = "用户信息-批量删除用户", businessType = BusinessType.DELETE)
    @DeleteMapping("/deleteById/{ids}")
    public AjaxResult remove(@PathVariable String ids)
    {
        String[] split = ids.split(",");
        List<Long> userIds = new ArrayList<>();
        for (String s : split) {
            userIds.add(Long.valueOf(s));
        }
        if (userIds.contains(getUserId()))
        {
            return error("当前用户不能删除");
        }
        return AjaxResult.success(userService.deleteUserByIds(userIds));
    }
    /**
     * 重置密码
     */
    // @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @ApiOperation(value = "重置密码")
    @Log(title = "用户信息-重置密码", businessType = BusinessType.UPDATE)
    @PostMapping("/resetPwd")
    public AjaxResult resetPwd(@RequestBody SysUser user)
    {
        userService.checkUserAllowed(user);
//        userService.checkUserDataScope(user.getUserId());
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
        user.setUpdateBy(getUsername());
        return AjaxResult.success(userService.resetPwd(user));
    }
    /**
     * 状态修改
     */
    @ApiOperation(value = "状态修改")
    @Log(title = "用户信息-状态修改", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public AjaxResult changeStatus(@RequestBody SysUserUpdateStatusDTO dto)
    {
        SysUser user = new SysUser();
        user.setUserId(dto.getUserId());
        user.setStatus(String.valueOf(dto.getStatus()));
        user.setUpdateBy(getUsername());
        return AjaxResult.success(userService.updateUserStatus(user));
    }
    /**
     * 根据用户编号获取授权角色
     */
    // @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    public AjaxResult authRole(@PathVariable("userId") Long userId)
    {
        AjaxResult ajax = AjaxResult.success();
        SysUser user = userService.selectUserById(userId);
        List<SysRole> roles = roleService.selectRolesByUserId(userId);
        ajax.put("user", user);
        ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
        return ajax;
    }
    /**
     * 用户授权角色
     */
    // @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
    {
        userService.checkUserDataScope(userId);
        userService.insertUserAuth(userId, roleIds);
        return AjaxResult.success();
    }
    /**
     * 获取部门树列表
     */
    // @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    public AjaxResult deptTree(SysDept dept)
    {
        return AjaxResult.success(deptService.selectDeptTreeList(dept));
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/BaiDuApi.java
New file
@@ -0,0 +1,180 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
/**
 * 百度文字识别
 */
@Slf4j
public class BaiDuApi {
    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();
    public static void main(String []args) throws IOException{
//        String url = "C:\\Users\\Admin\\Desktop\\picture\\6fd629ac-3327-4bdc-9459-fcb5295384bc.jpg";
        String url = "C:\\Users\\Admin\\Desktop\\picture\\6fd629ac-3327-4bdc-9459-fcb5295384bc.jpg";
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
//        System.err.println(response.body().string());
        Map<String,Object> map = new HashMap<>();
        String string = response.body().string();
        String idCard = string.substring(string.lastIndexOf("单号:") + 3, string.lastIndexOf("单号:") + 27);
        String time = string.substring(string.lastIndexOf("零时起") + 3, string.lastIndexOf("二十四时")-1);
        time = time.replace(".","-");
        map.put("idCard",idCard);
        map.put("time",time);
        System.err.println(map);
    }
    /**
     * 资质证明证件识别
     * @param url
     * @return
     * @throws IOException
     */
    public static Map<String,Object> qualification(String url) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        Map<String,Object> map = new HashMap<>();
        try{
            String string = response.body().string();
            String idCard = string.substring(string.lastIndexOf("号:") + 2, string.lastIndexOf("号:") + 21);
            String time = string.substring(string.lastIndexOf("至") + 1, string.lastIndexOf("至") + 11);
            time = time.replace(".","-");
            map.put("idCard",idCard);
            map.put("time",time);
        }catch (Exception e){
            log.error("资质证明证件识别错误!");
            throw new ServiceException("资质证明证件识别错误!");
        }
        return map;
    }
    /**
     * 身份证识别
     * @param url
     * @return
     * @throws IOException
     */
    public static Map<String,Object> idCard(String url) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        Map<String,Object> map = new HashMap<>();
        try{
            JSONObject jsonObject = JSONObject.parseObject(response.body().string());
            JSONArray jsonArray = JSONObject.parseArray(jsonObject.getString("words_result"));
            JSONObject obj1 = JSONObject.parseObject(jsonArray.get(0).toString());
            String name = obj1.getString("words");
            name = name.substring(2);
            JSONObject obj2 = JSONObject.parseObject(jsonArray.get(1).toString());
            String sexStr = obj2.getString("words");
            sexStr = sexStr.substring(2, 3);
            int sex = "男".equals(sexStr)?0:1;
            JSONObject obj3 = JSONObject.parseObject(jsonArray.get(3).toString());
            JSONObject obj4 = JSONObject.parseObject(jsonArray.get(4).toString());
            String address = obj3.getString("words") + obj4.getString("words");
            address = address.substring(2);
            JSONObject obj5 = JSONObject.parseObject(jsonArray.get(5).toString());
            String idCard = obj5.getString("words");
            idCard = idCard.substring(6);
            map.put("name",name);
            map.put("sex",sex);
            map.put("address",address);
            map.put("idCard",idCard);
        }catch (Exception e){
            log.error("身份证件识别错误!");
            throw new ServiceException("身份证件识别错误!");
        }
        return map;
    }
    /**
     * 通用文字识别(标准版)
     * @param url
     * @return
     * @throws IOException
     */
    public static JSONObject pictureOcr(String url) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image="+getFileContentAsBase64(url,true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token="+getAccessToken())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        return JSONObject.parseObject(response.body().string());
    }
    public static String getAccessToken() throws IOException {
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "");
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/oauth/2.0/token?client_id=2RkKEqd0ltIHPvnIf3G0VpHE&client_secret=RBpPt3O64e3e4BK7pG3lP0o8I6SGgiUy&grant_type=client_credentials")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject jsonObject = JSONObject.parseObject(response.body().string());
        return jsonObject.getString("access_token");
    }
    /**
     * 获取文件base64编码
     *
     * @param path      文件路径
     * @param urlEncode 如果Content-Type是application/x-www-form-urlencoded时,传true
     * @return base64编码信息,不带文件头
     * @throws IOException IO异常
     */
    static String getFileContentAsBase64(String path, boolean urlEncode) throws IOException {
        byte[] b = Files.readAllBytes(Paths.get(path));
        String base64 = Base64.getEncoder().encodeToString(b);
        if (urlEncode) {
            base64 = URLEncoder.encode(base64, "utf-8");
        }
        return base64;
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/HttpClientUtil.java
New file
@@ -0,0 +1,79 @@
package com.ruoyi.web.controller.tool;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
 * @author zhy
 * @title: HttpClientUtil
 * @projectName car_park
 * @description: http连接工具类
 * @date 2019/10/2219:23
 */
public class HttpClientUtil {
    /**
     * @param strUrl
     * @return byte[]
     * @throws
     * @description: 获取网络图片转成字节流
     * @author zhy
     * @date 2019/10/23 8:59
     */
    public static byte[] getImageFromNetByUrl(String strUrl) {
        if (!isURL(strUrl)){
            return null;
        }
        try {
            URL url = new URL(strUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(2 * 1000);
            InputStream inStream = conn.getInputStream();// 通过输入流获取图片数据
            byte[] btImg = readInputStream(inStream);// 得到图片的二进制数据
            return btImg;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 从输入流中获取字节流数据
     *
     * @param inStream 输入流
     * @return
     * @throws Exception
     */
    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[10240];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        inStream.close();
        return outStream.toByteArray();
    }
    public static boolean isURL(String str) {
        str = str.toLowerCase();
        String regex = "^((https|http|ftp|rtsp|mms)?://)"
                + "?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?"
                + "(([0-9]{1,3}\\.){3}[0-9]{1,3}"
                + "|"
                + "([0-9a-z_!~*'()-]+\\.)*"
                + "([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\\."
                + "[a-z]{2,6})"
                + "(:[0-9]{1,5})?"
                + "((/?)|"
                + "(/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+/?)$";
        return str.matches(regex);
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/ImportExcelUtil.java
New file
@@ -0,0 +1,39 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.R;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
/**
 * 导出返回信息
 */
@Slf4j
public class ImportExcelUtil {
    /**
     * @param errorLines   错误行数
     * @param successLines 成功行数
     * @param errorMessage 错误信息
     * @return
     * @throws IOException
     */
    public static R<String> importReturnMsg(int errorLines, int successLines, List<String> errorMessage) throws IOException {
        if (errorLines == 0) {
            return R.ok("共" + successLines + "行数据全部导入成功!");
        } else {
            JSONObject result = new JSONObject(5);
            int totalCount = successLines + errorLines;
            result.put("totalCount", totalCount);
            result.put("errorCount", errorLines);
            result.put("errorMessage", errorMessage);
            result.put("successCount", successLines);
            result.put("msg", "总上传行数:" + totalCount + ",已导入行数:" + successLines + ",错误行数:" + errorLines);
            return R.ok(JSON.toJSONString(result));
        }
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MsgCodeUtil.java
New file
@@ -0,0 +1,61 @@
package com.ruoyi.web.controller.tool;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.system.code.SubmitTemplateReg;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
/**
 * 短信工具类
 */
public class MsgCodeUtil implements Serializable {
    /**接口账号用户名*/
    private static final String AP_ID = "";
    /**企业名称*/
    private static final String EC_NAME = "";
    /**签名*/
    private static final String SECRET_KEY = "";
    /**签名编码*/
    private static final String SIGN = "";
    /**模板ID*/
    private static final String TEMPLATE_ID = "";
    /**
     * 实体封装
     * @param code
     * @return
     */
    public static SubmitTemplateReg getSubmitTemplateReg(String code,String mobiles) {
        SubmitTemplateReg submitReg =new SubmitTemplateReg();
        String[] paramss = {code};
        submitReg.setApId(AP_ID);
        submitReg.setEcName(EC_NAME);
        submitReg.setSecretKey(SECRET_KEY);
        submitReg.setParams(JSONObject.toJSONString(paramss));
        submitReg.setMobiles(mobiles);
        submitReg.setAddSerial("");
        submitReg.setSign(SIGN);
        submitReg.setTemplateId(TEMPLATE_ID);
        submitReg.setMac(TEMPLATE_ID);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(submitReg.getEcName( ));stringBuffer.append(submitReg.getApId());
        stringBuffer.append(submitReg.getSecretKey());stringBuffer.append(submitReg.getTemplateId());stringBuffer.append(submitReg.getMobiles());
        stringBuffer.append(submitReg.getParams());stringBuffer.append(submitReg.getSign());stringBuffer.append(submitReg.getAddSerial());
        submitReg.setMac(Hex.encodeHexString(stringBuffer.toString().getBytes(StandardCharsets.UTF_8)));
        String regText = JSONObject.toJSONString(submitReg);
        //加密
        String encode = Base64.encodeBase64String(regText.getBytes());
        System.err.println(encode);
        return submitReg;
    }
    public static void main(String[] args) {
        getSubmitTemplateReg("123456","18398968484");
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/MsgUtils.java
New file
@@ -0,0 +1,70 @@
package com.ruoyi.web.controller.tool;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class MsgUtils {
    @Value("${code.config.accessKeyId}")
    private  String accessKeyId;
    @Value("${code.config.accessKeySecret}")
    private  String accessKeySecret;
    @Value("${code.config.signName}")
    private  String signName;
    @Value("${code.config.templateCode}")
    private  String templateCode;
    @Value("${code.config.signNameTest}")
    private  String signNameTest;
    @Value("${code.config.templateCodeTest}")
    private  String templateCodeTest;
    /**
     * 使用AK&SK初始化账号Client
     * @param accessKeyId
     * @param accessKeySecret
     * @return Client
     * @throws Exception
     */
    public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
        Config config = new Config()
                // 您的 AccessKey ID
                .setAccessKeyId(accessKeyId)
                // 您的 AccessKey Secret
                .setAccessKeySecret(accessKeySecret);
        // 访问的域名
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new com.aliyun.dysmsapi20170525.Client(config);
    }
    public void sendMsg(String phone,String code) throws Exception {
        com.aliyun.dysmsapi20170525.Client client = MsgUtils.createClient(accessKeyId,accessKeySecret);
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setPhoneNumbers(phone)
                .setTemplateParam("{\"code\":\""+code+"\"}");
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            // 复制代码运行请自行打印 API 的返回值
            SendSmsResponse sendSmsResponse = client.sendSmsWithOptions(sendSmsRequest, runtime);
            log.info("短信发送成功:{},{}",sendSmsResponse.getBody().getMessage(),sendSmsResponse.getStatusCode());
        } catch (TeaException error) {
            // 如有需要,请打印 error
            com.aliyun.teautil.Common.assertAsString(error.message);
            log.info("短信发送失败:{}",error.message);
        } catch (Exception _error) {
            TeaException error = new TeaException(_error.getMessage(), _error);
            // 如有需要,请打印 error
            com.aliyun.teautil.Common.assertAsString(error.message);
            log.info("短信发送失败:{}",error.message);
        }
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/QRCodeUtil.java
New file
@@ -0,0 +1,124 @@
package com.ruoyi.web.controller.tool;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
/**
 * 二维码工具
 * @Author:debug (SteadyJack)
 * @Link: weixin-> debug0868  qq-> 1948831260
 * @Date: 2020/11/16 22:38
 **/
public class QRCodeUtil {
    private static final Logger log= LoggerFactory.getLogger(QRCodeUtil.class);
    //CODE_WIDTH:二维码宽度,单位像素
    private static final int CODE_WIDTH = 400;
    //CODE_HEIGHT:二维码高度,单位像素
    private static final int CODE_HEIGHT = 400;
    //FRONT_COLOR:二维码前景色,0x000000 表示黑色
    private static final int FRONT_COLOR = 0x000000;
    //BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色
    //演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白
    private static final int BACKGROUND_COLOR = 0xFFFFFF;
    public static void main(String[] args) {
        createCodeToFile("5261548530",new File("C:\\Users\\Admin\\Desktop\\qrcode"),"5261548530.png");
    }
    public static void createCodeToFile(String content, File codeImgFileSaveDir, String fileName) {
        try {
            if (StringUtils.isBlank(content) || StringUtils.isBlank(fileName)) {
                return;
            }
            content = content.trim();
            if (codeImgFileSaveDir==null || codeImgFileSaveDir.isFile()) {
                //二维码图片存在目录为空,默认放在桌面...
                codeImgFileSaveDir = FileSystemView.getFileSystemView().getHomeDirectory();
            }
            if (!codeImgFileSaveDir.exists()) {
                //二维码图片存在目录不存在,开始创建...
                codeImgFileSaveDir.mkdirs();
            }
            //核心代码-生成二维码
            BufferedImage bufferedImage = getBufferedImage(content);
            File codeImgFile = new File(codeImgFileSaveDir, fileName);
            ImageIO.write(bufferedImage, "png", codeImgFile);
            log.info("二维码图片生成成功:" + codeImgFile.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 生成二维码并输出到输出流, 通常用于输出到网页上进行显示,输出到网页与输出到磁盘上的文件中,区别在于最后一句 ImageIO.write
     * write(RenderedImage im,String formatName,File output):写到文件中
     * write(RenderedImage im,String formatName,OutputStream output):输出到输出流中
     * @param content  :二维码内容
     * @param outputStream :输出流,比如 HttpServletResponse 的 getOutputStream
     */
    public static void createCodeToOutputStream(String content, OutputStream outputStream) {
        try {
            if (StringUtils.isBlank(content)) {
                return;
            }
            content = content.trim();
            //核心代码-生成二维码
            BufferedImage bufferedImage = getBufferedImage(content);
            //区别就是这一句,输出到输出流中,如果第三个参数是 File,则输出到文件中
            ImageIO.write(bufferedImage, "png", outputStream);
            log.info("二维码图片生成到输出流成功...");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //核心代码-生成二维码
    private static BufferedImage getBufferedImage(String content) throws WriterException {
        //com.google.zxing.EncodeHintType:编码提示类型,枚举类型
        Map<EncodeHintType, Object> hints = new HashMap();
        //EncodeHintType.CHARACTER_SET:设置字符编码类型
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //EncodeHintType.ERROR_CORRECTION:设置误差校正
        //ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
        //不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        //EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近
        hints.put(EncodeHintType.MARGIN, 1);
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints);
        BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR);
        for (int x = 0; x < CODE_WIDTH; x++) {
            for (int y = 0; y < CODE_HEIGHT; y++) {
                bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR);
            }
        }
        return bufferedImage;
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TaskUtil.java
New file
@@ -0,0 +1,106 @@
package com.ruoyi.web.controller.tool;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.core.domain.entity.SysRole;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.Instant;
import java.util.*;
/**
 * 定时任务工具类
 */
@Slf4j
@Component
public class TaskUtil {
    @Autowired
    private ISysRoleService roleService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private RedisCache redisCache;
    @Scheduled(fixedRate = 1000 * 60)
    public void message() {
        try {
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 每隔一分钟去处理的定时任务
     */
    @Scheduled(fixedRate = 1000 * 60)
    public void taskMinute(){
        try {
//            List<Message> list = messageService.list();
//            Map<Integer,List<Message>> map = new LinkedHashMap<>();
//            for (Message message : list) {
//                if (map.get(message.getUserId())==null){
//                    List<Message> messages = new ArrayList<>();
//                    messages.add(message);
//                    map.put(message.getUserId(),messages);
//                    System.err.println("为空");
//                }else {
//                    List<Message> messages = map.get(message.getUserId());
//                    messages.add(message);
//                    map.put(message.getUserId(),messages);
//                }
//            }
//            Object cacheObject = redisCache.getCacheObject("1");
//            Set<Integer> integers = map.keySet();
//            for (Integer integer : integers) {
//                redisCache.deleteObject(String.valueOf(integer));
//                redisCache.setCacheList(String.valueOf(integer),map.get(integer));
//                List<Message> cacheList = redisCache.getCacheList(String.valueOf(integer));
//                System.err.println("====="+cacheList);
//            }
//
//
//            System.err.println("======="+map);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 每天的凌晨执行的任务
     */
    @Scheduled(cron = "0 0 0 * * *")
    public void taskDay(){
        List<SysRole> sysRoles = roleService.selectListByDelFlag(2);
        if(CollectionUtils.isEmpty(sysRoles)){
            return;
        }
        for (SysRole sysRole : sysRoles) {
            if(sysRole.getRemoveDays()>0){
                sysRole.setRemoveDays(sysRole.getRemoveDays()-1);
                roleService.updateRole(sysRole);
            }else {
                roleService.deleteRoleById(sysRole.getRoleId());
            }
        }
    }
    /**
     * 每天的凌晨执行的任务
     */
    @Scheduled(cron = "0 0 1 * * ? ")
    public void taskDayOne(){
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/tool/TestController.java
New file
@@ -0,0 +1,177 @@
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.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
/**
 * swagger 用户测试方法
 *
 * @author ruoyi
 */
@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"));
    }
    @GetMapping("/list")
    public R<List<UserEntity>> userList()
    {
        List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
        return R.ok(userList);
    }
    @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
    @GetMapping("/{userId}")
    public R<UserEntity> getUser(@PathVariable Integer userId)
    {
        if (!users.isEmpty() && users.containsKey(userId))
        {
            return R.ok(users.get(userId));
        }
        else
        {
            return R.fail("用户不存在");
        }
    }
    @ApiImplicitParams({
        @ApiImplicitParam(name = "userId", value = "用户id", dataType = "Integer", dataTypeClass = Integer.class),
        @ApiImplicitParam(name = "username", value = "用户名称", dataType = "String", dataTypeClass = String.class),
        @ApiImplicitParam(name = "password", value = "用户密码", dataType = "String", dataTypeClass = String.class),
        @ApiImplicitParam(name = "mobile", value = "用户手机", dataType = "String", dataTypeClass = String.class)
    })
    @PostMapping("/save")
    public 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();
    }
    @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();
    }
    @ApiImplicitParam(name = "userId", value = "用户ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
    @DeleteMapping("/{userId}")
    public R<String> delete(@PathVariable Integer userId)
    {
        if (!users.isEmpty() && users.containsKey(userId))
        {
            users.remove(userId);
            return R.ok();
        }
        else
        {
            return R.fail("用户不存在");
        }
    }
}
@ApiModel(value = "UserEntity", description = "用户实体")
class UserEntity
{
    @ApiModelProperty("用户ID")
    private Integer userId;
    @ApiModelProperty("用户名称")
    private String username;
    @ApiModelProperty("用户密码")
    private String password;
    @ApiModelProperty("用户手机")
    private String mobile;
    public UserEntity()
    {
    }
    public UserEntity(Integer userId, String username, String password, String mobile)
    {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.mobile = mobile;
    }
    public Integer getUserId()
    {
        return userId;
    }
    public void setUserId(Integer userId)
    {
        this.userId = userId;
    }
    public String getUsername()
    {
        return username;
    }
    public void setUsername(String username)
    {
        this.username = username;
    }
    public String getPassword()
    {
        return password;
    }
    public void setPassword(String password)
    {
        this.password = password;
    }
    public String getMobile()
    {
        return mobile;
    }
    public void setMobile(String mobile)
    {
        this.mobile = mobile;
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
New file
@@ -0,0 +1,125 @@
package com.ruoyi.web.core.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.config.RuoYiConfig;
import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.Contact;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
/**
 * Swagger2的接口配置
 *
 * @author ruoyi
 */
@Configuration
public class SwaggerConfig
{
    /** 系统基础配置 */
    @Autowired
    private RuoYiConfig ruoyiConfig;
    /** 是否开启swagger */
    @Value("${swagger.enabled}")
    private boolean enabled;
    /** 设置请求的统一前缀 */
    @Value("${swagger.pathMapping}")
    private String pathMapping;
    /**
     * 创建API
     */
    @Bean
    public Docket createRestApi()
    {
        return new Docket(DocumentationType.OAS_30)
                // 是否启用Swagger
                .enable(enabled)
                // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
                .apiInfo(apiInfo())
                // 设置哪些接口暴露给Swagger展示
                .select()
                // 扫描所有有注解的api,用这种方式更灵活
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                // 扫描指定包中的swagger注解
                // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
                // 扫描所有 .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build()
                /* 设置安全模式,swagger可以设置访问token */
                .securitySchemes(securitySchemes())
                .securityContexts(securityContexts())
                .pathMapping(pathMapping);
    }
    /**
     * 安全模式,这里指定token通过Authorization头请求头传递
     */
    private List<SecurityScheme> securitySchemes()
    {
        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
        return apiKeyList;
    }
    /**
     * 安全上下文
     */
    private List<SecurityContext> securityContexts()
    {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                        .build());
        return securityContexts;
    }
    /**
     * 默认的安全上引用
     */
    private List<SecurityReference> defaultAuth()
    {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }
    /**
     * 添加摘要信息
     */
    private ApiInfo apiInfo()
    {
        // 用ApiInfoBuilder进行定制
        return new ApiInfoBuilder()
                // 设置标题
                .title("标题:好莱坞小程序_接口文档")
                // 描述
                .description("好莱坞小程序接口文档")
                // 作者信息
                .contact(new Contact(ruoyiConfig.getName(), null, null))
                // 版本
                .version("版本号:" + ruoyiConfig.getVersion())
                .build();
    }
}
ruoyi-applet/src/main/resources/META-INF/spring-devtools.properties
New file
@@ -0,0 +1 @@
restart.include.json=/com.alibaba.fastjson.*.jar
ruoyi-applet/src/main/resources/application-druid.yml
New file
@@ -0,0 +1,64 @@
# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://192.168.110.34:3306/aba?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: root
                password: 123456
#                url: jdbc:mysql://8.137.10.192:3306/sys_config?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
#                username: root
#                password: shms#123~
            # 从库数据源
            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-applet/src/main/resources/application.yml
New file
@@ -0,0 +1,164 @@
# 项目相关配置
ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 3.8.6
  # 版权年份
  copyrightYear: 2023
  # 实例演示开关
  demoEnabled: true
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: false
  # 验证码类型 math 数字计算 char 字符验证
  captchaType: math
# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8082
  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:
  main:
    allow-bean-definition-overriding: true
  # 资源信息
  messages:
    # 国际化资源文件路径
    basename: i18n/messages
  profiles:
    active: druid
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 500MB
      # 设置总上传的文件大小
      max-request-size: 2000MB
  # 服务模块
  devtools:
    restart:
      # 热部署开关
      enabled: true
  # redis 配置
  redis:
    # 地址
    host: 127.0.0.1
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
# token配置
token:
  # 令牌自定义标识
  header: Authorization
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 120
# 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
mybatis-plus:
  # 此处在多数据源中生效
  config-location: classpath:/mybatis-config.xml
  global-config:
    banner: false
    db-config:
      logic-not-delete-value: 0
      logic-delete-value: 1
  type-aliases-package: com.ruoyi.**.domain,com.ruoyi.**.vo
  # 指定Mapper文件位置
  mapper-locations: classpath*:mapper/**/*.xml
# Swagger配置
swagger:
  # 是否开启swagger
  enabled: true
  # 请求前缀
  pathMapping: /
# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /system/notice
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
file:
  upload:
    location: /file/
    qrLocation: /file/qrCode/
    accessPath: /file/
    allowExt: .jpg|.png|.gif|.jpeg|.doc|.docx|.apk|.MP4|.mp4|.pdf|.PDF
wx:
  config:
    appId: wxc3985a05da7d86dc
    secret: 5cca42633c25439613b328c08ef20cc9
#OSS及短信配置
code:
  config:
    templateCodeTest: "SMS_154950909"
    signNameTest: "阿里云短信测试"
    accessKeyId: LTAI5tAdba8HtT1C6UqtSxBt
    accessKeySecret: 0SRb6XGkciQDPWn2rYqbJtq2qRMDY8
    signName: "四川金达通信工程"
    templateCode: "SMS_293985284"
ruoyi-applet/src/main/resources/banner.txt
New file
@@ -0,0 +1,24 @@
Application Version: ${ruoyi.version}
Spring Boot Version: ${spring-boot.version}
////////////////////////////////////////////////////////////////////
//                          _ooOoo_                               //
//                         o8888888o                              //
//                         88" . "88                              //
//                         (| ^_^ |)                              //
//                         O\  =  /O                              //
//                      ____/`---'\____                           //
//                    .'  \\|     |//  `.                         //
//                   /  \\|||  :  |||//  \                        //
//                  /  _||||| -:- |||||-  \                       //
//                  |   | \\\  -  /// |   |                       //
//                  | \_|  ''\---/''  |   |                       //
//                  \  .-\__  `-`  ___/-. /                       //
//                ___`. .'  /--.--\  `. . ___                     //
//              ."" '<  `.___\_<|>_/___.'  >'"".                  //
//            | | :  `- \`.;`\ _ /`;.`/ - ` : | |                 //
//            \  \ `-.   \_ __\ /__ _/   .-` /  /                 //
//      ========`-.____`-.___\_____/___.-`____.-'========         //
//                           `=---='                              //
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        //
//             佛祖保佑       永不宕机      永无BUG               //
////////////////////////////////////////////////////////////////////
ruoyi-applet/src/main/resources/i18n/messages.properties
New file
@@ -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-applet/src/main/resources/logback.xml
New file
@@ -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-applet/src/main/resources/mybatis-config.xml
New file
@@ -0,0 +1,25 @@
<?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="logImpl" value="STDOUT_LOGGING"/>
        <!--<setting name="logImpl" value="LOG4J" />-->
        <!-- 控制全局缓存(二级缓存),按美团技术团队的说法,尽量别用缓存机制 emmmm.... -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <!-- <setting name="lazyLoadingEnabled" value="true"/> -->
        <setting name="mapUnderscoreToCamelCase" value="false"/><!--是否将map下划线方式转为驼峰式命名-->
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <!-- <setting name="aggressiveLazyLoading" value="false"/>-->
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- 关于mybatis的一二级缓存 请参照:https://tech.meituan.com/2018/01/19/mybatis-cache.html -->
        <!-- 一级缓存范围默认:SESSION ,此范围在复杂应用场景中可能会出现脏读数据-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--<setting name="localCacheScope" value="STATEMENT"/>-->
        <setting name="localCacheScope" value="STATEMENT"/>
    </settings>
</configuration>
ruoyi-applet/src/main/resources/mybatis/mybatis-config.xml
New file
@@ -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
New file
@@ -0,0 +1,173 @@
<?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.8.6</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>ruoyi-common</artifactId>
    <description>
        common通用工具
    </description>
    <properties>
        <swagger.fox.version>3.0.0</swagger.fox.version>
        <swagger.core.version>1.6.2</swagger.core.version>
    </properties>
    <dependencies>
        <!-- Spring框架基本的核心工具 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
        <!-- SpringWeb模块 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
        </dependency>
        <!-- spring security 安全认证 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- pagehelper 分页插件 -->
<!--        <dependency>-->
<!--            <groupId>com.github.pagehelper</groupId>-->
<!--            <artifactId>pagehelper-spring-boot-starter</artifactId>-->
<!--        </dependency>-->
        <!-- 自定义验证注解 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <!--常用工具类 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!-- JSON工具类 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.5.2</version>
        </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>-->
        <!-- yml解析器 -->
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
        </dependency>
        <!-- Token生成与解析-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
        </dependency>
        <!-- Jaxb -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <!-- redis 缓存操作 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- pool 对象池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- 解析客户端操作系统、浏览器等 -->
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
        </dependency>
        <!-- servlet包 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>io.swagger</groupId>-->
<!--            <artifactId>swagger-models</artifactId>-->
<!--            <version>${swagger.core.version}</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>io.swagger</groupId>-->
<!--            <artifactId>swagger-annotations</artifactId>-->
<!--            <version>${swagger.core.version}</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>ws.schild</groupId>
            <artifactId>jave-all-deps</artifactId>
            <version>2.5.1</version>
        </dependency>
    </dependencies>
</project>
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
New file
@@ -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
New file
@@ -0,0 +1,33 @@
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 deptAlias() default "";
    /**
     * 用户表的别名
     */
    public String userAlias() default "";
    /**
     * 权限字符(用于多个角色匹配符合要求的权限)默认根据权限注解@ss获取,多个权限用逗号分隔开来
     */
    public String permission() default "";
}
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
New file
@@ -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
New file
@@ -0,0 +1,187 @@
//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
//     */
//    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 String[] combo() default {};
//
//    /**
//     * 是否需要纵向合并单元格,应对需求:含有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);
//        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
New file
@@ -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
New file
@@ -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
New file
@@ -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
New file
@@ -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/basic/PageInfo.java
New file
@@ -0,0 +1,70 @@
package com.ruoyi.common.basic;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import java.util.List;
/**
 * @Author liheng
 * @Date 2019/08/26 10:28 AM
 * @Description
 */
@JsonIgnoreProperties({"orders", "optimizeCountSql", "hitCount", "countId", "maxLimit", "searchCount"})
public class PageInfo<T> extends Page<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    private boolean hasNextPage;
    private boolean hasPrevPage;
    private long startIndex;
    public PageInfo(long currentPage, long pageShowCount) {
        super(currentPage, pageShowCount);
        this.startIndex = super.offset();
    }
    public PageInfo() {
        super();
    }
    private static boolean hasPrevPage(long currentPage) {
        return currentPage != 1;
    }
    @Override
    public PageInfo<T> setRecords(List<T> records) {
        super.setRecords(records);
        this.hasNextPage = super.hasNext();
        this.hasPrevPage = super.hasPrevious();
        return this;
    }
    public boolean getHasNextPage() {
        return hasNextPage;
    }
    public void setHasNextPage(boolean hasNextPage) {
        this.hasNextPage = hasNextPage;
    }
    public boolean getHasPrevPage() {
        return hasPrevPage;
    }
    public void setHasPrevPage(boolean hasPrevPage) {
        this.hasPrevPage = hasPrevPage;
    }
    private boolean hasNextPage(long currentPage, long totalPage) {
        return currentPage < totalPage && totalPage != 0;
    }
    public long getStartIndex() {
        return startIndex;
    }
    public void setStartIndex(long startIndex) {
        this.startIndex = startIndex;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/config/DataUpdateHandlerConfig.java
New file
@@ -0,0 +1,57 @@
package com.ruoyi.common.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Configuration;
/**
 * @author xiaochen
 * @ClassName DataUpdateInterceptor
 * @Description 数据更新操作处理
 * @date 2021-12-15
 * <p>
 * 注意,之前在此处注入了 JwtTokenUtils
 * <p>
 * 造成spring循环依赖,项目支棱不起来
 */
@Slf4j
@Configuration
public class DataUpdateHandlerConfig implements MetaObjectHandler {
    /**
     * 新增数据执行
     *
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        //  获取登录信息
       /* String userName = JwtTokenUtils.getUsername();
        if (StringUtils.isNotBlank(userName)) {
            this.setFieldValByName("createBy", userName, metaObject);
            this.setFieldValByName("updateBy", userName, metaObject);
        } else {
            this.setFieldValByName("createBy", "", metaObject);
            this.setFieldValByName("updateBy", "", metaObject);
        }*/
    }
    /**
     * 修改数据执行
     *
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        //  获取登录信息
        /*String userName = JwtTokenUtils.getUsername();
        if (StringUtils.isNotBlank(userName)) {
            this.setFieldValByName("createBy", userName, metaObject);
            this.setFieldValByName("updateBy", userName, metaObject);
        } else {
            this.setFieldValByName("createBy", "", metaObject);
            this.setFieldValByName("updateBy", "", metaObject);
        }*/
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/config/FileUploadConfig.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.common.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * <p>文件上传配置</p>
 *
 * @author mouseyCat
 * @date 2020/10/13 16:10
 */
@Data
@Component
@ConfigurationProperties(prefix = "file.upload")
public class FileUploadConfig {
    private String accessPath;
    private String allowExt;
    private String location;
    private String qrLocation;
}
ruoyi-common/src/main/java/com/ruoyi/common/config/MybatisPlusConfig.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.common.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @author liheng
 * @ClassName MybatisPlusConfig
 * @Description MybatisPlus相关配置
 * @date 2020-09-22 11:22、
 * 直接以实现类作为bean的注入(有事务管理的类)
 * @EnableTransactionManagement(proxyTargetClass = true)
 */
@Configuration
public class MybatisPlusConfig {
    private final DataUpdateHandlerConfig dataUpdateHandler;
    @Autowired
    public MybatisPlusConfig(DataUpdateHandlerConfig dataUpdateHandler) {
        this.dataUpdateHandler = dataUpdateHandler;
    }
    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    /**
     * 自动填充功能
     *
     * @return
     */
    @Bean
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setMetaObjectHandler(dataUpdateHandler);
        return globalConfig;
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
New file
@@ -0,0 +1,135 @@
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 boolean demoEnabled;
    /** 上传路径 */
    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 boolean isDemoEnabled()
    {
        return demoEnabled;
    }
    public void setDemoEnabled(boolean demoEnabled)
    {
        this.demoEnabled = demoEnabled;
    }
    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/WxConfig.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.common.config;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * 项目中需继承此类
 *
 * @author lihen
 */
@Data
@Component
@ConfigurationProperties(prefix = "wx.config")
public class WxConfig {
    /**
     * 获取 App ID
     *
     * @return App ID
     */
    @JsonProperty("appId")
    private String appId;
    /**
     * 获取 Secret
     *
     * @return Secret
     */
    @JsonProperty("secret")
    private String secret;
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
New file
@@ -0,0 +1,46 @@
package com.ruoyi.common.constant;
/**
 * 缓存的key 常量
 *
 * @author ruoyi
 */
public class CacheConstants
{
    /**
     * 登录用户 redis key
     */
    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
    // 小程序
    public static final String LOGIN_TOKEN_KEY_APPLET = "login_tokens_applet:";
    /**
     * 验证码 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
New file
@@ -0,0 +1,158 @@
package com.ruoyi.common.constant;
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";
    /**
     * 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 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";
    public static final String LOGIN_USER_APPLET_KEY = "login_user_applet_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 = { "org.springframework", "com.ruoyi" };
    /**
     * 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)
     */
    public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };
    /**
     * 定时任务违规的字符
     */
    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" };
    /**
     * 时间格式化
     */
    public static final String DATE_FORMATTER_TIME = "yyyy-MM-dd HH:mm:ss";
    /**
     * 用户类型
     */
    public static final String USER_TYPE = "用户类型";
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
New file
@@ -0,0 +1,117 @@
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[] 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
New file
@@ -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/OrderNumConstants.java
New file
@@ -0,0 +1,21 @@
package com.ruoyi.common.constant;
/**
 * 订单编号常量前缀
 *
 * @author ruoyi
 */
public class OrderNumConstants
{
    /**
     * 餐饮
     */
    public static final String MEAL = "CY";
    /** 销售 */
    public static final String SALE = "XS";
    /** 进货 */
    public static final String STOCK = "JH";
}
ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
New file
@@ -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
New file
@@ -0,0 +1,78 @@
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_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/constant/WxConstant.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.common.constant;
/**
 * @Description 对接微信小程序的常量
 * @Author xiaochen
 * @Date 2021/10/19/01914:01
 */
public class WxConstant {
    /**
     * 生成小程序码地址
     */
    public static final String CREATE_CODE_URL = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN";
    /**
     * 高德地图坐标转换
     */
    public static final String ADDRESS_CONVERT_TO_COORDINATE = "https://restapi.amap.com/v3/geocode/geo?key=KEY&address=ADDRESS";
}
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
New file
@@ -0,0 +1,209 @@
package com.ruoyi.common.core.controller;
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.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import java.beans.PropertyEditorSupport;
import java.util.Date;
import java.util.List;
/**
 * 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 startPage(Integer pageNum,Integer pageSize)
//    {
//        PageUtils.startPage(pageNum,pageSize);
//    }
    /**
     * 设置请求排序数据
     */
    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.setRecords(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();
    }
    public String getUsername1()
    {
        return getLoginUser().getUsername1();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/FileController.java
New file
@@ -0,0 +1,140 @@
package com.ruoyi.common.core.controller;
import com.ruoyi.common.config.FileUploadConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
 * 文件上传控制类
 *
 * @author junelee
 * @date 2020/3/20 20:21
 */
@Api(tags = "服务器文件上传")
@RestController
@CrossOrigin
@RequestMapping("/file/")
public class FileController {
    @Autowired
    private FileUploadConfig fileUploadConfig;
    @ApiOperation(value = "单文件上传", notes = "单文件上传,rename 默认不重命名")
    @PostMapping(value = "upload", headers = "content-type=multipart/form-data")
    public AjaxResult uploadImageMany(@RequestParam(value = "file") MultipartFile mf) throws IOException {
        if (mf.isEmpty()) {
            return AjaxResult.error("请传入文件!");
        }
        String TimeDir =new SimpleDateFormat("yyyy-MM-dd").format(new Date());
//        String realPath = fileUploadConfig.getLocation() + TimeDir;
        String realPath = "C:\\Users\\Admin\\Desktop\\qrcode\\" + TimeDir;
        File file = new File(realPath);
        // 没有目录就创建
        if (!file.exists()) {
            file.mkdirs();
        }
        // 获取文件名称
        String filename = mf.getOriginalFilename();
        // 获取文件后缀
        String ext = filename.substring(filename.lastIndexOf("."), filename.length());
        // 检查文件类型
        if (!fileUploadConfig.getAllowExt().contains(ext)) {
            return AjaxResult.error("上传文件格式不正确,仅支持" + fileUploadConfig.getAllowExt());
        }
        File targetFile = new File(realPath, filename);//目标文件
        //开始从源文件拷贝到目标文件
        //传图片一步到位
        mf.transferTo(targetFile);
        //拼接数据
//        String imgstr = fileUploadConfig.getAccessPath() + TimeDir +"\\"+ filename;
        String imgstr = TimeDir +"/"+ filename;
        return AjaxResult.success(imgstr);
    }
//    @ApiOperation(value = "单文件上传", notes = "单文件上传,rename 默认不重命名")
//    @PostMapping(value = "strUpload", headers = "content-type=multipart/form-data")
//    public String strUpload(@RequestParam(value = "file") MultipartFile mf,@RequestParam(value = "fileName")String fileName) throws IOException {
//        if (mf.isEmpty()) {
//            return "请传入文件!";
//        }
//        String TimeDir =new SimpleDateFormat("yyyy-MM-dd").format(new Date());
//        String realPath = fileUploadConfig.getQrLocation() + TimeDir;
//        File file = new File(realPath);
//        // 没有目录就创建
//        if (!file.exists()) {
//            file.mkdirs();
//        }
//        File targetFile = new File(realPath, fileName);//目标文件
//        //开始从源文件拷贝到目标文件
//        //传图片一步到位
//        mf.transferTo(targetFile);
//        //拼接数据
//        return fileUploadConfig.getQrLocation() + TimeDir +"\\"+ fileName;
//    }
    @ApiOperation(value = "单文件上传", notes = "单文件上传,rename 默认不重命名")
    @PostMapping(value = "strUpload", headers = "content-type=multipart/form-data")
    public String strUpload(@RequestParam(value = "file") MultipartFile mf,@RequestParam(value = "fileName")String fileName) throws IOException {
        if (mf.isEmpty()) {
            return "请传入文件!";
        }
        String TimeDir =new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String realPath = "C:\\Users\\Admin\\Desktop\\qrcode\\" + TimeDir;
        File file = new File(realPath);
        // 没有目录就创建
        if (!file.exists()) {
            file.mkdirs();
        }
        File targetFile = new File(realPath, fileName);//目标文件
        //开始从源文件拷贝到目标文件
        //传图片一步到位
        mf.transferTo(targetFile);
        //拼接数据
        return TimeDir +"/"+ fileName;
    }
    @ApiOperation(value = "单文件上传(覆盖服务器原文件)", notes = "单文件上传,rename 默认不重命名")
    @PostMapping(value = "test/upload", headers = "content-type=multipart/form-data")
    public AjaxResult uploadTest(@RequestParam(value = "file") MultipartFile mf) throws IOException {
        if (mf.isEmpty()) {
            return AjaxResult.error("请传入文件!");
        }
        String TimeDir = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String realPath = fileUploadConfig.getLocation() + "2021-11-17";
        File file = new File(realPath);
        // 没有目录就创建
        if (!file.exists()) {
            file.mkdirs();
        }
        // 判断文件大小
        String filename = "6u2mGlqHkeE75e2ab51b4a03c6982ff7d68f4c024d43.jpg";
        // 获取文件后缀
        String ext = filename.substring(filename.lastIndexOf("."), filename.length());
        // 检查文件类型
        if (!fileUploadConfig.getAllowExt().contains(ext)) {
            return AjaxResult.error("上传文件格式不正确,仅支持" + fileUploadConfig.getAllowExt());
        }
        File targetFile = new File(realPath, filename);//目标文件
        //开始从源文件拷贝到目标文件
        //传图片一步到位
        mf.transferTo(targetFile);
        //拼接数据
        String imgstr = fileUploadConfig.getAccessPath() + "2021-11-17" + "/" + filename;
        return AjaxResult.success(imgstr);
    }
}
Diff truncated after the above file
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseModel.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BasePage.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/TimeRangeQueryBody.java ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java ruoyi-common/src/main/java/com/ruoyi/common/enums/BoardEnum.java ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java ruoyi-common/src/main/java/com/ruoyi/common/enums/DisabledEnum.java ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java ruoyi-common/src/main/java/com/ruoyi/common/enums/UpdateTypeEnum.java ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java ruoyi-common/src/main/java/com/ruoyi/common/resp/AccessTokenRespBody.java ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java ruoyi-common/src/main/java/com/ruoyi/common/utils/CodeGenerateUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java ruoyi-common/src/main/java/com/ruoyi/common/utils/IDCardUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/MultipartFileUtil.java ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java ruoyi-common/src/main/java/com/ruoyi/common/utils/TimeConverter.java ruoyi-common/src/main/java/com/ruoyi/common/utils/VideoUtil.java ruoyi-common/src/main/java/com/ruoyi/common/utils/WebUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/WxAppletTools.java ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java 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/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/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/readme.txt 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/code/SubmitTemplateReg.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/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/TAppUser.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TBanner.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TCommittee.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TCommitteeMajor.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TCommitteeTechnical.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TConsultation.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TConsultationClassification.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TConsultationMessage.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TCourse.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TCourseComment.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TCoursePart.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNotice.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNoticeFile.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNoticeMajor.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TDeclareNoticeTechnical.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TGeneratedRecords.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TIndexMenu.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TInfoConfig.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TInformation.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TInformationClass.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TLevel.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TOrder.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TRegion.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TTechnicalTitle.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TTitleMajor.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TUserChange.java ruoyi-system/src/main/java/com/ruoyi/system/domain/TUserChangeDetail.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/dto/AddDishDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/AllertTitleDto.java ruoyi-system/src/main/java/com/ruoyi/system/dto/CheckoutDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/DataScreeningDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/MahorImportExcel.java ruoyi-system/src/main/java/com/ruoyi/system/dto/MealOrderGoodsDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/OrderMealGeneratorCountDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/OrderMealGeneratorDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/RegionChildrenDto.java ruoyi-system/src/main/java/com/ruoyi/system/dto/RegionDto.java ruoyi-system/src/main/java/com/ruoyi/system/dto/StockDataSetDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/SysRoleDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/SysUserUpdateStatusDTO.java ruoyi-system/src/main/java/com/ruoyi/system/dto/TVideoDto.java ruoyi-system/src/main/java/com/ruoyi/system/dto/TechImportExcel.java ruoyi-system/src/main/java/com/ruoyi/system/dto/UpdatePwdDTO.java ruoyi-system/src/main/java/com/ruoyi/system/export/MealGeneratorListExport.java ruoyi-system/src/main/java/com/ruoyi/system/export/OpticalInspectionExport.java ruoyi-system/src/main/java/com/ruoyi/system/export/SaleGeneratorListExport.java ruoyi-system/src/main/java/com/ruoyi/system/export/TOrderMealExportExcel.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/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/mapper/TAppUserMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TBannerMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCommitteeMajorMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCommitteeMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCommitteeTechnicalMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TConsultationClassificationMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TConsultationMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TConsultationMessageMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCourseCommentMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCourseMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TCoursePartMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeFileMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeMajorMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TDeclareNoticeTechnicalMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TGeneratedRecordsMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TIndexMenuMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInfoConfigMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInformationClassMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TInformationMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TLevelMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TOrderMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TRegionMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTechnicalTitleMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TTitleMajorMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TUserChangeDetailMapper.java ruoyi-system/src/main/java/com/ruoyi/system/mapper/TUserChangeMapper.java ruoyi-system/src/main/java/com/ruoyi/system/query/AppUserQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/CommentQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/GeneratedQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/MessageQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/OrderQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/ProfitDetailsQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/RegionQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/SysRoleQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/SysUserQuery.java ruoyi-system/src/main/java/com/ruoyi/system/query/TUserQuery.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/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/TAppUserService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TBannerService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TCommitteeMajorService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TCommitteeService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TCommitteeTechnicalService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TConsultationClassificationService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TConsultationMessageService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TConsultationService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TCourseCommentService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TCoursePartService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TCourseService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeFileService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeMajorService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TDeclareNoticeTechnicalService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TGeneratedRecordsService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TIndexMenuService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TInfoConfigService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TInformationClassService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TInformationService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TLevelService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TOrderService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TRegionService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TTechnicalTitleService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TTitleMajorService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TUserChangeDetailService.java ruoyi-system/src/main/java/com/ruoyi/system/service/TUserChangeService.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/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/java/com/ruoyi/system/service/impl/TAppUserServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TBannerServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCommitteeMajorServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCommitteeServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCommitteeTechnicalServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TConsultationClassificationServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TConsultationMessageServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TConsultationServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCourseCommentServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCoursePartServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TCourseServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeFileServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeMajorServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TDeclareNoticeTechnicalServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TGeneratedRecordsServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TIndexMenuServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInfoConfigServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationClassServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TInformationServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TLevelServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TOrderServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TRegionServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTechnicalTitleServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TTitleMajorServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TUserChangeDetailServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TUserChangeServiceImpl.java ruoyi-system/src/main/java/com/ruoyi/system/vo/AmountSumVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/GoodsProfitVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/OrderTrendsVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/PersonnelStatisticsAndSumVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/PersonnelStatisticsVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/ProfitDetailsVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/RoleInfoVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/SalesRankingVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/SalesVolumeVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/SysOperLogVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/SysUserVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/UserAddListVO.java ruoyi-system/src/main/java/com/ruoyi/system/vo/UserInfoVo.java ruoyi-system/src/main/java/com/ruoyi/system/vo/UserLevelVO.java ruoyi-system/src/main/java/com/ruoyi/system/vx/AlipayTradePagePay.java ruoyi-system/src/main/java/com/ruoyi/system/vx/QuickStart.java ruoyi-system/src/main/java/com/ruoyi/system/vx/WeChatConfig.java ruoyi-system/src/main/java/com/ruoyi/system/vx/WeChatUtil.java 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/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-system/src/main/resources/mapper/system/TAppUserMapper.xml ruoyi-system/src/main/resources/mapper/system/TBannerMapper.xml ruoyi-system/src/main/resources/mapper/system/TCommitteeMajorMapper.xml ruoyi-system/src/main/resources/mapper/system/TCommitteeMapper.xml ruoyi-system/src/main/resources/mapper/system/TCommitteeTechnicalMapper.xml ruoyi-system/src/main/resources/mapper/system/TConsultationClassificationMapper.xml ruoyi-system/src/main/resources/mapper/system/TConsultationMapper.xml ruoyi-system/src/main/resources/mapper/system/TConsultationMessageMapper.xml ruoyi-system/src/main/resources/mapper/system/TCourseCommentMapper.xml ruoyi-system/src/main/resources/mapper/system/TCourseMapper.xml ruoyi-system/src/main/resources/mapper/system/TCoursePartMapper.xml ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeFileMapper.xml ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeMajorMapper.xml ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeMapper.xml ruoyi-system/src/main/resources/mapper/system/TDeclareNoticeTechnicalMapper.xml ruoyi-system/src/main/resources/mapper/system/TGeneratedRecordsMapper.xml ruoyi-system/src/main/resources/mapper/system/TIndexMenuMapper.xml ruoyi-system/src/main/resources/mapper/system/TInfoConfigMapper.xml ruoyi-system/src/main/resources/mapper/system/TInformationClassMapper.xml ruoyi-system/src/main/resources/mapper/system/TInformationMapper.xml ruoyi-system/src/main/resources/mapper/system/TLevelMapper.xml ruoyi-system/src/main/resources/mapper/system/TOrderMapper.xml ruoyi-system/src/main/resources/mapper/system/TRegionMapper.xml ruoyi-system/src/main/resources/mapper/system/TTechnicalTitleMapper.xml ruoyi-system/src/main/resources/mapper/system/TTitleMajorMapper.xml ruoyi-system/src/main/resources/mapper/system/TUserChangeDetailMapper.xml ruoyi-system/src/main/resources/mapper/system/TUserChangeMapper.xml ry.bat ry.sh sql/quartz.sql sql/ry_20230706.sql tech_info.sql