From f28f7ea7791c2e868f3c5f8a9f2bb43da5145456 Mon Sep 17 00:00:00 2001 From: sunhe <1279224279@qq.com> Date: Sun, 13 Apr 2025 21:53:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E5=90=8E?= =?UTF-8?q?=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .DS_Store | Bin 0 -> 8196 bytes .gitignore | 147 ++++ .mvn/wrapper/maven-wrapper.properties | 2 + Dockerfile | 15 + doc/swagger.png | Bin 0 -> 455614 bytes mvnw | 316 +++++++++ mvnw.cmd | 188 ++++++ pom.xml | 156 +++++ sql/create_table.sql | 40 ++ sql/post_es_mapping.json | 52 ++ src/.DS_Store | Bin 0 -> 6148 bytes .../yupi/springbootinit/MainApplication.java | 27 + .../springbootinit/annotation/AuthCheck.java | 26 + .../springbootinit/aop/AuthInterceptor.java | 72 ++ .../springbootinit/aop/LogInterceptor.java | 56 ++ .../yupi/springbootinit/api/OpenAiApi.java | 38 ++ .../springbootinit/common/BaseResponse.java | 35 + .../springbootinit/common/DeleteRequest.java | 21 + .../yupi/springbootinit/common/ErrorCode.java | 44 ++ .../springbootinit/common/PageRequest.java | 34 + .../springbootinit/common/ResultUtils.java | 52 ++ .../springbootinit/config/CorsConfig.java | 28 + .../config/CosClientConfig.java | 53 ++ .../springbootinit/config/JsonConfig.java | 31 + .../config/MyBatisPlusConfig.java | 31 + .../springbootinit/config/RedissonConfig.java | 34 + .../springbootinit/config/WxOpenConfig.java | 51 ++ .../springbootinit/config/XingHuoConfig.java | 30 + .../constant/CommonConstant.java | 21 + .../springbootinit/constant/FileConstant.java | 16 + .../springbootinit/constant/UserConstant.java | 34 + .../controller/ChartController.java | 631 ++++++++++++++++++ .../controller/FileController.java | 108 +++ .../controller/PostController.java | 263 ++++++++ .../controller/PostFavourController.java | 109 +++ .../controller/PostThumbController.java | 56 ++ .../controller/QueueController.java | 56 ++ .../controller/UserController.java | 293 ++++++++ .../yupi/springbootinit/esdao/PostEsDao.java | 16 + .../exception/BusinessException.java | 36 + .../exception/GlobalExceptionHandler.java | 31 + .../springbootinit/exception/ThrowUtils.java | 45 ++ .../generate/CodeGenerator.java | 128 ++++ .../job/cycle/IncSyncPostToEs.java | 57 ++ .../job/once/FullSyncPostToEs.java | 48 ++ .../springbootinit/manager/AiManager.java | 85 +++ .../springbootinit/manager/CosManager.java | 51 ++ .../manager/RedisLimiterManager.java | 37 + .../manager/ThreadPoolExecutorConfig.java | 45 ++ .../springbootinit/mapper/ChartMapper.java | 18 + .../mapper/PostFavourMapper.java | 35 + .../springbootinit/mapper/PostMapper.java | 25 + .../mapper/PostThumbMapper.java | 18 + .../springbootinit/mapper/UserMapper.java | 18 + .../model/dto/chart/ChartAddRequest.java | 39 ++ .../model/dto/chart/ChartEditRequest.java | 47 ++ .../model/dto/chart/ChartQueryRequest.java | 42 ++ .../model/dto/chart/ChartUpdateRequest.java | 78 +++ .../model/dto/chart/GenChartByAiRequest.java | 32 + .../model/dto/file/UploadFileRequest.java | 21 + .../model/dto/post/PostAddRequest.java | 32 + .../model/dto/post/PostEditRequest.java | 37 + .../model/dto/post/PostEsDTO.java | 123 ++++ .../model/dto/post/PostQueryRequest.java | 65 ++ .../model/dto/post/PostUpdateRequest.java | 37 + .../dto/postfavour/PostFavourAddRequest.java | 21 + .../postfavour/PostFavourQueryRequest.java | 30 + .../dto/postthumb/PostThumbAddRequest.java | 21 + .../model/dto/user/UserAddRequest.java | 36 + .../model/dto/user/UserLoginRequest.java | 20 + .../model/dto/user/UserQueryRequest.java | 48 ++ .../model/dto/user/UserRegisterRequest.java | 22 + .../model/dto/user/UserUpdateMyRequest.java | 31 + .../model/dto/user/UserUpdateRequest.java | 40 ++ .../springbootinit/model/entity/Chart.java | 81 +++ .../springbootinit/model/entity/Post.java | 76 +++ .../model/entity/PostFavour.java | 49 ++ .../model/entity/PostThumb.java | 49 ++ .../springbootinit/model/entity/User.java | 61 ++ .../model/enums/FileUploadBizEnum.java | 61 ++ .../model/enums/UserRoleEnum.java | 63 ++ .../springbootinit/model/vo/BiResponse.java | 17 + .../springbootinit/model/vo/LoginUserVO.java | 52 ++ .../yupi/springbootinit/model/vo/PostVO.java | 112 ++++ .../yupi/springbootinit/model/vo/UserVO.java | 47 ++ .../springbootinit/service/ChartService.java | 13 + .../service/PostFavourService.java | 47 ++ .../springbootinit/service/PostService.java | 60 ++ .../service/PostThumbService.java | 32 + .../springbootinit/service/UserService.java | 112 ++++ .../service/impl/ChartServiceImpl.java | 22 + .../service/impl/PostFavourServiceImpl.java | 116 ++++ .../service/impl/PostServiceImpl.java | 312 +++++++++ .../service/impl/PostThumbServiceImpl.java | 105 +++ .../service/impl/UserServiceImpl.java | 240 +++++++ .../yupi/springbootinit/utils/ExcelUtils.java | 71 ++ .../yupi/springbootinit/utils/NetUtils.java | 55 ++ .../utils/SpringContextUtils.java | 57 ++ .../yupi/springbootinit/utils/SqlUtils.java | 25 + ...itional-spring-configuration-metadata.json | 52 ++ src/main/resources/application-prod.yml | 37 + src/main/resources/application-test.yml | 27 + src/main/resources/application.yml | 112 ++++ src/main/resources/banner.txt | 5 + src/main/resources/mapper/ChartMapper.xml | 25 + .../resources/mapper/PostFavourMapper.xml | 29 + src/main/resources/mapper/PostMapper.xml | 33 + src/main/resources/mapper/PostThumbMapper.xml | 21 + src/main/resources/mapper/UserMapper.xml | 23 + .../templates/TemplateController.java.ftl | 239 +++++++ .../templates/TemplateService.java.ftl | 53 ++ .../templates/TemplateServiceImpl.java.ftl | 224 +++++++ .../model/TemplateAddRequest.java.ftl | 33 + .../model/TemplateEditRequest.java.ftl | 38 ++ .../model/TemplateQueryRequest.java.ftl | 56 ++ .../model/TemplateUpdateRequest.java.ftl | 38 ++ .../templates/model/TemplateVO.java.ftl | 93 +++ src/main/resources/test_excel.xlsx | Bin 0 -> 9143 bytes src/main/resources/网站数据.xlsx | Bin 0 -> 9112 bytes src/test/.DS_Store | Bin 0 -> 6148 bytes .../springbootinit/MainApplicationTests.java | 19 + .../springbootinit/manager/AiManagerTest.java | 36 + .../manager/CosManagerTest.java | 23 + .../manager/RedisLimiterManagerTest.java | 32 + .../mapper/PostFavourMapperTest.java | 33 + .../springbootinit/mapper/PostMapperTest.java | 28 + .../service/PostFavourServiceTest.java | 46 ++ .../service/PostThumbServiceTest.java | 35 + .../service/UserServiceTest.java | 35 + .../springbootinit/utils/EasyExcelTest.java | 34 + 130 files changed, 8075 insertions(+) create mode 100644 .DS_Store create mode 100644 .gitignore create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 Dockerfile create mode 100644 doc/swagger.png create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 sql/create_table.sql create mode 100644 sql/post_es_mapping.json create mode 100644 src/.DS_Store create mode 100644 src/main/java/com/yupi/springbootinit/MainApplication.java create mode 100644 src/main/java/com/yupi/springbootinit/annotation/AuthCheck.java create mode 100644 src/main/java/com/yupi/springbootinit/aop/AuthInterceptor.java create mode 100644 src/main/java/com/yupi/springbootinit/aop/LogInterceptor.java create mode 100644 src/main/java/com/yupi/springbootinit/api/OpenAiApi.java create mode 100644 src/main/java/com/yupi/springbootinit/common/BaseResponse.java create mode 100644 src/main/java/com/yupi/springbootinit/common/DeleteRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/common/ErrorCode.java create mode 100644 src/main/java/com/yupi/springbootinit/common/PageRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/common/ResultUtils.java create mode 100644 src/main/java/com/yupi/springbootinit/config/CorsConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/config/CosClientConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/config/JsonConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/config/MyBatisPlusConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/config/RedissonConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/config/WxOpenConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/config/XingHuoConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/constant/CommonConstant.java create mode 100644 src/main/java/com/yupi/springbootinit/constant/FileConstant.java create mode 100644 src/main/java/com/yupi/springbootinit/constant/UserConstant.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/ChartController.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/FileController.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/PostController.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/PostFavourController.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/PostThumbController.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/QueueController.java create mode 100644 src/main/java/com/yupi/springbootinit/controller/UserController.java create mode 100644 src/main/java/com/yupi/springbootinit/esdao/PostEsDao.java create mode 100644 src/main/java/com/yupi/springbootinit/exception/BusinessException.java create mode 100644 src/main/java/com/yupi/springbootinit/exception/GlobalExceptionHandler.java create mode 100644 src/main/java/com/yupi/springbootinit/exception/ThrowUtils.java create mode 100644 src/main/java/com/yupi/springbootinit/generate/CodeGenerator.java create mode 100644 src/main/java/com/yupi/springbootinit/job/cycle/IncSyncPostToEs.java create mode 100644 src/main/java/com/yupi/springbootinit/job/once/FullSyncPostToEs.java create mode 100644 src/main/java/com/yupi/springbootinit/manager/AiManager.java create mode 100644 src/main/java/com/yupi/springbootinit/manager/CosManager.java create mode 100644 src/main/java/com/yupi/springbootinit/manager/RedisLimiterManager.java create mode 100644 src/main/java/com/yupi/springbootinit/manager/ThreadPoolExecutorConfig.java create mode 100644 src/main/java/com/yupi/springbootinit/mapper/ChartMapper.java create mode 100644 src/main/java/com/yupi/springbootinit/mapper/PostFavourMapper.java create mode 100644 src/main/java/com/yupi/springbootinit/mapper/PostMapper.java create mode 100644 src/main/java/com/yupi/springbootinit/mapper/PostThumbMapper.java create mode 100644 src/main/java/com/yupi/springbootinit/mapper/UserMapper.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/chart/ChartAddRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/chart/ChartEditRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/chart/ChartQueryRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/chart/ChartUpdateRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/chart/GenChartByAiRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/file/UploadFileRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/post/PostAddRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/post/PostEditRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/post/PostEsDTO.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/post/PostQueryRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/post/PostUpdateRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourAddRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourQueryRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/postthumb/PostThumbAddRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/user/UserAddRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/user/UserLoginRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/user/UserQueryRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/user/UserRegisterRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateMyRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateRequest.java create mode 100644 src/main/java/com/yupi/springbootinit/model/entity/Chart.java create mode 100644 src/main/java/com/yupi/springbootinit/model/entity/Post.java create mode 100644 src/main/java/com/yupi/springbootinit/model/entity/PostFavour.java create mode 100644 src/main/java/com/yupi/springbootinit/model/entity/PostThumb.java create mode 100644 src/main/java/com/yupi/springbootinit/model/entity/User.java create mode 100644 src/main/java/com/yupi/springbootinit/model/enums/FileUploadBizEnum.java create mode 100644 src/main/java/com/yupi/springbootinit/model/enums/UserRoleEnum.java create mode 100644 src/main/java/com/yupi/springbootinit/model/vo/BiResponse.java create mode 100644 src/main/java/com/yupi/springbootinit/model/vo/LoginUserVO.java create mode 100644 src/main/java/com/yupi/springbootinit/model/vo/PostVO.java create mode 100644 src/main/java/com/yupi/springbootinit/model/vo/UserVO.java create mode 100644 src/main/java/com/yupi/springbootinit/service/ChartService.java create mode 100644 src/main/java/com/yupi/springbootinit/service/PostFavourService.java create mode 100644 src/main/java/com/yupi/springbootinit/service/PostService.java create mode 100644 src/main/java/com/yupi/springbootinit/service/PostThumbService.java create mode 100644 src/main/java/com/yupi/springbootinit/service/UserService.java create mode 100644 src/main/java/com/yupi/springbootinit/service/impl/ChartServiceImpl.java create mode 100644 src/main/java/com/yupi/springbootinit/service/impl/PostFavourServiceImpl.java create mode 100644 src/main/java/com/yupi/springbootinit/service/impl/PostServiceImpl.java create mode 100644 src/main/java/com/yupi/springbootinit/service/impl/PostThumbServiceImpl.java create mode 100644 src/main/java/com/yupi/springbootinit/service/impl/UserServiceImpl.java create mode 100644 src/main/java/com/yupi/springbootinit/utils/ExcelUtils.java create mode 100644 src/main/java/com/yupi/springbootinit/utils/NetUtils.java create mode 100644 src/main/java/com/yupi/springbootinit/utils/SpringContextUtils.java create mode 100644 src/main/java/com/yupi/springbootinit/utils/SqlUtils.java create mode 100644 src/main/resources/META-INF/additional-spring-configuration-metadata.json create mode 100644 src/main/resources/application-prod.yml create mode 100644 src/main/resources/application-test.yml create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/banner.txt create mode 100644 src/main/resources/mapper/ChartMapper.xml create mode 100644 src/main/resources/mapper/PostFavourMapper.xml create mode 100644 src/main/resources/mapper/PostMapper.xml create mode 100644 src/main/resources/mapper/PostThumbMapper.xml create mode 100644 src/main/resources/mapper/UserMapper.xml create mode 100644 src/main/resources/templates/TemplateController.java.ftl create mode 100644 src/main/resources/templates/TemplateService.java.ftl create mode 100644 src/main/resources/templates/TemplateServiceImpl.java.ftl create mode 100644 src/main/resources/templates/model/TemplateAddRequest.java.ftl create mode 100644 src/main/resources/templates/model/TemplateEditRequest.java.ftl create mode 100644 src/main/resources/templates/model/TemplateQueryRequest.java.ftl create mode 100644 src/main/resources/templates/model/TemplateUpdateRequest.java.ftl create mode 100644 src/main/resources/templates/model/TemplateVO.java.ftl create mode 100644 src/main/resources/test_excel.xlsx create mode 100644 src/main/resources/网站数据.xlsx create mode 100644 src/test/.DS_Store create mode 100644 src/test/java/com/yupi/springbootinit/MainApplicationTests.java create mode 100644 src/test/java/com/yupi/springbootinit/manager/AiManagerTest.java create mode 100644 src/test/java/com/yupi/springbootinit/manager/CosManagerTest.java create mode 100644 src/test/java/com/yupi/springbootinit/manager/RedisLimiterManagerTest.java create mode 100644 src/test/java/com/yupi/springbootinit/mapper/PostFavourMapperTest.java create mode 100644 src/test/java/com/yupi/springbootinit/mapper/PostMapperTest.java create mode 100644 src/test/java/com/yupi/springbootinit/service/PostFavourServiceTest.java create mode 100644 src/test/java/com/yupi/springbootinit/service/PostThumbServiceTest.java create mode 100644 src/test/java/com/yupi/springbootinit/service/UserServiceTest.java create mode 100644 src/test/java/com/yupi/springbootinit/utils/EasyExcelTest.java diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..f5b639300c06cfd176318cff1c453ed071e0e68c GIT binary patch literal 8196 zcmeHM&1(}u6n~SZ&89`kp_Nh)7Q6_?nzXf2dWkVTR1l#NJ!q{-Hm1?dZknWx5DM|6 z=*7RF^dflEOHuIBg9kqjf`@w4lj5NV4?QS|zWHb}vzvO6TCp>*^Ct6tZ{C~Vyv$@a z06>z9Rvcgu01SMnjPzmEp-?@2d?g@yj-e!I4|XA*&bg(s52-se1DXNNfM!55pc(jA z7{D`|7GsBVpKEok8PE*uO9trvVB$k%LdYhUZ0o>^T>(%Av6~faM`#13DP%&(CYPwe zLbxePZc4-zgK%@~Hw7*sWRpv74n$l&i119r4TUi8IKIi?KoVT)S~H*-@H0T~?m-xa z0u-Sp-`~l`(SBK1a#N|S?Pjshc>d$thr91zoL2SLZ}sK*_Pc>VeH~4q8~ql+f;?no z&k(vgp=xE{FIU4utK7F_Uvk^tJ0oQOV0@(h>AXv@1diez;ESx2eLuBwYh&}Rc{5wt zb0@vxmv3%CoO1?hkeRmKoZyshTa?e?pR8bu#wT#udbKQY&$4B^Sgplk8zj&b?CuE} zhS6utrsv&yx|XReR+E{^W%}uY>)P4vb|!nVn6J-8`p>vdEmL&z6=qPh@(8(dspwd4 zJ?SnwR+ZVNxxxsC!*h|rMq@lS5;aF+vE``Qm>7vg&9Tw(<>jz3aOA|~%-l`8}XM7gFFt4sK!wR^U43q78Y^nmk6Fx+ZMZp|0Y{VGqvWnFV#su^hH770=dsMOy0+ zlrfePqHkesd(bor86Achn8Gnqa1JHSV$b+29@(M`s<7Z27c-6=l%f!*|0LhUY~*YM zayy1x3XPm=Z$E$CTH^akOWWR4`l^l4$#*Ohg;vfpAgeg&_NbmLqxcHs{445X9#KlH zy|3uaOxVk@-uZqbv1PZSK|A?d;nym$4n3i<_R#$Y<0@e8*VNc(?kKS-*gemU(RkF1 zpNjwCUZl)PX5E-v8}RZYbN}i5p$98GPn0p_71#+QuY)mN_N{{_bEtkdOBWw}kY?G` z&hP(sGXy=hWrS3 literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85544b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,147 @@ +### @author 程序员鱼皮 ### +### @from 编程导航知识星球 ### + +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### Maven template +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..3f266f4 --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..414cd3a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +# Docker 镜像构建 +# @author 程序员鱼皮 +# @from 编程导航知识星球 +FROM maven:3.8.1-jdk-8-slim as builder + +# Copy local code to the container image. +WORKDIR /app +COPY pom.xml . +COPY src ./src + +# Build a release artifact. +RUN mvn package -DskipTests + +# Run the web service on container startup. +CMD ["java","-jar","/app/target/hebi-backend-0.0.1-SNAPSHOT.jar","--spring.profiles.active=prod"] \ No newline at end of file diff --git a/doc/swagger.png b/doc/swagger.png new file mode 100644 index 0000000000000000000000000000000000000000..0518706c73e1ba3d715ae458144111605e0b28fa GIT binary patch literal 455614 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%0DV~!S z_i`M~`oT`+x&o&SZr?)|3*1Q|3}A!*zJpxzKe5!Dm|-GS$@7f3JX@lu1U7ng--9hj zzH-i#TRS0}pFqTAa`*Z|59Z^YwFuFxZr&^v|L|*!V1XehDEKgFd)o%+)5HWCL&cSp z2sO&gFtXE{ovZ+E(xG3Xr|Mpk=g>FpkKqQKr<2caqpYg$PBwVru|9LHd72zizHx1m z;;^!bjj%ezOG1jbLs7JoRgj?RL1l}T)s$qE=!5c&A0dw@)L_y;1Fr$}^liY3Tk|z0 zSAY*)qm+~o+uqKW8;|<&O!B1DfsL37vV8I4)FO>OZCU>SE01)|a7%VDZg*=pd0FAx z*d||^AqSDUv~|gKW=1%l}`zT;6EiQuW#D+Iij0QUq&x zJUYHA^<*4oX?!MJ8kR{+@rF#aJ}ji>8guO5;(kj3d~h_9A+Yl0F&K$dM^4cjRofb7 zz#Ln|zfE=4czPWK+jmqgkj-nzl{IHGFcRgH<79s)9^^kw>ukGE%4q+Vh5VO{n-l*^ zRs10nlZ>u~)R(8n1A_VI=QSPopzuW?Qf<0nfB8l3+o|XaPz(%zW+|$!e#&j!e=Et2 z%JAhOB7D%9#{4dcv#OB9;)w7gf!1ZHGKd(2cYOjrz5x~Fqi{*JKT4J5_gEkzyOv#S zI8v?6CAt+kPojUhnh@z1?EFl53$yt{!$=ujr6E^aLm+z0m*TyHkis94c&~Uj`C~(J z@Le#D)i9bZB+foW*B&=!l^eRBs~k;0gec{Ob~YH#cZpjC*VF&uo^+L9S3X0Jb;MxC zdc%Bdc_)o9vQ+Khxfzz3WDe$=du8@O(vQ>d2mDZE9lWeoch$l=;1Jb;Fd?~Ur z=77||>Z*$A3TazM&nrhq#~S&Wt*s!iVhGTj`m$w41_)G>;SVD61ML0KG1qpU`r%Qt zZhbU2NLih7>;S_*pYO%`e&Ck!@-sJ=WOMs*yXb%uBC~(Y8 z`<~AqMS+it+s}hz9gX(d6|lfCc~IR&#Za zrIx!PD8e-!E>E-nq`=Y2>cIfMadKAM>FI)4q~~f4L$@ZVFLV(Q+VW&=^V}&i$jZ$f z+N$|@8sB05WJz#>ZgaP~-F?aAxsPYT@B;m--P&i9JhM~zmgMNiXVe^wnkW_y5T@Y7 z+N=jQr;1+NwEup1H>MO~tNmk7In@+(hqm)(XYR>_u?RFnqUY&SZPt5|c@03SLBYQ8 zx~8XR?cx+;jr-vc2Yv>HUFEwEC2wWCPp6bk*`t2TMuNQ2ON)z(ho;8%VtZfm>@Y@1 z$qtyE!9*3E8YH)pH|phrC9HP!bI;zeaeGvuzvPoB0ygX-YY^H+=`yI&E%qYup}#BU zN$R`_n_Cdo7q;F>hk*lf1JTBFT(_7n2IGH$X^LSh=P9{8iw%@STCL5TD20kZ; zx{5NB+tuv`CxfkupU#6i6>>J~!6|Na$FHer;=!6vavu)vZ@C)4W!QB(M|HZciXQhU zO8BXq|L=(Vx2oWO>PJ4OIGkhNkspd^D)mUS*g;KDuV$*1cuZ49I4;gOmuleWX-?zlexo_Wzz)ZWxqWVPYsP{xNPUDb#OnC_6@X5a!$14tOP5^aB=2spplCxbRebowWLfD7_ z@=2GA%fyyQ%dwq}bt)T}1|v&(hF#~>#ZD~W`P)R5&X4F}S4l|}9#saALr0ha%&OZb zNRF8&@ej9>$mzAL9d+jJ`r)O|u5B6R6oRY!4LuK)W*A&q(~K!v$S*JO^K0J(;3-#D z4tczXf5`PzJYw1+n$tv}RO+`DmM(hXfffMGkD5q8&yn!?eE|?}9<^}h9vRt^P=qm- zk+!fM`YRoNEx$P?yx@}8kBtV%ylJIP`d)-$KL zt|~tmWu}tt6*tO_MFNy#G#9PrwoVrD;=WFE->IA(iDO%BCof!WI=QODg+xSuIbbN{ zI?iWX><`g?6Kp^IER<)R?I@ug7mIE~y;wadHMjEa3RZhrB8z^5TR?)7--*lHrC~Q% zYAJD;Vxi`MDv*p>3L_jFmkalauytR@nVB?Jmr;y;kih$~r8cp0JhD-XW_=c_uX$v^NC`c3{C_vMqf*e+9_kGij zJuO;5-!5U)u6Yi?1L+Wp9-Sr$ z%0A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

bB;^aBrv1Auv=fq9XbE zGqm<__u{AZXpm`H>C%tPVf59U&^RL%kJ&A~w!vV@c#>~Lr~sBnB5`~Xc}7FS1c7i0AvgNu3hLGeDJL!4)BxyUd8^KPyeqk zc~{{|^Oh@kSKW0y0?zS;$ZuzU_9$dU|DfA;52!LVO3^_9oX# z+l?5PiS@a&n{w;{}D#ZBWdM&%knQ$E&tmU z_@_36yN`hRq&Y(U(?hw{6h*}@b3_NurBo!i(cefvi?4L+qPnBlnc9LCxnpxp0lx$s zm$UiCqihNAWCG@SW!G~c=UDu6OIW~VoMHW(YF3%)*cwwW>TB=!x2nZ|fsTJH \(.*\)$'` + 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 "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..1d8ab01 --- /dev/null +++ b/mvnw.cmd @@ -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% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6b45750 --- /dev/null +++ b/pom.xml @@ -0,0 +1,156 @@ + + + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.2 + + + com.yupi + hebi-backend + 0.0.1-SNAPSHOT + hebi-backend + + 1.8 + + + + + + + + io.github.briqt + xunfei-spark4j + 1.3.0 + + + + + org.redisson + redisson + 3.21.3 + + + + org.springframework.boot + spring-boot-starter-freemarker + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-aop + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.2.2 + + + + com.baomidou + mybatis-plus-boot-starter + 3.5.2 + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.session + spring-session-data-redis + + + + org.springframework.boot + spring-boot-starter-data-elasticsearch + + + + com.github.binarywang + wx-java-mp-spring-boot-starter + 4.4.0 + + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + 4.4.0 + + + + com.qcloud + cos_api + 5.6.89 + + + + org.apache.commons + commons-lang3 + + + + com.alibaba + easyexcel + 3.1.1 + + + + cn.hutool + hutool-all + 5.8.8 + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + mysql + mysql-connector-java + runtime + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/sql/create_table.sql b/sql/create_table.sql new file mode 100644 index 0000000..f18851c --- /dev/null +++ b/sql/create_table.sql @@ -0,0 +1,40 @@ + + +-- 创建库 +create database if not exists hebi; + +-- 切换库 +use hebi; + +-- 用户表 +create table if not exists user +( + id bigint auto_increment comment 'id' primary key, + userAccount varchar(256) not null comment '账号', + userPassword varchar(512) not null comment '密码', + userName varchar(256) null comment '用户昵称', + userAvatar varchar(1024) null comment '用户头像', + userRole varchar(256) default 'user' not null comment '用户角色:user/admin', + createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + isDelete tinyint default 0 not null comment '是否删除', + index idx_userAccount (userAccount) + ) comment '用户' collate = utf8mb4_unicode_ci; + +-- 图表信息表 +create table if not exists chart +( + id bigint auto_increment comment 'id' primary key, + goal text null comment '分析目标', + `name` varchar(128) null comment '图标名称', + chartData text null comment '图表数据', + chartType varchar(128) null comment '图表类型', + genChart text null comment '生成的图表数据', + genResult text null comment '生成的分析结论', + status varchar(128) not null default 'wait' comment'wait,running,succeed,failed', + execMessage text null comment '执行信息', + userId bigint null comment '创建用户 id', + createTime datetime default CURRENT_TIMESTAMP not null comment '创建时间', + updateTime datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP comment '更新时间', + isDelete tinyint default 0 not null comment '是否删除' + ) comment '图表信息表' collate = utf8mb4_unicode_ci; \ No newline at end of file diff --git a/sql/post_es_mapping.json b/sql/post_es_mapping.json new file mode 100644 index 0000000..655272d --- /dev/null +++ b/sql/post_es_mapping.json @@ -0,0 +1,52 @@ +{ + "aliases": { + "post": {} + }, + "mappings": { + "properties": { + "title": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "content": { + "type": "text", + "analyzer": "ik_max_word", + "search_analyzer": "ik_smart", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "tags": { + "type": "keyword" + }, + "thumbNum": { + "type": "long" + }, + "favourNum": { + "type": "long" + }, + "userId": { + "type": "keyword" + }, + "createTime": { + "type": "date" + }, + "updateTime": { + "type": "date" + }, + "isDelete": { + "type": "keyword" + } + } + } +} \ No newline at end of file diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c8d52009d499fefbbefb1cf14626a00a748414f4 GIT binary patch literal 6148 zcmeHKy-veG47MRd1WP3r*zOf7v9Y98c!ExBP=W|jL#npynRy8|Mkd%9cmN)W&u0TU z5iueJwsiOT{Buq|DR(gu@${w|6OD){#}H&u21Lw*t}P1|C(9m-%kk{IZI%O@{8p1Z zdqxeN(G^`M&%e{2^nFcRmh(kBhb_OYtEa>IWs>@fHUyHfSeBj zL$EOH6ywo>DYgK>4CW}%rI(PLU|1M-its>KQ-PYw)?%=x!yYWIFzggHo!FWWw#x6# z3&-l%Kg4k2LeXbuz!^vx*w*Dp?*C(aGJ{Qin&K;Gz!~^s3~*M?$|+vT?$$4_CwFbY uIK>c=xK0!Z^yDW13pq#jqf`Asbi@^goucd__LvUzAAv}SPtL#(Fz^N-szv4i literal 0 HcmV?d00001 diff --git a/src/main/java/com/yupi/springbootinit/MainApplication.java b/src/main/java/com/yupi/springbootinit/MainApplication.java new file mode 100644 index 0000000..712c0b0 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/MainApplication.java @@ -0,0 +1,27 @@ +package com.yupi.springbootinit; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * 主类(项目启动入口) + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +// todo 如需开启 Redis,须移除 exclude 中的内容 +@SpringBootApplication(exclude = {RedisAutoConfiguration.class}) +@MapperScan("com.yupi.springbootinit.mapper") +@EnableScheduling +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +public class MainApplication { + + public static void main(String[] args) { + SpringApplication.run(MainApplication.class, args); + } + +} diff --git a/src/main/java/com/yupi/springbootinit/annotation/AuthCheck.java b/src/main/java/com/yupi/springbootinit/annotation/AuthCheck.java new file mode 100644 index 0000000..b06c232 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/annotation/AuthCheck.java @@ -0,0 +1,26 @@ +package com.yupi.springbootinit.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 权限校验 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AuthCheck { + + /** + * 必须有某个角色 + * + * @return + */ + String mustRole() default ""; + +} + diff --git a/src/main/java/com/yupi/springbootinit/aop/AuthInterceptor.java b/src/main/java/com/yupi/springbootinit/aop/AuthInterceptor.java new file mode 100644 index 0000000..adc3673 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/aop/AuthInterceptor.java @@ -0,0 +1,72 @@ +package com.yupi.springbootinit.aop; + +import com.yupi.springbootinit.annotation.AuthCheck; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.enums.UserRoleEnum; +import com.yupi.springbootinit.service.UserService; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +/** + * 权限校验 AOP + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Aspect +@Component +public class AuthInterceptor { + + @Resource + private UserService userService; + + /** + * 执行拦截 + * + * @param joinPoint + * @param authCheck + * @return + */ + @Around("@annotation(authCheck)") + public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable { + String mustRole = authCheck.mustRole(); + RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); + HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); + // 当前登录用户 + User loginUser = userService.getLoginUser(request); + UserRoleEnum mustRoleEnum = UserRoleEnum.getEnumByValue(mustRole); + // 不需要权限,放行 + if (mustRoleEnum == null) { + return joinPoint.proceed(); + } + // 必须有该权限才通过 + UserRoleEnum userRoleEnum = UserRoleEnum.getEnumByValue(loginUser.getUserRole()); + if (userRoleEnum == null) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + // 如果被封号,直接拒绝 + if (UserRoleEnum.BAN.equals(userRoleEnum)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + // 必须有管理员权限 + if (UserRoleEnum.ADMIN.equals(mustRoleEnum)) { + // 用户没有管理员权限,拒绝 + if (!UserRoleEnum.ADMIN.equals(userRoleEnum)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + } + // 通过权限校验,放行 + return joinPoint.proceed(); + } +} + diff --git a/src/main/java/com/yupi/springbootinit/aop/LogInterceptor.java b/src/main/java/com/yupi/springbootinit/aop/LogInterceptor.java new file mode 100644 index 0000000..5b804b9 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/aop/LogInterceptor.java @@ -0,0 +1,56 @@ +package com.yupi.springbootinit.aop; + +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +/** + * 请求响应日志 AOP + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + **/ +@Aspect +@Component +@Slf4j +public class LogInterceptor { + + /** + * 执行拦截 + */ + @Around("execution(* com.yupi.springbootinit.controller.*.*(..))") + public Object doInterceptor(ProceedingJoinPoint point) throws Throwable { + // 计时 + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + // 获取请求路径 + RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes(); + HttpServletRequest httpServletRequest = ((ServletRequestAttributes) requestAttributes).getRequest(); + // 生成请求唯一 id + String requestId = UUID.randomUUID().toString(); + String url = httpServletRequest.getRequestURI(); + // 获取请求参数 + Object[] args = point.getArgs(); + String reqParam = "[" + StringUtils.join(args, ", ") + "]"; + // 输出请求日志 + log.info("request start,id: {}, path: {}, ip: {}, params: {}", requestId, url, + httpServletRequest.getRemoteHost(), reqParam); + // 执行原方法 + Object result = point.proceed(); + // 输出响应日志 + stopWatch.stop(); + long totalTimeMillis = stopWatch.getTotalTimeMillis(); + log.info("request end, id: {}, cost: {}ms", requestId, totalTimeMillis); + return result; + } +} + diff --git a/src/main/java/com/yupi/springbootinit/api/OpenAiApi.java b/src/main/java/com/yupi/springbootinit/api/OpenAiApi.java new file mode 100644 index 0000000..5466cdd --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/api/OpenAiApi.java @@ -0,0 +1,38 @@ +package com.yupi.springbootinit.api; + +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +/** + * 调用 AI 平台的示例代码 + */ +@Service +public class OpenAiApi { + + public static void main(String[] args) { + +// /** +// * AI 对话(需要自己创建请求响应对象) +// * +// * @param request +// * @param openAiApiKey +// * @return +// */ +// public CreateChatCompletionResponse createChatCompletion(CreateChatCompletionRequest request, String openAiApiKey) { +// if (StringUtils.isBlank(openAiApiKey)) { +// throw new BusinessException(ErrorCode.PARAMS_ERROR, "未传 openAiApiKey"); +// } +// String url = "https://api.openai.com/v1/chat/completions"; +// String json = JSONUtil.toJsonStr(request); +// String result = HttpRequest.post(url) +// .header("Authorization", "Bearer " + openAiApiKey) +// .body(json) +// .execute() +// .body(); +// return JSONUtil.toBean(result, CreateChatCompletionResponse.class); +// } + + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/common/BaseResponse.java b/src/main/java/com/yupi/springbootinit/common/BaseResponse.java new file mode 100644 index 0000000..c1ca661 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/common/BaseResponse.java @@ -0,0 +1,35 @@ +package com.yupi.springbootinit.common; + +import java.io.Serializable; +import lombok.Data; + +/** + * 通用返回类 + * + * @param + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class BaseResponse implements Serializable { + + private int code; + + private T data; + + private String message; + + public BaseResponse(int code, T data, String message) { + this.code = code; + this.data = data; + this.message = message; + } + + public BaseResponse(int code, T data) { + this(code, data, ""); + } + + public BaseResponse(ErrorCode errorCode) { + this(errorCode.getCode(), null, errorCode.getMessage()); + } +} diff --git a/src/main/java/com/yupi/springbootinit/common/DeleteRequest.java b/src/main/java/com/yupi/springbootinit/common/DeleteRequest.java new file mode 100644 index 0000000..0109023 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/common/DeleteRequest.java @@ -0,0 +1,21 @@ +package com.yupi.springbootinit.common; + +import java.io.Serializable; +import lombok.Data; + +/** + * 删除请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class DeleteRequest implements Serializable { + + /** + * id + */ + private Long id; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/common/ErrorCode.java b/src/main/java/com/yupi/springbootinit/common/ErrorCode.java new file mode 100644 index 0000000..8880472 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/common/ErrorCode.java @@ -0,0 +1,44 @@ +package com.yupi.springbootinit.common; + +/** + * 自定义错误码 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public enum ErrorCode { + + SUCCESS(0, "ok"), + PARAMS_ERROR(40000, "请求参数错误"), + NOT_LOGIN_ERROR(40100, "未登录"), + NO_AUTH_ERROR(40101, "无权限"), + NOT_FOUND_ERROR(40400, "请求数据不存在"), + TOO_MANY_REQUEST(42900, "请求过于频繁"), + FORBIDDEN_ERROR(40300, "禁止访问"), + SYSTEM_ERROR(50000, "系统内部异常"), + OPERATION_ERROR(50001, "操作失败"); + + /** + * 状态码 + */ + private final int code; + + /** + * 信息 + */ + private final String message; + + ErrorCode(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/com/yupi/springbootinit/common/PageRequest.java b/src/main/java/com/yupi/springbootinit/common/PageRequest.java new file mode 100644 index 0000000..f17de55 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/common/PageRequest.java @@ -0,0 +1,34 @@ +package com.yupi.springbootinit.common; + +import com.yupi.springbootinit.constant.CommonConstant; +import lombok.Data; + +/** + * 分页请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PageRequest { + + /** + * 当前页号 + */ + private int current = 1; + + /** + * 页面大小 + */ + private int pageSize = 10; + + /** + * 排序字段 + */ + private String sortField; + + /** + * 排序顺序(默认升序) + */ + private String sortOrder = CommonConstant.SORT_ORDER_ASC; +} diff --git a/src/main/java/com/yupi/springbootinit/common/ResultUtils.java b/src/main/java/com/yupi/springbootinit/common/ResultUtils.java new file mode 100644 index 0000000..5544068 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/common/ResultUtils.java @@ -0,0 +1,52 @@ +package com.yupi.springbootinit.common; + +/** + * 返回工具类 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public class ResultUtils { + + /** + * 成功 + * + * @param data + * @param + * @return + */ + public static BaseResponse success(T data) { + return new BaseResponse<>(0, data, "ok"); + } + + /** + * 失败 + * + * @param errorCode + * @return + */ + public static BaseResponse error(ErrorCode errorCode) { + return new BaseResponse<>(errorCode); + } + + /** + * 失败 + * + * @param code + * @param message + * @return + */ + public static BaseResponse error(int code, String message) { + return new BaseResponse(code, null, message); + } + + /** + * 失败 + * + * @param errorCode + * @return + */ + public static BaseResponse error(ErrorCode errorCode, String message) { + return new BaseResponse(errorCode.getCode(), null, message); + } +} diff --git a/src/main/java/com/yupi/springbootinit/config/CorsConfig.java b/src/main/java/com/yupi/springbootinit/config/CorsConfig.java new file mode 100644 index 0000000..23184b5 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/CorsConfig.java @@ -0,0 +1,28 @@ +package com.yupi.springbootinit.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 全局跨域配置 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Configuration +public class CorsConfig implements WebMvcConfigurer { + + @Override + public void addCorsMappings(CorsRegistry registry) { + // 覆盖所有请求 + registry.addMapping("/**") + // 允许发送 Cookie + .allowCredentials(true) + // 放行哪些域名(必须用 patterns,否则 * 会和 allowCredentials 冲突) + .allowedOriginPatterns("*") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") + .allowedHeaders("*") + .exposedHeaders("*"); + } +} diff --git a/src/main/java/com/yupi/springbootinit/config/CosClientConfig.java b/src/main/java/com/yupi/springbootinit/config/CosClientConfig.java new file mode 100644 index 0000000..f01b26a --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/CosClientConfig.java @@ -0,0 +1,53 @@ +package com.yupi.springbootinit.config; + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.region.Region; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 腾讯云对象存储客户端 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Configuration +@ConfigurationProperties(prefix = "cos.client") +@Data +public class CosClientConfig { + + /** + * accessKey + */ + private String accessKey; + + /** + * secretKey + */ + private String secretKey; + + /** + * 区域 + */ + private String region; + + /** + * 桶名 + */ + private String bucket; + + @Bean + public COSClient cosClient() { + // 初始化用户身份信息(secretId, secretKey) + COSCredentials cred = new BasicCOSCredentials(accessKey, secretKey); + // 设置bucket的区域, COS地域的简称请参照 https://www.qcloud.com/document/product/436/6224 + ClientConfig clientConfig = new ClientConfig(new Region(region)); + // 生成cos客户端 + return new COSClient(cred, clientConfig); + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/config/JsonConfig.java b/src/main/java/com/yupi/springbootinit/config/JsonConfig.java new file mode 100644 index 0000000..86ad8a8 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/JsonConfig.java @@ -0,0 +1,31 @@ +package com.yupi.springbootinit.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import org.springframework.boot.jackson.JsonComponent; +import org.springframework.context.annotation.Bean; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +/** + * Spring MVC Json 配置 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@JsonComponent +public class JsonConfig { + + /** + * 添加 Long 转 json 精度丢失的配置 + */ + @Bean + public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { + ObjectMapper objectMapper = builder.createXmlMapper(false).build(); + SimpleModule module = new SimpleModule(); + module.addSerializer(Long.class, ToStringSerializer.instance); + module.addSerializer(Long.TYPE, ToStringSerializer.instance); + objectMapper.registerModule(module); + return objectMapper; + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/config/MyBatisPlusConfig.java b/src/main/java/com/yupi/springbootinit/config/MyBatisPlusConfig.java new file mode 100644 index 0000000..a5f3b9b --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/MyBatisPlusConfig.java @@ -0,0 +1,31 @@ +package com.yupi.springbootinit.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * MyBatis Plus 配置 + * + * @author https://github.com/liyupi + */ +@Configuration +@MapperScan("com.yupi.springbootinit.mapper") +public class MyBatisPlusConfig { + + /** + * 拦截器配置 + * + * @return + */ + @Bean + public MybatisPlusInterceptor mybatisPlusInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 分页插件 + interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); + return interceptor; + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/config/RedissonConfig.java b/src/main/java/com/yupi/springbootinit/config/RedissonConfig.java new file mode 100644 index 0000000..9927cbb --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/RedissonConfig.java @@ -0,0 +1,34 @@ +package com.yupi.springbootinit.config; + +import lombok.Data; +import org.redisson.Redisson; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "spring.redis") +@Data +public class RedissonConfig { + + private Integer database; + + private String host; + + private Integer port; + + private String password; + + @Bean + public RedissonClient redissonClient() { + Config config = new Config(); + config.useSingleServer() + .setDatabase(database) + .setAddress("redis://" + host + ":" + port); +// .setPassword("123456"); + RedissonClient redisson = Redisson.create(config); + return redisson; + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/config/WxOpenConfig.java b/src/main/java/com/yupi/springbootinit/config/WxOpenConfig.java new file mode 100644 index 0000000..b0d0dc1 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/WxOpenConfig.java @@ -0,0 +1,51 @@ +package com.yupi.springbootinit.config; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +/** + * 微信开放平台配置 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Slf4j +@Configuration +@ConfigurationProperties(prefix = "wx.open") +@Data +public class WxOpenConfig { + + private String appId; + + private String appSecret; + + private WxMpService wxMpService; + + /** + * 单例模式(不用 @Bean 是为了防止和公众号的 service 冲突) + * + * @return + */ + public WxMpService getWxMpService() { + if (wxMpService != null) { + return wxMpService; + } + synchronized (this) { + if (wxMpService != null) { + return wxMpService; + } + WxMpDefaultConfigImpl config = new WxMpDefaultConfigImpl(); + config.setAppId(appId); + config.setSecret(appSecret); + WxMpService service = new WxMpServiceImpl(); + service.setWxMpConfigStorage(config); + wxMpService = service; + return wxMpService; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/config/XingHuoConfig.java b/src/main/java/com/yupi/springbootinit/config/XingHuoConfig.java new file mode 100644 index 0000000..5fab7a8 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/config/XingHuoConfig.java @@ -0,0 +1,30 @@ +package com.yupi.springbootinit.config; + + +import io.github.briqt.spark4j.SparkClient; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author leikooo + * @Description 星火 AI 配置类 + */ +@Configuration +@ConfigurationProperties(prefix = "xun-fei.client") +@Data +public class XingHuoConfig { + private String appId; + private String apiSecret; + private String apiKey; + + @Bean + public SparkClient sparkClient() { + SparkClient sparkClient = new SparkClient(); + sparkClient.apiKey = apiKey; + sparkClient.apiSecret = apiSecret; + sparkClient.appid = appId; + return sparkClient; + } +} diff --git a/src/main/java/com/yupi/springbootinit/constant/CommonConstant.java b/src/main/java/com/yupi/springbootinit/constant/CommonConstant.java new file mode 100644 index 0000000..d7a1a54 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/constant/CommonConstant.java @@ -0,0 +1,21 @@ +package com.yupi.springbootinit.constant; + +/** + * 通用常量 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface CommonConstant { + + /** + * 升序 + */ + String SORT_ORDER_ASC = "ascend"; + + /** + * 降序 + */ + String SORT_ORDER_DESC = " descend"; + +} diff --git a/src/main/java/com/yupi/springbootinit/constant/FileConstant.java b/src/main/java/com/yupi/springbootinit/constant/FileConstant.java new file mode 100644 index 0000000..8781d56 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/constant/FileConstant.java @@ -0,0 +1,16 @@ +package com.yupi.springbootinit.constant; + +/** + * 文件常量 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface FileConstant { + + /** + * COS 访问地址 + * todo 需替换配置 + */ + String COS_HOST = "https://yupi.icu"; +} diff --git a/src/main/java/com/yupi/springbootinit/constant/UserConstant.java b/src/main/java/com/yupi/springbootinit/constant/UserConstant.java new file mode 100644 index 0000000..eeddd9b --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/constant/UserConstant.java @@ -0,0 +1,34 @@ +package com.yupi.springbootinit.constant; + +/** + * 用户常量 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface UserConstant { + + /** + * 用户登录态键 + */ + String USER_LOGIN_STATE = "user_login"; + + // region 权限 + + /** + * 默认角色 + */ + String DEFAULT_ROLE = "user"; + + /** + * 管理员角色 + */ + String ADMIN_ROLE = "admin"; + + /** + * 被封号 + */ + String BAN_ROLE = "ban"; + + // endregion +} diff --git a/src/main/java/com/yupi/springbootinit/controller/ChartController.java b/src/main/java/com/yupi/springbootinit/controller/ChartController.java new file mode 100644 index 0000000..93a407b --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/ChartController.java @@ -0,0 +1,631 @@ +package com.yupi.springbootinit.controller; + +import cn.hutool.core.io.FileUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.annotation.AuthCheck; +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.DeleteRequest; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import com.yupi.springbootinit.constant.CommonConstant; +import com.yupi.springbootinit.constant.FileConstant; +import com.yupi.springbootinit.constant.UserConstant; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.exception.ThrowUtils; +import com.yupi.springbootinit.manager.AiManager; +import com.yupi.springbootinit.manager.RedisLimiterManager; +import com.yupi.springbootinit.model.dto.chart.*; +import com.yupi.springbootinit.model.dto.file.UploadFileRequest; +import com.yupi.springbootinit.model.entity.Chart; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.enums.FileUploadBizEnum; +import com.yupi.springbootinit.model.vo.BiResponse; +import com.yupi.springbootinit.service.ChartService; +import com.yupi.springbootinit.service.UserService; +import com.yupi.springbootinit.utils.ExcelUtils; +import com.yupi.springbootinit.utils.SqlUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 帖子接口 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestController +@RequestMapping("/chart") +@Slf4j +public class ChartController { + + @Resource + private ChartService chartService; + + @Resource + private UserService userService; + + // region 增删改查 + + @Resource + private AiManager aiManager; + + @Resource + private RedisLimiterManager redisLimiterManager; + + @Resource + private ThreadPoolExecutor threadPoolExecutor; + + /** + * 创建 + * + * @param chartAddRequest + * @param request + * @return + */ + @PostMapping("/add") + public BaseResponse addChart(@RequestBody ChartAddRequest chartAddRequest, HttpServletRequest request) { + if (chartAddRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Chart chart = new Chart(); + BeanUtils.copyProperties(chartAddRequest, chart); + User loginUser = userService.getLoginUser(request); + chart.setUserId(loginUser.getId()); + boolean result = chartService.save(chart); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + long newChartId = chart.getId(); + return ResultUtils.success(newChartId); + } + + /** + * 删除 + * + * @param deleteRequest + * @param request + * @return + */ + @PostMapping("/delete") + public BaseResponse deleteChart(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = userService.getLoginUser(request); + long id = deleteRequest.getId(); + // 判断是否存在 + Chart oldChart = chartService.getById(id); + ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR); + // 仅本人或管理员可删除 + if (!oldChart.getUserId().equals(user.getId()) && !userService.isAdmin(request)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + boolean b = chartService.removeById(id); + return ResultUtils.success(b); + } + + /** + * 更新(仅管理员) + * + * @param chartUpdateRequest + * @return + */ + @PostMapping("/update") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse updateChart(@RequestBody ChartUpdateRequest chartUpdateRequest) { + if (chartUpdateRequest == null || chartUpdateRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Chart chart = new Chart(); + BeanUtils.copyProperties(chartUpdateRequest, chart); + long id = chartUpdateRequest.getId(); + // 判断是否存在 + Chart oldChart = chartService.getById(id); + ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR); + boolean result = chartService.updateById(chart); + return ResultUtils.success(result); + } + + /** + * 根据 id 获取 + * + * @param id + * @return + */ + @GetMapping("/get") + public BaseResponse getChartById(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Chart chart = chartService.getById(id); + if (chart == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + return ResultUtils.success(chart); + } + + /** + * 分页获取列表(封装类) + * + * @param chartQueryRequest + * @param request + * @return + */ + @PostMapping("/list/page") + public BaseResponse> listChartByPage(@RequestBody ChartQueryRequest chartQueryRequest, + HttpServletRequest request) { + long current = chartQueryRequest.getCurrent(); + long size = chartQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page chartPage = chartService.page(new Page<>(current, size), + getQueryWrapper(chartQueryRequest)); + return ResultUtils.success(chartPage); + } + + /** + * 分页获取当前用户创建的资源列表 + * + * @param chartQueryRequest + * @param request + * @return + */ + @PostMapping("/my/list/page") + public BaseResponse> listMyChartByPage(@RequestBody ChartQueryRequest chartQueryRequest, + HttpServletRequest request) { + if (chartQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + chartQueryRequest.setUserId(loginUser.getId()); + long current = chartQueryRequest.getCurrent(); + long size = chartQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page chartPage = chartService.page(new Page<>(current, size), + getQueryWrapper(chartQueryRequest)); + return ResultUtils.success(chartPage); + } + + // endregion + + /** + * 编辑(用户) + * + * @param chartEditRequest + * @param request + * @return + */ + @PostMapping("/edit") + public BaseResponse editChart(@RequestBody ChartEditRequest chartEditRequest, HttpServletRequest request) { + if (chartEditRequest == null || chartEditRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Chart chart = new Chart(); + BeanUtils.copyProperties(chartEditRequest, chart); + User loginUser = userService.getLoginUser(request); + long id = chartEditRequest.getId(); + // 判断是否存在 + Chart oldChart = chartService.getById(id); + ThrowUtils.throwIf(oldChart == null, ErrorCode.NOT_FOUND_ERROR); + // 仅本人或管理员可编辑 + if (!oldChart.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + boolean result = chartService.updateById(chart); + return ResultUtils.success(result); + } + + + + /** + * 智能分析(同步) + * + * @param multipartFile + * @param genChartByAiRequest + * @param request + * @return + */ + @PostMapping("/gen") + public BaseResponse genChartByAi(@RequestPart("file") MultipartFile multipartFile, + GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) { + String name = genChartByAiRequest.getName(); + String goal = genChartByAiRequest.getGoal(); + String chartType = genChartByAiRequest.getChartType(); + // 校验 + ThrowUtils.throwIf(StringUtils.isBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空"); + ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长"); + + //校验文件 + long size =multipartFile.getSize(); + String originalFilename = multipartFile.getOriginalFilename(); + //校验文件大小 + final long ONE_MB = 10 *1024*1024L; + ThrowUtils.throwIf(size>ONE_MB,ErrorCode.PARAMS_ERROR,"文件超过10M"); + //校验文件后缀 + String suffix = FileUtil.getSuffix(originalFilename); + final List validFileSuffixList = Arrays.asList("xlsx","xls"); + ThrowUtils.throwIf(!validFileSuffixList.contains(suffix),ErrorCode.PARAMS_ERROR,"文件后缀不合法"); + + + +// final String prompt = "你是一个数据分析师和前端开发专家,接下来我会按照以下固定格式给你提供内容:\n" + +// "分析需求:\n" + +// "{数据分析的需求或者目标}\n" + +// "原始数据:\n" + +// "{csv格式的原始数据,用,作为分隔符}\n" + +// "请根据这两部分内容,按照以下指定格式生成内容(此外不要输出任何多余的开头、结尾、注释)\n" + +// "'【【【【'\n" + +// "{前端 Echarts V5 的 option 配置对象js代码,合理地将数据进行可视化,不要生成任何多余的内容,比如注释}\n" + +// "'【【【【'\n" + +// "{明确的数据分析结论、越详细越好,不要生成多余的注释}"; + + User loginUser = userService.getLoginUser(request); + // 限流判断,每个用户一个限流器 + redisLimiterManager.doRateLimit("genChartByAi_" + loginUser.getId()); + + + // 分析需求: + // 分析网站用户的增长情况 + // 原始数据: + // 日期,用户数 + // 1号,10 + // 2号,20 + // 3号,30 + + // 构造用户输入 + StringBuilder userInput = new StringBuilder(); + userInput.append("分析需求:").append("\n"); + + // 拼接分析目标 + String userGoal = goal; + if (StringUtils.isNotBlank(chartType)) { + userGoal += ",请使用" + chartType; + } + userInput.append(userGoal).append("\n"); + userInput.append("原始数据:").append("\n"); + // 压缩后的数据 + String csvData = ExcelUtils.excelToCsv(multipartFile); + userInput.append(csvData).append("\n"); + + String result = aiManager.sendMsgToXingHuo(true,userInput.toString()); + + + String[] splits = result.split("'【【【【'"); + if (splits.length < 3) { + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "AI 生成错误"); + } + + String genChart = splits[1].trim(); + String genResult = splits[2].trim(); + + + // 插入到数据库 + Chart chart = new Chart(); + chart.setName(name); + chart.setGoal(goal); + chart.setChartData(csvData); + chart.setChartType(chartType); + chart.setGenChart(genChart); + chart.setGenResult(genResult); + chart.setUserId(loginUser.getId()); + boolean saveResult = chartService.save(chart); + ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败"); + + BiResponse biResponse = new BiResponse(); + biResponse.setGenChart(genChart); + biResponse.setGenResult(genResult); + biResponse.setChartId(chart.getId()); + return ResultUtils.success(biResponse); + +// // 校验文件 +// long size = multipartFile.getSize(); +// String originalFilename = multipartFile.getOriginalFilename(); +// // 校验文件大小 +// final long ONE_MB = 1024 * 1024L; +// ThrowUtils.throwIf(size > ONE_MB, ErrorCode.PARAMS_ERROR, "文件超过 1M"); +// // 校验文件后缀 aaa.png +// String suffix = FileUtil.getSuffix(originalFilename); +// final List validFileSuffixList = Arrays.asList("xlsx"); +// ThrowUtils.throwIf(!validFileSuffixList.contains(suffix), ErrorCode.PARAMS_ERROR, "文件后缀非法"); +// +// User loginUser = userService.getLoginUser(request); +// +// +// return ResultUtils.success(""); + } + + + /** + * 智能分析(异步) + * + * @param multipartFile + * @param genChartByAiRequest + * @param request + * @return + */ + @PostMapping("/gen/async") + public BaseResponse genChartByAiAsync(@RequestPart("file") MultipartFile multipartFile, + GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) { + String name = genChartByAiRequest.getName(); + String goal = genChartByAiRequest.getGoal(); + String chartType = genChartByAiRequest.getChartType(); + // 校验 + ThrowUtils.throwIf(StringUtils.isBlank(goal), ErrorCode.PARAMS_ERROR, "目标为空"); + ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length() > 100, ErrorCode.PARAMS_ERROR, "名称过长"); + // 校验文件 + long size = multipartFile.getSize(); + String originalFilename = multipartFile.getOriginalFilename(); + // 校验文件大小 + final long ONE_MB = 1024 * 1024L; + ThrowUtils.throwIf(size > ONE_MB, ErrorCode.PARAMS_ERROR, "文件超过 1M"); + // 校验文件后缀 aaa.png + String suffix = FileUtil.getSuffix(originalFilename); + final List validFileSuffixList = Arrays.asList("xlsx", "xls"); + ThrowUtils.throwIf(!validFileSuffixList.contains(suffix), ErrorCode.PARAMS_ERROR, "文件后缀非法"); + + User loginUser = userService.getLoginUser(request); + // 限流判断,每个用户一个限流器 + redisLimiterManager.doRateLimit("genChartByAi_" + loginUser.getId()); + + + // 构造用户输入 + StringBuilder userInput = new StringBuilder(); + userInput.append("分析需求:").append("\n"); + + // 拼接分析目标 + String userGoal = goal; + if (StringUtils.isNotBlank(chartType)) { + userGoal += ",请使用" + chartType; + } + userInput.append(userGoal).append("\n"); + userInput.append("原始数据:").append("\n"); + // 压缩后的数据 + String csvData = ExcelUtils.excelToCsv(multipartFile); + userInput.append(csvData).append("\n"); + + // 插入到数据库 + Chart chart = new Chart(); + chart.setName(name); + chart.setGoal(goal); + chart.setChartData(csvData); + chart.setChartType(chartType); + chart.setStatus("wait"); + chart.setUserId(loginUser.getId()); + boolean saveResult = chartService.save(chart); // 直接插入 + ThrowUtils.throwIf(!saveResult, ErrorCode.SYSTEM_ERROR, "图表保存失败"); + + // todo 建议处理任务队列满了后,抛异常的情况 + try{ + CompletableFuture.runAsync(() -> { + // 先修改图表任务状态为 “执行中”。等执行成功后,修改为 “已完成”、保存执行结果;执行失败后,状态修改为 “失败”,记录任务失败信息。 + Chart updateChart = new Chart(); + updateChart.setId(chart.getId()); + updateChart.setStatus("running"); + boolean b = chartService.updateById(updateChart); + if (!b) { + handleChartUpdateError(chart.getId(), "更新图表执行中状态失败"); + return; + } + // 调用 AI + String result = aiManager.sendMsgToXingHuo(true,userInput.toString()); + String[] splits = result.split("'【【【【'"); + if (splits.length < 3) { + handleChartUpdateError(chart.getId(), "AI 生成错误"); + return; + } + String genChart = splits[1].trim(); + String genResult = splits[2].trim(); + Chart updateChartResult = new Chart(); + updateChartResult.setId(chart.getId()); + updateChartResult.setGenChart(genChart); + updateChartResult.setGenResult(genResult); + // todo 建议定义状态为枚举值 + updateChartResult.setStatus("succeed"); + boolean updateResult = chartService.updateById(updateChartResult); + if (!updateResult) { + handleChartUpdateError(chart.getId(), "更新图表成功状态失败"); + } + }, threadPoolExecutor); + }catch (RejectedExecutionException e) { + log.error("任务队列已满,无法提交异步任务", e); + // 更新图表状态为失败 + handleChartUpdateError(chart.getId(), "任务队列已满,无法处理"); + } + + + BiResponse biResponse = new BiResponse(); + biResponse.setChartId(chart.getId()); + return ResultUtils.success(biResponse); + } + + + + //工具类 + private void handleChartUpdateError(long chartId, String execMessage) { + Chart updateChartResult = new Chart(); + updateChartResult.setId(chartId); + updateChartResult.setStatus("failed"); + updateChartResult.setExecMessage("execMessage"); + boolean updateResult = chartService.updateById(updateChartResult); + if (!updateResult) { + log.error("更新图表失败状态失败" + chartId + "," + execMessage); + } + } + + +// /** +// * 智能分析 +// * +// * @param multipartFile +// * @param genChartByAiRequest +// * @param request +// * @return +// */ +// @PostMapping("/gen") +// public BaseResponse genChartByAi(@RequestPart("file") MultipartFile multipartFile, +// GenChartByAiRequest genChartByAiRequest, HttpServletRequest request) { +// String name = genChartByAiRequest.getName(); +// String goal = genChartByAiRequest.getGoal(); +// String chartType = genChartByAiRequest.getChartType(); +// //校验 +// ThrowUtils.throwIf(StringUtils.isBlank(goal),ErrorCode.PARAMS_ERROR,"目标为空"); +// ThrowUtils.throwIf(StringUtils.isNotBlank(name) && name.length()>100,ErrorCode.PARAMS_ERROR,"名称过长"); +// +// //校验文件 +// long size =multipartFile.getSize(); +// String originalFilename = multipartFile.getOriginalFilename(); +// //校验文件大小 +// final long ONE_MB = 10 *1024*1024L; +// ThrowUtils.throwIf(size>ONE_MB,ErrorCode.PARAMS_ERROR,"文件超过10M"); +// //校验文件后缀 +// String suffix = FileUtil.getSuffix(originalFilename); +// final List validFileSuffixList = Arrays.asList("xlsx","xls"); +// ThrowUtils.throwIf(!validFileSuffixList.contains(suffix),ErrorCode.PARAMS_ERROR,"文件后缀不合法"); +// +// //获取用户信息 +// User loginUser = userService.getLoginUser(request); +// //限流判断,每个用户一个限流器(方法名+用户id) +// redisLimiterManager.doRateLimit("genChartByAi_"+loginUser.getId()); +// +// +// //系统预设 +//// final String prompt = "你是一个数据分析师和前端开发专家,接下来我会按照以下固定格式给你提供内容:\n" + +//// "分析需求:\n" + +//// "(数据分析的需求或者目标}\n" + +//// "原始数据:\n" + +//// "{csv格式的原始数据,用,作为分隔符]\n" + +//// "请根据这两部分内容,按照以下指定格式生成内容(此外不要输出任何多余的开头、结尾、注释)\n" + +//// "'【【【【'\n" + +//// "{前端Echarts V5的option配置对象js代码,合理地将数据进行可视化,不要生成任何多余的内容,比如注释}\n" + +//// "'【【【【'\n" + +//// "(明确的数据分析结论、越详细越好,不要生成多余的注释}"; +// +// +// //构造用户输入 +// StringBuilder userInput = new StringBuilder(); +// userInput.append("分析需求:").append("\n"); +// +// //拼接分析目标 +// String userGoal =goal; +// if(StringUtils.isNotBlank(chartType)){ +// userGoal+=",请使用"+chartType; +// } +// userInput.append(userGoal).append("\n"); +// userInput.append("原始数据:").append("\n"); +// +// //压缩后的数据 +// String csvData=ExcelUtils.excelToCsv(multipartFile); +// userInput.append(csvData).append("\n"); +// +// //插入到数据库中 +// Chart chart = new Chart(); +// chart.setName(name); +// chart.setGoal(goal); +// chart.setChartData(csvData); +// chart.setChartType(chartType); +// chart.setStatus("wait"); +// chart.setUserId(loginUser.getId()); +// boolean saveResult = chartService.save(chart); +// ThrowUtils.throwIf(!saveResult,ErrorCode.SYSTEM_ERROR,"图表保存失败"); +// +// //处理任务队列满了后,抛异常的情况 +// try { +// CompletableFuture.runAsync(() -> { +// // 先修改图表任务状态为 “执行中”。等执行成功后,修改为 “已完成”、保存执行结果;执行失败后,状态修改为 “失败”,记录任务失败信息。 +// Chart updateChart = new Chart(); +// updateChart.setId(chart.getId()); +// updateChart.setStatus("running"); +// boolean b = chartService.updateById(updateChart); +// if (!b) { +// handleChartUpdateError(chart.getId(), "更新图表执行中状态失败"); +// return; +// } +// //调用ai +// String result = aiManager.sendMsgToXingHuo(true,userInput.toString()); +// String[] splits = result.split("'【【【【'"); +// if(splits.length<3){ +// handleChartUpdateError(chart.getId(), "AI 生成错误"); +// return; +// } +// String genChart =splits[1].trim(); +// String genResult = splits[2].trim(); +// Chart updateChartResult = new Chart(); +// updateChartResult.setId(chart.getId()); +// updateChartResult.setGenChart(genChart); +// updateChartResult.setGenResult(genResult); +// updateChartResult.setStatus("success"); +// boolean updateResult = chartService.updateById(updateChartResult); +// if (!updateResult) { +// handleChartUpdateError(chart.getId(), "更新图表成功状态失败"); +// } +// },threadPoolExecutor); +// }catch (RejectedExecutionException e) { +// System.err.println("任务被拒绝,线程池任务队列已满: " + e.getMessage()); +// } +// +// BiResponse biResponse =new BiResponse(); +// biResponse.setChartId(chart.getId()); +// return ResultUtils.success(biResponse); +// +// } +// +// +// //工具类 +// private void handleChartUpdateError(long chartId, String execMessage) { +// Chart updateChartResult = new Chart(); +// updateChartResult.setId(chartId); +// updateChartResult.setStatus("failed"); +// updateChartResult.setExecMessage("execMessage"); +// boolean updateResult = chartService.updateById(updateChartResult); +// if (!updateResult) { +// log.error("更新图表失败状态失败" + chartId + "," + execMessage); +// } +// } + + + + /** + * 获取查询包装类 + * + * @param chartQueryRequest + * @return + */ + private QueryWrapper getQueryWrapper(ChartQueryRequest chartQueryRequest) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (chartQueryRequest == null) { + return queryWrapper; + } + Long id = chartQueryRequest.getId(); + String name = chartQueryRequest.getName(); + String goal = chartQueryRequest.getGoal(); + String chartType = chartQueryRequest.getChartType(); + Long userId = chartQueryRequest.getUserId(); + String sortField = chartQueryRequest.getSortField(); + String sortOrder = chartQueryRequest.getSortOrder(); + + queryWrapper.eq(id!=null && id>0,"id",id); + queryWrapper.like(StringUtils.isNotBlank(name),"name",name); + queryWrapper.eq(StringUtils.isNotBlank(goal),"goal",goal); + queryWrapper.eq(StringUtils.isNotBlank(chartType),"chartType",chartType); + queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId); + queryWrapper.eq("isDelete",false); + queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), + sortField); + return queryWrapper; + } + +} diff --git a/src/main/java/com/yupi/springbootinit/controller/FileController.java b/src/main/java/com/yupi/springbootinit/controller/FileController.java new file mode 100644 index 0000000..cd3b060 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/FileController.java @@ -0,0 +1,108 @@ +package com.yupi.springbootinit.controller; + +import cn.hutool.core.io.FileUtil; +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import com.yupi.springbootinit.constant.FileConstant; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.manager.CosManager; +import com.yupi.springbootinit.model.dto.file.UploadFileRequest; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.enums.FileUploadBizEnum; +import com.yupi.springbootinit.service.UserService; +import java.io.File; +import java.util.Arrays; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +/** + * 文件接口 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestController +@RequestMapping("/file") +@Slf4j +public class FileController { + + @Resource + private UserService userService; + + @Resource + private CosManager cosManager; + + /** + * 文件上传 + * + * @param multipartFile + * @param uploadFileRequest + * @param request + * @return + */ + @PostMapping("/upload") + public BaseResponse uploadFile(@RequestPart("file") MultipartFile multipartFile, + UploadFileRequest uploadFileRequest, HttpServletRequest request) { + String biz = uploadFileRequest.getBiz(); + FileUploadBizEnum fileUploadBizEnum = FileUploadBizEnum.getEnumByValue(biz); + if (fileUploadBizEnum == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + validFile(multipartFile, fileUploadBizEnum); + User loginUser = userService.getLoginUser(request); + // 文件目录:根据业务、用户来划分 + String uuid = RandomStringUtils.randomAlphanumeric(8); + String filename = uuid + "-" + multipartFile.getOriginalFilename(); + String filepath = String.format("/%s/%s/%s", fileUploadBizEnum.getValue(), loginUser.getId(), filename); + File file = null; + try { + // 上传文件 + file = File.createTempFile(filepath, null); + multipartFile.transferTo(file); + cosManager.putObject(filepath, file); + // 返回可访问地址 + return ResultUtils.success(FileConstant.COS_HOST + filepath); + } catch (Exception e) { + log.error("file upload error, filepath = " + filepath, e); + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败"); + } finally { + if (file != null) { + // 删除临时文件 + boolean delete = file.delete(); + if (!delete) { + log.error("file delete error, filepath = {}", filepath); + } + } + } + } + + /** + * 校验文件 + * + * @param multipartFile + * @param fileUploadBizEnum 业务类型 + */ + private void validFile(MultipartFile multipartFile, FileUploadBizEnum fileUploadBizEnum) { + // 文件大小 + long fileSize = multipartFile.getSize(); + // 文件后缀 + String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename()); + final long ONE_M = 1024 * 1024L; + if (FileUploadBizEnum.USER_AVATAR.equals(fileUploadBizEnum)) { + if (fileSize > ONE_M) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件大小不能超过 1M"); + } + if (!Arrays.asList("jpeg", "jpg", "svg", "png", "webp").contains(fileSuffix)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件类型错误"); + } + } + } +} diff --git a/src/main/java/com/yupi/springbootinit/controller/PostController.java b/src/main/java/com/yupi/springbootinit/controller/PostController.java new file mode 100644 index 0000000..676f173 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/PostController.java @@ -0,0 +1,263 @@ +package com.yupi.springbootinit.controller; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.annotation.AuthCheck; +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.DeleteRequest; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import com.yupi.springbootinit.constant.UserConstant; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.exception.ThrowUtils; +import com.yupi.springbootinit.model.dto.post.PostAddRequest; +import com.yupi.springbootinit.model.dto.post.PostEditRequest; +import com.yupi.springbootinit.model.dto.post.PostQueryRequest; +import com.yupi.springbootinit.model.dto.post.PostUpdateRequest; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.vo.PostVO; +import com.yupi.springbootinit.service.PostService; +import com.yupi.springbootinit.service.UserService; +import java.util.List; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 帖子接口 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestController +@RequestMapping("/post") +@Slf4j +public class PostController { + + @Resource + private PostService postService; + + @Resource + private UserService userService; + + // region 增删改查 + + /** + * 创建 + * + * @param postAddRequest + * @param request + * @return + */ + @PostMapping("/add") + public BaseResponse addPost(@RequestBody PostAddRequest postAddRequest, HttpServletRequest request) { + if (postAddRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Post post = new Post(); + BeanUtils.copyProperties(postAddRequest, post); + List tags = postAddRequest.getTags(); + if (tags != null) { + post.setTags(JSONUtil.toJsonStr(tags)); + } + postService.validPost(post, true); + User loginUser = userService.getLoginUser(request); + post.setUserId(loginUser.getId()); + post.setFavourNum(0); + post.setThumbNum(0); + boolean result = postService.save(post); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + long newPostId = post.getId(); + return ResultUtils.success(newPostId); + } + + /** + * 删除 + * + * @param deleteRequest + * @param request + * @return + */ + @PostMapping("/delete") + public BaseResponse deletePost(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = userService.getLoginUser(request); + long id = deleteRequest.getId(); + // 判断是否存在 + Post oldPost = postService.getById(id); + ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR); + // 仅本人或管理员可删除 + if (!oldPost.getUserId().equals(user.getId()) && !userService.isAdmin(request)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + boolean b = postService.removeById(id); + return ResultUtils.success(b); + } + + /** + * 更新(仅管理员) + * + * @param postUpdateRequest + * @return + */ + @PostMapping("/update") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse updatePost(@RequestBody PostUpdateRequest postUpdateRequest) { + if (postUpdateRequest == null || postUpdateRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Post post = new Post(); + BeanUtils.copyProperties(postUpdateRequest, post); + List tags = postUpdateRequest.getTags(); + if (tags != null) { + post.setTags(JSONUtil.toJsonStr(tags)); + } + // 参数校验 + postService.validPost(post, false); + long id = postUpdateRequest.getId(); + // 判断是否存在 + Post oldPost = postService.getById(id); + ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR); + boolean result = postService.updateById(post); + return ResultUtils.success(result); + } + + /** + * 根据 id 获取 + * + * @param id + * @return + */ + @GetMapping("/get/vo") + public BaseResponse getPostVOById(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Post post = postService.getById(id); + if (post == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + return ResultUtils.success(postService.getPostVO(post, request)); + } + + /** + * 分页获取列表(仅管理员) + * + * @param postQueryRequest + * @return + */ + @PostMapping("/list/page") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse> listPostByPage(@RequestBody PostQueryRequest postQueryRequest) { + long current = postQueryRequest.getCurrent(); + long size = postQueryRequest.getPageSize(); + Page postPage = postService.page(new Page<>(current, size), + postService.getQueryWrapper(postQueryRequest)); + return ResultUtils.success(postPage); + } + + /** + * 分页获取列表(封装类) + * + * @param postQueryRequest + * @param request + * @return + */ + @PostMapping("/list/page/vo") + public BaseResponse> listPostVOByPage(@RequestBody PostQueryRequest postQueryRequest, + HttpServletRequest request) { + long current = postQueryRequest.getCurrent(); + long size = postQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page postPage = postService.page(new Page<>(current, size), + postService.getQueryWrapper(postQueryRequest)); + return ResultUtils.success(postService.getPostVOPage(postPage, request)); + } + + /** + * 分页获取当前用户创建的资源列表 + * + * @param postQueryRequest + * @param request + * @return + */ + @PostMapping("/my/list/page/vo") + public BaseResponse> listMyPostVOByPage(@RequestBody PostQueryRequest postQueryRequest, + HttpServletRequest request) { + if (postQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + postQueryRequest.setUserId(loginUser.getId()); + long current = postQueryRequest.getCurrent(); + long size = postQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page postPage = postService.page(new Page<>(current, size), + postService.getQueryWrapper(postQueryRequest)); + return ResultUtils.success(postService.getPostVOPage(postPage, request)); + } + + // endregion + + /** + * 分页搜索(从 ES 查询,封装类) + * + * @param postQueryRequest + * @param request + * @return + */ + @PostMapping("/search/page/vo") + public BaseResponse> searchPostVOByPage(@RequestBody PostQueryRequest postQueryRequest, + HttpServletRequest request) { + long size = postQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page postPage = postService.searchFromEs(postQueryRequest); + return ResultUtils.success(postService.getPostVOPage(postPage, request)); + } + + /** + * 编辑(用户) + * + * @param postEditRequest + * @param request + * @return + */ + @PostMapping("/edit") + public BaseResponse editPost(@RequestBody PostEditRequest postEditRequest, HttpServletRequest request) { + if (postEditRequest == null || postEditRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + Post post = new Post(); + BeanUtils.copyProperties(postEditRequest, post); + List tags = postEditRequest.getTags(); + if (tags != null) { + post.setTags(JSONUtil.toJsonStr(tags)); + } + // 参数校验 + postService.validPost(post, false); + User loginUser = userService.getLoginUser(request); + long id = postEditRequest.getId(); + // 判断是否存在 + Post oldPost = postService.getById(id); + ThrowUtils.throwIf(oldPost == null, ErrorCode.NOT_FOUND_ERROR); + // 仅本人或管理员可编辑 + if (!oldPost.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + boolean result = postService.updateById(post); + return ResultUtils.success(result); + } + +} diff --git a/src/main/java/com/yupi/springbootinit/controller/PostFavourController.java b/src/main/java/com/yupi/springbootinit/controller/PostFavourController.java new file mode 100644 index 0000000..767d4ef --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/PostFavourController.java @@ -0,0 +1,109 @@ +package com.yupi.springbootinit.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.exception.ThrowUtils; +import com.yupi.springbootinit.model.dto.post.PostQueryRequest; +import com.yupi.springbootinit.model.dto.postfavour.PostFavourAddRequest; +import com.yupi.springbootinit.model.dto.postfavour.PostFavourQueryRequest; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.vo.PostVO; +import com.yupi.springbootinit.service.PostFavourService; +import com.yupi.springbootinit.service.PostService; +import com.yupi.springbootinit.service.UserService; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +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; + +/** + * 帖子收藏接口 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestController +@RequestMapping("/post_favour") +@Slf4j +public class PostFavourController { + + @Resource + private PostFavourService postFavourService; + + @Resource + private PostService postService; + + @Resource + private UserService userService; + + /** + * 收藏 / 取消收藏 + * + * @param postFavourAddRequest + * @param request + * @return resultNum 收藏变化数 + */ + @PostMapping("/") + public BaseResponse doPostFavour(@RequestBody PostFavourAddRequest postFavourAddRequest, + HttpServletRequest request) { + if (postFavourAddRequest == null || postFavourAddRequest.getPostId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + // 登录才能操作 + final User loginUser = userService.getLoginUser(request); + long postId = postFavourAddRequest.getPostId(); + int result = postFavourService.doPostFavour(postId, loginUser); + return ResultUtils.success(result); + } + + /** + * 获取我收藏的帖子列表 + * + * @param postQueryRequest + * @param request + */ + @PostMapping("/my/list/page") + public BaseResponse> listMyFavourPostByPage(@RequestBody PostQueryRequest postQueryRequest, + HttpServletRequest request) { + if (postQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + long current = postQueryRequest.getCurrent(); + long size = postQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page postPage = postFavourService.listFavourPostByPage(new Page<>(current, size), + postService.getQueryWrapper(postQueryRequest), loginUser.getId()); + return ResultUtils.success(postService.getPostVOPage(postPage, request)); + } + + /** + * 获取用户收藏的帖子列表 + * + * @param postFavourQueryRequest + * @param request + */ + @PostMapping("/list/page") + public BaseResponse> listFavourPostByPage(@RequestBody PostFavourQueryRequest postFavourQueryRequest, + HttpServletRequest request) { + if (postFavourQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long current = postFavourQueryRequest.getCurrent(); + long size = postFavourQueryRequest.getPageSize(); + Long userId = postFavourQueryRequest.getUserId(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20 || userId == null, ErrorCode.PARAMS_ERROR); + Page postPage = postFavourService.listFavourPostByPage(new Page<>(current, size), + postService.getQueryWrapper(postFavourQueryRequest.getPostQueryRequest()), userId); + return ResultUtils.success(postService.getPostVOPage(postPage, request)); + } +} diff --git a/src/main/java/com/yupi/springbootinit/controller/PostThumbController.java b/src/main/java/com/yupi/springbootinit/controller/PostThumbController.java new file mode 100644 index 0000000..faaaa3c --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/PostThumbController.java @@ -0,0 +1,56 @@ +package com.yupi.springbootinit.controller; + +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.model.dto.postthumb.PostThumbAddRequest; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.service.PostThumbService; +import com.yupi.springbootinit.service.UserService; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +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; + +/** + * 帖子点赞接口 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestController +@RequestMapping("/post_thumb") +@Slf4j +public class PostThumbController { + + @Resource + private PostThumbService postThumbService; + + @Resource + private UserService userService; + + /** + * 点赞 / 取消点赞 + * + * @param postThumbAddRequest + * @param request + * @return resultNum 本次点赞变化数 + */ + @PostMapping("/") + public BaseResponse doThumb(@RequestBody PostThumbAddRequest postThumbAddRequest, + HttpServletRequest request) { + if (postThumbAddRequest == null || postThumbAddRequest.getPostId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + // 登录才能点赞 + final User loginUser = userService.getLoginUser(request); + long postId = postThumbAddRequest.getPostId(); + int result = postThumbService.doPostThumb(postId, loginUser); + return ResultUtils.success(result); + } + +} diff --git a/src/main/java/com/yupi/springbootinit/controller/QueueController.java b/src/main/java/com/yupi/springbootinit/controller/QueueController.java new file mode 100644 index 0000000..9591eeb --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/QueueController.java @@ -0,0 +1,56 @@ +package com.yupi.springbootinit.controller; + +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 队列测试 + * + * @author Ding Jiaxiong + */ +@RestController +@RequestMapping("/queue") +@Slf4j +@Profile({ "dev", "local" }) +public class QueueController { + + @Resource + private ThreadPoolExecutor threadPoolExecutor; + + @GetMapping("/add") + public void add(String name) { + CompletableFuture.runAsync(() -> { +// System.out.println("任务执行中:" + name + ",执行人:" + Thread.currentThread().getName()); + log.info("任务执行中:" + name + ",执行人:" + Thread.currentThread().getName()); + try { + Thread.sleep(600000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }, threadPoolExecutor); + } + + @GetMapping("/get") + public String get() { + Map map = new HashMap<>(); + int size = threadPoolExecutor.getQueue().size(); + map.put("队列长度", size); + long taskCount = threadPoolExecutor.getTaskCount(); + map.put("任务总数", taskCount); + long completedTaskCount = threadPoolExecutor.getCompletedTaskCount(); + map.put("已完成任务数", completedTaskCount); + int activeCount = threadPoolExecutor.getActiveCount(); + map.put("正在工作的线程数", activeCount); + return JSONUtil.toJsonStr(map); + } +} diff --git a/src/main/java/com/yupi/springbootinit/controller/UserController.java b/src/main/java/com/yupi/springbootinit/controller/UserController.java new file mode 100644 index 0000000..d13d448 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/controller/UserController.java @@ -0,0 +1,293 @@ +package com.yupi.springbootinit.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.annotation.AuthCheck; +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.DeleteRequest; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import com.yupi.springbootinit.config.WxOpenConfig; +import com.yupi.springbootinit.constant.UserConstant; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.exception.ThrowUtils; +import com.yupi.springbootinit.model.dto.user.UserAddRequest; +import com.yupi.springbootinit.model.dto.user.UserLoginRequest; +import com.yupi.springbootinit.model.dto.user.UserQueryRequest; +import com.yupi.springbootinit.model.dto.user.UserRegisterRequest; +import com.yupi.springbootinit.model.dto.user.UserUpdateMyRequest; +import com.yupi.springbootinit.model.dto.user.UserUpdateRequest; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.vo.LoginUserVO; +import com.yupi.springbootinit.model.vo.UserVO; +import com.yupi.springbootinit.service.UserService; + +import java.util.List; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.util.DigestUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static com.yupi.springbootinit.service.impl.UserServiceImpl.SALT; + +/** + * 用户接口 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestController +@RequestMapping("/user") +@Slf4j +public class UserController { + + @Resource + private UserService userService; + + @Resource + private WxOpenConfig wxOpenConfig; + + // region 登录相关 + + /** + * 用户注册 + * + * @param userRegisterRequest + * @return + */ + @PostMapping("/register") + public BaseResponse userRegister(@RequestBody UserRegisterRequest userRegisterRequest) { + if (userRegisterRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + String userAccount = userRegisterRequest.getUserAccount(); + String userPassword = userRegisterRequest.getUserPassword(); + String checkPassword = userRegisterRequest.getCheckPassword(); + if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) { + return null; + } + long result = userService.userRegister(userAccount, userPassword, checkPassword); + return ResultUtils.success(result); + } + + /** + * 用户登录 + * + * @param userLoginRequest + * @param request + * @return + */ + @PostMapping("/login") + public BaseResponse userLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request) { + if (userLoginRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + String userAccount = userLoginRequest.getUserAccount(); + String userPassword = userLoginRequest.getUserPassword(); + if (StringUtils.isAnyBlank(userAccount, userPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + LoginUserVO loginUserVO = userService.userLogin(userAccount, userPassword, request); + return ResultUtils.success(loginUserVO); + } + + /** + * 用户注销 + * + * @param request + * @return + */ + @PostMapping("/logout") + public BaseResponse userLogout(HttpServletRequest request) { + if (request == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean result = userService.userLogout(request); + return ResultUtils.success(result); + } + + /** + * 获取当前登录用户 + * + * @param request + * @return + */ + @GetMapping("/get/login") + public BaseResponse getLoginUser(HttpServletRequest request) { + User user = userService.getLoginUser(request); + return ResultUtils.success(userService.getLoginUserVO(user)); + } + + // endregion + + // region 增删改查 + + /** + * 创建用户 + * + * @param userAddRequest + * @param request + * @return + */ + @PostMapping("/add") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse addUser(@RequestBody UserAddRequest userAddRequest, HttpServletRequest request) { + if (userAddRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = new User(); + BeanUtils.copyProperties(userAddRequest, user); + // 默认密码 12345678 + String defaultPassword = "12345678"; + String encryptPassword = DigestUtils.md5DigestAsHex((SALT + defaultPassword).getBytes()); + user.setUserPassword(encryptPassword); + boolean result = userService.save(user); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(user.getId()); + } + + /** + * 删除用户 + * + * @param deleteRequest + * @param request + * @return + */ + @PostMapping("/delete") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse deleteUser(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + boolean b = userService.removeById(deleteRequest.getId()); + return ResultUtils.success(b); + } + + /** + * 更新用户 + * + * @param userUpdateRequest + * @param request + * @return + */ + @PostMapping("/update") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse updateUser(@RequestBody UserUpdateRequest userUpdateRequest, + HttpServletRequest request) { + if (userUpdateRequest == null || userUpdateRequest.getId() == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = new User(); + BeanUtils.copyProperties(userUpdateRequest, user); + boolean result = userService.updateById(user); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(true); + } + + /** + * 根据 id 获取用户(仅管理员) + * + * @param id + * @param request + * @return + */ + @GetMapping("/get") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse getUserById(long id, HttpServletRequest request) { + if (id <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = userService.getById(id); + ThrowUtils.throwIf(user == null, ErrorCode.NOT_FOUND_ERROR); + return ResultUtils.success(user); + } + + /** + * 根据 id 获取包装类 + * + * @param id + * @param request + * @return + */ + @GetMapping("/get/vo") + public BaseResponse getUserVOById(long id, HttpServletRequest request) { + BaseResponse response = getUserById(id, request); + User user = response.getData(); + return ResultUtils.success(userService.getUserVO(user)); + } + + /** + * 分页获取用户列表(仅管理员) + * + * @param userQueryRequest + * @param request + * @return + */ + @PostMapping("/list/page") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse> listUserByPage(@RequestBody UserQueryRequest userQueryRequest, + HttpServletRequest request) { + long current = userQueryRequest.getCurrent(); + long size = userQueryRequest.getPageSize(); + Page userPage = userService.page(new Page<>(current, size), + userService.getQueryWrapper(userQueryRequest)); + return ResultUtils.success(userPage); + } + + /** + * 分页获取用户封装列表 + * + * @param userQueryRequest + * @param request + * @return + */ + @PostMapping("/list/page/vo") + public BaseResponse> listUserVOByPage(@RequestBody UserQueryRequest userQueryRequest, + HttpServletRequest request) { + if (userQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + long current = userQueryRequest.getCurrent(); + long size = userQueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + Page userPage = userService.page(new Page<>(current, size), + userService.getQueryWrapper(userQueryRequest)); + Page userVOPage = new Page<>(current, size, userPage.getTotal()); + List userVO = userService.getUserVO(userPage.getRecords()); + userVOPage.setRecords(userVO); + return ResultUtils.success(userVOPage); + } + + // endregion + + /** + * 更新个人信息 + * + * @param userUpdateMyRequest + * @param request + * @return + */ + @PostMapping("/update/my") + public BaseResponse updateMyUser(@RequestBody UserUpdateMyRequest userUpdateMyRequest, + HttpServletRequest request) { + if (userUpdateMyRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User loginUser = userService.getLoginUser(request); + User user = new User(); + BeanUtils.copyProperties(userUpdateMyRequest, user); + user.setId(loginUser.getId()); + boolean result = userService.updateById(user); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(true); + } +} diff --git a/src/main/java/com/yupi/springbootinit/esdao/PostEsDao.java b/src/main/java/com/yupi/springbootinit/esdao/PostEsDao.java new file mode 100644 index 0000000..8565f53 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/esdao/PostEsDao.java @@ -0,0 +1,16 @@ +package com.yupi.springbootinit.esdao; + +import com.yupi.springbootinit.model.dto.post.PostEsDTO; +import java.util.List; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +/** + * 帖子 ES 操作 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostEsDao extends ElasticsearchRepository { + + List findByUserId(Long userId); +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/exception/BusinessException.java b/src/main/java/com/yupi/springbootinit/exception/BusinessException.java new file mode 100644 index 0000000..6e7dd1c --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/exception/BusinessException.java @@ -0,0 +1,36 @@ +package com.yupi.springbootinit.exception; + +import com.yupi.springbootinit.common.ErrorCode; + +/** + * 自定义异常类 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public class BusinessException extends RuntimeException { + + /** + * 错误码 + */ + private final int code; + + public BusinessException(int code, String message) { + super(message); + this.code = code; + } + + public BusinessException(ErrorCode errorCode) { + super(errorCode.getMessage()); + this.code = errorCode.getCode(); + } + + public BusinessException(ErrorCode errorCode, String message) { + super(message); + this.code = errorCode.getCode(); + } + + public int getCode() { + return code; + } +} diff --git a/src/main/java/com/yupi/springbootinit/exception/GlobalExceptionHandler.java b/src/main/java/com/yupi/springbootinit/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..610ca49 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/exception/GlobalExceptionHandler.java @@ -0,0 +1,31 @@ +package com.yupi.springbootinit.exception; + +import com.yupi.springbootinit.common.BaseResponse; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.common.ResultUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +/** + * 全局异常处理器 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler { + + @ExceptionHandler(BusinessException.class) + public BaseResponse businessExceptionHandler(BusinessException e) { + log.error("BusinessException", e); + return ResultUtils.error(e.getCode(), e.getMessage()); + } + + @ExceptionHandler(RuntimeException.class) + public BaseResponse runtimeExceptionHandler(RuntimeException e) { + log.error("RuntimeException", e); + return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误"); + } +} diff --git a/src/main/java/com/yupi/springbootinit/exception/ThrowUtils.java b/src/main/java/com/yupi/springbootinit/exception/ThrowUtils.java new file mode 100644 index 0000000..e25468a --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/exception/ThrowUtils.java @@ -0,0 +1,45 @@ +package com.yupi.springbootinit.exception; + +import com.yupi.springbootinit.common.ErrorCode; + +/** + * 抛异常工具类 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public class ThrowUtils { + + /** + * 条件成立则抛异常 + * + * @param condition + * @param runtimeException + */ + public static void throwIf(boolean condition, RuntimeException runtimeException) { + if (condition) { + throw runtimeException; + } + } + + /** + * 条件成立则抛异常 + * + * @param condition + * @param errorCode + */ + public static void throwIf(boolean condition, ErrorCode errorCode) { + throwIf(condition, new BusinessException(errorCode)); + } + + /** + * 条件成立则抛异常 + * + * @param condition + * @param errorCode + * @param message + */ + public static void throwIf(boolean condition, ErrorCode errorCode, String message) { + throwIf(condition, new BusinessException(errorCode, message)); + } +} diff --git a/src/main/java/com/yupi/springbootinit/generate/CodeGenerator.java b/src/main/java/com/yupi/springbootinit/generate/CodeGenerator.java new file mode 100644 index 0000000..c379215 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/generate/CodeGenerator.java @@ -0,0 +1,128 @@ +package com.yupi.springbootinit.generate; + +import cn.hutool.core.io.FileUtil; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.io.FileWriter; +import java.io.Writer; + +/** + * 代码生成器 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +public class CodeGenerator { + + /** + * 用法:修改生成参数和生成路径,注释掉不需要的生成逻辑,然后运行即可 + * + * @param args + * @throws TemplateException + * @throws IOException + */ + public static void main(String[] args) throws TemplateException, IOException { + // 指定生成参数 + String packageName = "com.yupi.springbootinit"; + String dataName = "用户评论"; + String dataKey = "userComment"; + String upperDataKey = "UserComment"; + + // 封装生成参数 + Map dataModel = new HashMap<>(); + dataModel.put("packageName", packageName); + dataModel.put("dataName", dataName); + dataModel.put("dataKey", dataKey); + dataModel.put("upperDataKey", upperDataKey); + + // 生成路径默认值 + String projectPath = System.getProperty("user.dir"); + // 参考路径,可以自己调整下面的 outputPath + String inputPath = projectPath + File.separator + "src/main/resources/templates/模板名称.java.ftl"; + String outputPath = String.format("%s/generator/包名/%s类后缀.java", projectPath, upperDataKey); + + // 1、生成 Controller + // 指定生成路径 + inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateController.java.ftl"; + outputPath = String.format("%s/generator/controller/%sController.java", projectPath, upperDataKey); + // 生成 + doGenerate(inputPath, outputPath, dataModel); + System.out.println("生成 Controller 成功,文件路径:" + outputPath); + + // 2、生成 Service 接口和实现类 + // 生成 Service 接口 + inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateService.java.ftl"; + outputPath = String.format("%s/generator/service/%sService.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + System.out.println("生成 Service 接口成功,文件路径:" + outputPath); + // 生成 Service 实现类 + inputPath = projectPath + File.separator + "src/main/resources/templates/TemplateServiceImpl.java.ftl"; + outputPath = String.format("%s/generator/service/impl/%sServiceImpl.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + System.out.println("生成 Service 实现类成功,文件路径:" + outputPath); + + // 3、生成数据模型封装类(包括 DTO 和 VO) + // 生成 DTO + inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateAddRequest.java.ftl"; + outputPath = String.format("%s/generator/model/dto/%sAddRequest.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateQueryRequest.java.ftl"; + outputPath = String.format("%s/generator/model/dto/%sQueryRequest.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateEditRequest.java.ftl"; + outputPath = String.format("%s/generator/model/dto/%sEditRequest.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateUpdateRequest.java.ftl"; + outputPath = String.format("%s/generator/model/dto/%sUpdateRequest.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + System.out.println("生成 DTO 成功,文件路径:" + outputPath); + // 生成 VO + inputPath = projectPath + File.separator + "src/main/resources/templates/model/TemplateVO.java.ftl"; + outputPath = String.format("%s/generator/model/vo/%sVO.java", projectPath, upperDataKey); + doGenerate(inputPath, outputPath, dataModel); + System.out.println("生成 VO 成功,文件路径:" + outputPath); + } + + /** + * 生成文件 + * + * @param inputPath 模板文件输入路径 + * @param outputPath 输出路径 + * @param model 数据模型 + * @throws IOException + * @throws TemplateException + */ + public static void doGenerate(String inputPath, String outputPath, Object model) throws IOException, TemplateException { + // new 出 Configuration 对象,参数为 FreeMarker 版本号 + Configuration configuration = new Configuration(Configuration.VERSION_2_3_31); + + // 指定模板文件所在的路径 + File templateDir = new File(inputPath).getParentFile(); + configuration.setDirectoryForTemplateLoading(templateDir); + + // 设置模板文件使用的字符集 + configuration.setDefaultEncoding("utf-8"); + + // 创建模板对象,加载指定模板 + String templateName = new File(inputPath).getName(); + Template template = configuration.getTemplate(templateName); + + // 文件不存在则创建文件和父目录 + if (!FileUtil.exist(outputPath)) { + FileUtil.touch(outputPath); + } + + // 生成 + Writer out = new FileWriter(outputPath); + template.process(model, out); + + // 生成文件后别忘了关闭哦 + out.close(); + } +} diff --git a/src/main/java/com/yupi/springbootinit/job/cycle/IncSyncPostToEs.java b/src/main/java/com/yupi/springbootinit/job/cycle/IncSyncPostToEs.java new file mode 100644 index 0000000..9a24326 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/job/cycle/IncSyncPostToEs.java @@ -0,0 +1,57 @@ +package com.yupi.springbootinit.job.cycle; + +import com.yupi.springbootinit.esdao.PostEsDao; +import com.yupi.springbootinit.mapper.PostMapper; +import com.yupi.springbootinit.model.dto.post.PostEsDTO; +import com.yupi.springbootinit.model.entity.Post; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import cn.hutool.core.collection.CollUtil; +import org.springframework.scheduling.annotation.Scheduled; + +/** + * 增量同步帖子到 es + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +// todo 取消注释开启任务 +//@Component +@Slf4j +public class IncSyncPostToEs { + + @Resource + private PostMapper postMapper; + + @Resource + private PostEsDao postEsDao; + + /** + * 每分钟执行一次 + */ + @Scheduled(fixedRate = 60 * 1000) + public void run() { + // 查询近 5 分钟内的数据 + Date fiveMinutesAgoDate = new Date(new Date().getTime() - 5 * 60 * 1000L); + List postList = postMapper.listPostWithDelete(fiveMinutesAgoDate); + if (CollUtil.isEmpty(postList)) { + log.info("no inc post"); + return; + } + List postEsDTOList = postList.stream() + .map(PostEsDTO::objToDto) + .collect(Collectors.toList()); + final int pageSize = 500; + int total = postEsDTOList.size(); + log.info("IncSyncPostToEs start, total {}", total); + for (int i = 0; i < total; i += pageSize) { + int end = Math.min(i + pageSize, total); + log.info("sync from {} to {}", i, end); + postEsDao.saveAll(postEsDTOList.subList(i, end)); + } + log.info("IncSyncPostToEs end, total {}", total); + } +} diff --git a/src/main/java/com/yupi/springbootinit/job/once/FullSyncPostToEs.java b/src/main/java/com/yupi/springbootinit/job/once/FullSyncPostToEs.java new file mode 100644 index 0000000..e7b8793 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/job/once/FullSyncPostToEs.java @@ -0,0 +1,48 @@ +package com.yupi.springbootinit.job.once; + +import com.yupi.springbootinit.esdao.PostEsDao; +import com.yupi.springbootinit.model.dto.post.PostEsDTO; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.service.PostService; +import java.util.List; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import cn.hutool.core.collection.CollUtil; +import org.springframework.boot.CommandLineRunner; + +/** + * 全量同步帖子到 es + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +// todo 取消注释开启任务 +//@Component +@Slf4j +public class FullSyncPostToEs implements CommandLineRunner { + + @Resource + private PostService postService; + + @Resource + private PostEsDao postEsDao; + + @Override + public void run(String... args) { + List postList = postService.list(); + if (CollUtil.isEmpty(postList)) { + return; + } + List postEsDTOList = postList.stream().map(PostEsDTO::objToDto).collect(Collectors.toList()); + final int pageSize = 500; + int total = postEsDTOList.size(); + log.info("FullSyncPostToEs start, total {}", total); + for (int i = 0; i < total; i += pageSize) { + int end = Math.min(i + pageSize, total); + log.info("sync from {} to {}", i, end); + postEsDao.saveAll(postEsDTOList.subList(i, end)); + } + log.info("FullSyncPostToEs end, total {}", total); + } +} diff --git a/src/main/java/com/yupi/springbootinit/manager/AiManager.java b/src/main/java/com/yupi/springbootinit/manager/AiManager.java new file mode 100644 index 0000000..d8dcd14 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/manager/AiManager.java @@ -0,0 +1,85 @@ +package com.yupi.springbootinit.manager; + +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.exception.BusinessException; +import io.github.briqt.spark4j.SparkClient; +import io.github.briqt.spark4j.constant.SparkApiVersion; +import io.github.briqt.spark4j.model.SparkMessage; +import io.github.briqt.spark4j.model.request.SparkRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +@Service +@Slf4j +public class AiManager { + + @Resource + private SparkClient sparkClient; + + + /** + * 向 AI 发送请求 + * + * @param isNeedTemplate 是否使用模板,进行 AI 生成; true 使用 、false 不使用 ,false 的情况是只想用 AI 不只是生成前端代码 + * @param content 内容 + * 分析需求: + * 分析网站用户的增长情况 + * 原始数据: + * 日期,用户数 + * 1号,10 + * 2号,20 + * 3号,30 + * @return AI 返回的内容 + * '【【【【' + *

+ * '【【【【' + */ + public String sendMsgToXingHuo(boolean isNeedTemplate, String content) { + List messages = new ArrayList<>(); + if (isNeedTemplate) { + // AI 生成问题的预设条件 + String predefinedInformation = "请严格按照下面的输出格式生成结果,且不得添加任何多余内容(例如无关文字、注释、代码块标记或反引号):\n" + + "\n" + + "'【【【【'" + + "{ 生成 Echarts V5 的 option 配置对象 JSON 代码,要求为合法 JSON 格式且不含任何额外内容(如注释或多余字符) } '【【【【' 结论: {\n" + + "提供对数据的详细分析结论,内容应尽可能准确、详细,不允许添加其他无关文字或注释 }\n" + + "\n" + + "示例: 输入: 分析需求: 分析网站用户增长情况,请使用柱状图展示 原始数据: 日期,用户数 1号,10 2号,20 3号,30\n" + + "\n" + + "期望输出: '【【【【' { \"title\": { \"text\": \"分析网站用户增长情况\" }, \"xAxis\": { \"type\": \"category\", \"data\": [\"1号\", \"2号\", \"3号\"] }, \"yAxis\": { \"type\": \"value\" }, \"series\": [ { \"name\": \"用户数\", \"type\": \"bar\", \"data\": [10, 20, 30] } ] } '【【【【' 从数据看,网站用户数由1号的10人增长到2号的20人,再到3号的30人,呈现出明显的上升趋势。这表明在这段时间内网站用户吸引力增强,可能与推广活动、内容更新或其他外部因素有关。"; + messages.add(SparkMessage.systemContent(predefinedInformation + "\n" + "----------------------------------")); + } + messages.add(SparkMessage.userContent(content)); + // 构造请求 + SparkRequest sparkRequest = SparkRequest.builder() + // 消息列表 + .messages(messages) + // 模型回答的tokens的最大长度,非必传,取值为[1,4096],默认为2048 + .maxTokens(2048) + // 核采样阈值。用于决定结果随机性,取值越高随机性越强即相同的问题得到的不同答案的可能性越高 非必传,取值为[0,1],默认为0.5 + .temperature(0.6) + // 指定请求版本 + .apiVersion(SparkApiVersion.V4_0) + .build(); + // 同步调用 + String responseContent = sparkClient.chatSync(sparkRequest).getContent().trim(); + if (!isNeedTemplate) { + return responseContent; + } + log.info("星火 AI 返回的结果 {}", responseContent); + AtomicInteger atomicInteger = new AtomicInteger(1); + while (responseContent.split("'【【【【'").length < 3) { + responseContent = sparkClient.chatSync(sparkRequest).getContent().trim(); + if (atomicInteger.incrementAndGet() >= 4) { + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "星火 AI 生成失败"); + } + } + return responseContent; + } +} + diff --git a/src/main/java/com/yupi/springbootinit/manager/CosManager.java b/src/main/java/com/yupi/springbootinit/manager/CosManager.java new file mode 100644 index 0000000..a556cc2 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/manager/CosManager.java @@ -0,0 +1,51 @@ +package com.yupi.springbootinit.manager; + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.model.PutObjectRequest; +import com.qcloud.cos.model.PutObjectResult; +import com.yupi.springbootinit.config.CosClientConfig; +import java.io.File; +import javax.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * Cos 对象存储操作 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Component +public class CosManager { + + @Resource + private CosClientConfig cosClientConfig; + + @Resource + private COSClient cosClient; + + /** + * 上传对象 + * + * @param key 唯一键 + * @param localFilePath 本地文件路径 + * @return + */ + public PutObjectResult putObject(String key, String localFilePath) { + PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, + new File(localFilePath)); + return cosClient.putObject(putObjectRequest); + } + + /** + * 上传对象 + * + * @param key 唯一键 + * @param file 文件 + * @return + */ + public PutObjectResult putObject(String key, File file) { + PutObjectRequest putObjectRequest = new PutObjectRequest(cosClientConfig.getBucket(), key, + file); + return cosClient.putObject(putObjectRequest); + } +} diff --git a/src/main/java/com/yupi/springbootinit/manager/RedisLimiterManager.java b/src/main/java/com/yupi/springbootinit/manager/RedisLimiterManager.java new file mode 100644 index 0000000..9c39070 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/manager/RedisLimiterManager.java @@ -0,0 +1,37 @@ +package com.yupi.springbootinit.manager; + +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.exception.BusinessException; +import org.redisson.api.RRateLimiter; +import org.redisson.api.RateIntervalUnit; +import org.redisson.api.RateType; +import org.redisson.api.RedissonClient; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * 专门提供 RedisLimiter 限流基础服务的(提供了通用的能力) + */ +@Service +public class RedisLimiterManager { + + @Resource + private RedissonClient redissonClient; + + /** + * 限流操作 + * + * @param key 区分不同的限流器,比如不同的用户 id 应该分别统计 + */ + public void doRateLimit(String key) { + // 创建一个名称为user_limiter的限流器,每秒最多访问 2 次 + RRateLimiter rateLimiter = redissonClient.getRateLimiter(key); + rateLimiter.trySetRate(RateType.OVERALL, 2, 1, RateIntervalUnit.SECONDS); + // 每当一个操作来了后,请求一个令牌 + boolean canOp = rateLimiter.tryAcquire(1); + if (!canOp) { + throw new BusinessException(ErrorCode.TOO_MANY_REQUEST); + } + } +} diff --git a/src/main/java/com/yupi/springbootinit/manager/ThreadPoolExecutorConfig.java b/src/main/java/com/yupi/springbootinit/manager/ThreadPoolExecutorConfig.java new file mode 100644 index 0000000..662e329 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/manager/ThreadPoolExecutorConfig.java @@ -0,0 +1,45 @@ +package com.yupi.springbootinit.manager; + +import org.apache.poi.ss.formula.functions.T; +import org.jetbrains.annotations.NotNull; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +@Configuration +public class ThreadPoolExecutorConfig { + + @Bean + public ThreadPoolExecutor threadPoolExecutor() { + ThreadFactory threadFactory = new ThreadFactory() { + private int count = 1; + + @Override + public Thread newThread(@NotNull Runnable r) { + Thread thread = new Thread(r); + thread.setName("线程" + count); + count++; + return thread; + } + }; + +// corePoolSize(核心线程数=>正式员工数):正常情况下,我们的系统应该同时工作的线程数(随时就绪的状态) +// maximumPoolSize(最大线程数=>哪怕任务再多,你也最多招这些人):极限情况下,我们的线程池最多有多少个线程? +// keepAliveTime(空闲线程存活时间):非核心线程在没有任务的情况下,过多久要删除(理解为开除临时工),从而释放无用的线程资源。 +// TimeUnit unit(空闲线程存活时间的单位):分钟、秒 +// workQueue(工作队列):用于存放给线程执行的任务,存在一个队列的长度(一定要设置,不要说队列长度无限,因为也会占用资源) +// threadFactory(线程工厂):控制每个线程的生成、线程的属性(比如线程名) + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( + 2, + 4, + 100, + TimeUnit.SECONDS, + new ArrayBlockingQueue<>(4), + threadFactory); + return threadPoolExecutor; + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/mapper/ChartMapper.java b/src/main/java/com/yupi/springbootinit/mapper/ChartMapper.java new file mode 100644 index 0000000..89b467e --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/mapper/ChartMapper.java @@ -0,0 +1,18 @@ +package com.yupi.springbootinit.mapper; + +import com.yupi.springbootinit.model.entity.Chart; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author HeSun +* @description 针对表【chart(图表信息表)】的数据库操作Mapper +* @createDate 2025-02-20 20:52:40 +* @Entity com.yupi.springbootinit.model.entity.Chart +*/ +public interface ChartMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/mapper/PostFavourMapper.java b/src/main/java/com/yupi/springbootinit/mapper/PostFavourMapper.java new file mode 100644 index 0000000..c57cf5e --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/mapper/PostFavourMapper.java @@ -0,0 +1,35 @@ +package com.yupi.springbootinit.mapper; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.PostFavour; +import org.apache.ibatis.annotations.Param; + +/** + * 帖子收藏数据库操作 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostFavourMapper extends BaseMapper { + + /** + * 分页查询收藏帖子列表 + * + * @param page + * @param queryWrapper + * @param favourUserId + * @return + */ + Page listFavourPostByPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper, + long favourUserId); + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/mapper/PostMapper.java b/src/main/java/com/yupi/springbootinit/mapper/PostMapper.java new file mode 100644 index 0000000..2975b84 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/mapper/PostMapper.java @@ -0,0 +1,25 @@ +package com.yupi.springbootinit.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yupi.springbootinit.model.entity.Post; +import java.util.Date; +import java.util.List; + +/** + * 帖子数据库操作 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostMapper extends BaseMapper { + + /** + * 查询帖子列表(包括已被删除的数据) + */ + List listPostWithDelete(Date minUpdateTime); + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/mapper/PostThumbMapper.java b/src/main/java/com/yupi/springbootinit/mapper/PostThumbMapper.java new file mode 100644 index 0000000..fe39c82 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/mapper/PostThumbMapper.java @@ -0,0 +1,18 @@ +package com.yupi.springbootinit.mapper; + +import com.yupi.springbootinit.model.entity.PostThumb; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** + * 帖子点赞数据库操作 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostThumbMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/mapper/UserMapper.java b/src/main/java/com/yupi/springbootinit/mapper/UserMapper.java new file mode 100644 index 0000000..247bf3b --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/mapper/UserMapper.java @@ -0,0 +1,18 @@ +package com.yupi.springbootinit.mapper; + +import com.yupi.springbootinit.model.entity.User; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author HeSun +* @description 针对表【user(用户)】的数据库操作Mapper +* @createDate 2025-02-20 20:52:40 +* @Entity com.yupi.springbootinit.model.entity.User +*/ +public interface UserMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartAddRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartAddRequest.java new file mode 100644 index 0000000..420bbfb --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartAddRequest.java @@ -0,0 +1,39 @@ +package com.yupi.springbootinit.model.dto.chart; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 创建请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class ChartAddRequest implements Serializable { + + /** + * 名称 + */ + private String name; + + /** + * 分析目标 + */ + private String goal; + + /** + * 图表数据 + */ + private String chartData; + + /** + * 图表类型 + */ + private String chartType; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartEditRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartEditRequest.java new file mode 100644 index 0000000..2f8568c --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartEditRequest.java @@ -0,0 +1,47 @@ +package com.yupi.springbootinit.model.dto.chart; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 编辑请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class ChartEditRequest implements Serializable { + + /** + * 名称 + */ + private String name; + + /** + * id + */ + private Long id; + + /** + * 分析目标 + */ + private String goal; + + /** + * 图表数据 + */ + private String chartData; + + /** + * 图表类型 + */ + private String chartType; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartQueryRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartQueryRequest.java new file mode 100644 index 0000000..0c36cc6 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartQueryRequest.java @@ -0,0 +1,42 @@ +package com.yupi.springbootinit.model.dto.chart; + +import com.yupi.springbootinit.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; + +/** + * 查询请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ChartQueryRequest extends PageRequest implements Serializable { + + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 分析目标 + */ + private String goal; + + /** + * 图表类型 + */ + private String chartType; + + /** + * 用户id + */ + private Long userId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartUpdateRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartUpdateRequest.java new file mode 100644 index 0000000..bac3ac7 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/chart/ChartUpdateRequest.java @@ -0,0 +1,78 @@ +package com.yupi.springbootinit.model.dto.chart; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 更新请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class ChartUpdateRequest implements Serializable { + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 分析目标 + */ + private String goal; + + /** + * 图表数据 + */ + private String chartData; + + /** + * 图表类型 + */ + private String chartType; + + /** + * 生成的图表数据 + */ + private String genChart; + + /** + * 生成的分析结论 + */ + private String genResult; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Integer isDelete; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/chart/GenChartByAiRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/chart/GenChartByAiRequest.java new file mode 100644 index 0000000..b9b8cb2 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/chart/GenChartByAiRequest.java @@ -0,0 +1,32 @@ +package com.yupi.springbootinit.model.dto.chart; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 文件上传请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class GenChartByAiRequest implements Serializable { + + /** + * 名称 + */ + private String name; + + /** + * 分析目标 + */ + private String goal; + + /** + * 图标类型 + */ + private String chartType; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/file/UploadFileRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/file/UploadFileRequest.java new file mode 100644 index 0000000..09654ec --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/file/UploadFileRequest.java @@ -0,0 +1,21 @@ +package com.yupi.springbootinit.model.dto.file; + +import java.io.Serializable; +import lombok.Data; + +/** + * 文件上传请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UploadFileRequest implements Serializable { + + /** + * 业务 + */ + private String biz; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/post/PostAddRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/post/PostAddRequest.java new file mode 100644 index 0000000..45ac49c --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/post/PostAddRequest.java @@ -0,0 +1,32 @@ +package com.yupi.springbootinit.model.dto.post; + +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * 创建请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PostAddRequest implements Serializable { + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/post/PostEditRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/post/PostEditRequest.java new file mode 100644 index 0000000..40c3888 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/post/PostEditRequest.java @@ -0,0 +1,37 @@ +package com.yupi.springbootinit.model.dto.post; + +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * 编辑请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PostEditRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/post/PostEsDTO.java b/src/main/java/com/yupi/springbootinit/model/dto/post/PostEsDTO.java new file mode 100644 index 0000000..aa7ae46 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/post/PostEsDTO.java @@ -0,0 +1,123 @@ +package com.yupi.springbootinit.model.dto.post; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.json.JSONUtil; +import com.yupi.springbootinit.model.entity.Post; +import lombok.Data; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 帖子 ES 包装类 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + **/ +// todo 取消注释开启 ES(须先配置 ES) +//@Document(indexName = "post") +@Data +public class PostEsDTO implements Serializable { + + private static final String DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + + /** + * id + */ + @Id + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + /** + * 点赞数 + */ + private Integer thumbNum; + + /** + * 收藏数 + */ + private Integer favourNum; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + @Field(index = false, store = true, type = FieldType.Date, format = {}, pattern = DATE_TIME_PATTERN) + private Date createTime; + + /** + * 更新时间 + */ + @Field(index = false, store = true, type = FieldType.Date, format = {}, pattern = DATE_TIME_PATTERN) + private Date updateTime; + + /** + * 是否删除 + */ + private Integer isDelete; + + private static final long serialVersionUID = 1L; + + /** + * 对象转包装类 + * + * @param post + * @return + */ + public static PostEsDTO objToDto(Post post) { + if (post == null) { + return null; + } + PostEsDTO postEsDTO = new PostEsDTO(); + BeanUtils.copyProperties(post, postEsDTO); + String tagsStr = post.getTags(); + if (StringUtils.isNotBlank(tagsStr)) { + postEsDTO.setTags(JSONUtil.toList(tagsStr, String.class)); + } + return postEsDTO; + } + + /** + * 包装类转对象 + * + * @param postEsDTO + * @return + */ + public static Post dtoToObj(PostEsDTO postEsDTO) { + if (postEsDTO == null) { + return null; + } + Post post = new Post(); + BeanUtils.copyProperties(postEsDTO, post); + List tagList = postEsDTO.getTags(); + if (CollUtil.isNotEmpty(tagList)) { + post.setTags(JSONUtil.toJsonStr(tagList)); + } + return post; + } +} diff --git a/src/main/java/com/yupi/springbootinit/model/dto/post/PostQueryRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/post/PostQueryRequest.java new file mode 100644 index 0000000..c9f160a --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/post/PostQueryRequest.java @@ -0,0 +1,65 @@ +package com.yupi.springbootinit.model.dto.post; + +import com.yupi.springbootinit.common.PageRequest; +import java.io.Serializable; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 查询请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class PostQueryRequest extends PageRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * id + */ + private Long notId; + + /** + * 搜索词 + */ + private String searchText; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + /** + * 至少有一个标签 + */ + private List orTags; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 收藏用户 id + */ + private Long favourUserId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/post/PostUpdateRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/post/PostUpdateRequest.java new file mode 100644 index 0000000..c90bc70 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/post/PostUpdateRequest.java @@ -0,0 +1,37 @@ +package com.yupi.springbootinit.model.dto.post; + +import java.io.Serializable; +import java.util.List; +import lombok.Data; + +/** + * 更新请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PostUpdateRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourAddRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourAddRequest.java new file mode 100644 index 0000000..1b8cc27 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourAddRequest.java @@ -0,0 +1,21 @@ +package com.yupi.springbootinit.model.dto.postfavour; + +import java.io.Serializable; +import lombok.Data; + +/** + * 帖子收藏 / 取消收藏请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PostFavourAddRequest implements Serializable { + + /** + * 帖子 id + */ + private Long postId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourQueryRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourQueryRequest.java new file mode 100644 index 0000000..e8bf989 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/postfavour/PostFavourQueryRequest.java @@ -0,0 +1,30 @@ +package com.yupi.springbootinit.model.dto.postfavour; + +import com.yupi.springbootinit.common.PageRequest; +import com.yupi.springbootinit.model.dto.post.PostQueryRequest; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 帖子收藏查询请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PostFavourQueryRequest extends PageRequest implements Serializable { + + /** + * 帖子查询请求 + */ + private PostQueryRequest postQueryRequest; + + /** + * 用户 id + */ + private Long userId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/postthumb/PostThumbAddRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/postthumb/PostThumbAddRequest.java new file mode 100644 index 0000000..e6209e7 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/postthumb/PostThumbAddRequest.java @@ -0,0 +1,21 @@ +package com.yupi.springbootinit.model.dto.postthumb; + +import java.io.Serializable; +import lombok.Data; + +/** + * 帖子点赞请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PostThumbAddRequest implements Serializable { + + /** + * 帖子 id + */ + private Long postId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/UserAddRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/user/UserAddRequest.java new file mode 100644 index 0000000..7c56337 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/user/UserAddRequest.java @@ -0,0 +1,36 @@ +package com.yupi.springbootinit.model.dto.user; + +import java.io.Serializable; +import lombok.Data; + +/** + * 用户创建请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UserAddRequest implements Serializable { + + /** + * 用户昵称 + */ + private String userName; + + /** + * 账号 + */ + private String userAccount; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 用户角色: user, admin + */ + private String userRole; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/UserLoginRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/user/UserLoginRequest.java new file mode 100644 index 0000000..85c241e --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/user/UserLoginRequest.java @@ -0,0 +1,20 @@ +package com.yupi.springbootinit.model.dto.user; + +import java.io.Serializable; +import lombok.Data; + +/** + * 用户登录请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UserLoginRequest implements Serializable { + + private static final long serialVersionUID = 3191241716373120793L; + + private String userAccount; + + private String userPassword; +} diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/UserQueryRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/user/UserQueryRequest.java new file mode 100644 index 0000000..7b0e3d4 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/user/UserQueryRequest.java @@ -0,0 +1,48 @@ +package com.yupi.springbootinit.model.dto.user; + +import com.yupi.springbootinit.common.PageRequest; +import java.io.Serializable; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 用户查询请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class UserQueryRequest extends PageRequest implements Serializable { + /** + * id + */ + private Long id; + + /** + * 开放平台id + */ + private String unionId; + + /** + * 公众号openId + */ + private String mpOpenId; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 简介 + */ + private String userProfile; + + /** + * 用户角色:user/admin/ban + */ + private String userRole; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/UserRegisterRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/user/UserRegisterRequest.java new file mode 100644 index 0000000..ded70ed --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/user/UserRegisterRequest.java @@ -0,0 +1,22 @@ +package com.yupi.springbootinit.model.dto.user; + +import java.io.Serializable; +import lombok.Data; + +/** + * 用户注册请求体 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UserRegisterRequest implements Serializable { + + private static final long serialVersionUID = 3191241716373120793L; + + private String userAccount; + + private String userPassword; + + private String checkPassword; +} diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateMyRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateMyRequest.java new file mode 100644 index 0000000..f07f55a --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateMyRequest.java @@ -0,0 +1,31 @@ +package com.yupi.springbootinit.model.dto.user; + +import java.io.Serializable; +import lombok.Data; + +/** + * 用户更新个人信息请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UserUpdateMyRequest implements Serializable { + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 简介 + */ + private String userProfile; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateRequest.java b/src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateRequest.java new file mode 100644 index 0000000..6536de5 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/dto/user/UserUpdateRequest.java @@ -0,0 +1,40 @@ +package com.yupi.springbootinit.model.dto.user; + +import java.io.Serializable; +import lombok.Data; + +/** + * 用户更新请求 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UserUpdateRequest implements Serializable { + /** + * id + */ + private Long id; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 简介 + */ + private String userProfile; + + /** + * 用户角色:user/admin/ban + */ + private String userRole; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/entity/Chart.java b/src/main/java/com/yupi/springbootinit/model/entity/Chart.java new file mode 100644 index 0000000..02da097 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/entity/Chart.java @@ -0,0 +1,81 @@ +package com.yupi.springbootinit.model.entity; + +import com.baomidou.mybatisplus.annotation.*; + +import java.util.Date; +import lombok.Data; + +/** + * 图表信息表 + * @TableName chart + */ +@TableName(value ="chart") +@Data +public class Chart { + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + /** + * 名称 + */ + private String name; + + /** + * 分析目标 + */ + private String goal; + + /** + * 图表数据 + */ + private String chartData; + + /** + * 图表类型 + */ + private String chartType; + + /** + * 生成的图表数据 + */ + private String genChart; + + /** + * 生成的分析结论 + */ + private String genResult; + + /** + * 任务状态 + */ + private String status; + + /** + * 执行信息 + */ + private String execMessage; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Integer isDelete; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/entity/Post.java b/src/main/java/com/yupi/springbootinit/model/entity/Post.java new file mode 100644 index 0000000..3c0e301 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/entity/Post.java @@ -0,0 +1,76 @@ +package com.yupi.springbootinit.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 帖子 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@TableName(value = "post") +@Data +public class Post implements Serializable { + + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 json + */ + private String tags; + + /** + * 点赞数 + */ + private Integer thumbNum; + + /** + * 收藏数 + */ + private Integer favourNum; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Integer isDelete; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/entity/PostFavour.java b/src/main/java/com/yupi/springbootinit/model/entity/PostFavour.java new file mode 100644 index 0000000..7626ec5 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/entity/PostFavour.java @@ -0,0 +1,49 @@ +package com.yupi.springbootinit.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 帖子收藏 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + **/ +@TableName(value = "post_favour") +@Data +public class PostFavour implements Serializable { + + /** + * id + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 帖子 id + */ + private Long postId; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/entity/PostThumb.java b/src/main/java/com/yupi/springbootinit/model/entity/PostThumb.java new file mode 100644 index 0000000..c22f119 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/entity/PostThumb.java @@ -0,0 +1,49 @@ +package com.yupi.springbootinit.model.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 帖子点赞 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@TableName(value = "post_thumb") +@Data +public class PostThumb implements Serializable { + + /** + * id + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 帖子 id + */ + private Long postId; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/entity/User.java b/src/main/java/com/yupi/springbootinit/model/entity/User.java new file mode 100644 index 0000000..95ea135 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/entity/User.java @@ -0,0 +1,61 @@ +package com.yupi.springbootinit.model.entity; + +import com.baomidou.mybatisplus.annotation.*; + +import java.util.Date; +import lombok.Data; + +/** + * 用户 + * @TableName user + */ +@TableName(value ="user") +@Data +public class User { + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + /** + * 账号 + */ + private String userAccount; + + /** + * 密码 + */ + private String userPassword; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 用户角色:user/admin + */ + private String userRole; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 是否删除 + */ + @TableLogic + private Integer isDelete; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/enums/FileUploadBizEnum.java b/src/main/java/com/yupi/springbootinit/model/enums/FileUploadBizEnum.java new file mode 100644 index 0000000..da246eb --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/enums/FileUploadBizEnum.java @@ -0,0 +1,61 @@ +package com.yupi.springbootinit.model.enums; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.ObjectUtils; + +/** + * 文件上传业务类型枚举 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public enum FileUploadBizEnum { + + USER_AVATAR("用户头像", "user_avatar"); + + private final String text; + + private final String value; + + FileUploadBizEnum(String text, String value) { + this.text = text; + this.value = value; + } + + /** + * 获取值列表 + * + * @return + */ + public static List getValues() { + return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList()); + } + + /** + * 根据 value 获取枚举 + * + * @param value + * @return + */ + public static FileUploadBizEnum getEnumByValue(String value) { + if (ObjectUtils.isEmpty(value)) { + return null; + } + for (FileUploadBizEnum anEnum : FileUploadBizEnum.values()) { + if (anEnum.value.equals(value)) { + return anEnum; + } + } + return null; + } + + public String getValue() { + return value; + } + + public String getText() { + return text; + } +} diff --git a/src/main/java/com/yupi/springbootinit/model/enums/UserRoleEnum.java b/src/main/java/com/yupi/springbootinit/model/enums/UserRoleEnum.java new file mode 100644 index 0000000..3aeb3cc --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/enums/UserRoleEnum.java @@ -0,0 +1,63 @@ +package com.yupi.springbootinit.model.enums; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.ObjectUtils; + +/** + * 用户角色枚举 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public enum UserRoleEnum { + + USER("用户", "user"), + ADMIN("管理员", "admin"), + BAN("被封号", "ban"); + + private final String text; + + private final String value; + + UserRoleEnum(String text, String value) { + this.text = text; + this.value = value; + } + + /** + * 获取值列表 + * + * @return + */ + public static List getValues() { + return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList()); + } + + /** + * 根据 value 获取枚举 + * + * @param value + * @return + */ + public static UserRoleEnum getEnumByValue(String value) { + if (ObjectUtils.isEmpty(value)) { + return null; + } + for (UserRoleEnum anEnum : UserRoleEnum.values()) { + if (anEnum.value.equals(value)) { + return anEnum; + } + } + return null; + } + + public String getValue() { + return value; + } + + public String getText() { + return text; + } +} diff --git a/src/main/java/com/yupi/springbootinit/model/vo/BiResponse.java b/src/main/java/com/yupi/springbootinit/model/vo/BiResponse.java new file mode 100644 index 0000000..4cdd211 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/vo/BiResponse.java @@ -0,0 +1,17 @@ +package com.yupi.springbootinit.model.vo; + +import lombok.Data; + +/** + * Bi的返回结果 + */ + +@Data +public class BiResponse { + + private String genChart; + + private String genResult; + + private Long chartId; +} diff --git a/src/main/java/com/yupi/springbootinit/model/vo/LoginUserVO.java b/src/main/java/com/yupi/springbootinit/model/vo/LoginUserVO.java new file mode 100644 index 0000000..47ebf8f --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/vo/LoginUserVO.java @@ -0,0 +1,52 @@ +package com.yupi.springbootinit.model.vo; + +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 已登录用户视图(脱敏) + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + **/ +@Data +public class LoginUserVO implements Serializable { + + /** + * 用户 id + */ + private Long id; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 用户简介 + */ + private String userProfile; + + /** + * 用户角色:user/admin/ban + */ + private String userRole; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/model/vo/PostVO.java b/src/main/java/com/yupi/springbootinit/model/vo/PostVO.java new file mode 100644 index 0000000..92aa7fd --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/vo/PostVO.java @@ -0,0 +1,112 @@ +package com.yupi.springbootinit.model.vo; + +import cn.hutool.json.JSONUtil; +import com.yupi.springbootinit.model.entity.Post; +import java.io.Serializable; +import java.util.Date; +import java.util.List; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +/** + * 帖子视图 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class PostVO implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 点赞数 + */ + private Integer thumbNum; + + /** + * 收藏数 + */ + private Integer favourNum; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 标签列表 + */ + private List tagList; + + /** + * 创建人信息 + */ + private UserVO user; + + /** + * 是否已点赞 + */ + private Boolean hasThumb; + + /** + * 是否已收藏 + */ + private Boolean hasFavour; + + /** + * 包装类转对象 + * + * @param postVO + * @return + */ + public static Post voToObj(PostVO postVO) { + if (postVO == null) { + return null; + } + Post post = new Post(); + BeanUtils.copyProperties(postVO, post); + List tagList = postVO.getTagList(); + post.setTags(JSONUtil.toJsonStr(tagList)); + return post; + } + + /** + * 对象转包装类 + * + * @param post + * @return + */ + public static PostVO objToVo(Post post) { + if (post == null) { + return null; + } + PostVO postVO = new PostVO(); + BeanUtils.copyProperties(post, postVO); + postVO.setTagList(JSONUtil.toList(post.getTags(), String.class)); + return postVO; + } +} diff --git a/src/main/java/com/yupi/springbootinit/model/vo/UserVO.java b/src/main/java/com/yupi/springbootinit/model/vo/UserVO.java new file mode 100644 index 0000000..536b1f4 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/model/vo/UserVO.java @@ -0,0 +1,47 @@ +package com.yupi.springbootinit.model.vo; + +import java.io.Serializable; +import java.util.Date; +import lombok.Data; + +/** + * 用户视图(脱敏) + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Data +public class UserVO implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 用户昵称 + */ + private String userName; + + /** + * 用户头像 + */ + private String userAvatar; + + /** + * 用户简介 + */ + private String userProfile; + + /** + * 用户角色:user/admin/ban + */ + private String userRole; + + /** + * 创建时间 + */ + private Date createTime; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/service/ChartService.java b/src/main/java/com/yupi/springbootinit/service/ChartService.java new file mode 100644 index 0000000..4531e1d --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/ChartService.java @@ -0,0 +1,13 @@ +package com.yupi.springbootinit.service; + +import com.yupi.springbootinit.model.entity.Chart; +import com.baomidou.mybatisplus.extension.service.IService; + +/** +* @author HeSun +* @description 针对表【chart(图表信息表)】的数据库操作Service +* @createDate 2025-02-20 20:52:40 +*/ +public interface ChartService extends IService { + +} diff --git a/src/main/java/com/yupi/springbootinit/service/PostFavourService.java b/src/main/java/com/yupi/springbootinit/service/PostFavourService.java new file mode 100644 index 0000000..1e29151 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/PostFavourService.java @@ -0,0 +1,47 @@ +package com.yupi.springbootinit.service; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.PostFavour; +import com.yupi.springbootinit.model.entity.User; + +/** + * 帖子收藏服务 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostFavourService extends IService { + + /** + * 帖子收藏 + * + * @param postId + * @param loginUser + * @return + */ + int doPostFavour(long postId, User loginUser); + + /** + * 分页获取用户收藏的帖子列表 + * + * @param page + * @param queryWrapper + * @param favourUserId + * @return + */ + Page listFavourPostByPage(IPage page, Wrapper queryWrapper, + long favourUserId); + + /** + * 帖子收藏(内部服务) + * + * @param userId + * @param postId + * @return + */ + int doPostFavourInner(long userId, long postId); +} diff --git a/src/main/java/com/yupi/springbootinit/service/PostService.java b/src/main/java/com/yupi/springbootinit/service/PostService.java new file mode 100644 index 0000000..d938f0b --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/PostService.java @@ -0,0 +1,60 @@ +package com.yupi.springbootinit.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yupi.springbootinit.model.dto.post.PostQueryRequest; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.vo.PostVO; +import javax.servlet.http.HttpServletRequest; + +/** + * 帖子服务 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostService extends IService { + + /** + * 校验 + * + * @param post + * @param add + */ + void validPost(Post post, boolean add); + + /** + * 获取查询条件 + * + * @param postQueryRequest + * @return + */ + QueryWrapper getQueryWrapper(PostQueryRequest postQueryRequest); + + /** + * 从 ES 查询 + * + * @param postQueryRequest + * @return + */ + Page searchFromEs(PostQueryRequest postQueryRequest); + + /** + * 获取帖子封装 + * + * @param post + * @param request + * @return + */ + PostVO getPostVO(Post post, HttpServletRequest request); + + /** + * 分页获取帖子封装 + * + * @param postPage + * @param request + * @return + */ + Page getPostVOPage(Page postPage, HttpServletRequest request); +} diff --git a/src/main/java/com/yupi/springbootinit/service/PostThumbService.java b/src/main/java/com/yupi/springbootinit/service/PostThumbService.java new file mode 100644 index 0000000..db731f9 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/PostThumbService.java @@ -0,0 +1,32 @@ +package com.yupi.springbootinit.service; + +import com.yupi.springbootinit.model.entity.PostThumb; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yupi.springbootinit.model.entity.User; + +/** + * 帖子点赞服务 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface PostThumbService extends IService { + + /** + * 点赞 + * + * @param postId + * @param loginUser + * @return + */ + int doPostThumb(long postId, User loginUser); + + /** + * 帖子点赞(内部服务) + * + * @param userId + * @param postId + * @return + */ + int doPostThumbInner(long userId, long postId); +} diff --git a/src/main/java/com/yupi/springbootinit/service/UserService.java b/src/main/java/com/yupi/springbootinit/service/UserService.java new file mode 100644 index 0000000..5035bf6 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/UserService.java @@ -0,0 +1,112 @@ +package com.yupi.springbootinit.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.IService; +import com.yupi.springbootinit.model.dto.user.UserQueryRequest; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.vo.LoginUserVO; +import com.yupi.springbootinit.model.vo.UserVO; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; + +/** + * 用户服务 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public interface UserService extends IService { + + /** + * 用户注册 + * + * @param userAccount 用户账户 + * @param userPassword 用户密码 + * @param checkPassword 校验密码 + * @return 新用户 id + */ + long userRegister(String userAccount, String userPassword, String checkPassword); + + /** + * 用户登录 + * + * @param userAccount 用户账户 + * @param userPassword 用户密码 + * @param request + * @return 脱敏后的用户信息 + */ + LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request); + + /** + * 获取当前登录用户 + * + * @param request + * @return + */ + User getLoginUser(HttpServletRequest request); + + /** + * 获取当前登录用户(允许未登录) + * + * @param request + * @return + */ + User getLoginUserPermitNull(HttpServletRequest request); + + /** + * 是否为管理员 + * + * @param request + * @return + */ + boolean isAdmin(HttpServletRequest request); + + /** + * 是否为管理员 + * + * @param user + * @return + */ + boolean isAdmin(User user); + + /** + * 用户注销 + * + * @param request + * @return + */ + boolean userLogout(HttpServletRequest request); + + /** + * 获取脱敏的已登录用户信息 + * + * @return + */ + LoginUserVO getLoginUserVO(User user); + + /** + * 获取脱敏的用户信息 + * + * @param user + * @return + */ + UserVO getUserVO(User user); + + /** + * 获取脱敏的用户信息 + * + * @param userList + * @return + */ + List getUserVO(List userList); + + /** + * 获取查询条件 + * + * @param userQueryRequest + * @return + */ + QueryWrapper getQueryWrapper(UserQueryRequest userQueryRequest); + +} diff --git a/src/main/java/com/yupi/springbootinit/service/impl/ChartServiceImpl.java b/src/main/java/com/yupi/springbootinit/service/impl/ChartServiceImpl.java new file mode 100644 index 0000000..2cb39d7 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/impl/ChartServiceImpl.java @@ -0,0 +1,22 @@ +package com.yupi.springbootinit.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yupi.springbootinit.model.entity.Chart; +import com.yupi.springbootinit.service.ChartService; +import com.yupi.springbootinit.mapper.ChartMapper; +import org.springframework.stereotype.Service; + +/** +* @author HeSun +* @description 针对表【chart(图表信息表)】的数据库操作Service实现 +* @createDate 2025-02-20 20:52:40 +*/ +@Service +public class ChartServiceImpl extends ServiceImpl + implements ChartService{ + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/service/impl/PostFavourServiceImpl.java b/src/main/java/com/yupi/springbootinit/service/impl/PostFavourServiceImpl.java new file mode 100644 index 0000000..08abe11 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/impl/PostFavourServiceImpl.java @@ -0,0 +1,116 @@ +package com.yupi.springbootinit.service.impl; + +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.mapper.PostFavourMapper; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.PostFavour; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.service.PostFavourService; +import com.yupi.springbootinit.service.PostService; +import javax.annotation.Resource; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 帖子收藏服务实现 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Service +public class PostFavourServiceImpl extends ServiceImpl + implements PostFavourService { + + @Resource + private PostService postService; + + /** + * 帖子收藏 + * + * @param postId + * @param loginUser + * @return + */ + @Override + public int doPostFavour(long postId, User loginUser) { + // 判断是否存在 + Post post = postService.getById(postId); + if (post == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + // 是否已帖子收藏 + long userId = loginUser.getId(); + // 每个用户串行帖子收藏 + // 锁必须要包裹住事务方法 + PostFavourService postFavourService = (PostFavourService) AopContext.currentProxy(); + synchronized (String.valueOf(userId).intern()) { + return postFavourService.doPostFavourInner(userId, postId); + } + } + + @Override + public Page listFavourPostByPage(IPage page, Wrapper queryWrapper, long favourUserId) { + if (favourUserId <= 0) { + return new Page<>(); + } + return baseMapper.listFavourPostByPage(page, queryWrapper, favourUserId); + } + + /** + * 封装了事务的方法 + * + * @param userId + * @param postId + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int doPostFavourInner(long userId, long postId) { + PostFavour postFavour = new PostFavour(); + postFavour.setUserId(userId); + postFavour.setPostId(postId); + QueryWrapper postFavourQueryWrapper = new QueryWrapper<>(postFavour); + PostFavour oldPostFavour = this.getOne(postFavourQueryWrapper); + boolean result; + // 已收藏 + if (oldPostFavour != null) { + result = this.remove(postFavourQueryWrapper); + if (result) { + // 帖子收藏数 - 1 + result = postService.update() + .eq("id", postId) + .gt("favourNum", 0) + .setSql("favourNum = favourNum - 1") + .update(); + return result ? -1 : 0; + } else { + throw new BusinessException(ErrorCode.SYSTEM_ERROR); + } + } else { + // 未帖子收藏 + result = this.save(postFavour); + if (result) { + // 帖子收藏数 + 1 + result = postService.update() + .eq("id", postId) + .setSql("favourNum = favourNum + 1") + .update(); + return result ? 1 : 0; + } else { + throw new BusinessException(ErrorCode.SYSTEM_ERROR); + } + } + } + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/service/impl/PostServiceImpl.java b/src/main/java/com/yupi/springbootinit/service/impl/PostServiceImpl.java new file mode 100644 index 0000000..791c8c4 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/impl/PostServiceImpl.java @@ -0,0 +1,312 @@ +package com.yupi.springbootinit.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.constant.CommonConstant; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.exception.ThrowUtils; +import com.yupi.springbootinit.mapper.PostFavourMapper; +import com.yupi.springbootinit.mapper.PostMapper; +import com.yupi.springbootinit.mapper.PostThumbMapper; +import com.yupi.springbootinit.model.dto.post.PostEsDTO; +import com.yupi.springbootinit.model.dto.post.PostQueryRequest; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.PostFavour; +import com.yupi.springbootinit.model.entity.PostThumb; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.vo.PostVO; +import com.yupi.springbootinit.model.vo.UserVO; +import com.yupi.springbootinit.service.PostService; +import com.yupi.springbootinit.service.UserService; +import com.yupi.springbootinit.utils.SqlUtils; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import cn.hutool.core.collection.CollUtil; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.search.sort.SortBuilder; +import org.elasticsearch.search.sort.SortBuilders; +import org.elasticsearch.search.sort.SortOrder; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; +import org.springframework.data.elasticsearch.core.SearchHit; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.stereotype.Service; + +/** + * 帖子服务实现 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Service +@Slf4j +public class PostServiceImpl extends ServiceImpl implements PostService { + + @Resource + private UserService userService; + + @Resource + private PostThumbMapper postThumbMapper; + + @Resource + private PostFavourMapper postFavourMapper; + + @Resource + private ElasticsearchRestTemplate elasticsearchRestTemplate; + + @Override + public void validPost(Post post, boolean add) { + if (post == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + String title = post.getTitle(); + String content = post.getContent(); + String tags = post.getTags(); + // 创建时,参数不能为空 + if (add) { + ThrowUtils.throwIf(StringUtils.isAnyBlank(title, content, tags), ErrorCode.PARAMS_ERROR); + } + // 有参数则校验 + if (StringUtils.isNotBlank(title) && title.length() > 80) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "标题过长"); + } + if (StringUtils.isNotBlank(content) && content.length() > 8192) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "内容过长"); + } + } + + /** + * 获取查询包装类 + * + * @param postQueryRequest + * @return + */ + @Override + public QueryWrapper getQueryWrapper(PostQueryRequest postQueryRequest) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + if (postQueryRequest == null) { + return queryWrapper; + } + String searchText = postQueryRequest.getSearchText(); + String sortField = postQueryRequest.getSortField(); + String sortOrder = postQueryRequest.getSortOrder(); + Long id = postQueryRequest.getId(); + String title = postQueryRequest.getTitle(); + String content = postQueryRequest.getContent(); + List tagList = postQueryRequest.getTags(); + Long userId = postQueryRequest.getUserId(); + Long notId = postQueryRequest.getNotId(); + // 拼接查询条件 + if (StringUtils.isNotBlank(searchText)) { + queryWrapper.and(qw -> qw.like("title", searchText).or().like("content", searchText)); + } + queryWrapper.like(StringUtils.isNotBlank(title), "title", title); + queryWrapper.like(StringUtils.isNotBlank(content), "content", content); + if (CollUtil.isNotEmpty(tagList)) { + for (String tag : tagList) { + queryWrapper.like("tags", "\"" + tag + "\""); + } + } + queryWrapper.ne(ObjectUtils.isNotEmpty(notId), "id", notId); + queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id); + queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId); + queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), + sortField); + return queryWrapper; + } + + @Override + public Page searchFromEs(PostQueryRequest postQueryRequest) { + Long id = postQueryRequest.getId(); + Long notId = postQueryRequest.getNotId(); + String searchText = postQueryRequest.getSearchText(); + String title = postQueryRequest.getTitle(); + String content = postQueryRequest.getContent(); + List tagList = postQueryRequest.getTags(); + List orTagList = postQueryRequest.getOrTags(); + Long userId = postQueryRequest.getUserId(); + // es 起始页为 0 + long current = postQueryRequest.getCurrent() - 1; + long pageSize = postQueryRequest.getPageSize(); + String sortField = postQueryRequest.getSortField(); + String sortOrder = postQueryRequest.getSortOrder(); + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + // 过滤 + boolQueryBuilder.filter(QueryBuilders.termQuery("isDelete", 0)); + if (id != null) { + boolQueryBuilder.filter(QueryBuilders.termQuery("id", id)); + } + if (notId != null) { + boolQueryBuilder.mustNot(QueryBuilders.termQuery("id", notId)); + } + if (userId != null) { + boolQueryBuilder.filter(QueryBuilders.termQuery("userId", userId)); + } + // 必须包含所有标签 + if (CollUtil.isNotEmpty(tagList)) { + for (String tag : tagList) { + boolQueryBuilder.filter(QueryBuilders.termQuery("tags", tag)); + } + } + // 包含任何一个标签即可 + if (CollUtil.isNotEmpty(orTagList)) { + BoolQueryBuilder orTagBoolQueryBuilder = QueryBuilders.boolQuery(); + for (String tag : orTagList) { + orTagBoolQueryBuilder.should(QueryBuilders.termQuery("tags", tag)); + } + orTagBoolQueryBuilder.minimumShouldMatch(1); + boolQueryBuilder.filter(orTagBoolQueryBuilder); + } + // 按关键词检索 + if (StringUtils.isNotBlank(searchText)) { + boolQueryBuilder.should(QueryBuilders.matchQuery("title", searchText)); + boolQueryBuilder.should(QueryBuilders.matchQuery("description", searchText)); + boolQueryBuilder.should(QueryBuilders.matchQuery("content", searchText)); + boolQueryBuilder.minimumShouldMatch(1); + } + // 按标题检索 + if (StringUtils.isNotBlank(title)) { + boolQueryBuilder.should(QueryBuilders.matchQuery("title", title)); + boolQueryBuilder.minimumShouldMatch(1); + } + // 按内容检索 + if (StringUtils.isNotBlank(content)) { + boolQueryBuilder.should(QueryBuilders.matchQuery("content", content)); + boolQueryBuilder.minimumShouldMatch(1); + } + // 排序 + SortBuilder sortBuilder = SortBuilders.scoreSort(); + if (StringUtils.isNotBlank(sortField)) { + sortBuilder = SortBuilders.fieldSort(sortField); + sortBuilder.order(CommonConstant.SORT_ORDER_ASC.equals(sortOrder) ? SortOrder.ASC : SortOrder.DESC); + } + // 分页 + PageRequest pageRequest = PageRequest.of((int) current, (int) pageSize); + // 构造查询 + NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder) + .withPageable(pageRequest).withSorts(sortBuilder).build(); + SearchHits searchHits = elasticsearchRestTemplate.search(searchQuery, PostEsDTO.class); + Page page = new Page<>(); + page.setTotal(searchHits.getTotalHits()); + List resourceList = new ArrayList<>(); + // 查出结果后,从 db 获取最新动态数据(比如点赞数) + if (searchHits.hasSearchHits()) { + List> searchHitList = searchHits.getSearchHits(); + List postIdList = searchHitList.stream().map(searchHit -> searchHit.getContent().getId()) + .collect(Collectors.toList()); + List postList = baseMapper.selectBatchIds(postIdList); + if (postList != null) { + Map> idPostMap = postList.stream().collect(Collectors.groupingBy(Post::getId)); + postIdList.forEach(postId -> { + if (idPostMap.containsKey(postId)) { + resourceList.add(idPostMap.get(postId).get(0)); + } else { + // 从 es 清空 db 已物理删除的数据 + String delete = elasticsearchRestTemplate.delete(String.valueOf(postId), PostEsDTO.class); + log.info("delete post {}", delete); + } + }); + } + } + page.setRecords(resourceList); + return page; + } + + @Override + public PostVO getPostVO(Post post, HttpServletRequest request) { + PostVO postVO = PostVO.objToVo(post); + long postId = post.getId(); + // 1. 关联查询用户信息 + Long userId = post.getUserId(); + User user = null; + if (userId != null && userId > 0) { + user = userService.getById(userId); + } + UserVO userVO = userService.getUserVO(user); + postVO.setUser(userVO); + // 2. 已登录,获取用户点赞、收藏状态 + User loginUser = userService.getLoginUserPermitNull(request); + if (loginUser != null) { + // 获取点赞 + QueryWrapper postThumbQueryWrapper = new QueryWrapper<>(); + postThumbQueryWrapper.in("postId", postId); + postThumbQueryWrapper.eq("userId", loginUser.getId()); + PostThumb postThumb = postThumbMapper.selectOne(postThumbQueryWrapper); + postVO.setHasThumb(postThumb != null); + // 获取收藏 + QueryWrapper postFavourQueryWrapper = new QueryWrapper<>(); + postFavourQueryWrapper.in("postId", postId); + postFavourQueryWrapper.eq("userId", loginUser.getId()); + PostFavour postFavour = postFavourMapper.selectOne(postFavourQueryWrapper); + postVO.setHasFavour(postFavour != null); + } + return postVO; + } + + @Override + public Page getPostVOPage(Page postPage, HttpServletRequest request) { + List postList = postPage.getRecords(); + Page postVOPage = new Page<>(postPage.getCurrent(), postPage.getSize(), postPage.getTotal()); + if (CollUtil.isEmpty(postList)) { + return postVOPage; + } + // 1. 关联查询用户信息 + Set userIdSet = postList.stream().map(Post::getUserId).collect(Collectors.toSet()); + Map> userIdUserListMap = userService.listByIds(userIdSet).stream() + .collect(Collectors.groupingBy(User::getId)); + // 2. 已登录,获取用户点赞、收藏状态 + Map postIdHasThumbMap = new HashMap<>(); + Map postIdHasFavourMap = new HashMap<>(); + User loginUser = userService.getLoginUserPermitNull(request); + if (loginUser != null) { + Set postIdSet = postList.stream().map(Post::getId).collect(Collectors.toSet()); + loginUser = userService.getLoginUser(request); + // 获取点赞 + QueryWrapper postThumbQueryWrapper = new QueryWrapper<>(); + postThumbQueryWrapper.in("postId", postIdSet); + postThumbQueryWrapper.eq("userId", loginUser.getId()); + List postPostThumbList = postThumbMapper.selectList(postThumbQueryWrapper); + postPostThumbList.forEach(postPostThumb -> postIdHasThumbMap.put(postPostThumb.getPostId(), true)); + // 获取收藏 + QueryWrapper postFavourQueryWrapper = new QueryWrapper<>(); + postFavourQueryWrapper.in("postId", postIdSet); + postFavourQueryWrapper.eq("userId", loginUser.getId()); + List postFavourList = postFavourMapper.selectList(postFavourQueryWrapper); + postFavourList.forEach(postFavour -> postIdHasFavourMap.put(postFavour.getPostId(), true)); + } + // 填充信息 + List postVOList = postList.stream().map(post -> { + PostVO postVO = PostVO.objToVo(post); + Long userId = post.getUserId(); + User user = null; + if (userIdUserListMap.containsKey(userId)) { + user = userIdUserListMap.get(userId).get(0); + } + postVO.setUser(userService.getUserVO(user)); + postVO.setHasThumb(postIdHasThumbMap.getOrDefault(post.getId(), false)); + postVO.setHasFavour(postIdHasFavourMap.getOrDefault(post.getId(), false)); + return postVO; + }).collect(Collectors.toList()); + postVOPage.setRecords(postVOList); + return postVOPage; + } + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/service/impl/PostThumbServiceImpl.java b/src/main/java/com/yupi/springbootinit/service/impl/PostThumbServiceImpl.java new file mode 100644 index 0000000..a0b3c06 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/impl/PostThumbServiceImpl.java @@ -0,0 +1,105 @@ +package com.yupi.springbootinit.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.mapper.PostThumbMapper; +import com.yupi.springbootinit.model.entity.Post; +import com.yupi.springbootinit.model.entity.PostThumb; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.service.PostService; +import com.yupi.springbootinit.service.PostThumbService; +import javax.annotation.Resource; +import org.springframework.aop.framework.AopContext; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 帖子点赞服务实现 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Service +public class PostThumbServiceImpl extends ServiceImpl + implements PostThumbService { + + @Resource + private PostService postService; + + /** + * 点赞 + * + * @param postId + * @param loginUser + * @return + */ + @Override + public int doPostThumb(long postId, User loginUser) { + // 判断实体是否存在,根据类别获取实体 + Post post = postService.getById(postId); + if (post == null) { + throw new BusinessException(ErrorCode.NOT_FOUND_ERROR); + } + // 是否已点赞 + long userId = loginUser.getId(); + // 每个用户串行点赞 + // 锁必须要包裹住事务方法 + PostThumbService postThumbService = (PostThumbService) AopContext.currentProxy(); + synchronized (String.valueOf(userId).intern()) { + return postThumbService.doPostThumbInner(userId, postId); + } + } + + /** + * 封装了事务的方法 + * + * @param userId + * @param postId + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int doPostThumbInner(long userId, long postId) { + PostThumb postThumb = new PostThumb(); + postThumb.setUserId(userId); + postThumb.setPostId(postId); + QueryWrapper thumbQueryWrapper = new QueryWrapper<>(postThumb); + PostThumb oldPostThumb = this.getOne(thumbQueryWrapper); + boolean result; + // 已点赞 + if (oldPostThumb != null) { + result = this.remove(thumbQueryWrapper); + if (result) { + // 点赞数 - 1 + result = postService.update() + .eq("id", postId) + .gt("thumbNum", 0) + .setSql("thumbNum = thumbNum - 1") + .update(); + return result ? -1 : 0; + } else { + throw new BusinessException(ErrorCode.SYSTEM_ERROR); + } + } else { + // 未点赞 + result = this.save(postThumb); + if (result) { + // 点赞数 + 1 + result = postService.update() + .eq("id", postId) + .setSql("thumbNum = thumbNum + 1") + .update(); + return result ? 1 : 0; + } else { + throw new BusinessException(ErrorCode.SYSTEM_ERROR); + } + } + } + +} + + + + diff --git a/src/main/java/com/yupi/springbootinit/service/impl/UserServiceImpl.java b/src/main/java/com/yupi/springbootinit/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..7bdc599 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/service/impl/UserServiceImpl.java @@ -0,0 +1,240 @@ +package com.yupi.springbootinit.service.impl; + +import static com.yupi.springbootinit.constant.UserConstant.USER_LOGIN_STATE; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.yupi.springbootinit.common.ErrorCode; +import com.yupi.springbootinit.constant.CommonConstant; +import com.yupi.springbootinit.exception.BusinessException; +import com.yupi.springbootinit.mapper.UserMapper; +import com.yupi.springbootinit.model.dto.user.UserQueryRequest; +import com.yupi.springbootinit.model.entity.User; +import com.yupi.springbootinit.model.enums.UserRoleEnum; +import com.yupi.springbootinit.model.vo.LoginUserVO; +import com.yupi.springbootinit.model.vo.UserVO; +import com.yupi.springbootinit.service.UserService; +import com.yupi.springbootinit.utils.SqlUtils; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import javax.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.bean.WxOAuth2UserInfo; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.DigestUtils; + +/** + * 用户服务实现 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Service +@Slf4j +public class UserServiceImpl extends ServiceImpl implements UserService { + + /** + * 盐值,混淆密码 + */ + public static final String SALT = "yupi"; + + @Override + public long userRegister(String userAccount, String userPassword, String checkPassword) { + // 1. 校验 + if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"); + } + if (userAccount.length() < 4) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短"); + } + if (userPassword.length() < 8 || checkPassword.length() < 8) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短"); + } + // 密码和校验密码相同 + if (!userPassword.equals(checkPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致"); + } + synchronized (userAccount.intern()) { + // 账户不能重复 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("userAccount", userAccount); + long count = this.baseMapper.selectCount(queryWrapper); + if (count > 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复"); + } + // 2. 加密 + String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes()); + // 3. 插入数据 + User user = new User(); + user.setUserAccount(userAccount); + user.setUserPassword(encryptPassword); + boolean saveResult = this.save(user); + if (!saveResult) { + throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败,数据库错误"); + } + return user.getId(); + } + } + + @Override + public LoginUserVO userLogin(String userAccount, String userPassword, HttpServletRequest request) { + // 1. 校验 + if (StringUtils.isAnyBlank(userAccount, userPassword)) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"); + } + if (userAccount.length() < 4) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号错误"); + } + if (userPassword.length() < 8) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码错误"); + } + // 2. 加密 + String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes()); + // 查询用户是否存在 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("userAccount", userAccount); + queryWrapper.eq("userPassword", encryptPassword); + User user = this.baseMapper.selectOne(queryWrapper); + // 用户不存在 + if (user == null) { + log.info("user login failed, userAccount cannot match userPassword"); + throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误"); + } + // 3. 记录用户的登录态 + request.getSession().setAttribute(USER_LOGIN_STATE, user); + return this.getLoginUserVO(user); + } + + /** + * 获取当前登录用户 + * + * @param request + * @return + */ + @Override + public User getLoginUser(HttpServletRequest request) { + // 先判断是否已登录 + Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE); + User currentUser = (User) userObj; + if (currentUser == null || currentUser.getId() == null) { + throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); + } + // 从数据库查询(追求性能的话可以注释,直接走缓存) + long userId = currentUser.getId(); + currentUser = this.getById(userId); + if (currentUser == null) { + throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR); + } + return currentUser; + } + + /** + * 获取当前登录用户(允许未登录) + * + * @param request + * @return + */ + @Override + public User getLoginUserPermitNull(HttpServletRequest request) { + // 先判断是否已登录 + Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE); + User currentUser = (User) userObj; + if (currentUser == null || currentUser.getId() == null) { + return null; + } + // 从数据库查询(追求性能的话可以注释,直接走缓存) + long userId = currentUser.getId(); + return this.getById(userId); + } + + /** + * 是否为管理员 + * + * @param request + * @return + */ + @Override + public boolean isAdmin(HttpServletRequest request) { + // 仅管理员可查询 + Object userObj = request.getSession().getAttribute(USER_LOGIN_STATE); + User user = (User) userObj; + return isAdmin(user); + } + + @Override + public boolean isAdmin(User user) { + return user != null && UserRoleEnum.ADMIN.getValue().equals(user.getUserRole()); + } + + /** + * 用户注销 + * + * @param request + */ + @Override + public boolean userLogout(HttpServletRequest request) { + if (request.getSession().getAttribute(USER_LOGIN_STATE) == null) { + throw new BusinessException(ErrorCode.OPERATION_ERROR, "未登录"); + } + // 移除登录态 + request.getSession().removeAttribute(USER_LOGIN_STATE); + return true; + } + + @Override + public LoginUserVO getLoginUserVO(User user) { + if (user == null) { + return null; + } + LoginUserVO loginUserVO = new LoginUserVO(); + BeanUtils.copyProperties(user, loginUserVO); + return loginUserVO; + } + + @Override + public UserVO getUserVO(User user) { + if (user == null) { + return null; + } + UserVO userVO = new UserVO(); + BeanUtils.copyProperties(user, userVO); + return userVO; + } + + @Override + public List getUserVO(List userList) { + if (CollUtil.isEmpty(userList)) { + return new ArrayList<>(); + } + return userList.stream().map(this::getUserVO).collect(Collectors.toList()); + } + + @Override + public QueryWrapper getQueryWrapper(UserQueryRequest userQueryRequest) { + if (userQueryRequest == null) { + throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空"); + } + Long id = userQueryRequest.getId(); + String unionId = userQueryRequest.getUnionId(); + String mpOpenId = userQueryRequest.getMpOpenId(); + String userName = userQueryRequest.getUserName(); + String userProfile = userQueryRequest.getUserProfile(); + String userRole = userQueryRequest.getUserRole(); + String sortField = userQueryRequest.getSortField(); + String sortOrder = userQueryRequest.getSortOrder(); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(id != null, "id", id); + queryWrapper.eq(StringUtils.isNotBlank(unionId), "unionId", unionId); + queryWrapper.eq(StringUtils.isNotBlank(mpOpenId), "mpOpenId", mpOpenId); + queryWrapper.eq(StringUtils.isNotBlank(userRole), "userRole", userRole); + queryWrapper.like(StringUtils.isNotBlank(userProfile), "userProfile", userProfile); + queryWrapper.like(StringUtils.isNotBlank(userName), "userName", userName); + queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), + sortField); + return queryWrapper; + } +} diff --git a/src/main/java/com/yupi/springbootinit/utils/ExcelUtils.java b/src/main/java/com/yupi/springbootinit/utils/ExcelUtils.java new file mode 100644 index 0000000..f2c1ec3 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/utils/ExcelUtils.java @@ -0,0 +1,71 @@ +package com.yupi.springbootinit.utils; +import cn.hutool.core.collection.CollUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.support.ExcelTypeEnum; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.ResourceUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Excel 相关工具类 + */ +@Slf4j +public class ExcelUtils { + + /** + * excel 转 csv + * + * @param multipartFile + * @return + */ + public static String excelToCsv(MultipartFile multipartFile) { +// File file = null; +// try { +// file = ResourceUtils.getFile("classpath:网站数据.xlsx"); +// } catch (FileNotFoundException e) { +// e.printStackTrace(); +// } + // 读取数据 + List> list = null; + try { + list = EasyExcel.read(multipartFile.getInputStream()) + .excelType(ExcelTypeEnum.XLSX) + .sheet() + .headRowNumber(0) + .doReadSync(); + } catch (IOException e) { + log.error("表格处理错误", e); + } + if (CollUtil.isEmpty(list)) { + return ""; + } + // 转换为 csv + StringBuilder stringBuilder = new StringBuilder(); + // 读取表头 + LinkedHashMap headerMap = (LinkedHashMap) list.get(0); + List headerList = headerMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); + stringBuilder.append(StringUtils.join(headerList, ",")).append("\n"); + // 读取数据 + for (int i = 1; i < list.size(); i++) { + LinkedHashMap dataMap = (LinkedHashMap) list.get(i); + List dataList = dataMap.values().stream().filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); + stringBuilder.append(StringUtils.join(dataList, ",")).append("\n"); + } + return stringBuilder.toString(); + } + + public static void main(String[] args) { + excelToCsv(null); + } +} + diff --git a/src/main/java/com/yupi/springbootinit/utils/NetUtils.java b/src/main/java/com/yupi/springbootinit/utils/NetUtils.java new file mode 100644 index 0000000..88069fb --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/utils/NetUtils.java @@ -0,0 +1,55 @@ +package com.yupi.springbootinit.utils; + +import java.net.InetAddress; +import javax.servlet.http.HttpServletRequest; + +/** + * 网络工具类 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public class NetUtils { + + /** + * 获取客户端 IP 地址 + * + * @param request + * @return + */ + public static String getIpAddress(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + if (ip.equals("127.0.0.1")) { + // 根据网卡取本机配置的 IP + InetAddress inet = null; + try { + inet = InetAddress.getLocalHost(); + } catch (Exception e) { + e.printStackTrace(); + } + if (inet != null) { + ip = inet.getHostAddress(); + } + } + } + // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 + if (ip != null && ip.length() > 15) { + if (ip.indexOf(",") > 0) { + ip = ip.substring(0, ip.indexOf(",")); + } + } + if (ip == null) { + return "127.0.0.1"; + } + return ip; + } + +} diff --git a/src/main/java/com/yupi/springbootinit/utils/SpringContextUtils.java b/src/main/java/com/yupi/springbootinit/utils/SpringContextUtils.java new file mode 100644 index 0000000..60001f6 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/utils/SpringContextUtils.java @@ -0,0 +1,57 @@ +package com.yupi.springbootinit.utils; + +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring 上下文获取工具 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@Component +public class SpringContextUtils implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(@NotNull ApplicationContext applicationContext) throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + /** + * 通过名称获取 Bean + * + * @param beanName + * @return + */ + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } + + /** + * 通过 class 获取 Bean + * + * @param beanClass + * @param + * @return + */ + public static T getBean(Class beanClass) { + return applicationContext.getBean(beanClass); + } + + /** + * 通过名称和类型获取 Bean + * + * @param beanName + * @param beanClass + * @param + * @return + */ + public static T getBean(String beanName, Class beanClass) { + return applicationContext.getBean(beanName, beanClass); + } +} \ No newline at end of file diff --git a/src/main/java/com/yupi/springbootinit/utils/SqlUtils.java b/src/main/java/com/yupi/springbootinit/utils/SqlUtils.java new file mode 100644 index 0000000..1efeaa4 --- /dev/null +++ b/src/main/java/com/yupi/springbootinit/utils/SqlUtils.java @@ -0,0 +1,25 @@ +package com.yupi.springbootinit.utils; + +import org.apache.commons.lang3.StringUtils; + +/** + * SQL 工具 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +public class SqlUtils { + + /** + * 校验排序字段是否合法(防止 SQL 注入) + * + * @param sortField + * @return + */ + public static boolean validSortField(String sortField) { + if (StringUtils.isBlank(sortField)) { + return false; + } + return !StringUtils.containsAny(sortField, "=", "(", ")", " "); + } +} diff --git a/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/src/main/resources/META-INF/additional-spring-configuration-metadata.json new file mode 100644 index 0000000..670aab3 --- /dev/null +++ b/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -0,0 +1,52 @@ +{ + "properties": [ + { + "name": "cos.client.accessKey", + "type": "java.lang.String", + "description": "Description for cos.client.accessKey." + }, + { + "name": "cos.client.secretKey", + "type": "java.lang.String", + "description": "Description for cos.client.secretKey." + }, + { + "name": "cos.client.region", + "type": "java.lang.String", + "description": "Description for cos.client.region." + }, + { + "name": "cos.client.bucket", + "type": "java.lang.String", + "description": "Description for cos.client.bucket." + }, + { + "name": "wx.open.appId", + "type": "java.lang.String", + "description": "Description for wx.open.appId." + }, + { + "name": "wx.open.appSecret", + "type": "java.lang.String", + "description": "Description for wx.open.appSecret." + }, + + + + { + "name": "xun-fei.client.appId", + "type": "java.lang.String" + }, + { + "name": "xun-fei.client.apiSecret", + "type": "java.lang.String" + }, + { + "name": "xun-fei.client.apiKey", + "type": "java.lang.String" + } + + + + ] +} diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml new file mode 100644 index 0000000..b085964 --- /dev/null +++ b/src/main/resources/application-prod.yml @@ -0,0 +1,37 @@ +# 线上配置文件 +# @author 程序员鱼皮 +# @from 编程导航知识星球 +server: + port: 8101 +spring: + # 数据库配置 + # todo 需替换配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/my_db + username: root + password: 123456 + # Redis 配置 + # todo 需替换配置 + redis: + database: 1 + host: localhost + port: 6379 + timeout: 5000 + password: 123456 + # Elasticsearch 配置 + # todo 需替换配置 + elasticsearch: + uris: http://localhost:9200 + username: root + password: 123456 +mybatis-plus: + configuration: + # 生产环境关闭日志 + log-impl: '' +# 接口文档配置 +knife4j: + basic: + enable: true + username: root + password: 123456 diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml new file mode 100644 index 0000000..c0fcf94 --- /dev/null +++ b/src/main/resources/application-test.yml @@ -0,0 +1,27 @@ +# 测试配置文件 +# @author 程序员鱼皮 +# @from 编程导航知识星球 +server: + port: 8101 +spring: + # 数据库配置 + # todo 需替换配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/my_db + username: root + password: 123456 + # Redis 配置 + # todo 需替换配置 + redis: + database: 1 + host: localhost + port: 6379 + timeout: 5000 + password: 123456 + # Elasticsearch 配置 + # todo 需替换配置 + elasticsearch: + uris: http://localhost:9200 + username: root + password: 123456 \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..5993780 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,112 @@ +# 公共配置文件 +# @author 程序员鱼皮 +# @from 编程导航知识星球 +spring: + application: + name: hebi-backend + # 默认 dev 环境 + profiles: + active: dev + # 支持 swagger3 + mvc: + pathmatch: + matching-strategy: ant_path_matcher + # session 配置 + session: + # todo 取消注释开启分布式 session(须先配置 Redis) + # store-type: redis + # 30 天过期 + timeout: 2592000 + # 数据库配置 + # todo 需替换配置 + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/hebi + username: root + password: 123456 + # Redis 配置 + # todo 需替换配置,然后取消注释 + redis: + database: 1 + host: localhost + port: 6379 + timeout: 5000 +# password: 123456 + + # Elasticsearch 配置 + # todo 需替换配置,然后取消注释 +# elasticsearch: +# uris: http://localhost:9200 +# username: root +# password: 123456 + # 文件上传 + servlet: + multipart: + # 大小限制 + max-file-size: 10MB +server: + address: 0.0.0.0 + port: 8101 + servlet: + context-path: /api + # cookie 30 天过期 + session: + cookie: + max-age: 2592000 +mybatis-plus: + configuration: + map-underscore-to-camel-case: false + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl + global-config: + db-config: + logic-delete-field: isDelete # 全局逻辑删除的实体字段名 + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) +# 微信相关 +wx: + # 微信公众平台 + # todo 需替换配置 + mp: + token: xxx + aesKey: xxx + appId: xxx + secret: xxx + config-storage: + http-client-type: HttpClient + key-prefix: wx + redis: + host: 127.0.0.1 + port: 6379 + type: Memory + # 微信开放平台 + # todo 需替换配置 + open: + appId: xxx + appSecret: xxx +# 对象存储 +# todo 需替换配置 +cos: + client: + accessKey: xxx + secretKey: xxx + region: xxx + bucket: xxx +# 接口文档配置 +knife4j: + enable: true + openapi: + title: "接口文档" + version: 1.0 + group: + default: + api-rule: package + api-rule-resources: + - com.yupi.springbootinit.controller + + +## 讯飞 AI 配置 +xun-fei: + client: + appId: 6b30952a + apiSecret: Mzk2YjZhN2ZmODgwNGI2YmUzNDQ0Yjk1 + apiKey: faa9c010048c45e709ebf4585aa03e41 diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt new file mode 100644 index 0000000..1881b7f --- /dev/null +++ b/src/main/resources/banner.txt @@ -0,0 +1,5 @@ + ___ _ _ + / __| _ _ _ _ | || | ___ + \__ \ | +| | | ' \ | __ | / -_) + |___/ \_,_| |_||_| |_||_| \___| +_|"""""|_|"""""|_|"""""|_|"""""|_|"""""| \ No newline at end of file diff --git a/src/main/resources/mapper/ChartMapper.xml b/src/main/resources/mapper/ChartMapper.xml new file mode 100644 index 0000000..228ed32 --- /dev/null +++ b/src/main/resources/mapper/ChartMapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + id,`name`,goal,chartData,chartType,genChart,genResult, + userId,createTime,updateTime,isDelete + + diff --git a/src/main/resources/mapper/PostFavourMapper.xml b/src/main/resources/mapper/PostFavourMapper.xml new file mode 100644 index 0000000..b7985c9 --- /dev/null +++ b/src/main/resources/mapper/PostFavourMapper.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + id,postId,userId, + createTime,updateTime + + + + diff --git a/src/main/resources/mapper/PostMapper.xml b/src/main/resources/mapper/PostMapper.xml new file mode 100644 index 0000000..d57b866 --- /dev/null +++ b/src/main/resources/mapper/PostMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + id,title,content,tags, + thumbNum,favourNum,userId, + createTime,updateTime,isDelete + + + + diff --git a/src/main/resources/mapper/PostThumbMapper.xml b/src/main/resources/mapper/PostThumbMapper.xml new file mode 100644 index 0000000..07909ab --- /dev/null +++ b/src/main/resources/mapper/PostThumbMapper.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + id,postId, + userId,createTime,updateTime + + diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..09df560 --- /dev/null +++ b/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + id,userAccount,userPassword,userName,userAvatar,userRole, + createTime,updateTime,isDelete + + diff --git a/src/main/resources/templates/TemplateController.java.ftl b/src/main/resources/templates/TemplateController.java.ftl new file mode 100644 index 0000000..e5714b5 --- /dev/null +++ b/src/main/resources/templates/TemplateController.java.ftl @@ -0,0 +1,239 @@ +package ${packageName}.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import ${packageName}.annotation.AuthCheck; +import ${packageName}.common.BaseResponse; +import ${packageName}.common.DeleteRequest; +import ${packageName}.common.ErrorCode; +import ${packageName}.common.ResultUtils; +import ${packageName}.constant.UserConstant; +import ${packageName}.exception.BusinessException; +import ${packageName}.exception.ThrowUtils; +import ${packageName}.model.dto.${dataKey}.${upperDataKey}AddRequest; +import ${packageName}.model.dto.${dataKey}.${upperDataKey}EditRequest; +import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest; +import ${packageName}.model.dto.${dataKey}.${upperDataKey}UpdateRequest; +import ${packageName}.model.entity.${upperDataKey}; +import ${packageName}.model.entity.User; +import ${packageName}.model.vo.${upperDataKey}VO; +import ${packageName}.service.${upperDataKey}Service; +import ${packageName}.service.UserService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +/** + * ${dataName}接口 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@RestController +@RequestMapping("/${dataKey}") +@Slf4j +public class ${upperDataKey}Controller { + + @Resource + private ${upperDataKey}Service ${dataKey}Service; + + @Resource + private UserService userService; + + // region 增删改查 + + /** + * 创建${dataName} + * + * @param ${dataKey}AddRequest + * @param request + * @return + */ + @PostMapping("/add") + public BaseResponse add${upperDataKey}(@RequestBody ${upperDataKey}AddRequest ${dataKey}AddRequest, HttpServletRequest request) { + ThrowUtils.throwIf(${dataKey}AddRequest == null, ErrorCode.PARAMS_ERROR); + // todo 在此处将实体类和 DTO 进行转换 + ${upperDataKey} ${dataKey} = new ${upperDataKey}(); + BeanUtils.copyProperties(${dataKey}AddRequest, ${dataKey}); + // 数据校验 + ${dataKey}Service.valid${upperDataKey}(${dataKey}, true); + // todo 填充默认值 + User loginUser = userService.getLoginUser(request); + ${dataKey}.setUserId(loginUser.getId()); + // 写入数据库 + boolean result = ${dataKey}Service.save(${dataKey}); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + // 返回新写入的数据 id + long new${upperDataKey}Id = ${dataKey}.getId(); + return ResultUtils.success(new${upperDataKey}Id); + } + + /** + * 删除${dataName} + * + * @param deleteRequest + * @param request + * @return + */ + @PostMapping("/delete") + public BaseResponse delete${upperDataKey}(@RequestBody DeleteRequest deleteRequest, HttpServletRequest request) { + if (deleteRequest == null || deleteRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + User user = userService.getLoginUser(request); + long id = deleteRequest.getId(); + // 判断是否存在 + ${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id); + ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR); + // 仅本人或管理员可删除 + if (!old${upperDataKey}.getUserId().equals(user.getId()) && !userService.isAdmin(request)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + // 操作数据库 + boolean result = ${dataKey}Service.removeById(id); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(true); + } + + /** + * 更新${dataName}(仅管理员可用) + * + * @param ${dataKey}UpdateRequest + * @return + */ + @PostMapping("/update") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse update${upperDataKey}(@RequestBody ${upperDataKey}UpdateRequest ${dataKey}UpdateRequest) { + if (${dataKey}UpdateRequest == null || ${dataKey}UpdateRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + // todo 在此处将实体类和 DTO 进行转换 + ${upperDataKey} ${dataKey} = new ${upperDataKey}(); + BeanUtils.copyProperties(${dataKey}UpdateRequest, ${dataKey}); + // 数据校验 + ${dataKey}Service.valid${upperDataKey}(${dataKey}, false); + // 判断是否存在 + long id = ${dataKey}UpdateRequest.getId(); + ${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id); + ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR); + // 操作数据库 + boolean result = ${dataKey}Service.updateById(${dataKey}); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(true); + } + + /** + * 根据 id 获取${dataName}(封装类) + * + * @param id + * @return + */ + @GetMapping("/get/vo") + public BaseResponse<${upperDataKey}VO> get${upperDataKey}VOById(long id, HttpServletRequest request) { + ThrowUtils.throwIf(id <= 0, ErrorCode.PARAMS_ERROR); + // 查询数据库 + ${upperDataKey} ${dataKey} = ${dataKey}Service.getById(id); + ThrowUtils.throwIf(${dataKey} == null, ErrorCode.NOT_FOUND_ERROR); + // 获取封装类 + return ResultUtils.success(${dataKey}Service.get${upperDataKey}VO(${dataKey}, request)); + } + + /** + * 分页获取${dataName}列表(仅管理员可用) + * + * @param ${dataKey}QueryRequest + * @return + */ + @PostMapping("/list/page") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public BaseResponse> list${upperDataKey}ByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest) { + long current = ${dataKey}QueryRequest.getCurrent(); + long size = ${dataKey}QueryRequest.getPageSize(); + // 查询数据库 + Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size), + ${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest)); + return ResultUtils.success(${dataKey}Page); + } + + /** + * 分页获取${dataName}列表(封装类) + * + * @param ${dataKey}QueryRequest + * @param request + * @return + */ + @PostMapping("/list/page/vo") + public BaseResponse> list${upperDataKey}VOByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest, + HttpServletRequest request) { + long current = ${dataKey}QueryRequest.getCurrent(); + long size = ${dataKey}QueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + // 查询数据库 + Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size), + ${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest)); + // 获取封装类 + return ResultUtils.success(${dataKey}Service.get${upperDataKey}VOPage(${dataKey}Page, request)); + } + + /** + * 分页获取当前登录用户创建的${dataName}列表 + * + * @param ${dataKey}QueryRequest + * @param request + * @return + */ + @PostMapping("/my/list/page/vo") + public BaseResponse> listMy${upperDataKey}VOByPage(@RequestBody ${upperDataKey}QueryRequest ${dataKey}QueryRequest, + HttpServletRequest request) { + ThrowUtils.throwIf(${dataKey}QueryRequest == null, ErrorCode.PARAMS_ERROR); + // 补充查询条件,只查询当前登录用户的数据 + User loginUser = userService.getLoginUser(request); + ${dataKey}QueryRequest.setUserId(loginUser.getId()); + long current = ${dataKey}QueryRequest.getCurrent(); + long size = ${dataKey}QueryRequest.getPageSize(); + // 限制爬虫 + ThrowUtils.throwIf(size > 20, ErrorCode.PARAMS_ERROR); + // 查询数据库 + Page<${upperDataKey}> ${dataKey}Page = ${dataKey}Service.page(new Page<>(current, size), + ${dataKey}Service.getQueryWrapper(${dataKey}QueryRequest)); + // 获取封装类 + return ResultUtils.success(${dataKey}Service.get${upperDataKey}VOPage(${dataKey}Page, request)); + } + + /** + * 编辑${dataName}(给用户使用) + * + * @param ${dataKey}EditRequest + * @param request + * @return + */ + @PostMapping("/edit") + public BaseResponse edit${upperDataKey}(@RequestBody ${upperDataKey}EditRequest ${dataKey}EditRequest, HttpServletRequest request) { + if (${dataKey}EditRequest == null || ${dataKey}EditRequest.getId() <= 0) { + throw new BusinessException(ErrorCode.PARAMS_ERROR); + } + // todo 在此处将实体类和 DTO 进行转换 + ${upperDataKey} ${dataKey} = new ${upperDataKey}(); + BeanUtils.copyProperties(${dataKey}EditRequest, ${dataKey}); + // 数据校验 + ${dataKey}Service.valid${upperDataKey}(${dataKey}, false); + User loginUser = userService.getLoginUser(request); + // 判断是否存在 + long id = ${dataKey}EditRequest.getId(); + ${upperDataKey} old${upperDataKey} = ${dataKey}Service.getById(id); + ThrowUtils.throwIf(old${upperDataKey} == null, ErrorCode.NOT_FOUND_ERROR); + // 仅本人或管理员可编辑 + if (!old${upperDataKey}.getUserId().equals(loginUser.getId()) && !userService.isAdmin(loginUser)) { + throw new BusinessException(ErrorCode.NO_AUTH_ERROR); + } + // 操作数据库 + boolean result = ${dataKey}Service.updateById(${dataKey}); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR); + return ResultUtils.success(true); + } + + // endregion +} diff --git a/src/main/resources/templates/TemplateService.java.ftl b/src/main/resources/templates/TemplateService.java.ftl new file mode 100644 index 0000000..a688488 --- /dev/null +++ b/src/main/resources/templates/TemplateService.java.ftl @@ -0,0 +1,53 @@ +package ${packageName}.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest; +import ${packageName}.model.entity.${upperDataKey}; +import ${packageName}.model.vo.${upperDataKey}VO; + +import javax.servlet.http.HttpServletRequest; + +/** + * ${dataName}服务 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +public interface ${upperDataKey}Service extends IService<${upperDataKey}> { + + /** + * 校验数据 + * + * @param ${dataKey} + * @param add 对创建的数据进行校验 + */ + void valid${upperDataKey}(${upperDataKey} ${dataKey}, boolean add); + + /** + * 获取查询条件 + * + * @param ${dataKey}QueryRequest + * @return + */ + QueryWrapper<${upperDataKey}> getQueryWrapper(${upperDataKey}QueryRequest ${dataKey}QueryRequest); + + /** + * 获取${dataName}封装 + * + * @param ${dataKey} + * @param request + * @return + */ + ${upperDataKey}VO get${upperDataKey}VO(${upperDataKey} ${dataKey}, HttpServletRequest request); + + /** + * 分页获取${dataName}封装 + * + * @param ${dataKey}Page + * @param request + * @return + */ + Page<${upperDataKey}VO> get${upperDataKey}VOPage(Page<${upperDataKey}> ${dataKey}Page, HttpServletRequest request); +} diff --git a/src/main/resources/templates/TemplateServiceImpl.java.ftl b/src/main/resources/templates/TemplateServiceImpl.java.ftl new file mode 100644 index 0000000..3921f10 --- /dev/null +++ b/src/main/resources/templates/TemplateServiceImpl.java.ftl @@ -0,0 +1,224 @@ +package ${packageName}.service.impl; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import ${packageName}.common.ErrorCode; +import ${packageName}.constant.CommonConstant; +import ${packageName}.exception.ThrowUtils; +import ${packageName}.mapper.${upperDataKey}Mapper; +import ${packageName}.model.dto.${dataKey}.${upperDataKey}QueryRequest; +import ${packageName}.model.entity.${upperDataKey}; +import ${packageName}.model.entity.${upperDataKey}Favour; +import ${packageName}.model.entity.${upperDataKey}Thumb; +import ${packageName}.model.entity.User; +import ${packageName}.model.vo.${upperDataKey}VO; +import ${packageName}.model.vo.UserVO; +import ${packageName}.service.${upperDataKey}Service; +import ${packageName}.service.UserService; +import ${packageName}.utils.SqlUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * ${dataName}服务实现 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@Service +@Slf4j +public class ${upperDataKey}ServiceImpl extends ServiceImpl<${upperDataKey}Mapper, ${upperDataKey}> implements ${upperDataKey}Service { + + @Resource + private UserService userService; + + /** + * 校验数据 + * + * @param ${dataKey} + * @param add 对创建的数据进行校验 + */ + @Override + public void valid${upperDataKey}(${upperDataKey} ${dataKey}, boolean add) { + ThrowUtils.throwIf(${dataKey} == null, ErrorCode.PARAMS_ERROR); + // todo 从对象中取值 + String title = ${dataKey}.getTitle(); + // 创建数据时,参数不能为空 + if (add) { + // todo 补充校验规则 + ThrowUtils.throwIf(StringUtils.isBlank(title), ErrorCode.PARAMS_ERROR); + } + // 修改数据时,有参数则校验 + // todo 补充校验规则 + if (StringUtils.isNotBlank(title)) { + ThrowUtils.throwIf(title.length() > 80, ErrorCode.PARAMS_ERROR, "标题过长"); + } + } + + /** + * 获取查询条件 + * + * @param ${dataKey}QueryRequest + * @return + */ + @Override + public QueryWrapper<${upperDataKey}> getQueryWrapper(${upperDataKey}QueryRequest ${dataKey}QueryRequest) { + QueryWrapper<${upperDataKey}> queryWrapper = new QueryWrapper<>(); + if (${dataKey}QueryRequest == null) { + return queryWrapper; + } + // todo 从对象中取值 + Long id = ${dataKey}QueryRequest.getId(); + Long notId = ${dataKey}QueryRequest.getNotId(); + String title = ${dataKey}QueryRequest.getTitle(); + String content = ${dataKey}QueryRequest.getContent(); + String searchText = ${dataKey}QueryRequest.getSearchText(); + String sortField = ${dataKey}QueryRequest.getSortField(); + String sortOrder = ${dataKey}QueryRequest.getSortOrder(); + List tagList = ${dataKey}QueryRequest.getTags(); + Long userId = ${dataKey}QueryRequest.getUserId(); + // todo 补充需要的查询条件 + // 从多字段中搜索 + if (StringUtils.isNotBlank(searchText)) { + // 需要拼接查询条件 + queryWrapper.and(qw -> qw.like("title", searchText).or().like("content", searchText)); + } + // 模糊查询 + queryWrapper.like(StringUtils.isNotBlank(title), "title", title); + queryWrapper.like(StringUtils.isNotBlank(content), "content", content); + // JSON 数组查询 + if (CollUtil.isNotEmpty(tagList)) { + for (String tag : tagList) { + queryWrapper.like("tags", "\"" + tag + "\""); + } + } + // 精确查询 + queryWrapper.ne(ObjectUtils.isNotEmpty(notId), "id", notId); + queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id); + queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId); + // 排序规则 + queryWrapper.orderBy(SqlUtils.validSortField(sortField), + sortOrder.equals(CommonConstant.SORT_ORDER_ASC), + sortField); + return queryWrapper; + } + + /** + * 获取${dataName}封装 + * + * @param ${dataKey} + * @param request + * @return + */ + @Override + public ${upperDataKey}VO get${upperDataKey}VO(${upperDataKey} ${dataKey}, HttpServletRequest request) { + // 对象转封装类 + ${upperDataKey}VO ${dataKey}VO = ${upperDataKey}VO.objToVo(${dataKey}); + + // todo 可以根据需要为封装对象补充值,不需要的内容可以删除 + // region 可选 + // 1. 关联查询用户信息 + Long userId = ${dataKey}.getUserId(); + User user = null; + if (userId != null && userId > 0) { + user = userService.getById(userId); + } + UserVO userVO = userService.getUserVO(user); + ${dataKey}VO.setUser(userVO); + // 2. 已登录,获取用户点赞、收藏状态 + long ${dataKey}Id = ${dataKey}.getId(); + User loginUser = userService.getLoginUserPermitNull(request); + if (loginUser != null) { + // 获取点赞 + QueryWrapper<${upperDataKey}Thumb> ${dataKey}ThumbQueryWrapper = new QueryWrapper<>(); + ${dataKey}ThumbQueryWrapper.in("${dataKey}Id", ${dataKey}Id); + ${dataKey}ThumbQueryWrapper.eq("userId", loginUser.getId()); + ${upperDataKey}Thumb ${dataKey}Thumb = ${dataKey}ThumbMapper.selectOne(${dataKey}ThumbQueryWrapper); + ${dataKey}VO.setHasThumb(${dataKey}Thumb != null); + // 获取收藏 + QueryWrapper<${upperDataKey}Favour> ${dataKey}FavourQueryWrapper = new QueryWrapper<>(); + ${dataKey}FavourQueryWrapper.in("${dataKey}Id", ${dataKey}Id); + ${dataKey}FavourQueryWrapper.eq("userId", loginUser.getId()); + ${upperDataKey}Favour ${dataKey}Favour = ${dataKey}FavourMapper.selectOne(${dataKey}FavourQueryWrapper); + ${dataKey}VO.setHasFavour(${dataKey}Favour != null); + } + // endregion + + return ${dataKey}VO; + } + + /** + * 分页获取${dataName}封装 + * + * @param ${dataKey}Page + * @param request + * @return + */ + @Override + public Page<${upperDataKey}VO> get${upperDataKey}VOPage(Page<${upperDataKey}> ${dataKey}Page, HttpServletRequest request) { + List<${upperDataKey}> ${dataKey}List = ${dataKey}Page.getRecords(); + Page<${upperDataKey}VO> ${dataKey}VOPage = new Page<>(${dataKey}Page.getCurrent(), ${dataKey}Page.getSize(), ${dataKey}Page.getTotal()); + if (CollUtil.isEmpty(${dataKey}List)) { + return ${dataKey}VOPage; + } + // 对象列表 => 封装对象列表 + List<${upperDataKey}VO> ${dataKey}VOList = ${dataKey}List.stream().map(${dataKey} -> { + return ${upperDataKey}VO.objToVo(${dataKey}); + }).collect(Collectors.toList()); + + // todo 可以根据需要为封装对象补充值,不需要的内容可以删除 + // region 可选 + // 1. 关联查询用户信息 + Set userIdSet = ${dataKey}List.stream().map(${upperDataKey}::getUserId).collect(Collectors.toSet()); + Map> userIdUserListMap = userService.listByIds(userIdSet).stream() + .collect(Collectors.groupingBy(User::getId)); + // 2. 已登录,获取用户点赞、收藏状态 + Map ${dataKey}IdHasThumbMap = new HashMap<>(); + Map ${dataKey}IdHasFavourMap = new HashMap<>(); + User loginUser = userService.getLoginUserPermitNull(request); + if (loginUser != null) { + Set ${dataKey}IdSet = ${dataKey}List.stream().map(${upperDataKey}::getId).collect(Collectors.toSet()); + loginUser = userService.getLoginUser(request); + // 获取点赞 + QueryWrapper<${upperDataKey}Thumb> ${dataKey}ThumbQueryWrapper = new QueryWrapper<>(); + ${dataKey}ThumbQueryWrapper.in("${dataKey}Id", ${dataKey}IdSet); + ${dataKey}ThumbQueryWrapper.eq("userId", loginUser.getId()); + List<${upperDataKey}Thumb> ${dataKey}${upperDataKey}ThumbList = ${dataKey}ThumbMapper.selectList(${dataKey}ThumbQueryWrapper); + ${dataKey}${upperDataKey}ThumbList.forEach(${dataKey}${upperDataKey}Thumb -> ${dataKey}IdHasThumbMap.put(${dataKey}${upperDataKey}Thumb.get${upperDataKey}Id(), true)); + // 获取收藏 + QueryWrapper<${upperDataKey}Favour> ${dataKey}FavourQueryWrapper = new QueryWrapper<>(); + ${dataKey}FavourQueryWrapper.in("${dataKey}Id", ${dataKey}IdSet); + ${dataKey}FavourQueryWrapper.eq("userId", loginUser.getId()); + List<${upperDataKey}Favour> ${dataKey}FavourList = ${dataKey}FavourMapper.selectList(${dataKey}FavourQueryWrapper); + ${dataKey}FavourList.forEach(${dataKey}Favour -> ${dataKey}IdHasFavourMap.put(${dataKey}Favour.get${upperDataKey}Id(), true)); + } + // 填充信息 + ${dataKey}VOList.forEach(${dataKey}VO -> { + Long userId = ${dataKey}VO.getUserId(); + User user = null; + if (userIdUserListMap.containsKey(userId)) { + user = userIdUserListMap.get(userId).get(0); + } + ${dataKey}VO.setUser(userService.getUserVO(user)); + ${dataKey}VO.setHasThumb(${dataKey}IdHasThumbMap.getOrDefault(${dataKey}VO.getId(), false)); + ${dataKey}VO.setHasFavour(${dataKey}IdHasFavourMap.getOrDefault(${dataKey}VO.getId(), false)); + }); + // endregion + + ${dataKey}VOPage.setRecords(${dataKey}VOList); + return ${dataKey}VOPage; + } + +} diff --git a/src/main/resources/templates/model/TemplateAddRequest.java.ftl b/src/main/resources/templates/model/TemplateAddRequest.java.ftl new file mode 100644 index 0000000..a527ded --- /dev/null +++ b/src/main/resources/templates/model/TemplateAddRequest.java.ftl @@ -0,0 +1,33 @@ +package ${packageName}.model.dto.${dataKey}; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 创建${dataName}请求 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@Data +public class ${upperDataKey}AddRequest implements Serializable { + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/resources/templates/model/TemplateEditRequest.java.ftl b/src/main/resources/templates/model/TemplateEditRequest.java.ftl new file mode 100644 index 0000000..f955c53 --- /dev/null +++ b/src/main/resources/templates/model/TemplateEditRequest.java.ftl @@ -0,0 +1,38 @@ +package ${packageName}.model.dto.${dataKey}; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 编辑${dataName}请求 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@Data +public class ${upperDataKey}EditRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/resources/templates/model/TemplateQueryRequest.java.ftl b/src/main/resources/templates/model/TemplateQueryRequest.java.ftl new file mode 100644 index 0000000..3ff9b8e --- /dev/null +++ b/src/main/resources/templates/model/TemplateQueryRequest.java.ftl @@ -0,0 +1,56 @@ +package ${packageName}.model.dto.${dataKey}; + +import ${packageName}.common.PageRequest; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serializable; +import java.util.List; + +/** + * 查询${dataName}请求 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class ${upperDataKey}QueryRequest extends PageRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * id + */ + private Long notId; + + /** + * 搜索词 + */ + private String searchText; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + /** + * 创建用户 id + */ + private Long userId; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/resources/templates/model/TemplateUpdateRequest.java.ftl b/src/main/resources/templates/model/TemplateUpdateRequest.java.ftl new file mode 100644 index 0000000..9188baf --- /dev/null +++ b/src/main/resources/templates/model/TemplateUpdateRequest.java.ftl @@ -0,0 +1,38 @@ +package ${packageName}.model.dto.${dataKey}; + +import lombok.Data; + +import java.io.Serializable; +import java.util.List; + +/** + * 更新${dataName}请求 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@Data +public class ${upperDataKey}UpdateRequest implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 标签列表 + */ + private List tags; + + private static final long serialVersionUID = 1L; +} \ No newline at end of file diff --git a/src/main/resources/templates/model/TemplateVO.java.ftl b/src/main/resources/templates/model/TemplateVO.java.ftl new file mode 100644 index 0000000..9f04289 --- /dev/null +++ b/src/main/resources/templates/model/TemplateVO.java.ftl @@ -0,0 +1,93 @@ +package ${packageName}.model.vo; + +import cn.hutool.json.JSONUtil; +import ${packageName}.model.entity.${upperDataKey}; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * ${dataName}视图 + * + * @author 程序员鱼皮 + * @from 编程导航学习圈 + */ +@Data +public class ${upperDataKey}VO implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 标题 + */ + private String title; + + /** + * 内容 + */ + private String content; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 标签列表 + */ + private List tagList; + + /** + * 创建用户信息 + */ + private UserVO user; + + /** + * 封装类转对象 + * + * @param ${dataKey}VO + * @return + */ + public static ${upperDataKey} voToObj(${upperDataKey}VO ${dataKey}VO) { + if (${dataKey}VO == null) { + return null; + } + ${upperDataKey} ${dataKey} = new ${upperDataKey}(); + BeanUtils.copyProperties(${dataKey}VO, ${dataKey}); + List tagList = ${dataKey}VO.getTagList(); + ${dataKey}.setTags(JSONUtil.toJsonStr(tagList)); + return ${dataKey}; + } + + /** + * 对象转封装类 + * + * @param ${dataKey} + * @return + */ + public static ${upperDataKey}VO objToVo(${upperDataKey} ${dataKey}) { + if (${dataKey} == null) { + return null; + } + ${upperDataKey}VO ${dataKey}VO = new ${upperDataKey}VO(); + BeanUtils.copyProperties(${dataKey}, ${dataKey}VO); + ${dataKey}VO.setTagList(JSONUtil.toList(${dataKey}.getTags(), String.class)); + return ${dataKey}VO; + } +} diff --git a/src/main/resources/test_excel.xlsx b/src/main/resources/test_excel.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..9e4c4c6e0f68fce96fcdd5e6457b54e9d6a3cb52 GIT binary patch literal 9143 zcmeHN1y@|j)@>lTb>or*cN!;HaCZxCK^k`n?gZC{;7*VbAOv@U6A11hIE3I3pwYnB zGxO%nOlH1c@TPjLs&!Z2b5_aOwX62IYKlk?2mmMmGyniV1u#3zu{K5k01_Vn0Qdkj zL<31DM|X&$yU8-H^A}_VyJz;5WO%iR-@9@WHQre zcD+th>~Ldj;+}bKj=0Pbp4g7FG`fP)+QIi&nTM?AP4rp0et)7JOQ)ZqpHC-ae9W2J zb;}b%YZI_Ru2?Wt$mBdg%`T>nsFKTZ%)eKZut;h6xSMk6hHef2VebmLMN4i%qJ;_x zwFB#F@j$MWssJBzNI>b}$0q&{st4u|{TxdsP&Xe)U)~eIKszm`A0&VuKTy&7M;xpU z?g;trk8c@-9-gG`1ajS>008&*NC36Jz_MP8gXRn#Yf5m`VZvc);tH{MV`uxN{uhq_ z!x;S2&?}(Isy!T7;YV_}5rY>qONl@UMNe_LR;p(KLGoX4>*I=O$(K4A9s-|{g(ArY zwg=n}EiOHc+a08Wt@BjG;1LMXGAtj$iyRoJcq$SifIcZ`tg!3SmY<^Pn=kx{)t`H+d{8 za4xlE2U|2!Kxuz6gK*Hz%xa;^Z_u9V{EAFV(^|l$+AP;qklNeC!v4dlR8}Yc4?nO< z_Miqe58fr$nCt*u{&}E&9nZ;dj(0B~de7UzqQc^6ArG~NRreETCIWT%nS z5hOITgUZJtvdH*&`@4H@4=`~u-SC@5po6Tr1pHqw8R(-U{r8aB;XTiRAOQdo@Y4@2{0(@>{5e=EwA7ul1PKE2-0zXrb3W6Hp)qGj z04gawdRM^tZ2s!4`>9y+bJIwK*FPdA1TBLjXMF#RZ-A1k4?z}a1`ni)I5i46m zx$Vg+K1z*d4UFG5D1cXZ1f{dGwF^xPuDS(JPjB;7x9zC%9*22x0rGbwYM+&319xkn zGj&4vV7m_*XnLB+l2?%}+FY5Qbmrw%iE-~EY=_9*Vt|9198&7Xv3=BgcC%&RNDD$O zu}&86#W-t^7Z`@hTbe8S8D$1RUaN#U>_}xc(|XP)^JwxE%xJ!nhUPSDC#$L)Jg_GG z^!SEyZ+dA43=foXYsG8EfDjPXkw&$^XqSx~4s<_bkL*xS{wTDfO*qvPKy#TefhK1+ zt^oLWLz&sSZJBj?8ltoB$YK=QaG;~Vr=V4$KA}Ptg!i3eA*`Af?Pk!Ep$kO%1 zMVV)1_)4ElfW_M64I!F$7^>`8)hZtsncQ zaU0szh3GF{F+RzfkGsUHRXj1w%rnu56C%s*KdjC=t4z1*UcguLdcbOxFHD|0hq$h^ z&i|g*{W*Q8y5F1v*>M2KL;}HahdTu+I`>Fr4|#L({;ox?v?|T(4WaqsdyTmaU3CTO z;kZf2y6VAn0+A>s#tw2uemk=#-E4Znj+k(Ql8!sKJ{pcsE(I*GuQjju#w2qBCMjFa zUMn;@yCja~V{L!vogCv~t@04H(3>=(VY|y&nB>U2YG}O9-!J{9`_ddeHi~a*PwXsH z&${C?j8&e<*sS=@%yyw_L!Wz}l~uIQ%j~9#oX+BT*s>Z~m2&=*GZ}8VAKE6x4-T!C z_V&A5vCbZUr)H2m?}w09awRq#qR3K&iB3JXFJcqoJ)_m&5nyq9wd}7tG zC4|4IFZe#EX^K{bT4zqyl*+mi5gu7WrC+ON^yz>cU5iHsru#f5j)R zKhRWz3X`GJu7g+x>YDP{NoNSSxc%! zi%~{7%a2-C>1VxHD(^%G3?e(s7z9f_83frnjVr5E&f1l zm6tAxyIEIU-7@?mB0s3VG>?QM(gp(n!2S)9ZtmXp5Vv18?_TYZ_{Ar{4&rY@z!p2E zk5Ic-=;XQ2OBA_i#8w3Td}94V`@&mJMjxuuZ(xDVbT^9p(uTQw@x@YfXq$8d)P6Y2 zes4)yor2X>DqsbxGXu1NTEF@&dN-OWga0mSo08d0i=$aCn;|Vj$W;vz$%>`}r5_E~ z9t}O4Qe7Xi=Wo~5umy?@GP|VqSJ0E_TtP83a>@u_9hW@Q2O?>Kx_1wDcws7qNYn6FoT5O-OJD^5>GiBL*{1GSim^hWRp*H z6j8<-70e2SB+!{fqPA$)7|a)5=CeG{m#|R9QzS*aNvQL3NOuV zQQ{H;PXdO8S@w|zV|8>WRb0VmtQoFQ^xginEW&T#0?s;W-n~1>xkPdtg;YCs6P40N z^CU7)VZir>5}vPhJc;C);8d8+G{)Wb5DDWf4;zUdqkPlI;z7J4U~Mzy6mzkng9*2K zuSSPJSzgY3uLp-J(Q$sgKADF;8~i#SPb1Z~$JGEqK*=Vn*aQ9X*_A%*@d+^g6xLhD z=CszOe0diad~giXtGuKS#b|_l8C7ZI^nB$HSm8~EZK4d|`PCD-mDhe9u4ZUKc2KQ4 z?u_5H4)K-sa8BndUE{5c}SaUWN6RQKvmuXSFB$PcgqF@jYr@3z9kH&m8^2_%v(Oa$z2`t(L;~ zBESXq{=IGyO_5En=`sBFMEucX9Nx~D>G(?UEtiro2U z5-qI0$2CR;07fW((F}eiQFm*I1BCt8n)4Un?&}%Ekn<4)u%C%yogQ93*%-!iI^kWk z;6vAAC{EBffHA%$C6!-}Ll1_EypkwLOl>1jFu7J!zy$Nu;r?J>f{qU-d`q(2PnvbD z%7UgY84)Gi<`fmV#f#(!v|Ntnr2ELGV|GJRO*+)R3unj9r_)ZQ2DKoF&! z6RfRJtj{S!d(!@(FCX^VLPBQ#=Enqkpx^m%Bd$oeXrQlvY+koi6oKt?sjH4m1cMMV zArV%VFx^PDtz}Rln4*Ndc7v*e#y^3YYAq(!WKuN1<;D!;0Fij+n8>?{a?OxD{GdOA zP?#a_aRohg2uE4H&NXk)kcVOC^1E|87JsrJ85&(1+nCB);~f;zSwJzxqZZ$D<9how z>>o3{S&IeN^~Yo>ySTH*q2k1C)@!_seGzt-)l>Ut_CLr{*6r*recmi#?xqG{M>ERf z%#9aUYag)bw1y~=EV*=NnR1lraBT@-)R?|9vW-Sp+$=GSnQ-Vw1*nNd)5PG3VO z6X)^-(V=F0wOWvguaBs8Kfp?3E*5`-aX;gfFS-+12#&?Ffe`Cb&xWT6=aRT^C4=v| ztk1CrH)Io34)48O?@N<$MV~g`8$D^%hI~B8x3C@haeiJJ7v9-9kQaErIdDWFdb^q6^q9Y{Q9zJmO%l(1&8Tl+8JnmF@eynT z>COzV2Mwf%D4oAp(85lG>E#hzhB?>Ofa&D&oRs)@^0oo87tp&6<+tp>>mzbb;QVa* zWhaQmmaV6!$D7MTb#$Bl5Jf_^s=1Z%J>r+Vu^{6pMF?MaYQ`Ls0&V8{14UK;0UXX3 z6^H&3teuBRAgd7N*B2ruf|2}2T(qd#)LRllwBb#xhA0wc;FbNQ?}D){+DkpMPw*O$ z3vo6g()AtN!oK45vAvQc(41Opm6KtkxghqlSihE#cwL&#^-i>3qRFDlMfV-(jO7Ez zVfE33v^`BTZ3J6RYa}QBf_cOeS|4}m2yK+oe(O3=gTQ+(!@cVwyqP;tYhDM zo*G3UKYCK@mrL$1fT+FDRn^-PyKks9hE6m;y?Z<#30F@-tJ=z%k$qefC?8|A?rp3ts;oa*8NB%(+7-8 z$%gd+E0EtOG9@C%p`_Fk{^TPN>4B^@N@YQf<8u}15+CL^Qv7kw$)1*?Xw{ur|5ER^ zfqt9PT0?E4k?EI+AN|@0s`?8Q=``Idb3Ko=cRfVi%UdfHky7?!NKBP1$<;kb)J)OOPf^krPOFgP3t3B9&ptJ3XT5#pc4!z~}CY?~97)@8KCR$+{0 z$oM34zsW#QGh^qbOmNp+XmRnj^{^=ymVFJTiFL1yu<@3nC4P# zHftt#<=%~(1KCMamo^2{(`%0R3OQcY+oGkh(D2w@;eR9P8Sp}BrkOS%F4S!DCza22 zyi7AqB_*zjkV+9WOja2};Y>>RP3Z-jfCFD)^GrM}bYRg50xs)rWQwskWx4>}g$BL2 zx@c^|mq^reRVaejG^?Bg-u9V1uAp6b*xgPMm(Y$RxXlNAt*gt9 zRZW<*b>+GHe8_sPEqYQQC7wnwM(ssmxP?ez+OVHTs zU>&X3tYG){Q8v@$Skkcmk{M4Zu)$8Otm{=>g{ zy`__)Jj;89MoiGt?v;4$=lyAn5nEq1G@l%qf`v*CjCTFTW%9EY(;|VUZC_ckhjnk4 z@@Jh0Y_}X6fzt{@w=%VAxXiC!s5$Xni{BV)_kS4DydLyJIGlOm0GA2>;ZA$b0h*kH zOCZt6007Bvbo|Sm*3B9Mad%_?wfU8kvy(qME^+|FkC3l%9vpGiFT^7c2ix^oJ4&Z* zDyh@Na4?nAwikSBwW94&0hq)B^krzbZ>)OrP6vv#EpTV$r@r!#y-X2fQKDN^R=K}5 zM#W9xA6txOnUYXZUH!JPzL$2@HD755cq%Tj=la=e1rjST5%ks3LeSc!T82G_4w=bO5{vIQV2OAF;}a3#OSCORP?!NonpbqL1ZAh zc40;Hh9BKl4>6Lyg(C|mVX|LTBNn?}^GHVAKjPt#LU^HdNn$cR8(I*ktKo{uQe+I- zB2VcJ)f6A`9J=R;IHKf>8?(ti6Eh{S+(@>LieQy?I@vfDF@(xa?eNGa?=*=zlrB4O z6r@m{!!Jko_wePtzqd~`!0Dz0N;gVaBA5;Pk#H-S4a>+)^|JH6T!n2FP|k?D9+A3Q z4jRqPkne$~UIa!f_W-(u_ec8XNP}(U*XW9yPst3GkXWF>@@!6K%wdS?==)JuY5cG- zrryi*0X1~eALSNOcXB1qLWg`DIM_M-TT1v2&suhRs(6c)QPE?)x*H5Z$p=vOU;FcG z#WT`{(aiyTFm8f=gP={YQ@qocj9SnMTy(&j&Z*WTxL;=8eBy+|Eh!Idc&fUq9ce_Q zis}ku+Lw0@Z_~94SL4H>lj=Z;(<}Eqw#|jL=4O9Q*ME`{=u7PxN}8)2)zf`FmDIqX z+taYvUT~3_?r;ka`M(Q1k(0`=#^D{phHHHU@D?ucxLKRJLM$}hU2Pn#e!W%NCv++F zh!IF%gxqtqwdd$oM}ATw4lz*^eJ+Vxjdvq)eOfw6G9}`5i~^@n zpTC^VP9qUk)rjMH!uKZ1xPP9NcMkhHL{Td0Rj%cNk}L(_ONTUQ%D&Q<3&9$mlz|MwX{gc6O2 z!$)rdpC1rh6}50OS95i8c4Iepa)taSpZBjA3J;A~sJdz>2f@n~N8^ZDQz*KH zma1%=prVsXo1-VxU}Xcy%>~gsiKWQpyzl6b!)CsbR9`*RmFM;|We@v6;s}h(kqQoO zXZls$1_ZhTDbGEMC}mNrt@R8|AcmUDBwkPAP&SyWgBh3fNGe(v9 zEK2SJSxMjouaq%gY*5dFar)hnbiT_ozSind@Mv5QidJ$S!iI~L zg|SYPXO5|B@|CS7BNYZWnoi8Xi-_6-jqi0Lw?Pj;m;CN%ff~z`5d*F-qr+(BNs<#; z6>9QNNpq4C9KXN2V_Q~B9Jsn?7`16j2dV~9_Yj*DUjCyRe-QN=RsjEp3{FzOKgXS^ zv-7`U2amV^lx%1hoQC0f8zdM`_+ebOBV)9fHs@<{AKmu=dEaddK_Ys^@LsZyxsbF+ zC}-F&J}*{$cx+x5S2Fr}%8@p3eVZYA*KDq-q9@({_+|Q-Yf=GUL0y1BWY$PTvRe`z zqDctmW6bvhv}|X4I<|z8F-fc?v0y)DDdlOl*GeV*D3h^}F$F?1q+XjZLuy*Hs}K%P zY#(T;cL2SM>^DVL)z6^?B#($6{di|Xsx+47$aj+(T<ckHFR^>eINQfwy<(2V)n$bb1talKc)i{jkbhT34vXXBp*+CPkgv3}#%|H`#LoBk{m{b9-j{MGbl z+305nKOb%XaL_~i-;V$7p!>6zpU(t;co`@AZ3I7`5PtUXS5E!I9srmm2LS%Yus@ss jb!+^yxx(W=ng3^_R8vHTuPy+90sjTTNt}x6m#6;&6o%p( literal 0 HcmV?d00001 diff --git a/src/main/resources/网站数据.xlsx b/src/main/resources/网站数据.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..e8df24513fa159066524e977e61b283f6ab383cb GIT binary patch literal 9112 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 b{}=X`3atcy{qeG*gTL{B2itj*KH~l#1a7z@ literal 0 HcmV?d00001 diff --git a/src/test/.DS_Store b/src/test/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..bfeab2ce7ec9afcb8a706406d2de3980c6d8b9ae GIT binary patch literal 6148 zcmeHKJ5Iwu5S;}VmPnD3a*seH4zNV#1i1hSmWWUyr-6dXUCu$p3Ah0V5E=1-cQo|MHsLRweuRgJ}h*ZF&_t-rwR`=chFsVEpP;MoU zvX*CAkNLB=VQ$|w&1Tna5UXEb+V|`2$IUq3{+K^(htGBeDvb(I0V+TRsKCEe06kl+ zzHsD91*iZO_*Ou_4;ijl0((dMbYQU&0I0w5X1KOl0+=-bEP=fvBCzCCpi@(f7|H2~ z=cp@zy`$45*~z$1oSb4pNp?Eo*~%pqN3K+W3XByv_w8K!|1JE){68jfM+K程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +class MainApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/src/test/java/com/yupi/springbootinit/manager/AiManagerTest.java b/src/test/java/com/yupi/springbootinit/manager/AiManagerTest.java new file mode 100644 index 0000000..0432f1e --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/manager/AiManagerTest.java @@ -0,0 +1,36 @@ +package com.yupi.springbootinit.manager; + +import com.yupi.springbootinit.MainApplication; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.annotation.Resource; + +/** + * @author leikooo + * @date 2024/9/12 + * @description + */ +@SpringBootTest(classes = MainApplication.class) +public class AiManagerTest { + @Resource + private AiManager aiManager; + + + // import org.junit.jupiter.api.Test; + @Test + public void test() { + String c = "分析需求:\n" + + "分析网站用户的增长情况 \n" + + "请使用 柱状图 \n" + + "原始数据:\n" + + "日期,用户数\n" + + "1号,10\n" + + " 2号,20\n" + + " 3号,30"; + String s = aiManager.sendMsgToXingHuo(true, c); + System.out.println("s = " + s); + } + +} + diff --git a/src/test/java/com/yupi/springbootinit/manager/CosManagerTest.java b/src/test/java/com/yupi/springbootinit/manager/CosManagerTest.java new file mode 100644 index 0000000..e803a4b --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/manager/CosManagerTest.java @@ -0,0 +1,23 @@ +package com.yupi.springbootinit.manager; + +import javax.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * Cos 操作测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +class CosManagerTest { + + @Resource + private CosManager cosManager; + + @Test + void putObject() { + cosManager.putObject("test", "test.json"); + } +} \ No newline at end of file diff --git a/src/test/java/com/yupi/springbootinit/manager/RedisLimiterManagerTest.java b/src/test/java/com/yupi/springbootinit/manager/RedisLimiterManagerTest.java new file mode 100644 index 0000000..82529f9 --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/manager/RedisLimiterManagerTest.java @@ -0,0 +1,32 @@ +package com.yupi.springbootinit.manager; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import javax.annotation.Resource; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class RedisLimiterManagerTest { + + @Resource + private RedisLimiterManager redisLimiterManager; + + @Test + void doRateLimit() throws InterruptedException { + String userId = "1"; + for (int i = 0; i < 2; i++) { + redisLimiterManager.doRateLimit(userId); + System.out.println("成功"); + } + Thread.sleep(1000); + for (int i = 0; i < 5; i++) { + redisLimiterManager.doRateLimit(userId); + System.out.println("成功"); + } + + + + } +} \ No newline at end of file diff --git a/src/test/java/com/yupi/springbootinit/mapper/PostFavourMapperTest.java b/src/test/java/com/yupi/springbootinit/mapper/PostFavourMapperTest.java new file mode 100644 index 0000000..96bd2f3 --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/mapper/PostFavourMapperTest.java @@ -0,0 +1,33 @@ +package com.yupi.springbootinit.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.model.entity.Post; +import javax.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 帖子收藏数据库操作测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +class PostFavourMapperTest { + + @Resource + private PostFavourMapper postFavourMapper; + + @Test + void listUserFavourPostByPage() { + IPage page = new Page<>(2, 1); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("id", 1); + queryWrapper.like("content", "a"); + IPage result = postFavourMapper.listFavourPostByPage(page, queryWrapper, 1); + Assertions.assertNotNull(result); + } +} \ No newline at end of file diff --git a/src/test/java/com/yupi/springbootinit/mapper/PostMapperTest.java b/src/test/java/com/yupi/springbootinit/mapper/PostMapperTest.java new file mode 100644 index 0000000..b0186ba --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/mapper/PostMapperTest.java @@ -0,0 +1,28 @@ +package com.yupi.springbootinit.mapper; + +import com.yupi.springbootinit.model.entity.Post; +import java.util.Date; +import java.util.List; +import javax.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 帖子数据库操作测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +class PostMapperTest { + + @Resource + private PostMapper postMapper; + + @Test + void listPostWithDelete() { + List postList = postMapper.listPostWithDelete(new Date()); + Assertions.assertNotNull(postList); + } +} \ No newline at end of file diff --git a/src/test/java/com/yupi/springbootinit/service/PostFavourServiceTest.java b/src/test/java/com/yupi/springbootinit/service/PostFavourServiceTest.java new file mode 100644 index 0000000..e5434e2 --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/service/PostFavourServiceTest.java @@ -0,0 +1,46 @@ +package com.yupi.springbootinit.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.yupi.springbootinit.model.entity.Post; + +import javax.annotation.Resource; + +import com.yupi.springbootinit.model.entity.User; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 帖子收藏服务测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +class PostFavourServiceTest { + + @Resource + private PostFavourService postFavourService; + + private static final User loginUser = new User(); + + @BeforeAll + static void setUp() { + loginUser.setId(1L); + } + + @Test + void doPostFavour() { + int i = postFavourService.doPostFavour(1L, loginUser); + Assertions.assertTrue(i >= 0); + } + + @Test + void listFavourPostByPage() { + QueryWrapper postQueryWrapper = new QueryWrapper<>(); + postQueryWrapper.eq("id", 1L); + postFavourService.listFavourPostByPage(Page.of(0, 1), postQueryWrapper, loginUser.getId()); + } +} diff --git a/src/test/java/com/yupi/springbootinit/service/PostThumbServiceTest.java b/src/test/java/com/yupi/springbootinit/service/PostThumbServiceTest.java new file mode 100644 index 0000000..acd0774 --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/service/PostThumbServiceTest.java @@ -0,0 +1,35 @@ +package com.yupi.springbootinit.service; + +import javax.annotation.Resource; + +import com.yupi.springbootinit.model.entity.User; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 帖子点赞服务测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +class PostThumbServiceTest { + + @Resource + private PostThumbService postThumbService; + + private static final User loginUser = new User(); + + @BeforeAll + static void setUp() { + loginUser.setId(1L); + } + + @Test + void doPostThumb() { + int i = postThumbService.doPostThumb(1L, loginUser); + Assertions.assertTrue(i >= 0); + } +} diff --git a/src/test/java/com/yupi/springbootinit/service/UserServiceTest.java b/src/test/java/com/yupi/springbootinit/service/UserServiceTest.java new file mode 100644 index 0000000..0b152c5 --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/service/UserServiceTest.java @@ -0,0 +1,35 @@ +package com.yupi.springbootinit.service; + +import javax.annotation.Resource; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 用户服务测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +public class UserServiceTest { + + @Resource + private UserService userService; + + @Test + void userRegister() { + String userAccount = "yupi"; + String userPassword = ""; + String checkPassword = "123456"; + try { + long result = userService.userRegister(userAccount, userPassword, checkPassword); + Assertions.assertEquals(-1, result); + userAccount = "yu"; + result = userService.userRegister(userAccount, userPassword, checkPassword); + Assertions.assertEquals(-1, result); + } catch (Exception e) { + + } + } +} diff --git a/src/test/java/com/yupi/springbootinit/utils/EasyExcelTest.java b/src/test/java/com/yupi/springbootinit/utils/EasyExcelTest.java new file mode 100644 index 0000000..b74eb9f --- /dev/null +++ b/src/test/java/com/yupi/springbootinit/utils/EasyExcelTest.java @@ -0,0 +1,34 @@ +package com.yupi.springbootinit.utils; + +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.support.ExcelTypeEnum; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.util.ResourceUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Map; + +/** + * EasyExcel 测试 + * + * @author 程序员鱼皮 + * @from 编程导航知识星球 + */ +@SpringBootTest +public class EasyExcelTest { + + @Test + public void doImport() throws FileNotFoundException { + File file = ResourceUtils.getFile("classpath:test_excel.xlsx"); + List> list = EasyExcel.read(file) + .excelType(ExcelTypeEnum.XLSX) + .sheet() + .headRowNumber(0) + .doReadSync(); + System.out.println(list); + } + +} \ No newline at end of file