feat: 完善后端架构和service层实现

- 创建完整的entity实体类体系,包括所有业务实体
- 实现BaseEntity基类,统一管理公共字段
- 创建雪花算法ID生成器和自动填充处理器
- 简化所有mapper接口,只继承BaseMapper
- 重构service层,使用LambdaQueryWrapper进行数据库操作
- 创建BasePageRequest分页查询基类
- 完善用户上下文管理和JWT认证
- 新增WebSocket聊天功能和相关控制器
- 更新前端配置和组件,完善用户认证流程
- 同步数据库建表脚本
This commit is contained in:
2025-07-24 00:37:23 +08:00
parent 645036fcd2
commit 880e0e3c88
87 changed files with 8114 additions and 1106 deletions
@@ -0,0 +1,91 @@
package com.emotion.config;
import com.emotion.util.SnowflakeIdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetAddress;
import java.net.NetworkInterface;
/**
* ID生成器配置类
*
* @author emotion-museum
* @date 2025-07-23
*/
@Slf4j
@Configuration
public class IdGeneratorConfig {
/**
* 机器ID配置(可通过配置文件指定)
*/
@Value("${emotion.snowflake.machine-id:#{null}}")
private Long machineId;
/**
* 配置雪花算法ID生成器
*
* @return SnowflakeIdGenerator实例
*/
@Bean
public SnowflakeIdGenerator snowflakeIdGenerator() {
long finalMachineId;
if (machineId != null) {
// 使用配置文件中指定的机器ID
finalMachineId = machineId;
log.info("使用配置文件指定的机器ID: {}", finalMachineId);
} else {
// 自动生成机器ID
finalMachineId = generateMachineId();
log.info("自动生成机器ID: {}", finalMachineId);
}
return new SnowflakeIdGenerator(finalMachineId);
}
/**
* 自动生成机器ID
* 基于MAC地址和IP地址生成唯一的机器ID
*
* @return 机器ID (0-1023)
*/
private long generateMachineId() {
try {
// 获取本机IP地址
InetAddress localHost = InetAddress.getLocalHost();
// 获取网络接口
NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);
if (networkInterface != null) {
// 获取MAC地址
byte[] hardwareAddress = networkInterface.getHardwareAddress();
if (hardwareAddress != null && hardwareAddress.length >= 6) {
// 使用MAC地址的后两个字节生成机器ID
long machineId = ((hardwareAddress[4] & 0xFF) << 8) | (hardwareAddress[5] & 0xFF);
// 确保机器ID在有效范围内 (0-1023)
return machineId & 0x3FF;
}
}
// 如果无法获取MAC地址,使用IP地址生成
byte[] address = localHost.getAddress();
if (address.length >= 4) {
// 使用IP地址的后两个字节生成机器ID
long machineId = ((address[2] & 0xFF) << 8) | (address[3] & 0xFF);
return machineId & 0x3FF;
}
} catch (Exception e) {
log.warn("自动生成机器ID失败,使用默认策略: {}", e.getMessage());
}
// 如果所有方法都失败,使用当前时间戳生成
return System.currentTimeMillis() % 1024;
}
}
@@ -0,0 +1,28 @@
package com.emotion.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBatis-Plus配置类
*
* @author emotion-museum
* @date 2025-07-23
*/
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件配置
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
@@ -0,0 +1,57 @@
package com.emotion.config;
import com.emotion.interceptor.UserContextInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web配置类
* 配置拦截器、跨域等
*
* @author emotion-museum
* @date 2025-07-23
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserContextInterceptor userContextInterceptor;
/**
* 添加拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userContextInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(
"/error",
"/favicon.ico",
"/actuator/**",
"/swagger-ui/**",
"/swagger-resources/**",
"/v2/api-docs",
"/v3/api-docs",
"/webjars/**",
"/doc.html",
"/static/**",
"/public/**"
);
}
/**
* 跨域配置
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
@@ -0,0 +1,37 @@
package com.emotion.config;
import com.emotion.interceptor.JwtAuthInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web MVC配置
*
* @author emotion-museum
* @date 2025-07-23
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private JwtAuthInterceptor jwtAuthInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtAuthInterceptor)
.addPathPatterns("/api/**") // 拦截所有API请求
.excludePathPatterns(
"/api/auth/login", // 登录接口
"/api/auth/register", // 注册接口
"/api/auth/captcha", // 验证码接口
"/api/auth/refresh-token", // 刷新token接口
"/api/health", // 健康检查接口
"/api/ws/**", // WebSocket接口
"/swagger-ui/**", // Swagger UI
"/v3/api-docs/**", // API文档
"/actuator/**" // 监控端点
);
}
}