feat: 添加本地测试文件,用户删除功能修改

This commit is contained in:
bunny 2024-10-23 13:46:19 +08:00
parent cb4190a1d8
commit f600eea680
24 changed files with 120 additions and 224 deletions

View File

@ -488,7 +488,5 @@ IDEA中也有集成只要使用了actuator包即可看到服务内容、健康
# 展望未来
1. 数据库备份时上传到Minio
2. 数据库备份后可恢复
3. 定时邮件发送参数可在前端配置,动态形式
4. 首页看板内容
1. 定时邮件发送参数可在前端配置,动态形式
2. 首页看板内容

View File

@ -3,7 +3,6 @@ package cn.bunny.common.generator.generator;
import cn.bunny.common.generator.entity.BaseField;
import cn.bunny.common.generator.entity.BaseResultMap;
import cn.bunny.common.generator.utils.GeneratorCodeUtils;
import cn.bunny.dao.dto.log.UserLoginLogAddDto;
import cn.bunny.dao.dto.log.UserLoginLogDto;
import cn.bunny.dao.dto.log.UserLoginLogUpdateDto;
import cn.bunny.dao.entity.log.UserLoginLog;
@ -53,7 +52,7 @@ public class WebGeneratorCode {
public static void main(String[] args) throws Exception {
Class<?> originalClass = UserLoginLog.class;
Class<?> dtoClass = UserLoginLogDto.class;
Class<?> addDtoClass = UserLoginLogAddDto.class;
Class<?> addDtoClass = UserLoginLogDto.class;
Class<?> updateDtoClass = UserLoginLogUpdateDto.class;
Class<?> voClass = UserLoginLogVo.class;

View File

@ -15,11 +15,13 @@ import java.io.IOException;
@ControllerAdvice
public class ControllerStringParamTrimConfig {
/**
* 创建 String trim 编辑器
* 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为null
* 即如果为true,那么 " " 会被转换为 null,否者为 ""
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
// 创建 String trim 编辑器
// 构造方法中 boolean 参数含义为如果是空白字符串,是否转换为null
// 即如果为true,那么 " " 会被转换为 null,否者为 ""
StringTrimmerEditor propertyEditor = new StringTrimmerEditor(false);
// String 类对象注册编辑器
binder.registerCustomEditor(String.class, propertyEditor);
@ -33,7 +35,7 @@ public class ControllerStringParamTrimConfig {
.deserializerByType(String.class, new StdScalarDeserializer<String>(String.class) {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext ctx) throws IOException {
// // 去除全部空格
// 去除全部空格
// return StringUtils.trimAllWhitespace(jsonParser.getValueAsString());
// 仅去除前后空格
return jsonParser.getValueAsString().trim();

View File

@ -16,7 +16,7 @@ public class Knife4jConfig {
@Bean
public OpenAPI openAPI() {
// 作者等信息
Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://z-bunny.com");
Contact contact = new Contact().name("Bunny").email("1319900154@qq.com").url("http://z-bunny.cn");
// 使用协议
License license = new License().name("MIT").url("http://MUT.com");
// 相关信息

View File

@ -22,7 +22,8 @@ public class MybatisPlusConfig {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(600L);// ? 设置最大分页为100
// 设置最大分页为100
paginationInnerInterceptor.setMaxLimit(600L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
// 乐观锁
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

View File

@ -1,86 +0,0 @@
package cn.bunny.dao.dto.log;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Schema(name = "UserLoginLogDto对象", title = "用户登录日志分页查询", description = "用户登录日志分页查询")
public class UserLoginLogAddDto {
@Schema(name = "userId", title = "用户Id")
private Long userId;
@Schema(name = "username", title = "用户名")
private String username;
@Schema(name = "token", title = "登录token")
private String token;
@Schema(name = "ipAddress", title = "登录Ip")
private String ipAddress;
@Schema(name = "ipRegion", title = "登录Ip归属地")
private String ipRegion;
@Schema(name = "userAgent", title = "登录时代理")
private String userAgent;
@Schema(name = "type", title = "操作类型")
private String type;
@Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的")
private String xRequestedWith;
@Schema(name = "secChUa", title = "用户代理的品牌和版本")
private String secChUa;
@Schema(name = "secChUaArch", title = "用户代理的底层平台架构")
private String secChUaArch;
@Schema(name = "secChUaBitness", title = "用户代理的底层CPU架构位数")
private String secChUaBitness;
@Schema(name = "secChUaMobile", title = "用户代理是否在手机设备上运行")
private String secChUaMobile;
@Schema(name = "secChUaModel", title = "用户代理的设备模型")
private String secChUaModel;
@Schema(name = "secChUaPlatform", title = "用户代理的底层操作系统/平台")
private String secChUaPlatform;
@Schema(name = "secChUaPlatformVersion", title = "用户代理的底层操作系统版本")
private String secChUaPlatformVersion;
@Schema(name = "contentDpr", title = "客户端设备像素比")
private String contentDpr;
@Schema(name = "deviceMemory", title = "客户端RAM内存的近似值")
private String deviceMemory;
@Schema(name = "dpr", title = "客户端设备像素比")
private String dpr;
@Schema(name = "viewportWidth", title = "布局视口宽度")
private String viewportWidth;
@Schema(name = "width", title = "所需资源宽度")
private String width;
@Schema(name = "downlink", title = "客户端连接到服务器的近似带宽")
private String downlink;
@Schema(name = "ect", title = "有效连接类型")
private String ect;
@Schema(name = "rtt", title = "应用层往返时间")
private String rtt;
}

View File

@ -37,14 +37,5 @@ public class UserLoginLogDto {
@Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的")
private String xRequestedWith;
@Schema(name = "secChUa", title = "用户代理的品牌和版本")
private String secChUa;
@Schema(name = "secChUaMobile", title = "用户代理是否在手机设备上运行")
private String secChUaMobile;
@Schema(name = "secChUaPlatform", title = "用户代理的底层操作系统/平台")
private String secChUaPlatform;
}

View File

@ -37,13 +37,4 @@ public class UserLoginLogUpdateDto {
@Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的")
private String xRequestedWith;
@Schema(name = "secChUa", title = "用户代理的品牌和版本")
private String secChUa;
@Schema(name = "secChUaMobile", title = "用户代理是否在手机设备上运行")
private String secChUaMobile;
@Schema(name = "secChUaPlatform", title = "用户代理的底层操作系统/平台")
private String secChUaPlatform;
}

View File

@ -46,13 +46,4 @@ public class UserLoginLog extends BaseEntity {
@Schema(name = "xRequestedWith", title = "标识客户端是否是通过Ajax发送请求的")
private String xRequestedWith;
@Schema(name = "secChUa", title = "用户代理的品牌和版本")
private String secChUa;
@Schema(name = "secChUaMobile", title = "用户代理是否在手机设备上运行")
private String secChUaMobile;
@Schema(name = "secChUaPlatform", title = "用户代理的底层操作系统/平台")
private String secChUaPlatform;
}

View File

@ -38,13 +38,4 @@ public class UserLoginLogVo extends BaseVo {
@JsonProperty("xRequestedWith")
private String xRequestedWith;
@Schema(name = "secChUa", title = "用户代理的品牌和版本")
private String secChUa;
@Schema(name = "secChUaMobile", title = "用户代理是否在手机设备上运行")
private String secChUaMobile;
@Schema(name = "secChUaPlatform", title = "用户代理的底层操作系统/平台")
private String secChUaPlatform;
}

View File

@ -26,5 +26,9 @@ ENTRYPOINT ["java","-jar","/home/server/app.jar"]
#暴露 8000 端口
EXPOSE 8000
# 开发环境
# mvn clean package -Pprod -DskipTests
# 测试环境
# mvn clean package -Ptest -DskipTests

View File

@ -1,5 +1,6 @@
package cn.bunny.services.controller;
import cn.bunny.common.service.exception.BunnyException;
import cn.bunny.dao.dto.system.files.FileUploadDto;
import cn.bunny.dao.dto.system.files.FilesAddDto;
import cn.bunny.dao.dto.system.files.FilesDto;
@ -18,6 +19,7 @@ import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@ -85,9 +87,10 @@ public class FilesController {
}
@Operation(summary = "根据文件名访问resource下文件", description = "根据文件名访问resource下文件")
@GetMapping("noManage/getResourceByFilename/{filename}")
@GetMapping("noManage/resourceFiles/{filename}")
public ResponseEntity<Resource> getResourceByFilename(@PathVariable String filename) {
Resource file = filesService.getResourceByFilename(filename);
Resource file = new ClassPathResource("static/" + filename);
if (!file.exists()) throw new BunnyException(ResultCodeEnum.FILE_NOT_EXIST);
return ResponseEntity.ok().body(file);
}

View File

@ -140,7 +140,7 @@ public class UserController {
return Result.success(ResultCodeEnum.LOGOUT_SUCCESS);
}
@Operation(summary = "删除用户信息", description = "删除用户信息")
@Operation(summary = "删除用户", description = "删除用户")
@DeleteMapping("deleteAdminUser")
public Mono<Result<String>> deleteAdminUser(@RequestBody List<Long> ids) {
userService.deleteAdminUser(ids);

View File

@ -191,18 +191,6 @@ public class UserFactory {
String xRequestedWith = request.getHeader("X-Requested-With");
userLoginLog.setXRequestedWith(xRequestedWith);
// 获取Sec-CH-UA
String secCHUA = request.getHeader("sec-ch-ua");
userLoginLog.setSecChUa(secCHUA);
// 获取Sec-CH-UA-Mobile
String secCHUAMobile = request.getHeader("Sec-CH-UA-Mobile");
userLoginLog.setSecChUaMobile(secCHUAMobile);
// 获取Sec-CH-UA-Platform
String secCHUAPlatform = request.getHeader("Sec-CH-UA-Platform");
userLoginLog.setSecChUaPlatform(secCHUAPlatform);
return userLoginLog;
}
}

View File

@ -1,6 +1,5 @@
package cn.bunny.services.quartz;
import cn.bunny.services.aop.annotation.QuartzSchedulers;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
@ -19,7 +18,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j
@QuartzSchedulers(type = "backup", description = "数据库备份任务")
// @QuartzSchedulers(type = "backup", description = "数据库备份(仅限本地docker中MySQL)")
@Component
public class DatabaseBackupJob implements Job {

View File

@ -11,7 +11,6 @@ import cn.bunny.dao.vo.system.files.FilesVo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import jakarta.validation.Valid;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import java.util.List;
@ -85,12 +84,4 @@ public interface FilesService extends IService<Files> {
* @return 媒体文件类型列表
*/
Set<String> getAllMediaTypes();
/**
* * 根据文件名访问resource下文件
*
* @param filename 文件名
* @return Resource
*/
Resource getResourceByFilename(String filename);
}

View File

@ -24,8 +24,6 @@ import jakarta.validation.Valid;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@ -259,17 +257,4 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
return Set.of();
}
}
/**
* * 根据文件名访问resource下文件
*
* @param filename 文件名
* @return Resource
*/
@Override
public Resource getResourceByFilename(String filename) {
Resource file = new ClassPathResource("static/" + filename);
if (!file.exists()) throw new BunnyException(ResultCodeEnum.FILE_NOT_EXIST);
return file;
}
}

View File

@ -52,7 +52,11 @@ public class UserLoginLogServiceImpl extends ServiceImpl<UserLoginLogMapper, Use
*/
@Override
public void deleteUserLoginLog(List<Long> ids) {
baseMapper.deleteBatchIdsWithPhysics(ids);
// 逻辑删除
baseMapper.deleteBatchIds(ids);
// 物理删除
// baseMapper.deleteBatchIdsWithPhysics(ids);
}
/**

View File

@ -483,8 +483,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
// 判断数据请求是否为空
if (ids.isEmpty()) throw new BunnyException(ResultCodeEnum.REQUEST_IS_EMPTY);
// 删除用户
baseMapper.deleteBatchIdsWithPhysics(ids);
// 逻辑删除
baseMapper.deleteBatchIds(ids);
// 物理删除用户
// baseMapper.deleteBatchIdsWithPhysics(ids);
// 删除部门相关
userDeptMapper.deleteBatchIdsByUserIdWithPhysics(ids);

View File

@ -17,27 +17,6 @@ mybatis-plus:
global-config:
db-config:
logic-delete-field: isDeleted
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
# rabbitmq:
# host: ${bunny.rabbitmq.host}
# port: ${bunny.rabbitmq.port}
# username: ${bunny.rabbitmq.username}
# password: ${bunny.rabbitmq.password}
# virtual-host: ${bunny.rabbitmq.virtual-host}
# publisher-confirm-type: correlated # 交换机确认
# publisher-returns: true # 队列确认
# listener:
# simple:
# acknowledge-mode: manual # 手动处理消息
# connection-timeout: 1s # 设置MQ连接超时时间
# template:
# retry:
# enabled: true # 失败重试
# initial-interval: 1000ms # 失败后初始时间
# multiplier: 1 # 失败后下次等待时长倍数 initial-interval * multiplier
# max-attempts: 3 # 最大重试次数
bunny:
master:

View File

@ -27,8 +27,6 @@ bunny:
master:
host: 106.15.251.123
port: 3306
# host: 192.168.3.98
# port: 3304
database: auth_admin
username: root
password: "02120212"

View File

@ -0,0 +1,68 @@
server:
port: 8000
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
global-config:
db-config:
logic-delete-field: isDeleted
logging:
level:
cn.bunny.service.mapper: warn
cn.bunny.service.controller: warn
cn.bunny.service.service: warn
root: warn
pattern:
dateformat: HH:mm:ss:SSS
file:
path: "logs/${spring.application.name}"
# 线上禁用文档
knife4j:
enable: true
production: true
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
# rabbitmq:
# host: ${bunny.rabbitmq.host}
# port: ${bunny.rabbitmq.port}
# username: ${bunny.rabbitmq.username}
# password: ${bunny.rabbitmq.password}
# virtual-host: ${bunny.rabbitmq.virtual-host}
# publisher-confirm-type: correlated # 交换机确认
# publisher-returns: true # 队列确认
# listener:
# simple:
# acknowledge-mode: manual # 手动处理消息
# connection-timeout: 1s # 设置MQ连接超时时间
# template:
# retry:
# enabled: true # 失败重试
# initial-interval: 1000ms # 失败后初始时间
# multiplier: 1 # 失败后下次等待时长倍数 initial-interval * multiplier
# max-attempts: 3 # 最大重试次数
bunny:
master:
host: 192.168.3.98
port: 3304
database: auth_admin
username: root
password: "02120212"
redis:
host: 192.168.3.98
port: 6379
database: 0
password: "123456"
minio:
endpointUrl: "http://192.168.3.98:9000"
accessKey: bunny
secretKey: "02120212"
bucket-name: auth-admin
bashPath: "/home/server"

View File

@ -18,14 +18,11 @@
<id column="user_agent" property="userAgent"/>
<id column="type" property="type"/>
<id column="x_requested_with" property="xRequestedWith"/>
<id column="sec_ch_ua" property="secChUa"/>
<id column="sec_ch_ua_mobile" property="secChUaMobile"/>
<id column="sec_ch_ua_platform" property="secChUaPlatform"/>
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, create_time, update_time, create_user, update_user, is_deleted, user_id, username, token, ip_address, ip_region, user_agent, type, x_requested_with, sec_ch_ua, sec_ch_ua_mobile, sec_ch_ua_platform
id, create_time, update_time, create_user, update_user, is_deleted, user_id, username, token, ip_address, ip_region, user_agent, type, x_requested_with
</sql>
<!-- 分页查询用户登录日志内容 -->
@ -34,39 +31,21 @@
<include refid="Base_Column_List"/>
from log_user_login
<where>
<if test="dto.userId != null and dto.userId != ''">
and user_id like CONCAT('%',#{dto.userId},'%')
</if>
<if test="dto.username != null and dto.username != ''">
and username like CONCAT('%',#{dto.username},'%')
</if>
<if test="dto.token != null and dto.token != ''">
and token like CONCAT('%',#{dto.token},'%')
</if>
<if test="dto.ipAddress != null and dto.ipAddress != ''">
and ip_address like CONCAT('%',#{dto.ipAddress},'%')
</if>
<if test="dto.ipRegion != null and dto.ipRegion != ''">
and ip_region like CONCAT('%',#{dto.ipRegion},'%')
</if>
<if test="dto.userAgent != null and dto.userAgent != ''">
and user_agent like CONCAT('%',#{dto.userAgent},'%')
</if>
<if test="dto.type != null and dto.type != ''">
and type like CONCAT('%',#{dto.type},'%')
</if>
<if test="dto.xRequestedWith != null and dto.xRequestedWith != ''">
and x_requested_with like CONCAT('%',#{dto.xRequestedWith},'%')
</if>
<if test="dto.secChUa != null and dto.secChUa != ''">
and sec_ch_ua like CONCAT('%',#{dto.secChUa},'%')
</if>
<if test="dto.secChUaMobile != null and dto.secChUaMobile != ''">
and sec_ch_ua_mobile like CONCAT('%',#{dto.secChUaMobile},'%')
</if>
<if test="dto.secChUaPlatform != null and dto.secChUaPlatform != ''">
and sec_ch_ua_platform like CONCAT('%',#{dto.secChUaPlatform},'%')
</if>
</where>
</select>

View File

@ -1,12 +1,15 @@
package cn.bunny.service;
import lombok.SneakyThrows;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
public class FilesTest {
@ -30,4 +33,18 @@ public class FilesTest {
Files.write(Path.of("H:/资料" + "/backup.sh"), bytes);
inputStream.close();
}
@Test
void test3() throws IOException {
String string = Files.readString(Path.of("E:\\data.js"));
System.out.println(string);
}
@Test
void test4() throws IOException {
File file = FileUtils.listFiles(new File("E:\\资料\\其她\\分析日记\\2024\\10月"), null, true).stream()
.max(Comparator.comparing(File::lastModified))
.orElse(new File(""));
System.out.println(file.getPath());
}
}