feat: 移植工程
This commit is contained in:
35
.gitignore
vendored
Normal file
35
.gitignore
vendored
Normal file
@@ -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/**
|
||||||
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -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
|
||||||
52
README.md
Normal file
52
README.md
Normal file
@@ -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
|
||||||
|
|
||||||
38
admin-service/.gitignore
vendored
Normal file
38
admin-service/.gitignore
vendored
Normal file
@@ -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
|
||||||
6
admin-service/Dockerfile
Normal file
6
admin-service/Dockerfile
Normal file
@@ -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"]
|
||||||
58
admin-service/pom.xml
Normal file
58
admin-service/pom.xml
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.cxx</groupId>
|
||||||
|
<artifactId>sweet-hut-service</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>admin-service</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cxx</groupId>
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.checkerframework</groupId>-->
|
||||||
|
<!-- <artifactId>checker-qual</artifactId>-->
|
||||||
|
<!-- <version>2.0.0</version>-->
|
||||||
|
<!-- <scope>compile</scope>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<!-- 服务器监控 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.oshi</groupId>
|
||||||
|
<artifactId>oshi-core</artifactId>
|
||||||
|
<version>6.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- influxdb -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.influxdb</groupId>
|
||||||
|
<artifactId>influxdb-client-java</artifactId>
|
||||||
|
<version>7.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<!-- <build>-->
|
||||||
|
<!-- <plugins>-->
|
||||||
|
<!-- <plugin>-->
|
||||||
|
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
|
||||||
|
<!-- </plugin>-->
|
||||||
|
<!-- </plugins>-->
|
||||||
|
<!-- </build>-->
|
||||||
|
</project>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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";
|
||||||
|
}
|
||||||
@@ -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<AccountDto> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<BlogDto> 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<BlogCategoryDto> 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<BlogVisitDto> queryBlogVisit(@RequestParam("currentPage") Integer currentPage,
|
||||||
|
@RequestParam("pageSize") Integer pageSize) {
|
||||||
|
return blogManageService.queryBlogVisit(currentPage, pageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<FileInfoDto> getFolderInfo(@RequestParam String folderName) {
|
||||||
|
return fileService.getFolderInfo(folderName);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<SystemMetricsDto> querySystemMetrics(@RequestParam String range) {
|
||||||
|
return serverMonitorService.querySystemMetrics(range);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<AccountDto> queryAccount();
|
||||||
|
}
|
||||||
24
admin-service/src/main/java/com/cxx/admin/dao/BlogDao.java
Normal file
24
admin-service/src/main/java/com/cxx/admin/dao/BlogDao.java
Normal file
@@ -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<BlogDto> queryBlogByPage(IPage<Blog> page);
|
||||||
|
|
||||||
|
BlogDto queryBlogById(@Param("id") Long id);
|
||||||
|
|
||||||
|
List<BlogCategoryDto> queryBlogCategory();
|
||||||
|
|
||||||
|
IPage<BlogVisitDto> queryBlogVisit(IPage<Blog> page);
|
||||||
|
}
|
||||||
23
admin-service/src/main/java/com/cxx/admin/dto/FtpInfo.java
Normal file
23
admin-service/src/main/java/com/cxx/admin/dto/FtpInfo.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<Integer> uploadedChunkList;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.cxx.admin.dto.server;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class CpuDto {
|
||||||
|
private double usagePercent;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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("结束存储服务器状态");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<AccountDto> queryAccountList();
|
||||||
|
|
||||||
|
Account queryAccountByUserId(Long userId);
|
||||||
|
|
||||||
|
Boolean registerAccount(AccountDto accountDto);
|
||||||
|
|
||||||
|
Boolean deleteAccount(Long id);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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<BlogDto> queryBlogByPage(Integer currentPage, Integer pageSize);
|
||||||
|
|
||||||
|
BlogDto queryBlogById(Long id);
|
||||||
|
|
||||||
|
List<BlogCategoryDto> queryBlogCategory();
|
||||||
|
|
||||||
|
Boolean addBlog(BlogDto blog);
|
||||||
|
|
||||||
|
Boolean updateBlog(Long id, BlogDto blog);
|
||||||
|
|
||||||
|
Boolean deleteBlog(Long id);
|
||||||
|
|
||||||
|
IPage<BlogVisitDto> queryBlogVisit(Integer currentPage, Integer pageSize);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package com.cxx.admin.service;
|
||||||
|
|
||||||
|
|
||||||
|
public interface BudgetManageService {
|
||||||
|
Boolean addBudgetCategory(String category);
|
||||||
|
|
||||||
|
Boolean updateBudgetCategory(Long id, String category);
|
||||||
|
}
|
||||||
@@ -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<FileInfoDto> getFolderInfo(String folderName);
|
||||||
|
}
|
||||||
@@ -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<SystemMetricsDto> querySystemMetrics(String range) ;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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<AccountDto> queryAccountList() {
|
||||||
|
return accountDao.queryAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Account queryAccountByUserId(Long userId) {
|
||||||
|
LambdaQueryWrapper<Account> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
return accountMapper.selectOne(queryWrapper.eq(Account::getUserId, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Override
|
||||||
|
public Boolean registerAccount(AccountDto accountDto) {
|
||||||
|
LambdaQueryWrapper<Account> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (accountMapper.exists(queryWrapper.eq(Account::getAccountName, accountDto.getAccountName()))) {
|
||||||
|
throw new CustomException("该账户已经存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
LambdaQueryWrapper<User> userQueryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (userMapper.exists(userQueryWrapper.eq(User::getUsername, accountDto.getUsername()))) {
|
||||||
|
throw new CustomException("该用户已注册");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Integer> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<BillPay> 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<BillBook> 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<BillBook> 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<BillCategory> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<BlogDto> 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<BlogCategoryDto> 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<BlogVisitDto> 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<BlogCategory> 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<Blog> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<BudgetCategory> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Integer> 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<FileInfoDto> getFolderInfo(String folderName) {
|
||||||
|
File folder = new File(folderName);
|
||||||
|
List<FileInfoDto> fileInfoList = new ArrayList<>();
|
||||||
|
if (folder.exists() && folder.isDirectory()) {
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
List<FileInfoDto> folderInfoList = new ArrayList<>();
|
||||||
|
List<FileInfoDto> 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<FileRecord> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<HWDiskStore> 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<SystemMetricsDto> 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<Map<String, Object>> results = executeQuery(fluxQuery);
|
||||||
|
|
||||||
|
List<SystemMetricsDto> systemMetricsList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map<String, Object> 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<Map<String, Object>> executeQuery(String fluxQuery) {
|
||||||
|
List<FluxTable> tables = queryApi.query(fluxQuery);
|
||||||
|
List<Map<String, Object>> results = new ArrayList<>();
|
||||||
|
|
||||||
|
for (FluxTable table : tables) {
|
||||||
|
table.getRecords().forEach(record -> {
|
||||||
|
Map<String, Object> 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Account> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<User> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Character> 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
125
admin-service/src/main/java/com/cxx/admin/util/FtpUtils.java
Normal file
125
admin-service/src/main/java/com/cxx/admin/util/FtpUtils.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<Integer> getUploadedChunkList(String folder, String filename) {
|
||||||
|
List<Integer> uploadedChunkList = new ArrayList<>();
|
||||||
|
|
||||||
|
// 获取文件夹下所有的文件
|
||||||
|
try (Stream<Path> 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<Path> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
admin-service/src/main/resources/application-dev.yml
Normal file
15
admin-service/src/main/resources/application-dev.yml
Normal file
@@ -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\\
|
||||||
16
admin-service/src/main/resources/application-docker.yml
Normal file
16
admin-service/src/main/resources/application-docker.yml
Normal file
@@ -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/
|
||||||
16
admin-service/src/main/resources/application-prod.yml
Normal file
16
admin-service/src/main/resources/application-prod.yml
Normal file
@@ -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/
|
||||||
36
admin-service/src/main/resources/application.yml
Normal file
36
admin-service/src/main/resources/application.yml
Normal file
@@ -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
|
||||||
120
admin-service/src/main/resources/logback-spring-drop.xml
Normal file
120
admin-service/src/main/resources/logback-spring-drop.xml
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration scan="true" scanPeriod="10 seconds">
|
||||||
|
|
||||||
|
<contextName>logback</contextName>
|
||||||
|
|
||||||
|
<property name="log.path" value="logs/adminService"/>
|
||||||
|
|
||||||
|
<!--控制台日志格式:彩色日志-->
|
||||||
|
<!-- magenta:洋红 -->
|
||||||
|
<!-- boldMagenta:粗红-->
|
||||||
|
<!-- cyan:青色 -->
|
||||||
|
<!-- white:白色 -->
|
||||||
|
<!-- magenta:洋红 -->
|
||||||
|
<property name="CONSOLE_LOG_PATTERN"
|
||||||
|
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
|
||||||
|
|
||||||
|
<!--文件日志格式-->
|
||||||
|
<property name="FILE_LOG_PATTERN"
|
||||||
|
value="%date{yyyy-MM-dd HH:mm:ss} |%-5level |%thread |%file:%line |%logger |%msg%n"/>
|
||||||
|
|
||||||
|
<!--编码-->
|
||||||
|
<property name="ENCODING"
|
||||||
|
value="UTF-8"/>
|
||||||
|
|
||||||
|
<!--输出到控制台-->
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<!--日志级别-->
|
||||||
|
<level>DEBUG</level>
|
||||||
|
</filter>
|
||||||
|
<encoder>
|
||||||
|
<!--日志格式-->
|
||||||
|
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
|
||||||
|
<!--日志字符集-->
|
||||||
|
<charset>${ENCODING}</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!--输出到文件-->
|
||||||
|
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!--日志过滤器:此日志文件只记录INFO级别的-->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||||
|
<file>${log.path}/log_info.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>${ENCODING}</charset>
|
||||||
|
</encoder>
|
||||||
|
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 每天日志归档路径以及格式 -->
|
||||||
|
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>500MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!--日志文件保留天数-->
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!-- 日志过滤器:此日志文件只记录WARN级别的 -->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>WARN</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||||
|
<file>${log.path}/log_warn.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>${ENCODING}</charset> <!-- 此处设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!--日志文件保留天数-->
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!-- 日志过滤器:此日志文件只记录ERROR级别的 -->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||||
|
<file>${log.path}/log_error.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>${ENCODING}</charset> <!-- 此处设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!--日志文件保留天数-->
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
<appender-ref ref="INFO_FILE"/>
|
||||||
|
<appender-ref ref="WARN_FILE"/>
|
||||||
|
<appender-ref ref="ERROR_FILE"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
13
admin-service/src/main/resources/mapper/AccountMapper.xml
Normal file
13
admin-service/src/main/resources/mapper/AccountMapper.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.cxx.admin.dao.AccountDao">
|
||||||
|
<select id="queryAccount" resultType="com.cxx.admin.dto.user.AccountDto">
|
||||||
|
SELECT b.id AS id,
|
||||||
|
b.account_name AS accountName,
|
||||||
|
a.username AS username,
|
||||||
|
b.state AS state,
|
||||||
|
b.create_time AS date
|
||||||
|
FROM user as a
|
||||||
|
LEFT JOIN account as b on a.id = b.user_id
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
64
admin-service/src/main/resources/mapper/BlogMapper.xml
Normal file
64
admin-service/src/main/resources/mapper/BlogMapper.xml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.cxx.admin.dao.BlogDao">
|
||||||
|
<select id="queryBlogByPage" resultType="com.cxx.common.dto.blog.BlogDto">
|
||||||
|
SELECT a.id AS id,
|
||||||
|
a.title AS title,
|
||||||
|
a.top_value AS topValue,
|
||||||
|
a.is_great AS isGreat,
|
||||||
|
b.NAME AS category,
|
||||||
|
a.summary AS summary,
|
||||||
|
a.word_count AS wordCount,
|
||||||
|
a.read_duration AS readDuration,
|
||||||
|
COUNT(c.id) AS visitCount,
|
||||||
|
a.create_time AS createTime,
|
||||||
|
a.update_time AS updateTime
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b ON b.id = a.category_id
|
||||||
|
LEFT JOIN blog_visit c ON c.blog_id = a.id
|
||||||
|
GROUP BY a.id
|
||||||
|
ORDER BY a.top_value DESC,
|
||||||
|
a.update_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryBlogById" resultType="com.cxx.common.dto.blog.BlogDto">
|
||||||
|
SELECT a.id AS id,
|
||||||
|
a.title AS title,
|
||||||
|
a.top_value AS topValue,
|
||||||
|
a.is_great AS isGreat,
|
||||||
|
b.NAME AS category,
|
||||||
|
a.summary AS summary,
|
||||||
|
c.content AS content,
|
||||||
|
a.word_count AS wordCount,
|
||||||
|
a.read_duration AS readDuration,
|
||||||
|
COUNT(d.id) AS visitCount,
|
||||||
|
a.create_time AS createTime,
|
||||||
|
a.update_time AS updateTime
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b ON b.id = a.category_id
|
||||||
|
LEFT JOIN blog_content c ON c.id = a.content_id
|
||||||
|
LEFT JOIN blog_visit d ON d.blog_id = a.id
|
||||||
|
WHERE a.id = #{id} LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryBlogCategory" resultType="com.cxx.common.dto.blog.BlogCategoryDto">
|
||||||
|
SELECT b.name AS name,
|
||||||
|
count(b.name) AS count
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b
|
||||||
|
ON a.category_id = b.id
|
||||||
|
GROUP BY b.name
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryBlogVisit" resultType="com.cxx.common.dto.blog.BlogVisitDto">
|
||||||
|
SELECT a.ip AS ip,
|
||||||
|
a.os AS os,
|
||||||
|
a.browser AS browser,
|
||||||
|
a.uri AS uri,
|
||||||
|
b.title AS title,
|
||||||
|
a.create_time AS visitTime
|
||||||
|
FROM blog_visit AS a
|
||||||
|
LEFT JOIN blog AS b on a.blog_id = b.id
|
||||||
|
ORDER BY a.create_time DESC
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
@@ -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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
6
blog-service/Dockerfile
Normal file
6
blog-service/Dockerfile
Normal file
@@ -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"]
|
||||||
1
blog-service/pom.xml
Normal file
1
blog-service/pom.xml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<BlogDto> queryBlogByPage(@RequestParam("currentPage") Integer currentPage,
|
||||||
|
@RequestParam("pageSize") Integer pageSize) {
|
||||||
|
return blogService.queryBlogByPage(currentPage, pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "条件查询博客")
|
||||||
|
@GetMapping("/condition")
|
||||||
|
public @JsonView(ReadView.class) List<BlogDto> 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<BlogCategoryDto> queryBlogCategory() {
|
||||||
|
return blogService.queryBlogCategory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询博客统计信息")
|
||||||
|
@GetMapping("/stats")
|
||||||
|
public BlogStatsDto queryBlogStats() {
|
||||||
|
return blogService.queryBlogStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询近期博客")
|
||||||
|
@GetMapping("/latest")
|
||||||
|
public List<BlogLatestDto> queryLatestBlog() {
|
||||||
|
return blogService.queryLatestBlog();
|
||||||
|
}
|
||||||
|
}
|
||||||
25
blog-service/src/main/java/com/cxx/blog/dao/BlogDao.java
Normal file
25
blog-service/src/main/java/com/cxx/blog/dao/BlogDao.java
Normal file
@@ -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<BlogDto> queryBlogByPage(IPage<Blog> page);
|
||||||
|
|
||||||
|
List<BlogDto> queryBlogByCondition(@Param("query") BlogQueryVo query);
|
||||||
|
|
||||||
|
BlogDto queryBlogById(@Param("id") Long id);
|
||||||
|
|
||||||
|
List<BlogCategoryDto> queryBlogCategory();
|
||||||
|
|
||||||
|
List<BlogLatestDto> queryLatestBlog();
|
||||||
|
}
|
||||||
@@ -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<BlogDto> queryBlogByPage(Integer currentPage, Integer pageSize);
|
||||||
|
|
||||||
|
List<BlogDto> queryBlogByCondition(BlogQueryVo query);
|
||||||
|
|
||||||
|
BlogDto queryBlogById(Long id);
|
||||||
|
|
||||||
|
List<BlogCategoryDto> queryBlogCategory();
|
||||||
|
|
||||||
|
BlogStatsDto queryBlogStats();
|
||||||
|
|
||||||
|
List<BlogLatestDto> queryLatestBlog();
|
||||||
|
|
||||||
|
void addBlogVisit(BlogVisit blogVisit);
|
||||||
|
}
|
||||||
@@ -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<BlogDto> queryBlogByPage(Integer currentPage, Integer pageSize) {
|
||||||
|
return blogDao.queryBlogByPage(new Page<>(currentPage, pageSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BlogDto> queryBlogByCondition(BlogQueryVo query) {
|
||||||
|
return blogDao.queryBlogByCondition(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlogDto queryBlogById(Long id) {
|
||||||
|
return blogDao.queryBlogById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BlogCategoryDto> 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<BlogLatestDto> queryLatestBlog() {
|
||||||
|
return blogDao.queryLatestBlog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addBlogVisit(BlogVisit blogVisit) {
|
||||||
|
visitMapper.insert(blogVisit);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
blog-service/src/main/java/com/cxx/blog/util/BlogUtils.java
Normal file
36
blog-service/src/main/java/com/cxx/blog/util/BlogUtils.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
blog-service/src/main/java/com/cxx/blog/util/IpUtils.java
Normal file
59
blog-service/src/main/java/com/cxx/blog/util/IpUtils.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
blog-service/src/main/resources/application-dev.yml
Normal file
11
blog-service/src/main/resources/application-dev.yml
Normal file
@@ -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:
|
||||||
13
blog-service/src/main/resources/application-docker.yml
Normal file
13
blog-service/src/main/resources/application-docker.yml
Normal file
@@ -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
|
||||||
12
blog-service/src/main/resources/application-prod.yml
Normal file
12
blog-service/src/main/resources/application-prod.yml
Normal file
@@ -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
|
||||||
20
blog-service/src/main/resources/application.yml
Normal file
20
blog-service/src/main/resources/application.yml
Normal file
@@ -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
|
||||||
120
blog-service/src/main/resources/logback-spring-drop.xml
Normal file
120
blog-service/src/main/resources/logback-spring-drop.xml
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration scan="true" scanPeriod="10 seconds">
|
||||||
|
|
||||||
|
<contextName>logback</contextName>
|
||||||
|
|
||||||
|
<property name="log.path" value="logs/blogService"/>
|
||||||
|
|
||||||
|
<!--控制台日志格式:彩色日志-->
|
||||||
|
<!-- magenta:洋红 -->
|
||||||
|
<!-- boldMagenta:粗红-->
|
||||||
|
<!-- cyan:青色 -->
|
||||||
|
<!-- white:白色 -->
|
||||||
|
<!-- magenta:洋红 -->
|
||||||
|
<property name="CONSOLE_LOG_PATTERN"
|
||||||
|
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>
|
||||||
|
|
||||||
|
<!--文件日志格式-->
|
||||||
|
<property name="FILE_LOG_PATTERN"
|
||||||
|
value="%date{yyyy-MM-dd HH:mm:ss} |%-5level |%thread |%file:%line |%logger |%msg%n"/>
|
||||||
|
|
||||||
|
<!--编码-->
|
||||||
|
<property name="ENCODING"
|
||||||
|
value="UTF-8"/>
|
||||||
|
|
||||||
|
<!--输出到控制台-->
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<!--日志级别-->
|
||||||
|
<level>DEBUG</level>
|
||||||
|
</filter>
|
||||||
|
<encoder>
|
||||||
|
<!--日志格式-->
|
||||||
|
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
|
||||||
|
<!--日志字符集-->
|
||||||
|
<charset>${ENCODING}</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!--输出到文件-->
|
||||||
|
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!--日志过滤器:此日志文件只记录INFO级别的-->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||||
|
<file>${log.path}/log_info.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>${ENCODING}</charset>
|
||||||
|
</encoder>
|
||||||
|
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 每天日志归档路径以及格式 -->
|
||||||
|
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>500MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!--日志文件保留天数-->
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!-- 日志过滤器:此日志文件只记录WARN级别的 -->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>WARN</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||||
|
<file>${log.path}/log_warn.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>${ENCODING}</charset> <!-- 此处设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!--日志文件保留天数-->
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<!-- 日志过滤器:此日志文件只记录ERROR级别的 -->
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
<!-- 正在记录的日志文件的路径及文件名 -->
|
||||||
|
<file>${log.path}/log_error.log</file>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||||
|
<charset>${ENCODING}</charset> <!-- 此处设置字符集 -->
|
||||||
|
</encoder>
|
||||||
|
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<!--日志文件保留天数-->
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
<appender-ref ref="INFO_FILE"/>
|
||||||
|
<appender-ref ref="WARN_FILE"/>
|
||||||
|
<appender-ref ref="ERROR_FILE"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
90
blog-service/src/main/resources/mapper/blogMapper.xml
Normal file
90
blog-service/src/main/resources/mapper/blogMapper.xml
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.cxx.blog.dao.BlogDao">
|
||||||
|
<select id="queryBlogByPage" resultType="com.cxx.common.dto.blog.BlogDto">
|
||||||
|
SELECT a.id AS id,
|
||||||
|
a.title AS title,
|
||||||
|
a.top_value AS topValue,
|
||||||
|
a.is_great AS isGreat,
|
||||||
|
b.NAME AS category,
|
||||||
|
a.summary AS summary,
|
||||||
|
a.word_count AS wordCount,
|
||||||
|
a.read_duration AS readDuration,
|
||||||
|
COUNT(c.id) AS visitCount,
|
||||||
|
a.create_time AS createTime,
|
||||||
|
a.update_time AS updateTime
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b ON b.id = a.category_id
|
||||||
|
LEFT JOIN blog_visit c ON c.blog_id = a.id
|
||||||
|
GROUP BY a.id
|
||||||
|
ORDER BY a.top_value DESC,
|
||||||
|
a.update_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryBlogByCondition" resultType="com.cxx.common.dto.blog.BlogDto">
|
||||||
|
SELECT a.id AS id,
|
||||||
|
a.title AS title,
|
||||||
|
a.top_value AS topValue,
|
||||||
|
a.is_great AS isGreat,
|
||||||
|
b.name AS category,
|
||||||
|
a.summary AS summary,
|
||||||
|
c.content AS content,
|
||||||
|
a.word_count AS wordCount,
|
||||||
|
a.read_duration AS readDuration,
|
||||||
|
a.create_time AS createTime,
|
||||||
|
a.update_time AS updateTime
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b on a.category_id = b.id
|
||||||
|
LEFT JOIN blog_content c on a.content_id = c.id
|
||||||
|
<where>
|
||||||
|
<if test="query.category != null and query.category != ''">
|
||||||
|
b.name = #{query.category}
|
||||||
|
</if>
|
||||||
|
<if test="query.title != null and query.title != ''">
|
||||||
|
AND a.title LIKE CONCAT('%',#{query.title},'%')
|
||||||
|
</if>
|
||||||
|
<if test="query.year != null">
|
||||||
|
AND YEAR(a.create_time) = #{query.year}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
ORDER BY a.update_time DESC
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryBlogById" resultType="com.cxx.common.dto.blog.BlogDto">
|
||||||
|
SELECT a.id AS id,
|
||||||
|
a.title AS title,
|
||||||
|
a.top_value AS topValue,
|
||||||
|
a.is_great AS isGreat,
|
||||||
|
b.NAME AS category,
|
||||||
|
a.summary AS summary,
|
||||||
|
c.content AS content,
|
||||||
|
a.word_count AS wordCount,
|
||||||
|
a.read_duration AS readDuration,
|
||||||
|
COUNT(d.id) AS visitCount,
|
||||||
|
a.create_time AS createTime,
|
||||||
|
a.update_time AS updateTime
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b ON b.id = a.category_id
|
||||||
|
LEFT JOIN blog_content c ON c.id = a.content_id
|
||||||
|
LEFT JOIN blog_visit d ON d.blog_id = a.id
|
||||||
|
WHERE a.id = #{id}
|
||||||
|
LIMIT 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryBlogCategory" resultType="com.cxx.common.dto.blog.BlogCategoryDto">
|
||||||
|
SELECT b.name AS name,
|
||||||
|
count(b.name) AS count
|
||||||
|
FROM blog a
|
||||||
|
LEFT JOIN blog_category b
|
||||||
|
ON a.category_id = b.id
|
||||||
|
GROUP BY b.name
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="queryLatestBlog" resultType="com.cxx.common.dto.blog.BlogLatestDto">
|
||||||
|
SELECT id AS id,
|
||||||
|
title AS title
|
||||||
|
FROM blog
|
||||||
|
ORDER BY update_time DESC
|
||||||
|
LIMIT 5
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
18
blog-service/src/test/java/com/cxx/blog/BlogServiceTest.java
Normal file
18
blog-service/src/test/java/com/cxx/blog/BlogServiceTest.java
Normal file
@@ -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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
38
common/.gitignore
vendored
Normal file
38
common/.gitignore
vendored
Normal file
@@ -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
|
||||||
40
common/pom.xml
Normal file
40
common/pom.xml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.cxx</groupId>
|
||||||
|
<artifactId>sweet-hut-service</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cxx</groupId>
|
||||||
|
<artifactId>starter-web</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cxx</groupId>
|
||||||
|
<artifactId>starter-jdbc</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cxx</groupId>
|
||||||
|
<artifactId>starter-logging</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
4
common/src/main/java/com/cxx/common/PlainView.java
Normal file
4
common/src/main/java/com/cxx/common/PlainView.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package com.cxx.common;
|
||||||
|
|
||||||
|
public interface PlainView {
|
||||||
|
}
|
||||||
4
common/src/main/java/com/cxx/common/ReadView.java
Normal file
4
common/src/main/java/com/cxx/common/ReadView.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package com.cxx.common;
|
||||||
|
|
||||||
|
public interface ReadView extends PlainView {
|
||||||
|
}
|
||||||
4
common/src/main/java/com/cxx/common/WriteView.java
Normal file
4
common/src/main/java/com/cxx/common/WriteView.java
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
package com.cxx.common;
|
||||||
|
|
||||||
|
public interface WriteView extends PlainView {
|
||||||
|
}
|
||||||
11
common/src/main/java/com/cxx/common/dto/StatsChartDto.java
Normal file
11
common/src/main/java/com/cxx/common/dto/StatsChartDto.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<String> imageList;
|
||||||
|
|
||||||
|
@Schema(description = "账单日期")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||||||
|
private Date date;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package com.cxx.common.dto.blog;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
62
common/src/main/java/com/cxx/common/dto/plan/PlanDto.java
Normal file
62
common/src/main/java/com/cxx/common/dto/plan/PlanDto.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
25
common/src/main/java/com/cxx/common/dto/task/TaskDto.java
Normal file
25
common/src/main/java/com/cxx/common/dto/task/TaskDto.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
17
common/src/main/java/com/cxx/common/dto/user/SessionDto.java
Normal file
17
common/src/main/java/com/cxx/common/dto/user/SessionDto.java
Normal file
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user