From a2de21b09292329ecb5b5d6c4e71bc50f2bd8d52 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Tue, 10 Jun 2025 09:54:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E6=A4=8D=E5=B7=A5=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 35 + .mvn/wrapper/maven-wrapper.jar | Bin 0 -> 59925 bytes .mvn/wrapper/maven-wrapper.properties | 18 + README.md | 52 ++ admin-service/.gitignore | 38 ++ admin-service/Dockerfile | 6 + admin-service/pom.xml | 58 ++ .../cxx/admin/AdminServiceApplication.java | 15 + .../com/cxx/admin/config/WebMvcConfig.java | 31 + .../com/cxx/admin/constant/FileConstant.java | 7 + .../admin/controller/AccountController.java | 48 ++ .../controller/BillManageController.java | 58 ++ .../controller/BlogManageController.java | 69 ++ .../controller/BudgetManageController.java | 27 + .../cxx/admin/controller/FileController.java | 65 ++ .../controller/ServerMonitorController.java | 30 + .../admin/controller/SessionController.java | 23 + .../cxx/admin/controller/UserController.java | 33 + .../admin/controller/WeChatController.java | 19 + .../java/com/cxx/admin/dao/AccountDao.java | 12 + .../main/java/com/cxx/admin/dao/BlogDao.java | 24 + .../main/java/com/cxx/admin/dto/FtpInfo.java | 23 + .../com/cxx/admin/dto/file/ChunkInfoDto.java | 22 + .../cxx/admin/dto/file/ChunkResultDto.java | 20 + .../com/cxx/admin/dto/file/FileInfoDto.java | 17 + .../com/cxx/admin/dto/file/FileRecordDto.java | 14 + .../java/com/cxx/admin/dto/server/CpuDto.java | 10 + .../com/cxx/admin/dto/server/DiskDto.java | 13 + .../com/cxx/admin/dto/server/MemoryDto.java | 13 + .../cxx/admin/dto/server/SystemInfoDto.java | 24 + .../admin/dto/server/SystemMetricsDto.java | 24 + .../com/cxx/admin/dto/user/AccountDto.java | 42 ++ .../cxx/admin/dto/user/UserSummaryDto.java | 36 + .../com/cxx/admin/schedule/ServerMonitor.java | 21 + .../com/cxx/admin/service/AccountService.java | 17 + .../cxx/admin/service/BillManageService.java | 18 + .../cxx/admin/service/BlogManageService.java | 25 + .../admin/service/BudgetManageService.java | 8 + .../com/cxx/admin/service/FileService.java | 48 ++ .../admin/service/ServerMonitorService.java | 19 + .../com/cxx/admin/service/SessionService.java | 7 + .../com/cxx/admin/service/UserService.java | 10 + .../service/impl/AccountServiceImpl.java | 84 +++ .../service/impl/BillManageServiceImpl.java | 134 ++++ .../service/impl/BlogManageServiceImpl.java | 193 ++++++ .../service/impl/BudgetManageServiceImpl.java | 43 ++ .../admin/service/impl/FileServiceImpl.java | 204 ++++++ .../impl/ServerMonitorServiceImpl.java | 214 ++++++ .../service/impl/SessionServiceImpl.java | 56 ++ .../admin/service/impl/UserServiceImpl.java | 53 ++ .../java/com/cxx/admin/util/BlogUtils.java | 73 ++ .../java/com/cxx/admin/util/FileUtils.java | 28 + .../java/com/cxx/admin/util/FtpUtils.java | 125 ++++ .../com/cxx/admin/util/UploadFileUtil.java | 173 +++++ .../src/main/resources/application-dev.yml | 15 + .../src/main/resources/application-docker.yml | 16 + .../src/main/resources/application-prod.yml | 16 + .../src/main/resources/application.yml | 36 + .../main/resources/logback-spring-drop.xml | 120 ++++ .../main/resources/mapper/AccountMapper.xml | 13 + .../src/main/resources/mapper/BlogMapper.xml | 64 ++ .../admin/AdminServiceApplicationTests.java | 21 + blog-service/Dockerfile | 6 + blog-service/pom.xml | 1 + .../com/cxx/blog/BlogServiceApplication.java | 13 + .../com/cxx/blog/config/BlogVisitMonitor.java | 71 ++ .../cxx/blog/controller/BlogController.java | 62 ++ .../main/java/com/cxx/blog/dao/BlogDao.java | 25 + .../com/cxx/blog/service/BlogService.java | 28 + .../blog/service/impl/BlogServiceImpl.java | 73 ++ .../java/com/cxx/blog/util/BlogUtils.java | 36 + .../main/java/com/cxx/blog/util/IpUtils.java | 59 ++ .../src/main/resources/application-dev.yml | 11 + .../src/main/resources/application-docker.yml | 13 + .../src/main/resources/application-prod.yml | 12 + .../src/main/resources/application.yml | 20 + .../main/resources/logback-spring-drop.xml | 120 ++++ .../src/main/resources/mapper/blogMapper.xml | 90 +++ .../java/com/cxx/blog/BlogServiceTest.java | 18 + common/.gitignore | 38 ++ common/pom.xml | 40 ++ .../main/java/com/cxx/common/PlainView.java | 4 + .../main/java/com/cxx/common/ReadView.java | 4 + .../main/java/com/cxx/common/WriteView.java | 4 + .../com/cxx/common/dto/StatsChartDto.java | 11 + .../cxx/common/dto/bill/BillCategoryDto.java | 18 + .../com/cxx/common/dto/bill/BillItemDto.java | 26 + .../cxx/common/dto/bill/BillRecordDto.java | 52 ++ .../cxx/common/dto/bill/BillSummaryDto.java | 49 ++ .../cxx/common/dto/blog/BlogCategoryDto.java | 15 + .../java/com/cxx/common/dto/blog/BlogDto.java | 1 + .../cxx/common/dto/blog/BlogLatestDto.java | 20 + .../com/cxx/common/dto/blog/BlogStatsDto.java | 20 + .../com/cxx/common/dto/blog/BlogVisitDto.java | 31 + .../com/cxx/common/dto/budget/BudgetDto.java | 51 ++ .../common/dto/message/MailMessageDto.java | 10 + .../java/com/cxx/common/dto/plan/PlanDto.java | 62 ++ .../com/cxx/common/dto/plan/PlanStatsDto.java | 21 + .../java/com/cxx/common/dto/task/TaskDto.java | 25 + .../com/cxx/common/dto/user/SessionDto.java | 17 + .../java/com/cxx/common/dto/user/UserDto.java | 68 ++ .../java/com/cxx/common/entity/Account.java | 24 + .../java/com/cxx/common/entity/BillBook.java | 21 + .../com/cxx/common/entity/BillCategory.java | 27 + .../java/com/cxx/common/entity/BillImage.java | 15 + .../java/com/cxx/common/entity/BillPay.java | 21 + .../com/cxx/common/entity/BillRecord.java | 41 ++ .../main/java/com/cxx/common/entity/Blog.java | 36 + .../com/cxx/common/entity/BlogCategory.java | 20 + .../com/cxx/common/entity/BlogContent.java | 20 + .../java/com/cxx/common/entity/BlogVisit.java | 27 + .../java/com/cxx/common/entity/Budget.java | 38 ++ .../com/cxx/common/entity/BudgetCategory.java | 15 + .../com/cxx/common/entity/FileRecord.java | 24 + .../main/java/com/cxx/common/entity/Plan.java | 48 ++ .../main/java/com/cxx/common/entity/Task.java | 27 + .../main/java/com/cxx/common/entity/User.java | 52 ++ .../com/cxx/common/mapper/AccountMapper.java | 9 + .../com/cxx/common/mapper/BillBookMapper.java | 9 + .../cxx/common/mapper/BillCategoryMapper.java | 9 + .../cxx/common/mapper/BillImageMapper.java | 9 + .../com/cxx/common/mapper/BillPayMapper.java | 9 + .../cxx/common/mapper/BillRecordMapper.java | 9 + .../cxx/common/mapper/BlogCategoryMapper.java | 9 + .../cxx/common/mapper/BlogContentMapper.java | 9 + .../com/cxx/common/mapper/BlogMapper.java | 9 + .../cxx/common/mapper/BlogVisitMapper.java | 9 + .../common/mapper/BudgetCategoryMapper.java | 9 + .../com/cxx/common/mapper/BudgetMapper.java | 9 + .../cxx/common/mapper/FileRecordMapper.java | 9 + .../com/cxx/common/mapper/PlanMapper.java | 9 + .../com/cxx/common/mapper/TaskMapper.java | 9 + .../com/cxx/common/mapper/UserMapper.java | 9 + .../com/cxx/common/vo/bill/BillQueryVo.java | 21 + .../com/cxx/common/vo/blog/BlogQueryVo.java | 23 + .../com/cxx/common/vo/plan/PlanQueryVo.java | 15 + home-service/Dockerfile | 6 + home-service/pom.xml | 50 ++ .../com/cxx/home/HomeServiceApplication.java | 15 + .../controller/AnniversaryController.java | 55 ++ .../cxx/home/controller/AssetController.java | 54 ++ .../cxx/home/controller/BillController.java | 82 +++ .../cxx/home/controller/BudgetController.java | 67 ++ .../cxx/home/controller/FoodController.java | 105 +++ .../home/controller/JournalController.java | 50 ++ .../cxx/home/controller/KpiController.java | 49 ++ .../cxx/home/controller/LedgerController.java | 54 ++ .../cxx/home/controller/PeriodController.java | 55 ++ .../cxx/home/controller/PlanController.java | 62 ++ .../home/controller/ProductController.java | 62 ++ .../cxx/home/controller/QuartzController.java | 26 + .../home/controller/SessionController.java | 28 + .../cxx/home/controller/TravelController.java | 105 +++ .../java/com/cxx/home/dao/AnniversaryDao.java | 15 + .../main/java/com/cxx/home/dao/AssetDao.java | 14 + .../main/java/com/cxx/home/dao/BillDao.java | 27 + .../main/java/com/cxx/home/dao/BudgetDao.java | 17 + .../main/java/com/cxx/home/dao/FoodDao.java | 33 + .../java/com/cxx/home/dao/JournalDao.java | 13 + .../main/java/com/cxx/home/dao/KpiDao.java | 13 + .../main/java/com/cxx/home/dao/LedgerDao.java | 14 + .../main/java/com/cxx/home/dao/PeriodDao.java | 14 + .../main/java/com/cxx/home/dao/PlanDao.java | 16 + .../java/com/cxx/home/dao/ProductDao.java | 17 + .../main/java/com/cxx/home/dao/TravelDao.java | 35 + .../home/dto/anniversary/AnniversaryDto.java | 36 + .../java/com/cxx/home/dto/asset/AssetDto.java | 32 + .../cxx/home/dto/food/FoodMaterialDto.java | 24 + .../com/cxx/home/dto/food/FoodRecipeDto.java | 45 ++ .../com/cxx/home/dto/food/FoodRecordDto.java | 37 ++ .../com/cxx/home/dto/food/FoodStatsDto.java | 19 + .../com/cxx/home/dto/food/FoodStepDto.java | 24 + .../com/cxx/home/dto/food/FoodSummaryDto.java | 26 + .../com/cxx/home/dto/journal/JournalDto.java | 47 ++ .../java/com/cxx/home/dto/kpi/KpiDto.java | 33 + .../com/cxx/home/dto/ledger/LedgerDto.java | 51 ++ .../com/cxx/home/dto/period/PeriodDayDto.java | 39 ++ .../cxx/home/dto/period/PeriodSettingDto.java | 26 + .../com/cxx/home/dto/product/ProductDto.java | 58 ++ .../cxx/home/dto/travel/TravelRecordDto.java | 41 ++ .../cxx/home/dto/travel/TravelSpotDto.java | 57 ++ .../cxx/home/dto/travel/TravelStatsDto.java | 18 + .../cxx/home/dto/travel/TravelSummaryDto.java | 26 + .../java/com/cxx/home/entity/Anniversary.java | 31 + .../main/java/com/cxx/home/entity/Asset.java | 29 + .../com/cxx/home/entity/FoodMaterial.java | 24 + .../java/com/cxx/home/entity/FoodRecipe.java | 24 + .../java/com/cxx/home/entity/FoodRecord.java | 26 + .../java/com/cxx/home/entity/FoodStep.java | 24 + .../java/com/cxx/home/entity/Journal.java | 38 ++ .../main/java/com/cxx/home/entity/Kpi.java | 26 + .../main/java/com/cxx/home/entity/Ledger.java | 42 ++ .../java/com/cxx/home/entity/PeriodDay.java | 32 + .../com/cxx/home/entity/PeriodSetting.java | 23 + .../java/com/cxx/home/entity/Product.java | 40 ++ .../java/com/cxx/home/entity/TravelImage.java | 15 + .../com/cxx/home/entity/TravelRecord.java | 25 + .../java/com/cxx/home/entity/TravelSpot.java | 48 ++ .../java/com/cxx/home/entity/TravelVideo.java | 15 + .../cxx/home/mapper/AnniversaryMapper.java | 9 + .../java/com/cxx/home/mapper/AssetMapper.java | 9 + .../cxx/home/mapper/FoodMaterialMapper.java | 9 + .../com/cxx/home/mapper/FoodRecipeMapper.java | 9 + .../com/cxx/home/mapper/FoodRecordMapper.java | 9 + .../com/cxx/home/mapper/FoodStepMapper.java | 9 + .../com/cxx/home/mapper/JournalMapper.java | 9 + .../java/com/cxx/home/mapper/KpiMapper.java | 9 + .../com/cxx/home/mapper/LedgerMapper.java | 9 + .../com/cxx/home/mapper/PeriodDayMapper.java | 9 + .../cxx/home/mapper/PeriodSettingMapper.java | 9 + .../com/cxx/home/mapper/ProductMapper.java | 9 + .../cxx/home/mapper/TravelImageMapper.java | 9 + .../cxx/home/mapper/TravelRecordMapper.java | 9 + .../com/cxx/home/mapper/TravelSpotMapper.java | 9 + .../cxx/home/mapper/TravelVideoMapper.java | 9 + .../java/com/cxx/home/schedule/QuartzDto.java | 20 + .../java/com/cxx/home/schedule/QuartzJob.java | 55 ++ .../com/cxx/home/schedule/QuartzUtils.java | 47 ++ .../java/com/cxx/home/schedule/TaskType.java | 6 + .../cxx/home/service/AnniversaryService.java | 18 + .../com/cxx/home/service/AssetService.java | 17 + .../cxx/home/service/BillRecordService.java | 28 + .../com/cxx/home/service/BudgetService.java | 23 + .../com/cxx/home/service/FoodService.java | 37 ++ .../com/cxx/home/service/JournalService.java | 16 + .../java/com/cxx/home/service/KpiService.java | 16 + .../com/cxx/home/service/LedgerService.java | 17 + .../com/cxx/home/service/MessageService.java | 9 + .../com/cxx/home/service/PeriodService.java | 18 + .../com/cxx/home/service/PlanService.java | 21 + .../com/cxx/home/service/ProductService.java | 21 + .../com/cxx/home/service/QuartzService.java | 18 + .../com/cxx/home/service/SessionService.java | 7 + .../com/cxx/home/service/TaskService.java | 14 + .../com/cxx/home/service/TravelService.java | 37 ++ .../service/impl/AnniversaryServiceImpl.java | 65 ++ .../home/service/impl/AssetServiceImpl.java | 62 ++ .../service/impl/BillRecordServiceImpl.java | 158 +++++ .../home/service/impl/BudgetServiceImpl.java | 88 +++ .../home/service/impl/FoodServiceImpl.java | 200 ++++++ .../home/service/impl/JournalServiceImpl.java | 57 ++ .../cxx/home/service/impl/KpiServiceImpl.java | 58 ++ .../home/service/impl/LedgerServiceImpl.java | 61 ++ .../home/service/impl/MessageServiceImpl.java | 70 ++ .../home/service/impl/PeriodServiceImpl.java | 104 +++ .../home/service/impl/PlanServiceImpl.java | 136 ++++ .../home/service/impl/ProductServiceImpl.java | 76 +++ .../home/service/impl/QuartzServiceImpl.java | 112 ++++ .../home/service/impl/SessionServiceImpl.java | 57 ++ .../home/service/impl/TaskServiceImpl.java | 58 ++ .../home/service/impl/TravelServiceImpl.java | 197 ++++++ .../java/com/cxx/home/vo/FoodQueryVo.java | 13 + .../java/com/cxx/home/vo/JournalQueryVo.java | 15 + .../main/java/com/cxx/home/vo/KpiQueryVo.java | 15 + .../java/com/cxx/home/vo/ProductQueryVo.java | 16 + .../java/com/cxx/home/vo/TravelQueryVo.java | 13 + .../src/main/resources/application-dev.yml | 6 + .../src/main/resources/application-docker.yml | 6 + .../src/main/resources/application-prod.yml | 6 + .../src/main/resources/application.yml | 36 + .../resources/mapper/AnniversaryMapper.xml | 41 ++ .../src/main/resources/mapper/AssetMapper.xml | 25 + .../src/main/resources/mapper/BillMapper.xml | 164 +++++ .../main/resources/mapper/BudgetMapper.xml | 37 ++ .../src/main/resources/mapper/FoodMapper.xml | 147 ++++ .../main/resources/mapper/JournalMapper.xml | 19 + .../src/main/resources/mapper/KpiMapper.xml | 15 + .../main/resources/mapper/LedgerMapper.xml | 25 + .../main/resources/mapper/PeriodMapper.xml | 22 + .../src/main/resources/mapper/PlanMapper.xml | 42 ++ .../main/resources/mapper/ProductMapper.xml | 55 ++ .../main/resources/mapper/TravelMapper.xml | 138 ++++ .../cxx/home/HomeServiceApplicationTests.java | 11 + mvnw | 316 +++++++++ mvnw.cmd | 188 ++++++ pom.xml | 34 + sweet_hut.sql | 625 ++++++++++++++++++ 277 files changed, 11116 insertions(+) create mode 100644 .gitignore create mode 100644 .mvn/wrapper/maven-wrapper.jar create mode 100644 .mvn/wrapper/maven-wrapper.properties create mode 100644 README.md create mode 100644 admin-service/.gitignore create mode 100644 admin-service/Dockerfile create mode 100644 admin-service/pom.xml create mode 100644 admin-service/src/main/java/com/cxx/admin/AdminServiceApplication.java create mode 100644 admin-service/src/main/java/com/cxx/admin/config/WebMvcConfig.java create mode 100644 admin-service/src/main/java/com/cxx/admin/constant/FileConstant.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/AccountController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/BillManageController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/BlogManageController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/BudgetManageController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/FileController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/ServerMonitorController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/SessionController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/UserController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/controller/WeChatController.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dao/AccountDao.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dao/BlogDao.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/FtpInfo.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/file/ChunkInfoDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/file/ChunkResultDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/file/FileInfoDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/file/FileRecordDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/server/CpuDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/server/DiskDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/server/MemoryDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/server/SystemInfoDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/server/SystemMetricsDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/user/AccountDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/dto/user/UserSummaryDto.java create mode 100644 admin-service/src/main/java/com/cxx/admin/schedule/ServerMonitor.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/AccountService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/BillManageService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/BlogManageService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/BudgetManageService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/FileService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/ServerMonitorService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/SessionService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/UserService.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/AccountServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/BillManageServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/BlogManageServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/BudgetManageServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/FileServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/ServerMonitorServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/SessionServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/service/impl/UserServiceImpl.java create mode 100644 admin-service/src/main/java/com/cxx/admin/util/BlogUtils.java create mode 100644 admin-service/src/main/java/com/cxx/admin/util/FileUtils.java create mode 100644 admin-service/src/main/java/com/cxx/admin/util/FtpUtils.java create mode 100644 admin-service/src/main/java/com/cxx/admin/util/UploadFileUtil.java create mode 100644 admin-service/src/main/resources/application-dev.yml create mode 100644 admin-service/src/main/resources/application-docker.yml create mode 100644 admin-service/src/main/resources/application-prod.yml create mode 100644 admin-service/src/main/resources/application.yml create mode 100644 admin-service/src/main/resources/logback-spring-drop.xml create mode 100644 admin-service/src/main/resources/mapper/AccountMapper.xml create mode 100644 admin-service/src/main/resources/mapper/BlogMapper.xml create mode 100644 admin-service/src/test/java/com/cxx/admin/AdminServiceApplicationTests.java create mode 100644 blog-service/Dockerfile create mode 100644 blog-service/pom.xml create mode 100644 blog-service/src/main/java/com/cxx/blog/BlogServiceApplication.java create mode 100644 blog-service/src/main/java/com/cxx/blog/config/BlogVisitMonitor.java create mode 100644 blog-service/src/main/java/com/cxx/blog/controller/BlogController.java create mode 100644 blog-service/src/main/java/com/cxx/blog/dao/BlogDao.java create mode 100644 blog-service/src/main/java/com/cxx/blog/service/BlogService.java create mode 100644 blog-service/src/main/java/com/cxx/blog/service/impl/BlogServiceImpl.java create mode 100644 blog-service/src/main/java/com/cxx/blog/util/BlogUtils.java create mode 100644 blog-service/src/main/java/com/cxx/blog/util/IpUtils.java create mode 100644 blog-service/src/main/resources/application-dev.yml create mode 100644 blog-service/src/main/resources/application-docker.yml create mode 100644 blog-service/src/main/resources/application-prod.yml create mode 100644 blog-service/src/main/resources/application.yml create mode 100644 blog-service/src/main/resources/logback-spring-drop.xml create mode 100644 blog-service/src/main/resources/mapper/blogMapper.xml create mode 100644 blog-service/src/test/java/com/cxx/blog/BlogServiceTest.java create mode 100644 common/.gitignore create mode 100644 common/pom.xml create mode 100644 common/src/main/java/com/cxx/common/PlainView.java create mode 100644 common/src/main/java/com/cxx/common/ReadView.java create mode 100644 common/src/main/java/com/cxx/common/WriteView.java create mode 100644 common/src/main/java/com/cxx/common/dto/StatsChartDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/bill/BillCategoryDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/bill/BillItemDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/bill/BillRecordDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/bill/BillSummaryDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/blog/BlogCategoryDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/blog/BlogDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/blog/BlogLatestDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/blog/BlogStatsDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/blog/BlogVisitDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/budget/BudgetDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/message/MailMessageDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/plan/PlanDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/plan/PlanStatsDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/task/TaskDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/user/SessionDto.java create mode 100644 common/src/main/java/com/cxx/common/dto/user/UserDto.java create mode 100644 common/src/main/java/com/cxx/common/entity/Account.java create mode 100644 common/src/main/java/com/cxx/common/entity/BillBook.java create mode 100644 common/src/main/java/com/cxx/common/entity/BillCategory.java create mode 100644 common/src/main/java/com/cxx/common/entity/BillImage.java create mode 100644 common/src/main/java/com/cxx/common/entity/BillPay.java create mode 100644 common/src/main/java/com/cxx/common/entity/BillRecord.java create mode 100644 common/src/main/java/com/cxx/common/entity/Blog.java create mode 100644 common/src/main/java/com/cxx/common/entity/BlogCategory.java create mode 100644 common/src/main/java/com/cxx/common/entity/BlogContent.java create mode 100644 common/src/main/java/com/cxx/common/entity/BlogVisit.java create mode 100644 common/src/main/java/com/cxx/common/entity/Budget.java create mode 100644 common/src/main/java/com/cxx/common/entity/BudgetCategory.java create mode 100644 common/src/main/java/com/cxx/common/entity/FileRecord.java create mode 100644 common/src/main/java/com/cxx/common/entity/Plan.java create mode 100644 common/src/main/java/com/cxx/common/entity/Task.java create mode 100644 common/src/main/java/com/cxx/common/entity/User.java create mode 100644 common/src/main/java/com/cxx/common/mapper/AccountMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BillBookMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BillCategoryMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BillImageMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BillPayMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BillRecordMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BlogCategoryMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BlogContentMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BlogMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BlogVisitMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BudgetCategoryMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/BudgetMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/FileRecordMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/PlanMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/TaskMapper.java create mode 100644 common/src/main/java/com/cxx/common/mapper/UserMapper.java create mode 100644 common/src/main/java/com/cxx/common/vo/bill/BillQueryVo.java create mode 100644 common/src/main/java/com/cxx/common/vo/blog/BlogQueryVo.java create mode 100644 common/src/main/java/com/cxx/common/vo/plan/PlanQueryVo.java create mode 100644 home-service/Dockerfile create mode 100644 home-service/pom.xml create mode 100644 home-service/src/main/java/com/cxx/home/HomeServiceApplication.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/AnniversaryController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/AssetController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/BillController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/BudgetController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/FoodController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/JournalController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/KpiController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/LedgerController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/PeriodController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/PlanController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/ProductController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/QuartzController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/SessionController.java create mode 100644 home-service/src/main/java/com/cxx/home/controller/TravelController.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/AnniversaryDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/AssetDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/BillDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/BudgetDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/FoodDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/JournalDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/KpiDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/LedgerDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/PeriodDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/PlanDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/ProductDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dao/TravelDao.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/anniversary/AnniversaryDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/asset/AssetDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/food/FoodMaterialDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/food/FoodRecipeDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/food/FoodRecordDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/food/FoodStatsDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/food/FoodStepDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/food/FoodSummaryDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/journal/JournalDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/kpi/KpiDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/ledger/LedgerDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/period/PeriodDayDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/period/PeriodSettingDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/product/ProductDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/travel/TravelRecordDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/travel/TravelSpotDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/travel/TravelStatsDto.java create mode 100644 home-service/src/main/java/com/cxx/home/dto/travel/TravelSummaryDto.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/Anniversary.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/Asset.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/FoodMaterial.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/FoodRecipe.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/FoodRecord.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/FoodStep.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/Journal.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/Kpi.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/Ledger.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/PeriodDay.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/PeriodSetting.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/Product.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/TravelImage.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/TravelRecord.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/TravelSpot.java create mode 100644 home-service/src/main/java/com/cxx/home/entity/TravelVideo.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/AnniversaryMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/AssetMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/FoodMaterialMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/FoodRecipeMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/FoodRecordMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/FoodStepMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/JournalMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/KpiMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/LedgerMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/PeriodDayMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/PeriodSettingMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/ProductMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/TravelImageMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/TravelRecordMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/TravelSpotMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/mapper/TravelVideoMapper.java create mode 100644 home-service/src/main/java/com/cxx/home/schedule/QuartzDto.java create mode 100644 home-service/src/main/java/com/cxx/home/schedule/QuartzJob.java create mode 100644 home-service/src/main/java/com/cxx/home/schedule/QuartzUtils.java create mode 100644 home-service/src/main/java/com/cxx/home/schedule/TaskType.java create mode 100644 home-service/src/main/java/com/cxx/home/service/AnniversaryService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/AssetService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/BillRecordService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/BudgetService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/FoodService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/JournalService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/KpiService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/LedgerService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/MessageService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/PeriodService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/PlanService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/ProductService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/QuartzService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/SessionService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/TaskService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/TravelService.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/AnniversaryServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/AssetServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/BillRecordServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/BudgetServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/FoodServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/JournalServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/KpiServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/LedgerServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/MessageServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/PeriodServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/PlanServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/ProductServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/QuartzServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/SessionServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/TaskServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/service/impl/TravelServiceImpl.java create mode 100644 home-service/src/main/java/com/cxx/home/vo/FoodQueryVo.java create mode 100644 home-service/src/main/java/com/cxx/home/vo/JournalQueryVo.java create mode 100644 home-service/src/main/java/com/cxx/home/vo/KpiQueryVo.java create mode 100644 home-service/src/main/java/com/cxx/home/vo/ProductQueryVo.java create mode 100644 home-service/src/main/java/com/cxx/home/vo/TravelQueryVo.java create mode 100644 home-service/src/main/resources/application-dev.yml create mode 100644 home-service/src/main/resources/application-docker.yml create mode 100644 home-service/src/main/resources/application-prod.yml create mode 100644 home-service/src/main/resources/application.yml create mode 100644 home-service/src/main/resources/mapper/AnniversaryMapper.xml create mode 100644 home-service/src/main/resources/mapper/AssetMapper.xml create mode 100644 home-service/src/main/resources/mapper/BillMapper.xml create mode 100644 home-service/src/main/resources/mapper/BudgetMapper.xml create mode 100644 home-service/src/main/resources/mapper/FoodMapper.xml create mode 100644 home-service/src/main/resources/mapper/JournalMapper.xml create mode 100644 home-service/src/main/resources/mapper/KpiMapper.xml create mode 100644 home-service/src/main/resources/mapper/LedgerMapper.xml create mode 100644 home-service/src/main/resources/mapper/PeriodMapper.xml create mode 100644 home-service/src/main/resources/mapper/PlanMapper.xml create mode 100644 home-service/src/main/resources/mapper/ProductMapper.xml create mode 100644 home-service/src/main/resources/mapper/TravelMapper.xml create mode 100644 home-service/src/test/java/com/cxx/home/HomeServiceApplicationTests.java create mode 100644 mvnw create mode 100644 mvnw.cmd create mode 100644 pom.xml create mode 100644 sweet_hut.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea7f1ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,35 @@ +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/ + +!**/logs/** diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..bf82ff01c6cdae4a1bb754a6e062954d77ac5c11 GIT binary patch literal 59925 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

dy!05UMhSKsK zV1FiJ5SlAhkpcl_H0wRzql?0Qp5wz72o2cMC@utM(|&o0ZO_JpXr+N7l~F?Ef_02md^m|Ly|(EN; z%;)3t6SWt{5hgzszZWS1v^AU?`~Rctor7%qx@EySW!tuG+qP}nwr$(CZQHi1PTA*F z*Vo_ezW4q*-hHnl_8%)^$Bx*s=9+Vi%$1qr5fK%c+Hm4kiE$B;kgV)wam25w$Y7#k5$> zyB^6k3i~L_6~PX554`c3Lxx;&_sT;I^U92G@fS6#(Xv!B%;H3+{e)1R6lyU)8AK1_ z?@>F5H=sXG=ep;kDRZO_ofS}`Jus*Qp3`_V4v~&b-RQ=t8AN5H5{@!_Il~0 zZd!-aH=h)(7CJ&tL%%{P{6d_g=5tsj%S3Z!QxjrLdjoKmNP-zSjdJ!?qL(UMq38ps zjKSz5gzwhDFA;5md5yYb>QN)U_@8Xpjl4yw5065)+#MSGp;yQ*{%mt>12;$~R{eVV>o|juO{Z^ z^o^m@DOBrE2mm1nLgBfA(Wi=X9R%(1UYZcZJ!3;*bR^smI~6lyn`O4BOwo-STsQcyodVA~leg9`{=l(qDl@DCM>s+w`%S_q*PIjYP ziuHHuj0VVW1%+TH*lx9#-$^q&l)G_ojju-w{# zVs{oOc>_fcS51xY+19tN`;V~R0wVyuxdkS|t zC}~Gtu-UyA{H5~6*ocUWM)RfQ076mL1r zFVWV%zx!_*zk`5&dFbdq4nbWxIwAu=`+$V-`m<*-Z*mE2X|>OCAJVV;wlq0E$hVe@&x7V(!xg1*;%`} zxxBu5;jmZEH*e!Rj=Mz|udBR8BR6LiGoLWb<1=<14it;Fuk$6=7YCR&;F+%r`{S6M zP92W>ECy`pZR$Q<6n8Zw1|uh*M=zK=QP0b38_aX#$gB^y>EahIiUzy^MP1ct%UhZX z>FFLVJ=H`FRSq!<_DtWyjLZ6t^Nf|?<69Aj$U0*lrAJG0{t;t8Y^SKLacoR%3EXw+ zDi5T^PkjmJp7@B|$lkEwHHaQ7BGc$})@qNRqk4JH!(bgPM!{Mb&Kz|UGk?QskODW5-NCJ3`Fbks<}%TsOB+e{Hn1i7BP z(XsKkfl`r0N)u1VqaPYGlDxR3>%y{&vYaQCnX8AAv8h8>a^4<#jAhtfa;TdoFlN=?Ac{@Cdxj{YI z!kxobbr?~GU8JKwH2Ywa(#i=Rzof$nu?4-zlN#QJflTO^QkyarxNI<~MY1}jy~Jz` zBRwV&0+G01D9biQ4PR*1NiSqTXZB~NdI6yVEU|AiWJYA>k9G=*`R^VFjr{jhqZ$&G za0#huq)Mhb&8oR!jrv%;xRe@b&PWBXh7ATurhUY7yobngzP;($8b5g z9U{5JMt%fMp(N6ZVGsYa2p(#ry;Y&;GG(DG((_GrS%r&waWuX94*RX8>&x|Lzv8WCaXaWo(3FK=U@G#S$8kCX_R6q|VO;WbeXk~x zmq?NS+S2WfO|{j{dKy5``SRA!r+%)`DCW{s?8uZJW{-4%x}KJzAtiyY6b#)!fe0kA z)=W5C>X6ZLRFH_-$)Z(B8Hr}FD#FLGum2gRluDsrJHf$do$r!ORQqrI6~=-H0vPiG zC2V88MIp?Xhc&UnIS(c)naRXTu-r!%x0J;3uWjp5K%!b_v$;;T0*{_2txs!*+BgP} z%eY2;N7AFz(g@fFy&(hWk`R9#fRZ&X598A7xjHyoDJ4!3CK{Grr4>0bTBw3ps{tN7KqVY^)~B5St2NQS9wH_Lc=s8$1H5J?52_$nh z+rnm{F~bVIsiCZ^Gy&eV*X9JTJZB^`|6F$9|Fq@ekZKP~h_BWGsow^hUpo~MCTrdk^1B;= zNXiYAZnUPm>}{vX*&Yb&{0FNvW!V)h-<{na1yT-|kAkG7xU7QA-NAc|e4Nf2`OWnV zxbr6@^wO^6xW+Xdu=Z{sdK+Qw3Dii+X&Y(VdCv>CFEIOt?MCM?9@CDUKm7+N>%!q z$WI;(L@2YJ&Qfwr7k@<77r}%_q3O8c#><<+(JFdeT2?e+nsP4h+`n(HuX8^8qLN88 zv^9`|ICnNwS^PYDf7ebCGG~QNosD6-%$5;6Yx$`PGlZVnxs6ntftJW^L?iy3KIBDW&1q;{OspV)`a4w`+K45XmW5g6HLPL(lu zM^>HAPux}=ZJ?|;f=zDh!2|)WLyu7pHcc)9vAr(R_-sI`3GRfExjVpYMgql~xox)Q z)W3=WFT93oMdC)bluYO{cphI8Hjl&)W$TKN(PAk2r&mB9-)@%@xbewYx!c z{}phewJ939{qT;q&KR_!>>XnVYPC^kRaX%+G_v;*kg4g0jdi&G2G5$4#bk+*0mK8` zie_>y1oDA_0hGE(n`I(s0k(P&;*KDaX278vofbbNMZ-&1MCmPD*6d6oN$VjMzpTd@C8e zg81s83_+Y#T;duYQ%tXE$RWVk=@P5Z1VY<1C?mU)7?G9IHYx#rHCx1Mhb!ajXBoJ-rANULXqSAu0Mn9s%@_;uy-AOG|5#jDZ3j5dR7|< zR_{f>x5E@uRa$=rDD-yel$t(bf5=#v9ZWObAu%fou?4KkV-kvjmRiGX7iDe(Q)_^=>m}`2$#Xi#5CpJTi#5EF1T1mmPB}c@A6ou~a`>sHSeM4gF(ksh|DObX#Ao1r$Jp3I3 z-#zhd+d&)DO54E0K@@kKgxRB5%x&3BZ$OrawIi6~b_kN~$5G(kH6b5BD&%g70UWu6 z-ub`EccvhA2YleM%U@;V)N{Ixrkd0bjN}m=kn%!g%wE&P@WcBs>5NJ~t}y$Ar7F1n_=iC*<|&`C=qG#+ z0|)?s_kRK(@&?Z40!~gQHirKa2ua%+8CVNj{J7LD3|*Wp?EV9bZ1_j%PH`5U;9>aTZzwPD=a zXur{4zSk&)HrOFOmSK8ZKMHdg*HQk|a($OZ(0puje1K8EZNjPavWjhh64i-B(p7Zf z2g`IQ_W)I`lGa!LCabrDUSVPmGZbVX*#xhnAH|koEn~hs`=w;zVM^IEU${9oXf4C9 zk#|zrR`2_TI+u08MszOoi%H;viD}|x@Ax-{F_aW3ZIQHw-pT;hgNi%weuhcB7xt*kubK4fep+r)eaJIl%p9|sqv{M(E4lgwXe=HL2nYvO$$HX>QpPxqUn}WG zs*l{rztHOO@k5#cP%_alezmlZW9HCcT_;auQpbtV(Kh6e(9wF`C;OM(L&uqUaFglN zk@mRfKGV716J9j|zU-6W(m9pmEF&sbiZMv*M3~8lC~<@%sH8mKCL5zS4h--)TNbi$ zGT~m~}sa$tL(& zG_GBAe(+OZUY}-iY-rcb4f^fNZt_IXS52F^MC6>C?-IuOUttpxwVQBy0~D@|I1g*pQ^8D9@mu?5(kge3_GjbOm2G+7-z zkx`X#L5jF0+(b=RSgOE*XGFk$mF562Yft^UFH0micC5KNH~tfuDq*ce5Q~fKPyieC z9su^F5Df-F2X&FrZ1?<8uQ5h`uh~m z=&m+g_sL;h^%^JcRk%COiklbyo`Co8z9C%hj$&e+^pKMm>7Jt({+@)$DJbC`QjMHZ zi%3X-hLW4Gca)8|Pf3A1t4Ud8Gcj`ZNDE=lz<+3#C9z0jMR_q934+6jFXzJ$uCq~+ za-#O3p1hSU;tiKizC8=Mh@y(Ne3L{f0B?%ewopC*gCiXqueXVpGg9HaGK>hK#}F8++%^d7M6b=5@V(e#PAgrUnD^4)b1JPZ-PGNWqckW?kadj9w8b7f zp6l)!4JIwHtcBOekEW-B`yJ(E6n$+g06FFIjgZzz&+`UpKdgY-=lxNe1BI|=Cg;T; z?FYQs{*)^&tV>xbx0m~jf7l5>`+q#>!*0u^UJNZmE(3w>j|yNHB$#6zkjE;_0pL0S ze2gb)=zGHVUt5ge;3k7XmZcc5;mh=#z-ZobkM!xX0De$bw@9s|&m~zN9 z!K5tX5=4qA2sK|$bdVMz5etUdXN!`}2PL8R7qLr)Si} z!IONdCg$e~UlJ3u{n50K+;kj7SP&tC(^xDUbl{fdvL#ilA93{7Vm|&0)1p+nx=!XmT2qv6B?FjPHZV*SamC-ro9lXMAbWtsPx?Xq1Kcc_^$@r-YuI4|#Q?})HOyhMfBUVTIsc4Su?*`>kGqVs(0tbI_r0@mbv4tR&NZCQd@%?W!R_Br)qtk^~)!$ zd{bZ$2k_tV&)c$dz%vTer6*=naysJcAnpE2vboBzhwzL3ZZg^xE_1)_2eUw2B&FcL zW(!+zg@=0oy{=sCi##j;)Rn!Ty7I5A;QytP@}FjBaRXc9p9bUK6(&VZ!%ayA`L8Y0 zHgiu1Y%~0(WC8`wPF)OYDg?-xhpK#kN37I*3t$V> zeFT`E`_n>;_dQuVYN1PBmZ_}9TfEcl#^=`Abh1!Ek&ykSp^2 zUtg|J2l-(Fu4-@Z^fZW1~i@QYwP9Q9$d-lN6U6i%K#778wN;pE7`?CIfN* z4j%4F^H^LF6Q70%gi@GEB7#Kar{F)1=Hjc!yt?q2&-sWb^&Mo@Ali3 zYsI8ugwjs$rA3@sca{d2=a5mZ6PM=U7R~l1{udpZzpk<&^i)W$IV*$FUzyJ>#@G4l zunDZP3O}4G8=e2)DEXo;q|ooRSY*pQ@?dPnSA%LBmzMuh zj6iCX{hWsksbMQPykb&WEA^2^)4$ly11z>xG12rAj}?8Ft!(tswaOoNlpt=|kqrTJ z&?vxxBG>4bNn(%_w*|gVh^|*LD_=TzvKLX^EG3#)_JHhIOGSwPo4|0o#`B(-!+g_f zebxHKe=60kQz4i3=g8Q=o!~GyJjpp(m|JFSl$~J?ocx92m&&RUW=F?w)i?X8sjbbg z0+7xvpM&&Mvk2s6TEQh%-l$+wW+-wwx(yPsAW>CS<4@5r)9$_e^l&p0?yxh8t`Ni| zvkg20%R$9KD0hWHDff&(!UL3EXA@7RAORZg2_v!tmF`q!lSi%o$>srm>6H|S)B^2X ztV|vT66Q&WzEYv3LCrtL@fFVn_1u!3AIwvi9c5g^-LY)$kEOwFcdT%;T!@=Lh3b{K zJ5DKC5TfipAQ;Xelrj5>A z=_T7N`9+b0vmdY_zM3SwtpmRY?wNX&N^VG?5}z__+A;qz)l|ZX+QaujvNXdiXZ(V? z{OmPo1P@Yd;$G3ic^NHAm|1j%cIXFahDM~236V%gF?}nu9!H?ApHB?XA?IZs*m$xN z6e^ufgCQ0+_=81#=-f_IGbvy4Xizg)_Q^<)baO)G5(DO zgxn}JpKET9(UqMupTD8jB3cp z4G`IGH%ByG7iZ-QD?Esze`e049rA`qU8-l!$qPyeHl#z_q%CNdv(L)XI;?Ng4p}qk zjkLr}p4PA1I;7{Kc1WJp_Y!Q55JqK#sB5nY)=dehb&d)~g=roafxSw>Sbm)`xVXcf zG#`10jAW<8I#Nd!Q<)M`*0YE;dZ$(eKex&V5$dNnGAi-clRskp_SX#aKy?8;Y^RA; z@xEcdlr!iVGK@89*}AMBb@T}NL#V3*a00ErFr0GKMbDa2oQ-DkTV{N0Y_X9!nY1oWN1B)$PK)1Hfas5LPvtlH8ZL@g6sQ;=~> z=vTK;Y5TAt=ya36;hG?pES_n__RRVv!qlpCcy$N%vN$cm%p@=41Lzl*;2C>KsLXaT zT7L{$DZI@k7u*!SE|y2=Df|?99>gyrLB^ur~Y)vi9TpSJl6Z57d+o)lQAdh`R5kMGB7)eE`*Q;2G zQEcRN!Q?$b+o zUoag8iRTMmKuJ)5s&zS~S*B1~zU7tUT|q&h!EInBeZf#vwR|05>zpU0zRe0VWg5C; z+*3eGa6)oAS)jk-xN&bD5&{yx=Oh{=T<=akX4F4Yue*V0VM zkH4;7TLKmx%@)s6c5z_Q&5qaRX;$2vIP-ud)H84PAd0uJX*ee_AkeYKVtI6CW@W(9 z8KHRBux28|zpfOJu7mRVm*s z%?_&|3rLG%MZsk-XuimeAl!(zkxHX`$uQhJ=7%bztEXtmw!ImA{G>b$_T&F%g zFsQ^s?i59_UX8n_!c>ZltM6ABcMHOtRyrRBB3#Yo+AYyiYjPIXgd#0RF$%&xX*?+- zsPtBuy)cPjVkYkf31o50Tp3zUe-dekc|5FYz`%%l5L^>Pje2fT{!AGEHxWG_Yi|{!_@x>cc6%5SD z$ZvA==C5j@X;L3MCV!XA?SG9M0(T#83W28(9aS(t{d&siNAR`PZa(ke>q+Bbo82ut zvU5xmnR~F1ffCpw7|Fg1Gx@$)QGYDzf$|nfH3sKP3=Huhz#4)dH-ay~7cR-ML4hxY zJC3AyNh<#3hBqDyFFY{D#*eE*cnh{slzoT{|2On)ATR!sO#t-^ABA9?$(s~V<1UDq zyo>|Hc*Nrxk#`IYFkXaDTnoHWAP3E#`a^&-`SJ1RcPRHkeTbBZ&q3G_0==kIKNsi8 zPK+SND@w;5@(Jm9!|;LDkth-G0@RZYW&YJ3k={qg)_?xtrkih&RnY!V zo$Y^|7$WW_MlSzvW>1PbggdqghA-L1jCJc$kjxUIfuHEPj zLAS_=)=>DNjluF!EIspf<>8IN^gzw?ak~<)+k{ykeXo%GE=68f$Z;ZaxUAiN%zGF_5d-JZ0I9JZ*6=&gi*5l3i_WA7VrU|K{v|a zF=S?&Yw?$7*XrNDug-5bH}qO#ji37gcoNsG74BAO>OHL zJ+$W5wVs^^UjrNk2QiwyJ(aXP&FiHZNvXoDgPCs;lE0r3q^E zb1QZFSr@``4tbojlnOSCOUjP5QW*?2!?w1>p3YwB&Mp*GO3M*qgz>{jv{ak$b7(E?tkY*+R+^&>> z2dO%o%W=L!QGyw(WuAnw#oO{!I(8KwC|wq_y)<9lMxDiZwL#OlUU_DnD8&!tX&a7f zewQGgB8{dwkjR8EC%AP&bY^iirN#jA47*}#6?~g6@a?%^7(){yv(mgF=P`2yXr$Ab zuYEY=Rw^DeYTFZ^Ywa=6!`PU?q?O*FI=gFl`bbPev2k8T+=C;_X>sLJQt7BpOATpg zrpfyxa?;Uc`KUT2B@@q5dI0rCDDr{Q8d~En$h%e_rtAvjTEMd-OH%Qc7)o~}(R!O` z(i0MG6N^6LsC174qc^gK-0ayYDy1n5!q9mg_|@<( zH^wGhrdBV;Qzf}LA3=l3S|l{2(ylqgc3&K7pj~tzGSA`-wO86b&05pv_SO)Zw_hfmjx}wah`^|Qo(J(X2h!rc zPxx05-j4zshLMr@l7%0`IwPtjmgCwA{Sxj^m0H$vopZOcn-(l18gE{v?!K>bbY!=G2sL;OsI!wlS zl`om0y?Z#6@8vtXFRh`e5wNSy>T)H41%)Nt*jt9t?c#B>nBknI{Kbhq*5+Q8Lxe_H!J*!N? zH;Gr-bx%ExZEmt^9#)xcGN#!|?Xz6|l^~v7U7wM4&5cAIxbMj53pOBXW2LxqE#=+s zUC(EG;8)Odp&Rd)Qg_wrCnDExg_o7dmilm!?}lv0f5NK>w#Db7WRQa5Z94pw011GV zyHnjESKowJ&H%GT#al{iWgq|S`7S)99~4MXM?gl`=`rD9WWj$*)*NbWq$x&Jdq^ z(Q<+*Sx9NqE8$^Fqc(bfoIHwRM8##C@jW61>q;vG-*gk8G>_$;P+4b&%lQGl^XQpt z@48~+y!wp4mqN@Q?HOZ!Yr_;kT-E1R!Dz4OldNG)t;&2^&}q?~dMa&r60E7E)}#>< zrV*SWbim~#un~*J_!+nsWF_-x*9gTk>Hl>g2f7!ZQCMExX9omA0+-Fd%?Ek`^u5Av zTse2a$3`W_+4p=xIbdWKo>d*OlH=zIocE<>kNpS;Lx`OQ&-Q1P$CASxn1-0~RGYd=l#b>XT!xg+7u%F$Q7jSakj)eTa>Ty2qji4Eb4HFzvHy#qP|SXp zeb#Lbt?Nt*I~QuZr{s3Gk%GGcNPV5a16K0EjBCtb^pLdk4E5uLHP+1tY@v3z5hntx9$Vv0Tj2xkovNOuQz_TE%+7VTio)we=x|p6Zw6woNPx zcG_Z2O%BbGxfe9ld2ol=fLGR4aFV*%y*3D#mSjOJI|7z5B4+&ACSoxT&RK_fuBkxk z1Z{D-MxPSpq+f$DN!oyle^-|TkMi;fqFJ1UGd5NFA{AM^B_NurnPV??jj4yDq`QF! zXQ%rlV=SedtGKM5GccN+LZ_zY*nRh^QhVnOGA2jgF~DjqY%>eUXu}5pt)p9N9V|0Q zXC@$-8kj_9y)dSR&f2Q-S$t*V60-4m5IfeHAp)(*?%V*RU3YRI+fVm;XbrN;Znfre zHV>~Kt<08qOPU*d|3s=CmW8uaSX^bMnclwZa0*-JYD_xdlH-9QSVqCTFRD6%n}VS4 zy>uY+r9H8?BwSa;PMf%#`x7lDq2Ra&?)MJ=q&X-Vdw3kLg=AF;bh`Ngu`{SU0AP{2FA1bXzI)&Qc+N zQe2V^EkBDVUja~}gLyF(bfSN%OWm}6u4HUH3r`v7TIiEzS4!DYc1O$+O(bDf_b(zmfoP2*iYBPA-5lKMee z{!TLNugW*re`hye;8u`de34Z~ks!!LT7(P~?WfwY)j%M(rRlsVfY75wv`_j8-f<~Zh@@_No5u3lgB08$gw3J7t6YYm|-P>#mI z?Ihgih8w9<&jhN0?+L@xpaZf^v}|(+(B!Te$gx^{k_-y^@xZ8pvz4Teo8$&XcRy}gCz)E#b#7b-MxVm-OaCXYoKRhcAIJfQDELSMoUPZ2A zGJT9WYcGs3O6S~oE52|3o?hBGjTo}Z^#p~Y8HA5Pg?)uzq1dK9(?}wqZwRa130=%H zYf~z=E0yYqfTG0fyWBEMhY>h2^w4T@H3nLOIgGoExay2GP9=7H+(sF!>QtGs1-g&W z_gbac+_K^zlCn7G0blgrvHCKoOxX2B-RbMlZrJ;wg{CYdkQ}uH=vCz{^XL9b5MT@I1LRLBCN2G_*J_s4ZGh zWx7MbR#kfA8X5^2SsOa1ssX$FKr+_smpYMtr_8IC^|BTXp$X~a|@aOR`r7XM(DK=Ni-`62A>;$AvH z9_f{d2&YCRYk$@WOzak*c~OoAFfe6f@DJQ(UOb0(1s-V6+8}t zM%Y6TDbM(n0`0~e(Z=fVgsQi^OTtAv{cQHYLACfn!I5^C`4kt?8a_m$6 zbcTozSL$v*0uQgb2#l)xk-#q3kt{M?g;oWD0s&KKtKIf|mIluc_x>!Nn=F(UZhmoC@MLVWfWf8%A{!LJ-a9ibm(5(&roPX(GX)q zd@M1x1j~Z)riLkJ6l^njEwFgGs7mySZY8C9vkvltS$4KH+PxmEb7GD8$Z)quJ$36>!5YC6H4?tWLx3jX zL_~2klDHUK>j@1}T+ZgC#@^9#==euU-lRuP-UC^5Cc+L8jCGOV7-{#UL(6{hSs1p> z-8|04uLdI$1?;BBEEg_BTk#KN4^e`X!u!4==E(^tnRt1KV|!i-9k}i*QR9@it-?e5<6jq(E{}G5amY*n+H0gn_Y9 z-8;^pTZ~?CK_9>Yi%5S(q=#!=vps#u3bpC*N25|FGH$TQ9Pd_4r2%$YW!S{i=_C!G zD_fX}hHLaDE%xg_fp|i?KbzndD++)5bCZZKr8}JL`2AxVDM>tTh|-T>%j~EB_}}&( z|K(H^a5QtVF|l}x|sSOHm@dqAK_|9T*4ARfIiVq!E1 z{?^1IHFL*xX$M4a3Mm5YU!EpeD1oBkARcKhJu}}&7N2i-A0U4zc4~oNFEZ@*1*d{J z{!TQ-;$6U&WxGgOjF^lV^S+fK(41yMfFZe${01$COSKm>OdY0Ko`nRwC?nIcv5sS48^fobUN+7gD3h<@?TK=U zsq2}1JqYJDkDjs^)6H3!Y^(ni&NTu{w6vfAOZuc(I-NvUIA5QH9(Sk7D2hx zNiT)h!1lkZYyV}v{?Q|*B<@K93LuZprFU9Oj(?x*`7jTy!&B9yOv zBC(n=8x!WoL6TsFoU<~Hlq~@JoFJC(_I;+4<3?2gkpWZU!T~EWMF7v*q|26`QcQ^K zyY7tY=WEzh-Beb}LTZdzTqsr?>f%%?W^OSKq2qcG1lkqAukEF_zkk$u>XCWe4? z#Ea%vy>ICg-GEoSljel7W)-xQqU;Q+>#pyscZDYnsvo{+1MT9<8T4`~uVdxf?M~|B zynet59NiL z!rIjSxz;b%7{vy1l_G16WSgRE^<nid77&vHB`Hc!j_1F`ZD`0gi18)_8?o51 zU@6a|ci)iO?`1pg1#z@MGaRt#+VAApkLK*L@84Osn8n1p&wayu_RhR=UwwK_{XRd- z@_u3Wn-N%#fS{lWoezfKS`U=q7T4pO{SIjeFQMNZYxLGubs&kZYA-$P^!^hNiAC_F z(&Wq`HKids+xS2b*p4AAYkL|*f4oYA(x!rpT&_C7K;2ZG?{}K&D<-FkT@)`3VJ0Xb zH#wfssnie>s1svHRy7r9dzwfw#yY({tYB*1nNx)vazVXK$6z6(v#cyYmxjT(-pz)Q zmT^!`Ze~41QiQ(6|xf}+@C5ZNKgKywZ9F6&s&=xLzP2GjAv3Y0oF|N9sQ z)#f|e$7y6jIc&Qc}%ut}8+Yq?|zk-iAB&`7zddtXt^a zODQ(DgQqHOTe)pS1jRV(Z4SSYxFFm9bj`YffOXR_nrFrf=Pmfr^F8?NXDAH)RY_IJ zia@*!T}8>IHGTVN@d71~NRP5^{UuSEQBA;iP@E>vHBrii=Mt#3LM<}6v(uCW8I>pj z)iuPfGO41XkYTVm86?P+ZI7a!bu#F#q8E#ld66=_3qe5(7rwYzkyP1Cj<^O27m+O1 zqSOMa#3!)|Oi}&%<#TTC!j#90$`EUJWnuAw(DgEXbdGZ}D3-~lWKfV3CT06jARCpc zgW3?!cGxC<4bPFx>G2K|pQw6%H=mDNJ9f0i7Z9 zM9Op2T#uZC_CRl%l}%9a`x8xq0TEG6nyJmw%8@N+>W!pE-tgq@Th2AO(m( z5h}V(JEs-EqPp`)cKevppHePn%`Qoa-TTm}v83nfYu{=X)eka!5~;S>wiZ9KJjMq6 z>Fgx8lpK|M8rEmK1%a_jTLUsb8vpPoSY+$7N+_;3vCrkzy8E~s*E6qfhheM@ zrP!Wm9FgoRV70zMFupOPdouaMx%rka;9iusBffkukbq&Oa!Av$T*C5wgjUDJqJ6aB z(?h;NzQ4!^wA4Jl_hYZYcSg~3H}db;N0wk864a3n*J6lB-nb)I+5y2n+93^b!`=_} zy?b!&O*YX7-^{Ztu`4-1**M4EM4h_wU2-D?C}Aqy5ML7Yl@D#`Ppq--or&5LPqq_} zTx|N&G1%{D- z63FD%(!Xv4BFxTlU%s)bFl{J%a)l zqbCh9*g7WHB#?5O@r&ddY*myj&i_IQQSRbI!%jx#TIh8Iq)wt}a5M>>xO${;MLFTF zQ_O(@DdX&)d|+07Gko>hSrJy|%;=1|&mC?0hPHtn%4a35agZa4ED#_egj-4`fBqo0R#9mQ#BIn&i-6N6{L`Zvuc zhVM*t=AS0*G3(^>#-9WE*H7jAAN6DZVp#r5)s#1Ibo$Ty%9LoC$U%Pi5WROaGDy=C zPt+z^E_YxBba`ZMfei{n!7?uADyKFLcYluL^~1#!m1QqvZ}0E6J}Q3>QHVrfykO_w zv$|82jDqR3+Dr8`t0^fspZL6W?}Nb;in4>0ln_bv#S{!mP!7LHENN-l=~@%6ujbu+43{~BuZ zw^SLl6$KJ<_cuxbNb7Q!O0hDnWC6M4;8A_GNy9bkmdF>;M}Dt+#2h+{u6VQ^>0eSK z?k25<;(Ths!zu0AKiM3QGv1%~7fk+3?IroYB0MoYk(mh#@FSK8vIjI`ov_bH&I$oz zrLZYtsUQX0EBOWR#C}5l3RW{%Bo}~%2(30eRFFehtEwIkdu=PDTFFsev{oQPGaF9N zLO7CGqMw|o4 zXEdacLL>~Z9Q8;+O$?#CmfUc5aG9?YnHuPISSR3nZ8JM_D8dyb$SQv2-HWX?N}@nm z^pSjPE?!b&xN4pT6Iqj~IYUn!w~x*r*YJ!DJC8qDd%4PPqge{1d$*@GPtr)Wz z>kkUX_B@U^7XN4)%$HV&YAuDsY&6oUGVU~47&0HNr6)8$M29v4AHrT6Y7amNwe@2$ zMSs9J#(B)Opvkmq-rs#zH^A-}z<5I6p~|}zU3FOP#3gE}fPLjmm(O>k5}KVb$R=n4 zvES$OqRV_LtbbnFs2e-~T>F$+Tee&KFz1vD>C`sQ)TI=mBR(H3_R%|oh4VtiF3Lw_ z7tdE0!H=H2f)&ytAwMlWbDnuG(ULf9m*DTI1h-oaT(SX8kWAje29U8iM_5m`S?wCh z|2)fTcQ|>_y8p(TEt&BeR`_UPS^SO_Aw+z!Pzmz)2I2q4*o0Z?4L!A|{tFwR-u=j9 zsk_AMkBW&!9LF;X`vOexf?OkPMS?qF1or}T8%dvO4jne0W%dkm317^C;}z8p2F%50 zC&$arDGBdTWteETu7-Ej;`Eo6}jy1~TUaAs~m zhhS2-ZEu)clw!Zg9(sfvs-2Us;-4ssADLua7E|t`zlU(bj*`I2HTml-oa)BD4e;6x z#Il6qrF;-Y&tW8D@woFayo)8iO4hl9<<`}vd|k|mufrz)`$@MDyYyXLUZ9H^p@Jxe zn3mtSIH_Iw3x1|2Uhj^WaR8u^ISw=>@4vIf@UM=kjX!9O{)a6V`2W#l{>NGNfA8Xd zH=IuY-n}iVHvby@n;Z4Nh6Epb#M;g4i74tF_sb-Rd>-;(kwu z!RK#BjQOW9?`I~}#+8PwCNmj9+V$-8Ece{>&Gqh|xAzMwe+X%;d4~ahM4=pFn5%J& z@T0^41a(ePmuQCKNZXc45sKg7Sq99%CmTnsy4$U_RC+C;tYjWEXHr!g4%MNwS8o=t zU5BBC4m*jkf0GUk%P;RA01A1p(jYj9Vw|c~O0{}Vr%@Vn#JfdxEAB5UcKs;NtiXs5`3}FZBK{*S)g3 z$55~%jX_?tZ2!@XL*pbtJ0W!BhNlhcAlYmd__dLYu$LT3VyZdB7?{G*%+mk){+zJ4 zs;d!SlV0vINdFQ8yIDmbS|~){ZQ+Xl-0nVjY{WBZH5Ok(qD#50@k&HaWJ=SGQjG>sw?0g%xYX zo)I%5ZHB10EwcdHota@yKcn98pHZ*azYhpLLnCWD!~gxero1VS zp@{gsIoVg3UI+zeB3s%p_gfSf;DeNK@ONMnGm*)fS&4SKAx4v=6GM980?4Bv)-VW8 z#%=F+UKG0m8qZe7ZTAh#?Cr)Tq8}KQ_&S>Q)0X>H>+#1=Ija73_V>pJg^y?j*~!oY z-dh3EgHGCh#cwnQaC#T22>X=76ohcssCz$4SzkX0OcV~A(0xas~l-q|+(dlYU+po{VjMHA~h+?A9sV>Gg8pemGtgwQ5AD<1!^m1fsM?$4U=Pdx_dA z1Vdd^{^<QaRq{WW`$q8N+3kYCzjK`3k>V=-aI z24Nj-l1^-9@jCMfs_jjagNd?f30jHf$A9_`|w#Lm3Kw0)GM{<}zxR z>)9>F0>Hl3fVi{#9s@Nu0wh9jAuXw^`{pc}oS@tT^KC?^x}q(lC%Kz#g8xDh&VExs zNwY#ntAS8{_V% z>+5d(Cat43U!n=EJ35}M^%!aT7r^byL#@M=>I%4i#Ns}GAERjzpA-XOl0L$U&V?$O zU5Et*b(n1e(Qj=l+Kt#miKG*{HUE^I6ZIRiZkqVvq{2)w$2r|dfN{q6-d5PiP=H>y zFfj3n#fJ%9Wti#CMh3gPv`;=Zu!_H}OdwcEN1rtFVw`_} z_Z7iZ!2v$7Z1VH$Qo_SQ#Tns=?5 z`x!jNy9?0?NhcNi)A88qo3M6Dd#sE$?1>im5Hw1V3NN-b%$fzwzRli)mN1NdKEb(pdIM^yv_VSLm-8J|0?3wwKx390yng>H+3*|GL-*W zhqW^PVcIsjKMvvlr>9Td{6EOHk^L&Om4yV2S>uv;W9x#II$Ugm-=BcL6@dv|(oORY zX7m_FEQ`+Ch_@gwICp#EKsW=&-ti&EPRU}DiodxpG8l}z?0>$@*Qfn^lwUA4vHp>T zn8Xuty_)qK^|cm#L>NdIiWn4-tCFP#ErT)SiO;BWj^5g|5=@2g>;78mCz@MVas?|7 zTw9y_YH6PE62ZarIw}?Se;E~U6>#}oDb;e5%H*HjJ*!+#%z=w@6J{Q%VSe+1aY$-A zYiu2F<=VJ^sE|Gv9({JrR4pe`8$PwHv2b13V1af%!1$s2UkY;kRS;<6g!xUC8O*#Q-fj;-J7t=$q+gn)jXnj( z1wxL)j~-PE{e9s9bfni~T8*~RgP&P!!_c?gcR8}vTUg>9en5>d&RK=wqPzDm#gp4$ zj01f?E#o{t{#5aQ|3r&h{ZwH5!#4lnpFjQM4u=2m&Px?_6-;NO@5vh4aaz$4;+Vfo zXzFr0t(35F%ut&_KV4xqqT+;eWs@}=fuc#Njz-9FE@W#<@0CnSrHbWCOXB6BNkoY5 zx5$>A@1ET6XYn+j+&CX^rNsROBZnuWN+;2(HE>lR0 zdt+vO8Q`bJK=B4C;yF_|RX7V=U2w9SiCA@8{v$N4F98y0ULq4>-vfwx=hNc^ke)jP z=JtUX3@51;5GL@pCPIo6e?R{P_1Z&Yh~!3;`{l=LI!TdT+GBjnhRsd0E4$?t(cF!z z4~#=v5NNe=^9uQHzBg*}*h}OJs4&Oz+O9l{@=ma&6>15fDnS3Lu zhNjlUH_tu4aG8~G#M(x%^W-&-9c^k#MVC8F+(@<=A-S%`Ub$W?Fc$Kt5+9$Idch*` z8DPZGrrDga&I@4J#R*`!JUMdw*O>xdJluM;2O(QyC6bm(|7=LXtOMpeK2{Oc%&@VGgIM}n=xPTsHZu*o|%=ydsHI*DGc2AD4b$rWMYr_F+cj(?lYu$Y(d0;`Gym zsVB+o4{0WaVAxWNLo&g-2maMO*qGgJH^Fz&7= z2fEolQG2QIcl}C3QYX&n7uJjBQw?>=S+N}$3TvDBB4GzLg zRLYKx^=)OTX4DgErJ$67t1~NTT)b{xDBJpm-PJp6oYIFy>k5yf4es3Dl0RBGlcl=6 zkeqZGj7n2lOVEiD7>~>izlNL*I0?~Dk3B&I=?k3@VF&JxNNflsY7~FfIS1h??ud;d z(DEysJz}!|k{hFP%wR_V1vv6eo}VD6bZprUiHm6Oc!Z({ZoD1T7?|r-)XyP$bG-Kk zs+K#Tcp+0iFn)Ojr~N=xynz_nO>QaMQGRLk!77)=oI))vu#!h&Wy>uG*Xlp#{1EDy z%3$r6jdxpHLNJIgSmO)!3NMHED&BdX_<))Ch(?8pE>b8Lyn%w;OM+3lR+y?QTQooRsb|E)Y+ibYPpR&p z6s+)b!X(VTwzS7+!HF5!N~m_e9HxfjR~m1(1NVhmD`i`y54ph*TuOHuB+7D#w|bn^rs6qM}j4>u88m-909 z8Qn378h$ehryt=81-d2(punML3ZG(*KwecJa-AGkfNPyvMS%^{9mNgCm4!IL&HC@J z^l77MMF&_St=`G-5)v585Jn?7Ln~EA!8Fe_82Ch>P0PpQ+VT)sB9MB@HR@Z3(I;CA zJo(00bBCDqE0P=Q-p@S%iEzyp(jhvEEnkvBeitFmh~)w7kJK)2IQLuSThcG;t;19m zA}y3r+ik(BUg}RFoeS0@+Aw!O=T#}{7vd=KmTSobahGQvS@-iPF`2(zEWZ|rcL;+h z*A_P95X#6hgKb=iO8R&>Lx(@?U7Hnbcz{}VWQ+Y_<#T}WigYMJ>43m!22#ZMp5gld zvjS`{o;AuM{G5Q_d%Q8HaIyEgX^dy2Nw)g^$op4#@1uRb@iKc^`0oDIN}!Mz`O)-4 zeusYO!vEkuT+-Cu{)g`VLl%DQ1^)|Es7&0Jo|i!!?smr5TtY%458>ez*n}wn6hK@k z`Jf#NB}A3*Xpcyjt>2`!1o+JMh!McM?KR%_f7^?f=04Td*%F0@2j|n!kd%~Ws5j%c1tuc1<14SI~GT{=5FRz6U0JD0S?LmuiOd&*a4Hl2GA3j*mk~0 zHG{zh;!{+DZUTEyhhE~-I~nx~s|gCSu*A?HC1m3($CYe+6H9wDyGls11or9(nytJ| zd*-n%2D@K`5fS*rJ)?+*sq?mMo6t0*6fGywY7RRNIp4Ub#|f4Kahsq^&@5tt_sEw0 z6$tBs!r=*u#H5mic33oSM;v_oggvkemK}+&k^{?7?z2fqgf*5IzCiS_fY*Gr3UPfh4gBdXY(XjrTV_9xzp6snGzFWJz6*U5Ae z>b#^$8`}Oa>Yx%)Z5Ua^{d@1j`9<3&2(qX3VKiS|pK-r78?u0jI73d-73h_vE*v9^nb#_S=Y|+zY*z1#s8FFs5YJ2SHfgyTzIL#sp<+tP{L67dQd6i78rY* zPo1dBFRd8bfj;rLUm!egc@bm@LV0>{3_0s5RelFi_9kbtHD7z!KV_t9cYA;Qp^bbc zltWd_-A&ujR6b=W(!+E`0+JwY$>sB{$|=DQjq@`FVnLG&nzyoVm#wvk&sDJ%kUz$< zsz`N9uTKBzKyxY92j4VNeFI0ST2*<$kTnW%H&05Zz(!w3IP3>SMCedaI4A zV!|4#j{auL*KY|)(UQMQZG@D-G_i}_&nIGbPs1fosoM8gw&|v0gvu#GWiJny6dkAA z-tutWs3nWft)s%3*w5>H2Uz2q{mj;TB{`%`((Z0bgJ@|&bigU0=wieD!l+jHeA2opi z+<@NBOcX&dBF*y`WU)wDjBvt|L{|-1lJPd|sI&$C8(Rp_U|c3sZXHuWY9QX6;iwQ@ zLl)3S<^&wxggq*BjIn5v)~&}bg&vOc?VbThy}Qj`JF9KRFi;(X#(;=Vy)XB6dBV3J zDevR#SQo(;_9_)=xm+BwUe=4x19DusZ;98PG=+T`ysxWBjg|D)oYj_G%rpHZl7LV) zX$v2yquc{&c9dXA4Uk6IXmP8L=$*(MyP&AihZ^D6zu3_R{e=R?eo&(G zgA&1i|9A5rl>F<&q)_1>d>FMGiksGIAa&&UH3jzB36t8@&K8KuOPGl~Sdzxq8MLok zG>?S8p?u(Vy!;k|@2}?>b17=?6)Ue>Yv6hw&-f2<^6QYo2k0O#M4vuP>vh?m3~FAs zWF|jlFeAtn3PM((0JAqP$ndl)Z#OhZ5y~7=^E}9~1p_iy!7Z70a`oMBSE#o}pjLJh zVTz*5IIgH$C%LtC9E*RfOV079G@4(p_z1lzvA&$?%4XRKRqv;AP-^Pnu?;u+((h8i zL2LgIFjx6Cw&tN3x_U7nKUtE$c!a$9$#6D#qZGn;&uoa&U&%^Lp(&%yiJeB8xx|}Y z`tgF8XP6d)@q^wa%SeIAAnL0Rk7uuKv@%S~4y(V+fD5CQP@ZZivy)%ess1v}K?`t@ zQuF)fi}JY6u72#6vftxICFm+nwzg$GCg1zMT?(U0_l)Pc5!=B4LxEJS4ns<{gO;!< zXgw`8Hc(F_hbG98bMbG9=a+QL9r8@r^6nI{s-;H15v2MGagO#T9zUH9Ae$D7YdLjA z+b+6rUT1u5x61&npD`pu?-5155E}FMJ^B~@Z|iSJ|IA;1n~6ymKz||ax)GgDo`@H! z=P1HkG53^qWlx#xF?6NhQERNoVoC3Pkt;yj{nM9isXV40D1&?jp+)C!d0N7Z~W~jmsBwN~D`fatRBJZO#*%k>!yjFS^0uKVbnUJd2Ryq$#3wPIxJfZVqJ{k&L&9 zXGCBQb4AEn#6de{voh66ZgSnUtK&f&3VPU`{pLb@%fxrO3nm!q)B}6PdXBGvSNwRb znYu@N!ldSa(*GSjg59@YnmN^50&QLU~Q;g};bg&FW1uN-D6+(tiSj13|*jaU7szS?JO%dg{la; zsYTbJ>S51)l`=Ja293O0qU*grE{>~Vl~KEju8(CD)=RK6c8wXv=Ry{0eQY>gXHbMs zf(9?Q^CXoZo16h3k5t4ol0WgU@(59J#$rXL#!T$oiR2;)m5l~P=ou9rBG zKW3L*?Z8_lpgc$u*MB}N{M3p2H4S>dtnu8Y?ig969?)uZXiMBkgy{rwyvHX{IwQ*1 zAaq*bEdCiNur{67aksM~O|G6rDQ9Zva~!a|*~U!cX7%1NuGu&KR{sIq?_r_$D%$FK zxv_K6f~%Io%g_V7`)TPMKhqWVq~k!XKec!HEiArL`92$v=|=Fy{>{a`u^4b%_X}@F zaX=)3VSRhobHA_OLU51xa|m;}5)1(E>KAu5Af;kUL_1Q|j#ePnvNgw%f9VT`kTto~ zH}bUvD8g--TZr)D%6`~)z-4bH@U}GFb+C$o1;du}!_&pT=wTNZRcmcOcPPeBVAB6U zApYkL{b%<4&!DbQ;Zh1g7M80S$3itpF5HI{9ABip!2*Jmd?dIe6pq(l?`GSuohd_}1NBcI-LaLWPNMI*u862C=;tK_$ z(n&p`Ly#LKfE1kWXOo8=oF9Zma{O61Y#!*hdweURwIrF`@}}l=L)N;UYbO*a0={5B zQUPPZEY(0o5Osk`nMW4tB5m+6q$f&l_QhIa+@Wd8uwM`_ByCMc5C*DD%?Pb~C@-qq zcUh(7rHYZwlq0;NNurHgAibV_8IBFj&GvdPGrx4aFyXuJ79qf40_xr5Z*&bu?vUHi zrL{iT&VA80Zh;VY{H%tC6_8BZ({o_1Zv)FXq{4b}9w7xB9s!AIEI+J~1?*I0z!gqC z3xG=tIMJp6tvi@N)02M3zh-%m@oA)pc$rU1H2dNhDf8U~Nl`etmlVKWe5;&7d?}X) z#txXgpFv;o;ZgP|?+G}GT#aCqPZCeLfh~{RR&(0C1`nBj>JD@+Yd*Zipb_W7Gf&dR z5V2ZWykWs2WOT2WZg=R5kzfX%oX!y=y@3yCsa3&v#Q~(KRS0=IQG@~}1gL_Hi9MPT zOb$ZvS{D{a8pi$b?0yjmst@Cz0w#;kwov4k0bZp8{{js0aEg`EA7HHgs5Ad#3jY5h z$|y+wcqmZ4jM^{z+5*F5kf?I-8xU8MX!ONG3S{RC{6wKbw}R+RQPww&oWsAMXvhap zt+d>3e}@taRsYzaJdD+4Db3PcR$O_GT)VSUS82Aly#Lhr7-D^DHL6>UFAa!(Z`tDH2S}%#z)&5j#_v zI%kw=H*yBO2=zB(wjZ=7X^wI{0z0=}w?GQ@HU*|v+fE|{v@1JogpFc!`~(7k&3Q|dsgmZW#r!!e8PcYLjUy34;4uRDf z9#U%h>|eU(4V1H2NwYq^1oLj0j2<77JiF#IyodH-sB`399Jg_m`T>J$i9NBqF_T2| zyC&(TTyrJmb{i;KT(J-dQ+S^>oT@Y3lhjgdc2vlbcOEcq*0q?A*6wQ_9vQ>{0LuDb zZRZ6M1wCSOOxa5#T1c;C9jdqIy%R@%1LB=aqoVR=;61$~LOOqq4|2q|NfP$om`cza zxN$MGnK9`qf0*4Mo_0+=CIO(it+Jy|&3OL}#D@u}0H~9Qi!g9G0v+R!Lxh||kCi%P z(<{KR{57SQLKrXLIm6Z6l& zc$4!0Kzl;r(d}r&AQ6n@8xKsH{QdVC#Q%mnNLtVTh4tKLwY8B;`=gfQktp{QX3*lp z`jUi_(Lx+oeZBQoN2=!c z*Zn<;PjN}Bi2kG?u(|4nb8Qp|G&Vaa0zF69U4C+aLaW{18t48hLP};2qUR{TriE(( z_nufef{Tz|-WBOp)YCQ zAo-a9Tr1n4nZc&V?(4X#(kb*jw}?4Yd6IXU`Uo~-tv&3WlZt7X=AE&j>pXna8_WF7 zu%l%hY6M+wzY%r-KGIFb{7Rh~U65B(_(#e9GL)8hnJqlywnCmU+XCwELaE~6}7dR^0< zmG6o(Pe~FJK>Sp-LmmQ_Y{Ny|<%<-BV3k!?K4k7SP4Ui}8v#G&m)pT5%^uHxV*AOf5Z3mFX_%v@} zNJoU0h@y`^L0CQPfmGf{+kDXi6rb#B zHBK+?u?~L}H9l@Q&SWpRuHhg?M142jRAWZ!52aHNiFbvJ8aIyf!pst`fjGf5-6-f= zwb!bz9W=``d@FkoH4BPMZw#@XZv2wK9l1@uAviWs!4QCw$(cAyCaF|bC^_yq$P%7Z zu{nCX$L?(D3Z0;9JzjM5)QOA}SWlpp#I+9B9jRNo7%=6RC*+7oc@0!e*%D|r3Xd&G zl(~xANHEg(s8pe8%^PLPo!Pq5z$A2(dTpf|bb^>)2{CN|a^v@|NwKqqt4y zZJw|xD>_7omTcgs+u=xRHk>B!XurguZl!#dFd1?Y8D;e#LZ6?H0EVS0ayB!QtN-g$ zcH%6hKcDnOkn3A`eE6n7uz(m=Q__Lq7zgQdsbNhgsPy3#m~(CooW9}SsSp8C3pFuJO|^k466PtsDJwZU4jVD^=Zf6c$sz zJx3=tMkj&d{`&C7jN}vI;f;uc?!x`X7yFG4w_mUx-5YG#Gg~Rqd!M6RXb^Pvi z%t2y}>Hezt%l@$N_n%u|v#*jgp3)OuAYCVJJ)n-Lh+21Y{5( z{EQ?{{yV5!#4u$K;;=zlSwb&nd8J2pr6J!ak^wTk~#7Pug_Ji~W zzIeweDy5|82Dy0Q5*14Ejdd$Dj$?r03lnnPl=5km%95RA6a~DGO6YZEuqdOgUaFQO zu4U~)q1@XvD5O}+Z-ug-R`dp$p%jSwk9xHvD07!%0Tc#7cqp%hs;f4&p-QVcZpkl( z`ElaX+Gb+m8b%|Bzs)6CF9b07oG6b5{^&0|4*JL1*mI&oIx`Bew_lWCMGHW+^3k^T zMzNXq(UD+64Ee8TSm5)lC^r`p9Ug|pAbz()b%^tO2IYYLF!PBtzZWsd% zvISKmColu+(}g)1pXXz_g*7c$hjGX{Ga7|Zq2>!uK?&*K9$hJ&Et&?ekLm>0lfgUI z4MCYovgLTSV>!|vG=YIL0FMldJtyfX3?Oyt8JihgBD<$+&SSv@nW0}+4f^>V=?Jex zISZFs+aFnEzB3pEbC_uWhcEv`H8VLSZ#J!#o;EbI?WSGIwwI5GE;R)DF@be11NTRj zkL(pD$XEpP#a>4CVoAC8AxU(M|H*%J8Pc*TD%d;?W4CO2VlbT3e26X=rIpJMW)||t zBtD;=S4a_foJ;IY*+jQH0n*l_#f+dqI!IR5z`tP>Si>@8Uo<S{B0)7%2v-7I!k$kBpHTmCx3?f$ z-V45|wQlS}4y_x{$ax0I*8%XXm3rf9hzemc%s^*5MWkUflo)UxE7I_{PCY`gk8D7? zq}n;5q%8X6nvMkAp|ztEy>0Vq?p3_-m<;NH90_JLIdb`iwJGs})O^2~OaVug9$s;( z1TZ#2rV}R?B2&11e18F2sxI5*ZBPkV_iN@8bnk)$Oa^XTk>TskAA@lF)Y$Wlk=8bD z^~8Br&7r7Oww1+Qove3QT|**)gcG2hqNcwNmx zdKav4mfpGzC$czs#!CmON)5DFpNkY2Zp|nDF;s7?)6KX+izo--brmr3100TkLCV3NKFgNP zzRDHL-TM{8UGWvFl$e9gDvqs1tm7e8r(%k}m`Y@=_?SSB!g#1F`AJPqV30|!=_t#h z(Fz>96BCh@xDW?bmtWDKMo`x_sQAIHQw8-0=%M6^dS$u~RhUPwsr4pG9c@snMx#!v zz4g;^nRb;#+41L~7pu1BqmOog{Kai+aTtfhd#kjHA~ZLN2kB_bi;KzHjR#|?NgMbq zDtE4{hNCD4;Yl8%E#gLcPNNlK;#P_4h`pCd8+gw2kPiuIy;x?#P+wJDc1lF@JeRB@ z$Q|W*vmy&|?Fno9LHPW%3srylO;$JUqKUMV+^Jr}>;^sS*5lp}0mQKrIH+7jfcj1_ zg+s$)`O(~+Z5M1?oCRX%$?t%xb;lIl73z~;%t!lwX8%D0z6e`q4aN9(@%@&dO|W@V z;++@g`9#rU`e;?9(L$G*XN(8Bx}*DJ_pXYD$X;RIbq8Rr%D=?B$lobn(>RSrmZ>`M z-l<&a!zIsh8VZC13ys|@+*k?NH}m`AtVbM^IEkd?ryM$Cw+$2q#>N(Yi)YDlurNR8 z>WtKfeX;c>G{i;QZ0iQAs5v{=VT)>lsdThblcv*gG3QgFQq=PcL_cL3UQ$N(Nxf4R z4mK|YaaoT7B+@rRIk94fCa+#z8pbv>GA{?k6IfD9Qd$Y`8?O7`P8u?l8Bd@O1+~5F zk3b}KkS^EVpdSt0anCSL5RrJwt8hsKk+@l)dZiqBrNB~tHz-%_@?V2tbD~Rua0hn; zWoW$_b;r;ONq=)Qf5hY79~#b-t;BQ{x$wsnqi}_51Z!v z?L4$6bsRH{)NG@|>9RUTPPU;ONhxDMcV4ew6>^FOq?dPAiRxB-ce;+K97R*jDvO87 z%8ORzfSUXc=Fjj9(@u|Z<>=g^{8`_qMa2JjSc)TIdA9;7Ovs|WIF^2?5?@bHmEE9n z?$-A4c@Mu-|KO#O;O7Z`a9q zxJ`0HDXm>7us3bPC>`CLNegu8cx_I)SX5V?5VP5TcLnIIvESG{2TtKQ!ND(1UekCl zc7Z~|Rf=E8iPbjA*?%a-$`REL@!^e6s)e9S6@+6`78Q&|uy3@IdM-hfL5b}12!>@7 zfi4+{dXzwG`c-9RA($`Q=dT2GyitLcY8XS@vZwkO3Ci+XqErPHx&*hRQ>k!PAe-D( zKu_wUU(Mob>8;nnjzNB<#*tzzfAQ<1dwkKY{0Grhe`2(zv-PHPL9cVv!zUYJW6qGB=2E|tUuu!j*P^h z6A5wz`(>$mvRL93>J%R=#xIxH;;J2358v*)8^Nzz=BoGRGwaZ{3P8dA#muN~;kYDc z>n7*>Wq6krKp{owp7p!m9-g#sJ3KjP8~sZMC@ntYOMBxNs?=;(gUT<86<6XlZGIJq zmjh$mh%uR~bHRQ7BgV^SsjIB;v!HL`s&hF=eEGq3m?O6obVrt*UTHzU@Z4X z-?+ybh4+k#yoVF~sH@?!)5R-q4Q|Rswd5kTiVN*bX#f!fWUUvZ%G_8Wh_-8~Krz1T{UZn5L6|icUfS5@Q;jk& zVuJ-%WbUU5U_BeB_uF?JDo7x^y#3+W2V|U%!@mnHH_HruYy(upytxuSII3PphBQALx?9`yvjWq z!{rDyhWNr%9n&I}DeE;wT&`j5^IrP1xa2A;y)KY>>7rzO`p2Zq`2~9mCr27&C9Y}$ zfx-Fm65aMd-EO3PxIP63dL05*oaG(80iFDGhV@zm4jY1XbsMVt3-+Lk$CYS|8+hS& z8-%Yo2Jc~sPn4sx_K6vo)bL^3@`#>GdT8enLM_X2n`ng{EjEy6QHHDJ@!K4W-u}5j z;R82L;^tjjS9s~0wa*aDf%rR1PNM34(^t5xCC6U85Qv z#9;JkXR1$G`yyCjQMyIG)@UwUJ-!4f);oc9t_(w1yln2mwLz7>DA6+c{VHy#uD;PW zN?W=wE0W_bC`8(N-?(lFJxtjI;7k!>)4VR^AiV>FUDtB2%X2l;BD&j^t*Qr5y0^;) zw?b0Lo~#FTBRnG3aNY;OfGPz$bxA(;DSs7~`8HJMf(s=V$pp@Z>o_eid+dOnJS&Ua za40~9C)`k?Zi>!KS8xnaf9n^g-+oHVESv4eYS(du>_~|A515P|J4yDM=;2 zM0UyQN$}xOR(jHhN`2J1+j$tsogdDId=a1G34kCCB(G4k&=$@;>O>I|B>>^{_48Sc zF7goM;qdlV<~?UOte=}I&Ji_tE;=J>U=Zsh&qu-Rdjs0a+UHRgr^ak6plCe6KMeF@ zJU>)>K~p3`ao6e%LWVNsOi6dIjRmGE6I-(kifp$A3{Sw{=m9-@#~)7C{Vyvh&i?kDsRp06ZX^m-c+W=jeJ^p~r` z&+tq(N2?f3FuG>)h|bl(t=@I?$kxS)Nd|=ilsIL(qm|b|;aqq@BJM+w07*Q$e{p1b zO-~@UruWqZ<2gtf-?x_M^b)WpXI+Vm9hQZ_$sO<6#&`h%{5IL4!UqK9F4uw1q`lGK z{0=2%_apif(a-9CV}ppmK!6k0&h0_%`)R_3$Lf)y<^B~YGbDr6N0;I?p&eL8ihQ+5`uJtvS zwQtSfbOCxj}B3QIBrNu;DxC)>e6{U)~!hCzoqNp zny3{~n|&&G;_;E;K01dODI8 zgce24dlcM~M_7Q@}Ut2iC8q15dzD=iGf1Qb}_RWK_mU~xGb!Gi?!VX_-6|Lq=cFf7%4eVe=NU9K=Wtel9tQbDhyk7@)G zaj0%HnuKM}X@kYq@wq8P8UR1P)|Y09o!s#I`tXB|@NbghgAV!lkM0-Gs6jjMIJD5~ zLTaM>2S^zW_=`bgY{)EZmpg5NLtngzEc@%fOLn^h?{04}l=FyNQF^+-l}ln;N$hmK zs2B#P%)WyHu$muQ{niPwIQuM9iJKo*_bCE-xZ`Z`Ay@{x264);+4~-3-OIP`T-_`# zcPeW@wg{)zN6*M}nuJ;(iPbyb|6*;C%?G9x{IRt_{!DECkKr)?_lU;ef7!wRXIhh~ z{OXLMjPxZGE}TT-R6%H#QB;~Xm}EFe9!XYu$?iDUVr#}hM9pkPMw>)@R}d$J6`8?0 zlQf6iR@+cvy2>IC8e=EIH=_Fr1?>&keJd>^B{lK96=5)r-aH_DJkfsL)$Vn@#gXs5 z^)|2l3$yQ#bdR)*R1ofOEmCKVLP9=hd%Cg0imbqfWFZuEnWf4A+bwIgp6Fm8DZ5NW z9#*z_|FNv%tp!F_|2^DKvo?fmnI~PCrHkyKxU54iYVWw-r`#WH1%;I6#AaySpFu+JAajI9B6z9S6suF{--a*iU!GEB`hCyV+7663v!t`g(2DAf^( zvqL8QNtR_6sWrH?nM7C`d^aC+_^@#|yt$va@g@GW)5eal`&80|=ud zy3H!oR{ftWnPfWzqfu6(PngIVY4=rTa-mUM)x;s0BB)^ecXT%Ht3tf}4*m0dr!KVu zHuSYNA8)lLcAv_i3|cY6Gmlf87vpW zgQK60L2h^GY9g%N=dM-xTG!K_Ac~xyX35Q)Ff>57LNZBXOgcjz2f@}X4z`BsMOa+#jN$U=Mv3JwNnzIQSVcM;*Z3^E zA{w3pwPu#}T&w5q>C*~S!>Ck;QfkE4_@~-}UTIWF({*R?NVbKF#Tt%?4oqa2m1%() zy5ShK6#7M)xe0fFu-=Hz<HZzOA9QOVm*w#3~(}3Db$((Bg$sXXoT3D=1ov zkfK!s{bCbgA!eie60>QMBl$du2R;Ll3Orz#P0szlxIga=FiAe;RxOO3j-ZZT+Q5*? z6Q|eE7B>era5Jggs7a`%P6Eqn0q!c6Z}Qx?#9q-qP&^E*n=zQ71Rd7O)>QQ;5D{>< z2$yN_=V^VeVH*_*rA`uoo|=OY-_oF8)MjR)Bm6AOLGqg_X~2FldHi{{#Wi`MrnVzD zalyDY`H#%&obRVPCEA+Q3Z{==JPNl2U5QKkReQteUVho+E$bNh{-J=04tckZ#4b={ z#YfY19!wIu2|?Mr#~!MdwAhG$=D?u3d+3Y#ql3UC%v@ma(Y->Q6+guK5nSZ@t8GPl zx0v*OK4X_58bPD7r_r&0b8Ke7bAga^g~lBc+6|!@rJbWB4|#ay?>4(A_g~*E1n;i@ zK}pYZg7p5CMF#s2%bg+NMygbkP)>)A8rmWDUoh6^L%h% zUUA?NX=0>Bf2xpSkG+4hsathn7-sQHVo1_lFx>~p=JvevkF4kt|1(jzakgQep^wom zfv;MAa8fkl6)X+?yXVr&KOyuO2y@d*%*(WiWs2?0ULdr`zIB!l;Q2S1<20 z7k5(g7f7pd_44zx-869ZHB4^e`7ds-q;y|P;N;>sldO2o=P!Jawe8~XL`#|I-*kidTo?f;>AJ5z^yPW zL_Yy?tCFf_94%n=(yi!hm6D8JwG0Jd^AsX>tTdbR>88;CQdLJ z+Iljw44H!snRV~hZ+`*L@|C{R2I#7>_C4}O(DEM*Z}R&T2-zmMU=mc?Isr*%;l2Z6E@GdQXQ zE6yFGUdVB+48dw^#eF9P@tRto9xXw7caarv>W81sy`xkBCuxLSS zJYB2+XzL$#8wSySDztc86VU-1jzEqUjNycoV#A3LHku%J`m6DjMA&sBA%70|xj?F> z$%deE3^iWo4K}dQJT1D^^_tdz*`(?FuPq%TL5j8}E2Sgk6A=q77Ds1ZK30w{YP>p& z#8Vq#UY6HzAXjm1xJI4Cl-el^%?p2>fy%Q1LhYK1u%WXGg+sMSOM7{D<9fHu zb+yr%#^ebn7uVIY#S~TK9&<jqK}aJc*IBTk3GesKj0%hEbwuH<+{l)@|rc5 z-GAQ-{>shxYk_GNTO?bgUxJQ-v*(hd_CtaB7b_}5`75XJCbf7RdWO2IB<%VdjUhYJ z7abavE%-q)IMZ(_rXmIk8F0$b2D^fJ^0L!SFQ5mNFGF1!vnRa4I-tx|iXn0K<@piu zn!I_Zc>>#8+J`5P%s$me=Di=Bw0FgqGs=|<>MNzw1bHV!z{tO=ts#3LXvR1i7b-bB z(+XTuNJdAmk#H8ahCAUo5Qv$Z{fbN`t@EL+^l`ZQC3gjy8wnWDjeoZ~-X)RmQva6+ zAGHTbjm(R?DsQ^~dbshIIZMyjaTi`&a1+4*v%>4I+w4}F5KMetKAu0j2ezypAqt?~ zIT!PzHOjTgtiStX=)^XLORSQ-T8qwJbKZV^5`a2_Gx?9e%J=f;XO4t{e|#d~(b1GJ z^$Gx@Zl~deLFp61-Us0Gwc!6HhMq<4J6Dn~itURCUOqntcF|)BJI97<8wc2{_enZy zpQYA?u{$78y*U+Vo3?EV&0iyA3X^e@^)cYW-}n9(1BqMq&0Wxs1(oS1R!Zdmh#os@ zGedoc|34|qg>mCjeSZ;yrfpDU|J?f7%CZ25%mj+lgz{;?5%t#KjMYM#a!k_dxKL=O zw%h=CknWQy=-0?1w6l62Uw>z^%}<=K-$VSu?AJn;lNsw#0&Zfci4WRjOh7A;3M6@8 z^LHs+(~mJ31E3#i4h&vKXpTNhdd9K~voy6W9!>;Z%1xc&r!$%{6E{rXI9`I4OqQNy zxJG*RRQSJ2I}>;)w>OSYhR9M~LZos{lo*6aQd!12G`6~;m}DQuPLfa|WlLRKT+1|B zveXroREliLTFIIgd*oJ1uD}18D_+jkpnH6Ltk3UzmiN5pJ?FgVd8qGL{!Dwzg4I zc39+X9C0Lx{^I$>^PQTBw{Rf3>3_1Om{>t(y9z0b^~)7bDnHXYu{`Eble#U_&d!&& zqO0muWxsKCv7awPsWYwfe3b6hW)i9BW@9*n&ud8*nVdYs9=}KKc5lSZ*Y`aF(3%ap zE0P%VUey^Lu(i4%-Ej2%ie^l4si4mG?ef)m+S?0RB6Dg+JSu{nl}^7YYktIO@2mXg zk6v{~eslFzn0gh)_}|ncga~)ueQfGhocpp+;sA$J2xw~&(AF9YwKW`wbJkP_az%>tbe^WB+J|Mg2}58P`%3hV|#z$|=ikYS{X?2i_aoWVRqrw4GpRmSYS!x-AdZqF1dN@&?yW(6tB{}(slgRUw^dojogkv5-xylMbrrR#(P?LBG6U_1d zQ-8r#_esbnGGsqz-4h|7i~gBpB{xT3sAEf?O&#b5@0H&NPIZ((W9#CKl(AZR>XME` zPb()$5P(&J=uEVS-MZpoOfkqk;1$&rj&6sb^2G1b7ka?Ij}Axx}kXn%#&Ka~=( zBEvbvGPh3#IS#_E#a-6As2n2Z8TwkqN*zO|#2W&)1eLqCc(ck-Ndj;4+eDMHIV!@E z2`}z$+Q+u8`;uvWxbY`D(P8UE-9Rw>pa4WEPe**>A*Ffc}-k zi2sj41}83Yj_aGWadB=UoS))DMxUQ;iFq7o#;?R<_pkho;(Z-2L8j8P^u^D%f+dPG;UpB}sTa&=$IoCtP3saye==&j8<*KzwMwDHF+b<+pKzqR{Y_P<(F0mwn zrcl;zL6KVauEe4gHDhPT>Z@l>wLeSVa>1q*r+G8fesLU+(e^7VMd_Za%hk|*$~GF3 zn(%p#^~OgrCASlWg73E2-_vMibv(SI?cLZI?rTqZtAZ%clOC0It!$JlW0yQ1n#S!g z*z@YiP5%vnB#(n^Cz#oLcZFs+q^eM3S-;B$08#&rD;RZ<<^bHMtZmD^iqw zuBB65e^pB8LmvG%aninJoT`EGDyKd=Wa&3AYvQlr4>f1xEy1lR(5T+zoBBF2uU+0g zDv*2a$^5ln%`9J`F_)uF_lEA&znh=2`?0e2I!uhX68b>eF0xOMaUf^1X~ue9sF|S;^NedDo+GnDO%C+Gy1zg=|O+5EmS8KfwBxOGp^YhWZl9LB+ zoWXCn6}9=cTl!D|ka`B=OG1C=u5GOp{kS!4e_KL!?fWQ3@Ge#H@5XwH z8|@}}^H&;Lh*`Eq-rHN*GBln$7*!&cCq~X4tGQ10-EhUmc2~V$442}#p4}EhN{}hO zt)h1`@j%<93zx6DSiUeHVsA)enh?3KU(twm7ct2hzoFi8Fhz4PBbR4oFYZ&Q$;dT> z!C3D0%&p~^eRAO~HLXDdSN+63B{Q}9X>L4NT6^*ZUtz>@ANBO)j_s3mRYP4t;v;y1 z1J$k76io@2(v=)lQ}ui_yf*ydMmBj?=0@)9wY8RMTQft)j}b1B_xu07p-@NTt1O1- zrP&glb2U2-`-Q`(;a+19I#@FcwNEcG3AfmuF+c=pxVoPID8#uB=m8}g~n(O(fV>{k-yrT z%?ghWQ)IKh$vXwJZ@YAD40G=ap`+1KK4p)Br_1Woavo@T^m<>PC&B#hU!|J&ey|k_ z4nD3pDDgS3(P11-Y$uQNhZVz5N6F>F!h6BZllEk!_MdK|&aPx|cXhY3a?=stT8Y=e zON`*J*XWAt)HGrxwZ*q+Vqa@ZR!L$}q20V!284MwiP%v31Gsxj)?B>8!)?>u^OApn zubibAoVP(51dG%rOn3B)1%o>rsY(~gcHxBV%zHNcGJAG5LXzusqp zf6xIB1mL$bi4w3Gd_OZ<=ql@JspAZdBy`p3fx$rYJ<-5uph=7HP0s?jFr8%~{M}+| zNTO>9R$pfs>diHr8rccBgeCIxUk5pYDmyHW0xgInO29$zSUV$u*HXpl8RB4To$Jl) z{=g^)d?NLZLQw)fbI!8X+h+vqVdLNM)J_c802p356&!dPP6 zCE7UwrwB-(Cm67|{rYWDP!Y8AfYQ_I;43A7XB{1Ynw2%tgXFFTJT;NX#G{D6V^}|d zVDJD7^jm?x;T-)4a6Qv{?DzgRb=^((gMaJ8lLIg#^ggES;cg28O4wNB&wi4wpM0>1vR)_@;4cOr@Ob#+|3e&Q7EJv(^^|?+hTO*&u!_h2Ss`y zx5A)}f$&VC1c<8AQN@#OY^LLn!S!0&Q*9~*T1_5YgpxCYw2a=t(UH`pO*9TnO)F@Z z{`~n3`;;u525tv@p!e>cBQ9@1N1Q-(w^ep?vvNE_t6@CZl1Ngs1HH`dhzAnP1TKgR z&x+=ipcT78VZ`UK6Yo4@10Zu1dFQ^1lLKX#%I7Y+9FjbP)?{2X?wBENh6hH0t!iov~!_g0%`C9z|%z*OpA9f0PuiVfdgO zf~Mpy6+QnL1HT-G5DZEdApC1jdVT`D&y5iJDway1HzLD3f(U2xlZ7~o-yeiq2;Q4Q zs9aAMpu!K)v!10Ec)Wr4NDwHhZq{nR)NJ^N3n_D#JihOkz~zHi5)l;c*?&PH>xu*& VCNKd3JGtOvEm(5t0lFyE{{i--k}m)N literal 0 HcmV?d00001 diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..ca5ab4b --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc59295 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +Ubuntu安装ftp服务器 +1. 安装 + sudo apt-get install vsftpd +2. 查看是否成功 + sudo systemctl status vsftpd +3. 编辑配置文件 + sudo gedit /etc/vsftpd.conf + + 启用本地用户:local_enable=YES + 允许上传文件:write_enable=YES + +4. 重启vsftpd + sudo systemctl restart vsftpd + +5. 如果需要 可以新增FTP用户,如ftp-user + sudo adduser ftp-user +6. 设置用户的访问目录权限 + // 是否设置用户的访问目录权限 + chroot_local_user=YES + // 是否指定用户列表文件 + chroot_list_enable=YES + // 用户列表文件 + chroot_list_file=/etc/vsftpd.chroot_list + 例如设置了YES YES,则除了vsftpd.chroot_list文件里面的用户都不能 + 切换目录访问其他文件。 +7. 设置/home/ftp-user的权限为555! 这里不能有写的权限,否则登录失败。 +8. 在/home/ftp-user下新建文件夹,注意要改成777的权限,否则会写失败。 + +中文乱码问题: +utf8_filesystem=YES +dirmessage_enable=YES +use_localtime=YES +xferlog_enable=YES +connect_from_port_20=YES +https://blog.csdn.net/u013345780/article/details/134325550?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0-134325550-blog-51419630.235^v43^pc_blog_bottom_relevance_base5&spm=1001.2101.3001.4242.1&utm_relevant_index=3 + +Logback、Fluency 和 OpenObserve 之间的关系如下: + +Logback:这是一个 Java 日志框架,负责在 Spring Boot 应用中生成和管理日志。它提供了灵活的配置选项,可以定义日志格式和输出目标。 +Fluency:这是一个轻量级的 Fluentd 客户端库,能够将日志数据从 Logback 发送到 Fluentd。它充当了中间层,将 Logback 生成的日志收集并转发给 Fluentd。 +OpenObserve:这是一个日志监控和分析平台,接收来自 Fluentd 的日志数据。OpenObserve 提供可视化界面,用于查看和分析这些日志。 + +工作流程 +Logback 生成日志。 +Fluency 将这些日志发送到 Fluency,并将其格式化为适合传输的形式。 +Fluency 将日志转发到 OpenObserve,允许用户在 OpenObserve 界面上查看和分析日志数据。 +这种组合提供了一个强大且灵活的日志管理和监控解决方案。 + + +安装在服务器的软件: +FTP文件服务器:vsftpd + diff --git a/admin-service/.gitignore b/admin-service/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/admin-service/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/admin-service/Dockerfile b/admin-service/Dockerfile new file mode 100644 index 0000000..94ced11 --- /dev/null +++ b/admin-service/Dockerfile @@ -0,0 +1,6 @@ +FROM docker-0.unsee.tech/openjdk:11-jdk-slim +ARG JAR_FILE=target/*.jar +COPY $JAR_FILE app.jar +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo 'Asia/Shanghai' > /etc/timezone +ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/admin-service/pom.xml b/admin-service/pom.xml new file mode 100644 index 0000000..1f94e39 --- /dev/null +++ b/admin-service/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + com.cxx + sweet-hut-service + 2.0.0 + + + admin-service + 2.0.0 + + + 17 + 17 + UTF-8 + + + + + com.cxx + common + 2.0.0 + + + + + + + + + + + + com.github.oshi + oshi-core + 6.4.0 + + + + + com.influxdb + influxdb-client-java + 7.2.0 + + + + + + + + + + + + \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/AdminServiceApplication.java b/admin-service/src/main/java/com/cxx/admin/AdminServiceApplication.java new file mode 100644 index 0000000..0c9c2ed --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/AdminServiceApplication.java @@ -0,0 +1,15 @@ +package com.cxx.admin; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@MapperScan(basePackages = {"com.cxx.common.mapper", "com.cxx.admin.mapper", "com.cxx.admin.dao"}) +@EnableScheduling +public class AdminServiceApplication { + public static void main(String[] args) { + SpringApplication.run(AdminServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/config/WebMvcConfig.java b/admin-service/src/main/java/com/cxx/admin/config/WebMvcConfig.java new file mode 100644 index 0000000..bb75df0 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/config/WebMvcConfig.java @@ -0,0 +1,31 @@ +package com.cxx.admin.config; + +import com.cxx.admin.constant.FileConstant; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * @Author: Cxx + * @Date: 2024/9/22 10:57 + * @Description: + */ +@Configuration +public class WebMvcConfig implements WebMvcConfigurer { + @Value("${file.path}") + private String filePath; + + @Value("${file.log-path}") + private String logFilePath; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/" + FileConstant.FILE_URL_PREFIX + "/**") + .addResourceLocations("file:" + filePath); + + registry.addResourceHandler("/" + FileConstant.FILE_LOG_PREFIX + "/**") + .addResourceLocations("file:" + logFilePath); + } +} + diff --git a/admin-service/src/main/java/com/cxx/admin/constant/FileConstant.java b/admin-service/src/main/java/com/cxx/admin/constant/FileConstant.java new file mode 100644 index 0000000..6298a0c --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/constant/FileConstant.java @@ -0,0 +1,7 @@ +package com.cxx.admin.constant; + +public interface FileConstant { + String FILE_NAME_SPLIT = "_"; + String FILE_URL_PREFIX = "files"; + String FILE_LOG_PREFIX = "logs"; +} diff --git a/admin-service/src/main/java/com/cxx/admin/controller/AccountController.java b/admin-service/src/main/java/com/cxx/admin/controller/AccountController.java new file mode 100644 index 0000000..b0541a9 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/AccountController.java @@ -0,0 +1,48 @@ +package com.cxx.admin.controller; + +import com.cxx.admin.service.AccountService; +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.admin.dto.user.AccountDto; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/account") +@Tag(name = "账户管理") +public class AccountController { + @Resource + private AccountService accountService; + + @Operation(summary = "查询用户账号") + @GetMapping("") + public @JsonView(ReadView.class) List queryAccountList() { + return accountService.queryAccountList(); + } + + @Operation(summary = "注册账户") + @PostMapping("") + public Boolean registerAccount(@JsonView(WriteView.class) @Validated @RequestBody AccountDto accountDto) { + return accountService.registerAccount(accountDto); + } + + @Operation(summary = "注销账户") + @DeleteMapping("/{id}") + public Boolean deleteAccount(@PathVariable("id") Long id) { + return accountService.deleteAccount(id); + } + + @Operation(summary = "更改账户密码") + @PutMapping("/password/{id}") + public Boolean updateAccountPassword(@PathVariable("id") Long id, + @RequestParam String oldPassword, + @RequestParam String newPassword) { + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/controller/BillManageController.java b/admin-service/src/main/java/com/cxx/admin/controller/BillManageController.java new file mode 100644 index 0000000..994b929 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/BillManageController.java @@ -0,0 +1,58 @@ +package com.cxx.admin.controller; + +import com.cxx.admin.service.BillManageService; +import com.cxx.common.WriteView; +import com.cxx.common.dto.bill.BillCategoryDto; +import com.cxx.common.dto.bill.BillItemDto; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/bill-manage") +@Tag(name = "账单管理") +public class BillManageController { + @Resource + private BillManageService billManageService; + + @Operation(summary = "新增支付账户") + @PostMapping("/pay") + public Boolean addBillPay(@JsonView(WriteView.class) @RequestBody BillItemDto billItemDto) { + return billManageService.addBillPay(billItemDto); + } + + @Operation(summary = "更新支付账户") + @PutMapping("/pay/{id}") + public Boolean updateBillPay(@PathVariable("id") Long id, + @JsonView(WriteView.class) @RequestBody BillItemDto billItemDto) { + return billManageService.updateBillPay(id, billItemDto); + } + + @Operation(summary = "新增账本类型") + @PostMapping("/book") + public Boolean addBillBook(@JsonView(WriteView.class) @RequestBody BillItemDto billItemDto) { + return billManageService.addBillBook(billItemDto); + } + + @Operation(summary = "更新账本类型") + @PutMapping("/book/{id}") + public Boolean updateBillBook(@PathVariable("id") Long id, + @JsonView(WriteView.class) @RequestBody BillItemDto billItemDto) { + return billManageService.updateBillBook(id, billItemDto); + } + + @Operation(summary = "新增账单类型") + @PostMapping("/category") + public Boolean addBillCategory(@RequestBody BillCategoryDto billCategoryDto) { + return billManageService.addBillCategory(billCategoryDto); + } + + @Operation(summary = "更新账单类型") + @PutMapping("/category/{id}") + public Boolean updateBillCategory(@PathVariable("id") Long id, + @RequestBody BillCategoryDto billCategoryDto) { + return billManageService.updateBillCategory(id, billCategoryDto); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/controller/BlogManageController.java b/admin-service/src/main/java/com/cxx/admin/controller/BlogManageController.java new file mode 100644 index 0000000..3cdcfc6 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/BlogManageController.java @@ -0,0 +1,69 @@ +package com.cxx.admin.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.admin.service.BlogManageService; +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogVisitDto; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/blog-manage") +@Tag(name = "博客管理") +public class BlogManageController { + @Resource + private BlogManageService blogManageService; + + @Operation(summary = "分页查询博客") + @GetMapping("/page") + public IPage queryBlogByPage(@RequestParam("currentPage") Integer currentPage, + @RequestParam("pageSize") Integer pageSize) { + return blogManageService.queryBlogByPage(currentPage, pageSize); + } + + @Operation(summary = "查询博客内容") + @GetMapping("/content/{id}") + public @JsonView(ReadView.class) BlogDto queryBlogById(@PathVariable("id") long id) { + return blogManageService.queryBlogById(id); + } + + @Operation(summary = "查询博客分类") + @GetMapping("/category") + public List queryBlogCategory() { + return blogManageService.queryBlogCategory(); + } + + @Operation(summary = "增加博客") + @PostMapping("") + public Boolean addBlog(@JsonView(WriteView.class) @RequestBody BlogDto blog) { + return blogManageService.addBlog(blog); + } + + @Operation(summary = "更新博客") + @PutMapping("/{id}") + public Boolean updateBlog(@PathVariable("id") long id, + @JsonView(WriteView.class) @RequestBody BlogDto blog) { + return blogManageService.updateBlog(id, blog); + } + + @Operation(summary = "删除博客") + @DeleteMapping("/{id}") + public Boolean deleteBlog(@PathVariable("id") long id) { + return blogManageService.deleteBlog(id); + } + + @Operation(summary = "查询博客访问") + @GetMapping("/visit") + public IPage queryBlogVisit(@RequestParam("currentPage") Integer currentPage, + @RequestParam("pageSize") Integer pageSize) { + return blogManageService.queryBlogVisit(currentPage, pageSize); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/controller/BudgetManageController.java b/admin-service/src/main/java/com/cxx/admin/controller/BudgetManageController.java new file mode 100644 index 0000000..432f85c --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/BudgetManageController.java @@ -0,0 +1,27 @@ +package com.cxx.admin.controller; + +import com.cxx.admin.service.BudgetManageService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/budget-manage") +@Tag(name = "预算管理") +public class BudgetManageController { + @Resource + private BudgetManageService budgetManageService; + + @Operation(summary = "新增预算类别") + @PostMapping("/category") + public Boolean addBudgetCategory(@RequestParam String category) { + return budgetManageService.addBudgetCategory(category); + } + + @Operation(summary = "更新预算类别") + @PutMapping("/category/{id}") + public Boolean updateBudgetCategory(@PathVariable("id") Long id, @RequestParam String category) { + return budgetManageService.updateBudgetCategory(id, category); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/controller/FileController.java b/admin-service/src/main/java/com/cxx/admin/controller/FileController.java new file mode 100644 index 0000000..92a9f53 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/FileController.java @@ -0,0 +1,65 @@ +package com.cxx.admin.controller; + +import com.cxx.admin.dto.file.ChunkInfoDto; +import com.cxx.admin.dto.file.ChunkResultDto; +import com.cxx.admin.dto.file.FileInfoDto; +import com.cxx.admin.service.FileService; +import com.cxx.admin.dto.file.FileRecordDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@RestController +@RequestMapping("/file") +@Tag(name = "文件管理") +public class FileController { + @Resource + private FileService fileService; + + @Operation(summary = "上传文件") + @PostMapping(value = "", headers = "content-type=multipart/form-data") + public FileRecordDto uploadFile(@RequestPart("file") MultipartFile file, + @RequestParam("path") String path, + @RequestParam("md5") String md5) { + return fileService.uploadFile(file, path, md5); + } + + @Operation(summary = "上传文件块") + @PostMapping("/chunk") + public Boolean uploadChunk(ChunkInfoDto chunkInfo, + String path) { + return fileService.uploadChunk(chunkInfo, path); + } + + @Operation(summary = "验证当前文件块是否上传") + @GetMapping("/chunk") + public ChunkResultDto checkChunk(@RequestParam String identifier, + @RequestParam String filename, + @RequestParam String path) { + return fileService.checkChunk(identifier, filename, path); + } + + @Operation(summary = "删除当前已上传的文件块") + @DeleteMapping("/chunk") + public Boolean deleteChunk(@RequestParam String identifier, + @RequestParam String path) { + return fileService.deleteChunk(identifier, path); + } + + @Operation(summary = "合并文件") + @PostMapping("/chunk/merge") + public FileRecordDto mergeFile(@RequestParam String filename, + @RequestParam String path) { + return fileService.mergeFile(filename, path); + } + + @Operation(summary = "获取文件夹目录") + @GetMapping("/catalog") + public List getFolderInfo(@RequestParam String folderName) { + return fileService.getFolderInfo(folderName); + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/controller/ServerMonitorController.java b/admin-service/src/main/java/com/cxx/admin/controller/ServerMonitorController.java new file mode 100644 index 0000000..baa27d5 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/ServerMonitorController.java @@ -0,0 +1,30 @@ +package com.cxx.admin.controller; + +import com.cxx.admin.dto.server.*; +import com.cxx.admin.service.ServerMonitorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/server-monitor") +@Tag(name = "服务器监控") +public class ServerMonitorController { + @Resource + private ServerMonitorService serverMonitorService; + + @Operation(summary = "系统信息") + @GetMapping("/system/info") + public SystemInfoDto getSystemInfo() { + return serverMonitorService.getSystemInfo(); + } + + @Operation(summary = "系统指标") + @GetMapping("/system/metrics") + public List querySystemMetrics(@RequestParam String range) { + return serverMonitorService.querySystemMetrics(range); + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/controller/SessionController.java b/admin-service/src/main/java/com/cxx/admin/controller/SessionController.java new file mode 100644 index 0000000..f4a55c3 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/SessionController.java @@ -0,0 +1,23 @@ +package com.cxx.admin.controller; + +import com.cxx.common.dto.user.SessionDto; +import com.cxx.admin.service.SessionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/session") +@Tag(name = "会话管理") +public class SessionController { + @Resource + private SessionService sessionService; + + @Operation(summary = "创建会话") + @PostMapping("") + public SessionDto createSession(@RequestParam String name, + @RequestParam String password) { + return sessionService.create(name, password); + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/controller/UserController.java b/admin-service/src/main/java/com/cxx/admin/controller/UserController.java new file mode 100644 index 0000000..7079633 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/UserController.java @@ -0,0 +1,33 @@ +package com.cxx.admin.controller; + +import com.cxx.admin.service.UserService; +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.common.dto.user.UserDto; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/user") +@Tag(name = "用户管理") +public class UserController { + @Resource + private UserService userService; + + @Operation(summary = "查询用户") + @GetMapping("/{id}") + public @JsonView(ReadView.class) UserDto queryUser(@PathVariable("id") Long id) { + return userService.queryUser(id); + } + + @Operation(summary = "更新用户") + @PutMapping("/{id}") + public Boolean updateUser(@PathVariable("id") Long id, + @JsonView(WriteView.class) @Validated @RequestBody UserDto userDto) { + return userService.updateUser(id, userDto); + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/controller/WeChatController.java b/admin-service/src/main/java/com/cxx/admin/controller/WeChatController.java new file mode 100644 index 0000000..119ff6f --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/controller/WeChatController.java @@ -0,0 +1,19 @@ +package com.cxx.admin.controller; + + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/wechat") +@Tag(name = "微信管理") +public class WeChatController { + + @Operation(summary = "获取code") + @GetMapping("/code") + public Boolean getWeChatAuthCode(@RequestParam("code") String code) { + System.out.println(code); + return Boolean.TRUE; + } +} \ No newline at end of file diff --git a/admin-service/src/main/java/com/cxx/admin/dao/AccountDao.java b/admin-service/src/main/java/com/cxx/admin/dao/AccountDao.java new file mode 100644 index 0000000..e46f282 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dao/AccountDao.java @@ -0,0 +1,12 @@ +package com.cxx.admin.dao; + +import com.cxx.admin.dto.user.AccountDto; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + + +@Mapper +public interface AccountDao { + List queryAccount(); +} diff --git a/admin-service/src/main/java/com/cxx/admin/dao/BlogDao.java b/admin-service/src/main/java/com/cxx/admin/dao/BlogDao.java new file mode 100644 index 0000000..6060e8f --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dao/BlogDao.java @@ -0,0 +1,24 @@ +package com.cxx.admin.dao; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogVisitDto; +import com.cxx.common.entity.Blog; +import com.cxx.common.vo.blog.BlogQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + + +@Mapper +public interface BlogDao { + IPage queryBlogByPage(IPage page); + + BlogDto queryBlogById(@Param("id") Long id); + + List queryBlogCategory(); + + IPage queryBlogVisit(IPage page); +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/FtpInfo.java b/admin-service/src/main/java/com/cxx/admin/dto/FtpInfo.java new file mode 100644 index 0000000..26cbc0c --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/FtpInfo.java @@ -0,0 +1,23 @@ +package com.cxx.admin.dto; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author: Cxx + * @Date: 2024/9/24 22:41 + * @Description: + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class FtpInfo { + private String ftpIp; + + private Integer ftpPort; + + private String ftpUsername; + + private String ftpPassword; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/file/ChunkInfoDto.java b/admin-service/src/main/java/com/cxx/admin/dto/file/ChunkInfoDto.java new file mode 100644 index 0000000..955f901 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/file/ChunkInfoDto.java @@ -0,0 +1,22 @@ +package com.cxx.admin.dto.file; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.web.multipart.MultipartFile; + +@Getter +@Setter +public class ChunkInfoDto { + /** + * 当前文件块,从1开始 + */ + private Integer chunkNumber; + /** + * 文件名 + */ + private String filename; + /** + * 块内容 + */ + private transient MultipartFile multipartFile; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/file/ChunkResultDto.java b/admin-service/src/main/java/com/cxx/admin/dto/file/ChunkResultDto.java new file mode 100644 index 0000000..a44625a --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/file/ChunkResultDto.java @@ -0,0 +1,20 @@ +package com.cxx.admin.dto.file; + +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class ChunkResultDto { + /** + * 是否跳过上传(已上传的可以直接跳过,达到秒传的效果) + */ + private boolean isSkipUpload; + + /** + * 已经上传的文件块编号,可以跳过,断点续传 + */ + private List uploadedChunkList; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/file/FileInfoDto.java b/admin-service/src/main/java/com/cxx/admin/dto/file/FileInfoDto.java new file mode 100644 index 0000000..a57d2f5 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/file/FileInfoDto.java @@ -0,0 +1,17 @@ +package com.cxx.admin.dto.file; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +public class FileInfoDto { + private String name; + private String type; + private String size; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createDate; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/file/FileRecordDto.java b/admin-service/src/main/java/com/cxx/admin/dto/file/FileRecordDto.java new file mode 100644 index 0000000..daa9548 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/file/FileRecordDto.java @@ -0,0 +1,14 @@ +package com.cxx.admin.dto.file; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class FileRecordDto { + private Long id; + private String name; + private String md5; + private String path; + private String url; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/server/CpuDto.java b/admin-service/src/main/java/com/cxx/admin/dto/server/CpuDto.java new file mode 100644 index 0000000..7abc32d --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/server/CpuDto.java @@ -0,0 +1,10 @@ +package com.cxx.admin.dto.server; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CpuDto { + private double usagePercent; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/server/DiskDto.java b/admin-service/src/main/java/com/cxx/admin/dto/server/DiskDto.java new file mode 100644 index 0000000..e99406b --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/server/DiskDto.java @@ -0,0 +1,13 @@ +package com.cxx.admin.dto.server; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class DiskDto { + private double total; + private double used; + private double free; + private double usagePercent; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/server/MemoryDto.java b/admin-service/src/main/java/com/cxx/admin/dto/server/MemoryDto.java new file mode 100644 index 0000000..4b5ef8d --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/server/MemoryDto.java @@ -0,0 +1,13 @@ +package com.cxx.admin.dto.server; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class MemoryDto { + private double total; + private double used; + private double free; + private double usagePercent; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/server/SystemInfoDto.java b/admin-service/src/main/java/com/cxx/admin/dto/server/SystemInfoDto.java new file mode 100644 index 0000000..317ca4b --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/server/SystemInfoDto.java @@ -0,0 +1,24 @@ +package com.cxx.admin.dto.server; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +public class SystemInfoDto { + // CPU信息 + private String cpuName; + private String cpuVendor; + private int cpuLogicalCores; + private int cpuPhysicalCores; + private double cpuSystemLoad; + // 操作系统信息 + private String osFamily; + private String osVersion; + private String osManufacturer; + // 系统运行时间 + private long systemUptime; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/server/SystemMetricsDto.java b/admin-service/src/main/java/com/cxx/admin/dto/server/SystemMetricsDto.java new file mode 100644 index 0000000..9ac8396 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/server/SystemMetricsDto.java @@ -0,0 +1,24 @@ +package com.cxx.admin.dto.server; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +public class SystemMetricsDto { + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date time; + + private double cpuUsage; + private double memoryTotal; + private double memoryUsed; + private double memoryFree; + private double memoryUsage; + private double diskTotal; + private double diskUsed; + private double diskFree; + private double diskUsage; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/user/AccountDto.java b/admin-service/src/main/java/com/cxx/admin/dto/user/AccountDto.java new file mode 100644 index 0000000..07c9604 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/user/AccountDto.java @@ -0,0 +1,42 @@ +package com.cxx.admin.dto.user; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class AccountDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "账户名称") + @NotBlank(message = "账户名称不能为空") + private String accountName; + + @Schema(description = "密码") + @NotBlank(message = "密码不能为空") + private String password; + + @Schema(description = "用户名称") + @NotBlank(message = "用户名称不能为空") + private String username; + + @Schema(description = "账户状态") + @JsonView(ReadView.class) + private Integer state; + + @Schema(description = "创建日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + @JsonView(ReadView.class) + private Date date; +} diff --git a/admin-service/src/main/java/com/cxx/admin/dto/user/UserSummaryDto.java b/admin-service/src/main/java/com/cxx/admin/dto/user/UserSummaryDto.java new file mode 100644 index 0000000..14686a2 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/dto/user/UserSummaryDto.java @@ -0,0 +1,36 @@ +package com.cxx.admin.dto.user; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Getter +@Setter +@JsonView(PlainView.class) +public class UserSummaryDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "id") + @JsonView(ReadView.class) + private String accountName; + + @Schema(description = "用户名称") + @NotBlank(message = "用户名称不能为空") + private String username; + + @Schema(description = "账户状态") + private Integer state; + + @Schema(description = "创建日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private LocalDateTime date; +} diff --git a/admin-service/src/main/java/com/cxx/admin/schedule/ServerMonitor.java b/admin-service/src/main/java/com/cxx/admin/schedule/ServerMonitor.java new file mode 100644 index 0000000..277a69f --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/schedule/ServerMonitor.java @@ -0,0 +1,21 @@ +package com.cxx.admin.schedule; + +import com.cxx.admin.service.ServerMonitorService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + + +@Component +@Slf4j +public class ServerMonitor { + @Resource + private ServerMonitorService serverMonitorService; + + // @Scheduled(fixedRate = 60000) + public void collectAndStoreMetrics() { + log.info("开始存储服务器状态"); + serverMonitorService.storeSystemMetrics(); + log.info("结束存储服务器状态"); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/AccountService.java b/admin-service/src/main/java/com/cxx/admin/service/AccountService.java new file mode 100644 index 0000000..c6a8f95 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/AccountService.java @@ -0,0 +1,17 @@ +package com.cxx.admin.service; + + +import com.cxx.admin.dto.user.AccountDto; +import com.cxx.common.entity.Account; + +import java.util.List; + +public interface AccountService { + List queryAccountList(); + + Account queryAccountByUserId(Long userId); + + Boolean registerAccount(AccountDto accountDto); + + Boolean deleteAccount(Long id); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/BillManageService.java b/admin-service/src/main/java/com/cxx/admin/service/BillManageService.java new file mode 100644 index 0000000..f981594 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/BillManageService.java @@ -0,0 +1,18 @@ +package com.cxx.admin.service; + +import com.cxx.common.dto.bill.BillCategoryDto; +import com.cxx.common.dto.bill.BillItemDto; + +public interface BillManageService { + Boolean addBillPay(BillItemDto billItemDto); + + Boolean updateBillPay(Long id, BillItemDto billItemDto); + + Boolean addBillBook(BillItemDto billItemDto); + + Boolean updateBillBook(Long id,BillItemDto billItemDto); + + Boolean addBillCategory(BillCategoryDto billCategoryDto); + + Boolean updateBillCategory(Long id, BillCategoryDto billCategoryDto); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/BlogManageService.java b/admin-service/src/main/java/com/cxx/admin/service/BlogManageService.java new file mode 100644 index 0000000..6d38c9b --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/BlogManageService.java @@ -0,0 +1,25 @@ +package com.cxx.admin.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogVisitDto; +import com.cxx.common.vo.blog.BlogQueryVo; + +import java.util.List; + +public interface BlogManageService { + IPage queryBlogByPage(Integer currentPage, Integer pageSize); + + BlogDto queryBlogById(Long id); + + List queryBlogCategory(); + + Boolean addBlog(BlogDto blog); + + Boolean updateBlog(Long id, BlogDto blog); + + Boolean deleteBlog(Long id); + + IPage queryBlogVisit(Integer currentPage, Integer pageSize); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/BudgetManageService.java b/admin-service/src/main/java/com/cxx/admin/service/BudgetManageService.java new file mode 100644 index 0000000..37c19f6 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/BudgetManageService.java @@ -0,0 +1,8 @@ +package com.cxx.admin.service; + + +public interface BudgetManageService { + Boolean addBudgetCategory(String category); + + Boolean updateBudgetCategory(Long id, String category); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/FileService.java b/admin-service/src/main/java/com/cxx/admin/service/FileService.java new file mode 100644 index 0000000..2bd9148 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/FileService.java @@ -0,0 +1,48 @@ +package com.cxx.admin.service; + +import com.cxx.admin.dto.file.ChunkInfoDto; +import com.cxx.admin.dto.file.ChunkResultDto; +import com.cxx.admin.dto.file.FileInfoDto; +import com.cxx.admin.dto.file.FileRecordDto; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +public interface FileService { + FileRecordDto uploadFile(MultipartFile file, String path, String md5); + + /** + * 上传文件块 + * @param chunkInfo 文件块信息 + * @param path 上传路径 + * @return 是否上传成功 + */ + Boolean uploadChunk(ChunkInfoDto chunkInfo, String path); + + /** + * 检查文件块信息 + * @param identifier 唯一标识 + * @param filename 文件名 + * @param path 上传文件夹路径 + * @return 检查结果 + */ + ChunkResultDto checkChunk(String identifier, String filename, String path); + + /** + * 删除文件块 + * @param identifier 唯一标识 + * @param path 上传文件夹路径 + * @return 是否删除成功 + */ + Boolean deleteChunk(String identifier, String path); + + /** + * 合并文件 + * @param filename 文件名 + * @param path 上传文件夹路径 + * @return 是否合并成功 + */ + FileRecordDto mergeFile(String filename, String path); + + List getFolderInfo(String folderName); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/ServerMonitorService.java b/admin-service/src/main/java/com/cxx/admin/service/ServerMonitorService.java new file mode 100644 index 0000000..fc571a8 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/ServerMonitorService.java @@ -0,0 +1,19 @@ +package com.cxx.admin.service; + +import com.cxx.admin.dto.server.*; + +import java.util.List; + +public interface ServerMonitorService { + CpuDto getCpuInfo(); + + MemoryDto getMemoryInfo(); + + DiskDto getDiskInfo(); + + SystemInfoDto getSystemInfo(); + + void storeSystemMetrics(); + + List querySystemMetrics(String range) ; +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/SessionService.java b/admin-service/src/main/java/com/cxx/admin/service/SessionService.java new file mode 100644 index 0000000..56db9fb --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/SessionService.java @@ -0,0 +1,7 @@ +package com.cxx.admin.service; + +import com.cxx.common.dto.user.SessionDto; + +public interface SessionService { + SessionDto create(String name, String password); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/UserService.java b/admin-service/src/main/java/com/cxx/admin/service/UserService.java new file mode 100644 index 0000000..4adaec8 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/UserService.java @@ -0,0 +1,10 @@ +package com.cxx.admin.service; + + +import com.cxx.common.dto.user.UserDto; + +public interface UserService { + UserDto queryUser(Long id); + + Boolean updateUser(Long id, UserDto userDto); +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/AccountServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/AccountServiceImpl.java new file mode 100644 index 0000000..331dd15 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/AccountServiceImpl.java @@ -0,0 +1,84 @@ +package com.cxx.admin.service.impl; + + +import cn.dev33.satoken.secure.BCrypt; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.cxx.admin.dao.AccountDao; +import com.cxx.admin.service.AccountService; +import com.cxx.admin.dto.user.AccountDto; +import com.cxx.common.entity.Account; +import com.cxx.common.entity.User; +import com.cxx.common.mapper.AccountMapper; +import com.cxx.common.mapper.UserMapper; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + + +@Service +public class AccountServiceImpl implements AccountService { + @Resource + private AccountDao accountDao; + + @Resource + private AccountMapper accountMapper; + + @Resource + private UserMapper userMapper; + + @Override + public List queryAccountList() { + return accountDao.queryAccount(); + } + + @Override + public Account queryAccountByUserId(Long userId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + return accountMapper.selectOne(queryWrapper.eq(Account::getUserId, userId)); + } + + @Transactional + @Override + public Boolean registerAccount(AccountDto accountDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (accountMapper.exists(queryWrapper.eq(Account::getAccountName, accountDto.getAccountName()))) { + throw new CustomException("该账户已经存在"); + } + + LambdaQueryWrapper userQueryWrapper = new LambdaQueryWrapper<>(); + if (userMapper.exists(userQueryWrapper.eq(User::getUsername, accountDto.getUsername()))) { + throw new CustomException("该用户已注册"); + } + + List results = new ArrayList<>(); + User user = new User(); + BeanUtils.copyProperties(accountDto, user); + results.add(userMapper.insert(user)); + + Account account = new Account(); + account.setAccountName(accountDto.getAccountName()); + account.setPassword(BCrypt.hashpw(accountDto.getPassword(), BCrypt.gensalt())); + account.setUserId(user.getId()); + account.setState(0); + results.add(accountMapper.insert(account)); + + return results.stream().allMatch(x -> x > 0); + } + + @Override + public Boolean deleteAccount(Long id) { + Account account = accountMapper.selectById(id); + + if (account == null) { + throw new CustomException("该账号不存在"); + } + + accountMapper.deleteById(id); + return userMapper.deleteById(account.getUserId()) == 1; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/BillManageServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/BillManageServiceImpl.java new file mode 100644 index 0000000..905e2f5 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/BillManageServiceImpl.java @@ -0,0 +1,134 @@ +package com.cxx.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.cxx.admin.service.BillManageService; +import com.cxx.common.dto.bill.BillCategoryDto; +import com.cxx.common.dto.bill.BillItemDto; +import com.cxx.common.entity.BillBook; +import com.cxx.common.entity.BillCategory; +import com.cxx.common.entity.BillPay; +import com.cxx.common.mapper.BillBookMapper; +import com.cxx.common.mapper.BillCategoryMapper; +import com.cxx.common.mapper.BillPayMapper; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +@Service +public class BillManageServiceImpl implements BillManageService { + @Resource + private BillPayMapper billPayMapper; + + @Resource + private BillBookMapper billBookMapper; + + @Resource + private BillCategoryMapper billCategoryMapper; + + @Override + public Boolean addBillPay(BillItemDto billItemDto) { + // 1. 校验是否存在 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (billPayMapper.exists(queryWrapper.eq(BillPay::getName, billItemDto.getName()))) { + throw new CustomException("该账户已经存在"); + } + + // 2. 新增账户 + BillPay newbillPay = new BillPay(); + BeanUtils.copyProperties(billItemDto, newbillPay); + + return billPayMapper.insert(newbillPay) == 1; + } + + @Override + public Boolean updateBillPay(Long id, BillItemDto billItemDto) { + // 1. 校验是否存在 + if (Objects.isNull(billPayMapper.selectById(id))) { + throw new RuntimeException("该账户不存在"); + } + + // 2. 更新账户 + BillPay billPay = new BillPay(); + BeanUtils.copyProperties(billItemDto, billPay); + billPay.setId(id); + + return billPayMapper.updateById(billPay) == 1; + } + + @Override + public Boolean addBillBook(BillItemDto billItemDto) { + // 1. 校验是否存在 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (billBookMapper.exists(queryWrapper.eq(BillBook::getName, billItemDto.getName()))) { + throw new CustomException("该账本已经存在"); + } + + // 2. 新增账本 + BillBook billBook = new BillBook(); + BeanUtils.copyProperties(billItemDto, billBook); + + return billBookMapper.insert(billBook) == 1; + } + + @Override + public Boolean updateBillBook(Long id, BillItemDto billItemDto) { + // 1. 校验是否存在 + if (Objects.isNull(billBookMapper.selectById(id))) { + throw new CustomException("该账单不存在"); + } + + // 2. 更新账本 + BillBook billBook = new BillBook(); + BeanUtils.copyProperties(billItemDto, billBook); + billBook.setId(id); + + return billBookMapper.updateById(billBook) == 1; + } + + private Long getBillBook(String name) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(BillBook::getName, name); + BillBook billBook = billBookMapper.selectOne(queryWrapper); + + if (Objects.isNull(billBook)) { + throw new CustomException("该账本类型不存在"); + } + + return billBook.getId(); + } + + @Override + public Boolean addBillCategory(BillCategoryDto billCategoryDto) { + // 1. 校验是否存在 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (billCategoryMapper.exists(queryWrapper.eq(BillCategory::getName, billCategoryDto.getName()))) { + throw new CustomException("该账单类型已经存在"); + } + + // 2. 新增账单类型 + BillCategory newBillCategory = new BillCategory(); + BeanUtils.copyProperties(billCategoryDto, newBillCategory); + newBillCategory.setBookId(getBillBook(billCategoryDto.getBookName())); + + return billCategoryMapper.insert(newBillCategory) == 1; + } + + @Override + public Boolean updateBillCategory(Long id, BillCategoryDto billCategoryDto) { + // 1. 校验是否存在 + if (Objects.isNull(billCategoryMapper.selectById(id))) { + throw new CustomException("该账单类型不存在"); + } + + // 2. 更新账单类型 + BillCategory billCategory = new BillCategory(); + BeanUtils.copyProperties(billCategoryDto, billCategory); + billCategory.setBookId(getBillBook(billCategoryDto.getBookName())); + billCategory.setId(id); + + return billCategoryMapper.updateById(billCategory) == 1; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/BlogManageServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/BlogManageServiceImpl.java new file mode 100644 index 0000000..6379228 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/BlogManageServiceImpl.java @@ -0,0 +1,193 @@ +package com.cxx.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cxx.admin.dao.BlogDao; +import com.cxx.admin.service.BlogManageService; +import com.cxx.admin.util.BlogUtils; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogVisitDto; +import com.cxx.common.entity.Blog; +import com.cxx.common.entity.BlogCategory; +import com.cxx.common.entity.BlogContent; +import com.cxx.common.mapper.BlogCategoryMapper; +import com.cxx.common.mapper.BlogContentMapper; +import com.cxx.common.mapper.BlogMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +@Service +public class BlogManageServiceImpl implements BlogManageService { + @Resource + private BlogDao blogDao; + + @Resource + private BlogMapper blogMapper; + + @Resource + private BlogCategoryMapper categoryMapper; + + @Resource + private BlogContentMapper contentMapper; + + @Override + public IPage queryBlogByPage(Integer currentPage, Integer pageSize) { + return blogDao.queryBlogByPage(new Page<>(currentPage, pageSize)); + } + + @Override + public BlogDto queryBlogById(Long id) { + return blogDao.queryBlogById(id); + } + + @Override + public List queryBlogCategory() { + return blogDao.queryBlogCategory(); + } + + @Transactional + @Override + public Boolean addBlog(BlogDto blogDto) { + // 1. 新增博客基本信息 + Blog blog = saveOrUpdateNewBlog(blogDto); + // 2. 新增博客内容信息 + blog.setContentId(addBlogContent(blogDto.getContent())); + // 3. 插入数据库 + return blogMapper.insert(blog) == 1; + } + + @Transactional + @Override + public Boolean updateBlog(Long id, BlogDto blogDto) { + Blog blog = saveOrUpdateNewBlog(blogDto); + blog.setId(id); + // 1. 更新博客内容信息 + updateBlogContent(getBlogById(id).getContentId(), blogDto.getContent()); + // 2. 校验是否删除博客类别 + deleteBlogCategory(getBlogById(id).getCategoryId()); + // 3. 更新数据库 + return blogMapper.updateById(blog) == 1; + } + + @Transactional + @Override + public Boolean deleteBlog(Long id) { + // 1. 删除博客类别 + deleteBlogCategory(getBlogById(id).getCategoryId()); + // 2. 删除博客内容 + contentMapper.deleteById(getBlogById(id).getContentId()); + // 3. 删除博客 + return blogMapper.deleteById(id) == 1; + } + + @Override + public IPage queryBlogVisit(Integer currentPage, Integer pageSize) { + return blogDao.queryBlogVisit(new Page<>(currentPage, pageSize)); + } + + /** + * 通过博客id获取博客 + * @param id id + * @return 博客 + */ + private Blog getBlogById(Long id) { + Blog blog = blogMapper.selectById(id); + + if (Objects.isNull(blog)) { + throw new RuntimeException("暂无该博客"); + } + + return blog; + } + + /** + * 增加/更新 博客 + * @param blogDto 前端传入的博客内容 + * @return 博客 + */ + private Blog saveOrUpdateNewBlog(BlogDto blogDto) { + Blog newBlog = new Blog(); + + // 设置博客基础信息 + newBlog.setTitle(blogDto.getTitle()); + newBlog.setTopValue(blogDto.getTopValue()); + newBlog.setIsGreat(blogDto.getIsGreat()); + + // 设置博客类别 + newBlog.setCategoryId(saveOrUpdateBlogCategory(blogDto.getCategory())); + + // 设置博客内容 + newBlog.setSummary(BlogUtils.getBlogSummary(blogDto.getContent())); + + // 设置博客字数统计 + Integer wordCount = BlogUtils.getWordCount(blogDto.getContent()); + newBlog.setWordCount(wordCount); + newBlog.setReadDuration(BlogUtils.getReadDuration(wordCount)); + + return newBlog; + } + + /** + * 设置博客类别 + * @param category 类别 + * @return 类别id + */ + private Long saveOrUpdateBlogCategory(String category) { + // 1. 查找类别是否存在 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + BlogCategory blogCategory = categoryMapper.selectOne(queryWrapper.eq(BlogCategory::getName, category)); + + // 2. 如果存在则返回id 否则需要新增类别 + if (Objects.isNull(blogCategory)) { + BlogCategory newBlogCategory = new BlogCategory(); + newBlogCategory.setName(category); + categoryMapper.insert(newBlogCategory); + return newBlogCategory.getId(); + } else { + return blogCategory.getId(); + } + } + + /** + * 判断是否需要删除博客类别 + * @param categoryId 博客类别id + */ + private void deleteBlogCategory(Long categoryId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (!blogMapper.exists(queryWrapper.eq(Blog::getCategoryId, categoryId))) { + // 如果没有该类别的博客 则删除博客类别 + categoryMapper.deleteById(categoryId); + } + } + + /** + * 新增博客内容 + * @param content 博客内容 + * @return 博客内容id + */ + private Long addBlogContent(String content) { + BlogContent blogContent = new BlogContent(); + blogContent.setContent(content); + contentMapper.insert(blogContent); + + return blogContent.getId(); + } + + /** + * 更新博客内容 + * @param contentId 博客内容id + * @param content 博客内容 + */ + private void updateBlogContent(Long contentId, String content) { + BlogContent blogContent = new BlogContent(); + blogContent.setContent(content); + blogContent.setId(contentId); + contentMapper.updateById(blogContent); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/BudgetManageServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/BudgetManageServiceImpl.java new file mode 100644 index 0000000..e858e4c --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/BudgetManageServiceImpl.java @@ -0,0 +1,43 @@ +package com.cxx.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.cxx.admin.service.BudgetManageService; +import com.cxx.common.entity.BudgetCategory; +import com.cxx.common.mapper.BudgetCategoryMapper; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.Objects; + +@Service +public class BudgetManageServiceImpl implements BudgetManageService { + @Resource + private BudgetCategoryMapper budgetCategoryMapper; + + + @Override + public Boolean addBudgetCategory(String category) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (budgetCategoryMapper.exists(queryWrapper.eq(BudgetCategory::getName, category))) { + throw new CustomException("该预算类别已存在"); + } + + BudgetCategory budgetCategory = new BudgetCategory(); + budgetCategory.setName(category); + return budgetCategoryMapper.insert(budgetCategory) == 1; + } + + @Override + public Boolean updateBudgetCategory(Long id, String category) { + if (Objects.isNull(budgetCategoryMapper.selectById(id))) { + throw new CustomException("该预算类别不存在"); + } + + BudgetCategory budgetCategory = new BudgetCategory(); + budgetCategory.setId(id); + budgetCategory.setName(category); + + return budgetCategoryMapper.updateById(budgetCategory) == 1; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/FileServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/FileServiceImpl.java new file mode 100644 index 0000000..804940f --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/FileServiceImpl.java @@ -0,0 +1,204 @@ +package com.cxx.admin.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.cxx.admin.constant.FileConstant; +import com.cxx.admin.dto.file.ChunkInfoDto; +import com.cxx.admin.dto.file.ChunkResultDto; +import com.cxx.admin.dto.file.FileInfoDto; +import com.cxx.admin.service.FileService; +import com.cxx.admin.dto.file.FileRecordDto; +import com.cxx.admin.util.FileUtils; +import com.cxx.admin.util.UploadFileUtil; +import com.cxx.common.entity.FileRecord; +import com.cxx.common.mapper.FileRecordMapper; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.FilenameUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; + + +@Service +@Slf4j +public class FileServiceImpl implements FileService { + @Value("${file.path}") + private String fileRootPath; + + @Resource + private FileRecordMapper fileRecordMapper; + + @Override + public FileRecordDto uploadFile(MultipartFile multipartFile, String path, String md5) { + UploadFileUtil.checkDirIsExist(getFilePath(path)); + + String filename = multipartFile.getOriginalFilename(); + String newPath = path + File.separator + md5 + "." + FilenameUtils.getExtension(filename); + File newFile = new File(getFilePath(newPath)); + + saveFile(multipartFile, newFile); + + // 这里的url需要加上 WebMvcConfig 中设置的前缀 + String url = FileConstant.FILE_URL_PREFIX + File.separator + newPath; + return getFileRecord(filename, md5, path, url); + } + + @Override + public Boolean uploadChunk(ChunkInfoDto chunkInfo, String path) { + MultipartFile file = chunkInfo.getMultipartFile(); + + try { + // 1. 校验路径是否存在 + UploadFileUtil.checkDirIsExist(getFilePath(path)); + // 2. 获取文件块路径 + Path chunkPath = Paths.get(UploadFileUtil.generateChunkPath(getFilePath(path), chunkInfo)); + // 3. 将文件块写入指定路径 + Files.write(chunkPath, file.getBytes()); + } catch (IOException exception) { + log.error("文件上传块失败: {}", exception.getMessage()); + throw new CustomException("文件上传块失败: " + exception.getMessage()); + } + + return true; + } + + @Override + public ChunkResultDto checkChunk(String identifier, String filename, String path) { + ChunkResultDto chunkResult = new ChunkResultDto(); + List uploadedChunkList = new ArrayList<>(); + + String folder = getFilePath(path) + File.separator + identifier; + String file = folder + File.separator + filename; + + // 判断文件夹是否存在 + if (UploadFileUtil.fileExists(folder)) { + // 先判断整个文件是否已经上传过了,如果是,则告诉前端跳过上传,实现秒传 + if (UploadFileUtil.fileExists(file)) { + chunkResult.setSkipUpload(true); + chunkResult.setUploadedChunkList(uploadedChunkList); + log.info("完整文件已存在,直接跳过上传,实现秒传"); + } else { + chunkResult.setSkipUpload(false); + // 获取已经上传的文件块 + chunkResult.setUploadedChunkList(UploadFileUtil.getUploadedChunkList(folder, filename)); + } + } else { + chunkResult.setSkipUpload(false); + chunkResult.setUploadedChunkList(uploadedChunkList); + } + + return chunkResult; + } + + @Override + public Boolean deleteChunk(String identifier, String path) { + String folder = getFilePath(path) + File.separator + identifier; + log.info("开始删除文件: " + folder); + + // 判断文件夹是否存在 + if (UploadFileUtil.fileExists(folder)) { + UploadFileUtil.deleteDirectory(folder); + } else { + throw new CustomException("文件: " + folder + "不存在"); + } + + return true; + } + + @Override + public FileRecordDto mergeFile(String filename, String path) { + String uuid = UUID.randomUUID().toString().replace("-", ""); + String newFilename = uuid + "." + FilenameUtils.getExtension(filename); + try { + UploadFileUtil.mergeFile(newFilename, getFilePath(path)); + } catch (IOException exception) { + throw new CustomException("合并文件: " + filename + " 失败"); + } + + String newPath = path + File.separator + newFilename; + String url = FileConstant.FILE_URL_PREFIX + File.separator + newPath; + return getFileRecord(filename, uuid, path, url); + } + + @Override + public List getFolderInfo(String folderName) { + File folder = new File(folderName); + List fileInfoList = new ArrayList<>(); + if (folder.exists() && folder.isDirectory()) { + File[] files = folder.listFiles(); + if (files != null) { + List folderInfoList = new ArrayList<>(); + List fileInfoSubList = new ArrayList<>(); + for (File file : files) { + FileInfoDto fileInfo = new FileInfoDto(); + fileInfo.setName(file.getName()); + if (file.isDirectory()) { + fileInfo.setType("文件夹"); + fileInfo.setSize("-"); + folderInfoList.add(fileInfo); + } else { + fileInfo.setType(FileUtils.getFileType(file.getName())); + fileInfo.setSize(FileUtils.formatSize(file.length())); + fileInfoSubList.add(fileInfo); + } + fileInfo.setCreateDate(new Date(file.lastModified())); + } + fileInfoList.addAll(folderInfoList); + fileInfoList.addAll(fileInfoSubList); + } + } + return fileInfoList; + } + + private void saveFile(MultipartFile multipartFile, File file) { + // 如果文件不存在 + if (!file.exists()) { + try { + // 3. 如果不存在则创建文件 + multipartFile.transferTo(file); + } catch (IOException e) { + throw new CustomException("文件上传失败:{}", e.getMessage()); + } + } + } + + private FileRecordDto getFileRecord(String filename, String md5, String path, String url) { + FileRecord fileRecord = new FileRecord(); + fileRecord.setName(filename); + fileRecord.setMd5(md5); + fileRecord.setPath(path); + fileRecord.setUrl(url); + fileRecord.setId(saveDatabase(fileRecord, md5)); + + // 4. 返回文件信息 + FileRecordDto fileRecordDto = new FileRecordDto(); + BeanUtils.copyProperties(fileRecord, fileRecordDto); + + return fileRecordDto; + } + + private Long saveDatabase(FileRecord fileRecord, String md5) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(FileRecord.class); + FileRecord dbFileRecord = fileRecordMapper.selectOne(queryWrapper.eq(FileRecord::getMd5, md5)); + if (Objects.isNull(dbFileRecord)) { + fileRecordMapper.insert(fileRecord); + return fileRecord.getId(); + } else { + return dbFileRecord.getId(); + } + } + + private String getFilePath(String path) { + return fileRootPath + path; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/ServerMonitorServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/ServerMonitorServiceImpl.java new file mode 100644 index 0000000..5528e96 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/ServerMonitorServiceImpl.java @@ -0,0 +1,214 @@ +package com.cxx.admin.service.impl; + +import com.cxx.admin.dto.server.*; +import com.cxx.admin.service.ServerMonitorService; +import com.influxdb.client.InfluxDBClient; +import com.influxdb.client.InfluxDBClientFactory; +import com.influxdb.client.QueryApi; +import com.influxdb.client.WriteApi; +import com.influxdb.client.domain.WritePrecision; +import com.influxdb.client.write.Point; +import com.influxdb.query.FluxTable; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HWDiskStore; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.OperatingSystem; + +import java.io.File; +import java.text.DecimalFormat; +import java.time.Instant; +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Service +public class ServerMonitorServiceImpl implements ServerMonitorService { + private final SystemInfo systemInfo = new SystemInfo(); + private final HardwareAbstractionLayer hardware = systemInfo.getHardware(); + private final OperatingSystem os = systemInfo.getOperatingSystem(); + private final CentralProcessor processor = hardware.getProcessor(); + + private final InfluxDBClient client; + + private final QueryApi queryApi; + + private final String SYSTEM_METRICS = "system_metrics"; + + private final long GB = 1024 * 1024 * 1024; + private final DecimalFormat df = new DecimalFormat("0.00"); + + public ServerMonitorServiceImpl( + @Value("${influxdb.url}") String url, + @Value("${influxdb.token}") String token, + @Value("${influxdb.org}") String org, + @Value("${influxdb.bucket}") String bucket) { + this.client = InfluxDBClientFactory.create(url, token.toCharArray(), org, bucket); + this.queryApi = this.client.getQueryApi(); + } + + @Override + public CpuDto getCpuInfo() { + CpuDto cpuDto = new CpuDto(); + cpuDto.setUsagePercent(formatPercent(hardware.getProcessor().getSystemCpuLoad(500) * 100)); + + return cpuDto; + } + + @Override + public MemoryDto getMemoryInfo() { + GlobalMemory memory = hardware.getMemory(); + MemoryDto memoryDto = new MemoryDto(); + long total = memory.getTotal(); + long free = memory.getAvailable(); + long used = total - free; + + memoryDto.setTotal(bytesToGb(total)); + memoryDto.setUsed(bytesToGb(used)); + memoryDto.setFree(bytesToGb(free)); + memoryDto.setUsagePercent(formatPercent((used * 100.0) / total)); + + return memoryDto; + } + + @Override + public DiskDto getDiskInfo() { + List disks = hardware.getDiskStores(); + if (disks.isEmpty()) { + return null; + } + + // 获取根分区信息 + HWDiskStore rootDisk = disks.get(0); + DiskDto diskInfo = new DiskDto(); + diskInfo.setTotal(bytesToGb(rootDisk.getSize())); + + // 获取文件系统使用情况 + os.getFileSystem().getFileStores().stream() + .filter(fs -> fs.getMount().equals(File.separator)) + .findFirst() + .ifPresent(fs -> { + long total = fs.getTotalSpace(); + long free = fs.getFreeSpace(); + long used = total - free; + + diskInfo.setUsed(bytesToGb(used)); + diskInfo.setFree(bytesToGb(free)); + diskInfo.setUsagePercent(formatPercent((double) (used) * 100.0 / total)); + }); + + return diskInfo; + } + + @Override + public SystemInfoDto getSystemInfo() { + SystemInfoDto dto = new SystemInfoDto(); + + // 获取CPU信息 + dto.setCpuName(processor.getProcessorIdentifier().getName()); + dto.setCpuVendor(processor.getProcessorIdentifier().getVendor()); + dto.setCpuLogicalCores(processor.getLogicalProcessorCount()); + dto.setCpuPhysicalCores(processor.getPhysicalProcessorCount()); + + // 获取CPU负载 + double[] loadAverage = processor.getSystemLoadAverage(3); + dto.setCpuSystemLoad(loadAverage[0]); // 1分钟平均负载 + + // 获取操作系统信息 + dto.setOsFamily(os.getFamily()); + dto.setOsVersion(os.getVersionInfo().getVersion()); + dto.setOsManufacturer(os.getManufacturer()); + + // 获取系统运行时间(秒) + dto.setSystemUptime(TimeUnit.MILLISECONDS.toSeconds(systemInfo.getOperatingSystem().getSystemUptime())); + + return dto; + } + + @Override + public void storeSystemMetrics() { + try (WriteApi writeApi = client.getWriteApi()) { + CpuDto cpuDto = getCpuInfo(); + MemoryDto memoryDto = getMemoryInfo(); + DiskDto diskDto = getDiskInfo(); + + Point point = Point + .measurement(SYSTEM_METRICS) + .addTag("host", "localhost") + .addField("cpu_usage", cpuDto.getUsagePercent()) + .addField("memory_total", memoryDto.getTotal()) + .addField("memory_used", memoryDto.getUsed()) + .addField("memory_free", memoryDto.getFree()) + .addField("memory_usage", memoryDto.getUsagePercent()) + .addField("disk_total", diskDto.getTotal()) + .addField("disk_used", diskDto.getUsed()) + .addField("disk_free", diskDto.getFree()) + .addField("disk_usage", diskDto.getUsagePercent()) + .time(Instant.now(), WritePrecision.S); + + writeApi.writePoint(point); + } + } + + @Override + public List querySystemMetrics(String range) { + String fluxQuery = "from(bucket: \"server_metrics\")" + + "|> range(start: -" + range + ")" + // range 可以是 "1h", "24h" 等 + "|> filter(fn: (r) => r._measurement == \"system_metrics\")" + + "|> pivot(rowKey: [\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\")"; + + List> results = executeQuery(fluxQuery); + + List systemMetricsList = new ArrayList<>(); + + for (Map data : results) { + SystemMetricsDto systemMetrics = new SystemMetricsDto(); + systemMetrics.setCpuUsage((Double) data.get("cpu_usage")); + systemMetrics.setMemoryTotal((Double) data.get("memory_total")); + systemMetrics.setMemoryUsed((Double) data.get("memory_used")); + systemMetrics.setMemoryFree((Double) data.get("memory_free")); + systemMetrics.setMemoryUsage((Double) data.get("memory_usage")); + systemMetrics.setDiskTotal((Double) data.get("disk_total")); + systemMetrics.setDiskUsed((Double) data.get("disk_used")); + systemMetrics.setDiskFree((Double) data.get("disk_free")); + systemMetrics.setDiskUsage((Double) data.get("disk_usage")); + systemMetrics.setTime(Date.from((Instant) data.get("time"))); + + systemMetricsList.add(systemMetrics); + } + + return systemMetricsList; + } + + private List> executeQuery(String fluxQuery) { + List tables = queryApi.query(fluxQuery); + List> results = new ArrayList<>(); + + for (FluxTable table : tables) { + table.getRecords().forEach(record -> { + Map data = new HashMap<>(); + data.put("time", record.getTime()); + + record.getValues().forEach((key, value) -> { + if (!key.startsWith("_")) { // 过滤掉内部字段 + data.put(key, value); + } + }); + + results.add(data); + }); + } + return results; + } + + private double bytesToGb(long bytes) { + double gb = bytes / (double) GB; + return Double.parseDouble(df.format(gb)); + } + + public double formatPercent(double percent) { + return Double.parseDouble(df.format(percent)); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/SessionServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/SessionServiceImpl.java new file mode 100644 index 0000000..befcff1 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/SessionServiceImpl.java @@ -0,0 +1,56 @@ +package com.cxx.admin.service.impl; + + +import cn.dev33.satoken.secure.BCrypt; +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.cxx.common.dto.user.SessionDto; +import com.cxx.admin.service.SessionService; +import com.cxx.common.dto.user.UserDto; +import com.cxx.common.entity.Account; +import com.cxx.common.entity.User; +import com.cxx.common.mapper.AccountMapper; +import com.cxx.common.mapper.UserMapper; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + + +@Service +public class SessionServiceImpl implements SessionService { + @Resource + private AccountMapper accountMapper; + + @Resource + private UserMapper userMapper; + + @Override + public SessionDto create(String name, String password) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Account.class).eq(Account::getAccountName, name); + Account account = accountMapper.selectOne(queryWrapper); + if (account == null) { + throw new CustomException("账户: " + name + " 不存在"); + } + + if (!BCrypt.checkpw(password, account.getPassword())) { + throw new CustomException("密码不正确"); + } + + User user = userMapper.selectById(account.getUserId()); + UserDto userDto = new UserDto(); + BeanUtils.copyProperties(user, userDto); + userDto.setAccountId(account.getId()); + userDto.setAccountName(name); + + SessionDto sessionDto = new SessionDto(); + StpUtil.login(account.getId()); + sessionDto.setSaToken(StpUtil.getTokenInfo()); + sessionDto.setUserInfo(userDto); + + StpUtil.getSession().set("username", name); + + return sessionDto; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/service/impl/UserServiceImpl.java b/admin-service/src/main/java/com/cxx/admin/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..cc9713e --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/service/impl/UserServiceImpl.java @@ -0,0 +1,53 @@ +package com.cxx.admin.service.impl; + + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.cxx.admin.service.AccountService; +import com.cxx.admin.service.UserService; +import com.cxx.common.dto.user.UserDto; +import com.cxx.common.entity.User; +import com.cxx.common.mapper.UserMapper; +import com.cxx.framework.web.CustomException; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl implements UserService { + @Resource + private UserMapper userMapper; + + @Resource + private AccountService accountService; + + @Override + public UserDto queryUser(Long id) { + User user = userMapper.selectById(id); + if (user == null) { + throw new CustomException("未查询到该用户"); + } + + UserDto userDto = new UserDto(); + BeanUtils.copyProperties(user, userDto); + userDto.setAccountName(accountService.queryAccountByUserId(id).getAccountName()); + return userDto; + } + + @Override + public Boolean updateUser(Long id, UserDto userDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (!userMapper.exists(queryWrapper.eq(User::getId, id))) { + throw new CustomException("该用户不存在"); + } + + queryWrapper.clear(); + if (userMapper.exists(queryWrapper.eq(User::getUsername, userDto.getUsername()).ne(User::getId, id))) { + throw new CustomException("该用户已经存在"); + } + + User user = new User(); + BeanUtils.copyProperties(userDto, user); + user.setId(id); + return userMapper.updateById(user) == 1; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/util/BlogUtils.java b/admin-service/src/main/java/com/cxx/admin/util/BlogUtils.java new file mode 100644 index 0000000..52c8c9a --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/util/BlogUtils.java @@ -0,0 +1,73 @@ +package com.cxx.admin.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class BlogUtils { + /** + * 博客概要字数 + */ + private static final Integer BLOG_SUMMARY_COUNT = 100; + + /** + * 阅读速度 600 字/分钟 + */ + private static final Double READ_SPEED = 600.0; + + /** + * 博客非统计字符 + */ + private static final List excludeChart = new ArrayList<>(Arrays.asList(' ', '\n', '\t')); + + /** + * 获取文本字数 + * + * @param str 文本 + * @return 字数 + */ + public static Integer getWordCount(String str) { + Integer count = 0; + + if (null == str || str.isEmpty()) { + return count; + } + + for (int i = 0; i < str.length(); i++) { + char tmp = str.charAt(i); + if (!excludeChart.contains(tmp)) { + count++; + } + } + + return count; + } + + /** + * 获取阅读时长 单位:分钟 + * + * @param wordCount 文本字数 + * @return 阅读时长 + */ + public static Double getReadDuration(Integer wordCount) { + return wordCount / READ_SPEED; + } + + /** + * 获取简要信息 + * + * @param content 博客内容 + * @return 简要信息 + */ + public static String getBlogSummary(String content) { + if (content.length() > BLOG_SUMMARY_COUNT) { + return content.substring(0, BLOG_SUMMARY_COUNT); + } + + return content; + } + + public static String getHexTimeStamp() { + return Long.toHexString(System.currentTimeMillis()); + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/util/FileUtils.java b/admin-service/src/main/java/com/cxx/admin/util/FileUtils.java new file mode 100644 index 0000000..12c1759 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/util/FileUtils.java @@ -0,0 +1,28 @@ +package com.cxx.admin.util; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class FileUtils { + public static String getFileType(String fileName) { + int lastIndex = fileName.lastIndexOf('.'); + if (lastIndex != -1) { + return fileName.substring(lastIndex + 1); + } + return "未知类型"; + } + + public static String formatSize(long size) { + if (size < 1024) { + return size + " B"; + } else if (size < 1024 * 1024) { + return String.format("%.2f KB", (double) size / 1024); + } else if (size < 1024 * 1024 * 1024) { + return String.format("%.2f MB", (double) size / (1024 * 1024)); + } else { + return String.format("%.2f GB", (double) size / (1024 * 1024 * 1024)); + } + } + + +} diff --git a/admin-service/src/main/java/com/cxx/admin/util/FtpUtils.java b/admin-service/src/main/java/com/cxx/admin/util/FtpUtils.java new file mode 100644 index 0000000..b25a887 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/util/FtpUtils.java @@ -0,0 +1,125 @@ +package com.cxx.admin.util; + +import com.cxx.admin.dto.FtpInfo; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.net.PrintCommandListener; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPFile; + +import java.io.*; +import java.nio.charset.StandardCharsets; + +/** + * @Author: Cxx + * @Date: 2024/9/24 21:49 + * @Description: + */ +@Slf4j +public class FtpUtils { + private static FTPClient ftpClient; + + /** + * 文件名分隔符 + */ + public static String FILE_NAME_SPLIT = "_"; + + private static boolean connectFtp(FtpInfo ftpInfo) { + try { + ftpClient = new FTPClient(); + // 设置utf-8 编码 否则中文文件名会乱码 + ftpClient.setControlEncoding("utf-8"); + ftpClient.connect(ftpInfo.getFtpIp(), ftpInfo.getFtpPort()); + ftpClient.login(ftpInfo.getFtpUsername(), ftpInfo.getFtpPassword()); + ftpClient.addProtocolCommandListener( + new PrintCommandListener( + new PrintWriter(new OutputStreamWriter(System.out, StandardCharsets.UTF_8)), true)); + log.info("连接ftp服务器成功"); + } catch (IOException e) { + log.error("连接ftp服务器失败:", e); + throw new RuntimeException("连接ftp服务器失败"); + } + + return true; + } + + private static void disConnectFtp() { + try { + if (ftpClient != null) { + ftpClient.disconnect(); + } + log.info("关闭ftp服务器成功"); + } catch (IOException e) { + log.error("关闭ftp服务器失败:", e); + throw new RuntimeException("关闭ftp服务器失败"); + } + } + + private static void closeInputStream(FileInputStream fileInputStream) { + try { + if (fileInputStream != null) { + fileInputStream.close(); + } + } catch (IOException e) { + log.error("关闭文件流失败:", e); + throw new RuntimeException("关闭文件流失败"); + } + } + + public static void uploadFile(FtpInfo ftpInfo, String remotePath, String fileName, File file) { + FileInputStream fileInputStream = null; + + try { + if (connectFtp(ftpInfo)) { + ftpClient.changeWorkingDirectory(remotePath); + ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); + fileInputStream = new FileInputStream(file); + boolean uploadResult = ftpClient.storeFile(fileName, fileInputStream); + if (uploadResult) { + log.info("上传文件:{}成功", fileName); + } else { + throw new RuntimeException("上传ftp文件失败"); + } + } + } catch (IOException e) { + log.error("上传ftp文件异常:", e); + throw new RuntimeException("上传ftp文件异常"); + } finally { + disConnectFtp(); + closeInputStream(fileInputStream); + } + } + + /** + * 校验是否存在文件 + * + * @param ftpInfo ftp信息 + * @param remotePath 文件路径 + * @param md5 md5值 + * @return 校验结果 + */ + public static boolean checkIsExitFile(FtpInfo ftpInfo, String remotePath, String md5) { + boolean isExist = false; + try { + if (connectFtp(ftpInfo)) { + ftpClient.changeWorkingDirectory(remotePath); + FTPFile[] fileList = ftpClient.listFiles(); + if (fileList != null) { + for (FTPFile imageFile : fileList) { + String fileMd5 = imageFile.getName().split(FILE_NAME_SPLIT)[0]; + if (fileMd5.equals(md5)) { + log.info("文件{}已经存在", imageFile.getName()); + isExist = true; + } + } + } + } + } catch (IOException e) { + log.error("校验ftp文件异常:", e); + throw new RuntimeException("校验ftp文件异常"); + } finally { + disConnectFtp(); + } + + return isExist; + } +} diff --git a/admin-service/src/main/java/com/cxx/admin/util/UploadFileUtil.java b/admin-service/src/main/java/com/cxx/admin/util/UploadFileUtil.java new file mode 100644 index 0000000..4ce4f76 --- /dev/null +++ b/admin-service/src/main/java/com/cxx/admin/util/UploadFileUtil.java @@ -0,0 +1,173 @@ +package com.cxx.admin.util; + +import cn.hutool.core.io.file.FileNameUtil; +import com.cxx.admin.dto.file.ChunkInfoDto; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; + +/** + * @Author: chenxiuxiang + * @Date: 2023/7/24 14:49 + * @Description: 上传文件工具类 + */ +@Slf4j +public class UploadFileUtil { + private static final String FILE_SEPARATOR = "_"; + + /** + * 校验文件夹是否存在 + * + * @param path 路径 + */ + public static void checkDirIsExist(String path) { + File dir = new File(path); + if (!dir.exists() && !dir.isDirectory()) { + boolean mkdir = dir.mkdirs(); + } + } + + /** + * 获取文件路径 + * + * @param path 上传文件夹路径 + * @param chunkInfo 分片文件信息 + * @return 文件路径 + */ + public static String generateChunkPath(String path, ChunkInfoDto chunkInfo) { + return path + File.separator + chunkInfo.getFilename() + FILE_SEPARATOR + chunkInfo.getChunkNumber(); + } + + public static List getUploadedChunkList(String folder, String filename) { + List uploadedChunkList = new ArrayList<>(); + + // 获取文件夹下所有的文件 + try (Stream list = Files.list(Paths.get(folder))) { + // 去除需要合并的文件 + list.filter(path -> !path.getFileName().toString().equals(filename)) + // 循环遍历文件 将已经上传的文件序号添加至列表中 + .forEach(path -> { + String chunkPath = path.getFileName().toString(); + int index = chunkPath.lastIndexOf(FILE_SEPARATOR); + uploadedChunkList.add(Integer.valueOf(chunkPath.substring(index + 1))); + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + + return uploadedChunkList; + } + + /** + * 文件合并 + */ + public static void mergeFile(String filename, String path) throws IOException { + // 判断文件是否存在 + String file = path + File.separator + filename; + if (fileExists(file)) { + deleteFile(file); + } + + // 不存在的话,进行合并 + Files.createFile(Paths.get(file)); + + // 获取文件夹下所有的文件 + try (Stream list = Files.list(Paths.get(path))) { + // 保留后缀包含分隔符的 + list.filter(chunkPath -> FileNameUtil.getSuffix(chunkPath.getFileName().toString()).contains(FILE_SEPARATOR)) + // 按照文件名排序 + .sorted((o1, o2) -> { + String p1 = o1.getFileName().toString(); + String p2 = o2.getFileName().toString(); + int i1 = p1.lastIndexOf(FILE_SEPARATOR); + int i2 = p2.lastIndexOf(FILE_SEPARATOR); + return Integer.valueOf(p1.substring(i1 + 1)) + .compareTo(Integer.valueOf(p2.substring(i2 + 1))); + }) + // 循环写入到文件中 + .forEach(chunkPath -> { + try { + // 以追加的形式写入文件 + Files.write(Paths.get(file), Files.readAllBytes(chunkPath), StandardOpenOption.APPEND); + // 合并后删除该块 + Files.delete(chunkPath); + } catch (IOException exception) { + log.error("写入文件失败: " + exception.getMessage()); + throw new RuntimeException(exception); + } + }); + } + } + + /** + * 根据文件的全路径名判断文件是否存在 + */ + public static boolean fileExists(String file) { + Path path = Paths.get(file); + return Files.exists(path, LinkOption.NOFOLLOW_LINKS); + } + + /** + * 删除目录(文件夹)以及目录下的文件 + * + * @param sPath 被删除目录的文件路径 + * @return 目录删除成功返回true,否则返回false + */ + public static boolean deleteDirectory(String sPath) { + // 如果sPath不以文件分隔符结尾,自动添加文件分隔符 + if (!sPath.endsWith(File.separator)) { + sPath = sPath + File.separator; + } + File dirFile = new File(sPath); + // 如果dir对应的文件不存在,或者不是一个目录,则退出 + if (!dirFile.exists() || !dirFile.isDirectory()) { + return false; + } + + boolean flag = true; + // 删除文件夹下的所有文件(包括子目录) + File[] files = dirFile.listFiles(); + for (File file : Objects.requireNonNull(files)) { + // 删除子文件 + if (file.isFile()) { + flag = deleteFile(file.getAbsolutePath()); + } + // 删除子目录 + else { + flag = deleteDirectory(file.getAbsolutePath()); + } + if (!flag) { + break; + } + } + if (!flag) { + return false; + } + + log.info("文件删除成功"); + // 删除当前目录 + return dirFile.delete(); + } + + /** + * 删除单个文件 + * + * @param sPath 被删除文件的文件名 + * @return 单个文件删除成功返回true,否则返回false + */ + public static boolean deleteFile(String sPath) { + boolean flag = false; + File file = new File(sPath); + // 路径为文件且不为空则进行删除 + if (file.isFile() && file.exists()) { + flag = file.delete(); + } + return flag; + } +} \ No newline at end of file diff --git a/admin-service/src/main/resources/application-dev.yml b/admin-service/src/main/resources/application-dev.yml new file mode 100644 index 0000000..d85af55 --- /dev/null +++ b/admin-service/src/main/resources/application-dev.yml @@ -0,0 +1,15 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: 123456 + +logging: + level: + root: info + config: + +file: + path: D:\\temp\\ + log-path: D:\\temp\\ \ No newline at end of file diff --git a/admin-service/src/main/resources/application-docker.yml b/admin-service/src/main/resources/application-docker.yml new file mode 100644 index 0000000..141dfac --- /dev/null +++ b/admin-service/src/main/resources/application-docker.yml @@ -0,0 +1,16 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://mysql:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: docker + password: 19940822Cxx + +logging: + fluentd: + host: fluent-bit + port: 24224 + level: + root: info + +file: + path: /upload-file/ \ No newline at end of file diff --git a/admin-service/src/main/resources/application-prod.yml b/admin-service/src/main/resources/application-prod.yml new file mode 100644 index 0000000..b75d9df --- /dev/null +++ b/admin-service/src/main/resources/application-prod.yml @@ -0,0 +1,16 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: cxx + password: 19940822Cxx@1213 + +logging: + level: + root: info + config: + classpath:logback-spring-drop.xml + +file: + path: /root/docker/upload-file/ + log-path: /root/service/logs/ \ No newline at end of file diff --git a/admin-service/src/main/resources/application.yml b/admin-service/src/main/resources/application.yml new file mode 100644 index 0000000..46ea264 --- /dev/null +++ b/admin-service/src/main/resources/application.yml @@ -0,0 +1,36 @@ +server: + port: 8080 + +spring: + application: + name: @project.artifactId@ + version: @project.version@ + profiles: + active: dev + servlet: + multipart: + max-file-size: 10MB + max-request-size: 100MB + +# mybatis plus mapper路径 +mybatis-plus: + # mybatis plus + mapper-locations: classpath*:/mapper/**/*.xml + configuration: + log-impl: + org.apache.ibatis.logging.stdout.StdOutImpl + +ftp: + ip: 192.168.31.54 + port: 21 + username: ftp-cxx + password: 19940822cxx + +influxdb: + url: http://localhost:8086 + token: i3eja-5jMQBxxF29pvKBialZ_j4y3p8iAMI86Ht3YcMTXhitIeUfx30vAv79xfhckC5YExTKj91AribNwBZBOQ== + org: cxx + bucket: server_metrics + +web-starter: + base-package: com.cxx.service \ No newline at end of file diff --git a/admin-service/src/main/resources/logback-spring-drop.xml b/admin-service/src/main/resources/logback-spring-drop.xml new file mode 100644 index 0000000..d6f5043 --- /dev/null +++ b/admin-service/src/main/resources/logback-spring-drop.xml @@ -0,0 +1,120 @@ + + + + logback + + + + + + + + + + + + + + + + + + + + + + DEBUG + + + + ${CONSOLE_LOG_PATTERN} + + ${ENCODING} + + + + + + + + INFO + ACCEPT + DENY + + + ${log.path}/log_info.log + + ${FILE_LOG_PATTERN} + ${ENCODING} + + + + + ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log + + 500MB + + + 15 + + + + + + + WARN + ACCEPT + DENY + + + ${log.path}/log_warn.log + + ${FILE_LOG_PATTERN} + ${ENCODING} + + + + ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + + + + ERROR + ACCEPT + DENY + + + ${log.path}/log_error.log + + ${FILE_LOG_PATTERN} + ${ENCODING} + + + + ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + + + + + + + + \ No newline at end of file diff --git a/admin-service/src/main/resources/mapper/AccountMapper.xml b/admin-service/src/main/resources/mapper/AccountMapper.xml new file mode 100644 index 0000000..e41b387 --- /dev/null +++ b/admin-service/src/main/resources/mapper/AccountMapper.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/admin-service/src/main/resources/mapper/BlogMapper.xml b/admin-service/src/main/resources/mapper/BlogMapper.xml new file mode 100644 index 0000000..5d14e22 --- /dev/null +++ b/admin-service/src/main/resources/mapper/BlogMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/admin-service/src/test/java/com/cxx/admin/AdminServiceApplicationTests.java b/admin-service/src/test/java/com/cxx/admin/AdminServiceApplicationTests.java new file mode 100644 index 0000000..730e09e --- /dev/null +++ b/admin-service/src/test/java/com/cxx/admin/AdminServiceApplicationTests.java @@ -0,0 +1,21 @@ +package com.cxx.admin; + +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Date; + +@SpringBootTest +public class AdminServiceApplicationTests { + @Test + public void contextLoads() { + + } + + @Test + public void TestEmail() { + + } +} + diff --git a/blog-service/Dockerfile b/blog-service/Dockerfile new file mode 100644 index 0000000..94ced11 --- /dev/null +++ b/blog-service/Dockerfile @@ -0,0 +1,6 @@ +FROM docker-0.unsee.tech/openjdk:11-jdk-slim +ARG JAR_FILE=target/*.jar +COPY $JAR_FILE app.jar +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo 'Asia/Shanghai' > /etc/timezone +ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/blog-service/pom.xml b/blog-service/pom.xml new file mode 100644 index 0000000..4f785ae --- /dev/null +++ b/blog-service/pom.xml @@ -0,0 +1 @@ + 4.0.0 com.cxx sweet-hut-service 2.0.0 blog-service 2.0.0 17 17 UTF-8 com.cxx common 2.0.0 eu.bitwalker UserAgentUtils 1.21 \ No newline at end of file diff --git a/blog-service/src/main/java/com/cxx/blog/BlogServiceApplication.java b/blog-service/src/main/java/com/cxx/blog/BlogServiceApplication.java new file mode 100644 index 0000000..218b40a --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/BlogServiceApplication.java @@ -0,0 +1,13 @@ +package com.cxx.blog; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@MapperScan(basePackages = {"com.cxx.common.mapper", "com.cxx.blog.dao"}) +public class BlogServiceApplication { + public static void main(String[] args) { + SpringApplication.run(BlogServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/blog-service/src/main/java/com/cxx/blog/config/BlogVisitMonitor.java b/blog-service/src/main/java/com/cxx/blog/config/BlogVisitMonitor.java new file mode 100644 index 0000000..1c12f74 --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/config/BlogVisitMonitor.java @@ -0,0 +1,71 @@ +package com.cxx.blog.config; + +import com.cxx.blog.service.BlogService; +import com.cxx.common.entity.BlogVisit; +import com.cxx.blog.util.IpUtils; +import eu.bitwalker.useragentutils.Browser; +import eu.bitwalker.useragentutils.OperatingSystem; +import eu.bitwalker.useragentutils.UserAgent; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.*; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + + +/** + * 利用AOP监控博客访问 + * 1. @Before:前置通知,在方法执行之前执行 + * 2. @After:后置通知,在方法执行之后执行 + * 3. @AfterRunning:返回通知,在方法返回结果之后执行 + * 4. @AfterThrowing:异常通知,在方法抛出异常之后执行 + * 5. @Around:环绕通知,围绕着方法执行 + */ +@Component +@Aspect +@Slf4j +public class BlogVisitMonitor { + @Resource + private BlogService blogService; + + /** + * 定义切面 + * 指定需要统计的包 + */ + @Pointcut("execution(* com.cxx.blog.controller.BlogController.*(..))") + public void pointCut() { + + } + + /** + * 只有正常返回才会执行此方法 + * 如果程序执行失败,则不执行此方法 + */ + @AfterReturning(returning = "returnVal", pointcut = "pointCut()") + public void doAfterReturning(JoinPoint joinPoint, Object returnVal) { + // 获取接收到的HTTP请求信息 + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + + String agent = request.getHeader("User-Agent"); + UserAgent userAgent = UserAgent.parseUserAgentString(agent); + OperatingSystem os = userAgent.getOperatingSystem(); + Browser browser = userAgent.getBrowser(); + String uri = request.getRequestURI(); + + BlogVisit blogVisit = new BlogVisit(); + blogVisit.setIp(IpUtils.getIpAddress(request)); + blogVisit.setOs(os.getName()); + blogVisit.setBrowser(browser.getName() + "-" + userAgent.getBrowserVersion()); + blogVisit.setUri(uri); + blogVisit.setBlogId(0L); + + if (blogVisit.getUri().contains("content")) { + blogVisit.setBlogId(Long.valueOf(uri.split("/")[3])); + } + + blogService.addBlogVisit(blogVisit); + } +} diff --git a/blog-service/src/main/java/com/cxx/blog/controller/BlogController.java b/blog-service/src/main/java/com/cxx/blog/controller/BlogController.java new file mode 100644 index 0000000..5c5af84 --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/controller/BlogController.java @@ -0,0 +1,62 @@ +package com.cxx.blog.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.blog.service.BlogService; +import com.cxx.common.ReadView; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogLatestDto; +import com.cxx.common.dto.blog.BlogStatsDto; +import com.cxx.common.vo.blog.BlogQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/blog") +@Tag(name = "查看博客") +public class BlogController { + @Resource + private BlogService blogService; + + @Operation(summary = "分页查询博客") + @GetMapping("/page") + public IPage queryBlogByPage(@RequestParam("currentPage") Integer currentPage, + @RequestParam("pageSize") Integer pageSize) { + return blogService.queryBlogByPage(currentPage, pageSize); + } + + @Operation(summary = "条件查询博客") + @GetMapping("/condition") + public @JsonView(ReadView.class) List queryBlogByCondition(BlogQueryVo query) { + return blogService.queryBlogByCondition(query); + } + + @Operation(summary = "查询博客内容") + @GetMapping("/content/{id}") + public @JsonView(ReadView.class) BlogDto queryBlogById(@PathVariable("id") long id) { + return blogService.queryBlogById(id); + } + + @Operation(summary = "查询博客分类") + @GetMapping("/category") + public List queryBlogCategory() { + return blogService.queryBlogCategory(); + } + + @Operation(summary = "查询博客统计信息") + @GetMapping("/stats") + public BlogStatsDto queryBlogStats() { + return blogService.queryBlogStats(); + } + + @Operation(summary = "查询近期博客") + @GetMapping("/latest") + public List queryLatestBlog() { + return blogService.queryLatestBlog(); + } +} \ No newline at end of file diff --git a/blog-service/src/main/java/com/cxx/blog/dao/BlogDao.java b/blog-service/src/main/java/com/cxx/blog/dao/BlogDao.java new file mode 100644 index 0000000..2914937 --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/dao/BlogDao.java @@ -0,0 +1,25 @@ +package com.cxx.blog.dao; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogLatestDto; +import com.cxx.common.entity.Blog; +import com.cxx.common.vo.blog.BlogQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface BlogDao { + IPage queryBlogByPage(IPage page); + + List queryBlogByCondition(@Param("query") BlogQueryVo query); + + BlogDto queryBlogById(@Param("id") Long id); + + List queryBlogCategory(); + + List queryLatestBlog(); +} diff --git a/blog-service/src/main/java/com/cxx/blog/service/BlogService.java b/blog-service/src/main/java/com/cxx/blog/service/BlogService.java new file mode 100644 index 0000000..c42b96d --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/service/BlogService.java @@ -0,0 +1,28 @@ +package com.cxx.blog.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogLatestDto; +import com.cxx.common.dto.blog.BlogStatsDto; +import com.cxx.common.entity.BlogVisit; +import com.cxx.common.vo.blog.BlogQueryVo; + +import java.util.List; + + +public interface BlogService { + IPage queryBlogByPage(Integer currentPage, Integer pageSize); + + List queryBlogByCondition(BlogQueryVo query); + + BlogDto queryBlogById(Long id); + + List queryBlogCategory(); + + BlogStatsDto queryBlogStats(); + + List queryLatestBlog(); + + void addBlogVisit(BlogVisit blogVisit); +} diff --git a/blog-service/src/main/java/com/cxx/blog/service/impl/BlogServiceImpl.java b/blog-service/src/main/java/com/cxx/blog/service/impl/BlogServiceImpl.java new file mode 100644 index 0000000..e7101b3 --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/service/impl/BlogServiceImpl.java @@ -0,0 +1,73 @@ +package com.cxx.blog.service.impl; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cxx.blog.dao.BlogDao; +import com.cxx.blog.service.BlogService; +import com.cxx.common.dto.blog.BlogCategoryDto; +import com.cxx.common.dto.blog.BlogDto; +import com.cxx.common.dto.blog.BlogLatestDto; +import com.cxx.common.dto.blog.BlogStatsDto; +import com.cxx.common.entity.BlogVisit; +import com.cxx.common.mapper.BlogCategoryMapper; +import com.cxx.common.mapper.BlogMapper; +import com.cxx.common.mapper.BlogVisitMapper; +import com.cxx.common.vo.blog.BlogQueryVo; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class BlogServiceImpl implements BlogService { + @Resource + private BlogDao blogDao; + + @Resource + private BlogMapper blogMapper; + + @Resource + private BlogCategoryMapper categoryMapper; + + @Resource + private BlogVisitMapper visitMapper; + + @Override + public IPage queryBlogByPage(Integer currentPage, Integer pageSize) { + return blogDao.queryBlogByPage(new Page<>(currentPage, pageSize)); + } + + @Override + public List queryBlogByCondition(BlogQueryVo query) { + return blogDao.queryBlogByCondition(query); + } + + @Override + public BlogDto queryBlogById(Long id) { + return blogDao.queryBlogById(id); + } + + @Override + public List queryBlogCategory() { + return blogDao.queryBlogCategory(); + } + + @Override + public BlogStatsDto queryBlogStats() { + BlogStatsDto blogStats = new BlogStatsDto(); + blogStats.setBlogCount(blogMapper.selectCount(null)); + blogStats.setCategoryCount(categoryMapper.selectCount(null)); + + return blogStats; + } + + @Override + public List queryLatestBlog() { + return blogDao.queryLatestBlog(); + } + + @Override + public void addBlogVisit(BlogVisit blogVisit) { + visitMapper.insert(blogVisit); + } +} \ No newline at end of file diff --git a/blog-service/src/main/java/com/cxx/blog/util/BlogUtils.java b/blog-service/src/main/java/com/cxx/blog/util/BlogUtils.java new file mode 100644 index 0000000..e091b24 --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/util/BlogUtils.java @@ -0,0 +1,36 @@ +package com.cxx.blog.util; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class BlogUtils { + public static File multipartFileToFile(MultipartFile multipartFile) { + if (multipartFile.getOriginalFilename() == null) { + return null; + } + + File file = new File(multipartFile.getOriginalFilename()); + try { + InputStream ins = multipartFile.getInputStream(); + OutputStream os = new FileOutputStream(file); + int bytesRead = 0; + byte[] buffer = new byte[8192]; + while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { + os.write(buffer, 0, bytesRead); + } + os.close(); + ins.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + return file; + } +} diff --git a/blog-service/src/main/java/com/cxx/blog/util/IpUtils.java b/blog-service/src/main/java/com/cxx/blog/util/IpUtils.java new file mode 100644 index 0000000..36544ab --- /dev/null +++ b/blog-service/src/main/java/com/cxx/blog/util/IpUtils.java @@ -0,0 +1,59 @@ +package com.cxx.blog.util; + +import jakarta.servlet.http.HttpServletRequest; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class IpUtils { + private static final String UNKNOWN = "unknown"; + private static final String LOCALHOST_IP = "127.0.0.1"; + // 客户端与服务器同为一台机器,获取的 ip 有时候是 ipv6 格式 + private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1"; + private static final String SEPARATOR = ","; + + /** + * 根据 HttpServletRequest 获取 IP + * @param request 请求 + * @return ip + */ + public static String getIpAddress(HttpServletRequest request) { + if (request == null) { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.isEmpty() || UNKNOWN.equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + if (LOCALHOST_IP.equalsIgnoreCase(ip) || LOCALHOST_IPV6.equalsIgnoreCase(ip)) { + // 根据网卡取本机配置的 IP + InetAddress iNet = null; + try { + iNet = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + e.printStackTrace(); + } + if (iNet != null) + ip = iNet.getHostAddress(); + } + } + // 对于通过多个代理的情况,分割出第一个 IP + if (ip != null && ip.length() > 15) { + if (ip.indexOf(SEPARATOR) > 0) { + ip = ip.substring(0, ip.indexOf(SEPARATOR)); + } + } + return LOCALHOST_IPV6.equals(ip) ? LOCALHOST_IP : ip; + } +} diff --git a/blog-service/src/main/resources/application-dev.yml b/blog-service/src/main/resources/application-dev.yml new file mode 100644 index 0000000..e680bf2 --- /dev/null +++ b/blog-service/src/main/resources/application-dev.yml @@ -0,0 +1,11 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: 123456 + +logging: + level: + root: info + config: diff --git a/blog-service/src/main/resources/application-docker.yml b/blog-service/src/main/resources/application-docker.yml new file mode 100644 index 0000000..21f5ae1 --- /dev/null +++ b/blog-service/src/main/resources/application-docker.yml @@ -0,0 +1,13 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://mysql:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: docker + password: 19940822Cxx + +logging: + fluentd: + host: fluent-bit + port: 24224 + level: + root: info diff --git a/blog-service/src/main/resources/application-prod.yml b/blog-service/src/main/resources/application-prod.yml new file mode 100644 index 0000000..e8be661 --- /dev/null +++ b/blog-service/src/main/resources/application-prod.yml @@ -0,0 +1,12 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: cxx + password: 19940822Cxx@1213 + +logging: + level: + root: info + config: + classpath:logback-spring-drop.xml \ No newline at end of file diff --git a/blog-service/src/main/resources/application.yml b/blog-service/src/main/resources/application.yml new file mode 100644 index 0000000..8bd6ff3 --- /dev/null +++ b/blog-service/src/main/resources/application.yml @@ -0,0 +1,20 @@ +server: + port: 8082 + +spring: + application: + name: @project.artifactId@ + version: @project.version@ + profiles: + active: dev + +# mybatis plus mapper路径 +mybatis-plus: + # mybatis plus + mapper-locations: classpath*:/mapper/**/*.xml + configuration: + log-impl: + org.apache.ibatis.logging.stdout.StdOutImpl + +web-starter: + base-package: com.cxx.blog \ No newline at end of file diff --git a/blog-service/src/main/resources/logback-spring-drop.xml b/blog-service/src/main/resources/logback-spring-drop.xml new file mode 100644 index 0000000..1a73420 --- /dev/null +++ b/blog-service/src/main/resources/logback-spring-drop.xml @@ -0,0 +1,120 @@ + + + + logback + + + + + + + + + + + + + + + + + + + + + + DEBUG + + + + ${CONSOLE_LOG_PATTERN} + + ${ENCODING} + + + + + + + + INFO + ACCEPT + DENY + + + ${log.path}/log_info.log + + ${FILE_LOG_PATTERN} + ${ENCODING} + + + + + ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log + + 500MB + + + 15 + + + + + + + WARN + ACCEPT + DENY + + + ${log.path}/log_warn.log + + ${FILE_LOG_PATTERN} + ${ENCODING} + + + + ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + + + + ERROR + ACCEPT + DENY + + + ${log.path}/log_error.log + + ${FILE_LOG_PATTERN} + ${ENCODING} + + + + ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log + + 100MB + + + 15 + + + + + + + + + + + \ No newline at end of file diff --git a/blog-service/src/main/resources/mapper/blogMapper.xml b/blog-service/src/main/resources/mapper/blogMapper.xml new file mode 100644 index 0000000..a848ae3 --- /dev/null +++ b/blog-service/src/main/resources/mapper/blogMapper.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/blog-service/src/test/java/com/cxx/blog/BlogServiceTest.java b/blog-service/src/test/java/com/cxx/blog/BlogServiceTest.java new file mode 100644 index 0000000..78081b5 --- /dev/null +++ b/blog-service/src/test/java/com/cxx/blog/BlogServiceTest.java @@ -0,0 +1,18 @@ +package com.cxx.blog; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * @Author: Cxx + * @Date: 2024/9/22 0:17 + * @Description: + */ +@SpringBootTest +public class BlogServiceTest { + + @Test + public void test() { + + } +} diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/common/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..c9e8d75 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + com.cxx + sweet-hut-service + 2.0.0 + + + common + 2.0.0 + + jar + + + 17 + 17 + UTF-8 + + + + + com.cxx + starter-web + 2.0.0 + + + com.cxx + starter-jdbc + 2.0.0 + + + com.cxx + starter-logging + 2.0.0 + + + \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/PlainView.java b/common/src/main/java/com/cxx/common/PlainView.java new file mode 100644 index 0000000..90cf6e2 --- /dev/null +++ b/common/src/main/java/com/cxx/common/PlainView.java @@ -0,0 +1,4 @@ +package com.cxx.common; + +public interface PlainView { +} diff --git a/common/src/main/java/com/cxx/common/ReadView.java b/common/src/main/java/com/cxx/common/ReadView.java new file mode 100644 index 0000000..8fd71de --- /dev/null +++ b/common/src/main/java/com/cxx/common/ReadView.java @@ -0,0 +1,4 @@ +package com.cxx.common; + +public interface ReadView extends PlainView { +} diff --git a/common/src/main/java/com/cxx/common/WriteView.java b/common/src/main/java/com/cxx/common/WriteView.java new file mode 100644 index 0000000..92a9858 --- /dev/null +++ b/common/src/main/java/com/cxx/common/WriteView.java @@ -0,0 +1,4 @@ +package com.cxx.common; + +public interface WriteView extends PlainView { +} diff --git a/common/src/main/java/com/cxx/common/dto/StatsChartDto.java b/common/src/main/java/com/cxx/common/dto/StatsChartDto.java new file mode 100644 index 0000000..d5bdb8e --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/StatsChartDto.java @@ -0,0 +1,11 @@ +package com.cxx.common.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class StatsChartDto { + private String name; + private Double value; +} diff --git a/common/src/main/java/com/cxx/common/dto/bill/BillCategoryDto.java b/common/src/main/java/com/cxx/common/dto/bill/BillCategoryDto.java new file mode 100644 index 0000000..f5c912c --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/bill/BillCategoryDto.java @@ -0,0 +1,18 @@ +package com.cxx.common.dto.bill; + +import com.cxx.common.PlainView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class BillCategoryDto extends BillItemDto{ + @Schema(description = "账本名称") + private String bookName; + + @Schema(description = "账本类型") + private String type; +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/dto/bill/BillItemDto.java b/common/src/main/java/com/cxx/common/dto/bill/BillItemDto.java new file mode 100644 index 0000000..6d2012b --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/bill/BillItemDto.java @@ -0,0 +1,26 @@ +package com.cxx.common.dto.bill; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class BillItemDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "名称") + private String name; + + @Schema(description = "图标") + private String icon; + + @Schema(description = "颜色") + private String color; +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/dto/bill/BillRecordDto.java b/common/src/main/java/com/cxx/common/dto/bill/BillRecordDto.java new file mode 100644 index 0000000..0fb23c0 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/bill/BillRecordDto.java @@ -0,0 +1,52 @@ +package com.cxx.common.dto.bill; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class BillRecordDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "账本名称") + private String bookName; + + @Schema(description = "账单类型") + private String type; + + @Schema(description = "账单类别") + private String category; + + @Schema(description = "账单地点") + private String location; + + @Schema(description = "账单账户") + private String payAccount; + + @Schema(description = "账单金额") + private Double amount; + + @Schema(description = "账单内容") + private String content; + + @Schema(description = "账单备注") + private String remark; + + @Schema(description = "账单图片") + private List imageList; + + @Schema(description = "账单日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/dto/bill/BillSummaryDto.java b/common/src/main/java/com/cxx/common/dto/bill/BillSummaryDto.java new file mode 100644 index 0000000..163d507 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/bill/BillSummaryDto.java @@ -0,0 +1,49 @@ +package com.cxx.common.dto.bill; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class BillSummaryDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "账本名称") + private String bookName; + + @Schema(description = "账单类型") + private String type; + + @Schema(description = "账单类别") + private String category; + + @Schema(description = "账单地点") + private String location; + + @Schema(description = "账单账户") + private String payAccount; + + @Schema(description = "账单金额") + private Double amount; + + @Schema(description = "账单内容") + private String content; + + @Schema(description = "账单备注") + private String remark; + + @Schema(description = "账单日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/dto/blog/BlogCategoryDto.java b/common/src/main/java/com/cxx/common/dto/blog/BlogCategoryDto.java new file mode 100644 index 0000000..36bb833 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/blog/BlogCategoryDto.java @@ -0,0 +1,15 @@ +package com.cxx.common.dto.blog; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class BlogCategoryDto { + @Schema(description = "类别名称") + private String name; + + @Schema(description = "类别数量") + private Integer count; +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/dto/blog/BlogDto.java b/common/src/main/java/com/cxx/common/dto/blog/BlogDto.java new file mode 100644 index 0000000..67904d2 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/blog/BlogDto.java @@ -0,0 +1 @@ +package com.cxx.common.dto.blog; import com.cxx.common.PlainView; import com.cxx.common.ReadView; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; import lombok.Setter; import java.util.Date; @Getter @Setter @JsonView(PlainView.class) public class BlogDto { @Schema(description = "id") @JsonView(ReadView.class) private Long id; @Schema(description = "博客标题") private String title; @Schema(description = "置顶值") private Integer topValue; @Schema(description = "是否是精品") private Boolean isGreat; @Schema(description = "博客类别") private String category; @Schema(description = "博客简介") @JsonView(ReadView.class) private String summary; @Schema(description = "博客内容") private String content; @Schema(description = "博客字数") @JsonView(ReadView.class) private Integer wordCount; @Schema(description = "博客时长") @JsonView(ReadView.class) private Double readDuration; @Schema(description = "博客访问人数") @JsonView(ReadView.class) private Integer visitCount; @Schema(description = "创建时间") @JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonView(ReadView.class) private Date createTime; @Schema(description = "更新时间") @JsonFormat(pattern = "YYYY-MM-dd HH:mm:ss", timezone = "GMT+8") @JsonView(ReadView.class) private Date updateTime; } \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/dto/blog/BlogLatestDto.java b/common/src/main/java/com/cxx/common/dto/blog/BlogLatestDto.java new file mode 100644 index 0000000..60ac2c0 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/blog/BlogLatestDto.java @@ -0,0 +1,20 @@ +package com.cxx.common.dto.blog; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * @Author: Cxx + * @Date: 2024/9/16 19:47 + * @Description: + */ +@Getter +@Setter +public class BlogLatestDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "博客标题") + private String title; +} diff --git a/common/src/main/java/com/cxx/common/dto/blog/BlogStatsDto.java b/common/src/main/java/com/cxx/common/dto/blog/BlogStatsDto.java new file mode 100644 index 0000000..5a03072 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/blog/BlogStatsDto.java @@ -0,0 +1,20 @@ +package com.cxx.common.dto.blog; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * @Author: Cxx + * @Date: 2024/9/16 19:47 + * @Description: + */ +@Getter +@Setter +public class BlogStatsDto { + @Schema(description = "博客数量") + private Long blogCount; + + @Schema(description = "博客类别数量") + private Long categoryCount; +} diff --git a/common/src/main/java/com/cxx/common/dto/blog/BlogVisitDto.java b/common/src/main/java/com/cxx/common/dto/blog/BlogVisitDto.java new file mode 100644 index 0000000..fd8346b --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/blog/BlogVisitDto.java @@ -0,0 +1,31 @@ +package com.cxx.common.dto.blog; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +public class BlogVisitDto { + @Schema(description = "访问ip") + private String ip; + + @Schema(description = "访问系统") + private String os; + + @Schema(description = "访问浏览器") + private String browser; + + @Schema(description = "访问路径") + private String uri; + + @Schema(description = "博客标题") + private String title; + + @Schema(description = "访问时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date visitTime; +} diff --git a/common/src/main/java/com/cxx/common/dto/budget/BudgetDto.java b/common/src/main/java/com/cxx/common/dto/budget/BudgetDto.java new file mode 100644 index 0000000..bbed016 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/budget/BudgetDto.java @@ -0,0 +1,51 @@ +package com.cxx.common.dto.budget; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.PositiveOrZero; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class BudgetDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "预算类别") + @NotBlank(message = "类别不能为空") + private String category; + + @Schema(description = "预算项目") + @NotBlank(message = "项目不能为空") + private String project; + + @Schema(description = "预算内容") + private String content; + + @Schema(description = "供应商") + private String vendor; + + @Schema(description = "预算支出") + @PositiveOrZero(message = "预算支出支出必须大于等于0") + private Double budget; + + @Schema(description = "实际支出") + @PositiveOrZero(message = "实际支出支出必须大于等于0") + private Double actual; + + @Schema(description = "支付时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date payTime; + + @Schema(description = "备注") + private String remake; +} diff --git a/common/src/main/java/com/cxx/common/dto/message/MailMessageDto.java b/common/src/main/java/com/cxx/common/dto/message/MailMessageDto.java new file mode 100644 index 0000000..23d199f --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/message/MailMessageDto.java @@ -0,0 +1,10 @@ +package com.cxx.common.dto.message; + +import lombok.Data; + +@Data +public class MailMessageDto { + private String to; + private String subject; + private String body; +} diff --git a/common/src/main/java/com/cxx/common/dto/plan/PlanDto.java b/common/src/main/java/com/cxx/common/dto/plan/PlanDto.java new file mode 100644 index 0000000..a8b6047 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/plan/PlanDto.java @@ -0,0 +1,62 @@ +package com.cxx.common.dto.plan; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class PlanDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "标题") + @NotBlank(message = "标题不能为空") + private String title; + + @Schema(description = "内容") + private String content; + + @Schema(description = "日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "开始时间") + @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") + private Date startTime; + + @Schema(description = "结束时间") + @JsonFormat(pattern = "HH:mm", timezone = "GMT+8") + private Date endTime; + + @Schema(description = "提醒时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date alterTime; + + @Schema(description = "邮箱地址") + private String email; + + @Schema(description = "任务id") + private Long taskId; + + @Schema(description = "标签") + private String tag; + + @Schema(description = "是否置顶") + private Integer isTop; + + @Schema(description = "优先级") + private Integer priority; + + @Schema(description = "是否完成") + private Integer completed; +} diff --git a/common/src/main/java/com/cxx/common/dto/plan/PlanStatsDto.java b/common/src/main/java/com/cxx/common/dto/plan/PlanStatsDto.java new file mode 100644 index 0000000..8bb37f8 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/plan/PlanStatsDto.java @@ -0,0 +1,21 @@ +package com.cxx.common.dto.plan; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PlanStatsDto { + @Schema(description = "计划总数") + private Integer totalCount; + + @Schema(description = "完成总数") + private Integer completedCount; + + @Schema(description = "当前计划") + private Integer currentCount; + + @Schema(description = "过期计划") + private Integer remainCount; +} diff --git a/common/src/main/java/com/cxx/common/dto/task/TaskDto.java b/common/src/main/java/com/cxx/common/dto/task/TaskDto.java new file mode 100644 index 0000000..17e94cf --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/task/TaskDto.java @@ -0,0 +1,25 @@ +package com.cxx.common.dto.task; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +public class TaskDto { + @Schema(description = "任务类型") + private String type; + + @Schema(description = "任务内容") + private String content; + + @Schema(description = "执行时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date executeTime; + + @Schema(description = "定时任务表达式") + private String cronExpression; +} diff --git a/common/src/main/java/com/cxx/common/dto/user/SessionDto.java b/common/src/main/java/com/cxx/common/dto/user/SessionDto.java new file mode 100644 index 0000000..aa221ce --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/user/SessionDto.java @@ -0,0 +1,17 @@ +package com.cxx.common.dto.user; + +import cn.dev33.satoken.stp.SaTokenInfo; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class SessionDto { + @Schema(description = "令牌") + private SaTokenInfo saToken; + + @Schema(description = "用户信息") + private UserDto userInfo; +} + diff --git a/common/src/main/java/com/cxx/common/dto/user/UserDto.java b/common/src/main/java/com/cxx/common/dto/user/UserDto.java new file mode 100644 index 0000000..ff4b802 --- /dev/null +++ b/common/src/main/java/com/cxx/common/dto/user/UserDto.java @@ -0,0 +1,68 @@ +package com.cxx.common.dto.user; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class UserDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "账号id") + @JsonView(ReadView.class) + private Long accountId; + + @Schema(description = "账号名称") + @JsonView(ReadView.class) + private String accountName; + + @Schema(description = "用户名称") + @NotBlank(message = "用户名称不能为空") + private String username; + + @Schema(description = "性别") + private Integer gender; + + @Schema(description = "身份证号") + private String idNumber; + + @Schema(description = "手机号码") + private String phoneNumber; + + @Schema(description = "电子邮件") + private String email; + + @Schema(description = "生日") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date birthDate; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "地区") + private List area; + + @Schema(description = "地址") + private String address; + + @Schema(description = "职业") + private String job; + + @Schema(description = "标签") + private List tags; + + @Schema(description = "描述") + private String description; +} diff --git a/common/src/main/java/com/cxx/common/entity/Account.java b/common/src/main/java/com/cxx/common/entity/Account.java new file mode 100644 index 0000000..b89efd9 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/Account.java @@ -0,0 +1,24 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("account") +public class Account extends AbstractEntity { + @TableField("account_name") + private String accountName; + + @TableField("password") + private String password; + + @TableField("user_id") + private Long userId; + + @TableField("state") + private Integer state; +} diff --git a/common/src/main/java/com/cxx/common/entity/BillBook.java b/common/src/main/java/com/cxx/common/entity/BillBook.java new file mode 100644 index 0000000..8a5f29b --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BillBook.java @@ -0,0 +1,21 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("bill_book") +public class BillBook extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("icon") + private String icon; + + @TableField("color") + private String color; +} diff --git a/common/src/main/java/com/cxx/common/entity/BillCategory.java b/common/src/main/java/com/cxx/common/entity/BillCategory.java new file mode 100644 index 0000000..1cb537d --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BillCategory.java @@ -0,0 +1,27 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("bill_category") +public class BillCategory extends AbstractEntity { + @TableField("book_id") + private Long bookId; + + @TableField("name") + private String name; + + @TableField("type") + private String type; + + @TableField("icon") + private String icon; + + @TableField("color") + private String color; +} diff --git a/common/src/main/java/com/cxx/common/entity/BillImage.java b/common/src/main/java/com/cxx/common/entity/BillImage.java new file mode 100644 index 0000000..a005e9f --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BillImage.java @@ -0,0 +1,15 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("bill_image") +public class BillImage { + @TableField("bill_id") + private Long billId; + + @TableField("image_url") + private String imageUrl; +} diff --git a/common/src/main/java/com/cxx/common/entity/BillPay.java b/common/src/main/java/com/cxx/common/entity/BillPay.java new file mode 100644 index 0000000..96f97d6 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BillPay.java @@ -0,0 +1,21 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("bill_pay") +public class BillPay extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("icon") + private String icon; + + @TableField("color") + private String color; +} diff --git a/common/src/main/java/com/cxx/common/entity/BillRecord.java b/common/src/main/java/com/cxx/common/entity/BillRecord.java new file mode 100644 index 0000000..36dd7b5 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BillRecord.java @@ -0,0 +1,41 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("bill_record") +public class BillRecord extends AbstractEntity { + @TableField("book_id") + private Long bookId; + + @TableField("type") + private String type; + + @TableField("category_id") + private Long categoryId; + + @TableField("location") + private String location; + + @TableField("date") + private Date date; + + @TableField("amount") + private Double amount; + + @TableField("content") + private String content; + + @TableField("pay_id") + private Long payId; + + @TableField("remark") + private String remark; +} diff --git a/common/src/main/java/com/cxx/common/entity/Blog.java b/common/src/main/java/com/cxx/common/entity/Blog.java new file mode 100644 index 0000000..4aa6e27 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/Blog.java @@ -0,0 +1,36 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("blog") +public class Blog extends AbstractEntity { + @TableField("title") + private String title; + + @TableField("top_value") + private Integer topValue; + + @TableField("is_great") + private Boolean isGreat; + + @TableField("category_id") + private Long categoryId; + + @TableField("summary") + private String summary; + + @TableField("content_id") + private Long contentId; + + @TableField("word_count") + private Integer wordCount; + + @TableField("read_duration") + private Double readDuration; +} diff --git a/common/src/main/java/com/cxx/common/entity/BlogCategory.java b/common/src/main/java/com/cxx/common/entity/BlogCategory.java new file mode 100644 index 0000000..e6734f6 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BlogCategory.java @@ -0,0 +1,20 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author: Cxx + * @Date: 2024/9/15 10:11 + * @Description: 博客分类 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("blog_category") +public class BlogCategory extends AbstractEntity { + @TableField("name") + private String name; +} diff --git a/common/src/main/java/com/cxx/common/entity/BlogContent.java b/common/src/main/java/com/cxx/common/entity/BlogContent.java new file mode 100644 index 0000000..cc88b57 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BlogContent.java @@ -0,0 +1,20 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * @Author: Cxx + * @Date: 2024/9/15 10:09 + * @Description: 博客内容 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("blog_content") +public class BlogContent extends AbstractIdEntity { + @TableField("content") + private String content; +} diff --git a/common/src/main/java/com/cxx/common/entity/BlogVisit.java b/common/src/main/java/com/cxx/common/entity/BlogVisit.java new file mode 100644 index 0000000..70b3a81 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BlogVisit.java @@ -0,0 +1,27 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("blog_visit") +public class BlogVisit extends AbstractEntity { + @TableField("ip") + private String ip; + + @TableField("os") + private String os; + + @TableField("browser") + private String browser; + + @TableField("uri") + private String uri; + + @TableField("blog_id") + private Long blogId; +} diff --git a/common/src/main/java/com/cxx/common/entity/Budget.java b/common/src/main/java/com/cxx/common/entity/Budget.java new file mode 100644 index 0000000..e6643be --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/Budget.java @@ -0,0 +1,38 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("budget") +public class Budget extends AbstractEntity { + @TableField("category_id") + private Long categoryId; + + @TableField("project") + private String project; + + @TableField("content") + private String content; + + @TableField("vendor") + private String vendor; + + @TableField("budget") + private Double budget; + + @TableField("actual") + private Double actual; + + @TableField("pay_time") + private Date payTime; + + @TableField("remake") + private String remake; +} diff --git a/common/src/main/java/com/cxx/common/entity/BudgetCategory.java b/common/src/main/java/com/cxx/common/entity/BudgetCategory.java new file mode 100644 index 0000000..d16ff08 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/BudgetCategory.java @@ -0,0 +1,15 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("budget_category") +public class BudgetCategory extends AbstractEntity { + @TableField("name") + private String name; +} diff --git a/common/src/main/java/com/cxx/common/entity/FileRecord.java b/common/src/main/java/com/cxx/common/entity/FileRecord.java new file mode 100644 index 0000000..75e4bbd --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/FileRecord.java @@ -0,0 +1,24 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("file_record") +public class FileRecord extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("md5") + private String md5; + + @TableField("path") + private String path; + + @TableField("url") + private String url; +} diff --git a/common/src/main/java/com/cxx/common/entity/Plan.java b/common/src/main/java/com/cxx/common/entity/Plan.java new file mode 100644 index 0000000..bec12df --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/Plan.java @@ -0,0 +1,48 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("plan") +public class Plan extends AbstractEntity { + @TableField("title") + private String title; + + @TableField("content") + private String content; + + @TableField(value = "date", updateStrategy = FieldStrategy.ALWAYS) + private Date date; + + @TableField(value = "start_time", updateStrategy = FieldStrategy.ALWAYS) + private Date startTime; + + @TableField(value = "end_time", updateStrategy = FieldStrategy.ALWAYS) + private Date endTime; + + @TableField(value = "alter_time", updateStrategy = FieldStrategy.ALWAYS) + private Date alterTime; + + @TableField(value = "task_id", updateStrategy = FieldStrategy.ALWAYS) + private Long taskId; + + @TableField("tag") + private String tag; + + @TableField("is_top") + private Integer isTop; + + @TableField("priority") + private Integer priority; + + @TableField("completed") + private Integer completed; +} diff --git a/common/src/main/java/com/cxx/common/entity/Task.java b/common/src/main/java/com/cxx/common/entity/Task.java new file mode 100644 index 0000000..df7db43 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/Task.java @@ -0,0 +1,27 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("task") +public class Task extends AbstractIdEntity { + @TableField("type") + private String type; + + @TableField("content") + private String content; + + @TableField("execute_time") + private Date executeTime; + + @TableField("cron_expression") + private String cronExpression; +} diff --git a/common/src/main/java/com/cxx/common/entity/User.java b/common/src/main/java/com/cxx/common/entity/User.java new file mode 100644 index 0000000..54cd5a3 --- /dev/null +++ b/common/src/main/java/com/cxx/common/entity/User.java @@ -0,0 +1,52 @@ +package com.cxx.common.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName(value = "user", autoResultMap = true) +public class User extends AbstractEntity { + @TableField("username") + private String username; + + @TableField("gender") + private Integer gender; + + @TableField("id_number") + private String idNumber; + + @TableField("phone_number") + private String phoneNumber; + + @TableField("email") + private String email; + + @TableField("birth_date") + private Date birthDate; + + @TableField("avatar") + private String avatar; + + @TableField(value = "area", typeHandler = JacksonTypeHandler.class) + private List area; + + @TableField("address") + private String address; + + @TableField("job") + private String job; + + @TableField(value = "tags", typeHandler = JacksonTypeHandler.class) + private List tags; + + @TableField("description") + private String description; +} diff --git a/common/src/main/java/com/cxx/common/mapper/AccountMapper.java b/common/src/main/java/com/cxx/common/mapper/AccountMapper.java new file mode 100644 index 0000000..98e02ad --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/AccountMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.Account; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface AccountMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BillBookMapper.java b/common/src/main/java/com/cxx/common/mapper/BillBookMapper.java new file mode 100644 index 0000000..52451a0 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BillBookMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BillBook; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BillBookMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BillCategoryMapper.java b/common/src/main/java/com/cxx/common/mapper/BillCategoryMapper.java new file mode 100644 index 0000000..13d1a2b --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BillCategoryMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BillCategory; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BillCategoryMapper extends BaseMapper { +} diff --git a/common/src/main/java/com/cxx/common/mapper/BillImageMapper.java b/common/src/main/java/com/cxx/common/mapper/BillImageMapper.java new file mode 100644 index 0000000..5809400 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BillImageMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BillImage; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BillImageMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BillPayMapper.java b/common/src/main/java/com/cxx/common/mapper/BillPayMapper.java new file mode 100644 index 0000000..11a8e4d --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BillPayMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BillPay; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BillPayMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BillRecordMapper.java b/common/src/main/java/com/cxx/common/mapper/BillRecordMapper.java new file mode 100644 index 0000000..014d9cc --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BillRecordMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BillRecord; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BillRecordMapper extends BaseMapper { +} diff --git a/common/src/main/java/com/cxx/common/mapper/BlogCategoryMapper.java b/common/src/main/java/com/cxx/common/mapper/BlogCategoryMapper.java new file mode 100644 index 0000000..907a07c --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BlogCategoryMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BlogCategory; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BlogCategoryMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BlogContentMapper.java b/common/src/main/java/com/cxx/common/mapper/BlogContentMapper.java new file mode 100644 index 0000000..b349799 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BlogContentMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BlogContent; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BlogContentMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BlogMapper.java b/common/src/main/java/com/cxx/common/mapper/BlogMapper.java new file mode 100644 index 0000000..865077d --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BlogMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.Blog; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BlogMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BlogVisitMapper.java b/common/src/main/java/com/cxx/common/mapper/BlogVisitMapper.java new file mode 100644 index 0000000..3e1f101 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BlogVisitMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BlogVisit; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BlogVisitMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BudgetCategoryMapper.java b/common/src/main/java/com/cxx/common/mapper/BudgetCategoryMapper.java new file mode 100644 index 0000000..a9bf043 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BudgetCategoryMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.BudgetCategory; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BudgetCategoryMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/BudgetMapper.java b/common/src/main/java/com/cxx/common/mapper/BudgetMapper.java new file mode 100644 index 0000000..93ced54 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/BudgetMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.Budget; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface BudgetMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/FileRecordMapper.java b/common/src/main/java/com/cxx/common/mapper/FileRecordMapper.java new file mode 100644 index 0000000..1ba2e3d --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/FileRecordMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.FileRecord; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FileRecordMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/PlanMapper.java b/common/src/main/java/com/cxx/common/mapper/PlanMapper.java new file mode 100644 index 0000000..bcf5e82 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/PlanMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.Plan; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PlanMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/mapper/TaskMapper.java b/common/src/main/java/com/cxx/common/mapper/TaskMapper.java new file mode 100644 index 0000000..e24bedb --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/TaskMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.Task; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TaskMapper extends BaseMapper { +} diff --git a/common/src/main/java/com/cxx/common/mapper/UserMapper.java b/common/src/main/java/com/cxx/common/mapper/UserMapper.java new file mode 100644 index 0000000..d700d55 --- /dev/null +++ b/common/src/main/java/com/cxx/common/mapper/UserMapper.java @@ -0,0 +1,9 @@ +package com.cxx.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.common.entity.User; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserMapper extends BaseMapper { +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/vo/bill/BillQueryVo.java b/common/src/main/java/com/cxx/common/vo/bill/BillQueryVo.java new file mode 100644 index 0000000..a58e888 --- /dev/null +++ b/common/src/main/java/com/cxx/common/vo/bill/BillQueryVo.java @@ -0,0 +1,21 @@ +package com.cxx.common.vo.bill; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class BillQueryVo { + @Schema(description = "账本名称") + private String bookName; + + @Schema(description = "账单类型") + private String type; + + @Schema(description = "开始日期") + private String startDate; + + @Schema(description = "结束日期") + private String endDate; +} \ No newline at end of file diff --git a/common/src/main/java/com/cxx/common/vo/blog/BlogQueryVo.java b/common/src/main/java/com/cxx/common/vo/blog/BlogQueryVo.java new file mode 100644 index 0000000..303f03c --- /dev/null +++ b/common/src/main/java/com/cxx/common/vo/blog/BlogQueryVo.java @@ -0,0 +1,23 @@ +package com.cxx.common.vo.blog; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * @Author: Cxx + * @Date: 2024/9/16 19:52 + * @Description: + */ +@Getter +@Setter +public class BlogQueryVo { + @Schema(description = "博客类别") + private String category; + + @Schema(description = "博客标题") + private String title; + + @Schema(description = "博客年份") + private Integer year; +} diff --git a/common/src/main/java/com/cxx/common/vo/plan/PlanQueryVo.java b/common/src/main/java/com/cxx/common/vo/plan/PlanQueryVo.java new file mode 100644 index 0000000..63fac64 --- /dev/null +++ b/common/src/main/java/com/cxx/common/vo/plan/PlanQueryVo.java @@ -0,0 +1,15 @@ +package com.cxx.common.vo.plan; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class PlanQueryVo { + @Schema(description = "数据类型") + private String planType; + + @Schema(description = "排序类型") + private String orderType; +} diff --git a/home-service/Dockerfile b/home-service/Dockerfile new file mode 100644 index 0000000..94ced11 --- /dev/null +++ b/home-service/Dockerfile @@ -0,0 +1,6 @@ +FROM docker-0.unsee.tech/openjdk:11-jdk-slim +ARG JAR_FILE=target/*.jar +COPY $JAR_FILE app.jar +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime +RUN echo 'Asia/Shanghai' > /etc/timezone +ENTRYPOINT ["java","-jar","/app.jar"] \ No newline at end of file diff --git a/home-service/pom.xml b/home-service/pom.xml new file mode 100644 index 0000000..86734e4 --- /dev/null +++ b/home-service/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + + com.cxx + sweet-hut-service + 2.0.0 + + + home-service + 2.0.0 + + + 17 + 17 + UTF-8 + + + + + com.cxx + common + 2.0.0 + + + + + com.github.binarywang + weixin-java-mp + 4.7.5.B + + + + + + + org.graalvm.buildtools + native-maven-plugin + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/HomeServiceApplication.java b/home-service/src/main/java/com/cxx/home/HomeServiceApplication.java new file mode 100644 index 0000000..49ebf21 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/HomeServiceApplication.java @@ -0,0 +1,15 @@ +package com.cxx.home; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@MapperScan(basePackages = {"com.cxx.common.mapper", "com.cxx.home.mapper", "com.cxx.home.dao"}, sqlSessionTemplateRef = "sqlSessionTemplate") +@EnableScheduling +public class HomeServiceApplication { + public static void main(String[] args) { + SpringApplication.run(HomeServiceApplication.class, args); + } +} diff --git a/home-service/src/main/java/com/cxx/home/controller/AnniversaryController.java b/home-service/src/main/java/com/cxx/home/controller/AnniversaryController.java new file mode 100644 index 0000000..dbcb121 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/AnniversaryController.java @@ -0,0 +1,55 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.common.dto.StatsChartDto; +import com.cxx.home.dto.anniversary.AnniversaryDto; +import com.cxx.home.service.AnniversaryService; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/anniversary") +@Tag(name = "纪念日") +public class AnniversaryController { + @Resource + private AnniversaryService anniversaryService; + + @Operation(summary = "查询纪念日") + @GetMapping("") + public @JsonView(ReadView.class) List queryAnniversary(@RequestParam("category") String category) { + return anniversaryService.queryAnniversary(category); + } + + @Operation(summary = "新增纪念日") + @PostMapping("") + public Boolean addAnniversary(@RequestBody @JsonView(WriteView.class) @Validated AnniversaryDto anniversaryDto) { + return anniversaryService.addAnniversary(anniversaryDto); + } + + @Operation(summary = "更新纪念日") + @PutMapping("/{id}") + public Boolean updateAnniversary(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) AnniversaryDto anniversaryDto) { + return anniversaryService.updateAnniversary(id, anniversaryDto); + } + + @Operation(summary = "删除纪念日") + @DeleteMapping("/{id}") + public Boolean deleteAnniversary(@PathVariable("id") long id) { + return anniversaryService.deleteAnniversary(id); + } + + @Operation(summary = "查询纪念日类别") + @GetMapping("/category") + public List queryAnniversaryCategory() { + return anniversaryService.queryAnniversaryCategory(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/AssetController.java b/home-service/src/main/java/com/cxx/home/controller/AssetController.java new file mode 100644 index 0000000..9e53354 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/AssetController.java @@ -0,0 +1,54 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.asset.AssetDto; +import com.cxx.home.service.AssetService; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/asset") +@Tag(name = "资产") +public class AssetController { + @Resource + private AssetService assetService; + + @Operation(summary = "查询资产") + @GetMapping("") + public @JsonView(ReadView.class) List queryAsset(@RequestParam("category") String category) { + return assetService.queryAsset(category); + } + + @Operation(summary = "新增资产") + @PostMapping("") + public Boolean addAsset(@RequestBody @JsonView(WriteView.class) @Validated AssetDto assetDto) { + return assetService.addAsset(assetDto); + } + + @Operation(summary = "更新资产") + @PutMapping("/{id}") + public Boolean updateAsset(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) AssetDto assetDto) { + return assetService.updateAsset(id, assetDto); + } + + @Operation(summary = "删除资产") + @DeleteMapping("/{id}") + public Boolean deleteAsset(@PathVariable("id") long id) { + return assetService.deleteAsset(id); + } + + @Operation(summary = "查询资产类别") + @GetMapping("/category") + public List queryAssetCategory() { + return assetService.queryAssetCategory(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/BillController.java b/home-service/src/main/java/com/cxx/home/controller/BillController.java new file mode 100644 index 0000000..f846df7 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/BillController.java @@ -0,0 +1,82 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.bill.BillCategoryDto; +import com.cxx.common.dto.bill.BillItemDto; +import com.cxx.common.dto.bill.BillRecordDto; +import com.cxx.common.dto.bill.BillSummaryDto; +import com.cxx.home.service.BillRecordService; +import com.cxx.common.vo.bill.BillQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/bill") +@Tag(name = "账单记录") +public class BillController { + @Resource + private BillRecordService billRecordService; + + @Operation(summary = "新增账单") + @PostMapping("") + public Boolean addBillRecord(@RequestBody @JsonView(WriteView.class) BillRecordDto billRecordDto) { + return billRecordService.saveOrUpdateBillRecord(0L, billRecordDto); + } + + @Operation(summary = "更新账单") + @PutMapping("/{id}") + public Boolean updateBillRecord(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) BillRecordDto billRecordDto) { + return billRecordService.saveOrUpdateBillRecord(id, billRecordDto); + } + + @Operation(summary = "删除账单") + @DeleteMapping("/{id}") + public Boolean deleteBillRecord(@PathVariable("id") long id) { + return billRecordService.deleteBillRecord(id); + } + + @Operation(summary = "查询账单记录") + @GetMapping("/{id}") + public @JsonView(ReadView.class) BillRecordDto queryBillRecord(@PathVariable("id") long id) { + return billRecordService.queryBillRecord(id); + } + + @Operation(summary = "查询账单概要") + @GetMapping("/summary") + public @JsonView(ReadView.class) List queryBillSummary(BillQueryVo billQueryVo) { + return billRecordService.queryBillSummary(billQueryVo); + } + + @Operation(summary = "查询账单统计") + @GetMapping("/stats/{type}") + public List queryBillStats(@PathVariable("type") String type, BillQueryVo billQueryVo) { + return billRecordService.queryBillStats(type, billQueryVo); + } + + @Operation(summary = "查询账户") + @GetMapping("/pay") + public @JsonView(ReadView.class) List queryBillPay() { + return billRecordService.queryBillPay(); + } + + @Operation(summary = "查询账本") + @GetMapping("/book") + public @JsonView(ReadView.class) List queryBillBook() { + return billRecordService.queryBillBook(); + } + + @Operation(summary = "查询账单类型") + @GetMapping("/category") + public List queryBillCategory() { + return billRecordService.queryBillCategory(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/BudgetController.java b/home-service/src/main/java/com/cxx/home/controller/BudgetController.java new file mode 100644 index 0000000..ed20b2f --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/BudgetController.java @@ -0,0 +1,67 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.budget.BudgetDto; +import com.cxx.home.service.BudgetService; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/budget") +@Tag(name = "预算统计") +public class BudgetController { + @Resource + private BudgetService budgetService; + + @Operation(summary = "查询预算类别") + @GetMapping("/category") + public List queryBudgetCategory() { + return budgetService.queryBudgetCategory(); + } + + @Operation(summary = "新增预算") + @PostMapping("") + public Boolean addBudget(@RequestBody @JsonView(WriteView.class) @Validated BudgetDto budgetDto) { + return budgetService.addBudget(budgetDto); + } + + @Operation(summary = "更新预算") + @PutMapping("/{id}") + public Boolean updateBudget(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) BudgetDto budgetDto) { + return budgetService.updateBudget(id, budgetDto); + } + + @Operation(summary = "删除预算") + @DeleteMapping("/{id}") + public Boolean deleteBudget(@PathVariable("id") long id) { + return budgetService.deleteBudget(id); + } + + @Operation(summary = "查询预算") + @GetMapping("") + public @JsonView(ReadView.class) List queryBudget(@RequestParam("category") String category) { + return budgetService.queryBudget(category); + } + + @Operation(summary = "预算排行统计") + @GetMapping("stats/rank") + public List queryBudgetRankStats(@RequestParam("category") String category) { + return budgetService.queryBudgetRankStats(category); + } + + @Operation(summary = "预算项目统计") + @GetMapping("stats/project") + public List queryBudgetProjectStats(@RequestParam("category") String category) { + return budgetService.queryBudgetProjectStats(category); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/FoodController.java b/home-service/src/main/java/com/cxx/home/controller/FoodController.java new file mode 100644 index 0000000..c3229c0 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/FoodController.java @@ -0,0 +1,105 @@ +package com.cxx.home.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.food.FoodRecipeDto; +import com.cxx.home.dto.food.FoodRecordDto; +import com.cxx.home.dto.food.FoodStatsDto; +import com.cxx.home.dto.food.FoodSummaryDto; +import com.cxx.home.service.FoodService; +import com.cxx.home.vo.FoodQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/food") +@Tag(name = "美食记录") +public class FoodController { + @Resource + private FoodService foodService; + + @Operation(summary = "新增美食菜谱") + @PostMapping("/recipe") + public Boolean addFoodRecipe(@RequestBody @JsonView(WriteView.class) @Validated FoodRecipeDto foodRecipeDto) { + return foodService.addFoodRecipe(foodRecipeDto); + } + + @Operation(summary = "更新美食菜谱") + @PutMapping("/recipe/{id}") + public Boolean updateFoodRecipe(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) FoodRecipeDto foodRecipeDto) { + return foodService.updateFoodRecipe(id, foodRecipeDto); + } + + @Operation(summary = "删除美食菜谱") + @DeleteMapping("/recipe/{id}") + public Boolean deleteFoodRecipe(@PathVariable("id") long id) { + return foodService.deleteFoodRecipe(id); + } + + @Operation(summary = "分页查询美食菜谱") + @GetMapping("/recipe/page") + public IPage queryFoodSummary(@RequestParam("currentPage") Integer currentPage, + @RequestParam("pageSize") Integer pageSize, + FoodQueryVo foodQueryVo) { + return foodService.queryFoodSummary(currentPage, pageSize, foodQueryVo); + } + + @Operation(summary = "查询美食") + @GetMapping("/recipe/{id}") + public @JsonView(ReadView.class) FoodRecipeDto queryFoodRecipe(@PathVariable("id") long id) { + return foodService.queryFoodRecipe(id); + } + + @Operation(summary = "查询所有美食名称") + @GetMapping("/recipe/name") + public List queryFoodName() { + return foodService.queryFoodName(); + } + + @Operation(summary = "新增美食成果") + @PostMapping("/record") + public Boolean addFoodRecord(@RequestBody @JsonView(WriteView.class) @Validated FoodRecordDto foodRecordDto) { + return foodService.addFoodRecord(foodRecordDto); + } + + @Operation(summary = "更新美食成果") + @PutMapping("/record/{id}") + public Boolean updateFoodRecord(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) FoodRecordDto foodRecordDto) { + return foodService.updateFoodRecord(id, foodRecordDto); + } + + @Operation(summary = "删除美食成果") + @DeleteMapping("/record/{id}") + public Boolean deleteFoodRecord(@PathVariable("id") long id) { + return foodService.deleteFoodRecord(id); + } + + @Operation(summary = "查询美食记录") + @GetMapping("/record") + public @JsonView(ReadView.class) List queryFoodRecord(@RequestParam("startDate") String startDate, + @RequestParam("endDate") String endDate) { + return foodService.queryFoodRecord(startDate, endDate); + } + + @Operation(summary = "查询美食类别") + @GetMapping("/category") + public List queryFoodCategory() { + return foodService.queryFoodCategory(); + } + + @Operation(summary = "查询美食统计") + @GetMapping("/stats") + public FoodStatsDto queryFoodStats() { + return foodService.queryFoodStats(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/JournalController.java b/home-service/src/main/java/com/cxx/home/controller/JournalController.java new file mode 100644 index 0000000..e98ae09 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/JournalController.java @@ -0,0 +1,50 @@ + +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.journal.JournalDto; +import com.cxx.home.service.JournalService; +import com.cxx.home.vo.JournalQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/journal") +@Tag(name = "日记") +public class JournalController { + @Resource + private JournalService journalService; + + @Operation(summary = "查询日记") + @GetMapping("") + public @JsonView(ReadView.class) List queryJournal(JournalQueryVo queryVo) { + return journalService.queryJournal(queryVo); + } + + @Operation(summary = "新增日记") + @PostMapping("") + public Boolean addAnniversary(@RequestBody @JsonView(WriteView.class) @Validated JournalDto journalDto) { + return journalService.addJournal(journalDto); + } + + @Operation(summary = "更新日记") + @PutMapping("/{id}") + public Boolean updateAnniversary(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) JournalDto journalDto) { + return journalService.updateJournal(id, journalDto); + } + + @Operation(summary = "删除日记") + @DeleteMapping("/{id}") + public Boolean deleteAnniversary(@PathVariable("id") long id) { + return journalService.deleteJournal(id); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/KpiController.java b/home-service/src/main/java/com/cxx/home/controller/KpiController.java new file mode 100644 index 0000000..cf2193f --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/KpiController.java @@ -0,0 +1,49 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.kpi.KpiDto; +import com.cxx.home.service.KpiService; +import com.cxx.home.vo.KpiQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/kpi") +@Tag(name = "绩效") +public class KpiController { + @Resource + private KpiService kpiService; + + @Operation(summary = "查询绩效") + @GetMapping("") + public @JsonView(ReadView.class) List queryKpi(KpiQueryVo queryVo) { + return kpiService.queryKpi(queryVo); + } + + @Operation(summary = "新增绩效") + @PostMapping("") + public Boolean addKpi(@RequestBody @JsonView(WriteView.class) @Validated KpiDto kpiDto) { + return kpiService.addKpi(kpiDto); + } + + @Operation(summary = "更新绩效") + @PutMapping("/{id}") + public Boolean updateKpi(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) KpiDto kpiDto) { + return kpiService.updateKpi(id, kpiDto); + } + + @Operation(summary = "删除绩效") + @DeleteMapping("/{id}") + public Boolean deleteKpi(@PathVariable("id") long id) { + return kpiService.deleteKpi(id); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/LedgerController.java b/home-service/src/main/java/com/cxx/home/controller/LedgerController.java new file mode 100644 index 0000000..a15d17d --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/LedgerController.java @@ -0,0 +1,54 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.ledger.LedgerDto; +import com.cxx.home.service.LedgerService; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/ledger") +@Tag(name = "账本") +public class LedgerController { + @Resource + private LedgerService ledgerService; + + @Operation(summary = "查询账本内容") + @GetMapping("") + public @JsonView(ReadView.class) List queryLedger(@RequestParam("book") String book) { + return ledgerService.queryLedger(book); + } + + @Operation(summary = "新增账本内容") + @PostMapping("") + public Boolean addLedger(@RequestBody @JsonView(WriteView.class) @Validated LedgerDto ledgerDto) { + return ledgerService.addLedger(ledgerDto); + } + + @Operation(summary = "更新账本内容") + @PutMapping("/{id}") + public Boolean updateLedger(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) LedgerDto ledgerDto) { + return ledgerService.updateLedger(id, ledgerDto); + } + + @Operation(summary = "删除账本内容") + @DeleteMapping("/{id}") + public Boolean deleteLedger(@PathVariable("id") long id) { + return ledgerService.deleteLedger(id); + } + + @Operation(summary = "查询账本") + @GetMapping("/book") + public List queryLedgerBook() { + return ledgerService.queryLedgerBook(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/PeriodController.java b/home-service/src/main/java/com/cxx/home/controller/PeriodController.java new file mode 100644 index 0000000..62ec578 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/PeriodController.java @@ -0,0 +1,55 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.period.PeriodDayDto; +import com.cxx.home.dto.period.PeriodSettingDto; +import com.cxx.home.service.PeriodService; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/period") +@Tag(name = "月经记录") +public class PeriodController { + @Resource + private PeriodService periodService; + + @Operation(summary = "查询月经天") + @GetMapping("/day") + public @JsonView(ReadView.class) List queryPeriodDay(@RequestParam("month") String month) { + return periodService.queryPeriodDay(month); + } + + @Operation(summary = "更新月经天") + @PutMapping("/day/{id}") + public Boolean updatePeriodDay(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) PeriodDayDto periodDayDto) { + return periodService.updatePeriodDay(id, periodDayDto); + } + + @Operation(summary = "获取当月月经初始天") + @GetMapping("/menstruate") + public String getMenstruateFirstDate(@RequestParam("month") String month) { + return periodService.getMenstruateFirstDate(month); + } + + @Operation(summary = "查询月经设置") + @GetMapping("/setting") + public @JsonView(ReadView.class) PeriodSettingDto queryPeriodSetting() { + return periodService.queryPeriodSetting(); + } + + @Operation(summary = "更新月经设置") + @PutMapping("/setting/{id}") + public Boolean updatePeriodSetting(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) PeriodSettingDto periodSettingDto) { + return periodService.updatePeriodSetting(id, periodSettingDto); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/PlanController.java b/home-service/src/main/java/com/cxx/home/controller/PlanController.java new file mode 100644 index 0000000..bdf21c2 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/PlanController.java @@ -0,0 +1,62 @@ +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.common.dto.plan.PlanDto; +import com.cxx.common.dto.plan.PlanStatsDto; +import com.cxx.common.vo.plan.PlanQueryVo; +import com.cxx.home.service.PlanService; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/plan") +@Tag(name = "日程安排") +public class PlanController { + @Resource + private PlanService planService; + + @Operation(summary = "查询日程安排") + @GetMapping("") + public @JsonView(ReadView.class) List queryPlan(PlanQueryVo query) { + return planService.queryPlan(query); + } + + @Operation(summary = "新增日程安排") + @PostMapping("") + public Boolean addPlan(@RequestBody @JsonView(WriteView.class) @Validated PlanDto planDto) { + return planService.addPlan(planDto); + } + + @Operation(summary = "更新日程安排") + @PutMapping("/{id}") + public Boolean updatePlan(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) PlanDto planDto) { + return planService.updatePlan(id, planDto); + } + + @Operation(summary = "删除日程安排") + @DeleteMapping("/{id}") + public Boolean deletePlan(@PathVariable("id") long id) { + return planService.deletePlan(id); + } + + @Operation(summary = "更新日程状态") + @PutMapping("/{id}/status") + public Boolean setPlanStatus(@PathVariable("id") long id, @RequestParam("status") boolean status) { + return planService.setPlanStatus(id, status); + } + + @Operation(summary = "查看日程统计") + @GetMapping("/stats") + public PlanStatsDto queryPlanStats() { + return planService.queryPlanStats(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/ProductController.java b/home-service/src/main/java/com/cxx/home/controller/ProductController.java new file mode 100644 index 0000000..b33a38a --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/ProductController.java @@ -0,0 +1,62 @@ + +package com.cxx.home.controller; + +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.product.ProductDto; +import com.cxx.home.service.ProductService; +import com.cxx.home.vo.ProductQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/product") +@Tag(name = "商品清单") +public class ProductController { + @Resource + private ProductService productService; + + @Operation(summary = "新增商品清单") + @PostMapping("") + public Boolean addProduct(@RequestBody @JsonView(WriteView.class) @Validated ProductDto productDto) { + return productService.addProduct(productDto); + } + + @Operation(summary = "更新商品清单") + @PutMapping("/{id}") + public Boolean updateProduct(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) @Validated ProductDto productDto) { + return productService.updateProduct(id, productDto); + } + + @Operation(summary = "删除商品清单") + @DeleteMapping("/{id}") + public Boolean deleteProduct(@PathVariable("id") long id) { + return productService.deleteProduct(id); + } + + @Operation(summary = "查询所有商品清单") + @GetMapping("") + public @JsonView(ReadView.class) List queryProductList(ProductQueryVo queryVo) { + return productService.queryProductList(queryVo); + } + + @Operation(summary = "查询商品清单") + @GetMapping("/{id}") + public @JsonView(ReadView.class) ProductDto queryProduct(@PathVariable("id") long id) { + return productService.queryProduct(id); + } + + @Operation(summary = "查询商品类别") + @GetMapping("/category") + public List queryProductCategory() { + return productService.queryProductCategory(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/QuartzController.java b/home-service/src/main/java/com/cxx/home/controller/QuartzController.java new file mode 100644 index 0000000..4aa59ef --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/QuartzController.java @@ -0,0 +1,26 @@ +package com.cxx.home.controller; + + +import com.cxx.home.schedule.QuartzDto; +import com.cxx.home.service.QuartzService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/quartz") +@Tag(name = "定时任务") +public class QuartzController { + @Resource + private QuartzService quartzService; + + @Operation(summary = "查询所有任务") + @GetMapping("") + public List queryQuartz() { + return quartzService.queryQuartzTask(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/SessionController.java b/home-service/src/main/java/com/cxx/home/controller/SessionController.java new file mode 100644 index 0000000..9a5c293 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/SessionController.java @@ -0,0 +1,28 @@ +package com.cxx.home.controller; + +import cn.dev33.satoken.annotation.SaIgnore; +import com.cxx.home.service.SessionService; +import com.cxx.common.dto.user.SessionDto; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/session") +@Tag(name = "会话管理") +public class SessionController { + @Resource + private SessionService sessionService; + + @Operation(summary = "创建会话") + @PostMapping("") + @SaIgnore + public SessionDto createSession(@RequestParam("name") String name, + @RequestParam("password") String password) { + return sessionService.create(name, password); + } +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/controller/TravelController.java b/home-service/src/main/java/com/cxx/home/controller/TravelController.java new file mode 100644 index 0000000..08654ff --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/controller/TravelController.java @@ -0,0 +1,105 @@ +package com.cxx.home.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.common.ReadView; +import com.cxx.common.WriteView; +import com.cxx.home.dto.travel.TravelRecordDto; +import com.cxx.home.dto.travel.TravelSpotDto; +import com.cxx.home.dto.travel.TravelStatsDto; +import com.cxx.home.dto.travel.TravelSummaryDto; +import com.cxx.home.service.TravelService; +import com.cxx.home.vo.TravelQueryVo; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/travel") +@Tag(name = "旅行记录") +public class TravelController { + @Resource + private TravelService travelService; + + @Operation(summary = "新增旅行景点") + @PostMapping("/spot") + public Boolean addTravelSpot(@RequestBody @JsonView(WriteView.class) @Validated TravelSpotDto travelSpotDto) { + return travelService.addTravelSpot(travelSpotDto); + } + + @Operation(summary = "更新旅行景点") + @PutMapping("/spot/{id}") + public Boolean updateTravelSpot(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) TravelSpotDto travelSpotDto) { + return travelService.updateTravelSpot(id, travelSpotDto); + } + + @Operation(summary = "删除旅行景点") + @DeleteMapping("/spot/{id}") + public Boolean deleteTravelSpot(@PathVariable("id") long id) { + return travelService.deleteTravelRecord(id); + } + + @Operation(summary = "分页查询旅行景点") + @GetMapping("/spot/page") + public IPage queryTravelSummary(@RequestParam("currentPage") Integer currentPage, + @RequestParam("pageSize") Integer pageSize, + TravelQueryVo travelQueryVo) { + return travelService.queryTravelSummary(currentPage, pageSize, travelQueryVo); + } + + @Operation(summary = "查询旅行景点") + @GetMapping("/spot/{id}") + public @JsonView(ReadView.class) TravelSpotDto queryTravelSpot(@PathVariable("id") long id) { + return travelService.queryTravelSpot(id); + } + + @Operation(summary = "查询所有旅行景点") + @GetMapping("/spot/name") + public List queryFoodName() { + return travelService.queryTravelSpotName(); + } + + @Operation(summary = "新增旅行记录") + @PostMapping("/record") + public Boolean addTravelRecord(@RequestBody @JsonView(WriteView.class) @Validated TravelRecordDto travelRecordDto) { + return travelService.addTravelRecord(travelRecordDto); + } + + @Operation(summary = "更新旅行记录") + @PutMapping("/record/{id}") + public Boolean updateTravelRecord(@PathVariable("id") long id, + @RequestBody @JsonView(WriteView.class) TravelRecordDto travelRecordDto) { + return travelService.updateTravelRecord(id, travelRecordDto); + } + + @Operation(summary = "删除旅行记录") + @DeleteMapping("/record/{id}") + public Boolean deleteTravelRecord(@PathVariable("id") long id) { + return travelService.deleteTravelRecord(id); + } + + @Operation(summary = "查询旅行记录") + @GetMapping("/record") + public @JsonView(ReadView.class) List queryTravelRecord(@RequestParam("startDate") String startDate, + @RequestParam("endDate") String endDate) { + return travelService.queryTravelRecord(startDate, endDate); + } + + @Operation(summary = "查询旅行类别") + @GetMapping("/category") + public List queryTravelCategory() { + return travelService.queryTravelCategory(); + } + + @Operation(summary = "查询旅行统计") + @GetMapping("/stats") + public TravelStatsDto queryTravelStats() { + return travelService.queryTravelStats(); + } +} + \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/dao/AnniversaryDao.java b/home-service/src/main/java/com/cxx/home/dao/AnniversaryDao.java new file mode 100644 index 0000000..e148add --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/AnniversaryDao.java @@ -0,0 +1,15 @@ +package com.cxx.home.dao; + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.home.dto.anniversary.AnniversaryDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface AnniversaryDao { + List queryAnniversary(@Param("category") String category); + + List queryAnniversaryCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/AssetDao.java b/home-service/src/main/java/com/cxx/home/dao/AssetDao.java new file mode 100644 index 0000000..b222e02 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/AssetDao.java @@ -0,0 +1,14 @@ +package com.cxx.home.dao; + +import com.cxx.home.dto.asset.AssetDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface AssetDao { + List queryAsset(@Param("category") String category); + + List queryAssetCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/BillDao.java b/home-service/src/main/java/com/cxx/home/dao/BillDao.java new file mode 100644 index 0000000..6364ba9 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/BillDao.java @@ -0,0 +1,27 @@ +package com.cxx.home.dao; + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.bill.*; +import com.cxx.common.vo.bill.BillQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface BillDao { + BillRecordDto queryBillRecord(@Param("id") Long id); + + List queryBillSummary(@Param("query") BillQueryVo query); + + void insertBillImage(@Param("billId") Long billId, + @Param("list") List imageFiles); + + List queryBillStats(@Param("type") String type, @Param("query") BillQueryVo query); + + List queryBillPay(); + + List queryBillBook(); + + List queryBillCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/BudgetDao.java b/home-service/src/main/java/com/cxx/home/dao/BudgetDao.java new file mode 100644 index 0000000..5f0a0cc --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/BudgetDao.java @@ -0,0 +1,17 @@ +package com.cxx.home.dao; + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.budget.BudgetDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface BudgetDao { + List queryBudget(@Param("category") String category); + + List queryBudgetRankStats(@Param("category") String category); + + List queryBudgetProjectStats(@Param("category") String category); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/FoodDao.java b/home-service/src/main/java/com/cxx/home/dao/FoodDao.java new file mode 100644 index 0000000..a6c3343 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/FoodDao.java @@ -0,0 +1,33 @@ +package com.cxx.home.dao; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.home.dto.food.*; +import com.cxx.home.vo.FoodQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface FoodDao { + FoodRecipeDto queryFoodRecipe(@Param("id") Long id); + + IPage queryFoodSummary(IPage page, + @Param("query") FoodQueryVo foodQueryVo); + + List queryFoodRecordById(@Param("id") Long id); + + List queryFoodRecord(@Param("startDate") String startDate, + @Param("endDate") String endDate); + + FoodStatsDto queryFoodStats(); + + List queryFoodCategory(); + + void insertFoodMaterial(@Param("foodId") Long foodId, + @Param("list") List list); + + void insertFoodStep(@Param("foodId") Long foodId, + @Param("list") List list); + +} diff --git a/home-service/src/main/java/com/cxx/home/dao/JournalDao.java b/home-service/src/main/java/com/cxx/home/dao/JournalDao.java new file mode 100644 index 0000000..72f2349 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/JournalDao.java @@ -0,0 +1,13 @@ +package com.cxx.home.dao; + +import com.cxx.home.dto.journal.JournalDto; +import com.cxx.home.vo.JournalQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface JournalDao { + List queryJournal(@Param("query") JournalQueryVo queryVo); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/KpiDao.java b/home-service/src/main/java/com/cxx/home/dao/KpiDao.java new file mode 100644 index 0000000..9190241 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/KpiDao.java @@ -0,0 +1,13 @@ +package com.cxx.home.dao; + +import com.cxx.home.dto.kpi.KpiDto; +import com.cxx.home.vo.KpiQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface KpiDao { + List queryKpi(@Param("query") KpiQueryVo queryVo); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/LedgerDao.java b/home-service/src/main/java/com/cxx/home/dao/LedgerDao.java new file mode 100644 index 0000000..badb22a --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/LedgerDao.java @@ -0,0 +1,14 @@ +package com.cxx.home.dao; + +import com.cxx.home.dto.ledger.LedgerDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface LedgerDao { + List queryLedger(@Param("book") String book); + + List queryLedgerBook(); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/PeriodDao.java b/home-service/src/main/java/com/cxx/home/dao/PeriodDao.java new file mode 100644 index 0000000..3d7cad9 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/PeriodDao.java @@ -0,0 +1,14 @@ +package com.cxx.home.dao; + +import com.cxx.home.dto.period.PeriodDayDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface PeriodDao { + List queryPeriodDay(@Param("month") String month); + + String getMenstruateFirstDate(@Param("month") String month); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/PlanDao.java b/home-service/src/main/java/com/cxx/home/dao/PlanDao.java new file mode 100644 index 0000000..9be6573 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/PlanDao.java @@ -0,0 +1,16 @@ +package com.cxx.home.dao; + +import com.cxx.common.dto.plan.PlanDto; +import com.cxx.common.dto.plan.PlanStatsDto; +import com.cxx.common.vo.plan.PlanQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface PlanDao { + List queryPlan(@Param("query") PlanQueryVo query); + + PlanStatsDto queryPlanStats(); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/ProductDao.java b/home-service/src/main/java/com/cxx/home/dao/ProductDao.java new file mode 100644 index 0000000..8a6747b --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/ProductDao.java @@ -0,0 +1,17 @@ +package com.cxx.home.dao; + +import com.cxx.home.dto.product.ProductDto; +import com.cxx.home.vo.ProductQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface ProductDao { + ProductDto queryProduct(@Param("id") Long id); + + List queryProductList(@Param("query") ProductQueryVo queryVo); + + List queryProductCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/dao/TravelDao.java b/home-service/src/main/java/com/cxx/home/dao/TravelDao.java new file mode 100644 index 0000000..034beb9 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dao/TravelDao.java @@ -0,0 +1,35 @@ +package com.cxx.home.dao; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.home.dto.travel.TravelRecordDto; +import com.cxx.home.dto.travel.TravelSpotDto; +import com.cxx.home.dto.travel.TravelStatsDto; +import com.cxx.home.dto.travel.TravelSummaryDto; +import com.cxx.home.vo.TravelQueryVo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface TravelDao { + TravelSpotDto queryTravelSpot(@Param("id") Long id); + + IPage queryTravelSummary(IPage page, + @Param("query") TravelQueryVo travelQueryVo); + + List queryTravelRecordById(@Param("id") Long id); + + List queryTravelRecord(@Param("startDate") String startDate, + @Param("endDate") String endDate); + + TravelStatsDto queryTravelStats(); + + List queryTravelCategory(); + + void insertTravelImage(@Param("recordId") Long recordId, + @Param("list") List imageFiles); + + void insertTravelVideo(@Param("recordId") Long recordId, + @Param("list") List videoFiles); +} diff --git a/home-service/src/main/java/com/cxx/home/dto/anniversary/AnniversaryDto.java b/home-service/src/main/java/com/cxx/home/dto/anniversary/AnniversaryDto.java new file mode 100644 index 0000000..5bbbff6 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/anniversary/AnniversaryDto.java @@ -0,0 +1,36 @@ +package com.cxx.home.dto.anniversary; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class AnniversaryDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "标题") + private String title; + + @Schema(description = "日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "是否重复") + private Boolean recurring; + + @Schema(description = "纪念日类型") + private String type; + + @Schema(description = "纪念日类别") + private String category; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/asset/AssetDto.java b/home-service/src/main/java/com/cxx/home/dto/asset/AssetDto.java new file mode 100644 index 0000000..ca8c888 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/asset/AssetDto.java @@ -0,0 +1,32 @@ +package com.cxx.home.dto.asset; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class AssetDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "类别") + private String category; + + @Schema(description = "名称") + private String name; + + @Schema(description = "金额") + private Double amount; + + @Schema(description = "所属人") + private String owner; + + @Schema(description = "备注") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/food/FoodMaterialDto.java b/home-service/src/main/java/com/cxx/home/dto/food/FoodMaterialDto.java new file mode 100644 index 0000000..c81ceda --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/food/FoodMaterialDto.java @@ -0,0 +1,24 @@ +package com.cxx.home.dto.food; + +import com.cxx.common.PlainView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodMaterialDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "食材类型") + private String type; + + @Schema(description = "食材名称") + private String name; + + @Schema(description = "食材分量") + private String amount; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/food/FoodRecipeDto.java b/home-service/src/main/java/com/cxx/home/dto/food/FoodRecipeDto.java new file mode 100644 index 0000000..20a0c0d --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/food/FoodRecipeDto.java @@ -0,0 +1,45 @@ +package com.cxx.home.dto.food; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Range; + +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodRecipeDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "美食名称") + @NotBlank(message = "名称不能为空") + private String name; + + @Schema(description = "美食菜系") + private String category; + + @Schema(description = "推荐指数") + @Range(min = 0, max = 5, message = "推荐指数在0-5之间") + private Integer recommendRate; + + @Schema(description = "美食食材") + private List materialList; + + @Schema(description = "美食步骤") + private List stepList; + + @Schema(description = "美食成果") + @JsonView(ReadView.class) + private List recordList; + + @Schema(description = "备注") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/food/FoodRecordDto.java b/home-service/src/main/java/com/cxx/home/dto/food/FoodRecordDto.java new file mode 100644 index 0000000..90951d0 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/food/FoodRecordDto.java @@ -0,0 +1,37 @@ +package com.cxx.home.dto.food; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodRecordDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "名称") + private String name; + + @Schema(description = "分类") + @JsonView(ReadView.class) + private String category; + + @Schema(description = "完成时间") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "完成人") + private String person; + + @Schema(description = "成果图片") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/food/FoodStatsDto.java b/home-service/src/main/java/com/cxx/home/dto/food/FoodStatsDto.java new file mode 100644 index 0000000..88658a1 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/food/FoodStatsDto.java @@ -0,0 +1,19 @@ +package com.cxx.home.dto.food; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Setter +public class FoodStatsDto { + @Schema(description = "菜谱总数") + private Integer recipeCount; + + @Schema(description = "菜谱类别") + private Integer categoryCount; + + @Schema(description = "做菜次数") + private Integer workCount; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/food/FoodStepDto.java b/home-service/src/main/java/com/cxx/home/dto/food/FoodStepDto.java new file mode 100644 index 0000000..645da10 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/food/FoodStepDto.java @@ -0,0 +1,24 @@ +package com.cxx.home.dto.food; + +import com.cxx.common.PlainView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class FoodStepDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "顺序") + private Integer sort; + + @Schema(description = "步骤内容") + private String content; + + @Schema(description = "步骤图片") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/food/FoodSummaryDto.java b/home-service/src/main/java/com/cxx/home/dto/food/FoodSummaryDto.java new file mode 100644 index 0000000..c712178 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/food/FoodSummaryDto.java @@ -0,0 +1,26 @@ +package com.cxx.home.dto.food; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class FoodSummaryDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "美食名称") + private String name; + + @Schema(description = "美食类型") + private String category; + + @Schema(description = "推荐指数") + private Integer recommendRate; + + @Schema(description = "美食记录") + private List recordList; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/journal/JournalDto.java b/home-service/src/main/java/com/cxx/home/dto/journal/JournalDto.java new file mode 100644 index 0000000..c776e71 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/journal/JournalDto.java @@ -0,0 +1,47 @@ +package com.cxx.home.dto.journal; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class JournalDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date date; + + @Schema(description = "地点") + private String location; + + @Schema(description = "类别") + private String category; + + @Schema(description = "天气") + private String weather; + + @Schema(description = "心情") + private String mood; + + @Schema(description = "内容") + @NotBlank(message = "内容不能为空") + private String content; + + @Schema(description = "图片地址") + private String imageUrl; + + @Schema(description = "视频地址") + private String videoUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/kpi/KpiDto.java b/home-service/src/main/java/com/cxx/home/dto/kpi/KpiDto.java new file mode 100644 index 0000000..72ca337 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/kpi/KpiDto.java @@ -0,0 +1,33 @@ +package com.cxx.home.dto.kpi; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class KpiDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "患者姓名") + private String patientName; + + @Schema(description = "项目") + private String project; + + @Schema(description = "价格") + private Integer price; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/ledger/LedgerDto.java b/home-service/src/main/java/com/cxx/home/dto/ledger/LedgerDto.java new file mode 100644 index 0000000..ea8e126 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/ledger/LedgerDto.java @@ -0,0 +1,51 @@ +package com.cxx.home.dto.ledger; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class LedgerDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "账本") + private String book; + + @Schema(description = "类别") + private String category; + + @Schema(description = "内容") + private String content; + + @Schema(description = "价格") + private Double price; + + @Schema(description = "数量") + private Integer number; + + @Schema(description = "总价") + @JsonView(ReadView.class) + private Double totalPrice; + + @Schema(description = "单位") + private String unit; + + @Schema(description = "付款人") + private String payer; + + @Schema(description = "供应商") + private String provider; + + @Schema(description = "图片") + private String imagerUrl; + + @Schema(description = "备注") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/period/PeriodDayDto.java b/home-service/src/main/java/com/cxx/home/dto/period/PeriodDayDto.java new file mode 100644 index 0000000..301a871 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/period/PeriodDayDto.java @@ -0,0 +1,39 @@ +package com.cxx.home.dto.period; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class PeriodDayDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "是否吃药") + private Boolean isDrug; + + @Schema(description = "是否来月经") + private Boolean isMenstruate; + + @Schema(description = "流量") + private String flowLevel; + + @Schema(description = "症状") + private String crampLevel; + + @Schema(description = "爱爱") + private String sexActivity; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/period/PeriodSettingDto.java b/home-service/src/main/java/com/cxx/home/dto/period/PeriodSettingDto.java new file mode 100644 index 0000000..b241c94 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/period/PeriodSettingDto.java @@ -0,0 +1,26 @@ +package com.cxx.home.dto.period; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@JsonView(PlainView.class) +public class PeriodSettingDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "月经周期") + private Integer cycleLength; + + @Schema(description = "持续天数") + private Integer duration; + + @Schema(description = "是否计算") + private Boolean isCalculate; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/product/ProductDto.java b/home-service/src/main/java/com/cxx/home/dto/product/ProductDto.java new file mode 100644 index 0000000..d70a3ad --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/product/ProductDto.java @@ -0,0 +1,58 @@ +package com.cxx.home.dto.product; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.PositiveOrZero; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; + +@Getter +@Setter +@JsonView(PlainView.class) +public class ProductDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "名称") + @NotBlank(message = "商品名称不能为空") + private String name; + + @Schema(description = "购买日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date purchaseDate; + + @Schema(description = "过期日期") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date expiryDate; + + @Schema(description = "总天数") + @JsonView(ReadView.class) + private Integer totalDay; + + @Schema(description = "价格") + @PositiveOrZero(message = "商品价格必须大于等于0") + private Double price; + + @Schema(description = "日均价格") + @JsonView(ReadView.class) + private Double averagePrice; + + @Schema(description = "类别") + private String category; + + @Schema(description = "购买人") + private String purchaser; + + @Schema(description = "购买渠道") + private String channel; + + @Schema(description = "图片路径") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/travel/TravelRecordDto.java b/home-service/src/main/java/com/cxx/home/dto/travel/TravelRecordDto.java new file mode 100644 index 0000000..02174d9 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/travel/TravelRecordDto.java @@ -0,0 +1,41 @@ +package com.cxx.home.dto.travel; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.Date; +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class TravelRecordDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "名称") + private String name; + + @Schema(description = "地址") + @JsonView(ReadView.class) + private List area; + + @Schema(description = "完成时间") + @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") + private Date date; + + @Schema(description = "完成人") + private List persons; + + @Schema(description = "旅行图片") + private List imageList; + + @Schema(description = "旅行视频") + private List videoList; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/travel/TravelSpotDto.java b/home-service/src/main/java/com/cxx/home/dto/travel/TravelSpotDto.java new file mode 100644 index 0000000..a0fcbd3 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/travel/TravelSpotDto.java @@ -0,0 +1,57 @@ +package com.cxx.home.dto.travel; + +import com.cxx.common.PlainView; +import com.cxx.common.ReadView; +import com.fasterxml.jackson.annotation.JsonView; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Getter; +import lombok.Setter; +import org.hibernate.validator.constraints.Range; + +import java.util.List; + +@Getter +@Setter +@JsonView(PlainView.class) +public class TravelSpotDto { + @Schema(description = "id") + @JsonView(ReadView.class) + private Long id; + + @Schema(description = "景点名称") + @NotBlank(message = "名称不能为空") + private String name; + + @Schema(description = "景点地区") + private List area; + + @Schema(description = "景点地址") + private String address; + + @Schema(description = "门票价格") + private Double price; + + @Schema(description = "推荐指数") + @Range(min = 0, max = 5, message = "推荐指数在0-5之间") + private Integer recommendRate; + + @Schema(description = "交通") + private String traffic; + + @Schema(description = "旅游路线") + private String router; + + @Schema(description = "美食推荐") + private List foods; + + @Schema(description = "项目推荐") + private List projects; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "旅游记录") + @JsonView(ReadView.class) + private List recordList; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/travel/TravelStatsDto.java b/home-service/src/main/java/com/cxx/home/dto/travel/TravelStatsDto.java new file mode 100644 index 0000000..7b574b2 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/travel/TravelStatsDto.java @@ -0,0 +1,18 @@ +package com.cxx.home.dto.travel; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class TravelStatsDto { + @Schema(description = "景点总数") + private Integer spotCount; + + @Schema(description = "城市总数") + private Integer cityCount; + + @Schema(description = "记录次数") + private Integer recordCount; +} diff --git a/home-service/src/main/java/com/cxx/home/dto/travel/TravelSummaryDto.java b/home-service/src/main/java/com/cxx/home/dto/travel/TravelSummaryDto.java new file mode 100644 index 0000000..96ddb50 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/dto/travel/TravelSummaryDto.java @@ -0,0 +1,26 @@ +package com.cxx.home.dto.travel; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +public class TravelSummaryDto { + @Schema(description = "id") + private Long id; + + @Schema(description = "景点名称") + private String name; + + @Schema(description = "景点地区") + private List area; + + @Schema(description = "推荐指数") + private Integer recommendRate; + + @Schema(description = "美食成果") + private List recordList; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/Anniversary.java b/home-service/src/main/java/com/cxx/home/entity/Anniversary.java new file mode 100644 index 0000000..8f23cb3 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/Anniversary.java @@ -0,0 +1,31 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("anniversary") +public class Anniversary extends AbstractEntity { + @TableField(value = "title") + private String title; + + @TableField("date") + private Date date; + + @TableField("recurring") + private Integer recurring; + + @TableField("type") + private String type; + + @TableField("category") + private String category; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/Asset.java b/home-service/src/main/java/com/cxx/home/entity/Asset.java new file mode 100644 index 0000000..6e9b8e7 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/Asset.java @@ -0,0 +1,29 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("asset") +public class Asset extends AbstractEntity { + @TableField(value = "category") + private String category; + + @TableField("name") + private String name; + + @TableField("amount") + private Double amount; + + @TableField("owner") + private String owner; + + @TableField("remark") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/FoodMaterial.java b/home-service/src/main/java/com/cxx/home/entity/FoodMaterial.java new file mode 100644 index 0000000..8f11b97 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/FoodMaterial.java @@ -0,0 +1,24 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_material") +public class FoodMaterial extends AbstractIdEntity { + @TableField("food_id") + private Long foodId; + + @TableField("type") + private String type; + + @TableField("name") + private String name; + + @TableField("amount") + private String amount; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/FoodRecipe.java b/home-service/src/main/java/com/cxx/home/entity/FoodRecipe.java new file mode 100644 index 0000000..abac1d5 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/FoodRecipe.java @@ -0,0 +1,24 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_recipe") +public class FoodRecipe extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("category") + private String category; + + @TableField("recommend_rate") + private Integer recommendRate; + + @TableField("remark") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/FoodRecord.java b/home-service/src/main/java/com/cxx/home/entity/FoodRecord.java new file mode 100644 index 0000000..8b0e7d2 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/FoodRecord.java @@ -0,0 +1,26 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_record") +public class FoodRecord extends AbstractIdEntity { + @TableField("food_id") + private Long foodId; + + @TableField("date") + private Date date; + + @TableField("person") + private String person; + + @TableField("image_url") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/FoodStep.java b/home-service/src/main/java/com/cxx/home/entity/FoodStep.java new file mode 100644 index 0000000..15886d6 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/FoodStep.java @@ -0,0 +1,24 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("food_step") +public class FoodStep extends AbstractIdEntity { + @TableField("food_id") + private Long foodId; + + @TableField("sort") + private Integer sort; + + @TableField("content") + private String content; + + @TableField("image_url") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/Journal.java b/home-service/src/main/java/com/cxx/home/entity/Journal.java new file mode 100644 index 0000000..1d6ee41 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/Journal.java @@ -0,0 +1,38 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("journal") +public class Journal extends AbstractEntity { + @TableField("date") + private Date date; + + @TableField(value = "location") + private String location; + + @TableField(value = "category") + private String category; + + @TableField(value = "weather") + private String weather; + + @TableField("mood") + private String mood; + + @TableField("content") + private String content; + + @TableField("image_url") + private String imageUrl; + + @TableField("video_url") + private String videoUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/Kpi.java b/home-service/src/main/java/com/cxx/home/entity/Kpi.java new file mode 100644 index 0000000..d9246af --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/Kpi.java @@ -0,0 +1,26 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("kpi") +public class Kpi extends AbstractEntity { + @TableField("date") + private Date date; + + @TableField("patient_name") + private String patientName; + + @TableField("project") + private String project; + + @TableField("price") + private Integer price; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/Ledger.java b/home-service/src/main/java/com/cxx/home/entity/Ledger.java new file mode 100644 index 0000000..c283e20 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/Ledger.java @@ -0,0 +1,42 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("ledger") +public class Ledger extends AbstractEntity { + @TableField(value = "book") + private String book; + + @TableField("category") + private String category; + + @TableField("content") + private String content; + + @TableField("price") + private Double price; + + @TableField("number") + private Integer number; + + @TableField("unit") + private String unit; + + @TableField("payer") + private String payer; + + @TableField("provider") + private String provider; + + @TableField("imager_url") + private String imagerUrl; + + @TableField("remark") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/PeriodDay.java b/home-service/src/main/java/com/cxx/home/entity/PeriodDay.java new file mode 100644 index 0000000..82e0cf1 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/PeriodDay.java @@ -0,0 +1,32 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("period_day") +public class PeriodDay extends AbstractEntity { + @TableField("date") + private Date date; + + @TableField("is_drug") + private Integer isDrug; + + @TableField("is_menstruate") + private Integer isMenstruate; + + @TableField("flow_level") + private String flowLevel; + + @TableField("cramp_level") + private String crampLevel; + + @TableField("sex_activity") + private String sexActivity; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/PeriodSetting.java b/home-service/src/main/java/com/cxx/home/entity/PeriodSetting.java new file mode 100644 index 0000000..e718150 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/PeriodSetting.java @@ -0,0 +1,23 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("period_setting") +public class PeriodSetting extends AbstractEntity { + @TableField("cycle_length") + private Integer cycleLength; + + @TableField("duration") + private Integer duration; + + @TableField("is_calculate") + private Integer isCalculate; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/Product.java b/home-service/src/main/java/com/cxx/home/entity/Product.java new file mode 100644 index 0000000..c69aaa8 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/Product.java @@ -0,0 +1,40 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("product") +public class Product extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("purchase_date") + private Date purchaseDate; + + @TableField("expiry_date") + private Date expiryDate; + + @TableField("price") + private Double price; + + @TableField("category") + private String category; + + @TableField("purchaser") + private String purchaser; + + @TableField("channel") + private String channel; + + @TableField("image_url") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/TravelImage.java b/home-service/src/main/java/com/cxx/home/entity/TravelImage.java new file mode 100644 index 0000000..9198451 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/TravelImage.java @@ -0,0 +1,15 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("travel_image") +public class TravelImage { + @TableField("record_id") + private Long recordId; + + @TableField("image_url") + private String imageUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/TravelRecord.java b/home-service/src/main/java/com/cxx/home/entity/TravelRecord.java new file mode 100644 index 0000000..24e35a0 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/TravelRecord.java @@ -0,0 +1,25 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.cxx.framework.data.AbstractIdEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("travel_record") +public class TravelRecord extends AbstractIdEntity { + @TableField("travel_id") + private Long travelId; + + @TableField("date") + private Date date; + + @TableField(value = "persons", typeHandler = JacksonTypeHandler.class) + private List persons; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/TravelSpot.java b/home-service/src/main/java/com/cxx/home/entity/TravelSpot.java new file mode 100644 index 0000000..4009195 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/TravelSpot.java @@ -0,0 +1,48 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; +import com.cxx.framework.data.AbstractEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("travel_spot") +public class TravelSpot extends AbstractEntity { + @TableField("name") + private String name; + + @TableField("city") + private String city; + + @TableField(value = "area", typeHandler = JacksonTypeHandler.class) + private List area; + + @TableField("address") + private String address; + + @TableField("price") + private Double price; + + @TableField("recommend_rate") + private Integer recommendRate; + + @TableField("traffic") + private String traffic; + + @TableField("router") + private String router; + + @TableField(value = "foods", typeHandler = JacksonTypeHandler.class) + private List foods; + + @TableField(value = "projects", typeHandler = JacksonTypeHandler.class) + private List projects; + + @TableField("remark") + private String remark; +} diff --git a/home-service/src/main/java/com/cxx/home/entity/TravelVideo.java b/home-service/src/main/java/com/cxx/home/entity/TravelVideo.java new file mode 100644 index 0000000..79aa09b --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/entity/TravelVideo.java @@ -0,0 +1,15 @@ +package com.cxx.home.entity; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +@Data +@TableName("travel_video") +public class TravelVideo { + @TableField("record_id") + private Long recordId; + + @TableField("video_url") + private String videoUrl; +} diff --git a/home-service/src/main/java/com/cxx/home/mapper/AnniversaryMapper.java b/home-service/src/main/java/com/cxx/home/mapper/AnniversaryMapper.java new file mode 100644 index 0000000..60ab2a9 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/AnniversaryMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.Anniversary; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface AnniversaryMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/AssetMapper.java b/home-service/src/main/java/com/cxx/home/mapper/AssetMapper.java new file mode 100644 index 0000000..263262f --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/AssetMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.Asset; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface AssetMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/FoodMaterialMapper.java b/home-service/src/main/java/com/cxx/home/mapper/FoodMaterialMapper.java new file mode 100644 index 0000000..eb3b972 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/FoodMaterialMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.FoodMaterial; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodMaterialMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/FoodRecipeMapper.java b/home-service/src/main/java/com/cxx/home/mapper/FoodRecipeMapper.java new file mode 100644 index 0000000..ec145a2 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/FoodRecipeMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.FoodRecipe; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodRecipeMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/FoodRecordMapper.java b/home-service/src/main/java/com/cxx/home/mapper/FoodRecordMapper.java new file mode 100644 index 0000000..2fb9441 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/FoodRecordMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.FoodRecord; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodRecordMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/FoodStepMapper.java b/home-service/src/main/java/com/cxx/home/mapper/FoodStepMapper.java new file mode 100644 index 0000000..fa741fa --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/FoodStepMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.FoodStep; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface FoodStepMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/JournalMapper.java b/home-service/src/main/java/com/cxx/home/mapper/JournalMapper.java new file mode 100644 index 0000000..b53d878 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/JournalMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.Journal; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface JournalMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/KpiMapper.java b/home-service/src/main/java/com/cxx/home/mapper/KpiMapper.java new file mode 100644 index 0000000..b7c6b32 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/KpiMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.Kpi; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface KpiMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/LedgerMapper.java b/home-service/src/main/java/com/cxx/home/mapper/LedgerMapper.java new file mode 100644 index 0000000..5236584 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/LedgerMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.Ledger; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface LedgerMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/PeriodDayMapper.java b/home-service/src/main/java/com/cxx/home/mapper/PeriodDayMapper.java new file mode 100644 index 0000000..79ba9da --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/PeriodDayMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.PeriodDay; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PeriodDayMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/PeriodSettingMapper.java b/home-service/src/main/java/com/cxx/home/mapper/PeriodSettingMapper.java new file mode 100644 index 0000000..d148c93 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/PeriodSettingMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.PeriodSetting; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PeriodSettingMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/ProductMapper.java b/home-service/src/main/java/com/cxx/home/mapper/ProductMapper.java new file mode 100644 index 0000000..39b1878 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/ProductMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.Product; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface ProductMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/TravelImageMapper.java b/home-service/src/main/java/com/cxx/home/mapper/TravelImageMapper.java new file mode 100644 index 0000000..a82446f --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/TravelImageMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.TravelImage; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TravelImageMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/TravelRecordMapper.java b/home-service/src/main/java/com/cxx/home/mapper/TravelRecordMapper.java new file mode 100644 index 0000000..9487a7a --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/TravelRecordMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.TravelRecord; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TravelRecordMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/TravelSpotMapper.java b/home-service/src/main/java/com/cxx/home/mapper/TravelSpotMapper.java new file mode 100644 index 0000000..0b69712 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/TravelSpotMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.TravelSpot; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TravelSpotMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/mapper/TravelVideoMapper.java b/home-service/src/main/java/com/cxx/home/mapper/TravelVideoMapper.java new file mode 100644 index 0000000..f0a4a3d --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/mapper/TravelVideoMapper.java @@ -0,0 +1,9 @@ +package com.cxx.home.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.cxx.home.entity.TravelVideo; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface TravelVideoMapper extends BaseMapper { +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/schedule/QuartzDto.java b/home-service/src/main/java/com/cxx/home/schedule/QuartzDto.java new file mode 100644 index 0000000..4c06f7b --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/schedule/QuartzDto.java @@ -0,0 +1,20 @@ +package com.cxx.home.schedule; + + +import com.cxx.common.dto.task.TaskDto; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class QuartzDto extends TaskDto { + @Schema(description = "任务名称/id") + private String name; + + @Schema(description = "任务组别") + private String group; + + @Schema(description = "任务状态") + private String status; +} diff --git a/home-service/src/main/java/com/cxx/home/schedule/QuartzJob.java b/home-service/src/main/java/com/cxx/home/schedule/QuartzJob.java new file mode 100644 index 0000000..97cb78a --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/schedule/QuartzJob.java @@ -0,0 +1,55 @@ +package com.cxx.home.schedule; + +import com.cxx.common.dto.message.MailMessageDto; +import com.cxx.common.entity.Task; +import com.cxx.framework.web.CustomException; +import com.cxx.common.mapper.TaskMapper; +import com.cxx.home.service.MessageService; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; + +@Slf4j +public class QuartzJob implements Job { + @Resource + private TaskMapper taskMapper; + + @Resource + private MessageService messageService; + + private final ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public void execute(JobExecutionContext context) { + JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); + Long taskId = jobDataMap.getLong("id"); + + Task task = taskMapper.selectById(taskId); + try { + JsonNode taskContent = objectMapper.readTree(task.getContent()); + + switch (task.getType()) { + case TaskType.EMAIL: + handleEmailTask(taskContent); + break; + case TaskType.SMS: + break; + } + } catch (Exception e) { + throw new CustomException("执行任务错误:", e.getMessage()); + } + } + + private void handleEmailTask(JsonNode taskContent) { + MailMessageDto mailMessageDto = new MailMessageDto(); + mailMessageDto.setTo(taskContent.get("to").asText()); + mailMessageDto.setSubject(taskContent.get("subject").asText()); + mailMessageDto.setBody(taskContent.get("body").asText()); + + messageService.sendMailMessage(mailMessageDto); + } +} diff --git a/home-service/src/main/java/com/cxx/home/schedule/QuartzUtils.java b/home-service/src/main/java/com/cxx/home/schedule/QuartzUtils.java new file mode 100644 index 0000000..8f4e998 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/schedule/QuartzUtils.java @@ -0,0 +1,47 @@ +package com.cxx.home.schedule; + +import com.cxx.common.entity.Task; +import com.cxx.framework.web.CustomException; +import org.quartz.*; +import org.springframework.stereotype.Component; + +@Component +public class QuartzUtils { + public static JobDetail getJobDetail(Task task, JobKey jobKey) { + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("id", task.getId()); + jobDataMap.put("type", task.getType()); + jobDataMap.put("content", task.getContent()); + + return JobBuilder.newJob(QuartzJob.class) + .withIdentity(jobKey) // 使用 id 作为唯一标识 + .usingJobData(jobDataMap) + .build(); + } + + public static Trigger getTrigger(Task task, JobKey jobKey) { + Trigger trigger; + // 判断任务类型:Cron 任务或者一次性任务 + if (task.getCronExpression() != null && !task.getCronExpression().isEmpty()) { + // 定时任务:使用 Cron 表达式 + trigger = TriggerBuilder.newTrigger() + .withIdentity(jobKey.getName() + "Trigger") + .withSchedule(CronScheduleBuilder.cronSchedule(task.getCronExpression())) + .forJob(jobKey) + .build(); + } else if (task.getExecuteTime() != null) { + // 一次性任务:使用 executeTime + trigger = TriggerBuilder.newTrigger() + .withIdentity(jobKey.getName() + "Trigger") + .startAt(task.getExecuteTime()) + .forJob(jobKey) + .build(); + } else { + // 如果没有 Cron 表达式和 executeTime,任务不能调度,抛出异常 + throw new CustomException("任务没有有效的 Cron 表达式或执行时间"); + } + + return trigger; + } +} + diff --git a/home-service/src/main/java/com/cxx/home/schedule/TaskType.java b/home-service/src/main/java/com/cxx/home/schedule/TaskType.java new file mode 100644 index 0000000..d6ab4df --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/schedule/TaskType.java @@ -0,0 +1,6 @@ +package com.cxx.home.schedule; + +public interface TaskType { + String EMAIL = "EMAIL"; + String SMS = "SMS"; +} diff --git a/home-service/src/main/java/com/cxx/home/service/AnniversaryService.java b/home-service/src/main/java/com/cxx/home/service/AnniversaryService.java new file mode 100644 index 0000000..446a374 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/AnniversaryService.java @@ -0,0 +1,18 @@ +package com.cxx.home.service; + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.home.dto.anniversary.AnniversaryDto; + +import java.util.List; + +public interface AnniversaryService { + Boolean addAnniversary(AnniversaryDto anniversaryDto); + + Boolean updateAnniversary(Long id, AnniversaryDto anniversaryDto); + + Boolean deleteAnniversary(Long id); + + List queryAnniversary(String category); + + List queryAnniversaryCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/AssetService.java b/home-service/src/main/java/com/cxx/home/service/AssetService.java new file mode 100644 index 0000000..739e03e --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/AssetService.java @@ -0,0 +1,17 @@ +package com.cxx.home.service; + +import com.cxx.home.dto.asset.AssetDto; + +import java.util.List; + +public interface AssetService { + Boolean addAsset(AssetDto assetDto); + + Boolean updateAsset(Long id, AssetDto assetDto); + + Boolean deleteAsset(Long id); + + List queryAsset(String category); + + List queryAssetCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/BillRecordService.java b/home-service/src/main/java/com/cxx/home/service/BillRecordService.java new file mode 100644 index 0000000..8565ded --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/BillRecordService.java @@ -0,0 +1,28 @@ +package com.cxx.home.service; + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.bill.BillCategoryDto; +import com.cxx.common.dto.bill.BillItemDto; +import com.cxx.common.dto.bill.BillRecordDto; +import com.cxx.common.dto.bill.BillSummaryDto; +import com.cxx.common.vo.bill.BillQueryVo; + +import java.util.List; + +public interface BillRecordService { + Boolean saveOrUpdateBillRecord(Long id, BillRecordDto billRecordDto); + + Boolean deleteBillRecord(Long id); + + BillRecordDto queryBillRecord(Long id); + + List queryBillSummary(BillQueryVo billQueryVo); + + List queryBillStats(String type, BillQueryVo billQueryVo); + + List queryBillPay(); + + List queryBillBook(); + + List queryBillCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/BudgetService.java b/home-service/src/main/java/com/cxx/home/service/BudgetService.java new file mode 100644 index 0000000..74b4a40 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/BudgetService.java @@ -0,0 +1,23 @@ +package com.cxx.home.service; + + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.budget.BudgetDto; + +import java.util.List; + +public interface BudgetService { + List queryBudgetCategory(); + + Boolean addBudget(BudgetDto budgetDto); + + Boolean updateBudget(Long id, BudgetDto budgetDto); + + Boolean deleteBudget(Long id); + + List queryBudget(String category); + + List queryBudgetRankStats(String category); + + List queryBudgetProjectStats(String category); +} diff --git a/home-service/src/main/java/com/cxx/home/service/FoodService.java b/home-service/src/main/java/com/cxx/home/service/FoodService.java new file mode 100644 index 0000000..9ea1fd5 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/FoodService.java @@ -0,0 +1,37 @@ +package com.cxx.home.service; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.home.dto.food.FoodRecipeDto; +import com.cxx.home.dto.food.FoodRecordDto; +import com.cxx.home.dto.food.FoodStatsDto; +import com.cxx.home.dto.food.FoodSummaryDto; +import com.cxx.home.vo.FoodQueryVo; + +import java.util.List; + +public interface FoodService { + Boolean addFoodRecipe(FoodRecipeDto foodRecipeDto); + + Boolean updateFoodRecipe(Long id, FoodRecipeDto foodRecipeDto); + + Boolean deleteFoodRecipe(Long id); + + Boolean addFoodRecord(FoodRecordDto foodRecordDto); + + Boolean updateFoodRecord(Long id, FoodRecordDto foodRecordDto); + + Boolean deleteFoodRecord(Long id); + + FoodRecipeDto queryFoodRecipe(Long id); + + IPage queryFoodSummary(Integer currentPage, Integer pageSize, FoodQueryVo foodQueryVo); + + List queryFoodRecord(String startDate, String endDate); + + List queryFoodName(); + + List queryFoodCategory(); + + FoodStatsDto queryFoodStats(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/JournalService.java b/home-service/src/main/java/com/cxx/home/service/JournalService.java new file mode 100644 index 0000000..be3f293 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/JournalService.java @@ -0,0 +1,16 @@ +package com.cxx.home.service; + +import com.cxx.home.dto.journal.JournalDto; +import com.cxx.home.vo.JournalQueryVo; + +import java.util.List; + +public interface JournalService { + Boolean addJournal(JournalDto journalDto); + + Boolean updateJournal(Long id, JournalDto journalDto); + + Boolean deleteJournal(Long id); + + List queryJournal(JournalQueryVo queryVo); +} diff --git a/home-service/src/main/java/com/cxx/home/service/KpiService.java b/home-service/src/main/java/com/cxx/home/service/KpiService.java new file mode 100644 index 0000000..7a4b534 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/KpiService.java @@ -0,0 +1,16 @@ +package com.cxx.home.service; + +import com.cxx.home.dto.kpi.KpiDto; +import com.cxx.home.vo.KpiQueryVo; + +import java.util.List; + +public interface KpiService { + Boolean addKpi(KpiDto kpiDto); + + Boolean updateKpi(Long id, KpiDto kpiDto); + + Boolean deleteKpi(Long id); + + List queryKpi(KpiQueryVo queryVo); +} diff --git a/home-service/src/main/java/com/cxx/home/service/LedgerService.java b/home-service/src/main/java/com/cxx/home/service/LedgerService.java new file mode 100644 index 0000000..8afbcf1 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/LedgerService.java @@ -0,0 +1,17 @@ +package com.cxx.home.service; + +import com.cxx.home.dto.ledger.LedgerDto; + +import java.util.List; + +public interface LedgerService { + Boolean addLedger(LedgerDto ledgerDto); + + Boolean updateLedger(Long id, LedgerDto ledgerDto); + + Boolean deleteLedger(Long id); + + List queryLedger(String book); + + List queryLedgerBook(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/MessageService.java b/home-service/src/main/java/com/cxx/home/service/MessageService.java new file mode 100644 index 0000000..f1fd264 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/MessageService.java @@ -0,0 +1,9 @@ +package com.cxx.home.service; + +import com.cxx.common.dto.message.MailMessageDto; + +public interface MessageService { + void sendMailMessage(MailMessageDto mailMessageDto); + + void sendWxMessage(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/PeriodService.java b/home-service/src/main/java/com/cxx/home/service/PeriodService.java new file mode 100644 index 0000000..ad6d6ea --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/PeriodService.java @@ -0,0 +1,18 @@ +package com.cxx.home.service; + +import com.cxx.home.dto.period.PeriodDayDto; +import com.cxx.home.dto.period.PeriodSettingDto; + +import java.util.List; + +public interface PeriodService { + Boolean updatePeriodDay(Long id, PeriodDayDto periodDayDto); + + List queryPeriodDay(String month); + + String getMenstruateFirstDate(String month); + + Boolean updatePeriodSetting(Long id, PeriodSettingDto periodSettingDto); + + PeriodSettingDto queryPeriodSetting(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/PlanService.java b/home-service/src/main/java/com/cxx/home/service/PlanService.java new file mode 100644 index 0000000..aa6aefa --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/PlanService.java @@ -0,0 +1,21 @@ +package com.cxx.home.service; + +import com.cxx.common.dto.plan.PlanDto; +import com.cxx.common.dto.plan.PlanStatsDto; +import com.cxx.common.vo.plan.PlanQueryVo; + +import java.util.List; + +public interface PlanService { + Boolean addPlan(PlanDto planDto); + + Boolean updatePlan(Long id, PlanDto planDto); + + Boolean deletePlan(Long id); + + List queryPlan(PlanQueryVo query); + + Boolean setPlanStatus(Long id, Boolean status); + + PlanStatsDto queryPlanStats(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/ProductService.java b/home-service/src/main/java/com/cxx/home/service/ProductService.java new file mode 100644 index 0000000..956dbd4 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/ProductService.java @@ -0,0 +1,21 @@ +package com.cxx.home.service; + + +import com.cxx.home.dto.product.ProductDto; +import com.cxx.home.vo.ProductQueryVo; + +import java.util.List; + +public interface ProductService { + Boolean addProduct(ProductDto productDto); + + Boolean updateProduct(Long id, ProductDto productDto); + + Boolean deleteProduct(Long id); + + ProductDto queryProduct(Long id); + + List queryProductList(ProductQueryVo queryVo); + + List queryProductCategory(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/QuartzService.java b/home-service/src/main/java/com/cxx/home/service/QuartzService.java new file mode 100644 index 0000000..ea52d67 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/QuartzService.java @@ -0,0 +1,18 @@ +package com.cxx.home.service; + +import com.cxx.common.entity.Task; +import com.cxx.home.schedule.QuartzDto; +import org.quartz.JobKey; + +import java.util.List; + + +public interface QuartzService { + List queryQuartzTask(); + + void createQuartzTask(Task task); + + void updateQuartzTask(Task task); + + void deleteQuartzTask(JobKey jobKey); +} diff --git a/home-service/src/main/java/com/cxx/home/service/SessionService.java b/home-service/src/main/java/com/cxx/home/service/SessionService.java new file mode 100644 index 0000000..52998bd --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/SessionService.java @@ -0,0 +1,7 @@ +package com.cxx.home.service; + +import com.cxx.common.dto.user.SessionDto; + +public interface SessionService { + SessionDto create(String name, String password); +} diff --git a/home-service/src/main/java/com/cxx/home/service/TaskService.java b/home-service/src/main/java/com/cxx/home/service/TaskService.java new file mode 100644 index 0000000..a1386ab --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/TaskService.java @@ -0,0 +1,14 @@ +package com.cxx.home.service; + +import com.cxx.common.dto.task.TaskDto; + + +public interface TaskService { + TaskDto queryTaskById(Long id); + + Long addTask(TaskDto taskDto); + + Boolean updateTask(Long id, TaskDto taskDto); + + Boolean deleteTask(Long id); +} diff --git a/home-service/src/main/java/com/cxx/home/service/TravelService.java b/home-service/src/main/java/com/cxx/home/service/TravelService.java new file mode 100644 index 0000000..87a6e51 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/TravelService.java @@ -0,0 +1,37 @@ +package com.cxx.home.service; + + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.cxx.home.dto.travel.TravelRecordDto; +import com.cxx.home.dto.travel.TravelSpotDto; +import com.cxx.home.dto.travel.TravelStatsDto; +import com.cxx.home.dto.travel.TravelSummaryDto; +import com.cxx.home.vo.TravelQueryVo; + +import java.util.List; + +public interface TravelService { + Boolean addTravelSpot(TravelSpotDto travelSpotDto); + + Boolean updateTravelSpot(Long id, TravelSpotDto travelSpotDto); + + Boolean deleteTravelSpot(Long id); + + Boolean addTravelRecord(TravelRecordDto travelRecordDto); + + Boolean updateTravelRecord(Long id, TravelRecordDto travelRecordDto); + + Boolean deleteTravelRecord(Long id); + + TravelSpotDto queryTravelSpot(Long id); + + IPage queryTravelSummary(Integer currentPage, Integer pageSize, TravelQueryVo travelQueryVo); + + List queryTravelRecord(String startDate, String endDate); + + List queryTravelSpotName(); + + List queryTravelCategory(); + + TravelStatsDto queryTravelStats(); +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/AnniversaryServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/AnniversaryServiceImpl.java new file mode 100644 index 0000000..9245af1 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/AnniversaryServiceImpl.java @@ -0,0 +1,65 @@ +package com.cxx.home.service.impl; + +import com.cxx.common.dto.StatsChartDto; +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.AnniversaryDao; +import com.cxx.home.dto.anniversary.AnniversaryDto; +import com.cxx.home.entity.Anniversary; +import com.cxx.home.mapper.AnniversaryMapper; +import com.cxx.home.service.AnniversaryService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class AnniversaryServiceImpl implements AnniversaryService { + @Resource + private AnniversaryDao anniversaryDao; + + @Resource + private AnniversaryMapper anniversaryMapper; + + + @Override + public Boolean addAnniversary(AnniversaryDto anniversaryDto) { + Anniversary anniversary = new Anniversary(); + BeanUtils.copyProperties(anniversaryDto, anniversary); + anniversary.setRecurring(anniversaryDto.getRecurring() ? 1 : 0); + + return anniversaryMapper.insert(anniversary) == 1; + } + + @Override + public Boolean updateAnniversary(Long id, AnniversaryDto anniversaryDto) { + if (anniversaryMapper.selectById(id) == null) { + throw new CustomException("该纪念日不存在"); + } + + Anniversary anniversary = new Anniversary(); + BeanUtils.copyProperties(anniversaryDto, anniversary); + anniversary.setId(id); + anniversary.setRecurring(anniversaryDto.getRecurring() ? 1 : 0); + return anniversaryMapper.updateById(anniversary) == 1; + } + + @Override + public Boolean deleteAnniversary(Long id) { + if (anniversaryMapper.selectById(id) == null) { + throw new CustomException("该纪念日不存在"); + } + + return anniversaryMapper.deleteById(id) == 1; + } + + @Override + public List queryAnniversary(String category) { + return anniversaryDao.queryAnniversary(category); + } + + @Override + public List queryAnniversaryCategory() { + return anniversaryDao.queryAnniversaryCategory(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/AssetServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/AssetServiceImpl.java new file mode 100644 index 0000000..ede95af --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/AssetServiceImpl.java @@ -0,0 +1,62 @@ +package com.cxx.home.service.impl; + +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.AssetDao; +import com.cxx.home.dto.asset.AssetDto; +import com.cxx.home.entity.Asset; +import com.cxx.home.mapper.AssetMapper; +import com.cxx.home.service.AssetService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class AssetServiceImpl implements AssetService { + @Resource + private AssetDao assetDao; + + @Resource + private AssetMapper assetMapper; + + + @Override + public Boolean addAsset(AssetDto assetDto) { + Asset asset = new Asset(); + BeanUtils.copyProperties(assetDto, asset); + + return assetMapper.insert(asset) == 1; + } + + @Override + public Boolean updateAsset(Long id, AssetDto assetDto) { + if (assetMapper.selectById(id) == null) { + throw new CustomException("该资产不存在"); + } + + Asset asset = new Asset(); + BeanUtils.copyProperties(assetDto, asset); + asset.setId(id); + return assetMapper.updateById(asset) == 1; + } + + @Override + public Boolean deleteAsset(Long id) { + if (assetMapper.selectById(id) == null) { + throw new CustomException("该资产不存在"); + } + + return assetMapper.deleteById(id) == 1; + } + + @Override + public List queryAsset(String category) { + return assetDao.queryAsset(category); + } + + @Override + public List queryAssetCategory() { + return assetDao.queryAssetCategory(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/BillRecordServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/BillRecordServiceImpl.java new file mode 100644 index 0000000..af1924c --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/BillRecordServiceImpl.java @@ -0,0 +1,158 @@ +package com.cxx.home.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.bill.*; +import com.cxx.common.entity.*; +import com.cxx.common.mapper.*; +import com.cxx.common.entity.BillBook; +import com.cxx.common.entity.BillCategory; +import com.cxx.common.entity.BillPay; +import com.cxx.common.entity.BillRecord; +import com.cxx.common.mapper.BillBookMapper; +import com.cxx.common.mapper.BillCategoryMapper; +import com.cxx.common.mapper.BillPayMapper; +import com.cxx.common.mapper.BillRecordMapper; +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.BillDao; +import com.cxx.home.service.BillRecordService; +import com.cxx.common.vo.bill.BillQueryVo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +@Service +public class BillRecordServiceImpl implements BillRecordService { + @Resource + private BillDao billDao; + + @Resource + private BillRecordMapper billRecordMapper; + + @Resource + private BillPayMapper billPayMapper; + + @Resource + private BillBookMapper billBookMapper; + + @Resource + private BillCategoryMapper billCategoryMapper; + + @Resource + private BillImageMapper billImageMapper; + + @Override + public Boolean saveOrUpdateBillRecord(Long id, BillRecordDto billRecord) { + // 1. 如果是更新 查询账单是否存在 + boolean isUpdate = id > 0; + if (isUpdate && Objects.isNull(billRecordMapper.selectById(id))) { + throw new CustomException("该账单不存在"); + } + + // 2. 新增/更新账单 + BillRecord newBillRecord = new BillRecord(); + BeanUtils.copyProperties(billRecord, newBillRecord); + newBillRecord.setPayId(getBillPayId(billRecord.getPayAccount())); + newBillRecord.setBookId(getBillBook(billRecord.getBookName())); + newBillRecord.setCategoryId(getBillCategory(billRecord.getCategory())); + + if (isUpdate) { + newBillRecord.setId(id); + billRecordMapper.updateById(newBillRecord); + } else { + billRecordMapper.insert(newBillRecord); + } + + // 6. 新增/更新账单图片 + if (isUpdate) { + // 如果是更新先删除所有的账单图片记录 + deleteBillImage(id); + } + + // 新增账单图片 + insertBillImage(newBillRecord.getId(), billRecord.getImageList()); + + return Boolean.TRUE; + } + + private Long getBillPayId(String payAccount) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(BillPay.class); + BillPay billPay = billPayMapper.selectOne(queryWrapper.eq(BillPay::getName, payAccount)); + if (Objects.isNull(billPay)) { + throw new CustomException("暂无该账户类型"); + } + + return billPay.getId(); + } + + private Long getBillBook(String bookName) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(BillBook.class); + BillBook billBook = billBookMapper.selectOne(queryWrapper.eq(BillBook::getName, bookName)); + if (Objects.isNull(billBook)) { + throw new CustomException("暂无该账本类型"); + } + + return billBook.getId(); + } + + private Long getBillCategory(String categoryName) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(BillCategory.class); + BillCategory billCategory = billCategoryMapper.selectOne(queryWrapper.eq(BillCategory::getName, categoryName)); + if (Objects.isNull(billCategory)) { + throw new CustomException("暂无该账单类型"); + } + + return billCategory.getId(); + } + + private void insertBillImage(Long billId, List imageDtoList) { + if (imageDtoList.isEmpty()) { + return; + } + billDao.insertBillImage(billId, imageDtoList); + } + + private void deleteBillImage(Long id) { + billImageMapper.delete(Wrappers.lambdaQuery(BillImage.class).eq(BillImage::getBillId, id)); + } + + @Override + public Boolean deleteBillRecord(Long id) { + deleteBillImage(id); + return billRecordMapper.deleteById(id) == 1; + } + + @Override + public BillRecordDto queryBillRecord(Long id) { + return billDao.queryBillRecord(id); + } + + @Override + public List queryBillSummary(BillQueryVo billQuery) { + return billDao.queryBillSummary(billQuery); + } + + @Override + public List queryBillStats(String type, BillQueryVo billQuery) { + return billDao.queryBillStats(type, billQuery); + } + + @Override + public List queryBillPay() { + return billDao.queryBillPay(); + } + + @Override + public List queryBillBook() { + return billDao.queryBillBook(); + } + + @Override + public List queryBillCategory() { + return billDao.queryBillCategory(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/BudgetServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/BudgetServiceImpl.java new file mode 100644 index 0000000..e15d893 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/BudgetServiceImpl.java @@ -0,0 +1,88 @@ +package com.cxx.home.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.toolkit.SimpleQuery; +import com.cxx.common.dto.StatsChartDto; +import com.cxx.common.dto.budget.BudgetDto; +import com.cxx.common.entity.Budget; +import com.cxx.common.entity.BudgetCategory; +import com.cxx.common.mapper.BudgetCategoryMapper; +import com.cxx.common.mapper.BudgetMapper; +import com.cxx.home.dao.BudgetDao; +import com.cxx.home.service.BudgetService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; + +@Service +public class BudgetServiceImpl implements BudgetService { + @Resource + private BudgetDao budgetDao; + + @Resource + private BudgetMapper budgetMapper; + + @Resource + private BudgetCategoryMapper budgetCategoryMapper; + + @Override + public List queryBudgetCategory() { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(BudgetCategory.class); + return SimpleQuery.list(queryWrapper.select(BudgetCategory::getName), BudgetCategory::getName); + } + + @Override + public Boolean addBudget(BudgetDto budgetDto) { + Budget budge = new Budget(); + BeanUtils.copyProperties(budgetDto, budge); + budge.setCategoryId(getBudgetCategory(budgetDto.getCategory())); + + return budgetMapper.insert(budge) == 1; + } + + @Override + public Boolean updateBudget(Long id, BudgetDto budgetDto) { + Budget budge = new Budget(); + BeanUtils.copyProperties(budgetDto, budge); + budge.setCategoryId(getBudgetCategory(budgetDto.getCategory())); + budge.setId(id); + return budgetMapper.updateById(budge) == 1; + } + + private Long getBudgetCategory(String category) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + BudgetCategory budgetCategory = budgetCategoryMapper.selectOne(queryWrapper.eq(BudgetCategory::getName, category)); + if (Objects.isNull(budgetCategory)) { + BudgetCategory newBudgetCategory = new BudgetCategory(); + newBudgetCategory.setName(category); + budgetCategoryMapper.insert(newBudgetCategory); + return newBudgetCategory.getId(); + } else { + return budgetCategory.getId(); + } + } + + @Override + public Boolean deleteBudget(Long id) { + return budgetMapper.deleteById(id) == 1; + } + + @Override + public List queryBudget(String category) { + return budgetDao.queryBudget(category); + } + + @Override + public List queryBudgetRankStats(String category) { + return budgetDao.queryBudgetRankStats(category); + } + + @Override + public List queryBudgetProjectStats(String category) { + return budgetDao.queryBudgetProjectStats(category); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/FoodServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/FoodServiceImpl.java new file mode 100644 index 0000000..4b67a04 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/FoodServiceImpl.java @@ -0,0 +1,200 @@ +package com.cxx.home.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cxx.home.dto.food.*; +import com.cxx.home.mapper.FoodMaterialMapper; +import com.cxx.home.mapper.FoodStepMapper; +import com.cxx.home.mapper.FoodRecipeMapper; +import com.cxx.home.mapper.FoodRecordMapper; +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.FoodDao; +import com.cxx.home.entity.FoodMaterial; +import com.cxx.home.entity.FoodRecipe; +import com.cxx.home.entity.FoodRecord; +import com.cxx.home.entity.FoodStep; +import com.cxx.home.service.FoodService; +import com.cxx.home.vo.FoodQueryVo; +import com.github.yitter.idgen.YitIdHelper; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class FoodServiceImpl implements FoodService { + @Resource + private FoodDao foodDao; + + @Resource + private FoodRecipeMapper foodRecipeMapper; + + @Resource + private FoodMaterialMapper foodMaterialMapper; + + @Resource + private FoodStepMapper foodStepMapper; + + @Resource + private FoodRecordMapper foodRecordMapper; + + @Override + @Transactional + public Boolean addFoodRecipe(FoodRecipeDto foodRecipeDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (foodRecipeMapper.exists(queryWrapper.eq(FoodRecipe::getName, foodRecipeDto.getName()))) { + throw new CustomException("该菜谱已经存在"); + } + + FoodRecipe foodRecipe = new FoodRecipe(); + BeanUtils.copyProperties(foodRecipeDto, foodRecipe); + foodRecipeMapper.insert(foodRecipe); + resetFoodRecipe(foodRecipe.getId(), foodRecipeDto); + + return Boolean.TRUE; + } + + @Override + @Transactional + public Boolean updateFoodRecipe(Long id, FoodRecipeDto foodRecipeDto) { + if (foodRecipeMapper.selectById(id) == null) { + throw new CustomException("该菜谱不存在"); + } + + FoodRecipe foodRecipe = new FoodRecipe(); + BeanUtils.copyProperties(foodRecipeDto, foodRecipe); + foodRecipe.setId(id); + foodRecipeMapper.updateById(foodRecipe); + resetFoodRecipe(foodRecipe.getId(), foodRecipeDto); + + return Boolean.TRUE; + } + + @Override + @Transactional + public Boolean deleteFoodRecipe(Long id) { + foodRecipeMapper.deleteById(id); + foodMaterialMapper.delete(Wrappers.lambdaQuery(FoodMaterial.class).eq(FoodMaterial::getFoodId, id)); + foodStepMapper.delete(Wrappers.lambdaQuery(FoodStep.class).eq(FoodStep::getFoodId, id)); + foodRecordMapper.delete(Wrappers.lambdaQuery(FoodRecord.class).eq(FoodRecord::getFoodId, id)); + + return Boolean.TRUE; + } + + @Override + public Boolean addFoodRecord(FoodRecordDto foodRecordDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + FoodRecipe foodRecipe = foodRecipeMapper.selectOne(queryWrapper.eq(FoodRecipe::getName, foodRecordDto.getName())); + if (foodRecipe == null) { + throw new CustomException("该菜谱不存在"); + } + + FoodRecord foodRecord = new FoodRecord(); + foodRecord.setFoodId(foodRecipe.getId()); + BeanUtils.copyProperties(foodRecordDto, foodRecord); + foodRecordMapper.insert(foodRecord); + + return Boolean.TRUE; + } + + @Override + public Boolean updateFoodRecord(Long id, FoodRecordDto foodRecordDto) { + if (foodRecordMapper.selectById(id) == null) { + throw new CustomException("该成果不存在"); + } + + FoodRecord foodRecord = new FoodRecord(); + BeanUtils.copyProperties(foodRecordDto, foodRecord); + foodRecord.setId(id); + foodRecordMapper.updateById(foodRecord); + + return Boolean.TRUE; + } + + @Override + public Boolean deleteFoodRecord(Long id) { + foodRecordMapper.deleteById(id); + + return Boolean.TRUE; + } + + private void resetFoodRecipe(Long id, FoodRecipeDto foodRecipeDto) { + foodMaterialMapper.delete(Wrappers.lambdaQuery(FoodMaterial.class).eq(FoodMaterial::getFoodId, id)); + foodStepMapper.delete(Wrappers.lambdaQuery(FoodStep.class).eq(FoodStep::getFoodId, id)); + + insertFoodMaterial(id, foodRecipeDto.getMaterialList()); + insertFoodStep(id, foodRecipeDto.getStepList()); + } + + private void insertFoodMaterial(Long foodId, List foodMaterialList) { + if (foodMaterialList.isEmpty()) { + return; + } + + foodMaterialList.forEach((item) -> { + item.setId(YitIdHelper.nextId()); + }); + foodDao.insertFoodMaterial(foodId, foodMaterialList); + } + + private void insertFoodStep(Long foodId, List foodStepList) { + if (foodStepList.isEmpty()) { + return; + } + + foodStepList.forEach((item) -> { + item.setId(YitIdHelper.nextId()); + }); + foodDao.insertFoodStep(foodId, foodStepList); + } + + @Override + public FoodRecipeDto queryFoodRecipe(Long id) { + if (foodRecipeMapper.selectById(id) == null) { + throw new CustomException("该美食不存在"); + } + + return foodDao.queryFoodRecipe(id); + } + + @Override + public IPage queryFoodSummary(Integer currentPage, Integer pageSize, FoodQueryVo foodQueryVo) { + // 这里只能先对主表进行分页 然后在查询子表信息 + // 不能使用Left Join关联表查询,因为这里是一对多数据,关联查询会导致数据有重复 + // 从而导致page计算错误(会把重复的数据当成多条记录,实际上只有1条记录) + IPage foodSummaryPage = foodDao.queryFoodSummary(new Page<>(currentPage, pageSize), foodQueryVo); + List foodSummaryList = foodSummaryPage.getRecords(); + for (FoodSummaryDto foodSummary : foodSummaryList) { + foodSummary.setRecordList(foodDao.queryFoodRecordById(foodSummary.getId())); + } + + foodSummaryPage.setRecords(foodSummaryList); + return foodSummaryPage; + } + + @Override + public List queryFoodRecord(String startDate, String endDate) { + return foodDao.queryFoodRecord(startDate, endDate); + } + + @Override + public List queryFoodName() { + return foodRecipeMapper.selectList(null) + .stream().map(FoodRecipe::getName).collect(Collectors.toList()); + } + + @Override + public List queryFoodCategory() { + return foodDao.queryFoodCategory(); + } + + @Override + public FoodStatsDto queryFoodStats() { + return foodDao.queryFoodStats(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/JournalServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/JournalServiceImpl.java new file mode 100644 index 0000000..cc1c4ea --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/JournalServiceImpl.java @@ -0,0 +1,57 @@ +package com.cxx.home.service.impl; + +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.JournalDao; +import com.cxx.home.dto.journal.JournalDto; +import com.cxx.home.entity.Journal; +import com.cxx.home.mapper.JournalMapper; +import com.cxx.home.service.JournalService; +import com.cxx.home.vo.JournalQueryVo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class JournalServiceImpl implements JournalService { + @Resource + private JournalDao journalDao; + + @Resource + private JournalMapper journalMapper; + + @Override + public Boolean addJournal(JournalDto journalDto) { + Journal journal = new Journal(); + BeanUtils.copyProperties(journalDto, journal); + + return journalMapper.insert(journal) == 1; + } + + @Override + public Boolean updateJournal(Long id, JournalDto journalDto) { + if (journalMapper.selectById(id) == null) { + throw new CustomException("该日记不存在"); + } + + Journal journal = new Journal(); + BeanUtils.copyProperties(journalDto, journal); + journal.setId(id); + return journalMapper.updateById(journal) == 1; + } + + @Override + public Boolean deleteJournal(Long id) { + if (journalMapper.selectById(id) == null) { + throw new CustomException("该纪念日不存在"); + } + + return journalMapper.deleteById(id) == 1; + } + + @Override + public List queryJournal(JournalQueryVo queryVo) { + return journalDao.queryJournal(queryVo); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/KpiServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/KpiServiceImpl.java new file mode 100644 index 0000000..584461d --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/KpiServiceImpl.java @@ -0,0 +1,58 @@ +package com.cxx.home.service.impl; + +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.KpiDao; +import com.cxx.home.dto.kpi.KpiDto; +import com.cxx.home.entity.Kpi; +import com.cxx.home.mapper.KpiMapper; +import com.cxx.home.service.KpiService; +import com.cxx.home.vo.KpiQueryVo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class KpiServiceImpl implements KpiService { + @Resource + private KpiDao kpiDao; + + @Resource + private KpiMapper kpiMapper; + + + @Override + public Boolean addKpi(KpiDto kpiDto) { + Kpi kpi = new Kpi(); + BeanUtils.copyProperties(kpiDto, kpi); + + return kpiMapper.insert(kpi) == 1; + } + + @Override + public Boolean updateKpi(Long id, KpiDto kpiDto) { + if (kpiMapper.selectById(id) == null) { + throw new CustomException("该绩效不存在"); + } + + Kpi kpi = new Kpi(); + BeanUtils.copyProperties(kpiDto, kpi); + kpi.setId(id); + return kpiMapper.updateById(kpi) == 1; + } + + @Override + public Boolean deleteKpi(Long id) { + if (kpiMapper.selectById(id) == null) { + throw new CustomException("该绩效不存在"); + } + + return kpiMapper.deleteById(id) == 1; + } + + @Override + public List queryKpi(KpiQueryVo queryVo) { + return kpiDao.queryKpi(queryVo); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/LedgerServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/LedgerServiceImpl.java new file mode 100644 index 0000000..7a063dc --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/LedgerServiceImpl.java @@ -0,0 +1,61 @@ +package com.cxx.home.service.impl; + +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.LedgerDao; +import com.cxx.home.dto.ledger.LedgerDto; +import com.cxx.home.entity.Ledger; +import com.cxx.home.mapper.LedgerMapper; +import com.cxx.home.service.LedgerService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class LedgerServiceImpl implements LedgerService { + @Resource + private LedgerDao ledgerDao; + + @Resource + private LedgerMapper ledgerMapper; + + @Override + public Boolean addLedger(LedgerDto ledgerDto) { + Ledger ledger = new Ledger(); + BeanUtils.copyProperties(ledgerDto, ledger); + + return ledgerMapper.insert(ledger) == 1; + } + + @Override + public Boolean updateLedger(Long id, LedgerDto ledgerDto) { + if (ledgerMapper.selectById(id) == null) { + throw new CustomException("该账本内容不存在"); + } + + Ledger ledger = new Ledger(); + BeanUtils.copyProperties(ledgerDto, ledger); + ledger.setId(id); + return ledgerMapper.updateById(ledger) == 1; + } + + @Override + public Boolean deleteLedger(Long id) { + if (ledgerMapper.selectById(id) == null) { + throw new CustomException("该绩效不存在"); + } + + return ledgerMapper.deleteById(id) == 1; + } + + @Override + public List queryLedger(String book) { + return ledgerDao.queryLedger(book); + } + + @Override + public List queryLedgerBook() { + return ledgerDao.queryLedgerBook(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/MessageServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/MessageServiceImpl.java new file mode 100644 index 0000000..b81a805 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/MessageServiceImpl.java @@ -0,0 +1,70 @@ +package com.cxx.home.service.impl; + +import com.cxx.common.dto.message.MailMessageDto; +import com.cxx.home.service.MessageService; +import jakarta.annotation.Resource; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +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.bean.template.WxMpTemplateData; +import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage; +import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Slf4j +public class MessageServiceImpl implements MessageService { + @Resource + private JavaMailSender javaMailSender; + + @Override + public void sendMailMessage(MailMessageDto mailMessageDto) { + try { + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true); + helper.setFrom("njcxx0822@163.com"); + helper.setTo(mailMessageDto.getTo()); + helper.setSubject(mailMessageDto.getSubject()); + helper.setText(mailMessageDto.getBody(), true); + + // 发送邮件 + javaMailSender.send(mimeMessage); + log.info("邮件发送成功"); + } catch (MessagingException e) { + log.error("邮件发送失败: {}", e.getMessage()); + } + } + + @Override + public void sendWxMessage() { + WxMpDefaultConfigImpl wxStorage = new WxMpDefaultConfigImpl(); + wxStorage.setAppId("wxdf137d1a34489880"); + wxStorage.setSecret("25b73681c66a480e726d67bb38aeb71e"); + + WxMpService wxMpService = new WxMpServiceImpl(); + wxMpService.setWxMpConfigStorage(wxStorage); + // 此处的 key/value 需和模板消息对应 + List wxMpTemplateDataList = List.of( + new WxMpTemplateData("test", "Hello World") + ); + + WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder() + .toUser("ol1ZM7PJvNZ4MXWglwz68GtQCppI") // openId为1.3步骤中得到的微信号 + .templateId("JoY6-AmAxLLU7N-tG0-Bl2o0P3_j7gTI4O-L2nZ0R8g") + .data(wxMpTemplateDataList) + .build(); + + try { + wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage); + log.info("推送消息成功"); + } catch (Exception e) { + log.error("推送失败:{}", e.getMessage()); + } + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/PeriodServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/PeriodServiceImpl.java new file mode 100644 index 0000000..9d32b9e --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/PeriodServiceImpl.java @@ -0,0 +1,104 @@ +package com.cxx.home.service.impl; + +import com.cxx.home.dao.PeriodDao; +import com.cxx.home.dto.period.PeriodDayDto; +import com.cxx.home.dto.period.PeriodSettingDto; +import com.cxx.home.entity.PeriodDay; +import com.cxx.home.entity.PeriodSetting; +import com.cxx.home.mapper.PeriodDayMapper; +import com.cxx.home.mapper.PeriodSettingMapper; +import com.cxx.home.service.PeriodService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class PeriodServiceImpl implements PeriodService { + @Resource + private PeriodDao periodDao; + + @Resource + private PeriodDayMapper periodDayMapper; + + @Resource + private PeriodSettingMapper periodSettingMapper; + + @Transactional + @Override + public Boolean updatePeriodDay(Long id, PeriodDayDto periodDayDto) { + if (id == 0) { + // 非月经天 + if (!periodDayDto.getIsMenstruate() && periodDayDto.getSexActivity().isEmpty() + && !periodDayDto.getIsDrug()) { + return Boolean.TRUE; + } else { + PeriodDay periodDay = new PeriodDay(); + BeanUtils.copyProperties(periodDayDto, periodDay); + periodDay.setIsDrug(periodDayDto.getIsDrug() ? 1 : 0); + periodDay.setIsMenstruate(periodDayDto.getIsMenstruate() ? 1 : 0); + return periodDayMapper.insert(periodDay) == 1; + } + } else { + PeriodDay periodDay = new PeriodDay(); + + // 非月经天 + if (!periodDayDto.getIsMenstruate() && periodDayDto.getSexActivity().isEmpty() + && !periodDayDto.getIsDrug()) { + return periodDayMapper.deleteById(id) == 1; + } else { + BeanUtils.copyProperties(periodDayDto, periodDay); + periodDay.setId(id); + periodDay.setIsDrug(periodDayDto.getIsDrug() ? 1 : 0); + periodDay.setIsMenstruate(periodDayDto.getIsMenstruate() ? 1 : 0); + return periodDayMapper.updateById(periodDay) == 1; + } + } + } + + @Override + public List queryPeriodDay(String month) { + return periodDao.queryPeriodDay(month); + } + + @Override + public String getMenstruateFirstDate(String month) { + return periodDao.getMenstruateFirstDate(month); + } + + @Override + public Boolean updatePeriodSetting(Long id, PeriodSettingDto periodSettingDto) { + if (id == 0) { + PeriodSetting periodSetting = new PeriodSetting(); + BeanUtils.copyProperties(periodSettingDto, periodSetting); + periodSetting.setIsCalculate(periodSettingDto.getIsCalculate() ? 1 : 0); + return periodSettingMapper.insert(periodSetting) == 1; + } else { + PeriodSetting periodSetting = new PeriodSetting(); + BeanUtils.copyProperties(periodSettingDto, periodSetting); + periodSetting.setId(id); + periodSetting.setIsCalculate(periodSettingDto.getIsCalculate() ? 1 : 0); + return periodSettingMapper.updateById(periodSetting) == 1; + } + } + + @Override + public PeriodSettingDto queryPeriodSetting() { + List periodSettingList = periodSettingMapper.selectList(null); + PeriodSettingDto periodSettingDto = new PeriodSettingDto(); + + if (periodSettingList.size() > 0) { + BeanUtils.copyProperties(periodSettingList.get(0), periodSettingDto); + periodSettingDto.setIsCalculate(periodSettingList.get(0).getIsCalculate() == 1); + } else { + periodSettingDto.setId(0L); + periodSettingDto.setCycleLength(0); + periodSettingDto.setDuration(0); + periodSettingDto.setIsCalculate(false); + } + + return periodSettingDto; + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/PlanServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/PlanServiceImpl.java new file mode 100644 index 0000000..387e257 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/PlanServiceImpl.java @@ -0,0 +1,136 @@ +package com.cxx.home.service.impl; + +import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.cxx.common.dto.message.MailMessageDto; +import com.cxx.common.dto.plan.PlanDto; +import com.cxx.common.dto.plan.PlanStatsDto; +import com.cxx.common.dto.task.TaskDto; +import com.cxx.common.entity.Plan; +import com.cxx.common.mapper.PlanMapper; +import com.cxx.common.vo.plan.PlanQueryVo; +import com.cxx.home.dao.PlanDao; +import com.cxx.home.schedule.TaskType; +import com.cxx.home.service.PlanService; +import com.cxx.home.service.TaskService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class PlanServiceImpl implements PlanService { + @Resource + private PlanDao planDao; + + @Resource + private PlanMapper planMapper; + + @Resource + private TaskService taskService; + + @Override + public Boolean addPlan(PlanDto planDto) { + Plan plan = new Plan(); + BeanUtils.copyProperties(planDto, plan); + + // 如果存在提醒时间,则新建定时任务 + if (planDto.getAlterTime() != null) { + plan.setTaskId(addPlanTask(planDto)); + } + + return planMapper.insert(plan) == 1; + } + + @Override + public Boolean updatePlan(Long id, PlanDto planDto) { + Plan plan = new Plan(); + BeanUtils.copyProperties(planDto, plan); + plan.setId(id); + planMapper.updateById(plan); + + // 如果存在定时任务,则更新 + if (planDto.getTaskId() != null) { + updatePlanTask(id, plan.getTaskId(), planDto); + } else { + // 如果不存在定时任务,但存在提醒时间,则新建 + if (planDto.getAlterTime() != null) { + plan.setTaskId(addPlanTask(planDto)); + planMapper.updateById(plan); + } + } + + return Boolean.TRUE; + } + + @Override + public Boolean deletePlan(Long id) { + Plan plan = planMapper.selectById(id); + + // 如果存在定时任务 + if (plan != null && plan.getTaskId() != null) { + Long taskId = plan.getTaskId(); + + // 如果存在提醒时间,则删除 + if (plan.getAlterTime() != null) { + taskService.deleteTask(taskId); + } + } + + return planMapper.deleteById(id) == 1; + } + + @Override + public List queryPlan(PlanQueryVo query) { + return planDao.queryPlan(query); + } + + @Override + public Boolean setPlanStatus(Long id, Boolean status) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + updateWrapper.eq("id", id).set("completed", status ? 1 : 0); + + return planMapper.update(null, updateWrapper) > 0; + } + + @Override + public PlanStatsDto queryPlanStats() { + return planDao.queryPlanStats(); + } + + private Long addPlanTask(PlanDto planDto) { + TaskDto taskDto = new TaskDto(); + taskDto.setType(TaskType.EMAIL); + taskDto.setContent(getPlanContent(planDto)); + taskDto.setExecuteTime(planDto.getAlterTime()); + return taskService.addTask(taskDto); + } + + private void updatePlanTask(Long planId, Long taskId, PlanDto planDto) { + TaskDto taskDto = taskService.queryTaskById(taskId); + + // 如果存在提醒时间,则更新 + if (planDto.getAlterTime() != null) { + taskDto.setContent(getPlanContent(planDto)); + taskDto.setExecuteTime(planDto.getAlterTime()); + taskService.updateTask(taskId, taskDto); + } else { + // 如果不存在,则删除 + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(Plan::getId, planId).set(Plan::getTaskId, null); + planMapper.update(updateWrapper); + taskService.deleteTask(taskId); + } + } + + private String getPlanContent(PlanDto planDto) { + MailMessageDto messageDto = new MailMessageDto(); + messageDto.setTo(planDto.getEmail()); + messageDto.setSubject("日程提醒"); + messageDto.setBody("

" + planDto.getTitle() + "


" + planDto.getContent() + "

"); + + return JSONUtil.toJsonStr(messageDto); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/ProductServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/ProductServiceImpl.java new file mode 100644 index 0000000..cb6c567 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/ProductServiceImpl.java @@ -0,0 +1,76 @@ +package com.cxx.home.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.ProductDao; +import com.cxx.home.dto.product.ProductDto; +import com.cxx.home.entity.*; +import com.cxx.home.mapper.*; +import com.cxx.home.service.ProductService; +import com.cxx.home.vo.ProductQueryVo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +public class ProductServiceImpl implements ProductService { + @Resource + private ProductDao productDao; + + @Resource + private ProductMapper productMapper; + + @Override + @Transactional + public Boolean addProduct(ProductDto productDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (productMapper.exists(queryWrapper.eq(Product::getName, productDto.getName()))) { + throw new CustomException("该商品已经存在"); + } + + Product product = new Product(); + BeanUtils.copyProperties(productDto, product); + return productMapper.insert(product) == 1; + } + + @Override + @Transactional + public Boolean updateProduct(Long id, ProductDto productDto) { + if (productMapper.selectById(id) == null) { + throw new CustomException("该商品不存在"); + } + + Product product = new Product(); + BeanUtils.copyProperties(productDto, product); + product.setId(id); + return productMapper.updateById(product) == 1; + } + + @Override + @Transactional + public Boolean deleteProduct(Long id) { + return productMapper.deleteById(id) == 1; + } + + @Override + public ProductDto queryProduct(Long id) { + if (productMapper.selectById(id) == null) { + throw new CustomException("该商品不存在"); + } + + return productDao.queryProduct(id); + } + + @Override + public List queryProductList(ProductQueryVo queryVo) { + return productDao.queryProductList(queryVo); + } + + @Override + public List queryProductCategory() { + return productDao.queryProductCategory(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/QuartzServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/QuartzServiceImpl.java new file mode 100644 index 0000000..706268c --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/QuartzServiceImpl.java @@ -0,0 +1,112 @@ +package com.cxx.home.service.impl; + +import com.cxx.common.entity.Task; +import com.cxx.common.mapper.TaskMapper; +import com.cxx.framework.web.CustomException; +import com.cxx.home.schedule.QuartzDto; +import com.cxx.home.schedule.QuartzUtils; +import com.cxx.home.service.QuartzService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.quartz.*; +import org.quartz.impl.matchers.GroupMatcher; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Set; + +@Service +@Slf4j +public class QuartzServiceImpl implements QuartzService { + @Resource + private Scheduler scheduler; + + @Resource + private TaskMapper taskMapper; + + @Override + public List queryQuartzTask() { + GroupMatcher matcher = GroupMatcher.anyJobGroup(); + List quartzDtoList = new ArrayList<>(); + + try { + Set jobKeys = scheduler.getJobKeys(matcher); + for (JobKey jobKey : jobKeys) { + List triggers = scheduler.getTriggersOfJob(jobKey); + for (Trigger trigger : triggers) { + QuartzDto quartzDto = new QuartzDto(); + // 获取名称和组别 + quartzDto.setName(jobKey.getName()); + quartzDto.setGroup(jobKey.getGroup()); + + // 获取类型和内容 + Task task = taskMapper.selectById(jobKey.getName()); + quartzDto.setType(task.getType()); + quartzDto.setContent(task.getContent()); + + // 获取状态 + // NONE(触发器不存在)NORMAL(正常执行) PAUSED(暂停) + // COMPLETE(完成) ERROR(执行出错) BLOCKED(阻塞) + Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey()); + quartzDto.setStatus(triggerState.name()); + + // 获取执行时间 + if (trigger instanceof CronTrigger) { + CronTrigger cronTrigger = (CronTrigger) trigger; + String cronExpression = cronTrigger.getCronExpression(); + quartzDto.setCronExpression(cronExpression); + } + if (trigger instanceof SimpleTrigger) { + SimpleTrigger simpleTrigger = (SimpleTrigger) trigger; + Date startTime = simpleTrigger.getStartTime(); + quartzDto.setExecuteTime(startTime); + } + quartzDtoList.add(quartzDto); + } + } + } catch (SchedulerException e) { + throw new CustomException("获取任务列表失败: " + e.getMessage()); + } + + return quartzDtoList; + } + + @Override + public void createQuartzTask(Task task) { + try { + JobKey jobKey = new JobKey(task.getId().toString()); + scheduler.scheduleJob(QuartzUtils.getJobDetail(task, jobKey), QuartzUtils.getTrigger(task, jobKey)); + } catch (SchedulerException e) { + throw new CustomException("创建任务: {} " + task.getId() + "失败: {}" + e.getMessage()); + } + } + + @Override + public void updateQuartzTask(Task task) { + try { + JobKey jobKey = new JobKey(task.getId().toString()); + + // 此时并未执行,则更新 + if (scheduler.getJobDetail(jobKey) != null) { + Trigger oldTrigger = scheduler.getTriggersOfJob(jobKey).get(0); + scheduler.rescheduleJob(oldTrigger.getKey(), QuartzUtils.getTrigger(task, jobKey)); + } else { + // 如果已经执行,则新建 + scheduler.scheduleJob(QuartzUtils.getJobDetail(task, jobKey), QuartzUtils.getTrigger(task, jobKey)); + } + } catch (SchedulerException e) { + throw new CustomException("更新任务: {} " + task.getId() + "失败: {}" + e.getMessage()); + } + } + + @Override + public void deleteQuartzTask(JobKey jobKey) { + try { + scheduler.deleteJob(jobKey); + } catch (SchedulerException e) { + throw new CustomException("删除任务: {} " + jobKey.getName() + "失败: {}" + e.getMessage()); + } + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/SessionServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/SessionServiceImpl.java new file mode 100644 index 0000000..4657dcd --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/SessionServiceImpl.java @@ -0,0 +1,57 @@ +package com.cxx.home.service.impl; + + +import cn.dev33.satoken.secure.BCrypt; +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; + +import com.cxx.common.dto.user.SessionDto; +import com.cxx.common.dto.user.UserDto; +import com.cxx.common.entity.Account; +import com.cxx.common.entity.User; +import com.cxx.common.mapper.AccountMapper; +import com.cxx.common.mapper.UserMapper; +import com.cxx.framework.web.CustomException; +import com.cxx.home.service.SessionService; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + + +@Service +public class SessionServiceImpl implements SessionService { + @Resource + private AccountMapper accountMapper; + + @Resource + private UserMapper userMapper; + + @Override + public SessionDto create(String name, String password) { + LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(Account.class).eq(Account::getAccountName, name); + Account account = accountMapper.selectOne(queryWrapper); + if (account == null) { + throw new CustomException("账户: " + name + " 不存在"); + } + + if (!BCrypt.checkpw(password, account.getPassword())) { + throw new CustomException("密码不正确"); + } + + User user = userMapper.selectById(account.getUserId()); + UserDto userDto = new UserDto(); + BeanUtils.copyProperties(user, userDto); + userDto.setAccountId(account.getId()); + userDto.setAccountName(name); + + SessionDto sessionDto = new SessionDto(); + StpUtil.login(account.getId()); + sessionDto.setSaToken(StpUtil.getTokenInfo()); + sessionDto.setUserInfo(userDto); + + StpUtil.getSession().set("username", name); + + return sessionDto; + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/TaskServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/TaskServiceImpl.java new file mode 100644 index 0000000..c34341f --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/TaskServiceImpl.java @@ -0,0 +1,58 @@ +package com.cxx.home.service.impl; + +import com.cxx.common.dto.task.TaskDto; +import com.cxx.common.entity.Task; +import com.cxx.common.mapper.TaskMapper; +import com.cxx.home.service.QuartzService; +import com.cxx.home.service.TaskService; +import jakarta.annotation.Resource; +import org.quartz.JobKey; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; + +@Service +public class TaskServiceImpl implements TaskService { + @Resource + private TaskMapper taskMapper; + + @Resource + private QuartzService quartzService; + + @Override + public TaskDto queryTaskById(Long id) { + Task task = taskMapper.selectById(id); + TaskDto taskDto = new TaskDto(); + taskDto.setType(task.getType()); + taskDto.setContent(task.getContent()); + taskDto.setExecuteTime(task.getExecuteTime()); + taskDto.setCronExpression(task.getCronExpression()); + + return taskDto; + } + + @Override + public Long addTask(TaskDto taskDto) { + Task newTask = new Task(); + BeanUtils.copyProperties(taskDto, newTask); + + taskMapper.insert(newTask); + quartzService.createQuartzTask(newTask); + return newTask.getId(); + } + + @Override + public Boolean updateTask(Long id, TaskDto taskDto) { + Task newTask = new Task(); + BeanUtils.copyProperties(taskDto, newTask); + + newTask.setId(id); + quartzService.updateQuartzTask(newTask); + return taskMapper.updateById(newTask) == 1; + } + + @Override + public Boolean deleteTask(Long id) { + quartzService.deleteQuartzTask(new JobKey(id.toString())); + return taskMapper.deleteById(id) == 1; + } +} diff --git a/home-service/src/main/java/com/cxx/home/service/impl/TravelServiceImpl.java b/home-service/src/main/java/com/cxx/home/service/impl/TravelServiceImpl.java new file mode 100644 index 0000000..0b143e2 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/service/impl/TravelServiceImpl.java @@ -0,0 +1,197 @@ +package com.cxx.home.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.cxx.home.dto.travel.TravelRecordDto; +import com.cxx.home.dto.travel.TravelSpotDto; +import com.cxx.home.dto.travel.TravelStatsDto; +import com.cxx.home.dto.travel.TravelSummaryDto; +import com.cxx.framework.web.CustomException; +import com.cxx.home.dao.TravelDao; +import com.cxx.home.entity.TravelImage; +import com.cxx.home.entity.TravelRecord; +import com.cxx.home.entity.TravelSpot; +import com.cxx.home.entity.TravelVideo; +import com.cxx.home.mapper.TravelImageMapper; +import com.cxx.home.mapper.TravelRecordMapper; +import com.cxx.home.mapper.TravelSpotMapper; +import com.cxx.home.mapper.TravelVideoMapper; +import com.cxx.home.service.TravelService; +import com.cxx.home.vo.TravelQueryVo; +import jakarta.annotation.Resource; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class TravelServiceImpl implements TravelService { + @Resource + private TravelDao travelDao; + + @Resource + private TravelSpotMapper travelSpotMapper; + + @Resource + private TravelRecordMapper travelRecordMapper; + + @Resource + private TravelImageMapper travelImageMapper; + + @Resource + private TravelVideoMapper travelVideoMapper; + + @Override + @Transactional + public Boolean addTravelSpot(TravelSpotDto travelSpotDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + if (travelSpotMapper.exists(queryWrapper.eq(TravelSpot::getName, travelSpotDto.getName()))) { + throw new CustomException("该景点已经存在"); + } + + TravelSpot travelSpot = new TravelSpot(); + BeanUtils.copyProperties(travelSpotDto, travelSpot); + travelSpot.setCity(travelSpotDto.getArea().get(1)); + travelSpotMapper.insert(travelSpot); + + return Boolean.TRUE; + } + + @Override + @Transactional + public Boolean updateTravelSpot(Long id, TravelSpotDto travelSpotDto) { + if (travelSpotMapper.selectById(id) == null) { + throw new CustomException("该景点不存在"); + } + + TravelSpot travelSpot = new TravelSpot(); + BeanUtils.copyProperties(travelSpotDto, travelSpot); + travelSpot.setId(id); + travelSpot.setCity(travelSpotDto.getArea().get(1)); + travelSpotMapper.updateById(travelSpot); + + return Boolean.TRUE; + } + + @Override + @Transactional + public Boolean deleteTravelSpot(Long id) { + travelSpotMapper.deleteById(id); + travelRecordMapper.delete(Wrappers.lambdaQuery(TravelRecord.class).eq(TravelRecord::getTravelId, id)); + + return Boolean.TRUE; + } + + @Override + public Boolean addTravelRecord(TravelRecordDto travelRecordDto) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + TravelSpot travelSpot = travelSpotMapper.selectOne(queryWrapper.eq(TravelSpot::getName, travelRecordDto.getName())); + if (travelSpot == null) { + throw new CustomException("该景点不存在"); + } + + TravelRecord travelRecord = new TravelRecord(); + travelRecord.setTravelId(travelSpot.getId()); + BeanUtils.copyProperties(travelRecordDto, travelRecord); + travelRecordMapper.insert(travelRecord); + + insertTravelImage(travelRecord.getTravelId(), travelRecordDto.getImageList()); + insertTravelVideo(travelRecord.getTravelId(), travelRecordDto.getVideoList()); + return Boolean.TRUE; + } + + @Override + public Boolean updateTravelRecord(Long id, TravelRecordDto travelRecordDto) { + if (travelRecordMapper.selectById(id) == null) { + throw new CustomException("该记录不存在"); + } + + TravelRecord travelRecord = new TravelRecord(); + BeanUtils.copyProperties(travelRecordDto, travelRecord); + travelRecord.setId(id); + travelRecordMapper.updateById(travelRecord); + + deleteTravelImage(id); + deleteTravelVideo(id); + + insertTravelImage(id, travelRecordDto.getImageList()); + insertTravelVideo(id, travelRecordDto.getVideoList()); + return Boolean.TRUE; + } + + @Override + public Boolean deleteTravelRecord(Long id) { + travelRecordMapper.deleteById(id); + + return Boolean.TRUE; + } + + private void insertTravelImage(Long travelId, List imageList) { + if (!imageList.isEmpty()) { + travelDao.insertTravelImage(travelId, imageList); + } + } + + private void insertTravelVideo(Long travelId, List videoList) { + if (!videoList.isEmpty()) { + travelDao.insertTravelVideo(travelId, videoList); + } + } + + private void deleteTravelImage(Long id) { + travelImageMapper.delete(Wrappers.lambdaQuery(TravelImage.class).eq(TravelImage::getRecordId, id)); + } + + private void deleteTravelVideo(Long id) { + travelVideoMapper.delete(Wrappers.lambdaQuery(TravelVideo.class).eq(TravelVideo::getRecordId, id)); + } + + @Override + public TravelSpotDto queryTravelSpot(Long id) { + if (travelSpotMapper.selectById(id) == null) { + throw new CustomException("该景点不存在"); + } + + return travelDao.queryTravelSpot(id); + } + + @Override + public IPage queryTravelSummary(Integer currentPage, Integer pageSize, TravelQueryVo travelQueryVo) { + // 这里只能先对主表进行分页 然后在查询子表信息 + // 不能使用Left Join关联表查询,因为这里是一对多数据,关联查询会导致数据有重复 + // 从而导致page计算错误(会把重复的数据当成多条记录,实际上只有1条记录) + IPage travelSummaryPage = travelDao.queryTravelSummary(new Page<>(currentPage, pageSize), travelQueryVo); + List travelSummaryList = travelSummaryPage.getRecords(); + for (TravelSummaryDto travelSummary : travelSummaryList) { + travelSummary.setRecordList(travelDao.queryTravelRecordById(travelSummary.getId())); + } + + travelSummaryPage.setRecords(travelSummaryList); + return travelSummaryPage; + } + + @Override + public List queryTravelRecord(String startDate, String endDate) { + return travelDao.queryTravelRecord(startDate, endDate); + } + + @Override + public List queryTravelSpotName() { + return travelSpotMapper.selectList(null) + .stream().map(TravelSpot::getName).collect(Collectors.toList()); + } + + @Override + public List queryTravelCategory() { + return travelDao.queryTravelCategory(); + } + + @Override + public TravelStatsDto queryTravelStats() { + return travelDao.queryTravelStats(); + } +} diff --git a/home-service/src/main/java/com/cxx/home/vo/FoodQueryVo.java b/home-service/src/main/java/com/cxx/home/vo/FoodQueryVo.java new file mode 100644 index 0000000..e4f6bd8 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/vo/FoodQueryVo.java @@ -0,0 +1,13 @@ + +package com.cxx.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class FoodQueryVo { + @Schema(description = "美食类别") + private String category; +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/vo/JournalQueryVo.java b/home-service/src/main/java/com/cxx/home/vo/JournalQueryVo.java new file mode 100644 index 0000000..42c0d2a --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/vo/JournalQueryVo.java @@ -0,0 +1,15 @@ +package com.cxx.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class JournalQueryVo { + @Schema(description = "开始日期") + private String startDate; + + @Schema(description = "结束日期") + private String endDate; +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/vo/KpiQueryVo.java b/home-service/src/main/java/com/cxx/home/vo/KpiQueryVo.java new file mode 100644 index 0000000..b22848b --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/vo/KpiQueryVo.java @@ -0,0 +1,15 @@ +package com.cxx.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class KpiQueryVo { + @Schema(description = "开始日期") + private String startDate; + + @Schema(description = "结束日期") + private String endDate; +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/vo/ProductQueryVo.java b/home-service/src/main/java/com/cxx/home/vo/ProductQueryVo.java new file mode 100644 index 0000000..aa88cf8 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/vo/ProductQueryVo.java @@ -0,0 +1,16 @@ + +package com.cxx.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ProductQueryVo { + @Schema(description = "物品类别") + private String category; + + @Schema(description = "排序规则") + private String order; +} \ No newline at end of file diff --git a/home-service/src/main/java/com/cxx/home/vo/TravelQueryVo.java b/home-service/src/main/java/com/cxx/home/vo/TravelQueryVo.java new file mode 100644 index 0000000..f168739 --- /dev/null +++ b/home-service/src/main/java/com/cxx/home/vo/TravelQueryVo.java @@ -0,0 +1,13 @@ + +package com.cxx.home.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class TravelQueryVo { + @Schema(description = "旅行类别") + private String category; +} \ No newline at end of file diff --git a/home-service/src/main/resources/application-dev.yml b/home-service/src/main/resources/application-dev.yml new file mode 100644 index 0000000..56c58fe --- /dev/null +++ b/home-service/src/main/resources/application-dev.yml @@ -0,0 +1,6 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: root + password: 123456 diff --git a/home-service/src/main/resources/application-docker.yml b/home-service/src/main/resources/application-docker.yml new file mode 100644 index 0000000..5a6d0ab --- /dev/null +++ b/home-service/src/main/resources/application-docker.yml @@ -0,0 +1,6 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://mysql:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: docker + password: 19940822Cxx diff --git a/home-service/src/main/resources/application-prod.yml b/home-service/src/main/resources/application-prod.yml new file mode 100644 index 0000000..42635cf --- /dev/null +++ b/home-service/src/main/resources/application-prod.yml @@ -0,0 +1,6 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://127.0.0.1:3306/sweet_hut?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8&useSSL=false + username: cxx + password: 19940822Cxx@1213 \ No newline at end of file diff --git a/home-service/src/main/resources/application.yml b/home-service/src/main/resources/application.yml new file mode 100644 index 0000000..eeb4a86 --- /dev/null +++ b/home-service/src/main/resources/application.yml @@ -0,0 +1,36 @@ +server: + port: 8081 + +spring: + application: + name: @project.artifactId@ + version: @project.version@ + profiles: + active: dev + mail: + host: smtp.163.com + port: 465 + username: njcxx0822@163.com + password: CDfsF386Y2FWKHHm + protocol: smtps + properties: + mail: + smtp: + auth: true + starttls: + enable: true + default-encoding: UTF-8 + quartz: + job-store-type: jdbc + + +# mybatis plus mapper路径 +mybatis-plus: + # mybatis plus + mapper-locations: classpath*:/mapper/**/*.xml + configuration: + log-impl: + org.apache.ibatis.logging.stdout.StdOutImpl + +web-starter: + base-package: com.cxx.home \ No newline at end of file diff --git a/home-service/src/main/resources/mapper/AnniversaryMapper.xml b/home-service/src/main/resources/mapper/AnniversaryMapper.xml new file mode 100644 index 0000000..f84c702 --- /dev/null +++ b/home-service/src/main/resources/mapper/AnniversaryMapper.xml @@ -0,0 +1,41 @@ + + + + + + + diff --git a/home-service/src/main/resources/mapper/AssetMapper.xml b/home-service/src/main/resources/mapper/AssetMapper.xml new file mode 100644 index 0000000..7a7b14b --- /dev/null +++ b/home-service/src/main/resources/mapper/AssetMapper.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/home-service/src/main/resources/mapper/BillMapper.xml b/home-service/src/main/resources/mapper/BillMapper.xml new file mode 100644 index 0000000..abf2cd4 --- /dev/null +++ b/home-service/src/main/resources/mapper/BillMapper.xml @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO bill_image (bill_id, image_url) VALUES + + (#{billId}, #{item}) + + + + + + + + + + + diff --git a/home-service/src/main/resources/mapper/BudgetMapper.xml b/home-service/src/main/resources/mapper/BudgetMapper.xml new file mode 100644 index 0000000..802367d --- /dev/null +++ b/home-service/src/main/resources/mapper/BudgetMapper.xml @@ -0,0 +1,37 @@ + + + + + + + + + diff --git a/home-service/src/main/resources/mapper/FoodMapper.xml b/home-service/src/main/resources/mapper/FoodMapper.xml new file mode 100644 index 0000000..f681063 --- /dev/null +++ b/home-service/src/main/resources/mapper/FoodMapper.xml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO food_material (id, food_id, type, name, amount) VALUES + + (#{item.id}, #{foodId}, #{item.type}, #{item.name}, #{item.amount}) + + + + + INSERT INTO food_step (id, food_id, sort, content, image_url) VALUES + + (#{item.id}, #{foodId}, #{item.sort}, #{item.content}, #{item.imageUrl}) + + + diff --git a/home-service/src/main/resources/mapper/JournalMapper.xml b/home-service/src/main/resources/mapper/JournalMapper.xml new file mode 100644 index 0000000..489d51f --- /dev/null +++ b/home-service/src/main/resources/mapper/JournalMapper.xml @@ -0,0 +1,19 @@ + + + + + diff --git a/home-service/src/main/resources/mapper/KpiMapper.xml b/home-service/src/main/resources/mapper/KpiMapper.xml new file mode 100644 index 0000000..8c40553 --- /dev/null +++ b/home-service/src/main/resources/mapper/KpiMapper.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/home-service/src/main/resources/mapper/LedgerMapper.xml b/home-service/src/main/resources/mapper/LedgerMapper.xml new file mode 100644 index 0000000..c47fca7 --- /dev/null +++ b/home-service/src/main/resources/mapper/LedgerMapper.xml @@ -0,0 +1,25 @@ + + + + + + + diff --git a/home-service/src/main/resources/mapper/PeriodMapper.xml b/home-service/src/main/resources/mapper/PeriodMapper.xml new file mode 100644 index 0000000..dd61010 --- /dev/null +++ b/home-service/src/main/resources/mapper/PeriodMapper.xml @@ -0,0 +1,22 @@ + + + + + + + diff --git a/home-service/src/main/resources/mapper/PlanMapper.xml b/home-service/src/main/resources/mapper/PlanMapper.xml new file mode 100644 index 0000000..7df7ce2 --- /dev/null +++ b/home-service/src/main/resources/mapper/PlanMapper.xml @@ -0,0 +1,42 @@ + + + + + + + diff --git a/home-service/src/main/resources/mapper/ProductMapper.xml b/home-service/src/main/resources/mapper/ProductMapper.xml new file mode 100644 index 0000000..5062aae --- /dev/null +++ b/home-service/src/main/resources/mapper/ProductMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + diff --git a/home-service/src/main/resources/mapper/TravelMapper.xml b/home-service/src/main/resources/mapper/TravelMapper.xml new file mode 100644 index 0000000..2a300d3 --- /dev/null +++ b/home-service/src/main/resources/mapper/TravelMapper.xml @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO travel_image (record_id, image_url) VALUES + + (#{recordId}, #{item}) + + + + + INSERT INTO travel_video (record_id, video_url) VALUES + + (#{recordId}, #{item}) + + + diff --git a/home-service/src/test/java/com/cxx/home/HomeServiceApplicationTests.java b/home-service/src/test/java/com/cxx/home/HomeServiceApplicationTests.java new file mode 100644 index 0000000..992f06d --- /dev/null +++ b/home-service/src/test/java/com/cxx/home/HomeServiceApplicationTests.java @@ -0,0 +1,11 @@ +package com.cxx.home; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +@Slf4j +public class HomeServiceApplicationTests { + +} + diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..8a8fb22 --- /dev/null +++ b/mvnw @@ -0,0 +1,316 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 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..04bb870 --- /dev/null +++ b/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + + com.cxx + starter-parent + 2.0.0 + + + + sweet-hut-service + 2.0.0 + pom + + + 2.0.0 + + + + blog-service + home-service + admin-service + common + + + + + temp + file:///D:/temp/maven + + + diff --git a/sweet_hut.sql b/sweet_hut.sql new file mode 100644 index 0000000..390d863 --- /dev/null +++ b/sweet_hut.sql @@ -0,0 +1,625 @@ +/* + Navicat Premium Data Transfer + + Source Server : localhost + Source Server Type : MySQL + Source Server Version : 80027 + Source Host : localhost:3306 + Source Schema : sweet_hut + + Target Server Type : MySQL + Target Server Version : 80027 + File Encoding : 65001 + + Date: 16/02/2025 22:04:44 +*/ + +SET NAMES utf8mb4; +SET FOREIGN_KEY_CHECKS = 0; + +-- ---------------------------- +-- Table structure for account +-- ---------------------------- +DROP TABLE IF EXISTS `account`; +CREATE TABLE `account` ( + `id` bigint NOT NULL, + `account_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '账户名', + `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '密码', + `user_id` bigint NULL DEFAULT NULL COMMENT '用户id', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '家庭账户' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for bill_book +-- ---------------------------- +DROP TABLE IF EXISTS `bill_book`; +CREATE TABLE `bill_book` ( + `id` bigint NOT NULL, + `name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账本名称', + `icon` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账本图标', + `color` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标颜色', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '账本类型' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for bill_category +-- ---------------------------- +DROP TABLE IF EXISTS `bill_category`; +CREATE TABLE `bill_category` ( + `id` bigint NOT NULL, + `book_id` bigint NULL DEFAULT NULL COMMENT '账本id', + `name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单类别名称', + `type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单类型', + `icon` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单类别图标', + `color` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标颜色', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '账单类型' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for bill_image +-- ---------------------------- +DROP TABLE IF EXISTS `bill_image`; +CREATE TABLE `bill_image` ( + `bill_id` bigint NOT NULL COMMENT '账单id', + `image_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '图片路径', + PRIMARY KEY (`bill_id`, `image_url`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '账单图片' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for bill_pay +-- ---------------------------- +DROP TABLE IF EXISTS `bill_pay`; +CREATE TABLE `bill_pay` ( + `id` bigint NOT NULL, + `name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账户名称', + `icon` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图标', + `color` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '颜色', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '账单账户' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for bill_record +-- ---------------------------- +DROP TABLE IF EXISTS `bill_record`; +CREATE TABLE `bill_record` ( + `id` bigint NOT NULL, + `book_id` bigint NULL DEFAULT NULL COMMENT '账本id', + `type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单类型 支出/收入', + `category_id` bigint NULL DEFAULT NULL COMMENT '账单类别id', + `location` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单地点', + `date` datetime NULL DEFAULT NULL COMMENT '账单日期', + `pay_id` bigint NULL DEFAULT NULL COMMENT '支付账户', + `amount` decimal(10, 2) NULL DEFAULT NULL COMMENT '账单金额', + `content` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单内容', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账单备注', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '账单记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for blog +-- ---------------------------- +DROP TABLE IF EXISTS `blog`; +CREATE TABLE `blog` ( + `id` bigint NOT NULL, + `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '博客标题', + `top_value` int NULL DEFAULT NULL COMMENT '置顶值 越大越靠前', + `is_great` tinyint NULL DEFAULT NULL COMMENT '是否是精品 0否1是', + `category_id` bigint NULL DEFAULT NULL COMMENT '博客类别', + `summary` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '博客内容概要', + `content_id` bigint NULL DEFAULT NULL COMMENT '博客内容', + `word_count` int NULL DEFAULT NULL COMMENT '字数统计', + `read_duration` decimal(10, 2) NULL DEFAULT NULL COMMENT '阅读时长', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '发布时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '发布人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '博客记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for blog_category +-- ---------------------------- +DROP TABLE IF EXISTS `blog_category`; +CREATE TABLE `blog_category` ( + `id` bigint NOT NULL, + `name` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '类别名称', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '博客类别' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for blog_comment +-- ---------------------------- +DROP TABLE IF EXISTS `blog_comment`; +CREATE TABLE `blog_comment` ( + `id` bigint NOT NULL COMMENT 'id', + `parent_id` bigint NULL DEFAULT NULL COMMENT '父评论id', + `user_id` bigint NULL DEFAULT NULL COMMENT '评论人id', + `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '评论内容', + `create_time` datetime NULL DEFAULT NULL COMMENT '评论时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '博客评论' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for blog_content +-- ---------------------------- +DROP TABLE IF EXISTS `blog_content`; +CREATE TABLE `blog_content` ( + `id` bigint NOT NULL, + `content` mediumblob NULL COMMENT '博客内容', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '博客内容' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for blog_like +-- ---------------------------- +DROP TABLE IF EXISTS `blog_like`; +CREATE TABLE `blog_like` ( + `id` bigint NOT NULL COMMENT 'id', + `user_id` bigint NULL DEFAULT NULL COMMENT '点赞人', + `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '点赞类型(博客、评论)', + `target_id` bigint NULL DEFAULT NULL COMMENT '点赞目标的id', + `status` tinyint NULL DEFAULT NULL COMMENT '点赞状态 0取消点赞/1点赞', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '博客点赞' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for blog_visit +-- ---------------------------- +DROP TABLE IF EXISTS `blog_visit`; +CREATE TABLE `blog_visit` ( + `id` bigint NOT NULL, + `ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'ip地址', + `os` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '操作系统', + `browser` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '浏览器', + `uri` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '路径', + `blog_id` bigint NULL DEFAULT NULL COMMENT '博客id', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '博客访问记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for budget +-- ---------------------------- +DROP TABLE IF EXISTS `budget`; +CREATE TABLE `budget` ( + `id` bigint NOT NULL, + `category_id` bigint NULL DEFAULT NULL COMMENT '类别id', + `project` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '项目', + `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '内容', + `vendor` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '供应商', + `budget` decimal(10, 2) NULL DEFAULT NULL COMMENT '预算支出', + `actual` decimal(10, 2) NULL DEFAULT NULL COMMENT '实际支出', + `pay_time` datetime NULL DEFAULT NULL COMMENT '支付时间', + `remake` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '预算支出' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for budget_category +-- ---------------------------- +DROP TABLE IF EXISTS `budget_category`; +CREATE TABLE `budget_category` ( + `id` bigint NOT NULL, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类别名称', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '预算支出' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for file_record +-- ---------------------------- +DROP TABLE IF EXISTS `file_record`; +CREATE TABLE `file_record` ( + `id` bigint NOT NULL, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件名称', + `md5` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件md5', + `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件路径', + `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件url', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '文件' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for food_material +-- ---------------------------- +DROP TABLE IF EXISTS `food_material`; +CREATE TABLE `food_material` ( + `id` bigint NOT NULL, + `food_id` bigint NULL DEFAULT NULL COMMENT '美食id', + `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '类型', + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '名称', + `amount` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '分量', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '美食食材' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for food_recipe +-- ---------------------------- +DROP TABLE IF EXISTS `food_recipe`; +CREATE TABLE `food_recipe` ( + `id` bigint NOT NULL, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '美食名称', + `category` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '美食菜系', + `recommend_rate` int NULL DEFAULT NULL COMMENT '推荐指数', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '美食记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for food_record +-- ---------------------------- +DROP TABLE IF EXISTS `food_record`; +CREATE TABLE `food_record` ( + `id` bigint NOT NULL, + `food_id` bigint NULL DEFAULT NULL COMMENT '美食id', + `date` date NULL DEFAULT NULL COMMENT '完成时间', + `person` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '完成人', + `image_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片路径', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '美食成果' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for food_step +-- ---------------------------- +DROP TABLE IF EXISTS `food_step`; +CREATE TABLE `food_step` ( + `id` bigint NOT NULL, + `food_id` bigint NULL DEFAULT NULL COMMENT '美食id', + `sort` int NULL DEFAULT NULL COMMENT '顺序', + `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '内容', + `image_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '图片地址', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '美食步骤' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for home_account +-- ---------------------------- +DROP TABLE IF EXISTS `home_account`; +CREATE TABLE `home_account` ( + `id` bigint NOT NULL, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '账户名', + `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '昵称', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '家庭账户' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for plan +-- ---------------------------- +DROP TABLE IF EXISTS `plan`; +CREATE TABLE `plan` ( + `id` bigint NOT NULL, + `title` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标题', + `content` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '内容', + `date` date NULL DEFAULT NULL COMMENT '日期', + `start_time` time NULL DEFAULT NULL COMMENT '开始时间', + `end_time` time NULL DEFAULT NULL COMMENT '结束时间', + `alter_time` datetime NULL DEFAULT NULL COMMENT '提醒时间', + `task_id` bigint NULL DEFAULT NULL COMMENT '任务id', + `tag` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '标签', + `is_top` tinyint NULL DEFAULT NULL COMMENT '是否置顶1是0否', + `priority` tinyint NULL DEFAULT NULL COMMENT '优先级 0高1中2低3正常', + `completed` tinyint NULL DEFAULT NULL COMMENT '是否完成1完成0未完成', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `update_by` datetime NULL DEFAULT NULL COMMENT '更新人', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '日程计划' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for property_record +-- ---------------------------- +DROP TABLE IF EXISTS `property_record`; +CREATE TABLE `property_record` ( + `id` int NOT NULL AUTO_INCREMENT, + `date` date NULL DEFAULT NULL, + `role` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + `amount` int NULL DEFAULT NULL, + `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 19 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_blob_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_blob_triggers`; +CREATE TABLE `qrtz_blob_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `BLOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_calendars +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_calendars`; +CREATE TABLE `qrtz_calendars` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CALENDAR_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CALENDAR` blob NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_cron_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_cron_triggers`; +CREATE TABLE `qrtz_cron_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `CRON_EXPRESSION` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TIME_ZONE_ID` varchar(80) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_fired_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_fired_triggers`; +CREATE TABLE `qrtz_fired_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `ENTRY_ID` varchar(95) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `INSTANCE_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `FIRED_TIME` bigint NOT NULL, + `SCHED_TIME` bigint NOT NULL, + `PRIORITY` int NOT NULL, + `STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_job_details +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_job_details`; +CREATE TABLE `qrtz_job_details` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_DURABLE` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_locks +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_locks`; +CREATE TABLE `qrtz_locks` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `LOCK_NAME` varchar(40) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_paused_trigger_grps +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_paused_trigger_grps`; +CREATE TABLE `qrtz_paused_trigger_grps` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_scheduler_state +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_scheduler_state`; +CREATE TABLE `qrtz_scheduler_state` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `INSTANCE_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `LAST_CHECKIN_TIME` bigint NOT NULL, + `CHECKIN_INTERVAL` bigint NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_simple_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simple_triggers`; +CREATE TABLE `qrtz_simple_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `REPEAT_COUNT` bigint NOT NULL, + `REPEAT_INTERVAL` bigint NOT NULL, + `TIMES_TRIGGERED` bigint NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_simprop_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_simprop_triggers`; +CREATE TABLE `qrtz_simprop_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `STR_PROP_1` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `STR_PROP_2` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `STR_PROP_3` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `INT_PROP_1` int NULL DEFAULT NULL, + `INT_PROP_2` int NULL DEFAULT NULL, + `LONG_PROP_1` bigint NULL DEFAULT NULL, + `LONG_PROP_2` bigint NULL DEFAULT NULL, + `DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL, + `DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL, + `BOOL_PROP_1` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `BOOL_PROP_2` varchar(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `qrtz_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `qrtz_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for qrtz_triggers +-- ---------------------------- +DROP TABLE IF EXISTS `qrtz_triggers`; +CREATE TABLE `qrtz_triggers` ( + `SCHED_NAME` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `NEXT_FIRE_TIME` bigint NULL DEFAULT NULL, + `PREV_FIRE_TIME` bigint NULL DEFAULT NULL, + `PRIORITY` int NULL DEFAULT NULL, + `TRIGGER_STATE` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `TRIGGER_TYPE` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `START_TIME` bigint NOT NULL, + `END_TIME` bigint NULL DEFAULT NULL, + `CALENDAR_NAME` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, + `MISFIRE_INSTR` smallint NULL DEFAULT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `SCHED_NAME`(`SCHED_NAME` ASC, `JOB_NAME` ASC, `JOB_GROUP` ASC) USING BTREE, + CONSTRAINT `qrtz_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `qrtz_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for task +-- ---------------------------- +DROP TABLE IF EXISTS `task`; +CREATE TABLE `task` ( + `id` bigint NOT NULL, + `type` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '任务类型', + `content` json NULL COMMENT '任务内容', + `execute_time` datetime NULL DEFAULT NULL COMMENT '执行时间', + `cron_expression` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '定时时间', + `is_scheduled` tinyint(1) NULL DEFAULT NULL COMMENT '是否执行', + `is_updated` tinyint(1) NULL DEFAULT NULL COMMENT '是否更新', + `is_deleted` tinyint(1) NULL DEFAULT NULL COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '任务' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for travel_image +-- ---------------------------- +DROP TABLE IF EXISTS `travel_image`; +CREATE TABLE `travel_image` ( + `record_id` bigint NOT NULL COMMENT '记录id', + `image_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '图片路径', + PRIMARY KEY (`record_id`, `image_url`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '旅行记录图片' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for travel_record +-- ---------------------------- +DROP TABLE IF EXISTS `travel_record`; +CREATE TABLE `travel_record` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `travel_id` bigint NULL DEFAULT NULL, + `date` date NULL DEFAULT NULL, + `persons` json NULL, + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 643681849069638 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '旅行记录' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for travel_spot +-- ---------------------------- +DROP TABLE IF EXISTS `travel_spot`; +CREATE TABLE `travel_spot` ( + `id` bigint NOT NULL, + `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '景点名称', + `area` json NULL COMMENT '景点地区', + `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '景点地址', + `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '景点价格', + `recommend_rate` int NULL DEFAULT NULL COMMENT '推荐指数', + `traffic` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '交通', + `router` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '游戏路线', + `foods` json NULL COMMENT '美食推荐', + `projects` json NULL COMMENT '项目推荐', + `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '旅游景点' ROW_FORMAT = DYNAMIC; + +-- ---------------------------- +-- Table structure for user +-- ---------------------------- +DROP TABLE IF EXISTS `user`; +CREATE TABLE `user` ( + `id` bigint NOT NULL, + `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名', + `gender` tinyint NULL DEFAULT NULL COMMENT '性别', + `id_number` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '身份证号', + `phone_number` varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号', + `email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱', + `birth_date` date NULL DEFAULT NULL COMMENT '生日', + `avatar` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '头像', + `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = DYNAMIC; + +SET FOREIGN_KEY_CHECKS = 1;