commit a2de21b09292329ecb5b5d6c4e71bc50f2bd8d52
Author: Cxx0822 <1556464090@qq.com>
Date: Tue Jun 10 09:54:52 2025 +0800
feat: 移植工程
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 0000000..bf82ff0
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
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