diff --git a/java-backend/.gitignore b/java-backend/.gitignore deleted file mode 100644 index 63c5eb2..0000000 --- a/java-backend/.gitignore +++ /dev/null @@ -1,44 +0,0 @@ -# Maven -target/ -*.class -*.log -.mvn/ -mvnw* -pom.xml.tag -pom.xml.releaseBackup -pom.xml.versionsBackup -pom.xml.next -release.properties -dependency-reduced-pom.xml -buildNumber.properties -.mvn/timing.properties - -# IDE -.idea/ -*.iml -*.ipr -*.iws -.project -.classpath -.settings/ -.vscode/ - -# OS -.DS_Store -Thumbs.db - -# 配置文件(敏感信息) -src/main/resources/application-local.yml -src/main/resources/application-prod.yml.local - -# 日志 -logs/ -*.log - -# 临时文件 -tmp/ -temp/ -*.tmp -*.bak -*.swp -*~ diff --git a/java-backend/README.md b/java-backend/README.md deleted file mode 100644 index fa24612..0000000 --- a/java-backend/README.md +++ /dev/null @@ -1,177 +0,0 @@ -# Creation Java Backend - -Spring Boot 后端基础框架 - -## 技术栈 - -| 组件 | 技术 | 版本 | -|:------|:------|:------| -| 框架 | Spring Boot | 3.2.4 | -| 持久层 | MyBatis-Plus | 3.5.5 | -| 数据库 | MySQL 8.0 | 8.0.33 | -| 迁移 | Flyway | 10.10.0 | -| 认证 | Spring Security + JWT | 0.12.3 | -| 缓存 | Redis | - | -| 连接池 | Alibaba Druid | 1.2.20 | -| 对象映射 | MapStruct | 1.5.5.Final | -| API 文档 | Knife4j | 4.4.0 | -| 日志 | Logback | - | -| JSON | FastJSON2 | 2.0.43 | -| 工具类 | Hutool | 5.8.26 | - -## 快速开始 - -### 环境要求 -- Java 17+ -- Maven 3.8+ -- MySQL 8.0+ -- Redis 6.0+ - -### 配置数据库 - -1. 创建数据库 -```sql -CREATE DATABASE creation_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -``` - -2. 修改 `src/main/resources/application-dev.yml` 中的数据库连接信息 - -### 启动应用 - -```bash -cd java-backend -mvn spring-boot:run -Dspring-boot.run.profiles=dev -``` - -启动成功后访问: -- 应用地址:http://localhost:8580 -- API 文档:http://localhost:8580/swagger-ui.html - -## 项目结构 - -``` -java-backend/ -├── src/main/java/com/lesingle/creation/ -│ ├── CreationApplication.java # 启动类 -│ ├── common/ # 公共模块 -│ │ ├── config/ # 配置类 -│ │ │ ├── MybatisPlusConfig.java -│ │ │ ├── SecurityConfig.java -│ │ │ └── JwtProperties.java -│ │ ├── constant/ # 常量定义 -│ │ │ └── ErrorCode.java -│ │ ├── core/ # 核心类 -│ │ │ └── Result.java -│ │ ├── exception/ # 异常处理 -│ │ │ ├── BusinessException.java -│ │ │ └── GlobalExceptionHandler.java -│ │ ├── filter/ # 过滤器 -│ │ │ └── JwtAuthenticationFilter.java -│ │ └── util/ # 工具类 -│ │ └── JwtTokenUtil.java -│ ├── controller/ # 控制器 -│ ├── service/ # 服务层 -│ ├── mapper/ # Mapper 接口 -│ ├── entity/ # 实体类 -│ ├── dto/ # 数据传输对象 -│ └── vo/ # 视图对象 -├── src/main/resources/ -│ ├── application.yml # 主配置 -│ ├── application-dev.yml # 开发环境 -│ ├── application-test.yml # 测试环境 -│ ├── application-prod.yml # 生产环境 -│ ├── db/migration/ # Flyway 迁移脚本 -│ │ └── V1.0__init_schema.sql -│ └── logback-spring.xml # 日志配置 -└── pom.xml # Maven 配置 -``` - -## 默认账户 - -Flyway 初始迁移后会自动创建以下账户: - -| 用户名 | 密码 | 角色 | -|:------|:------|:------| -| admin | admin123 | 超级管理员 | - -## 开发规范 - -### 三层架构 - -| 层级 | 职责 | 数据流 | -|:------|:------|:------| -| **Controller** | 接收请求、参数校验 | DTO ↔ VO | -| **Service** | 业务逻辑、事务控制 | 使用 Entity | -| **Mapper** | 数据库 CRUD | 使用 Entity | - -### 代码规范 - -- Java 17 严格模式 -- 注释和日志使用中文 -- 使用 Lombok 简化代码 -- 使用 MapStruct 进行对象映射 - -### 日志规范 - -- 所有日志使用中文 -- 使用 MDC 实现 TraceId 链路追踪 -- 开发环境:DEBUG 级别 -- 生产环境:INFO/WARN 级别 - -## 常用命令 - -```bash -# 编译 -mvn clean compile - -# 打包 -mvn clean package - -# 运行(开发环境) -mvn spring-boot:run -Dspring-boot.run.profiles=dev - -# 运行(测试环境) -mvn spring-boot:run -Dspring-boot.run.profiles=test - -# 运行(生产环境) -mvn spring-boot:run -Dspring-boot.run.profiles=prod - -# 跳过测试打包 -mvn clean package -DskipTests - -# 查看依赖 -mvn dependency:tree -``` - -## API 接口 - -### 认证相关 -- `POST /api/auth/login` - 用户登录 -- `POST /api/auth/logout` - 用户登出 -- `POST /api/auth/register` - 用户注册 -- `POST /api/auth/refresh` - 刷新 Token - -### 用户相关 -- `GET /api/users` - 用户列表 -- `GET /api/users/{id}` - 获取用户详情 -- `POST /api/users` - 创建用户 -- `PUT /api/users/{id}` - 更新用户 -- `DELETE /api/users/{id}` - 删除用户 - -## 环境变量(生产环境) - -生产环境部署时需设置以下环境变量: - -| 变量名 | 说明 | 示例 | -|:------|:------|:------| -| `DATABASE_URL` | 数据库连接 URL | `jdbc:mysql://host:3306/db` | -| `DB_USERNAME` | 数据库用户名 | `root` | -| `DB_PASSWORD` | 数据库密码 | `password` | -| `REDIS_HOST` | Redis 主机 | `localhost` | -| `REDIS_PORT` | Redis 端口 | `6379` | -| `REDIS_PASSWORD` | Redis 密码 | `password` | -| `JWT_SECRET` | JWT 密钥 | `your-secret-key` | - -## License - -MIT diff --git a/java-backend/lombok.config b/java-backend/lombok.config deleted file mode 100644 index 7a21e88..0000000 --- a/java-backend/lombok.config +++ /dev/null @@ -1 +0,0 @@ -lombok.addLombokGeneratedAnnotation = true diff --git a/java-backend/pom.xml b/java-backend/pom.xml deleted file mode 100644 index 142a960..0000000 --- a/java-backend/pom.xml +++ /dev/null @@ -1,241 +0,0 @@ - - - 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 3.2.4 - - - - com.lesingle.creation - creation - 1.0.0-SNAPSHOT - creation - Lesingle Creation - Spring Boot 后端服务 - - - 17 - 3.5.5 - 1.2.20 - 8.0.33 - 1.5.5.Final - 1.18.34 - 5.8.26 - 2.0.43 - 0.12.3 - 10.10.0 - 3.17.2 - 17 - 17 - - - - - - aliyun - Aliyun Maven - https://maven.aliyun.com/repository/public - - - - - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-security - - - - org.springframework.boot - spring-boot-starter-data-redis - - - - org.springframework.boot - spring-boot-starter-validation - - - - org.springframework.boot - spring-boot-starter-aop - - - - org.springframework.boot - spring-boot-configuration-processor - true - - - - - com.baomidou - mybatis-plus-spring-boot3-starter - ${mybatis-plus.version} - - - - - com.mysql - mysql-connector-j - ${mysql.version} - - - - - com.alibaba - druid-spring-boot-3-starter - ${druid.version} - - - - - org.flywaydb - flyway-core - ${flyway.version} - - - - - org.flywaydb - flyway-mysql - ${flyway.version} - - - - - org.springdoc - springdoc-openapi-starter-webmvc-ui - 2.3.0 - - - - - org.mapstruct - mapstruct - ${mapstruct.version} - - - - org.mapstruct - mapstruct-processor - ${mapstruct.version} - - - - - org.projectlombok - lombok - ${lombok.version} - true - - - - - cn.hutool - hutool-all - ${hutool.version} - - - - - com.aliyun.oss - aliyun-sdk-oss - ${aliyun.oss.version} - - - - - com.alibaba.fastjson2 - fastjson2 - ${fastjson2.version} - - - - - io.jsonwebtoken - jjwt-api - ${jjwt.version} - - - - io.jsonwebtoken - jjwt-impl - ${jjwt.version} - runtime - - - - io.jsonwebtoken - jjwt-jackson - ${jjwt.version} - runtime - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.security - spring-security-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - org.projectlombok - lombok - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - 17 - 17 - UTF-8 - - - org.projectlombok - lombok - ${lombok.version} - - - org.projectlombok - lombok-mapstruct-binding - 0.2.0 - - - org.mapstruct - mapstruct-processor - ${mapstruct.version} - - - - - - - - diff --git a/java-backend/src/main/java/com/lesingle/creation/CreationApplication.java b/java-backend/src/main/java/com/lesingle/creation/CreationApplication.java deleted file mode 100644 index 35f3e89..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/CreationApplication.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lesingle.creation; - -import org.mybatis.spring.annotation.MapperScan; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -/** - * Spring Boot 启动类 - * - * @author lesingle - * @since 1.0.0 - */ -@SpringBootApplication -@MapperScan("com.lesingle.creation.mapper") -public class CreationApplication { - - public static void main(String[] args) { - SpringApplication.run(CreationApplication.class, args); - System.out.println("============================================"); - System.out.println(" Creation 应用启动成功!"); - System.out.println(" 端口:8580"); - System.out.println(" API 文档:http://localhost:8580/doc.html"); - System.out.println("============================================"); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/annotation/RateLimiter.java b/java-backend/src/main/java/com/lesingle/creation/common/annotation/RateLimiter.java deleted file mode 100644 index 5a062b4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/annotation/RateLimiter.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.lesingle.creation.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 限流注解 - *

- * 基于 Redis 滑动窗口实现限流 - * - * @author lesingle - * @since 1.0.0 - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RateLimiter { - - /** - * 限流 Key - * 支持 SpEL 表达式,如 "#username" - */ - String key() default ""; - - /** - * 限流时间窗口(秒) - * 默认 60 秒 - */ - int time() default 60; - - /** - * 时间窗口内最大请求数 - * 默认 100 次 - */ - int count() default 100; - - /** - * 提示信息 - */ - String message() default "请求过于频繁,请稍后再试"; - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/aspect/LogAspect.java b/java-backend/src/main/java/com/lesingle/creation/common/aspect/LogAspect.java deleted file mode 100644 index 1b93a46..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/aspect/LogAspect.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.lesingle.creation.common.aspect; - -import com.lesingle.creation.common.util.TraceIdUtil; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import jakarta.servlet.http.HttpServletRequest; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * 日志切面 - *

- * 拦截 Controller 层所有方法,记录请求日志 - * 包含:TraceId、请求方法、请求路径、IP、耗时 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Aspect -@Component -public class LogAspect { - - /** - * 定义切点:拦截 Controller 层所有方法 - */ - @Pointcut("execution(* com.lesingle.creation.controller..*.*(..))") - public void controllerPointcut() { - } - - /** - * 环绕通知:记录请求耗时 - */ - @Around("controllerPointcut()") - public Object around(ProceedingJoinPoint joinPoint) throws Throwable { - ServletRequestAttributes attributes = - (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attributes == null) { - return joinPoint.proceed(); - } - - HttpServletRequest request = attributes.getRequest(); - String traceId = TraceIdUtil.getTraceId(); - String method = request.getMethod(); - String uri = request.getRequestURI(); - String ip = getIpAddress(request); - - long startTime = System.currentTimeMillis(); - log.info("【{}】请求开始 | 方法:{} | 路径:{} | IP:{}", traceId, method, uri, ip); - - Object result; - try { - result = joinPoint.proceed(); - long endTime = System.currentTimeMillis(); - log.info("【{}】请求成功 | 方法:{} | 路径:{} | 耗时:{}ms", - traceId, method, uri, (endTime - startTime)); - } catch (Throwable e) { - long endTime = System.currentTimeMillis(); - log.error("【{}】请求异常 | 方法:{} | 路径:{} | 耗时:{}ms | 异常:{}", - traceId, method, uri, (endTime - startTime), e.getMessage(), e); - throw e; - } - - return result; - } - - /** - * 获取请求 IP 地址 - */ - private String getIpAddress(HttpServletRequest request) { - 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("WL-Proxy-Client-IP"); - } - if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { - ip = request.getRemoteAddr(); - // 如果是本地 IPv6,转换为 IPv4 - if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { - try { - ip = InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException e) { - log.error("获取 IP 地址失败:{}", e.getMessage()); - } - } - } - // 多个代理时,取第一个 IP - if (ip != null && ip.contains(",")) { - ip = ip.split(",")[0].trim(); - } - return ip; - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/aspect/RateLimiterAspect.java b/java-backend/src/main/java/com/lesingle/creation/common/aspect/RateLimiterAspect.java deleted file mode 100644 index d1012c3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/aspect/RateLimiterAspect.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.lesingle.creation.common.aspect; - -import com.lesingle.creation.common.annotation.RateLimiter; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.common.util.RateLimiterUtil; -import com.lesingle.creation.common.util.TraceIdUtil; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Before; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.expression.Expression; -import org.springframework.expression.ExpressionParser; -import org.springframework.expression.spel.standard.SpelExpressionParser; -import org.springframework.expression.spel.support.StandardEvaluationContext; -import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import jakarta.servlet.http.HttpServletRequest; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.UnknownHostException; - -/** - * 限流切面 - *

- * 拦截标注了 @RateLimiter 注解的方法,实现限流控制 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Aspect -@Component -public class RateLimiterAspect { - - private static final ExpressionParser PARSER = new SpelExpressionParser(); - - /** - * 前置通知:执行限流检查 - */ - @Before("@annotation(rateLimiter)") - public void before(JoinPoint joinPoint, RateLimiter rateLimiter) { - // 获取注解参数 - String keyExpression = rateLimiter.key(); - int time = rateLimiter.time(); - int count = rateLimiter.count(); - String message = rateLimiter.message(); - - // 解析 Key - String key = parseKey(keyExpression, joinPoint); - - // 执行限流检查 - boolean allowed = RateLimiterUtil.tryAcquire(key, time, count); - if (!allowed) { - String traceId = TraceIdUtil.getTraceId(); - log.warn("【{}】请求被限流 | Key: {} | 限制:{}/{}s", traceId, key, count, time); - throw new BusinessException(message); - } - - log.debug("限流检查通过 | Key: {} | 当前计数:{}", key, RateLimiterUtil.getCurrentCount(key)); - } - - /** - * 解析限流 Key - * 支持 SpEL 表达式 - */ - private String parseKey(String keyExpression, JoinPoint joinPoint) { - if (keyExpression.isEmpty()) { - // 默认使用 IP 地址作为 key - return "rate_limit:" + getIpAddress(); - } - - // 解析 SpEL 表达式 - MethodSignature signature = (MethodSignature) joinPoint.getSignature(); - Method method = signature.getMethod(); - Object[] args = joinPoint.getArgs(); - String[] paramNames = signature.getParameterNames(); - - StandardEvaluationContext context = new StandardEvaluationContext(); - for (int i = 0; i < args.length; i++) { - context.setVariable(paramNames[i], args[i]); - } - - try { - Expression expression = PARSER.parseExpression(keyExpression); - Object value = expression.getValue(context); - return "rate_limit:" + (value != null ? value.toString() : "unknown"); - } catch (Exception e) { - log.error("解析限流 Key 失败:{}", keyExpression, e); - return "rate_limit:error"; - } - } - - /** - * 获取请求 IP 地址 - */ - private String getIpAddress() { - try { - ServletRequestAttributes attributes = - (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attributes != null) { - HttpServletRequest request = attributes.getRequest(); - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { - ip = request.getRemoteAddr(); - } - if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { - ip = InetAddress.getLocalHost().getHostAddress(); - } - return ip; - } - } catch (UnknownHostException e) { - log.error("获取 IP 地址失败:{}", e.getMessage()); - } - return "unknown"; - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/aspect/TraceIdAspect.java b/java-backend/src/main/java/com/lesingle/creation/common/aspect/TraceIdAspect.java deleted file mode 100644 index 0f6b269..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/aspect/TraceIdAspect.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.common.aspect; - -import com.lesingle.creation.common.util.TraceIdUtil; -import lombok.extern.slf4j.Slf4j; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.springframework.stereotype.Component; - -/** - * TraceId 日志链路追踪切面 - *

- * 在 Controller 层拦截请求,生成 TraceId 并放入 MDC,实现全链路日志追踪 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Aspect -@Component -public class TraceIdAspect { - - /** - * 环绕通知,拦截 Controller 层所有方法 - */ - @Around("execution(* com.lesingle.creation.controller..*.*(..))") - public Object around(ProceedingJoinPoint joinPoint) throws Throwable { - long startTime = System.currentTimeMillis(); - - try { - // 生成 TraceId 并放入 MDC - TraceIdUtil.setTraceId(); - - log.debug("请求开始,TraceId: {}", TraceIdUtil.getTraceId()); - - // 执行目标方法 - Object result = joinPoint.proceed(); - - long costTime = System.currentTimeMillis() - startTime; - log.debug("请求结束,TraceId: {}, 耗时:{}ms", TraceIdUtil.getTraceId(), costTime); - - return result; - } finally { - // 清除 MDC,防止内存泄漏 - TraceIdUtil.clear(); - } - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/base/BaseEntity.java b/java-backend/src/main/java/com/lesingle/creation/common/base/BaseEntity.java deleted file mode 100644 index d663856..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/base/BaseEntity.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.lesingle.creation.common.base; - -import com.baomidou.mybatisplus.annotation.*; -import lombok.Data; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 实体基类 - *

- * 包含基础字段:id、createBy、createTime、updateBy、updateTime、deleted - * 所有实体类应继承此类 - * - * @author lesingle - * @since 1.0.0 - */ -@Data -public abstract class BaseEntity implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * 主键 ID - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 创建人账号 - */ - @TableField(fill = FieldFill.INSERT) - private String createBy; - - /** - * 创建时间 - */ - @TableField(fill = FieldFill.INSERT) - private LocalDateTime createTime; - - /** - * 更新人账号 - */ - @TableField(fill = FieldFill.INSERT_UPDATE) - private String updateBy; - - /** - * 更新时间 - */ - @TableField(fill = FieldFill.INSERT_UPDATE) - private LocalDateTime updateTime; - - /** - * 逻辑删除标识(0-未删除,1-已删除) - */ - @TableLogic - private Integer deleted; - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/config/JwtProperties.java b/java-backend/src/main/java/com/lesingle/creation/common/config/JwtProperties.java deleted file mode 100644 index 93ec7b6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/config/JwtProperties.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.lesingle.creation.common.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * JWT 配置属性 - * - * @author lesingle - * @since 1.0.0 - */ -@Data -@Component -@ConfigurationProperties(prefix = "jwt") -public class JwtProperties { - - /** - * JWT 密钥 - */ - private String secret; - - /** - * Token 过期时间(毫秒) - */ - private Long expiration; - - /** - * Token 前缀 - */ - private String tokenPrefix; - - /** - * Token 请求头名称 - */ - private String header; - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/config/MybatisPlusConfig.java b/java-backend/src/main/java/com/lesingle/creation/common/config/MybatisPlusConfig.java deleted file mode 100644 index 3e7e1a3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/config/MybatisPlusConfig.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.lesingle.creation.common.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 lesingle - * @since 1.0.0 - */ -@Configuration -public class MybatisPlusConfig { - - /** - * 分页插件配置 - */ - @Bean - public MybatisPlusInterceptor mybatisPlusInterceptor() { - MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); - // 添加分页插件 - interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); - return interceptor; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/config/OssProperties.java b/java-backend/src/main/java/com/lesingle/creation/common/config/OssProperties.java deleted file mode 100644 index 2802405..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/config/OssProperties.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.common.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 阿里云 OSS 配置属性 - * - * @author lesingle - * @since 1.0.0 - */ -@Data -@Component -@ConfigurationProperties(prefix = "aliyun.oss") -public class OssProperties { - - /** - * OSS Endpoint - * 如:oss-cn-hangzhou.aliyuncs.com - */ - private String endpoint; - - /** - * Access Key ID - */ - private String accessKeyId; - - /** - * Access Key Secret - */ - private String accessKeySecret; - - /** - * Bucket 名称 - */ - private String bucketName; - - /** - * 自定义域名(可选) - * 如:https://cdn.example.com - */ - private String customDomain; - - /** - * 文件上传根目录 - * 如:uploads/ - */ - private String rootDir = ""; - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/config/RedisConfig.java b/java-backend/src/main/java/com/lesingle/creation/common/config/RedisConfig.java deleted file mode 100644 index 365a771..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/config/RedisConfig.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.lesingle.creation.common.config; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.PropertyAccessor; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; -import org.springframework.cache.CacheManager; -import org.springframework.cache.annotation.EnableCaching; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.cache.RedisCacheConfiguration; -import org.springframework.data.redis.cache.RedisCacheManager; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; -import org.springframework.data.redis.serializer.RedisSerializationContext; -import org.springframework.data.redis.serializer.StringRedisSerializer; - -import java.time.Duration; - -/** - * Redis 配置类 - *

- * 配置 RedisTemplate 和 CacheManager - * - * @author lesingle - * @since 1.0.0 - */ -@Configuration -@EnableCaching -public class RedisConfig { - - /** - * 配置 RedisTemplate - */ - @Bean - public RedisTemplate redisTemplate(RedisConnectionFactory factory) { - RedisTemplate template = new RedisTemplate<>(); - template.setConnectionFactory(factory); - - // 配置 JSON 序列化器 - Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); - ObjectMapper om = new ObjectMapper(); - om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); - om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); - jackson2JsonRedisSerializer.setObjectMapper(om); - - // String 序列化器 - StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); - - // Key 采用 String 序列化 - template.setKeySerializer(stringRedisSerializer); - template.setHashKeySerializer(stringRedisSerializer); - - // Value 采用 JSON 序列化 - template.setValueSerializer(jackson2JsonRedisSerializer); - template.setHashValueSerializer(jackson2JsonRedisSerializer); - - template.afterPropertiesSet(); - return template; - } - - /** - * 配置缓存管理器 - */ - @Bean - public CacheManager cacheManager(RedisConnectionFactory factory) { - // JSON 序列化器 - Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class); - ObjectMapper om = new ObjectMapper(); - om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); - om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); - jackson2JsonRedisSerializer.setObjectMapper(om); - - // 缓存配置 - RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() - // 缓存过期时间:默认 30 分钟 - .entryTtl(Duration.ofMinutes(30)) - // Key 前缀 - .prefixCacheNameWith("lesingle:") - // 禁用空值缓存 - .disableCachingNullValues() - // 序列化配置 - .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer())) - .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer)); - - return RedisCacheManager.builder(factory) - .cacheDefaults(config) - .build(); - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/config/SecurityConfig.java b/java-backend/src/main/java/com/lesingle/creation/common/config/SecurityConfig.java deleted file mode 100644 index b2f3684..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/config/SecurityConfig.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.lesingle.creation.common.config; - -import com.lesingle.creation.common.filter.JwtAuthenticationFilter; -import lombok.RequiredArgsConstructor; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; -import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.CorsConfigurationSource; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; - -import java.util.Arrays; -import java.util.List; - -/** - * Spring Security 配置类 - * - * @author lesingle - * @since 1.0.0 - */ -@Configuration -@EnableWebSecurity -@EnableMethodSecurity -public class SecurityConfig { - - private final JwtAuthenticationFilter jwtAuthenticationFilter; - - public SecurityConfig(@org.springframework.context.annotation.Lazy JwtAuthenticationFilter jwtAuthenticationFilter) { - this.jwtAuthenticationFilter = jwtAuthenticationFilter; - } - - /** - * 密码编码器 - */ - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - /** - * 认证管理器 - */ - @Bean - public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { - return config.getAuthenticationManager(); - } - - /** - * 安全过滤链配置 - */ - @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http - // 关闭 CSRF - .csrf(AbstractHttpConfigurer::disable) - // 关闭表单登录 - .formLogin(AbstractHttpConfigurer::disable) - // 关闭 HTTP Basic - .httpBasic(AbstractHttpConfigurer::disable) - // 关闭会话管理(使用 JWT) - .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - // 配置授权规则 - .authorizeHttpRequests(auth -> auth - // 放行静态资源 - .requestMatchers("/favicon.ico", "/error").permitAll() - // 放行 API 文档 - .requestMatchers("/doc.html", "/swagger-ui/**", "/v3/api-docs/**", "/swagger-resources/**").permitAll() - // 放行登录、注册接口(支持 Vite 代理后/auth/** 和直接访问/api/auth/**) - .requestMatchers("/auth/**", "/api/auth/**").permitAll() - // 放行菜单接口(支持 Vite 代理后/menu/** 和直接访问/api/menu/**) - .requestMatchers("/menu/**", "/api/menu/**").permitAll() - // 放行公开用户接口(支持 Vite 代理后/public/** 和直接访问/api/public/**) - .requestMatchers("/public/**", "/api/public/**").permitAll() - // 其他请求需要认证 - .anyRequest().authenticated() - ) - // 配置跨域 - .cors(cors -> cors.configurationSource(corsConfigurationSource())) - // 添加 JWT 过滤器(在 BasicAuthenticationFilter 之前) - .addFilterBefore(jwtAuthenticationFilter, BasicAuthenticationFilter.class); - - return http.build(); - } - - /** - * 跨域配置 - */ - @Bean - public CorsConfigurationSource corsConfigurationSource() { - CorsConfiguration config = new CorsConfiguration(); - // 允许所有来源 - config.setAllowedOriginPatterns(List.of("*")); - // 允许的请求方法 - config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); - // 允许的请求头 - config.setAllowedHeaders(List.of("*")); - // 允许携带凭证 - config.setAllowCredentials(true); - // 预检请求缓存时间 - config.setMaxAge(3600L); - - UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); - source.registerCorsConfiguration("/**", config); - return source; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/constant/ErrorCode.java b/java-backend/src/main/java/com/lesingle/creation/common/constant/ErrorCode.java deleted file mode 100644 index 4c592ff..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/constant/ErrorCode.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.lesingle.creation.common.constant; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 统一错误码枚举 - * - * @author lesingle - * @since 1.0.0 - */ -@Getter -@AllArgsConstructor -public enum ErrorCode { - - // ========== 成功 ========== - SUCCESS(200, "操作成功"), - - // ========== 客户端错误(4xx) ========== - BAD_REQUEST(400, "请求参数错误"), - UNAUTHORIZED(401, "未登录或 Token 已过期"), - FORBIDDEN(403, "没有访问权限"), - NOT_FOUND(404, "资源不存在"), - METHOD_NOT_ALLOWED(405, "请求方法不支持"), - CONFLICT(409, "资源冲突"), - - // ========== 服务端错误(5xx) ========== - INTERNAL_ERROR(500, "系统内部错误"), - SERVICE_UNAVAILABLE(503, "服务不可用"), - - // ========== 业务错误(1xxx) ========== - USER_NOT_FOUND(1001, "用户不存在"), - USER_ACCOUNT_LOCKED(1002, "用户账号已被锁定"), - USER_PASSWORD_ERROR(1003, "用户名或密码错误"), - USER_ALREADY_EXISTS(1004, "用户已存在"), - - ROLE_NOT_FOUND(1101, "角色不存在"), - ROLE_ALREADY_EXISTS(1102, "角色已存在"), - - PERMISSION_DENIED(1201, "权限不足"), - PERMISSION_NOT_FOUND(1202, "权限不存在"), - - TOKEN_INVALID(1301, "Token 无效"), - TOKEN_EXPIRED(1302, "Token 已过期"), - - DATA_NOT_FOUND(1401, "数据不存在"), - DATA_ALREADY_EXISTS(1402, "数据已存在"), - DATA_VERSION_ERROR(1403, "数据版本冲突"), - - PARAMS_ERROR(1501, "参数校验失败"), - FILE_UPLOAD_ERROR(1502, "文件上传失败"), - FILE_DOWNLOAD_ERROR(1503, "文件下载失败"), - FILE_NOT_FOUND(1504, "文件不存在"), - - // ========== 数据库错误(2xxx) ========== - DB_ERROR(2001, "数据库操作失败"), - DB_CONNECTION_ERROR(2002, "数据库连接失败"), - DB_QUERY_ERROR(2003, "数据库查询失败"), - DB_UPDATE_ERROR(2004, "数据库更新失败"), - DB_DELETE_ERROR(2005, "数据库删除失败"), - DB_INSERT_ERROR(2006, "数据库插入失败"), - - // ========== 竞赛业务错误(3xxx) ========== - CONTEST_NOT_FOUND(3001, "竞赛不存在"), - CONTEST_ALREADY_PUBLISHED(3002, "竞赛已发布"), - CONTEST_NOT_STARTED(3003, "竞赛未开始"), - CONTEST_ALREADY_FINISHED(3004, "竞赛已结束"), - CONTEST_NAME_DUPLICATE(3005, "竞赛名称已存在"), - - REGISTRATION_NOT_FOUND(3101, "报名记录不存在"), - REGISTRATION_ALREADY_EXISTS(3102, "已报名,不能重复报名"), - REGISTRATION_AUDIT_PENDING(3103, "报名待审核"), - REGISTRATION_CLOSED(3104, "报名已截止"), - REGISTRATION_NOT_ALLOWED(3105, "不允许报名"), - - WORK_NOT_FOUND(3201, "作品不存在"), - WORK_SUBMISSION_CLOSED(3202, "作品提交已截止"), - WORK_ALREADY_SUBMITTED(3203, "作品已提交"), - WORK_NOT_LATEST_VERSION(3204, "不是最新版本"), - - REVIEW_NOT_ASSIGNED(3301, "未分配评审任务"), - REVIEW_ALREADY_SCORED(3302, "已评分,不能重复评分"), - REVIEW_SCORE_INVALID(3303, "评分无效"), - REVIEW_NOT_STARTED(3304, "评审未开始"), - - TEAM_NOT_FOUND(3401, "团队不存在"), - TEAM_MEMBER_FULL(3402, "团队成员已满"), - TEAM_MEMBER_DUPLICATE(3403, "用户已在团队中"), - - JUDGE_NOT_FOUND(3501, "评委不存在"), - JUDGE_ALREADY_ASSIGNED(3502, "评委已分配"), - - AWARD_NOT_FOUND(3601, "奖项不存在"), - AWARD_ALREADY_SET(3602, "奖项已设置"), - - NOTICE_NOT_FOUND(3701, "公告不存在"), - - // ========== 学校业务错误(4xxx) ========== - SCHOOL_NOT_FOUND(4001, "学校不存在"), - SCHOOL_CODE_DUPLICATE(4002, "学校编码已存在"), - - GRADE_NOT_FOUND(4101, "年级不存在"), - GRADE_DUPLICATE(4102, "年级名称已存在"), - - CLASS_NOT_FOUND(4201, "班级不存在"), - CLASS_DUPLICATE(4202, "班级名称已存在"), - - TEACHER_NOT_FOUND(4301, "教师不存在"), - STUDENT_NOT_FOUND(4401, "学生不存在"); - - /** - * 错误码 - */ - private final Integer code; - - /** - * 错误消息 - */ - private final String message; - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/core/Result.java b/java-backend/src/main/java/com/lesingle/creation/common/core/Result.java deleted file mode 100644 index e8eb00b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/core/Result.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.lesingle.creation.common.core; - -import com.alibaba.fastjson2.JSON; -import com.lesingle.creation.common.constant.ErrorCode; -import lombok.Data; - -import java.io.Serializable; - -/** - * 统一响应结果类 - * - * @param 数据类型 - * @author lesingle - * @since 1.0.0 - */ -@Data -public class Result implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * 响应码 - */ - private Integer code; - - /** - * 响应消息 - */ - private String message; - - /** - * 响应数据 - */ - private T data; - - /** - * 时间戳 - */ - private Long timestamp; - - public Result() { - this.timestamp = System.currentTimeMillis(); - } - - public Result(Integer code, String message, T data) { - this.code = code; - this.message = message; - this.data = data; - this.timestamp = System.currentTimeMillis(); - } - - /** - * 成功响应(无数据) - */ - public static Result success() { - return new Result<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMessage(), null); - } - - /** - * 成功响应(带数据) - */ - public static Result success(T data) { - return new Result<>(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMessage(), data); - } - - /** - * 成功响应(自定义消息) - */ - public static Result success(String message, T data) { - return new Result<>(ErrorCode.SUCCESS.getCode(), message, data); - } - - /** - * 失败响应 - */ - public static Result fail(String message) { - return new Result<>(ErrorCode.INTERNAL_ERROR.getCode(), message, null); - } - - /** - * 失败响应(指定错误码) - */ - public static Result fail(ErrorCode errorCode) { - return new Result<>(errorCode.getCode(), errorCode.getMessage(), null); - } - - /** - * 失败响应(指定错误码和消息) - */ - public static Result fail(ErrorCode errorCode, String message) { - return new Result<>(errorCode.getCode(), message, null); - } - - /** - * 失败响应(指定错误码和数据) - */ - public static Result fail(Integer code, String message) { - return new Result<>(code, message, null); - } - - /** - * 判断是否成功 - */ - public boolean isSuccess() { - return ErrorCode.SUCCESS.getCode().equals(this.code); - } - - @Override - public String toString() { - return JSON.toJSONString(this); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/AI3DGenerateTypeEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/AI3DGenerateTypeEnum.java deleted file mode 100644 index e5050a4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/AI3DGenerateTypeEnum.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI3D 生成类型枚举 - */ -@Getter -@AllArgsConstructor -public enum AI3DGenerateTypeEnum { - - NORMAL("Normal", "带纹理"), - GEOMETRY("Geometry", "白模"), - LOW_POLY("LowPoly", "低多边形"), - SKETCH("Sketch", "草图"); - - private final String code; - private final String desc; - - public static AI3DGenerateTypeEnum getByCode(String code) { - if (code == null) { - return NORMAL; - } - for (AI3DGenerateTypeEnum type : values()) { - if (type.getCode().equals(code)) { - return type; - } - } - return NORMAL; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/AI3DTaskStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/AI3DTaskStatusEnum.java deleted file mode 100644 index a61677b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/AI3DTaskStatusEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * AI3D 任务状态枚举 - */ -@Getter -@AllArgsConstructor -public enum AI3DTaskStatusEnum { - - PENDING("pending", "待处理"), - PROCESSING("processing", "处理中"), - COMPLETED("completed", "已完成"), - FAILED("failed", "失败"), - TIMEOUT("timeout", "超时"); - - private final String code; - private final String desc; - - public static AI3DTaskStatusEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (AI3DTaskStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/AssignmentStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/AssignmentStatusEnum.java deleted file mode 100644 index 85fbddf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/AssignmentStatusEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 评审分配状态枚举 - */ -@Getter -@AllArgsConstructor -public enum AssignmentStatusEnum { - - ASSIGNED("assigned", "已分配"), - REVIEWING("reviewing", "评审中"), - COMPLETED("completed", "已完成"); - - private final String code; - private final String desc; - - public static AssignmentStatusEnum getByCode(String code) { - if (code == null) { - return ASSIGNED; - } - for (AssignmentStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return ASSIGNED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/AwardLevelEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/AwardLevelEnum.java deleted file mode 100644 index 479a761..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/AwardLevelEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 奖项等级枚举 - */ -@Getter -@AllArgsConstructor -public enum AwardLevelEnum { - - FIRST("first", "一等奖"), - SECOND("second", "二等奖"), - THIRD("third", "三等奖"), - EXCELLENT("excellent", "优秀奖"), - NONE("none", "无奖项"); - - private final String code; - private final String desc; - - public static AwardLevelEnum getByCode(String code) { - if (code == null) { - return NONE; - } - for (AwardLevelEnum level : values()) { - if (level.getCode().equals(code)) { - return level; - } - } - return NONE; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/CommentStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/CommentStatusEnum.java deleted file mode 100644 index cb35737..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/CommentStatusEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 评论状态枚举 - */ -@Getter -@AllArgsConstructor -public enum CommentStatusEnum { - - PENDING("pending", "待审核"), - APPROVED("approved", "已通过"), - REJECTED("rejected", "已拒绝"); - - private final String code; - private final String desc; - - public static CommentStatusEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (CommentStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestStateEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestStateEnum.java deleted file mode 100644 index 48d76a3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestStateEnum.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 竞赛状态枚举 - */ -@Getter -@AllArgsConstructor -public enum ContestStateEnum { - - UNPUBLISHED("unpublished", "未发布"), - PUBLISHED("published", "已发布"), - REGISTERING("registering", "报名中"), - SUBMITTING("submitting", "作品提交中"), - REVIEWING("reviewing", "评审中"), - FINISHED("finished", "已完结"); - - private final String code; - private final String desc; - - public static ContestStateEnum getByCode(String code) { - if (code == null) { - return UNPUBLISHED; - } - for (ContestStateEnum state : values()) { - if (state.getCode().equals(code)) { - return state; - } - } - return UNPUBLISHED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestStatusEnum.java deleted file mode 100644 index d8696d2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestStatusEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 竞赛进度状态枚举 - */ -@Getter -@AllArgsConstructor -public enum ContestStatusEnum { - - ONGOING("ongoing", "进行中"), - FINISHED("finished", "已完结"); - - private final String code; - private final String desc; - - public static ContestStatusEnum getByCode(String code) { - if (code == null) { - return ONGOING; - } - for (ContestStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return ONGOING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestTypeEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestTypeEnum.java deleted file mode 100644 index b2f3d10..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ContestTypeEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 竞赛类型枚举 - */ -@Getter -@AllArgsConstructor -public enum ContestTypeEnum { - - INDIVIDUAL("individual", "个人赛"), - TEAM("team", "团队赛"); - - private final String code; - private final String desc; - - public static ContestTypeEnum getByCode(String code) { - if (code == null) { - return INDIVIDUAL; - } - for (ContestTypeEnum type : values()) { - if (type.getCode().equals(code)) { - return type; - } - } - return INDIVIDUAL; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/GenderEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/GenderEnum.java deleted file mode 100644 index eabe94e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/GenderEnum.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 性别枚举 - */ -@Getter -@AllArgsConstructor -public enum GenderEnum { - - MALE("male", "男"), - FEMALE("female", "女"); - - private final String code; - private final String desc; - - public static GenderEnum getByCode(String code) { - if (code == null) { - return null; - } - for (GenderEnum gender : values()) { - if (gender.getCode().equals(code)) { - return gender; - } - } - return null; - } - - /** - * 根据数字代码获取性别 - * @param code 1-男,2-女 - * @return 性别枚举 - */ - public static GenderEnum getByIntCode(Integer code) { - if (code == null) { - return null; - } - if (code == 1) { - return MALE; - } else if (code == 2) { - return FEMALE; - } - return null; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java deleted file mode 100644 index be18282..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkStatusEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 作业状态枚举 - */ -@Getter -@AllArgsConstructor -public enum HomeworkStatusEnum { - - UNPUBLISHED("unpublished", "未发布"), - PUBLISHED("published", "已发布"); - - private final String code; - private final String desc; - - public static HomeworkStatusEnum getByCode(String code) { - if (code == null) { - return UNPUBLISHED; - } - for (HomeworkStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return UNPUBLISHED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java deleted file mode 100644 index 3bac975..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/HomeworkSubmissionStatusEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 作业提交状态枚举 - */ -@Getter -@AllArgsConstructor -public enum HomeworkSubmissionStatusEnum { - - PENDING("pending", "待评审"), - REVIEWED("reviewed", "已评审"), - REJECTED("rejected", "已拒绝"); - - private final String code; - private final String desc; - - public static HomeworkSubmissionStatusEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (HomeworkSubmissionStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ParticipantTypeEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ParticipantTypeEnum.java deleted file mode 100644 index a83fc28..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ParticipantTypeEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 参与者类型枚举 - */ -@Getter -@AllArgsConstructor -public enum ParticipantTypeEnum { - - SELF("self", "自己"), - CHILD("child", "代子女"); - - private final String code; - private final String desc; - - public static ParticipantTypeEnum getByCode(String code) { - if (code == null) { - return SELF; - } - for (ParticipantTypeEnum type : values()) { - if (type.getCode().equals(code)) { - return type; - } - } - return SELF; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/RegisterTaskStateEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/RegisterTaskStateEnum.java deleted file mode 100644 index a8a39fe..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/RegisterTaskStateEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 报名任务状态枚举 - */ -@Getter -@AllArgsConstructor -public enum RegisterTaskStateEnum { - - STARTED("started", "已开始"), - CLOSED("closed", "已截止"); - - private final String code; - private final String desc; - - public static RegisterTaskStateEnum getByCode(String code) { - if (code == null) { - return STARTED; - } - for (RegisterTaskStateEnum state : values()) { - if (state.getCode().equals(code)) { - return state; - } - } - return STARTED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/RegistrationStateEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/RegistrationStateEnum.java deleted file mode 100644 index bf2631b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/RegistrationStateEnum.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 报名状态枚举 - */ -@Getter -@AllArgsConstructor -public enum RegistrationStateEnum { - - PENDING("pending", "待审核"), - PASSED("passed", "已通过"), - REJECTED("rejected", "已拒绝"), - WITHDRAWN("withdrawn", "已撤回"); - - private final String code; - private final String desc; - - public static RegistrationStateEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (RegistrationStateEnum state : values()) { - if (state.getCode().equals(code)) { - return state; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ReportActionEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ReportActionEnum.java deleted file mode 100644 index 119c3fb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ReportActionEnum.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 举报处理动作枚举 - */ -@Getter -@AllArgsConstructor -public enum ReportActionEnum { - - TAKE_DOWN("takedown", "下架"), - WARN("warn", "警告"), - BAN("ban", "封禁"), - IGNORE("ignore", "忽略"); - - private final String code; - private final String desc; - - public static ReportActionEnum getByCode(String code) { - if (code == null) { - return IGNORE; - } - for (ReportActionEnum action : values()) { - if (action.getCode().equals(code)) { - return action; - } - } - return IGNORE; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ReportStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ReportStatusEnum.java deleted file mode 100644 index 5acccac..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ReportStatusEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 举报状态枚举 - */ -@Getter -@AllArgsConstructor -public enum ReportStatusEnum { - - PENDING("pending", "待处理"), - HANDLED("handled", "已处理"), - IGNORED("ignored", "已忽略"); - - private final String code; - private final String desc; - - public static ReportStatusEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (ReportStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ReviewStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ReviewStatusEnum.java deleted file mode 100644 index 4b6c2f1..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ReviewStatusEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 评审状态枚举 - */ -@Getter -@AllArgsConstructor -public enum ReviewStatusEnum { - - PENDING("pending", "待评审"), - REVIEWING("reviewing", "评审中"), - COMPLETED("completed", "已完成"); - - private final String code; - private final String desc; - - public static ReviewStatusEnum getByCode(String code) { - if (code == null) { - return PENDING; - } - for (ReviewStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return PENDING; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/TeamRoleEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/TeamRoleEnum.java deleted file mode 100644 index 34e0549..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/TeamRoleEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 团队角色枚举 - */ -@Getter -@AllArgsConstructor -public enum TeamRoleEnum { - - MEMBER("member", "队员"), - LEADER("leader", "队长"), - MENTOR("mentor", "指导老师"); - - private final String code; - private final String desc; - - public static TeamRoleEnum getByCode(String code) { - if (code == null) { - return MEMBER; - } - for (TeamRoleEnum role : values()) { - if (role.getCode().equals(code)) { - return role; - } - } - return MEMBER; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/TenantTypeEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/TenantTypeEnum.java deleted file mode 100644 index c89cd4f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/TenantTypeEnum.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 租户类型枚举 - */ -@Getter -@AllArgsConstructor -public enum TenantTypeEnum { - - PLATFORM("platform", "平台"), - LIBRARY("library", "图书馆"), - KINDERGARTEN("kindergarten", "幼儿园"), - SCHOOL("school", "学校"), - INSTITUTION("institution", "机构"), - OTHER("other", "其他"); - - private final String code; - private final String desc; - - public static TenantTypeEnum getByCode(String code) { - if (code == null) { - return OTHER; - } - for (TenantTypeEnum type : values()) { - if (type.getCode().equals(code)) { - return type; - } - } - return OTHER; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserSourceEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/UserSourceEnum.java deleted file mode 100644 index 825f58a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserSourceEnum.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 用户来源枚举 - */ -@Getter -@AllArgsConstructor -public enum UserSourceEnum { - - ADMIN_CREATED("admin_created", "管理员创建"), - SELF_REGISTERED("self_registered", "自主注册"), - CHILD_MIGRATED("child_migrated", "子女账号迁移"); - - private final String code; - private final String desc; - - public static UserSourceEnum getByCode(String code) { - if (code == null) { - return ADMIN_CREATED; - } - for (UserSourceEnum source : values()) { - if (source.getCode().equals(code)) { - return source; - } - } - return ADMIN_CREATED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/UserStatusEnum.java deleted file mode 100644 index beeb96e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserStatusEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 用户状态枚举 - */ -@Getter -@AllArgsConstructor -public enum UserStatusEnum { - - ENABLED("enabled", "启用"), - DISABLED("disabled", "禁用"); - - private final String code; - private final String desc; - - public static UserStatusEnum getByCode(String code) { - if (code == null) { - return ENABLED; - } - for (UserStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return ENABLED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserTypeEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/UserTypeEnum.java deleted file mode 100644 index 32a6e65..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserTypeEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 用户类型枚举 - */ -@Getter -@AllArgsConstructor -public enum UserTypeEnum { - - ADULT("adult", "成人"), - CHILD("child", "子女"); - - private final String code; - private final String desc; - - public static UserTypeEnum getByCode(String code) { - if (code == null) { - return ADULT; - } - for (UserTypeEnum type : values()) { - if (type.getCode().equals(code)) { - return type; - } - } - return ADULT; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserWorkStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/UserWorkStatusEnum.java deleted file mode 100644 index 4e3cdf2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/UserWorkStatusEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * UGC 作品状态枚举 - */ -@Getter -@AllArgsConstructor -public enum UserWorkStatusEnum { - - DRAFT("draft", "草稿"), - PENDING_REVIEW("pending_review", "待审核"), - PUBLISHED("published", "已发布"), - REJECTED("rejected", "已拒绝"), - TAKEN_DOWN("taken_down", "已下架"); - - private final String code; - private final String desc; - - public static UserWorkStatusEnum getByCode(String code) { - if (code == null) { - return DRAFT; - } - for (UserWorkStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return DRAFT; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/ValidStateEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/ValidStateEnum.java deleted file mode 100644 index b1b55fb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/ValidStateEnum.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 有效状态枚举 - */ -@Getter -@AllArgsConstructor -public enum ValidStateEnum { - - VALID(1, "有效"), - INVALID(2, "失效"); - - private final Integer code; - private final String desc; - - public static ValidStateEnum getByCode(Integer code) { - if (code == null) { - return VALID; - } - for (ValidStateEnum state : values()) { - if (state.getCode().equals(code)) { - return state; - } - } - return VALID; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/VisibilityEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/VisibilityEnum.java deleted file mode 100644 index 5c49648..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/VisibilityEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 可见性枚举 - */ -@Getter -@AllArgsConstructor -public enum VisibilityEnum { - - PUBLIC("public", "公开"), - PRIVATE("private", "私有"), - DESIGNATED("designated", "指定"), - INTERNAL("internal", "内部"), - FRIENDS("friends", "好友可见"); - - private final String code; - private final String desc; - - public static VisibilityEnum getByCode(String code) { - if (code == null) { - return PRIVATE; - } - for (VisibilityEnum visibility : values()) { - if (visibility.getCode().equals(code)) { - return visibility; - } - } - return PRIVATE; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/WorkStatusEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/WorkStatusEnum.java deleted file mode 100644 index a62d30a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/WorkStatusEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 作品状态枚举 - */ -@Getter -@AllArgsConstructor -public enum WorkStatusEnum { - - SUBMITTED("submitted", "已提交"), - LOCKED("locked", "已锁定"), - REVIEWING("reviewing", "评审中"), - REJECTED("rejected", "已拒绝"), - ACCEPTED("accepted", "已接受"); - - private final String code; - private final String desc; - - public static WorkStatusEnum getByCode(String code) { - if (code == null) { - return SUBMITTED; - } - for (WorkStatusEnum status : values()) { - if (status.getCode().equals(code)) { - return status; - } - } - return SUBMITTED; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/enums/WorkTypeEnum.java b/java-backend/src/main/java/com/lesingle/creation/common/enums/WorkTypeEnum.java deleted file mode 100644 index ccfe320..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/enums/WorkTypeEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -/** - * 作品类型枚举 - */ -@Getter -@AllArgsConstructor -public enum WorkTypeEnum { - - IMAGE("image", "图片"), - VIDEO("video", "视频"), - DOCUMENT("document", "文档"), - CODE("code", "代码"), - OTHER("other", "其他"); - - private final String code; - private final String desc; - - public static WorkTypeEnum getByCode(String code) { - if (code == null) { - return OTHER; - } - for (WorkTypeEnum type : values()) { - if (type.getCode().equals(code)) { - return type; - } - } - return OTHER; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/exception/BusinessException.java b/java-backend/src/main/java/com/lesingle/creation/common/exception/BusinessException.java deleted file mode 100644 index da078e3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/exception/BusinessException.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.common.exception; - -import com.lesingle.creation.common.constant.ErrorCode; -import lombok.Getter; - -/** - * 业务异常类 - * - * @author lesingle - * @since 1.0.0 - */ -@Getter -public class BusinessException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - /** - * 错误码 - */ - private final Integer code; - - public BusinessException(String message) { - super(message); - this.code = ErrorCode.INTERNAL_ERROR.getCode(); - } - - public BusinessException(Integer code, String message) { - super(message); - this.code = code; - } - - public BusinessException(ErrorCode errorCode) { - super(errorCode.getMessage()); - this.code = errorCode.getCode(); - } - - public BusinessException(ErrorCode errorCode, String message) { - super(message); - this.code = errorCode.getCode(); - } - - public BusinessException(String message, Throwable cause) { - super(message, cause); - this.code = ErrorCode.INTERNAL_ERROR.getCode(); - } - - public BusinessException(ErrorCode errorCode, Throwable cause) { - super(errorCode.getMessage(), cause); - this.code = errorCode.getCode(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/exception/GlobalExceptionHandler.java b/java-backend/src/main/java/com/lesingle/creation/common/exception/GlobalExceptionHandler.java deleted file mode 100644 index 7bf5e74..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/exception/GlobalExceptionHandler.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.lesingle.creation.common.exception; - -import com.lesingle.creation.common.constant.ErrorCode; -import com.lesingle.creation.common.core.Result; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.core.AuthenticationException; -import org.springframework.validation.BindException; -import org.springframework.validation.FieldError; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.MethodArgumentNotValidException; -import org.springframework.web.bind.MissingPathVariableException; -import org.springframework.web.bind.MissingServletRequestParameterException; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; -import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; -import org.springframework.web.multipart.MaxUploadSizeExceededException; -import org.springframework.web.servlet.NoHandlerFoundException; - -import java.sql.SQLIntegrityConstraintViolationException; - -/** - * 全局异常处理器 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@RestControllerAdvice -public class GlobalExceptionHandler { - - /** - * 处理业务异常 - */ - @ExceptionHandler(BusinessException.class) - @ResponseStatus(HttpStatus.OK) - public Result handleBusinessException(BusinessException e) { - log.warn("业务异常:{}", e.getMessage()); - return Result.fail(e.getCode(), e.getMessage()); - } - - /** - * 处理参数校验异常(@Validated) - */ - @ExceptionHandler(MethodArgumentNotValidException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - FieldError fieldError = e.getBindingResult().getFieldError(); - String message = fieldError != null ? fieldError.getDefaultMessage() : "参数校验失败"; - log.warn("参数校验异常:{}", message); - return Result.fail(ErrorCode.PARAMS_ERROR, message); - } - - /** - * 处理参数绑定异常 - */ - @ExceptionHandler(BindException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleBindException(BindException e) { - FieldError fieldError = e.getBindingResult().getFieldError(); - String message = fieldError != null ? fieldError.getDefaultMessage() : "参数绑定失败"; - log.warn("参数绑定异常:{}", message); - return Result.fail(ErrorCode.PARAMS_ERROR, message); - } - - /** - * 处理参数类型不匹配异常 - */ - @ExceptionHandler(MethodArgumentTypeMismatchException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) { - String message = String.format("参数 [%s] 类型错误,应为:%s", e.getName(), e.getRequiredType().getSimpleName()); - log.warn("参数类型错误:{}", message); - return Result.fail(ErrorCode.PARAMS_ERROR, message); - } - - /** - * 处理缺少请求参数异常 - */ - @ExceptionHandler(MissingServletRequestParameterException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleMissingServletRequestParameterException(MissingServletRequestParameterException e) { - String message = String.format("缺少必填参数:%s", e.getParameterName()); - log.warn("缺少请求参数:{}", message); - return Result.fail(ErrorCode.PARAMS_ERROR, message); - } - - /** - * 处理缺少路径参数异常 - */ - @ExceptionHandler(MissingPathVariableException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleMissingPathVariableException(MissingPathVariableException e) { - String message = String.format("缺少路径参数:%s", e.getVariableName()); - log.warn("缺少路径参数:{}", message); - return Result.fail(ErrorCode.PARAMS_ERROR, message); - } - - /** - * 处理认证异常 - */ - @ExceptionHandler(AuthenticationException.class) - @ResponseStatus(HttpStatus.UNAUTHORIZED) - public Result handleAuthenticationException(AuthenticationException e) { - String message = "认证失败:" + e.getMessage(); - log.warn("认证异常:{}", message); - return Result.fail(ErrorCode.UNAUTHORIZED, message); - } - - /** - * 处理凭证错误(如密码错误) - */ - @ExceptionHandler(BadCredentialsException.class) - @ResponseStatus(HttpStatus.UNAUTHORIZED) - public Result handleBadCredentialsException(BadCredentialsException e) { - log.warn("凭证错误:{}", e.getMessage()); - return Result.fail(ErrorCode.UNAUTHORIZED, "用户名或密码错误"); - } - - /** - * 处理认证凭据未找到异常 - */ - @ExceptionHandler(AuthenticationCredentialsNotFoundException.class) - @ResponseStatus(HttpStatus.UNAUTHORIZED) - public Result handleAuthenticationCredentialsNotFoundException(AuthenticationCredentialsNotFoundException e) { - log.warn("未提供认证凭据:{}", e.getMessage()); - return Result.fail(ErrorCode.UNAUTHORIZED, "未登录或 Token 已过期"); - } - - /** - * 处理授权异常(权限不足) - */ - @ExceptionHandler(AccessDeniedException.class) - @ResponseStatus(HttpStatus.FORBIDDEN) - public Result handleAccessDeniedException(AccessDeniedException e) { - log.warn("权限不足:{}", e.getMessage()); - return Result.fail(ErrorCode.FORBIDDEN, "没有访问权限"); - } - - /** - * 处理资源不存在异常 - */ - @ExceptionHandler(NoHandlerFoundException.class) - @ResponseStatus(HttpStatus.NOT_FOUND) - public Result handleNoHandlerFoundException(NoHandlerFoundException e) { - String message = String.format("资源不存在:%s %s", e.getHttpMethod(), e.getRequestURL()); - log.warn("资源不存在:{}", message); - return Result.fail(ErrorCode.NOT_FOUND, message); - } - - /** - * 处理请求方法不支持异常 - */ - @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) - public Result handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { - String message = String.format("不支持的请求方法:%s", e.getMethod()); - log.warn("请求方法不支持:{}", message); - return Result.fail(ErrorCode.METHOD_NOT_ALLOWED, message); - } - - /** - * 处理文件上传大小超限异常 - */ - @ExceptionHandler(MaxUploadSizeExceededException.class) - @ResponseStatus(HttpStatus.BAD_REQUEST) - public Result handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) { - log.warn("文件大小超限:{}", e.getMessage()); - return Result.fail(ErrorCode.FILE_UPLOAD_ERROR, "上传文件大小超过限制"); - } - - /** - * 处理数据库唯一约束冲突异常 - */ - @ExceptionHandler(SQLIntegrityConstraintViolationException.class) - @ResponseStatus(HttpStatus.CONFLICT) - public Result handleSQLIntegrityConstraintViolationException(SQLIntegrityConstraintViolationException e) { - String message = e.getMessage(); - if (message != null && message.contains("Duplicate entry")) { - message = "数据已存在,请勿重复添加"; - } - log.warn("数据库约束冲突:{}", message); - return Result.fail(ErrorCode.DATA_ALREADY_EXISTS, message); - } - - /** - * 处理其他未知异常 - */ - @ExceptionHandler(Exception.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public Result handleException(Exception e) { - log.error("系统内部错误:", e); - return Result.fail(ErrorCode.INTERNAL_ERROR, "系统内部错误:" + e.getMessage()); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/filter/JwtAuthenticationFilter.java b/java-backend/src/main/java/com/lesingle/creation/common/filter/JwtAuthenticationFilter.java deleted file mode 100644 index 134892f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/filter/JwtAuthenticationFilter.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.lesingle.creation.common.filter; - -import com.lesingle.creation.common.config.JwtProperties; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.common.util.JwtTokenUtil; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; -import org.springframework.web.filter.OncePerRequestFilter; - -import java.io.IOException; - -/** - * JWT 认证过滤器 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class JwtAuthenticationFilter extends OncePerRequestFilter { - - private final JwtTokenUtil jwtTokenUtil; - private final UserDetailsService userDetailsService; - private final JwtProperties jwtProperties; - - @Override - protected void doFilterInternal(HttpServletRequest request, - HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { - // 从请求头中获取 Token - String token = getTokenFromRequest(request); - - if (StringUtils.hasText(token)) { - try { - // 验证 Token - String username = jwtTokenUtil.getUsernameFromToken(token); - - if (StringUtils.hasText(username) && SecurityContextHolder.getContext().getAuthentication() == null) { - // 从数据库加载用户信息(UserDetailsServiceImpl 返回的是 UserPrincipal) - UserDetails userDetails = userDetailsService.loadUserByUsername(username); - - // 验证 Token 是否有效 - if (jwtTokenUtil.isTokenValid(token, userDetails)) { - // 创建认证对象(principal 使用 UserPrincipal 类型) - UsernamePasswordAuthenticationToken authentication = - new UsernamePasswordAuthenticationToken( - userDetails, // 这就是 UserPrincipal 类型 - null, - userDetails.getAuthorities() - ); - authentication.setDetails( - new WebAuthenticationDetailsSource().buildDetails(request) - ); - // 设置到 SecurityContext - SecurityContextHolder.getContext().setAuthentication(authentication); - log.debug("用户认证成功:{}, userId={}", - userDetails.getUsername(), - userDetails instanceof UserPrincipal ? ((UserPrincipal) userDetails).getUserId() : "unknown"); - } - } - } catch (Exception e) { - log.warn("Token 验证失败:{}", e.getMessage()); - } - } - - filterChain.doFilter(request, response); - } - - /** - * 从请求头中获取 Token - */ - private String getTokenFromRequest(HttpServletRequest request) { - String bearerToken = request.getHeader(jwtProperties.getHeader()); - if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(jwtProperties.getTokenPrefix())) { - return bearerToken.substring(jwtProperties.getTokenPrefix().length()).trim(); - } - // 也支持 token 作为查询参数 - String token = request.getParameter("token"); - if (StringUtils.hasText(token)) { - return token; - } - return null; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/handler/MyMetaObjectHandler.java b/java-backend/src/main/java/com/lesingle/creation/common/handler/MyMetaObjectHandler.java deleted file mode 100644 index c822f54..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/handler/MyMetaObjectHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.lesingle.creation.common.handler; - -import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; -import com.lesingle.creation.util.SecurityUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.reflection.MetaObject; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; - -/** - * MyBatis-Plus 自动填充处理器 - *

- * 自动填充创建人、创建时间、更新人、更新时间字段 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class MyMetaObjectHandler implements MetaObjectHandler { - - private final SecurityUtils securityUtils; - - @Override - public void insertFill(MetaObject metaObject) { - log.debug("执行插入操作,自动填充审计字段"); - LocalDateTime now = LocalDateTime.now(); - - // 填充创建时间 - this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, now); - - // 填充创建人(从 UserContext 获取当前用户名) - this.strictInsertFill(metaObject, "createBy", String.class, getCurrentUsername()); - - // 填充更新时间 - this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, now); - - // 填充更新人 - this.strictInsertFill(metaObject, "updateBy", String.class, getCurrentUsername()); - } - - @Override - public void updateFill(MetaObject metaObject) { - log.debug("执行更新操作,自动填充审计字段"); - LocalDateTime now = LocalDateTime.now(); - - // 填充更新时间 - this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, now); - - // 填充更新人 - this.strictUpdateFill(metaObject, "updateBy", String.class, getCurrentUsername()); - } - - /** - * 获取当前登录用户名 - * 从 SecurityUtils 获取,非登录场景返回 "system" - */ - private String getCurrentUsername() { - try { - return securityUtils.getCurrentUsernameStr(); - } catch (Exception e) { - log.warn("获取当前用户名失败,使用默认值:{}", e.getMessage()); - return "system"; - } - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/security/UserPrincipal.java b/java-backend/src/main/java/com/lesingle/creation/common/security/UserPrincipal.java deleted file mode 100644 index 7df876e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/security/UserPrincipal.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lesingle.creation.common.security; - -import lombok.Getter; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Collection; - -/** - * 用户 Principal 实现类 - * - * @author lesingle - * @since 1.0.0 - */ -@Getter -public class UserPrincipal implements UserDetails { - - private final Long userId; - private final String username; // 用户名(用于显示) - private final String password; - private final Collection authorities; - private final Long tenantId; - private final String tenantCode; // 租户编码 - private final boolean isSuperTenant; // 是否超级租户 - - public UserPrincipal(Long userId, String username, String password, - Collection authorities, - Long tenantId, String tenantCode, boolean isSuperTenant) { - this.userId = userId; - this.username = username; - this.password = password; - this.authorities = authorities; - this.tenantId = tenantId; - this.tenantCode = tenantCode; - this.isSuperTenant = isSuperTenant; - } - - @Override - public Collection getAuthorities() { - return this.authorities; - } - - @Override - public String getPassword() { - return this.password; - } - - @Override - public String getUsername() { - return String.valueOf(this.userId); // 返回用户 ID 字符串,方便 SecurityUtils 获取 - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return true; - } - - /** - * 获取显示用户名(用于日志等) - * - * @return 显示用户名 - */ - public String getDisplayName() { - return this.username; - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/util/JwtTokenUtil.java b/java-backend/src/main/java/com/lesingle/creation/common/util/JwtTokenUtil.java deleted file mode 100644 index 93535f1..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/util/JwtTokenUtil.java +++ /dev/null @@ -1,182 +0,0 @@ -package com.lesingle.creation.common.util; - -import com.lesingle.creation.common.config.JwtProperties; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.security.Keys; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Component; - -import javax.crypto.SecretKey; -import java.nio.charset.StandardCharsets; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Function; - -/** - * JWT Token 工具类 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class JwtTokenUtil { - - private final JwtProperties jwtProperties; - - /** - * 获取密钥 - */ - private SecretKey getSigningKey() { - byte[] keyBytes = jwtProperties.getSecret().getBytes(StandardCharsets.UTF_8); - return Keys.hmacShaKeyFor(keyBytes); - } - - /** - * 从 Token 中获取用户名 - */ - public String getUsernameFromToken(String token) { - return getClaimFromToken(token, Claims::getSubject); - } - - /** - * 从 Token 中获取用户 ID - * - * @param token JWT Token - * @return 用户 ID - */ - public Long getUserIdFromToken(String token) { - String username = getUsernameFromToken(token); - try { - return Long.parseLong(username); - } catch (NumberFormatException e) { - log.warn("无法解析用户 ID:{}", username); - return null; - } - } - - /** - * 从 Token 中获取指定声明 - */ - public T getClaimFromToken(String token, Function claimsResolver) { - final Claims claims = getAllClaimsFromToken(token); - return claimsResolver.apply(claims); - } - - /** - * 获取所有声明 - */ - private Claims getAllClaimsFromToken(String token) { - return Jwts.parser() - .verifyWith(getSigningKey()) - .build() - .parseSignedClaims(token) - .getPayload(); - } - - /** - * 生成 Token - */ - public String generateToken(String username) { - Map claims = new HashMap<>(); - return createToken(claims, username); - } - - /** - * 生成带额外信息的 Token - */ - public String generateToken(String username, Map claims) { - return createToken(claims, username); - } - - /** - * 生成带租户信息的 Token - * - * @param userId 用户 ID - * @param tenantId 租户 ID - * @param tenantCode 租户编码 - * @return JWT Token - */ - public String generateToken(Long userId, Long tenantId, String tenantCode) { - Map claims = new HashMap<>(); - claims.put("tenantId", tenantId); - claims.put("tenantCode", tenantCode); - return createToken(claims, String.valueOf(userId)); - } - - /** - * 生成带用户名的 Token(用于公众用户) - * - * @param userId 用户 ID - * @param username 用户名 - * @return JWT Token - */ - public String generateToken(Long userId, String username) { - Map claims = new HashMap<>(); - claims.put("userId", userId); - return createToken(claims, username); - } - - /** - * 从 Token 中获取租户 ID - * - * @param token JWT Token - * @return 租户 ID - */ - public Long getTenantIdFromToken(String token) { - return getClaimFromToken(token, claims -> claims.get("tenantId", Long.class)); - } - - /** - * 从 Token 中获取租户编码 - * - * @param token JWT Token - * @return 租户编码 - */ - public String getTenantCodeFromToken(String token) { - return getClaimFromToken(token, claims -> claims.get("tenantCode", String.class)); - } - - /** - * 创建 Token - */ - private String createToken(Map claims, String subject) { - Date now = new Date(); - Date expirationDate = new Date(now.getTime() + jwtProperties.getExpiration()); - - return Jwts.builder() - .claims(claims) - .subject(subject) - .issuedAt(now) - .expiration(expirationDate) - .signWith(getSigningKey()) - .compact(); - } - - /** - * 验证 Token 是否有效 - */ - public boolean isTokenValid(String token, UserDetails userDetails) { - final String username = getUsernameFromToken(token); - return (username.equals(userDetails.getUsername()) && !isTokenExpired(token)); - } - - /** - * 判断 Token 是否过期 - */ - private boolean isTokenExpired(String token) { - return extractExpiration(token).before(new Date()); - } - - /** - * 获取 Token 过期时间 - */ - public Date extractExpiration(String token) { - return getClaimFromToken(token, Claims::getExpiration); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/util/OssUtil.java b/java-backend/src/main/java/com/lesingle/creation/common/util/OssUtil.java deleted file mode 100644 index afa1dfc..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/util/OssUtil.java +++ /dev/null @@ -1,274 +0,0 @@ -package com.lesingle.creation.common.util; - -import com.aliyun.oss.OSS; -import com.aliyun.oss.OSSClientBuilder; -import com.aliyun.oss.model.PutObjectRequest; -import com.lesingle.creation.common.config.OssProperties; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; - -/** - * 阿里云 OSS 文件上传工具类 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class OssUtil { - - private final OssProperties ossProperties; - - /** - * 允许上传的文件类型 - */ - private static final List ALLOWED_TYPES = Arrays.asList( - "image/jpeg", "image/png", "image/gif", "image/webp", - "application/pdf", "application/msword", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document" - ); - - /** - * 最大文件大小:100MB - */ - private static final long MAX_FILE_SIZE = 100 * 1024 * 1024; - - /** - * 上传文件 - * - * @param file 上传的文件 - * @return 文件访问 URL - * @throws IOException 上传失败抛出异常 - */ - public String upload(MultipartFile file) throws IOException { - // 校验文件 - validateFile(file); - - // 生成文件名 - String fileName = generateFileName(file.getOriginalFilename()); - - // 生成文件路径(按日期分目录) - String objectKey = buildObjectKey(fileName); - - // 获取 OSS 客户端 - OSS ossClient = createOssClient(); - - try { - // 上传文件 - InputStream inputStream = file.getInputStream(); - PutObjectRequest putObjectRequest = new PutObjectRequest( - ossProperties.getBucketName(), - objectKey, - inputStream - ); - ossClient.putObject(putObjectRequest); - - // 返回文件 URL - String fileUrl = getFileUrl(objectKey); - log.info("文件上传成功:{}, URL: {}", objectKey, fileUrl); - return fileUrl; - } finally { - // 关闭客户端 - ossClient.shutdown(); - } - } - - /** - * 上传文件(自定义路径) - * - * @param file 上传的文件 - * @param customPath 自定义路径(如:avatars/) - * @return 文件访问 URL - * @throws IOException 上传失败抛出异常 - */ - public String upload(MultipartFile file, String customPath) throws IOException { - // 校验文件 - validateFile(file); - - // 生成文件名 - String fileName = generateFileName(file.getOriginalFilename()); - - // 生成文件路径 - String objectKey = customPath + (customPath.endsWith("/") ? "" : "/") + fileName; - - // 获取 OSS 客户端 - OSS ossClient = createOssClient(); - - try { - // 上传文件 - InputStream inputStream = file.getInputStream(); - PutObjectRequest putObjectRequest = new PutObjectRequest( - ossProperties.getBucketName(), - objectKey, - inputStream - ); - ossClient.putObject(putObjectRequest); - - // 返回文件 URL - String fileUrl = getFileUrl(objectKey); - log.info("文件上传成功:{}, URL: {}", objectKey, fileUrl); - return fileUrl; - } finally { - // 关闭客户端 - ossClient.shutdown(); - } - } - - /** - * 上传字节数组 - * - * @param bytes 文件字节数组 - * @param fileName 文件名 - * @param customPath 自定义路径 - * @return 文件访问 URL - * @throws IOException 上传失败抛出异常 - */ - public String upload(byte[] bytes, String fileName, String customPath) throws IOException { - String finalFileName = generateFileName(fileName); - String objectKey = customPath + (customPath.endsWith("/") ? "" : "/") + finalFileName; - - OSS ossClient = createOssClient(); - try { - InputStream inputStream = new ByteArrayInputStream(bytes); - PutObjectRequest putObjectRequest = new PutObjectRequest( - ossProperties.getBucketName(), - objectKey, - inputStream - ); - ossClient.putObject(putObjectRequest); - - return getFileUrl(objectKey); - } finally { - ossClient.shutdown(); - } - } - - /** - * 删除文件 - * - * @param fileUrl 文件 URL - */ - public void delete(String fileUrl) { - String objectKey = extractObjectKey(fileUrl); - if (objectKey == null) { - log.warn("无法解析文件 Key: {}", fileUrl); - return; - } - - OSS ossClient = createOssClient(); - try { - ossClient.deleteObject(ossProperties.getBucketName(), objectKey); - log.info("文件删除成功:{}", objectKey); - } catch (Exception e) { - log.error("文件删除失败:{}", objectKey, e); - } finally { - ossClient.shutdown(); - } - } - - /** - * 校验文件 - */ - private void validateFile(MultipartFile file) { - // 检查文件是否为空 - if (file == null || file.isEmpty()) { - throw new IllegalArgumentException("上传文件不能为空"); - } - - // 检查文件大小 - if (file.getSize() > MAX_FILE_SIZE) { - throw new IllegalArgumentException("文件大小超过限制:" + (MAX_FILE_SIZE / 1024 / 1024) + "MB"); - } - - // 检查文件类型 - String contentType = file.getContentType(); - if (contentType == null || !ALLOWED_TYPES.contains(contentType.toLowerCase())) { - throw new IllegalArgumentException("不支持的文件类型:" + contentType); - } - } - - /** - * 生成文件名(使用 UUID) - */ - private String generateFileName(String originalFilename) { - if (originalFilename == null || originalFilename.isEmpty()) { - return UUID.randomUUID().toString(); - } - - int dotIndex = originalFilename.lastIndexOf("."); - if (dotIndex > 0) { - String extension = originalFilename.substring(dotIndex); - return UUID.randomUUID().toString() + extension; - } - - return UUID.randomUUID().toString(); - } - - /** - * 构建文件路径(按日期分目录) - */ - private String buildObjectKey(String fileName) { - String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd/")); - String rootDir = ossProperties.getRootDir(); - - return (rootDir != null && !rootDir.isEmpty() ? rootDir + "/" : "") - + datePath + fileName; - } - - /** - * 获取文件访问 URL - */ - private String getFileUrl(String objectKey) { - if (ossProperties.getCustomDomain() != null && !ossProperties.getCustomDomain().isEmpty()) { - return ossProperties.getCustomDomain() + "/" + objectKey; - } - - return "https://" + ossProperties.getBucketName() + "." + ossProperties.getEndpoint() + "/" + objectKey; - } - - /** - * 从 URL 中提取 Object Key - */ - private String extractObjectKey(String fileUrl) { - if (fileUrl == null || fileUrl.isEmpty()) { - return null; - } - - // 尝试从自定义域名解析 - if (ossProperties.getCustomDomain() != null && fileUrl.startsWith(ossProperties.getCustomDomain())) { - return fileUrl.substring(ossProperties.getCustomDomain().length() + 1); - } - - // 从 OSS 默认域名解析 - String bucketDomain = ossProperties.getBucketName() + "." + ossProperties.getEndpoint(); - if (fileUrl.contains(bucketDomain)) { - return fileUrl.substring(fileUrl.indexOf(bucketDomain) + bucketDomain.length() + 1); - } - - return null; - } - - /** - * 创建 OSS 客户端 - */ - private OSS createOssClient() { - return new OSSClientBuilder().build( - ossProperties.getEndpoint(), - ossProperties.getAccessKeyId(), - ossProperties.getAccessKeySecret() - ); - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/util/RateLimiterUtil.java b/java-backend/src/main/java/com/lesingle/creation/common/util/RateLimiterUtil.java deleted file mode 100644 index 51eb6f8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/util/RateLimiterUtil.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.lesingle.creation.common.util; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; - -import java.util.concurrent.TimeUnit; - -/** - * Redis 限流工具类 - *

- * 基于滑动窗口算法实现限流 - * - * @author lesingle - * @since 1.0.0 - */ -@Slf4j -@Component -public class RateLimiterUtil { - - private static RedisTemplate redisTemplate; - - public RateLimiterUtil(RedisTemplate redisTemplate) { - RateLimiterUtil.redisTemplate = redisTemplate; - } - - /** - * 判断是否允许请求通过 - * - * @param key 限流 key - * @param time 时间窗口(秒) - * @param count 时间窗口内最大请求数 - * @return true-允许通过,false-拒绝请求 - */ - public static boolean tryAcquire(String key, int time, int count) { - try { - Long currentCount = redisTemplate.opsForValue().increment(key); - if (currentCount == 1) { - // 第一次请求,设置过期时间 - redisTemplate.expire(key, time, TimeUnit.SECONDS); - } - return currentCount <= count; - } catch (Exception e) { - log.error("Redis 限流异常,key: {}", key, e); - // Redis 异常时放行 - return true; - } - } - - /** - * 获取当前请求数 - * - * @param key 限流 key - * @return 当前请求数 - */ - public static Long getCurrentCount(String key) { - try { - String value = (String) redisTemplate.opsForValue().get(key); - return value != null ? Long.parseLong(value) : 0L; - } catch (Exception e) { - log.error("获取限流计数异常,key: {}", key, e); - return 0L; - } - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/common/util/TraceIdUtil.java b/java-backend/src/main/java/com/lesingle/creation/common/util/TraceIdUtil.java deleted file mode 100644 index 1759d24..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/common/util/TraceIdUtil.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.common.util; - -import cn.hutool.core.util.IdUtil; -import org.slf4j.MDC; - -/** - * TraceId 工具类 - *

- * 用于生成和管理链路追踪 ID,实现全链路日志追踪 - * - * @author lesingle - * @since 1.0.0 - */ -public class TraceIdUtil { - - /** - * MDC 中 TraceId 的 key - */ - private static final String TRACE_ID_KEY = "traceId"; - - /** - * 生成 TraceId 并放入 MDC - */ - public static void setTraceId() { - MDC.put(TRACE_ID_KEY, IdUtil.fastSimpleUUID()); - } - - /** - * 获取当前 TraceId - * - * @return TraceId,不存在则返回 "unknown" - */ - public static String getTraceId() { - return MDC.get(TRACE_ID_KEY) != null ? MDC.get(TRACE_ID_KEY) : "unknown"; - } - - /** - * 清除 MDC 中的 TraceId - */ - public static void clearTraceId() { - MDC.remove(TRACE_ID_KEY); - } - - /** - * 清除所有 MDC 内容 - */ - public static void clear() { - MDC.clear(); - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/AI3DTaskController.java b/java-backend/src/main/java/com/lesingle/creation/controller/AI3DTaskController.java deleted file mode 100644 index 46d55cd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/AI3DTaskController.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.ai3d.AI3DTaskQueryDTO; -import com.lesingle.creation.dto.ai3d.CreateAI3DTaskDTO; -import com.lesingle.creation.service.AI3DTaskService; -import com.lesingle.creation.vo.ai3d.AI3DTaskVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * AI 3D 生成控制器 - */ -@Tag(name = "AI 3D 生成") -@RestController -@RequestMapping("/api/ai-3d") -@RequiredArgsConstructor -public class AI3DTaskController { - - private final AI3DTaskService ai3dTaskService; - - @PostMapping - @Operation(summary = "创建 AI 3D 任务") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateAI3DTaskDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long userId = userPrincipal.getUserId(); - AI3DTaskVO result = ai3dTaskService.create(dto, tenantId, userId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取任务详情") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - AI3DTaskVO result = ai3dTaskService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/page") - @Operation(summary = "分页查询任务列表") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute AI3DTaskQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Long userId = userPrincipal.getUserId(); // 查询自己的任务 - Page result = ai3dTaskService.pageQuery(queryDTO, tenantId, userId); - return Result.success(result); - } - - @PutMapping("/{id}/cancel") - @Operation(summary = "取消任务") - public Result cancel( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ai3dTaskService.cancel(id, tenantId); - return Result.success(null); - } - - @PutMapping("/{id}/retry") - @Operation(summary = "重试失败的任务") - public Result retry( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - AI3DTaskVO result = ai3dTaskService.retry(id, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除 AI 3D 任务") - @PreAuthorize("hasAuthority('ai-3d:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ai3dTaskService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/AuthController.java b/java-backend/src/main/java/com/lesingle/creation/controller/AuthController.java deleted file mode 100644 index 78fc4cb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/AuthController.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.auth.LoginDTO; -import com.lesingle.creation.service.AuthService; -import com.lesingle.creation.vo.auth.LoginResponseVO; -import com.lesingle.creation.vo.auth.UserInfoVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.web.bind.annotation.*; - -/** - * 认证控制器 - */ -@Slf4j -@Tag(name = "认证管理", description = "用户登录、登出、刷新 Token 等接口") -@RestController -@RequestMapping("/api/auth") -@RequiredArgsConstructor -public class AuthController { - - private final AuthService authService; - - /** - * 用户登录 - */ - @Operation(summary = "用户登录") - @PostMapping("/login") - public Result login(@RequestBody LoginDTO loginDTO) { - LoginResponseVO response = authService.login(loginDTO); - return Result.success(response); - } - - /** - * 获取当前用户信息 - */ - @Operation(summary = "获取当前用户信息") - @GetMapping("/me") - public Result getCurrentUser() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - log.debug("Authentication: {}", authentication); - if (authentication == null || !authentication.isAuthenticated()) { - return Result.fail(401, "未授权"); - } - - Object principal = authentication.getPrincipal(); - log.debug("Principal type: {}", principal != null ? principal.getClass().getName() : "null"); - Long userId; - - if (principal instanceof UserPrincipal) { - userId = ((UserPrincipal) principal).getUserId(); - log.info("UserPrincipal userId: {}", userId); - } else if (principal instanceof UserDetails) { - // 从 UserDetails 获取用户名,然后通过用户名查询用户 - String username = ((UserDetails) principal).getUsername(); - log.debug("Principal 是 UserDetails 类型,用户名:{}", username); - // 尝试从 authorities 获取用户 ID(如果有) - userId = null; - } else { - log.warn("无法识别的 Principal 类型:{}", principal != null ? principal.getClass().getName() : "null"); - return Result.fail(401, "无法获取用户信息"); - } - - if (userId == null) { - return Result.fail(401, "无法获取用户 ID"); - } - - UserInfoVO userInfo = authService.getUserInfo(userId); - return Result.success(userInfo); - } - - /** - * 用户登出 - */ - @Operation(summary = "用户登出") - @PostMapping("/logout") - public Result logout() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication != null && authentication.getPrincipal() instanceof UserDetails) { - String username = ((UserDetails) authentication.getPrincipal()).getUsername(); - log.info("用户登出:{}", username); - } - // TODO: 可以将 token 加入黑名单(使用 Redis) - return Result.success(null); - } - - /** - * 刷新 Token - */ - @Operation(summary = "刷新 Token") - @PostMapping("/refresh-token") - public Result refreshToken(@RequestHeader("Authorization") String token) { - LoginResponseVO response = authService.refreshToken(token); - return Result.success(response); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ConfigController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ConfigController.java deleted file mode 100644 index e6839b3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ConfigController.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.config.CreateConfigDTO; -import com.lesingle.creation.dto.config.UpdateConfigDTO; -import com.lesingle.creation.service.ConfigService; -import com.lesingle.creation.vo.config.ConfigDetailVO; -import com.lesingle.creation.vo.config.ConfigListVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 系统配置管理控制器 - */ -@Tag(name = "系统配置管理") -@RestController -@RequestMapping("/api/config") -@RequiredArgsConstructor -public class ConfigController { - - private final ConfigService configService; - - @PostMapping - @Operation(summary = "创建配置") - @PreAuthorize("hasAuthority('config:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateConfigDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long operatorId = userPrincipal.getUserId(); - ConfigDetailVO result = configService.create(dto, tenantId, operatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "配置列表") - @PreAuthorize("hasAuthority('config:read')") - public Result> pageList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int pageSize) { - Long tenantId = userPrincipal.getTenantId(); - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - configService.pageList(tenantId, page, pageSize); - return Result.success(result); - } - - @GetMapping("/key/{key}") - @Operation(summary = "根据键查询配置") - @PreAuthorize("hasAuthority('config:read')") - public Result getByKey( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable String key) { - Long tenantId = userPrincipal.getTenantId(); - ConfigDetailVO result = configService.getByKey(key, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "配置详情") - @PreAuthorize("hasAuthority('config:read')") - public Result detail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ConfigDetailVO result = configService.detail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新配置") - @PreAuthorize("hasAuthority('config:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateConfigDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - ConfigDetailVO result = configService.update(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除配置") - @PreAuthorize("hasAuthority('config:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - configService.delete(id, tenantId); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestController.java deleted file mode 100644 index d7847ca..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestController.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.contest.*; -import com.lesingle.creation.service.ContestService; -import com.lesingle.creation.vo.contest.ContestDetailVO; -import com.lesingle.creation.vo.contest.ContestListVO; -import com.lesingle.creation.vo.contest.ContestStatsVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 竞赛管理控制器 - */ -@Tag(name = "竞赛管理") -@RestController -@RequestMapping("/api/contests") -@RequiredArgsConstructor -public class ContestController { - - private final ContestService contestService; - - @PostMapping - @Operation(summary = "创建竞赛") - @PreAuthorize("hasAuthority('contest:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateContestDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - ContestDetailVO result = contestService.create(dto, tenantId); - return Result.success(result); - } - - @GetMapping("/stats") - @Operation(summary = "竞赛统计") - @PreAuthorize("hasAuthority('contest:read')") - public Result getStats() { - ContestStatsVO result = contestService.getStats(); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "竞赛列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> pageList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - ContestQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = contestService.pageList(queryDTO, tenantId); - return Result.success(result); - } - - @GetMapping("/my-contests") - @Operation(summary = "我参与的活动列表") - public Result> myContests( - @AuthenticationPrincipal UserPrincipal userPrincipal, - ContestQueryDTO queryDTO) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - Page result = contestService.myContests(queryDTO, userId, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "竞赛详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result detail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ContestDetailVO result = contestService.detail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新竞赛") - @PreAuthorize("hasAuthority('contest:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateContestDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - ContestDetailVO result = contestService.update(id, dto, tenantId); - return Result.success(result); - } - - @PatchMapping("/{id}/publish") - @Operation(summary = "发布/取消发布竞赛") - @PreAuthorize("hasAuthority('contest:publish')") - public Result publish( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated PublishContestDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - ContestDetailVO result = contestService.publish(id, dto.getContestState(), tenantId); - return Result.success(result); - } - - @PatchMapping("/{id}/finish") - @Operation(summary = "标记竞赛为完结") - @PreAuthorize("hasAuthority('contest:update')") - public Result finish( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ContestDetailVO result = contestService.finish(id, tenantId); - return Result.success(result); - } - - @PatchMapping("/{id}/reopen") - @Operation(summary = "重新开启竞赛") - @PreAuthorize("hasAuthority('contest:update')") - public Result reopen( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ContestDetailVO result = contestService.reopen(id, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除竞赛") - @PreAuthorize("hasAuthority('contest:delete')") - public Result delete(@PathVariable Long id) { - contestService.delete(id); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestJudgeController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestJudgeController.java deleted file mode 100644 index a32d98f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestJudgeController.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.judge.CreateJudgeDTO; -import com.lesingle.creation.dto.judge.UpdateJudgeDTO; -import com.lesingle.creation.service.ContestJudgeService; -import com.lesingle.creation.vo.judge.JudgeVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; -import java.util.Map; - -/** - * 竞赛评委管理控制器 - */ -@Tag(name = "竞赛评委管理") -@RestController -@RequestMapping("/api/contests/judges") -@RequiredArgsConstructor -public class ContestJudgeController { - - private final ContestJudgeService judgeService; - - @PostMapping - @Operation(summary = "创建评委") - @PreAuthorize("hasAuthority('contest:judge:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateJudgeDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - JudgeVO result = judgeService.create(dto, creatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新评委") - @PreAuthorize("hasAuthority('contest:judge:update')") - public Result update( - @PathVariable Long id, - @RequestBody @Validated UpdateJudgeDTO dto) { - JudgeVO result = judgeService.update(id, dto); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除评委") - @PreAuthorize("hasAuthority('contest:judge:delete')") - public Result delete(@PathVariable Long id) { - judgeService.delete(id); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取评委详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail(@PathVariable Long id) { - JudgeVO result = judgeService.getDetail(id); - return Result.success(result); - } - - @GetMapping("/contest/{contestId}") - @Operation(summary = "查询活动的评委列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listByContest(@PathVariable Long contestId) { - List result = judgeService.listByContest(contestId); - return Result.success(result); - } - - @PostMapping("/freeze") - @Operation(summary = "冻结评委") - @PreAuthorize("hasAuthority('contest:judge:update')") - public Result freeze(@RequestBody Map params) { - Long id = params.get("id"); - JudgeVO result = judgeService.freeze(id); - return Result.success(result); - } - - @PostMapping("/unfreeze") - @Operation(summary = "解冻评委") - @PreAuthorize("hasAuthority('contest:judge:update')") - public Result unfreeze(@RequestBody Map params) { - Long id = params.get("id"); - JudgeVO result = judgeService.unfreeze(id); - return Result.success(result); - } - - @PostMapping("/batch-delete") - @Operation(summary = "批量删除评委") - @PreAuthorize("hasAuthority('contest:judge:delete')") - public Result batchDelete(@RequestBody List ids) { - judgeService.batchDelete(ids); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestNoticeController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestNoticeController.java deleted file mode 100644 index 3161f0e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestNoticeController.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.notice.CreateNoticeDTO; -import com.lesingle.creation.dto.notice.UpdateNoticeDTO; -import com.lesingle.creation.service.ContestNoticeService; -import com.lesingle.creation.vo.notice.NoticeVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛公告管理控制器 - */ -@Tag(name = "竞赛公告管理") -@RestController -@RequestMapping("/api/contests/notices") -@RequiredArgsConstructor -public class ContestNoticeController { - - private final ContestNoticeService noticeService; - - @PostMapping - @Operation(summary = "创建公告") - @PreAuthorize("hasAuthority('contest:notice:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateNoticeDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - NoticeVO result = noticeService.create(dto, creatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新公告") - @PreAuthorize("hasAuthority('contest:notice:update')") - public Result update( - @PathVariable Long id, - @RequestBody @Validated UpdateNoticeDTO dto) { - NoticeVO result = noticeService.update(id, dto); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除公告") - @PreAuthorize("hasAuthority('contest:notice:delete')") - public Result delete(@PathVariable Long id) { - noticeService.delete(id); - return Result.success(null); - } - - @PostMapping("/{id}/publish") - @Operation(summary = "发布公告") - @PreAuthorize("hasAuthority('contest:notice:publish')") - public Result publish(@PathVariable Long id) { - NoticeVO result = noticeService.publish(id); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取公告详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail(@PathVariable Long id) { - NoticeVO result = noticeService.getDetail(id); - return Result.success(result); - } - - @GetMapping("/contest/{contestId}") - @Operation(summary = "查询活动的公告列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listByContest(@PathVariable Long contestId) { - List result = noticeService.listByContest(contestId); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestPresetCommentController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestPresetCommentController.java deleted file mode 100644 index 73a6a6b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestPresetCommentController.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.presetcomment.CreatePresetCommentDTO; -import com.lesingle.creation.service.ContestPresetCommentService; -import com.lesingle.creation.vo.presetcomment.PresetCommentVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛预设评语管理控制器 - */ -@Tag(name = "竞赛预设评语管理") -@RestController -@RequestMapping("/api/contests/preset-comments") -@RequiredArgsConstructor -public class ContestPresetCommentController { - - private final ContestPresetCommentService presetCommentService; - - @PostMapping - @Operation(summary = "创建预设评语") - @PreAuthorize("hasAuthority('contest:preset-comment:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreatePresetCommentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - PresetCommentVO result = presetCommentService.create(dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除预设评语") - @PreAuthorize("hasAuthority('contest:preset-comment:delete')") - public Result delete(@PathVariable Long id) { - presetCommentService.delete(id); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取预设评语详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail(@PathVariable Long id) { - PresetCommentVO result = presetCommentService.getDetail(id); - return Result.success(result); - } - - @GetMapping("/contest/{contestId}") - @Operation(summary = "查询活动的预设评语列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listByContest( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId) { - Long tenantId = userPrincipal.getTenantId(); - List result = presetCommentService.listByContest(contestId, tenantId); - return Result.success(result); - } - - @GetMapping("/common") - @Operation(summary = "查询通用评语列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listCommon( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = presetCommentService.listCommon(tenantId); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java deleted file mode 100644 index e55a9d0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestRegistrationController.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.registration.*; -import com.lesingle.creation.service.ContestRegistrationService; -import com.lesingle.creation.vo.registration.RegistrationStatsVO; -import com.lesingle.creation.vo.registration.RegistrationVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 竞赛报名管理控制器 - */ -@Tag(name = "竞赛报名管理") -@RestController -@RequestMapping("/api/contests/registrations") -@RequiredArgsConstructor -public class ContestRegistrationController { - - private final ContestRegistrationService registrationService; - - @PostMapping - @Operation(summary = "创建报名") - @PreAuthorize("hasAuthority('contest:register')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateRegistrationDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - RegistrationVO result = registrationService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping("/stats") - @Operation(summary = "报名统计") - @PreAuthorize("hasAuthority('contest:read')") - public Result getStats(@RequestParam(required = false) Long contestId) { - RegistrationStatsVO result = registrationService.getStats(contestId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "分页查询报名列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute RegistrationQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = registrationService.pageQuery(queryDTO, tenantId); - return Result.success(result); - } - - @GetMapping("/my/{contestId}") - @Operation(summary = "获取用户在某活动中的报名记录") - @PreAuthorize("hasAuthority('contest:read')") - public Result getMyRegistration( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId) { - Long userId = userPrincipal.getUserId(); - RegistrationVO result = registrationService.getMyRegistration(contestId, userId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取报名详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - RegistrationVO result = registrationService.getDetail(id, tenantId); - return Result.success(result); - } - - @PatchMapping("/{id}/review") - @Operation(summary = "审核报名") - @PreAuthorize("hasAuthority('contest:update')") - public Result review( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated ReviewRegistrationDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - RegistrationVO result = registrationService.review(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @PostMapping("/{id}/teachers") - @Operation(summary = "添加指导老师") - @PreAuthorize("hasAuthority('contest:update')") - public Result addTeacher( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated AddTeacherDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long operatorId = userPrincipal.getUserId(); - RegistrationVO result = registrationService.addTeacher(id, dto.getTeacherUserId(), tenantId, operatorId); - return Result.success(result); - } - - @DeleteMapping("/{id}/teachers/{teacherUserId}") - @Operation(summary = "移除指导老师") - @PreAuthorize("hasAuthority('contest:update')") - public Result removeTeacher( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @PathVariable Long teacherUserId) { - Long tenantId = userPrincipal.getTenantId(); - registrationService.removeTeacher(id, teacherUserId, tenantId); - return Result.success(null); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除报名") - @PreAuthorize("hasAuthority('contest:update')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - registrationService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestResultController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestResultController.java deleted file mode 100644 index 26037b0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestResultController.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.result.CreateResultDTO; -import com.lesingle.creation.service.ContestResultService; -import com.lesingle.creation.vo.result.ResultVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛结果管理控制器 - */ -@Tag(name = "竞赛结果管理") -@RestController -@RequestMapping("/api/contests/results") -@RequiredArgsConstructor -public class ContestResultController { - - private final ContestResultService resultService; - - @PostMapping - @Operation(summary = "创建竞赛结果") - @PreAuthorize("hasAuthority('contest:result:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateResultDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - ResultVO result = resultService.create(dto, creatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新竞赛结果") - @PreAuthorize("hasAuthority('contest:result:update')") - public Result update( - @PathVariable Long id, - @RequestBody @Validated CreateResultDTO dto) { - ResultVO result = resultService.update(id, dto); - return Result.success(result); - } - - @PostMapping("/{id}/publish") - @Operation(summary = "发布竞赛结果") - @PreAuthorize("hasAuthority('contest:result:publish')") - public Result publish(@PathVariable Long id) { - ResultVO result = resultService.publish(id); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除竞赛结果") - @PreAuthorize("hasAuthority('contest:result:delete')") - public Result delete(@PathVariable Long id) { - resultService.delete(id); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取竞赛结果详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail(@PathVariable Long id) { - ResultVO result = resultService.getDetail(id); - return Result.success(result); - } - - @GetMapping("/contest/{contestId}") - @Operation(summary = "查询活动的竞赛结果列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listByContest(@PathVariable Long contestId) { - List result = resultService.listByContest(contestId); - return Result.success(result); - } - - @GetMapping("/contest/{contestId}/winners") - @Operation(summary = "查询获奖结果列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listWinners(@PathVariable Long contestId) { - List result = resultService.listWinners(contestId); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestReviewController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestReviewController.java deleted file mode 100644 index 8cc8136..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestReviewController.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.review.*; -import com.lesingle.creation.service.ContestReviewService; -import com.lesingle.creation.vo.review.ReviewAssignmentVO; -import com.lesingle.creation.vo.review.ReviewStatsVO; -import com.lesingle.creation.vo.review.WorkScoreVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛评审管理控制器 - */ -@Tag(name = "竞赛评审管理") -@RestController -@RequestMapping("/api/contests/reviews") -@RequiredArgsConstructor -public class ContestReviewController { - - private final ContestReviewService reviewService; - - @PostMapping("/assign") - @Operation(summary = "分配作品给评委") - @PreAuthorize("hasAuthority('contest:review:assign')") - public Result> assignWork( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam Long contestId, - @RequestBody @Validated AssignWorkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - List result = reviewService.assignWork(contestId, dto, tenantId); - return Result.success(result); - } - - @PostMapping("/batch-assign") - @Operation(summary = "批量分配作品") - @PreAuthorize("hasAuthority('contest:review:assign')") - public Result> batchAssign( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated BatchAssignDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - List result = reviewService.batchAssign(dto, tenantId); - return Result.success(result); - } - - @PostMapping("/score") - @Operation(summary = "评分") - @PreAuthorize("hasAuthority('contest:review:score')") - public Result score( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateScoreDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long judgeId = userPrincipal.getUserId(); - WorkScoreVO result = reviewService.score(dto, judgeId, tenantId); - return Result.success(result); - } - - @PutMapping("/score/{scoreId}") - @Operation(summary = "更新评分") - @PreAuthorize("hasAuthority('contest:review:score')") - public Result updateScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long scoreId, - @RequestBody @Validated CreateScoreDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - WorkScoreVO result = reviewService.updateScore(scoreId, dto, tenantId); - return Result.success(result); - } - - @GetMapping("/assignments/page") - @Operation(summary = "分页查询评审分配列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute ReviewAssignmentQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = reviewService.pageQuery(queryDTO, tenantId); - return Result.success(result); - } - - @GetMapping("/my-assignments") - @Operation(summary = "获取评委待评审作品列表") - @PreAuthorize("hasAuthority('contest:review:score')") - public Result> getMyAssignments( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long judgeId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - List result = reviewService.getMyAssignments(judgeId, tenantId); - return Result.success(result); - } - - @GetMapping("/stats") - @Operation(summary = "评审统计") - @PreAuthorize("hasAuthority('contest:read')") - public Result getStats(@RequestParam(required = false) Long contestId) { - ReviewStatsVO result = reviewService.getStats(contestId); - return Result.success(result); - } - - @GetMapping("/works/{workId}/scores") - @Operation(summary = "获取作品的评分列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> getWorkScores( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long workId) { - Long tenantId = userPrincipal.getTenantId(); - List result = reviewService.getWorkScores(workId, tenantId); - return Result.success(result); - } - - @GetMapping("/works/{workId}/average-score") - @Operation(summary = "获取作品的平均分") - @PreAuthorize("hasAuthority('contest:read')") - public Result getAverageScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long workId) { - Long tenantId = userPrincipal.getTenantId(); - java.math.BigDecimal result = reviewService.getAverageScore(workId, tenantId); - return Result.success(result); - } - - @PostMapping("/auto-assign") - @Operation(summary = "自动分配作品给评委") - @PreAuthorize("hasAuthority('contest:review:assign')") - public Result autoAssign( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam Long contestId) { - Long tenantId = userPrincipal.getTenantId(); - String result = reviewService.autoAssign(contestId, tenantId); - return Result.success(result); - } - - @GetMapping("/progress/{contestId}") - @Operation(summary = "获取评审进度统计") - @PreAuthorize("hasAuthority('contest:read')") - public Result getReviewProgress( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId) { - Long tenantId = userPrincipal.getTenantId(); - com.lesingle.creation.vo.review.ReviewProgressVO result = - reviewService.getReviewProgress(contestId, tenantId); - return Result.success(result); - } - - @GetMapping("/work-status/{contestId}") - @Operation(summary = "获取作品状态统计") - @PreAuthorize("hasAuthority('contest:read')") - public Result getWorkStatusStats( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId) { - Long tenantId = userPrincipal.getTenantId(); - com.lesingle.creation.vo.review.WorkStatusStatsVO result = - reviewService.getWorkStatusStats(contestId, tenantId); - return Result.success(result); - } - - @GetMapping("/works/{workId}/final-score") - @Operation(summary = "获取作品的最终得分") - @PreAuthorize("hasAuthority('contest:read')") - public Result getFinalScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long workId) { - Long tenantId = userPrincipal.getTenantId(); - com.lesingle.creation.vo.review.FinalScoreVO result = - reviewService.getFinalScore(workId, tenantId); - return Result.success(result); - } - - @PostMapping("/replace-judge") - @Operation(summary = "替换评委") - @PreAuthorize("hasAuthority('contest:review:assign')") - public Result replaceJudge( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam Long assignmentId, - @RequestParam Long newJudgeId) { - Long tenantId = userPrincipal.getTenantId(); - reviewService.replaceJudge(assignmentId, newJudgeId, tenantId); - return Result.success(null); - } - - @GetMapping("/judge/contests") - @Operation(summary = "获取评委参与的活动列表") - public Result> getJudgeContests( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long judgeId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - java.util.List result = - reviewService.getJudgeContests(judgeId, tenantId); - return Result.success(result); - } - - @GetMapping("/judge/contests/{contestId}/works") - @Operation(summary = "获取评委在某个活动下的作品列表") - public Result> - getJudgeContestWorks( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId, - @ModelAttribute com.lesingle.creation.dto.review.JudgeWorkQueryDTO queryDTO) { - Long judgeId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - reviewService.getJudgeContestWorks(contestId, judgeId, tenantId, queryDTO); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestReviewRuleController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestReviewRuleController.java deleted file mode 100644 index 5b6eaeb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestReviewRuleController.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.reviewrule.CreateReviewDimensionDTO; -import com.lesingle.creation.dto.reviewrule.CreateReviewRuleDTO; -import com.lesingle.creation.service.ContestReviewRuleService; -import com.lesingle.creation.vo.reviewrule.ReviewRuleVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛评审规则管理控制器 - */ -@Tag(name = "竞赛评审规则管理") -@RestController -@RequestMapping("/api/contests/review-rules") -@RequiredArgsConstructor -public class ContestReviewRuleController { - - private final ContestReviewRuleService reviewRuleService; - - @PostMapping - @Operation(summary = "创建评审规则") - @PreAuthorize("hasAuthority('contest:review-rule:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateReviewRuleDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - ReviewRuleVO result = reviewRuleService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除评审规则") - @PreAuthorize("hasAuthority('contest:review-rule:delete')") - public Result delete(@PathVariable Long id) { - reviewRuleService.delete(id); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取评审规则详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail(@PathVariable Long id) { - ReviewRuleVO result = reviewRuleService.getDetail(id); - return Result.success(result); - } - - @GetMapping("/list") - @Operation(summary = "查询评审规则列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = reviewRuleService.list(tenantId); - return Result.success(result); - } - - @GetMapping("/select") - @Operation(summary = "获取可选的评审规则") - public Result> listForSelect( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = reviewRuleService.listForSelect(tenantId); - return Result.success(result); - } - - @PostMapping("/dimensions") - @Operation(summary = "添加评审维度") - @PreAuthorize("hasAuthority('contest:review-rule:update')") - public Result addDimension(@RequestBody @Validated CreateReviewDimensionDTO dto) { - ReviewRuleVO result = reviewRuleService.addDimension(dto); - return Result.success(result); - } - - @DeleteMapping("/dimensions/{id}") - @Operation(summary = "删除评审维度") - @PreAuthorize("hasAuthority('contest:review-rule:update')") - public Result deleteDimension(@PathVariable Long id) { - reviewRuleService.deleteDimension(id); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestTeamController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestTeamController.java deleted file mode 100644 index 5ef5a32..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestTeamController.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.team.*; -import com.lesingle.creation.service.ContestTeamService; -import com.lesingle.creation.vo.team.TeamVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛团队管理控制器 - */ -@Tag(name = "竞赛团队管理") -@RestController -@RequestMapping("/api/contests/teams") -@RequiredArgsConstructor -public class ContestTeamController { - - private final ContestTeamService teamService; - - @PostMapping - @Operation(summary = "创建团队") - @PreAuthorize("hasAuthority('contest:team:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateTeamDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - TeamVO result = teamService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新团队") - @PreAuthorize("hasAuthority('contest:team:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateTeamDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - TeamVO result = teamService.update(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除团队") - @PreAuthorize("hasAuthority('contest:team:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - teamService.delete(id, tenantId); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取团队详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - TeamVO result = teamService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/list") - @Operation(summary = "查询团队列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) Long contestId) { - Long tenantId = userPrincipal.getTenantId(); - List result = teamService.list(contestId, tenantId); - return Result.success(result); - } - - @GetMapping("/contest/{contestId}") - @Operation(summary = "按竞赛查询团队列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listByContest( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId) { - Long tenantId = userPrincipal.getTenantId(); - List result = teamService.listByContest(contestId, tenantId); - return Result.success(result); - } - - @GetMapping("/my/{contestId}") - @Operation(summary = "获取用户在某活动中的团队") - @PreAuthorize("hasAuthority('contest:read')") - public Result getMyTeam( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long contestId) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - TeamVO result = teamService.getMyTeam(contestId, userId, tenantId); - return result != null ? Result.success(result) : Result.success(null); - } - - @PostMapping("/{id}/members") - @Operation(summary = "邀请成员") - @PreAuthorize("hasAuthority('contest:team:update')") - public Result inviteMember( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated InviteMemberDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - teamService.inviteMember(id, dto, tenantId, creatorId); - return Result.success(null); - } - - @DeleteMapping("/{id}/members/{userId}") - @Operation(summary = "移除成员") - @PreAuthorize("hasAuthority('contest:team:update')") - public Result removeMember( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @PathVariable Long userId) { - Long tenantId = userPrincipal.getTenantId(); - teamService.removeMember(id, userId, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/ContestWorkController.java b/java-backend/src/main/java/com/lesingle/creation/controller/ContestWorkController.java deleted file mode 100644 index 05fd96b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/ContestWorkController.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.work.SubmitWorkDTO; -import com.lesingle.creation.dto.work.WorkQueryDTO; -import com.lesingle.creation.service.ContestWorkService; -import com.lesingle.creation.vo.work.WorkStatsVO; -import com.lesingle.creation.vo.work.WorkVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 竞赛作品管理控制器 - */ -@Tag(name = "竞赛作品管理") -@RestController -@RequestMapping("/api/contests/works") -@RequiredArgsConstructor -public class ContestWorkController { - - private final ContestWorkService workService; - - @PostMapping - @Operation(summary = "提交作品") - @PreAuthorize("hasAuthority('contest:work:submit')") - public Result submit( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated SubmitWorkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long submitterUserId = userPrincipal.getUserId(); - WorkVO result = workService.submit(dto, tenantId, submitterUserId); - return Result.success(result); - } - - @GetMapping("/stats") - @Operation(summary = "作品统计") - @PreAuthorize("hasAuthority('contest:read')") - public Result getStats(@RequestParam(required = false) Long contestId) { - WorkStatsVO result = workService.getStats(contestId); - return Result.success(result); - } - - @GetMapping("/page") - @Operation(summary = "分页查询作品列表") - @PreAuthorize("hasAuthority('contest:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute WorkQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = workService.pageQuery(queryDTO, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取作品详情") - @PreAuthorize("hasAuthority('contest:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - WorkVO result = workService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}/return") - @Operation(summary = "退回作品") - @PreAuthorize("hasAuthority('contest:work:update')") - public Result returnWork( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestParam String reason) { - Long tenantId = userPrincipal.getTenantId(); - WorkVO result = workService.returnWork(id, tenantId, reason); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除作品") - @PreAuthorize("hasAuthority('contest:work:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - workService.delete(id, tenantId); - return Result.success(null); - } - - @GetMapping("/registration/{registrationId}") - @Operation(summary = "查询某报名的所有作品") - @PreAuthorize("hasAuthority('contest:read')") - public Result> listByRegistration( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long registrationId) { - Long tenantId = userPrincipal.getTenantId(); - List result = workService.listByRegistration(registrationId, tenantId); - return Result.success(result); - } - - @GetMapping("/registration/{registrationId}/versions") - @Operation(summary = "查询某报名的所有作品版本") - @PreAuthorize("hasAuthority('contest:read')") - public Result> getVersionsByRegistration( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long registrationId) { - Long tenantId = userPrincipal.getTenantId(); - List result = workService.getVersionsByRegistration(registrationId, tenantId); - return Result.success(result); - } - - @GetMapping("/guided") - @Operation(summary = "查询教师指导的作品列表") - public Result> getGuidedWorks( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute WorkQueryDTO queryDTO) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - Page result = workService.getGuidedWorks(queryDTO, userId, tenantId); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java b/java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java deleted file mode 100644 index 1541320..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/DepartmentController.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.department.CreateDepartmentDTO; -import com.lesingle.creation.dto.department.UpdateDepartmentDTO; -import com.lesingle.creation.service.DepartmentService; -import com.lesingle.creation.vo.department.DepartmentVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 部门管理控制器 - */ -@Tag(name = "部门管理", description = "部门 CRUD 和树形结构接口") -@RestController -@RequestMapping("/api/departments") -@RequiredArgsConstructor -public class DepartmentController { - - private final DepartmentService departmentService; - - @PostMapping - @Operation(summary = "创建部门") - @PreAuthorize("hasAuthority('department:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateDepartmentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - DepartmentVO result = departmentService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "查询部门列表") - @PreAuthorize("hasAuthority('department:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) Long parentId) { - Long tenantId = userPrincipal.getTenantId(); - List result = departmentService.list(tenantId, parentId); - return Result.success(result); - } - - @GetMapping("/tree") - @Operation(summary = "查询部门树形结构") - @PreAuthorize("hasAuthority('department:read')") - public Result> tree( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = departmentService.tree(tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取部门详情") - @PreAuthorize("hasAuthority('department:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - DepartmentVO result = departmentService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新部门") - @PreAuthorize("hasAuthority('department:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateDepartmentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - DepartmentVO result = departmentService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除部门") - @PreAuthorize("hasAuthority('department:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - departmentService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/DictController.java b/java-backend/src/main/java/com/lesingle/creation/controller/DictController.java deleted file mode 100644 index 5172a03..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/DictController.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.dict.CreateDictDTO; -import com.lesingle.creation.dto.dict.UpdateDictDTO; -import com.lesingle.creation.service.DictService; -import com.lesingle.creation.vo.dict.DictDetailVO; -import com.lesingle.creation.vo.dict.DictListVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 字典管理控制器 - */ -@Tag(name = "字典管理") -@RestController -@RequestMapping("/api/dict") -@RequiredArgsConstructor -public class DictController { - - private final DictService dictService; - - @PostMapping - @Operation(summary = "创建字典") - @PreAuthorize("hasAuthority('dict:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateDictDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long operatorId = userPrincipal.getUserId(); - DictDetailVO result = dictService.create(dto, tenantId, operatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "字典列表") - @PreAuthorize("hasAuthority('dict:read')") - public Result> pageList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int pageSize) { - Long tenantId = userPrincipal.getTenantId(); - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - dictService.pageList(tenantId, page, pageSize); - return Result.success(result); - } - - @GetMapping("/code/{code}") - @Operation(summary = "根据编码查询字典") - @PreAuthorize("hasAuthority('dict:read')") - public Result getByCode( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable String code) { - Long tenantId = userPrincipal.getTenantId(); - DictDetailVO result = dictService.getByCode(code, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "字典详情") - @PreAuthorize("hasAuthority('dict:read')") - public Result detail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - DictDetailVO result = dictService.detail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新字典") - @PreAuthorize("hasAuthority('dict:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateDictDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - DictDetailVO result = dictService.update(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除字典") - @PreAuthorize("hasAuthority('dict:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - dictService.delete(id, tenantId); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java b/java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java deleted file mode 100644 index 6bdacac..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/GradeController.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.grade.CreateGradeDTO; -import com.lesingle.creation.dto.grade.UpdateGradeDTO; -import com.lesingle.creation.service.GradeService; -import com.lesingle.creation.vo.grade.GradeVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -/** - * 年级管理控制器 - */ -@Tag(name = "年级管理", description = "年级 CRUD 接口") -@RestController -@RequestMapping("/api/grades") -@RequiredArgsConstructor -public class GradeController { - - private final GradeService gradeService; - - @PostMapping - @Operation(summary = "创建年级") - @PreAuthorize("hasAuthority('grade:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateGradeDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - GradeVO result = gradeService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "分页查询年级列表") - @PreAuthorize("hasAuthority('grade:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false, defaultValue = "1") Integer pageNum, - @RequestParam(required = false, defaultValue = "10") Integer pageSize) { - Long tenantId = userPrincipal.getTenantId(); - Page result = gradeService.pageQuery(pageNum, pageSize, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取年级详情") - @PreAuthorize("hasAuthority('grade:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - GradeVO result = gradeService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新年级") - @PreAuthorize("hasAuthority('grade:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateGradeDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - GradeVO result = gradeService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除年级") - @PreAuthorize("hasAuthority('grade:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - gradeService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java b/java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java deleted file mode 100644 index 89d1e8d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/HomeworkController.java +++ /dev/null @@ -1,290 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.dto.homework.*; -import com.lesingle.creation.vo.school.ClassTreeNodeVO; -import com.lesingle.creation.service.HomeworkService; -import com.lesingle.creation.vo.homework.HomeworkDetailVO; -import com.lesingle.creation.vo.homework.HomeworkListVO; -import com.lesingle.creation.vo.homework.ReviewRuleVO; -import com.lesingle.creation.vo.homework.SubmissionVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import com.lesingle.creation.common.security.UserPrincipal; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 作业管理控制器 - */ -@Tag(name = "作业管理") -@RestController -@RequestMapping("/api/homeworks") -@RequiredArgsConstructor -public class HomeworkController { - - private final HomeworkService homeworkService; - - @PostMapping - @Operation(summary = "创建作业") - @PreAuthorize("hasAuthority('homework:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - HomeworkDetailVO result = homeworkService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新作业") - @PreAuthorize("hasAuthority('homework:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.update(id, dto, tenantId); - return Result.success(result); - } - - @PostMapping("/{id}/publish") - @Operation(summary = "发布作业") - @PreAuthorize("hasAuthority('homework:publish')") - public Result publish( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.publish(id, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除作业") - @PreAuthorize("hasAuthority('homework:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.delete(id, tenantId); - return Result.success(null); - } - - @GetMapping("/{id}") - @Operation(summary = "获取作业详情") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/page") - @Operation(summary = "分页查询作业列表") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute HomeworkQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = homeworkService.pageQuery(queryDTO, tenantId); - return Result.success(result); - } - - @PostMapping("/submit") - @Operation(summary = "提交作业") - public Result submit( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated SubmitHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long studentId = userPrincipal.getUserId(); - SubmissionVO result = homeworkService.submit(dto, tenantId, studentId); - return Result.success(result); - } - - @PostMapping("/review") - @Operation(summary = "批改作业") - @PreAuthorize("hasAuthority('homework:review')") - public Result review( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated ReviewHomeworkDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long reviewerId = userPrincipal.getUserId(); - SubmissionVO result = homeworkService.review(dto, tenantId, reviewerId); - return Result.success(result); - } - - @GetMapping("/{homeworkId}/submissions") - @Operation(summary = "获取作业提交列表") - @PreAuthorize("hasAuthority('homework:review')") - public Result> getSubmissions( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long homeworkId) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getSubmissions(homeworkId, tenantId); - return Result.success(result); - } - - @PostMapping("/review-rules") - @Operation(summary = "创建评审规则") - @PreAuthorize("hasAuthority('homework:review-rule:create')") - public Result createReviewRule( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam String ruleName, - @RequestParam(required = false, defaultValue = "custom") String ruleType, - @RequestParam(required = false) java.math.BigDecimal totalScore, - @RequestParam(required = false) String description) { - Long tenantId = userPrincipal.getTenantId(); - ReviewRuleVO result = homeworkService.createReviewRule( - ruleName, ruleType, totalScore, description, tenantId); - return Result.success(result); - } - - @GetMapping("/review-rules") - @Operation(summary = "获取评审规则列表") - public Result> getReviewRules( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getReviewRules(tenantId); - return Result.success(result); - } - - @GetMapping("/review-rules/select") - @Operation(summary = "获取可选的评审规则") - public Result> getReviewRulesForSelect( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getReviewRulesForSelect(tenantId); - return Result.success(result); - } - - @PutMapping("/review-rules/{id}") - @Operation(summary = "更新评审规则") - @PreAuthorize("hasAuthority('homework:review-rule:update')") - public Result updateReviewRule( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateReviewRuleDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - ReviewRuleVO result = homeworkService.updateReviewRule(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/review-rules/{id}") - @Operation(summary = "删除评审规则") - @PreAuthorize("hasAuthority('homework:review-rule:delete')") - public Result deleteReviewRule( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.deleteReviewRule(id, tenantId); - return Result.success(null); - } - - @GetMapping("/my") - @Operation(summary = "我的作业列表(学生端)") - public Result> getMyHomeworks( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute HomeworkQueryDTO queryDTO) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - Page result = homeworkService.getMyHomeworks(queryDTO, userId, tenantId); - return Result.success(result); - } - - @PostMapping("/{id}/unpublish") - @Operation(summary = "取消发布作业") - @PreAuthorize("hasAuthority('homework:publish')") - public Result unpublish( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - HomeworkDetailVO result = homeworkService.unpublish(id, tenantId); - return Result.success(result); - } - - @GetMapping("/submissions") - @Operation(summary = "获取提交记录列表") - @PreAuthorize("hasAuthority('homework:review')") - public Result> getSubmissionsList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute SubmissionQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = homeworkService.getSubmissionsList(queryDTO, tenantId); - return Result.success(result); - } - - @GetMapping("/submissions/{id}") - @Operation(summary = "获取提交记录详情") - @PreAuthorize("hasAuthority('homework:review')") - public Result getSubmissionDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - SubmissionVO result = homeworkService.getSubmissionDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/submissions/class-tree") - @Operation(summary = "获取班级树结构") - @PreAuthorize("hasAuthority('homework:review')") - public Result> getClassTree( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = homeworkService.getClassTree(tenantId); - return Result.success(result); - } - - @GetMapping("/submissions/my/{homeworkId}") - @Operation(summary = "获取我的提交记录") - public Result getMySubmission( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long homeworkId) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - SubmissionVO result = homeworkService.getMySubmission(homeworkId, userId, tenantId); - return result != null ? Result.success(result) : Result.success(null); - } - - @PostMapping("/scores") - @Operation(summary = "提交评分") - @PreAuthorize("hasAuthority('homework:review')") - public Result createScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateScoreDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long reviewerId = userPrincipal.getUserId(); - SubmissionVO result = homeworkService.createScore(dto, tenantId, reviewerId); - return Result.success(result); - } - - @PostMapping("/scores/{submissionId}/violation") - @Operation(summary = "标记作品违规") - @PreAuthorize("hasAuthority('homework:review')") - public Result markViolation( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long submissionId, - @RequestParam(required = false) String reason) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.markViolation(submissionId, reason, tenantId); - return Result.success(null); - } - - @PostMapping("/scores/{submissionId}/reset") - @Operation(summary = "重置评分") - @PreAuthorize("hasAuthority('homework:review')") - public Result resetScore( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long submissionId) { - Long tenantId = userPrincipal.getTenantId(); - homeworkService.resetScore(submissionId, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/MenuController.java b/java-backend/src/main/java/com/lesingle/creation/controller/MenuController.java deleted file mode 100644 index b65efe3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/MenuController.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.menu.CreateMenuDTO; -import com.lesingle.creation.dto.menu.UpdateMenuDTO; -import com.lesingle.creation.service.MenuService; -import com.lesingle.creation.vo.menu.MenuDetailVO; -import com.lesingle.creation.vo.menu.MenuTreeVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 菜单管理控制器 - */ -@Tag(name = "菜单管理") -@RestController -@RequestMapping("/api/menus") -@RequiredArgsConstructor -public class MenuController { - - private final MenuService menuService; - - @PostMapping - @Operation(summary = "创建菜单") - @PreAuthorize("hasAuthority('menu:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateMenuDTO dto) { - Long operatorId = userPrincipal.getUserId(); - MenuDetailVO result = menuService.create(dto, operatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "菜单树") - @PreAuthorize("hasAuthority('menu:read')") - public Result> tree() { - List result = menuService.tree(); - return Result.success(result); - } - - @GetMapping("/user-menus") - @Operation(summary = "当前用户菜单") - @PreAuthorize("hasAuthority('menu:read')") - public Result> userMenus( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long userId = userPrincipal.getUserId(); - Long tenantId = userPrincipal.getTenantId(); - List result = menuService.getUserMenus(userId, tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "菜单详情") - @PreAuthorize("hasAuthority('menu:read')") - public Result detail(@PathVariable Long id) { - MenuDetailVO result = menuService.detail(id); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新菜单") - @PreAuthorize("hasAuthority('menu:update')") - public Result update( - @PathVariable Long id, - @RequestBody @Validated UpdateMenuDTO dto) { - MenuDetailVO result = menuService.update(id, dto); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除菜单") - @PreAuthorize("hasAuthority('menu:delete')") - public Result delete(@PathVariable Long id) { - menuService.delete(id); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/PermissionController.java b/java-backend/src/main/java/com/lesingle/creation/controller/PermissionController.java deleted file mode 100644 index 45f2c29..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/PermissionController.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.permission.CreatePermissionDTO; -import com.lesingle.creation.dto.permission.UpdatePermissionDTO; -import com.lesingle.creation.service.PermissionService; -import com.lesingle.creation.vo.permission.PermissionDetailVO; -import com.lesingle.creation.vo.permission.PermissionListVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 权限管理控制器 - */ -@Tag(name = "权限管理") -@RestController -@RequestMapping("/api/permissions") -@RequiredArgsConstructor -public class PermissionController { - - private final PermissionService permissionService; - - @PostMapping - @Operation(summary = "创建权限") - @PreAuthorize("hasAuthority('super_admin')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreatePermissionDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long operatorId = userPrincipal.getUserId(); - PermissionDetailVO result = permissionService.create(dto, tenantId, operatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "权限列表") - @PreAuthorize("hasAuthority('permission:read')") - public Result> pageList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int pageSize) { - Long tenantId = userPrincipal.getTenantId(); - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - permissionService.pageList(tenantId, page, pageSize); - return Result.success(result); - } - - @GetMapping("/all") - @Operation(summary = "所有权限列表") - @PreAuthorize("hasAuthority('permission:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = permissionService.list(tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "权限详情") - @PreAuthorize("hasAuthority('permission:read')") - public Result detail(@PathVariable Long id) { - PermissionDetailVO result = permissionService.detail(id); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新权限") - @PreAuthorize("hasAuthority('super_admin')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdatePermissionDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - PermissionDetailVO result = permissionService.update(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除权限") - @PreAuthorize("hasAuthority('super_admin')") - public Result delete( - @PathVariable Long id) { - permissionService.delete(id); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/PublicController.java b/java-backend/src/main/java/com/lesingle/creation/controller/PublicController.java deleted file mode 100644 index 0a538c2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/PublicController.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.child.CreateChildDTO; -import com.lesingle.creation.dto.child.UpdateChildDTO; -import com.lesingle.creation.dto.publicuser.PublicLoginDTO; -import com.lesingle.creation.dto.publicuser.PublicRegisterDTO; -import com.lesingle.creation.dto.publicuser.PublicUserUpdateDTO; -import com.lesingle.creation.service.PublicService; -import com.lesingle.creation.vo.child.ChildVO; -import com.lesingle.creation.vo.publicuser.PublicUserVO; -import com.lesingle.creation.vo.publicuser.LoginResponseVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 公共接口控制器 - * 提供公众用户注册、登录、个人信息、子女管理等功能 - */ -@Tag(name = "公共接口", description = "公众用户相关接口") -@RestController -@RequestMapping("/api/public") -@RequiredArgsConstructor -public class PublicController { - - private final PublicService publicService; - - // ==================== 注册 & 登录(公开接口) ==================== - - @PostMapping("/auth/register") - @Operation(summary = "用户注册") - public Result register(@RequestBody @Valid PublicRegisterDTO dto) { - return Result.success(publicService.register(dto)); - } - - @PostMapping("/auth/login") - @Operation(summary = "用户登录") - public Result login(@RequestBody @Valid PublicLoginDTO dto) { - return Result.success(publicService.login(dto)); - } - - // ==================== 个人信息(需要登录) ==================== - - @GetMapping("/mine/profile") - @Operation(summary = "获取个人信息") - public Result getProfile(@AuthenticationPrincipal UserPrincipal userPrincipal) { - - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.getUserInfo(userId)); - } - - @PutMapping("/mine/profile") - @Operation(summary = "更新个人信息") - public Result updateProfile( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody PublicUserUpdateDTO dto) { - - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.updateProfile(userId, dto)); - } - - // ==================== 子女管理(需要登录) ==================== - - @GetMapping("/mine/children") - @Operation(summary = "获取子女列表") - public Result> getChildren(@AuthenticationPrincipal UserPrincipal userPrincipal) { - - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.getChildren(userId)); - } - - @PostMapping("/mine/children") - @Operation(summary = "创建子女") - public Result createChild( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateChildDTO dto) { - - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.createChild(userId, dto)); - } - - @GetMapping("/mine/children/{id}") - @Operation(summary = "获取子女详情") - public Result getChild( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.getChild(userId, id)); - } - - @PutMapping("/mine/children/{id}") - @Operation(summary = "更新子女信息") - public Result updateChild( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody UpdateChildDTO dto) { - - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.updateChild(userId, id, dto)); - } - - @DeleteMapping("/mine/children/{id}") - @Operation(summary = "删除子女") - public Result deleteChild( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long userId = userPrincipal.getUserId(); - publicService.deleteChild(userId, id); - return Result.success(null); - } - - // ==================== 子女独立账号管理 ==================== - - @PostMapping("/children/create-account") - @Operation(summary = "创建子女独立账号") - public Result createChildAccount( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateChildDTO dto) { - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.createChildAccount(userId, dto)); - } - - @GetMapping("/children/accounts") - @Operation(summary = "获取子女账号列表") - public Result> getChildAccounts(@AuthenticationPrincipal UserPrincipal userPrincipal) { - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.getChildAccounts(userId)); - } - - @PutMapping("/children/accounts/{id}") - @Operation(summary = "更新子女账号信息") - public Result updateChildAccount( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody UpdateChildDTO dto) { - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.updateChildAccount(userId, id, dto)); - } - - @GetMapping("/mine/parent-info") - @Operation(summary = "获取监护人信息") - public Result getParentInfo(@AuthenticationPrincipal UserPrincipal userPrincipal) { - Long userId = userPrincipal.getUserId(); - return Result.success(publicService.getParentInfo(userId)); - } - - // ==================== 活动浏览(公开接口) ==================== - - @GetMapping("/activities") - @Operation(summary = "获取活动列表") - public Result getActivities( - @RequestParam(defaultValue = "1") Integer page, - @RequestParam(defaultValue = "12") Integer pageSize, - @RequestParam(required = false) String keyword, - @RequestParam(required = false) String contestType, - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long userId = userPrincipal != null ? userPrincipal.getUserId() : null; - return Result.success(publicService.getPublicActivities(page, pageSize, keyword, contestType, userId)); - } - - @GetMapping("/activities/{id}") - @Operation(summary = "获取活动详情") - public Result getActivityDetail(@PathVariable Long id) { - return Result.success(publicService.getActivityDetail(id)); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/RoleController.java b/java-backend/src/main/java/com/lesingle/creation/controller/RoleController.java deleted file mode 100644 index d5ed49e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/RoleController.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.role.CreateRoleDTO; -import com.lesingle.creation.dto.role.UpdateRoleDTO; -import com.lesingle.creation.service.RoleService; -import com.lesingle.creation.vo.role.RoleDetailVO; -import com.lesingle.creation.vo.role.RoleListVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 角色管理控制器 - */ -@Tag(name = "角色管理") -@RestController -@RequestMapping("/api/roles") -@RequiredArgsConstructor -public class RoleController { - - private final RoleService roleService; - - @PostMapping - @Operation(summary = "创建角色") - @PreAuthorize("hasAuthority('role:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateRoleDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long operatorId = userPrincipal.getUserId(); - RoleDetailVO result = roleService.create(dto, tenantId, operatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "角色列表") - @PreAuthorize("hasAuthority('role:read')") - public Result> pageList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int pageSize) { - Long tenantId = userPrincipal.getTenantId(); - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - roleService.pageList(tenantId, page, pageSize); - return Result.success(result); - } - - @GetMapping("/all") - @Operation(summary = "所有角色列表") - @PreAuthorize("hasAuthority('role:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - List result = roleService.list(tenantId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "角色详情") - @PreAuthorize("hasAuthority('role:read')") - public Result detail(@PathVariable Long id) { - RoleDetailVO result = roleService.detail(id); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新角色") - @PreAuthorize("hasAuthority('role:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateRoleDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - RoleDetailVO result = roleService.update(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除角色") - @PreAuthorize("hasAuthority('role:delete')") - public Result delete( - @PathVariable Long id) { - roleService.delete(id); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java b/java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java deleted file mode 100644 index 28d4d13..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolClassController.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.schoolclass.CreateClassDTO; -import com.lesingle.creation.dto.schoolclass.UpdateClassDTO; -import com.lesingle.creation.service.SchoolClassService; -import com.lesingle.creation.vo.schoolclass.ClassVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -/** - * 班级管理控制器 - */ -@Tag(name = "班级管理", description = "班级 CRUD 接口") -@RestController -@RequestMapping("/api/classes") -@RequiredArgsConstructor -public class SchoolClassController { - - private final SchoolClassService schoolClassService; - - @PostMapping - @Operation(summary = "创建班级") - @PreAuthorize("hasAuthority('class:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateClassDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - ClassVO result = schoolClassService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "分页查询班级列表") - @PreAuthorize("hasAuthority('class:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false, defaultValue = "1") Integer pageNum, - @RequestParam(required = false, defaultValue = "10") Integer pageSize, - @RequestParam(required = false) Long gradeId, - @RequestParam(required = false) Integer type) { - Long tenantId = userPrincipal.getTenantId(); - Page result = schoolClassService.pageQuery(pageNum, pageSize, tenantId, gradeId, type); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取班级详情") - @PreAuthorize("hasAuthority('class:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - ClassVO result = schoolClassService.getDetail(id, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新班级") - @PreAuthorize("hasAuthority('class:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateClassDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - ClassVO result = schoolClassService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除班级") - @PreAuthorize("hasAuthority('class:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - schoolClassService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java b/java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java deleted file mode 100644 index 64d9929..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/SchoolController.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.school.CreateSchoolDTO; -import com.lesingle.creation.dto.school.UpdateSchoolDTO; -import com.lesingle.creation.service.SchoolService; -import com.lesingle.creation.vo.school.SchoolVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 学校管理控制器 - */ -@Tag(name = "学校管理") -@RestController -@RequestMapping("/api/schools") -@RequiredArgsConstructor -public class SchoolController { - - private final SchoolService schoolService; - - @PostMapping - @Operation(summary = "创建学校") - @PreAuthorize("hasAuthority('school:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateSchoolDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - SchoolVO result = schoolService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "获取学校信息") - @PreAuthorize("hasAuthority('school:read')") - public Result get( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - SchoolVO result = schoolService.getByTenantId(tenantId); - return Result.success(result); - } - - @PutMapping - @Operation(summary = "更新学校") - @PreAuthorize("hasAuthority('school:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated UpdateSchoolDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - SchoolVO result = schoolService.update(dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping - @Operation(summary = "删除学校") - @PreAuthorize("hasAuthority('school:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal) { - Long tenantId = userPrincipal.getTenantId(); - schoolService.delete(tenantId); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java b/java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java deleted file mode 100644 index 0c16edd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/StudentController.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.student.CreateStudentDTO; -import com.lesingle.creation.dto.student.UpdateStudentDTO; -import com.lesingle.creation.service.StudentService; -import com.lesingle.creation.vo.student.StudentVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 学生管理控制器 - */ -@Tag(name = "学生管理", description = "学生 CRUD 和查询接口") -@RestController -@RequestMapping("/api/students") -@RequiredArgsConstructor -public class StudentController { - - private final StudentService studentService; - - @PostMapping - @Operation(summary = "创建学生") - @PreAuthorize("hasAuthority('student:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateStudentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - StudentVO result = studentService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "查询学生列表") - @PreAuthorize("hasAuthority('student:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(defaultValue = "1") Integer page, - @RequestParam(defaultValue = "10") Integer pageSize, - @RequestParam(required = false) Long classId) { - Long tenantId = userPrincipal.getTenantId(); - List result = studentService.list(tenantId, page, pageSize, classId); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取学生详情") - @PreAuthorize("hasAuthority('student:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - StudentVO result = studentService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/user/{userId}") - @Operation(summary = "根据用户 ID 获取学生信息") - @PreAuthorize("hasAuthority('student:read')") - public Result getByUserId( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long userId) { - Long tenantId = userPrincipal.getTenantId(); - StudentVO result = studentService.getByUserId(userId, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新学生") - @PreAuthorize("hasAuthority('student:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateStudentDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - StudentVO result = studentService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除学生") - @PreAuthorize("hasAuthority('student:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - studentService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/SysLogController.java b/java-backend/src/main/java/com/lesingle/creation/controller/SysLogController.java deleted file mode 100644 index 3278e5b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/SysLogController.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.lesingle.creation.controller; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.log.LogQueryDTO; -import com.lesingle.creation.service.SysLogService; -import com.lesingle.creation.vo.log.LogStatisticsVO; -import com.lesingle.creation.vo.log.LogVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 系统日志控制器 - */ -@Tag(name = "系统日志", description = "日志查询、统计等接口") -@RestController -@RequestMapping("/api/sys-log") -@RequiredArgsConstructor -public class SysLogController { - - private final SysLogService sysLogService; - - @Operation(summary = "分页查询日志列表") - @GetMapping("/page") - @PreAuthorize("hasAuthority('log:read')") - public Result> pageQuery( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @ModelAttribute LogQueryDTO queryDTO) { - Long tenantId = userPrincipal.getTenantId(); - Page result = sysLogService.pageQuery(queryDTO, tenantId); - return Result.success(result); - } - - /** - * 获取日志详情 - */ - @Operation(summary = "获取日志详情") - @GetMapping("/{id}") - @PreAuthorize("hasAuthority('log:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - LogVO result = sysLogService.getDetail(id, tenantId); - return Result.success(result); - } - - /** - * 获取日志统计信息 - */ - @Operation(summary = "获取日志统计信息") - @GetMapping("/statistics") - @PreAuthorize("hasAuthority('log:read')") - public Result getStatistics( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false, defaultValue = "7") Integer days) { - Long tenantId = userPrincipal.getTenantId(); - LogStatisticsVO result = sysLogService.getStatistics(days, tenantId); - return Result.success(result); - } - - /** - * 批量删除日志 - */ - @Operation(summary = "批量删除日志") - @DeleteMapping - @PreAuthorize("hasAuthority('log:delete')") - public Result deleteByIds( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam("ids") List ids) { - Long tenantId = userPrincipal.getTenantId(); - int result = sysLogService.deleteByIds(ids, tenantId); - return Result.success(result); - } - - /** - * 清理过期日志 - */ - @Operation(summary = "清理过期日志") - @PostMapping("/clean") - @PreAuthorize("hasAuthority('log:delete')") - public Result cleanOldLogs( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) Integer days) { - Long tenantId = userPrincipal.getTenantId(); - int result = sysLogService.cleanOldLogs(days, tenantId); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java b/java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java deleted file mode 100644 index c83238d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/TeacherController.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.teacher.CreateTeacherDTO; -import com.lesingle.creation.dto.teacher.UpdateTeacherDTO; -import com.lesingle.creation.service.TeacherService; -import com.lesingle.creation.vo.teacher.TeacherVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 教师管理控制器 - */ -@Tag(name = "教师管理", description = "教师 CRUD 和查询接口") -@RestController -@RequestMapping("/api/teachers") -@RequiredArgsConstructor -public class TeacherController { - - private final TeacherService teacherService; - - @PostMapping - @Operation(summary = "创建教师") - @PreAuthorize("hasAuthority('teacher:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Valid CreateTeacherDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long creatorId = userPrincipal.getUserId(); - TeacherVO result = teacherService.create(dto, tenantId, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "查询教师列表") - @PreAuthorize("hasAuthority('teacher:read')") - public Result> list( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) Long departmentId, - @RequestParam(required = false) String nickname, - @RequestParam(required = false) String username) { - Long tenantId = userPrincipal.getTenantId(); - List result = teacherService.list(tenantId, departmentId, nickname, username); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "获取教师详情") - @PreAuthorize("hasAuthority('teacher:read')") - public Result getDetail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - TeacherVO result = teacherService.getDetail(id, tenantId); - return Result.success(result); - } - - @GetMapping("/user/{userId}") - @Operation(summary = "根据用户 ID 获取教师信息") - @PreAuthorize("hasAuthority('teacher:read')") - public Result getByUserId( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long userId) { - Long tenantId = userPrincipal.getTenantId(); - TeacherVO result = teacherService.getByUserId(userId, tenantId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新教师") - @PreAuthorize("hasAuthority('teacher:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Valid UpdateTeacherDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long modifierId = userPrincipal.getUserId(); - TeacherVO result = teacherService.update(id, dto, tenantId, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除教师") - @PreAuthorize("hasAuthority('teacher:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - teacherService.delete(id, tenantId); - return Result.success(null); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/TenantController.java b/java-backend/src/main/java/com/lesingle/creation/controller/TenantController.java deleted file mode 100644 index a30f863..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/TenantController.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.tenant.CreateTenantDTO; -import com.lesingle.creation.dto.tenant.UpdateTenantDTO; -import com.lesingle.creation.service.TenantService; -import com.lesingle.creation.vo.tenant.TenantDetailVO; -import com.lesingle.creation.vo.tenant.TenantListVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -/** - * 租户管理控制器 - */ -@Tag(name = "租户管理") -@RestController -@RequestMapping("/api/tenants") -@RequiredArgsConstructor -public class TenantController { - - private final TenantService tenantService; - - @PostMapping - @Operation(summary = "创建租户") - @PreAuthorize("hasAuthority('tenant:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateTenantDTO dto) { - Long creatorId = userPrincipal.getUserId(); - TenantDetailVO result = tenantService.create(dto, creatorId); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "租户列表") - @PreAuthorize("hasAuthority('tenant:read')") - public Result> pageList( - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int pageSize) { - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - tenantService.pageList(page, pageSize); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "租户详情") - @PreAuthorize("hasAuthority('tenant:read')") - public Result detail(@PathVariable Long id) { - TenantDetailVO result = tenantService.detail(id); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新租户") - @PreAuthorize("hasAuthority('tenant:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateTenantDTO dto) { - Long modifierId = userPrincipal.getUserId(); - TenantDetailVO result = tenantService.update(id, dto, modifierId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除租户") - @PreAuthorize("hasAuthority('tenant:delete')") - public Result delete(@PathVariable Long id) { - tenantService.delete(id); - return Result.success(); - } - - @GetMapping("/{id}/menus") - @Operation(summary = "获取租户菜单") - @PreAuthorize("hasAuthority('tenant:read')") - public Result> getTenantMenus(@PathVariable Long id) { - List result = tenantService.getTenantMenus(id); - return Result.success(result); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/UploadController.java b/java-backend/src/main/java/com/lesingle/creation/controller/UploadController.java deleted file mode 100644 index 4898e92..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/UploadController.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.common.util.OssUtil; -import com.lesingle.creation.vo.upload.UploadResponseVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - * 文件上传控制器 - */ -@Tag(name = "文件上传", description = "文件上传、删除等接口") -@Slf4j -@RestController -@RequestMapping("/api/upload") -@RequiredArgsConstructor -public class UploadController { - - private final OssUtil ossUtil; - - /** - * 上传文件 - */ - @Operation(summary = "上传文件") - @PostMapping - public Result uploadFile( - @RequestParam("file") MultipartFile file, - @AuthenticationPrincipal UserPrincipal userPrincipal) { - try { - if (file == null || file.isEmpty()) { - throw new BusinessException("请选择要上传的文件"); - } - - // 调用 OssUtil 上传文件 - String fileUrl = ossUtil.upload(file); - - // 构建响应 - UploadResponseVO response = new UploadResponseVO(); - response.setUrl(fileUrl); - response.setFileName(file.getOriginalFilename()); - response.setSize(file.getSize()); - - log.info("文件上传成功,文件名={}, 大小={}", file.getOriginalFilename(), file.getSize()); - - return Result.success(response); - - } catch (IOException e) { - log.error("文件上传失败", e); - throw new BusinessException("文件上传失败:" + e.getMessage()); - } - } - - /** - * 删除文件 - */ - @Operation(summary = "删除文件") - @DeleteMapping - public Result deleteFile(@RequestParam("url") String fileUrl) { - try { - ossUtil.delete(fileUrl); - return Result.success(null); - } catch (Exception e) { - log.error("文件删除失败", e); - throw new BusinessException("文件删除失败:" + e.getMessage()); - } - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/controller/UserController.java b/java-backend/src/main/java/com/lesingle/creation/controller/UserController.java deleted file mode 100644 index 1850301..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/controller/UserController.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.lesingle.creation.controller; - -import com.lesingle.creation.common.core.Result; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.dto.user.CreateUserDTO; -import com.lesingle.creation.dto.user.UpdateUserDTO; -import com.lesingle.creation.dto.user.UserQueryDTO; -import com.lesingle.creation.service.UserService; -import com.lesingle.creation.vo.user.UserDetailVO; -import com.lesingle.creation.vo.user.UserListVO; -import com.lesingle.creation.vo.user.UserStatsVO; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.RequiredArgsConstructor; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; - -/** - * 用户管理控制器 - */ -@Tag(name = "用户管理") -@RestController -@RequestMapping("/api/users") -@RequiredArgsConstructor -public class UserController { - - private final UserService userService; - - @PostMapping - @Operation(summary = "创建用户") - @PreAuthorize("hasAuthority('user:create')") - public Result create( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestBody @Validated CreateUserDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - Long operatorId = userPrincipal.getUserId(); - UserDetailVO result = userService.create(dto, tenantId, operatorId); - return Result.success(result); - } - - @GetMapping("/stats") - @Operation(summary = "用户统计(仅超管)") - @PreAuthorize("hasAuthority('super_admin')") - public Result getStats() { - UserStatsVO result = userService.getStats(); - return Result.success(result); - } - - @GetMapping - @Operation(summary = "用户列表") - @PreAuthorize("hasAuthority('user:read')") - public Result> pageList( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @RequestParam(required = false) String keyword, - @RequestParam(required = false) String userType, - @RequestParam(required = false) String userSource, - @RequestParam(required = false) String status, - @RequestParam(defaultValue = "1") int page, - @RequestParam(defaultValue = "10") int pageSize) { - Long tenantId = userPrincipal.getTenantId(); - boolean isSuperTenant = userPrincipal.isSuperTenant(); - - UserQueryDTO queryDTO = new UserQueryDTO(); - queryDTO.setKeyword(keyword); - queryDTO.setUserType(userType); - queryDTO.setUserSource(userSource); - queryDTO.setStatus(status); - queryDTO.setPage(page); - queryDTO.setPageSize(pageSize); - - com.baomidou.mybatisplus.extension.plugins.pagination.Page result = - userService.pageList(queryDTO, tenantId, isSuperTenant); - return Result.success(result); - } - - @GetMapping("/{id}") - @Operation(summary = "用户详情") - @PreAuthorize("hasAuthority('user:read')") - public Result detail( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - boolean isSuperTenant = userPrincipal.isSuperTenant(); - UserDetailVO result = userService.detail(id, tenantId, isSuperTenant); - return Result.success(result); - } - - @PatchMapping("/{id}/status") - @Operation(summary = "更新用户状态") - @PreAuthorize("hasAuthority('user:manage')") - public Result updateStatus( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestParam String status) { - Long operatorId = userPrincipal.getUserId(); - UserDetailVO result = userService.updateStatus(id, status, operatorId); - return Result.success(result); - } - - @PutMapping("/{id}") - @Operation(summary = "更新用户") - @PreAuthorize("hasAuthority('user:update')") - public Result update( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id, - @RequestBody @Validated UpdateUserDTO dto) { - Long tenantId = userPrincipal.getTenantId(); - UserDetailVO result = userService.update(id, dto, tenantId); - return Result.success(result); - } - - @DeleteMapping("/{id}") - @Operation(summary = "删除用户") - @PreAuthorize("hasAuthority('user:delete')") - public Result delete( - @AuthenticationPrincipal UserPrincipal userPrincipal, - @PathVariable Long id) { - Long tenantId = userPrincipal.getTenantId(); - userService.delete(id, tenantId); - return Result.success(); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/ai3d/AI3DTaskQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/ai3d/AI3DTaskQueryDTO.java deleted file mode 100644 index 52fb7d0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/ai3d/AI3DTaskQueryDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.dto.ai3d; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * AI 3D 任务查询 DTO - */ -@Data -@Schema(description = "AI 3D 任务查询参数") -public class AI3DTaskQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页数量", example = "10") - private Integer pageSize = 10; - - @Schema(description = "任务状态:pending/processing/completed/failed/timeout") - private String status; - - @Schema(description = "输入类型:text/image") - private String inputType; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/ai3d/CreateAI3DTaskDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/ai3d/CreateAI3DTaskDTO.java deleted file mode 100644 index 7d60519..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/ai3d/CreateAI3DTaskDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.ai3d; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -/** - * 创建 AI 3D 任务请求 DTO - */ -@Data -@Schema(description = "创建 AI 3D 任务请求") -public class CreateAI3DTaskDTO { - - @NotBlank(message = "输入内容不能为空") - @Schema(description = "输入类型:text/image", example = "text") - private String inputType; - - @NotBlank(message = "输入内容不能为空") - @Schema(description = "输入内容:文字描述或图片 URL", example = "一只可爱的小猫") - private String inputContent; - - @Schema(description = "生成类型:Normal/Geometry/LowPoly/Sketch", example = "Normal") - private String generateType = "Normal"; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/auth/LoginDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/auth/LoginDTO.java deleted file mode 100644 index 0fa01ad..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/auth/LoginDTO.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.lesingle.creation.dto.auth; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 登录请求 DTO - */ -@Data -@Schema(description = "登录请求") -public class LoginDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @Schema(description = "租户编码") - private String tenantCode; - - @Schema(description = "验证码") - private String captcha; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/child/CreateChildDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/child/CreateChildDTO.java deleted file mode 100644 index ce1a7d2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/child/CreateChildDTO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.dto.child; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 创建子女 DTO - */ -@Data -@Schema(description = "创建子女请求") -public class CreateChildDTO { - - @NotBlank(message = "子女用户名不能为空") - @Schema(description = "子女用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "性别:male/female") - private String gender; - - @Schema(description = "出生日期") - private LocalDate birthday; - - @Schema(description = "所在城市") - private String city; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "与监护人关系") - private String relationship; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/child/UpdateChildDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/child/UpdateChildDTO.java deleted file mode 100644 index 9821b7d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/child/UpdateChildDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.dto.child; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新子女 DTO - */ -@Data -@Schema(description = "更新子女请求") -public class UpdateChildDTO { - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "密码") - private String password; - - @Schema(description = "性别:male/female") - private String gender; - - @Schema(description = "出生日期") - private LocalDate birthday; - - @Schema(description = "所在城市") - private String city; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "管控模式:full/control/free") - private String controlMode; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/config/CreateConfigDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/config/CreateConfigDTO.java deleted file mode 100644 index 86a7693..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/config/CreateConfigDTO.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.lesingle.creation.dto.config; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 创建配置 DTO - */ -@Data -@Schema(description = "创建配置请求") -public class CreateConfigDTO { - - @NotBlank(message = "配置键不能为空") - @Schema(description = "配置键", example = "system.title") - private String configKey; - - @NotBlank(message = "配置值不能为空") - @Schema(description = "配置值", example = "图书馆创作平台") - private String configValue; - - @Schema(description = "配置名称", example = "系统标题") - private String configName; - - @Schema(description = "配置描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/config/UpdateConfigDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/config/UpdateConfigDTO.java deleted file mode 100644 index 2eb1881..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/config/UpdateConfigDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.lesingle.creation.dto.config; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新配置 DTO - */ -@Data -@Schema(description = "更新配置请求") -public class UpdateConfigDTO { - - @Schema(description = "配置值") - private String configValue; - - @Schema(description = "配置名称") - private String configName; - - @Schema(description = "配置描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/contest/ContestQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/contest/ContestQueryDTO.java deleted file mode 100644 index 41b306a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/contest/ContestQueryDTO.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.lesingle.creation.dto.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 竞赛查询 DTO - */ -@Data -@Schema(description = "竞赛查询参数") -public class ContestQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer page = 1; - - @Schema(description = "每页大小", example = "10") - private Integer pageSize = 10; - - @Schema(description = "竞赛名称关键字") - private String contestName; - - @Schema(description = "竞赛状态:unpublished/published", example = "published") - private String contestState; - - @Schema(description = "竞赛类型:individual/team", example = "individual") - private String contestType; - - @Schema(description = "可见范围:public/designated/internal", example = "designated") - private String visibility; - - @Schema(description = "进度状态:ongoing/finished", example = "ongoing") - private String status; - - @Schema(description = "阶段:unpublished/registering/submitting/reviewing/finished", example = "registering") - private String stage; - - @Schema(description = "创建者租户 ID") - private Long creatorTenantId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/contest/CreateContestDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/contest/CreateContestDTO.java deleted file mode 100644 index 652f6bb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/contest/CreateContestDTO.java +++ /dev/null @@ -1,135 +0,0 @@ -package com.lesingle.creation.dto.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.time.LocalDateTime; -import java.util.List; - -/** - * 创建竞赛 DTO - */ -@Data -@Schema(description = "创建竞赛请求") -public class CreateContestDTO { - - @NotBlank(message = "竞赛名称不能为空") - @Schema(description = "竞赛名称", example = "第十届创意绘画比赛") - private String contestName; - - @NotBlank(message = "竞赛类型不能为空") - @Schema(description = "竞赛类型:individual-个人赛/team-团队赛", example = "individual") - private String contestType; - - @Schema(description = "可见范围:public-公开/designated-指定机构/internal-仅内部", example = "designated") - private String visibility; - - @Schema(description = "目标城市列表(定向推送时使用)") - private List targetCities; - - @Schema(description = "最小年龄限制", example = "6") - private Integer ageMin; - - @Schema(description = "最大年龄限制", example = "18") - private Integer ageMax; - - @NotNull(message = "竞赛开始时间不能为空") - @Schema(description = "竞赛开始时间") - private LocalDateTime startTime; - - @NotNull(message = "竞赛结束时间不能为空") - @Schema(description = "竞赛结束时间") - private LocalDateTime endTime; - - @Schema(description = "线下地址") - private String address; - - @Schema(description = "竞赛详情") - private String content; - - @Schema(description = "授权租户 ID 列表") - private List contestTenants; - - @Schema(description = "封面 URL") - private String coverUrl; - - @Schema(description = "海报 URL") - private String posterUrl; - - @Schema(description = "联系人") - private String contactName; - - @Schema(description = "联系电话") - private String contactPhone; - - @Schema(description = "联系人二维码") - private String contactQrcode; - - @Schema(description = "主办单位") - private String organizers; - - @Schema(description = "协办单位") - private String coOrganizers; - - @Schema(description = "赞助单位") - private String sponsors; - - @NotNull(message = "报名开始时间不能为空") - @Schema(description = "报名开始时间") - private LocalDateTime registerStartTime; - - @NotNull(message = "报名结束时间不能为空") - @Schema(description = "报名结束时间") - private LocalDateTime registerEndTime; - - @Schema(description = "报名任务状态:open-开放/closed-关闭", example = "open") - private String registerState; - - @Schema(description = "是否需要审核", example = "true") - private Boolean requireAudit; - - @Schema(description = "允许报名的年级 ID 列表") - private List allowedGrades; - - @Schema(description = "允许报名的班级 ID 列表") - private List allowedClasses; - - @Schema(description = "团队最少成员数", example = "1") - private Integer teamMinMembers; - - @Schema(description = "团队最多成员数", example = "5") - private Integer teamMaxMembers; - - @Schema(description = "提交规则:once-仅一次/resubmit-可重复提交", example = "once") - private String submitRule; - - @NotNull(message = "作品提交开始时间不能为空") - @Schema(description = "作品提交开始时间") - private LocalDateTime submitStartTime; - - @NotNull(message = "作品提交结束时间不能为空") - @Schema(description = "作品提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "作品类型:image/video/document/code/other", example = "image") - private String workType; - - @Schema(description = "作品要求说明") - private String workRequirement; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; - - @NotNull(message = "评审开始时间不能为空") - @Schema(description = "评审开始时间") - private LocalDateTime reviewStartTime; - - @NotNull(message = "评审结束时间不能为空") - @Schema(description = "评审结束时间") - private LocalDateTime reviewEndTime; - - @Schema(description = "结果发布时间") - private LocalDateTime resultPublishTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/contest/PublishContestDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/contest/PublishContestDTO.java deleted file mode 100644 index cc09019..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/contest/PublishContestDTO.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.lesingle.creation.dto.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 发布/取消发布竞赛 DTO - */ -@Data -@Schema(description = "发布竞赛请求") -public class PublishContestDTO { - - @Schema(description = "竞赛状态:unpublished/published", example = "published") - private String contestState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/contest/UpdateContestDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/contest/UpdateContestDTO.java deleted file mode 100644 index 02275e8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/contest/UpdateContestDTO.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.lesingle.creation.dto.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 更新竞赛 DTO - */ -@Data -@Schema(description = "更新竞赛请求") -public class UpdateContestDTO { - - @Schema(description = "竞赛名称") - private String contestName; - - @Schema(description = "竞赛类型:individual/team") - private String contestType; - - @Schema(description = "可见范围:public/designated/internal") - private String visibility; - - @Schema(description = "目标城市列表") - private List targetCities; - - @Schema(description = "最小年龄限制") - private Integer ageMin; - - @Schema(description = "最大年龄限制") - private Integer ageMax; - - @Schema(description = "竞赛开始时间") - private LocalDateTime startTime; - - @Schema(description = "竞赛结束时间") - private LocalDateTime endTime; - - @Schema(description = "线下地址") - private String address; - - @Schema(description = "竞赛详情") - private String content; - - @Schema(description = "授权租户 ID 列表") - private List contestTenants; - - @Schema(description = "封面 URL") - private String coverUrl; - - @Schema(description = "海报 URL") - private String posterUrl; - - @Schema(description = "联系人") - private String contactName; - - @Schema(description = "联系电话") - private String contactPhone; - - @Schema(description = "联系人二维码") - private String contactQrcode; - - @Schema(description = "主办单位") - private String organizers; - - @Schema(description = "协办单位") - private String coOrganizers; - - @Schema(description = "赞助单位") - private String sponsors; - - @Schema(description = "报名开始时间") - private LocalDateTime registerStartTime; - - @Schema(description = "报名结束时间") - private LocalDateTime registerEndTime; - - @Schema(description = "报名任务状态:open/closed") - private String registerState; - - @Schema(description = "是否需要审核") - private Boolean requireAudit; - - @Schema(description = "允许报名的年级 ID 列表") - private List allowedGrades; - - @Schema(description = "允许报名的班级 ID 列表") - private List allowedClasses; - - @Schema(description = "团队最少成员数") - private Integer teamMinMembers; - - @Schema(description = "团队最多成员数") - private Integer teamMaxMembers; - - @Schema(description = "提交规则:once/resubmit") - private String submitRule; - - @Schema(description = "作品提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "作品提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "作品类型") - private String workType; - - @Schema(description = "作品要求说明") - private String workRequirement; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; - - @Schema(description = "评审开始时间") - private LocalDateTime reviewStartTime; - - @Schema(description = "评审结束时间") - private LocalDateTime reviewEndTime; - - @Schema(description = "结果发布时间") - private LocalDateTime resultPublishTime; - - @Schema(description = "竞赛状态:unpublished/published") - private String contestState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java deleted file mode 100644 index 4d5b6e9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/department/CreateDepartmentDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.department; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -/** - * 创建部门 DTO - */ -@Data -@Schema(description = "创建部门请求") -public class CreateDepartmentDTO { - - @NotBlank(message = "部门名称不能为空") - @Schema(description = "部门名称") - private String name; - - @NotBlank(message = "部门编码不能为空") - @Schema(description = "部门编码") - private String code; - - @Schema(description = "父部门 ID") - private Long parentId; - - @Schema(description = "部门描述") - private String description; - - @Schema(description = "排序") - private Integer sort = 0; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java deleted file mode 100644 index 1cad0cf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/department/UpdateDepartmentDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.department; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新部门 DTO - */ -@Data -@Schema(description = "更新部门请求") -public class UpdateDepartmentDTO { - - @Schema(description = "部门名称") - private String name; - - @Schema(description = "部门编码") - private String code; - - @Schema(description = "父部门 ID") - private Long parentId; - - @Schema(description = "部门描述") - private String description; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/dict/CreateDictDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/dict/CreateDictDTO.java deleted file mode 100644 index eec4276..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/dict/CreateDictDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.dto.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; - -/** - * 创建字典 DTO - */ -@Data -@Schema(description = "创建字典请求") -public class CreateDictDTO { - - @NotBlank(message = "字典名称不能为空") - @Schema(description = "字典名称", example = "性别") - private String name; - - @NotBlank(message = "字典编码不能为空") - @Schema(description = "字典编码", example = "gender") - private String code; - - @Schema(description = "字典描述") - private String description; - - @Schema(description = "字典项列表") - private List items; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/dict/CreateDictItemDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/dict/CreateDictItemDTO.java deleted file mode 100644 index 7d01475..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/dict/CreateDictItemDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -/** - * 创建字典项 DTO - */ -@Data -@Schema(description = "创建字典项请求") -public class CreateDictItemDTO { - - @NotBlank(message = "字典项标签不能为空") - @Schema(description = "字典项标签", example = "男") - private String label; - - @NotBlank(message = "字典项值不能为空") - @Schema(description = "字典项值", example = "male") - private String value; - - @Schema(description = "排序", example = "1") - private Integer sort; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/dict/UpdateDictDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/dict/UpdateDictDTO.java deleted file mode 100644 index 9190bdd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/dict/UpdateDictDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 更新字典 DTO - */ -@Data -@Schema(description = "更新字典请求") -public class UpdateDictDTO { - - @Schema(description = "字典名称") - private String name; - - @Schema(description = "字典编码") - private String code; - - @Schema(description = "字典描述") - private String description; - - @Schema(description = "字典项列表") - private List items; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/dict/UpdateDictItemDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/dict/UpdateDictItemDTO.java deleted file mode 100644 index 7200b11..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/dict/UpdateDictItemDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 更新字典项 DTO - */ -@Data -@Schema(description = "更新字典项请求") -public class UpdateDictItemDTO { - - @Schema(description = "字典项 ID") - private Long id; - - @Schema(description = "字典项标签") - private String label; - - @Schema(description = "字典项值") - private String value; - - @Schema(description = "排序") - private Integer sort; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java deleted file mode 100644 index 79948b7..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/grade/CreateGradeDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.dto.grade; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -/** - * 创建年级 DTO - */ -@Data -@Schema(description = "创建年级请求") -public class CreateGradeDTO { - - @NotBlank(message = "年级名称不能为空") - @Schema(description = "年级名称") - private String name; - - @NotBlank(message = "年级编码不能为空") - @Schema(description = "年级编码") - private String code; - - @NotNull(message = "年级级别不能为空") - @Schema(description = "年级级别") - private Integer level; - - @Schema(description = "年级描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java deleted file mode 100644 index 15f9350..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/grade/UpdateGradeDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.dto.grade; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新年级 DTO - */ -@Data -@Schema(description = "更新年级请求") -public class UpdateGradeDTO { - - @Schema(description = "年级名称") - private String name; - - @Schema(description = "年级编码") - private String code; - - @Schema(description = "年级级别") - private Integer level; - - @Schema(description = "年级描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java deleted file mode 100644 index 6730ed3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateHomeworkDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.time.LocalDateTime; - -/** - * 创建作业请求 DTO - */ -@Data -@Schema(description = "创建作业请求") -public class CreateHomeworkDTO { - - @NotBlank(message = "作业名称不能为空") - @Schema(description = "作业名称", example = "创意绘画练习") - private String name; - - @Schema(description = "作业内容(富文本)") - private String content; - - @NotNull(message = "提交开始时间不能为空") - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @NotNull(message = "提交结束时间不能为空") - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "公开范围(班级 ID 数组 JSON)") - private String publishScope; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java deleted file mode 100644 index 5ac2cd4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/CreateScoreDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; -import java.util.List; - -/** - * 创建评分请求 DTO - */ -@Data -@Schema(description = "创建评分请求") -public class CreateScoreDTO { - - @NotNull(message = "提交 ID 不能为空") - @Schema(description = "提交 ID") - private Long submissionId; - - @Schema(description = "维度评分列表") - private List dimensionScores; - - @Schema(description = "评语") - private String comments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java deleted file mode 100644 index 867302f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/DimensionScoreDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 维度评分 DTO - */ -@Data -@Schema(description = "维度评分") -public class DimensionScoreDTO { - - @NotBlank(message = "维度名称不能为空") - @Schema(description = "维度名称") - private String name; - - @NotNull(message = "得分不能为空") - @Schema(description = "得分") - private BigDecimal score; - - @Schema(description = "满分") - private BigDecimal maxScore; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java deleted file mode 100644 index c803880..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/HomeworkQueryDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 作业查询 DTO - */ -@Data -@Schema(description = "作业查询参数") -public class HomeworkQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页数量", example = "10") - private Integer pageSize = 10; - - @Schema(description = "作业名称关键字") - private String nameKeyword; - - @Schema(description = "作业状态:unpublished/published") - private String status; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java deleted file mode 100644 index 16c42de..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewDimensionDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 评审维度 DTO - */ -@Data -@Schema(description = "评审维度") -public class ReviewDimensionDTO { - - @Schema(description = "维度名称") - @NotBlank(message = "维度名称不能为空") - private String name; - - @Schema(description = "满分") - @NotNull(message = "满分不能为空") - private BigDecimal maxScore; - - @Schema(description = "维度描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java deleted file mode 100644 index bc25155..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/ReviewHomeworkDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 批改作业请求 DTO - */ -@Data -@Schema(description = "批改作业请求") -public class ReviewHomeworkDTO { - - @NotNull(message = "提交 ID 不能为空") - @Schema(description = "提交 ID") - private Long submissionId; - - @Schema(description = "批改分数") - private BigDecimal score; - - @Schema(description = "批改评语") - private String comment; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java deleted file mode 100644 index 3cf00b0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmissionQueryDTO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 提交记录查询 DTO - */ -@Data -@Schema(description = "提交记录查询参数") -public class SubmissionQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页大小", example = "10") - private Integer pageSize = 10; - - @Schema(description = "作业 ID") - private Long homeworkId; - - @Schema(description = "作品编号") - private String workNo; - - @Schema(description = "作品名称") - private String workName; - - @Schema(description = "学生账号") - private String studentAccount; - - @Schema(description = "学生姓名") - private String studentName; - - @Schema(description = "提交状态") - private String status; - - @Schema(description = "班级 ID 列表") - private java.util.List classIds; - - @Schema(description = "年级 ID") - private Long gradeId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java deleted file mode 100644 index a747361..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/SubmitHomeworkDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 提交作业请求 DTO - */ -@Data -@Schema(description = "提交作业请求") -public class SubmitHomeworkDTO { - - @NotNull(message = "作业 ID 不能为空") - @Schema(description = "作业 ID") - private Long homeworkId; - - @Schema(description = "提交内容") - private String content; - - @Schema(description = "提交附件列表(JSON 数组)") - private String attachments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java deleted file mode 100644 index 98f6b58..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateHomeworkDTO.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.time.LocalDateTime; - -/** - * 更新作业请求 DTO - */ -@Data -@Schema(description = "更新作业请求") -public class UpdateHomeworkDTO { - - @NotBlank(message = "作业名称不能为空") - @Schema(description = "作业名称", example = "创意绘画练习") - private String name; - - @Schema(description = "作业内容(富文本)") - private String content; - - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "公开范围(班级 ID 数组 JSON)") - private String publishScope; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java deleted file mode 100644 index b7fad0a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/homework/UpdateReviewRuleDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; -import java.util.List; - -/** - * 更新评审规则请求 DTO - */ -@Data -@Schema(description = "更新评审规则请求") -public class UpdateReviewRuleDTO { - - @Schema(description = "规则名称") - private String ruleName; - - @Schema(description = "规则描述") - private String description; - - @Schema(description = "评审维度列表") - private List dimensions; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/judge/CreateJudgeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/judge/CreateJudgeDTO.java deleted file mode 100644 index c173fbe..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/judge/CreateJudgeDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.lesingle.creation.dto.judge; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -/** - * 创建评委请求 DTO - */ -@Data -@Schema(description = "创建评委请求") -public class CreateJudgeDTO { - - @NotNull(message = "活动 ID 不能为空") - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "评委姓名") - private String judgeName; - - @Schema(description = "职称") - private String title; - - @Schema(description = "所属单位") - private String organization; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "专业领域") - private String specialty; - - @Schema(description = "权重", example = "1.0") - private java.math.BigDecimal weight = java.math.BigDecimal.ONE; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/judge/UpdateJudgeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/judge/UpdateJudgeDTO.java deleted file mode 100644 index c947584..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/judge/UpdateJudgeDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.dto.judge; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新评委请求 DTO - */ -@Data -@Schema(description = "更新评委请求") -public class UpdateJudgeDTO { - - @Schema(description = "评委姓名") - private String judgeName; - - @Schema(description = "职称") - private String title; - - @Schema(description = "所属单位") - private String organization; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "专业领域") - private String specialty; - - @Schema(description = "状态:1-活跃,2-不活跃") - private Integer status; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/log/LogQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/log/LogQueryDTO.java deleted file mode 100644 index 23fd26f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/log/LogQueryDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.log; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 日志查询参数 DTO - */ -@Data -@Schema(description = "日志查询参数") -public class LogQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页大小", example = "20") - private Integer pageSize = 20; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "操作类型") - private String action; - - @Schema(description = "关键字") - private String keyword; - - @Schema(description = "请求 IP") - private String ip; - - @Schema(description = "开始时间") - private String startTime; - - @Schema(description = "结束时间") - private String endTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/menu/CreateMenuDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/menu/CreateMenuDTO.java deleted file mode 100644 index c3affa9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/menu/CreateMenuDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.menu; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 创建菜单 DTO - */ -@Data -@Schema(description = "创建菜单请求") -public class CreateMenuDTO { - - @NotBlank(message = "菜单名称不能为空") - @Schema(description = "菜单名称", example = "用户管理") - private String name; - - @Schema(description = "路由路径", example = "/system/user") - private String path; - - @Schema(description = "图标", example = "user") - private String icon; - - @Schema(description = "组件路径", example = "system/user/index") - private String component; - - @Schema(description = "父菜单 ID", example = "1") - private Long parentId; - - @Schema(description = "权限编码", example = "user:read") - private String permission; - - @Schema(description = "排序", example = "1") - private Integer sort; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/menu/UpdateMenuDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/menu/UpdateMenuDTO.java deleted file mode 100644 index 7401aff..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/menu/UpdateMenuDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.dto.menu; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新菜单 DTO - */ -@Data -@Schema(description = "更新菜单请求") -public class UpdateMenuDTO { - - @Schema(description = "菜单名称") - private String name; - - @Schema(description = "路由路径") - private String path; - - @Schema(description = "图标") - private String icon; - - @Schema(description = "组件路径") - private String component; - - @Schema(description = "父菜单 ID") - private Long parentId; - - @Schema(description = "权限编码") - private String permission; - - @Schema(description = "排序") - private Integer sort; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/notice/CreateNoticeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/notice/CreateNoticeDTO.java deleted file mode 100644 index 47a0cbc..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/notice/CreateNoticeDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.dto.notice; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -/** - * 创建公告请求 DTO - */ -@Data -@Schema(description = "创建公告请求") -public class CreateNoticeDTO { - - @NotNull(message = "活动 ID 不能为空") - @Schema(description = "活动 ID") - private Long contestId; - - @NotBlank(message = "公告标题不能为空") - @Schema(description = "公告标题", example = "比赛通知") - private String title; - - @NotBlank(message = "公告内容不能为空") - @Schema(description = "公告内容") - private String content; - - @Schema(description = "公告类型:manual/system", example = "manual") - private String noticeType = "manual"; - - @Schema(description = "优先级(数字越大越优先)", example = "0") - private Integer priority = 0; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/notice/UpdateNoticeDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/notice/UpdateNoticeDTO.java deleted file mode 100644 index 91e60f7..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/notice/UpdateNoticeDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.dto.notice; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 更新公告请求 DTO - */ -@Data -@Schema(description = "更新公告请求") -public class UpdateNoticeDTO { - - @NotBlank(message = "公告标题不能为空") - @Schema(description = "公告标题", example = "比赛通知") - private String title; - - @Schema(description = "公告内容") - private String content; - - @Schema(description = "优先级(数字越大越优先)", example = "0") - private Integer priority; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/permission/CreatePermissionDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/permission/CreatePermissionDTO.java deleted file mode 100644 index beec0bb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/permission/CreatePermissionDTO.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.lesingle.creation.dto.permission; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; - -/** - * 创建权限 DTO - */ -@Data -@Schema(description = "创建权限请求") -public class CreatePermissionDTO { - - @NotBlank(message = "权限名称不能为空") - @Schema(description = "权限名称", example = "用户创建") - private String name; - - @NotBlank(message = "权限编码不能为空") - @Schema(description = "权限编码", example = "user:create") - private String code; - - @NotBlank(message = "资源名称不能为空") - @Schema(description = "资源名称", example = "user") - private String resource; - - @NotBlank(message = "操作类型不能为空") - @Schema(description = "操作类型", example = "create") - private String action; - - @Schema(description = "权限描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/permission/UpdatePermissionDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/permission/UpdatePermissionDTO.java deleted file mode 100644 index 045f26a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/permission/UpdatePermissionDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.permission; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; - -/** - * 更新权限 DTO - */ -@Data -@Schema(description = "更新权限请求") -public class UpdatePermissionDTO { - - @Schema(description = "权限名称") - private String name; - - @Schema(description = "权限编码") - private String code; - - @Schema(description = "资源名称") - private String resource; - - @Schema(description = "操作类型") - private String action; - - @Schema(description = "权限描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/presetcomment/CreatePresetCommentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/presetcomment/CreatePresetCommentDTO.java deleted file mode 100644 index f0cf4af..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/presetcomment/CreatePresetCommentDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.presetcomment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 创建预设评语请求 DTO - */ -@Data -@Schema(description = "创建预设评语请求") -public class CreatePresetCommentDTO { - - @Schema(description = "活动 ID(为空表示通用评语)") - private Long contestId; - - @NotBlank(message = "评语内容不能为空") - @Schema(description = "评语内容", example = "作品非常有创意") - private String content; - - @NotBlank(message = "评语类型不能为空") - @Schema(description = "评语类型:positive/neutral/negative", example = "positive") - private String type; - - @Schema(description = "适用分数范围最小值") - private BigDecimal scoreRangeMin; - - @Schema(description = "适用分数范围最大值") - private BigDecimal scoreRangeMax; - - @Schema(description = "排序", example = "0") - private Integer sort = 0; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicLoginDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicLoginDTO.java deleted file mode 100644 index 4157db5..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicLoginDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.lesingle.creation.dto.publicuser; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -/** - * 公众用户登录 DTO - */ -@Data -@Schema(description = "公众用户登录请求") -public class PublicLoginDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名/手机号") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicRegisterDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicRegisterDTO.java deleted file mode 100644 index 636c7bf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicRegisterDTO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.lesingle.creation.dto.publicuser; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import lombok.Data; - -/** - * 公众用户注册 DTO - */ -@Data -@Schema(description = "公众用户注册请求") -public class PublicRegisterDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "手机号") - private String phone; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "性别:male/female") - private String gender; - - @Schema(description = "所在城市") - private String city; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicUserUpdateDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicUserUpdateDTO.java deleted file mode 100644 index 547b178..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/publicuser/PublicUserUpdateDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.dto.publicuser; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新公众用户信息 DTO - */ -@Data -@Schema(description = "更新公众用户信息请求") -public class PublicUserUpdateDTO { - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "所在城市") - private String city; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "性别:male/female") - private String gender; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/registration/AddTeacherDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/registration/AddTeacherDTO.java deleted file mode 100644 index 97fa383..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/registration/AddTeacherDTO.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.lesingle.creation.dto.registration; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** - * 添加指导老师请求 DTO - */ -@Data -@Schema(description = "添加指导老师请求") -public class AddTeacherDTO { - - @NotNull(message = "老师用户 ID 不能为空") - @Schema(description = "老师用户 ID") - private Long teacherUserId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/registration/CreateRegistrationDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/registration/CreateRegistrationDTO.java deleted file mode 100644 index ef3e33d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/registration/CreateRegistrationDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.registration; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -/** - * 创建报名请求 DTO - */ -@Data -@Schema(description = "创建报名请求") -public class CreateRegistrationDTO { - - @NotNull(message = "活动 ID 不能为空") - @Schema(description = "活动 ID") - private Long contestId; - - @NotNull(message = "用户 ID 不能为空") - @Schema(description = "用户 ID") - private Long userId; - - @NotBlank(message = "参与类型不能为空") - @Schema(description = "参与类型:individual/team", example = "individual") - private String registrationType; - - @Schema(description = "团队 ID(团队参与时必填)") - private Long teamId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/registration/RegistrationQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/registration/RegistrationQueryDTO.java deleted file mode 100644 index 2e0d745..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/registration/RegistrationQueryDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.registration; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 报名查询 DTO - */ -@Data -@Schema(description = "报名查询参数") -public class RegistrationQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页数量", example = "10") - private Integer pageSize = 10; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "审核状态:pending/passed/rejected") - private String registrationState; - - @Schema(description = "参与类型:individual/team") - private String registrationType; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "参赛者类型") - private String participantType; - - @Schema(description = "关键词搜索:参与者姓名、手机号、子女姓名") - private String keyword; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/registration/ReviewRegistrationDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/registration/ReviewRegistrationDTO.java deleted file mode 100644 index 77f9087..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/registration/ReviewRegistrationDTO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.lesingle.creation.dto.registration; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 审核报名请求 DTO - */ -@Data -@Schema(description = "审核报名请求") -public class ReviewRegistrationDTO { - - @NotBlank(message = "审核状态不能为空") - @Schema(description = "审核状态:pending/passed/rejected", example = "passed") - private String registrationState; - - @Schema(description = "审核原因(驳回时填写)") - private String reason; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/result/CreateResultDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/result/CreateResultDTO.java deleted file mode 100644 index 0b967ee..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/result/CreateResultDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.dto.result; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 创建竞赛结果请求 DTO - */ -@Data -@Schema(description = "创建竞赛结果请求") -public class CreateResultDTO { - - @NotNull(message = "作品 ID 不能为空") - @Schema(description = "作品 ID") - private Long workId; - - @NotNull(message = "报名 ID 不能为空") - @Schema(description = "报名 ID") - private Long registrationId; - - @Schema(description = "总分") - private BigDecimal totalScore; - - @Schema(description = "奖项等级", example = "first/second/third") - private String awardLevel; - - @Schema(description = "获奖描述") - private String description; - - @Schema(description = "是否获奖", example = "true") - private Boolean isWinner = true; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/review/AssignWorkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/review/AssignWorkDTO.java deleted file mode 100644 index 694fc7f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/review/AssignWorkDTO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.dto.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 分配作品请求 DTO - */ -@Data -@Schema(description = "分配作品请求") -public class AssignWorkDTO { - - @NotNull(message = "作品 ID 不能为空") - @Schema(description = "作品 ID") - private Long workId; - - @NotEmpty(message = "评委 ID 列表不能为空") - @Schema(description = "评委 ID 列表") - private List judgeIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/review/BatchAssignDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/review/BatchAssignDTO.java deleted file mode 100644 index cae007b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/review/BatchAssignDTO.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.lesingle.creation.dto.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 批量分配作品请求 DTO - */ -@Data -@Schema(description = "批量分配作品请求") -public class BatchAssignDTO { - - @NotNull(message = "活动 ID 不能为空") - @Schema(description = "活动 ID") - private Long contestId; - - @NotEmpty(message = "作品 ID 列表不能为空") - @Schema(description = "作品 ID 列表") - private List workIds; - - @NotEmpty(message = "评委 ID 列表不能为空") - @Schema(description = "评委 ID 列表") - private List judgeIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/review/CreateScoreDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/review/CreateScoreDTO.java deleted file mode 100644 index 01b91ce..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/review/CreateScoreDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.dto.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.DecimalMin; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 创建评分请求 DTO - */ -@Data -@Schema(description = "创建评分请求") -public class CreateScoreDTO { - - @NotNull(message = "分配 ID 不能为空") - @Schema(description = "分配 ID") - private Long assignmentId; - - @NotNull(message = "作品 ID 不能为空") - @Schema(description = "作品 ID") - private Long workId; - - @NotNull(message = "分数不能为空") - @DecimalMin(value = "0", message = "分数不能小于 0") - @Schema(description = "分数") - private BigDecimal score; - - @Schema(description = "评语") - private String comment; - - @Schema(description = "各维度评分(JSON)") - private String dimensionScores; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/review/JudgeWorkQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/review/JudgeWorkQueryDTO.java deleted file mode 100644 index fa00895..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/review/JudgeWorkQueryDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 评委作品查询 DTO - */ -@Data -@Schema(description = "评委作品查询参数") -public class JudgeWorkQueryDTO { - - @Schema(description = "页码") - private Integer pageNum = 1; - - @Schema(description = "每页大小") - private Integer pageSize = 10; - - @Schema(description = "作品编号") - private String workNo; - - @Schema(description = "参赛者账号") - private String accountNo; - - @Schema(description = "评审状态") - private String reviewStatus; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/review/ReviewAssignmentQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/review/ReviewAssignmentQueryDTO.java deleted file mode 100644 index 77711bb..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/review/ReviewAssignmentQueryDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 评审分配查询 DTO - */ -@Data -@Schema(description = "评审分配查询参数") -public class ReviewAssignmentQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页数量", example = "10") - private Integer pageSize = 10; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "作品 ID") - private Long workId; - - @Schema(description = "评委 ID") - private Long judgeId; - - @Schema(description = "分配状态:assigned/reviewing/completed") - private String status; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/reviewrule/CreateReviewDimensionDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/reviewrule/CreateReviewDimensionDTO.java deleted file mode 100644 index f2c8f74..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/reviewrule/CreateReviewDimensionDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.reviewrule; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 创建评审维度请求 DTO - */ -@Data -@Schema(description = "创建评审维度请求") -public class CreateReviewDimensionDTO { - - @NotNull(message = "规则 ID 不能为空") - @Schema(description = "规则 ID") - private Long ruleId; - - @NotBlank(message = "维度名称不能为空") - @Schema(description = "维度名称", example = "创意性") - private String dimensionName; - - @Schema(description = "维度描述") - private String description; - - @Schema(description = "权重", example = "0.3") - private BigDecimal weight = new BigDecimal("0.3"); - - @Schema(description = "满分", example = "30.00") - private BigDecimal maxScore = new BigDecimal("30.00"); - - @Schema(description = "排序", example = "1") - private Integer sort = 1; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/reviewrule/CreateReviewRuleDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/reviewrule/CreateReviewRuleDTO.java deleted file mode 100644 index ea12656..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/reviewrule/CreateReviewRuleDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.dto.reviewrule; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.math.BigDecimal; - -/** - * 创建评审规则请求 DTO - */ -@Data -@Schema(description = "创建评审规则请求") -public class CreateReviewRuleDTO { - - @NotBlank(message = "规则名称不能为空") - @Schema(description = "规则名称", example = "创意绘画评分标准") - private String ruleName; - - @Schema(description = "规则类型:default/custom", example = "custom") - private String ruleType = "custom"; - - @Schema(description = "总分", example = "100.00") - private BigDecimal totalScore = new BigDecimal("100.00"); - - @Schema(description = "规则描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/role/CreateRoleDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/role/CreateRoleDTO.java deleted file mode 100644 index e56eef6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/role/CreateRoleDTO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.dto.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; - -/** - * 创建角色 DTO - */ -@Data -@Schema(description = "创建角色请求") -public class CreateRoleDTO { - - @NotBlank(message = "角色名称不能为空") - @Schema(description = "角色名称", example = "管理员") - private String name; - - @NotBlank(message = "角色编码不能为空") - @Schema(description = "角色编码", example = "admin") - private String code; - - @Schema(description = "角色描述") - private String description; - - @Schema(description = "权限 ID 列表") - private List permissionIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/role/UpdateRoleDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/role/UpdateRoleDTO.java deleted file mode 100644 index ffdc23d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/role/UpdateRoleDTO.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.dto.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 更新角色 DTO - */ -@Data -@Schema(description = "更新角色请求") -public class UpdateRoleDTO { - - @Schema(description = "角色名称") - private String name; - - @Schema(description = "角色编码") - private String code; - - @Schema(description = "角色描述") - private String description; - - @Schema(description = "权限 ID 列表") - private java.util.List permissionIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java deleted file mode 100644 index 82a970a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/school/CreateSchoolDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.time.LocalDate; - -/** - * 创建学校 DTO - */ -@Data -@Schema(description = "创建学校请求") -public class CreateSchoolDTO { - - @Schema(description = "学校地址") - private String address; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "校长姓名") - private String principal; - - @Schema(description = "建校时间") - private LocalDate established; - - @Schema(description = "学校描述") - private String description; - - @Schema(description = "学校 Logo URL") - private String logo; - - @Schema(description = "学校网站") - private String website; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java deleted file mode 100644 index a59458e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/school/UpdateSchoolDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.dto.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新学校 DTO - */ -@Data -@Schema(description = "更新学校请求") -public class UpdateSchoolDTO { - - @Schema(description = "学校地址") - private String address; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "校长姓名") - private String principal; - - @Schema(description = "建校时间") - private LocalDate established; - - @Schema(description = "学校描述") - private String description; - - @Schema(description = "学校 Logo URL") - private String logo; - - @Schema(description = "学校网站") - private String website; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/schoolclass/CreateClassDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/schoolclass/CreateClassDTO.java deleted file mode 100644 index 0c58ed7..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/schoolclass/CreateClassDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.schoolclass; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -/** - * 创建班级 DTO - */ -@Data -@Schema(description = "创建班级请求") -public class CreateClassDTO { - - @NotNull(message = "年级 ID 不能为空") - @Schema(description = "年级 ID") - private Long gradeId; - - @NotBlank(message = "班级名称不能为空") - @Schema(description = "班级名称") - private String name; - - @NotBlank(message = "班级编码不能为空") - @Schema(description = "班级编码") - private String code; - - @NotNull(message = "班级类型不能为空") - @Schema(description = "班级类型:1-行政班级,2-兴趣班") - private Integer type; - - @Schema(description = "班级容量") - private Integer capacity; - - @Schema(description = "班级描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/schoolclass/UpdateClassDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/schoolclass/UpdateClassDTO.java deleted file mode 100644 index c962da3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/schoolclass/UpdateClassDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.schoolclass; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 更新班级 DTO - */ -@Data -@Schema(description = "更新班级请求") -public class UpdateClassDTO { - - @Schema(description = "年级 ID") - private Long gradeId; - - @Schema(description = "班级名称") - private String name; - - @Schema(description = "班级编码") - private String code; - - @Schema(description = "班级类型") - private Integer type; - - @Schema(description = "班级容量") - private Integer capacity; - - @Schema(description = "班级描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java deleted file mode 100644 index db489a2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/student/CreateStudentDTO.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.lesingle.creation.dto.student; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 创建学生 DTO - */ -@Data -@Schema(description = "创建学生请求") -public class CreateStudentDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @NotNull(message = "行政班级 ID 不能为空") - @Schema(description = "行政班级 ID") - private Long classId; - - @Schema(description = "学号") - private String studentNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入学日期") - private LocalDate enrollmentDate; - - @Schema(description = "家长姓名") - private String parentName; - - @Schema(description = "家长电话") - private String parentPhone; - - @Schema(description = "家庭地址") - private String address; - - @Schema(description = "学生描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java deleted file mode 100644 index 102c94f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/student/UpdateStudentDTO.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.lesingle.creation.dto.student; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新学生 DTO - */ -@Data -@Schema(description = "更新学生请求") -public class UpdateStudentDTO { - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "行政班级 ID") - private Long classId; - - @Schema(description = "学号") - private String studentNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入学日期") - private LocalDate enrollmentDate; - - @Schema(description = "家长姓名") - private String parentName; - - @Schema(description = "家长电话") - private String parentPhone; - - @Schema(description = "家庭地址") - private String address; - - @Schema(description = "学生描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java deleted file mode 100644 index 4f2c25c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/CreateTeacherDTO.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.lesingle.creation.dto.teacher; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 创建教师 DTO - */ -@Data -@Schema(description = "创建教师请求") -public class CreateTeacherDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @NotNull(message = "部门 ID 不能为空") - @Schema(description = "部门 ID") - private Long departmentId; - - @Schema(description = "工号") - private String employeeNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入职日期") - private LocalDate hireDate; - - @Schema(description = "任教科目") - private String subject; - - @Schema(description = "职称") - private String title; - - @Schema(description = "教师描述") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java deleted file mode 100644 index 7b7b83c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/teacher/UpdateTeacherDTO.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.lesingle.creation.dto.teacher; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; - -/** - * 更新教师 DTO - */ -@Data -@Schema(description = "更新教师请求") -public class UpdateTeacherDTO { - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "部门 ID") - private Long departmentId; - - @Schema(description = "工号") - private String employeeNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入职日期") - private LocalDate hireDate; - - @Schema(description = "任教科目") - private String subject; - - @Schema(description = "职称") - private String title; - - @Schema(description = "教师描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/team/CreateTeamDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/team/CreateTeamDTO.java deleted file mode 100644 index 5d88029..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/team/CreateTeamDTO.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.dto.team; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 创建团队请求 DTO - */ -@Data -@Schema(description = "创建团队请求") -public class CreateTeamDTO { - - @NotNull(message = "活动 ID 不能为空") - @Schema(description = "活动 ID") - private Long contestId; - - @NotBlank(message = "团队名称不能为空") - @Schema(description = "团队名称", example = "梦想队") - private String teamName; - - @NotNull(message = "队长 ID 不能为空") - @Schema(description = "队长用户 ID") - private Long leaderId; - - @Schema(description = "最大人数", example = "5") - private Integer maxMembers = 5; - - @Schema(description = "队员用户 ID 列表") - private List memberIds; - - @Schema(description = "指导老师用户 ID 列表") - private List teacherIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/team/InviteMemberDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/team/InviteMemberDTO.java deleted file mode 100644 index d4d97c4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/team/InviteMemberDTO.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.lesingle.creation.dto.team; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; - -/** - * 邀请成员请求 DTO - */ -@Data -@Schema(description = "邀请成员请求") -public class InviteMemberDTO { - - @NotNull(message = "用户 ID 不能为空") - @Schema(description = "被邀请用户 ID") - private Long userId; - - @NotBlank(message = "角色不能为空") - @Schema(description = "角色:member/mentor", example = "member") - private String role; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/team/UpdateTeamDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/team/UpdateTeamDTO.java deleted file mode 100644 index d2a9643..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/team/UpdateTeamDTO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.dto.team; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; - -/** - * 更新团队请求 DTO - */ -@Data -@Schema(description = "更新团队请求") -public class UpdateTeamDTO { - - @NotBlank(message = "团队名称不能为空") - @Schema(description = "团队名称", example = "梦想队") - private String teamName; - - @Schema(description = "最大人数", example = "5") - private Integer maxMembers = 5; - - @Schema(description = "队员用户 ID 列表") - private java.util.List memberIds; - - @Schema(description = "指导老师用户 ID 列表") - private java.util.List teacherIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/tenant/CreateTenantDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/tenant/CreateTenantDTO.java deleted file mode 100644 index ed3be90..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/tenant/CreateTenantDTO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.dto.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 创建租户 DTO - */ -@Data -@Schema(description = "创建租户请求") -public class CreateTenantDTO { - - @NotBlank(message = "租户名称不能为空") - @Schema(description = "租户名称", example = "测试图书馆") - private String name; - - @NotBlank(message = "租户编码不能为空") - @Schema(description = "租户编码", example = "library001") - private String code; - - @Schema(description = "租户域名", example = "library001.example.com") - private String domain; - - @Schema(description = "租户描述") - private String description; - - @Schema(description = "租户类型", example = "library") - private String tenantType; - - @Schema(description = "分配的菜单 ID 列表") - private List menuIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/tenant/UpdateTenantDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/tenant/UpdateTenantDTO.java deleted file mode 100644 index d09364b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/tenant/UpdateTenantDTO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.dto.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.Max; -import jakarta.validation.constraints.Min; - -/** - * 更新租户 DTO - */ -@Data -@Schema(description = "更新租户请求") -public class UpdateTenantDTO { - - @Schema(description = "租户名称") - private String name; - - @Schema(description = "租户编码") - private String code; - - @Schema(description = "租户域名") - private String domain; - - @Schema(description = "租户描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效", example = "1") - @Min(value = 1, message = "有效状态最小值为 1") - @Max(value = 2, message = "有效状态最大值为 2") - private Integer validState; - - @Schema(description = "分配的菜单 ID 列表") - private java.util.List menuIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/user/CreateUserDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/user/CreateUserDTO.java deleted file mode 100644 index f0e7c0d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/user/CreateUserDTO.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.lesingle.creation.dto.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import java.util.List; - -/** - * 创建用户 DTO - */ -@Data -@Schema(description = "创建用户请求") -public class CreateUserDTO { - - @NotBlank(message = "用户名不能为空") - @Schema(description = "用户名", example = "zhangsan") - private String username; - - @NotBlank(message = "密码不能为空") - @Schema(description = "密码", example = "123456") - private String password; - - @NotBlank(message = "昵称不能为空") - @Schema(description = "昵称", example = "张三") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "手机号") - private String phone; - - @Schema(description = "性别:male-男,female-女", example = "male") - private String gender; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "账号状态:enabled-启用,disabled-停用", example = "enabled") - private String status; - - @Schema(description = "角色 ID 列表") - private List roleIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/user/UpdateUserDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/user/UpdateUserDTO.java deleted file mode 100644 index c8b6d9f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/user/UpdateUserDTO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.dto.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 更新用户 DTO - */ -@Data -@Schema(description = "更新用户请求") -public class UpdateUserDTO { - - @Schema(description = "用户名") - private String username; - - @Schema(description = "密码") - private String password; - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "手机号") - private String phone; - - @Schema(description = "性别:male-男,female-女") - private String gender; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "账号状态:enabled-启用,disabled-停用") - private String status; - - @Schema(description = "角色 ID 列表") - private List roleIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/user/UserQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/user/UserQueryDTO.java deleted file mode 100644 index 37a1747..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/user/UserQueryDTO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.dto.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 用户查询 DTO - */ -@Data -@Schema(description = "用户查询参数") -public class UserQueryDTO { - - @Schema(description = "关键字(用户名/昵称/邮箱/手机号)") - private String keyword; - - @Schema(description = "用户类型:adult/child") - private String userType; - - @Schema(description = "用户来源:admin_created/self_registered/child_migrated") - private String userSource; - - @Schema(description = "账号状态:enabled/disabled") - private String status; - - @Schema(description = "页码", example = "1") - private Integer page = 1; - - @Schema(description = "每页大小", example = "10") - private Integer pageSize = 10; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/work/SubmitWorkDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/work/SubmitWorkDTO.java deleted file mode 100644 index a314d84..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/work/SubmitWorkDTO.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.lesingle.creation.dto.work; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.util.List; - -/** - * 提交作品请求 DTO - */ -@Data -@Schema(description = "提交作品请求") -public class SubmitWorkDTO { - - @NotNull(message = "报名 ID 不能为空") - @Schema(description = "报名 ID") - private Long registrationId; - - @NotBlank(message = "作品标题不能为空") - @Schema(description = "作品标题", example = "我的创意绘画") - private String title; - - @Schema(description = "作品描述") - private String description; - - @Schema(description = "文件列表(JSON 数组)") - private String files; - - @Schema(description = "预览图 URL") - private String previewUrl; - - @Schema(description = "预览图 URL 数组(JSON)") - private String previewUrls; - - @Schema(description = "AI 模型元数据(JSON)") - private String aiModelMeta; - - @Schema(description = "附件列表") - private List attachments; - - @Data - @Schema(description = "附件信息") - public static class AttachmentDTO { - @Schema(description = "文件名称") - private String fileName; - - @Schema(description = "文件 URL") - private String fileUrl; - - @Schema(description = "文件类型") - private String fileType; - - @Schema(description = "文件大小(字节)") - private Long size; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/dto/work/WorkQueryDTO.java b/java-backend/src/main/java/com/lesingle/creation/dto/work/WorkQueryDTO.java deleted file mode 100644 index 64b8f08..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/dto/work/WorkQueryDTO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.dto.work; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 作品查询 DTO - */ -@Data -@Schema(description = "作品查询参数") -public class WorkQueryDTO { - - @Schema(description = "页码", example = "1") - private Integer pageNum = 1; - - @Schema(description = "每页数量", example = "10") - private Integer pageSize = 10; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "报名 ID") - private Long registrationId; - - @Schema(description = "作品标题关键字") - private String titleKeyword; - - @Schema(description = "提交人 ID") - private Long submitterId; - - @Schema(description = "是否仅查询最新版本", example = "true") - private Boolean latestOnly = true; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/AI3DTask.java b/java-backend/src/main/java/com/lesingle/creation/entity/AI3DTask.java deleted file mode 100644 index 2269bcc..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/AI3DTask.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * AI 3D 任务表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_ai3d_task") -public class AI3DTask extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 用户 ID - */ - @TableField("user_id") - private Long userId; - - /** - * 输入类型:text/image - */ - @TableField("input_type") - private String inputType; - - /** - * 输入内容:文字描述或图片 URL - */ - @TableField("input_content") - private String inputContent; - - /** - * 生成类型:Normal/Geometry/LowPoly/Sketch - */ - @TableField("generate_type") - private String generateType; - - /** - * 任务状态:pending/processing/completed/failed/timeout - */ - @TableField("status") - private String status; - - /** - * 生成的 3D 模型 URL(单结果) - */ - @TableField("result_url") - private String resultUrl; - - /** - * 预览图 URL(单结果) - */ - @TableField("preview_url") - private String previewUrl; - - /** - * 生成的 3D 模型 URL 数组(多结果,JSON 格式) - */ - @TableField("result_urls") - private String resultUrls; - - /** - * 预览图 URL 数组(多结果,JSON 格式) - */ - @TableField("preview_urls") - private String previewUrls; - - /** - * 失败错误信息 - */ - @TableField("error_message") - private String errorMessage; - - /** - * 外部 AI 服务任务 ID - */ - @TableField("external_task_id") - private String externalTaskId; - - /** - * 已重试次数 - */ - @TableField("retry_count") - private Integer retryCount; - - /** - * 完成时间 - */ - @TableField("complete_time") - private java.time.LocalDateTime completeTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Contest.java b/java-backend/src/main/java/com/lesingle/creation/entity/Contest.java deleted file mode 100644 index 59635fd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Contest.java +++ /dev/null @@ -1,266 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.util.List; - -/** - * 竞赛/活动表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest") -public class Contest extends BaseEntity { - - /** - * 赛事名称 - */ - @TableField("contest_name") - private String contestName; - - /** - * 赛事类型:individual/team - */ - @TableField("contest_type") - private String contestType; - - /** - * 赛事状态:unpublished/published - */ - @TableField("contest_state") - private String contestState; - - /** - * 赛事进度状态:ongoing/finished - */ - @TableField("status") - private String status; - - /** - * 赛事开始时间 - */ - @TableField("start_time") - private LocalDateTime startTime; - - /** - * 赛事结束时间 - */ - @TableField("end_time") - private LocalDateTime endTime; - - /** - * 线下地址 - */ - @TableField("address") - private String address; - - /** - * 赛事详情 - */ - @TableField("content") - private String content; - - /** - * 授权租户 ID 数组(JSON) - */ - @TableField("contest_tenants") - private String contestTenants; - - /** - * 封面 URL - */ - @TableField("cover_url") - private String coverUrl; - - /** - * 海报 URL - */ - @TableField("poster_url") - private String posterUrl; - - /** - * 联系人 - */ - @TableField("contact_name") - private String contactName; - - /** - * 联系电话 - */ - @TableField("contact_phone") - private String contactPhone; - - /** - * 联系人二维码 - */ - @TableField("contact_qrcode") - private String contactQrcode; - - /** - * 主办单位数组(JSON) - */ - @TableField("organizers") - private String organizers; - - /** - * 协办单位数组(JSON) - */ - @TableField("co_organizers") - private String coOrganizers; - - /** - * 赞助单位数组(JSON) - */ - @TableField("sponsors") - private String sponsors; - - /** - * 报名开始时间 - */ - @TableField("register_start_time") - private LocalDateTime registerStartTime; - - /** - * 报名结束时间 - */ - @TableField("register_end_time") - private LocalDateTime registerEndTime; - - /** - * 报名任务状态:started/closed - */ - @TableField("register_state") - private String registerState; - - /** - * 报名是否需要审核 - */ - @TableField("require_audit") - private Boolean requireAudit; - - /** - * 允许报名的年级 ID 数组(JSON) - */ - @TableField("allowed_grades") - private String allowedGrades; - - /** - * 允许报名的班级 ID 数组(JSON) - */ - @TableField("allowed_classes") - private String allowedClasses; - - /** - * 团队最少成员数 - */ - @TableField("team_min_members") - private Integer teamMinMembers; - - /** - * 团队最多成员数 - */ - @TableField("team_max_members") - private Integer teamMaxMembers; - - /** - * 目标城市列表(JSON) - */ - @TableField("target_cities") - private String targetCities; - - /** - * 最小年龄限制 - */ - @TableField("age_min") - private Integer ageMin; - - /** - * 最大年龄限制 - */ - @TableField("age_max") - private Integer ageMax; - - /** - * 提交规则:once/resubmit - */ - @TableField("submit_rule") - private String submitRule; - - /** - * 作品提交开始时间 - */ - @TableField("submit_start_time") - private LocalDateTime submitStartTime; - - /** - * 作品提交结束时间 - */ - @TableField("submit_end_time") - private LocalDateTime submitEndTime; - - /** - * 作品类型:image/video/document/code/other - */ - @TableField("work_type") - private String workType; - - /** - * 作品要求说明 - */ - @TableField("work_requirement") - private String workRequirement; - - /** - * 评审规则 ID - */ - @TableField("review_rule_id") - private Long reviewRuleId; - - /** - * 评审开始时间 - */ - @TableField("review_start_time") - private LocalDateTime reviewStartTime; - - /** - * 评审结束时间 - */ - @TableField("review_end_time") - private LocalDateTime reviewEndTime; - - /** - * 赛果状态:unpublished/published - */ - @TableField("result_state") - private String resultState; - - /** - * 结果发布时间 - */ - @TableField("result_publish_time") - private LocalDateTime resultPublishTime; - - /** - * 可见范围:public/designated/internal - */ - @TableField("visibility") - private String visibility; - - /** - * 所属租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestAttachment.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestAttachment.java deleted file mode 100644 index 00b1d6b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestAttachment.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 竞赛附件表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_attachment") -public class ContestAttachment extends BaseEntity { - - /** - * 竞赛 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 附件名称 - */ - @TableField("name") - private String name; - - /** - * 附件 URL - */ - @TableField("url") - private String url; - - /** - * 附件类型 - */ - @TableField("type") - private String type; - - /** - * 文件大小(字节) - */ - @TableField("size") - private Long size; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestJudge.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestJudge.java deleted file mode 100644 index 22c9edf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestJudge.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 竞赛评委表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_judge") -public class ContestJudge extends BaseEntity { - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 评委用户 ID - */ - @TableField("judge_id") - private Long judgeId; - - /** - * 评委姓名 - */ - @TableField("judge_name") - private String judgeName; - - /** - * 职称 - */ - @TableField("title") - private String title; - - /** - * 所属单位 - */ - @TableField("organization") - private String organization; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 邮箱 - */ - @TableField("email") - private String email; - - /** - * 专业领域 - */ - @TableField("specialty") - private String specialty; - - /** - * 状态:active/inactive - */ - @TableField("status") - private String status; - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; - - /** - * 权重 - */ - @TableField("weight") - private java.math.BigDecimal weight; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestNotice.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestNotice.java deleted file mode 100644 index 5b40df8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestNotice.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -/** - * 竞赛公告表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_notice") -public class ContestNotice extends BaseEntity { - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 公告标题 - */ - @TableField("title") - private String title; - - /** - * 公告内容 - */ - @TableField("content") - private String content; - - /** - * 优先级(数字越大越优先) - */ - @TableField("priority") - private Integer priority; - - /** - * 发布时间 - */ - @TableField("publish_time") - private LocalDateTime publishTime; - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; - - /** - * 公告类型 - */ - @TableField("notice_type") - private String noticeType; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestPresetComment.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestPresetComment.java deleted file mode 100644 index d28476e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestPresetComment.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 竞赛预设评语表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_preset_comment") -public class ContestPresetComment extends BaseEntity { - - /** - * 赛事 ID(为空表示通用评语) - */ - @TableField("contest_id") - private Long contestId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 评语内容 - */ - @TableField("content") - private String content; - - /** - * 评语类型:positive/neutral/negative - */ - @TableField("type") - private String type; - - /** - * 适用分数范围最小值 - */ - @TableField("score_range_min") - private BigDecimal scoreRangeMin; - - /** - * 适用分数范围最大值 - */ - @TableField("score_range_max") - private BigDecimal scoreRangeMax; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 使用次数 - */ - @TableField("usage_count") - private Integer usageCount; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestRegistration.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestRegistration.java deleted file mode 100644 index ae22bd9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestRegistration.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDateTime; - -/** - * 竞赛报名表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_registration") -public class ContestRegistration extends BaseEntity { - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 所属租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 报名类型:individual/team - */ - @TableField("registration_type") - private String registrationType; - - /** - * 团队 ID - */ - @TableField("team_id") - private Long teamId; - - /** - * 团队名称快照 - */ - @TableField("team_name") - private String teamName; - - /** - * 账号 ID - */ - @TableField("user_id") - private Long userId; - - /** - * 报名账号 - */ - @TableField("account_no") - private String accountNo; - - /** - * 报名账号名称 - */ - @TableField("account_name") - private String accountName; - - /** - * 报名角色快照:leader/member/mentor - */ - @TableField("role") - private String role; - - /** - * 报名状态:pending/passed/rejected/withdrawn - */ - @TableField("registration_state") - private String registrationState; - - /** - * 参与者类型:self-自己/child-代子女报名 - */ - @TableField("participant_type") - private String participantType; - - /** - * 子女 ID - */ - @TableField("child_id") - private Long childId; - - /** - * 实际报名人用户 ID - */ - @TableField("registrant") - private Long registrant; - - /** - * 报名时间 - */ - @TableField("registration_time") - private LocalDateTime registrationTime; - - /** - * 审核理由 - */ - @TableField("reason") - private String reason; - - /** - * 审核人用户 ID - */ - @TableField("operator") - private Long operator; - - /** - * 审核时间 - */ - @TableField("operation_date") - private LocalDateTime operationDate; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; - - /** - * 指导老师 ID 列表(JSON) - */ - @TableField("teacher_ids") - private String teacherIds; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestRegistrationTeacher.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestRegistrationTeacher.java deleted file mode 100644 index d3035d5..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestRegistrationTeacher.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; - -/** - * 竞赛报名指导老师关联表实体类 - * 中间表,不使用逻辑删除和审计字段 - */ -@Data -@TableName("t_biz_contest_registration_teacher") -public class ContestRegistrationTeacher implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * 主键 ID - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 报名 ID - */ - @TableField("registration_id") - private Long registrationId; - - /** - * 老师用户 ID - */ - @TableField("user_id") - private Long userId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 是否默认指导老师 - */ - @TableField("is_default") - private Boolean isDefault; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestResult.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestResult.java deleted file mode 100644 index fb023a6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestResult.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 竞赛结果表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_result") -public class ContestResult extends BaseEntity { - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 作品 ID - */ - @TableField("work_id") - private Long workId; - - /** - * 报名 ID - */ - @TableField("registration_id") - private Long registrationId; - - /** - * 团队 ID - */ - @TableField("team_id") - private Long teamId; - - /** - * 奖项等级:first/second/third/excellent - */ - @TableField("award_level") - private String awardLevel; - - /** - * 奖项名称 - */ - @TableField("award_name") - private String awardName; - - /** - * 排名 - */ - @TableField("rank") - private Integer rank; - - /** - * 最终得分 - */ - @TableField("final_score") - private BigDecimal finalScore; - - /** - * 证书 URL - */ - @TableField("certificate_url") - private String certificateUrl; - - /** - * 发布时间 - */ - @TableField("publish_time") - private LocalDateTime publishTime; - - /** - * 是否获奖:1-是,0-否 - */ - @TableField("is_winner") - private Boolean isWinner; - - /** - * 总分 - */ - @TableField("total_score") - private BigDecimal totalScore; - - /** - * 公开状态 - */ - @TableField("public_state") - private String publicState; - - /** - * 描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestReviewDimension.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestReviewDimension.java deleted file mode 100644 index c4dee94..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestReviewDimension.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 评审维度表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_review_dimension") -public class ContestReviewDimension extends BaseEntity { - - /** - * 评审规则 ID - */ - @TableField("rule_id") - private Long ruleId; - - /** - * 维度名称 - */ - @TableField("dimension_name") - private String dimensionName; - - /** - * 维度编码 - */ - @TableField("dimension_code") - private String dimensionCode; - - /** - * 权重(百分比) - */ - @TableField("weight") - private BigDecimal weight; - - /** - * 满分 - */ - @TableField("max_score") - private BigDecimal maxScore; - - /** - * 维度说明 - */ - @TableField("description") - private String description; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestReviewRule.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestReviewRule.java deleted file mode 100644 index f81e021..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestReviewRule.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 评审规则表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_review_rule") -public class ContestReviewRule extends BaseEntity { - - /** - * 竞赛 ID(为空表示默认规则) - */ - @TableField("contest_id") - private Long contestId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 规则名称 - */ - @TableField("rule_name") - private String ruleName; - - /** - * 规则类型:default/custom - */ - @TableField("rule_type") - private String ruleType; - - /** - * 总分 - */ - @TableField("total_score") - private BigDecimal totalScore; - - /** - * 及格分 - */ - @TableField("pass_score") - private BigDecimal passScore; - - /** - * 规则描述 - */ - @TableField("description") - private String description; - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestTeam.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestTeam.java deleted file mode 100644 index 9cb8d58..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestTeam.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 竞赛团队表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_team") -public class ContestTeam extends BaseEntity { - - /** - * 团队所属租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 团队名称 - */ - @TableField("team_name") - private String teamName; - - /** - * 团队负责人用户 ID - */ - @TableField("leader_user_id") - private Long leaderUserId; - - /** - * 团队最大成员数 - */ - @TableField("max_members") - private Integer maxMembers; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestTeamMember.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestTeamMember.java deleted file mode 100644 index 2aa71dc..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestTeamMember.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; -import java.time.LocalDateTime; - -/** - * 竞赛团队成员表实体类 - * 中间表,不使用逻辑删除和审计字段 - */ -@Data -@TableName("t_biz_contest_team_member") -public class ContestTeamMember implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * 主键 ID - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 团队 ID - */ - @TableField("team_id") - private Long teamId; - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 用户 ID - */ - @TableField("user_id") - private Long userId; - - /** - * 团队角色:leader/member/mentor - */ - @TableField("role") - private String role; - - /** - * 加入时间 - */ - @TableField("join_time") - private LocalDateTime joinTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWork.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestWork.java deleted file mode 100644 index 4f9593f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWork.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 竞赛作品表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_work") -public class ContestWork extends BaseEntity { - - /** - * 作品所属租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 报名记录 ID - */ - @TableField("registration_id") - private Long registrationId; - - /** - * 作品编号 - */ - @TableField("work_no") - private String workNo; - - /** - * 作品标题 - */ - @TableField("title") - private String title; - - /** - * 作品说明 - */ - @TableField("description") - private String description; - - /** - * 作品文件列表(JSON) - */ - @TableField("files") - private String files; - - /** - * 作品版本号 - */ - @TableField("version") - private Integer version; - - /** - * 是否最新版本 - */ - @TableField("is_latest") - private Boolean isLatest; - - /** - * 作品状态:submitted/locked/reviewing/rejected/accepted - */ - @TableField("status") - private String status; - - /** - * 提交时间 - */ - @TableField("submit_time") - private LocalDateTime submitTime; - - /** - * 提交人用户 ID - */ - @TableField("submitter_user_id") - private Long submitterUserId; - - /** - * 提交人账号 - */ - @TableField("submitter_account_no") - private String submitterAccountNo; - - /** - * 提交来源:teacher/student/team_leader - */ - @TableField("submit_source") - private String submitSource; - - /** - * 作品预览 URL - */ - @TableField("preview_url") - private String previewUrl; - - /** - * 作品预览图 URL 列表(JSON) - */ - @TableField("preview_urls") - private String previewUrls; - - /** - * AI 建模元数据(JSON) - */ - @TableField("ai_model_meta") - private String aiModelMeta; - - /** - * 关联用户作品库 ID - */ - @TableField("user_work_id") - private Long userWorkId; - - /** - * 最终得分 - */ - @TableField("final_score") - private BigDecimal finalScore; - - /** - * 排名 - */ - @TableField("rank") - private Integer rank; - - /** - * 奖项等级:first/second/third/excellent/none - */ - @TableField("award_level") - private String awardLevel; - - /** - * 奖项名称 - */ - @TableField("award_name") - private String awardName; - - /** - * 证书 URL - */ - @TableField("certificate_url") - private String certificateUrl; - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkAssignment.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkAssignment.java deleted file mode 100644 index d714281..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkAssignment.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 竞赛作品评审分配表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_work_assignment") -public class ContestWorkAssignment extends BaseEntity { - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 作品 ID - */ - @TableField("work_id") - private Long workId; - - /** - * 评委用户 ID - */ - @TableField("judge_id") - private Long judgeId; - - /** - * 评委姓名 - */ - @TableField("judge_name") - private String judgeName; - - /** - * 分配状态:pending/reviewing/completed - */ - @TableField("assignment_status") - private String assignmentStatus; - - /** - * 分配人 ID - */ - @TableField("assigned_by") - private Long assignedBy; - - /** - * 分配时间 - */ - @TableField("assigned_time") - private LocalDateTime assignedTime; - - /** - * 评审时间 - */ - @TableField("review_time") - private LocalDateTime reviewTime; - - /** - * 评分 - */ - @TableField("score") - private BigDecimal score; - - /** - * 评语 - */ - @TableField("comment") - private String comment; - - /** - * 预设评语 ID - */ - @TableField("preset_comment_id") - private Long presetCommentId; - - /** - * 自定义评语 - */ - @TableField("custom_comment") - private String customComment; - - /** - * 分配状态:pending/reviewing/completed(别名,用于兼容) - */ - @TableField(exist = false) - private String status; - - /** - * 分配时间(别名,用于兼容) - */ - @TableField(exist = false) - private LocalDateTime assignTime; - - /** - * 完成时间(别名,用于兼容) - */ - @TableField(exist = false) - private LocalDateTime completeTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkAttachment.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkAttachment.java deleted file mode 100644 index 869929a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkAttachment.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 竞赛作品附件表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_work_attachment") -public class ContestWorkAttachment extends BaseEntity { - - /** - * 作品 ID - */ - @TableField("work_id") - private Long workId; - - /** - * 附件名称 - */ - @TableField("name") - private String name; - - /** - * 附件 URL - */ - @TableField("url") - private String url; - - /** - * 附件类型 - */ - @TableField("type") - private String type; - - /** - * 文件大小(字节) - */ - @TableField("size") - private Long size; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 文件名称 - */ - @TableField("file_name") - private String fileName; - - /** - * 文件 URL - */ - @TableField("file_url") - private String fileUrl; - - /** - * 文件类型 - */ - @TableField("file_type") - private String fileType; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkScore.java b/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkScore.java deleted file mode 100644 index 7fcf9b6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/ContestWorkScore.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 竞赛作品评分表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_contest_work_score") -public class ContestWorkScore extends BaseEntity { - - /** - * 赛事 ID - */ - @TableField("contest_id") - private Long contestId; - - /** - * 作品 ID - */ - @TableField("work_id") - private Long workId; - - /** - * 评审分配 ID - */ - @TableField("assignment_id") - private Long assignmentId; - - /** - * 评委用户 ID - */ - @TableField("judge_id") - private Long judgeId; - - /** - * 评委姓名 - */ - @TableField("judge_name") - private String judgeName; - - /** - * 评审维度 ID - */ - @TableField("dimension_id") - private Long dimensionId; - - /** - * 评审维度名称 - */ - @TableField("dimension_name") - private String dimensionName; - - /** - * 得分 - */ - @TableField("score") - private BigDecimal score; - - /** - * 评语 - */ - @TableField("comment") - private String comment; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 维度得分(JSON 格式) - */ - @TableField("dimension_scores") - private String dimensionScores; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Department.java b/java-backend/src/main/java/com/lesingle/creation/entity/Department.java deleted file mode 100644 index 366b8b8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Department.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 部门表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_department") -public class Department extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 部门名称 - */ - @TableField("name") - private String name; - - /** - * 部门编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 父部门 ID(支持树形结构) - */ - @TableField("parent_id") - private Long parentId; - - /** - * 部门描述 - */ - @TableField("description") - private String description; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; - - /** - * 子部门列表(非数据库字段) - */ - @TableField(exist = false) - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Dict.java b/java-backend/src/main/java/com/lesingle/creation/entity/Dict.java deleted file mode 100644 index c814400..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Dict.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 字典表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_sys_dict") -public class Dict extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 字典名称 - */ - @TableField("name") - private String name; - - /** - * 字典编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 字典描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/DictItem.java b/java-backend/src/main/java/com/lesingle/creation/entity/DictItem.java deleted file mode 100644 index 4f19d2b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/DictItem.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 字典项表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_sys_dict_item") -public class DictItem extends BaseEntity { - - /** - * 字典 ID - */ - @TableField("dict_id") - private Long dictId; - - /** - * 字典项标签 - */ - @TableField("label") - private String label; - - /** - * 字典项值 - */ - @TableField("value") - private String value; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Grade.java b/java-backend/src/main/java/com/lesingle/creation/entity/Grade.java deleted file mode 100644 index 33edee8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Grade.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 年级表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_grade") -public class Grade extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 年级名称(如:一年级、二年级) - */ - @TableField("name") - private String name; - - /** - * 年级编码(在租户内唯一,如:grade_1, grade_2) - */ - @TableField("code") - private String code; - - /** - * 年级级别(用于排序,如:1, 2, 3) - */ - @TableField("level") - private Integer level; - - /** - * 年级描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Homework.java b/java-backend/src/main/java/com/lesingle/creation/entity/Homework.java deleted file mode 100644 index 4c82d63..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Homework.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 作业表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework") -public class Homework extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 作业名称 - */ - @TableField("name") - private String name; - - /** - * 作业内容(富文本) - */ - @TableField("content") - private String content; - - /** - * 作业状态:unpublished/published - */ - @TableField("status") - private String status; - - /** - * 发布时间 - */ - @TableField("publish_time") - private java.time.LocalDateTime publishTime; - - /** - * 提交开始时间 - */ - @TableField("submit_start_time") - private java.time.LocalDateTime submitStartTime; - - /** - * 提交结束时间 - */ - @TableField("submit_end_time") - private java.time.LocalDateTime submitEndTime; - - /** - * 附件列表(JSON 格式) - */ - @TableField("attachments") - private String attachments; - - /** - * 公开范围(班级 ID 数组 JSON 格式) - */ - @TableField("publish_scope") - private String publishScope; - - /** - * 评审规则 ID - */ - @TableField("review_rule_id") - private Long reviewRuleId; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java deleted file mode 100644 index 20c6a4a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewDimension.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业评审维度实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_review_dimension") -public class HomeworkReviewDimension extends BaseEntity { - - /** - * 规则 ID - */ - @TableField("rule_id") - private Long ruleId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 维度名称 - */ - @TableField("name") - private String name; - - /** - * 满分 - */ - @TableField("max_score") - private BigDecimal maxScore; - - /** - * 维度描述 - */ - @TableField("description") - private String description; - - /** - * 排序顺序 - */ - @TableField("sort_order") - private Integer sortOrder; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java deleted file mode 100644 index 9fe0fcd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkReviewRule.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业评审规则表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_review_rule") -public class HomeworkReviewRule extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 规则名称 - */ - @TableField("rule_name") - private String ruleName; - - /** - * 规则类型:default/custom - */ - @TableField("rule_type") - private String ruleType; - - /** - * 总分 - */ - @TableField("total_score") - private BigDecimal totalScore; - - /** - * 规则描述 - */ - @TableField("description") - private String description; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java deleted file mode 100644 index 4f1d676..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkScore.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业评分表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_score") -public class HomeworkScore extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 提交 ID - */ - @TableField("submission_id") - private Long submissionId; - - /** - * 作业 ID - */ - @TableField("homework_id") - private Long homeworkId; - - /** - * 评分人 ID - */ - @TableField("reviewer_id") - private Long reviewerId; - - /** - * 得分 - */ - @TableField("score") - private BigDecimal score; - - /** - * 评语 - */ - @TableField("comment") - private String comment; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java b/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java deleted file mode 100644 index 3e88557..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/HomeworkSubmission.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.math.BigDecimal; - -/** - * 作业提交表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_homework_submission") -public class HomeworkSubmission extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 作业 ID - */ - @TableField("homework_id") - private Long homeworkId; - - /** - * 学生用户 ID - */ - @TableField("student_id") - private Long studentId; - - /** - * 学生姓名 - */ - @TableField("student_name") - private String studentName; - - /** - * 提交内容 - */ - @TableField("content") - private String content; - - /** - * 提交附件列表(JSON 格式) - */ - @TableField("attachments") - private String attachments; - - /** - * 提交状态:submitted/reviewing/returned - */ - @TableField("status") - private String status; - - /** - * 提交时间 - */ - @TableField("submit_time") - private java.time.LocalDateTime submitTime; - - /** - * 批改时间 - */ - @TableField("review_time") - private java.time.LocalDateTime reviewTime; - - /** - * 批改人 ID - */ - @TableField("reviewer_id") - private Long reviewerId; - - /** - * 批改评语 - */ - @TableField("review_comment") - private String reviewComment; - - /** - * 批改分数 - */ - @TableField("review_score") - private BigDecimal reviewScore; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Menu.java b/java-backend/src/main/java/com/lesingle/creation/entity/Menu.java deleted file mode 100644 index cd9e89d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Menu.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.util.List; - -/** - * 菜单表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_auth_menu") -public class Menu extends BaseEntity { - - /** - * 菜单名称 - */ - @TableField("name") - private String name; - - /** - * 路由路径 - */ - @TableField("path") - private String path; - - /** - * 图标 - */ - @TableField("icon") - private String icon; - - /** - * 组件路径 - */ - @TableField("component") - private String component; - - /** - * 父菜单 ID - */ - @TableField("parent_id") - private Long parentId; - - /** - * 权限编码(用于控制菜单显示) - */ - @TableField("permission") - private String permission; - - /** - * 排序 - */ - @TableField("sort") - private Integer sort; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; - - /** - * 子菜单列表(非数据库字段) - */ - @TableField(exist = false) - private List

children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Permission.java b/java-backend/src/main/java/com/lesingle/creation/entity/Permission.java deleted file mode 100644 index eae825e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Permission.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 权限表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_auth_permission") -public class Permission extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 权限名称 - */ - @TableField("name") - private String name; - - /** - * 权限编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 资源名称,如 user, role, menu - */ - @TableField("resource") - private String resource; - - /** - * 操作类型,如 create, read, update, delete - */ - @TableField("action") - private String action; - - /** - * 权限描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Role.java b/java-backend/src/main/java/com/lesingle/creation/entity/Role.java deleted file mode 100644 index 92ea0c3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Role.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 角色表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_auth_role") -public class Role extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 角色名称(在租户内唯一) - */ - @TableField("name") - private String name; - - /** - * 角色编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 角色描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/RolePermission.java b/java-backend/src/main/java/com/lesingle/creation/entity/RolePermission.java deleted file mode 100644 index 90817cd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/RolePermission.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * 角色权限关联表实体类 - */ -@Data -@TableName("t_auth_role_permission") -public class RolePermission { - - /** - * 主键 ID - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 角色 ID - */ - @TableField("role_id") - private Long roleId; - - /** - * 权限 ID - */ - @TableField("permission_id") - private Long permissionId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/School.java b/java-backend/src/main/java/com/lesingle/creation/entity/School.java deleted file mode 100644 index 45f5de0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/School.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDate; - -/** - * 学校信息表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_school") -public class School extends BaseEntity { - - /** - * 租户 ID(一对一) - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 学校地址 - */ - @TableField("address") - private String address; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 校长姓名 - */ - @TableField("principal") - private String principal; - - /** - * 建校时间 - */ - @TableField("established") - private LocalDate established; - - /** - * 学校描述 - */ - @TableField("description") - private String description; - - /** - * 学校 Logo URL - */ - @TableField("logo") - private String logo; - - /** - * 学校网站 - */ - @TableField("website") - private String website; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java b/java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java deleted file mode 100644 index 14fdd89..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/SchoolClass.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 班级表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_class") -public class SchoolClass extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 年级 ID - */ - @TableField("grade_id") - private Long gradeId; - - /** - * 班级名称(如:一年级 1 班、二年级 2 班) - */ - @TableField("name") - private String name; - - /** - * 班级编码(在租户内唯一) - */ - @TableField("code") - private String code; - - /** - * 班级类型:1-行政班级(教学班级),2-兴趣班 - */ - @TableField("type") - private Integer type; - - /** - * 班级容量(可选) - */ - @TableField("capacity") - private Integer capacity; - - /** - * 班级描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Student.java b/java-backend/src/main/java/com/lesingle/creation/entity/Student.java deleted file mode 100644 index 3c4b139..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Student.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDate; - -/** - * 学生表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_student") -public class Student extends BaseEntity { - - /** - * 用户 ID(一对一) - */ - @TableField("user_id") - private Long userId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 行政班级 ID - */ - @TableField("class_id") - private Long classId; - - /** - * 学号(在租户内唯一) - */ - @TableField("student_no") - private String studentNo; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 身份证号 - */ - @TableField("id_card") - private String idCard; - - /** - * 性别:1-男,2-女 - */ - @TableField("gender") - private Integer gender; - - /** - * 出生日期 - */ - @TableField("birth_date") - private LocalDate birthDate; - - /** - * 入学日期 - */ - @TableField("enrollment_date") - private LocalDate enrollmentDate; - - /** - * 家长姓名 - */ - @TableField("parent_name") - private String parentName; - - /** - * 家长电话 - */ - @TableField("parent_phone") - private String parentPhone; - - /** - * 家庭地址 - */ - @TableField("address") - private String address; - - /** - * 学生描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/SysConfig.java b/java-backend/src/main/java/com/lesingle/creation/entity/SysConfig.java deleted file mode 100644 index 6a8e502..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/SysConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 系统配置表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_sys_config") -public class SysConfig extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 配置键(在租户内唯一) - */ - @TableField("config_key") - private String configKey; - - /** - * 配置值 - */ - @TableField("config_value") - private String configValue; - - /** - * 配置名称 - */ - @TableField("config_name") - private String configName; - - /** - * 配置描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/SysLog.java b/java-backend/src/main/java/com/lesingle/creation/entity/SysLog.java deleted file mode 100644 index 89b6c02..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/SysLog.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 系统日志表实体类 - */ -@Data -@TableName("t_sys_log") -public class SysLog { - - /** - * 主键 ID - */ - @TableId(value = "id", type = IdType.AUTO) - private Long id; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 用户 ID - */ - @TableField("user_id") - private Long userId; - - /** - * 用户名 - */ - @TableField("username") - private String username; - - /** - * 操作模块 - */ - @TableField("module") - private String module; - - /** - * 操作类型 - */ - @TableField("action") - private String action; - - /** - * 操作描述 - */ - @TableField("content") - private String content; - - /** - * 请求 IP - */ - @TableField("ip") - private String ip; - - /** - * 用户代理 - */ - @TableField("user_agent") - private String userAgent; - - /** - * 请求方法 - */ - @TableField("request_method") - private String requestMethod; - - /** - * 请求 URL - */ - @TableField("request_url") - private String requestUrl; - - /** - * 操作时长 (ms) - */ - @TableField("duration") - private Long duration; - - /** - * 操作状态:success/failure - */ - @TableField("status") - private String status; - - /** - * 错误信息 - */ - @TableField("error_message") - private String errorMessage; - - /** - * 创建时间 - */ - @TableField("create_time") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java b/java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java deleted file mode 100644 index 8ada535..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Teacher.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -import java.time.LocalDate; - -/** - * 教师表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_biz_teacher") -public class Teacher extends BaseEntity { - - /** - * 用户 ID(一对一) - */ - @TableField("user_id") - private Long userId; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 部门 ID - */ - @TableField("department_id") - private Long departmentId; - - /** - * 工号(在租户内唯一) - */ - @TableField("employee_no") - private String employeeNo; - - /** - * 联系电话 - */ - @TableField("phone") - private String phone; - - /** - * 身份证号 - */ - @TableField("id_card") - private String idCard; - - /** - * 性别:1-男,2-女 - */ - @TableField("gender") - private Integer gender; - - /** - * 出生日期 - */ - @TableField("birth_date") - private LocalDate birthDate; - - /** - * 入职日期 - */ - @TableField("hire_date") - private LocalDate hireDate; - - /** - * 任教科目(可选,如:语文、数学) - */ - @TableField("subject") - private String subject; - - /** - * 职称(可选,如:高级教师、一级教师) - */ - @TableField("title") - private String title; - - /** - * 教师描述 - */ - @TableField("description") - private String description; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/Tenant.java b/java-backend/src/main/java/com/lesingle/creation/entity/Tenant.java deleted file mode 100644 index 00a8375..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/Tenant.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 租户表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_sys_tenant") -public class Tenant extends BaseEntity { - - /** - * 租户名称 - */ - @TableField("name") - private String name; - - /** - * 租户编码(唯一,用于访问链接) - */ - @TableField("code") - private String code; - - /** - * 租户域名(可选,用于子域名访问) - */ - @TableField("domain") - private String domain; - - /** - * 租户描述 - */ - @TableField("description") - private String description; - - /** - * 是否为超级租户:0-否,1-是 - */ - @TableField("is_super") - private Integer isSuper; - - /** - * 租户类型:platform/library/kindergarten/school/institution/other - */ - @TableField("tenant_type") - private String tenantType; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/TenantMenu.java b/java-backend/src/main/java/com/lesingle/creation/entity/TenantMenu.java deleted file mode 100644 index 420b4d2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/TenantMenu.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -/** - * 租户菜单关联表实体类 - */ -@Data -@TableName("t_auth_tenant_menu") -public class TenantMenu { - - /** - * 主键 ID - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 菜单 ID - */ - @TableField("menu_id") - private Long menuId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/User.java b/java-backend/src/main/java/com/lesingle/creation/entity/User.java deleted file mode 100644 index eeb17fe..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/User.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.lesingle.creation.common.base.BaseEntity; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 用户表实体类 - */ -@Data -@EqualsAndHashCode(callSuper = true) -@TableName("t_sys_user") -public class User extends BaseEntity { - - /** - * 租户 ID - */ - @TableField("tenant_id") - private Long tenantId; - - /** - * 用户名(在租户内唯一) - */ - @TableField("username") - private String username; - - /** - * 密码(加密存储) - */ - @TableField("password") - private String password; - - /** - * 昵称 - */ - @TableField("nickname") - private String nickname; - - /** - * 邮箱(在租户内唯一,可选) - */ - @TableField("email") - private String email; - - /** - * 手机号(全局唯一,用于手机号登录) - */ - @TableField("phone") - private String phone; - - /** - * 微信 OpenID - */ - @TableField("wx_openid") - private String wxOpenid; - - /** - * 微信 UnionID - */ - @TableField("wx_unionid") - private String wxUnionid; - - /** - * 用户来源:admin_created/self_registered/child_migrated - */ - @TableField("user_source") - private String userSource; - - /** - * 用户类型:adult/child - */ - @TableField("user_type") - private String userType; - - /** - * 所在城市 - */ - @TableField("city") - private String city; - - /** - * 出生日期 - */ - @TableField("birthday") - private java.time.LocalDate birthday; - - /** - * 性别:male-男,female-女 - */ - @TableField("gender") - private String gender; - - /** - * 头像 URL - */ - @TableField("avatar") - private String avatar; - - /** - * 所属单位(用于评委等独立用户) - */ - @TableField("organization") - private String organization; - - /** - * 账号状态:enabled-启用,disabled-停用 - */ - @TableField("status") - private String status; - - /** - * 有效状态:1-有效,2-失效 - */ - @TableField("valid_state") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/UserChild.java b/java-backend/src/main/java/com/lesingle/creation/entity/UserChild.java deleted file mode 100644 index 017a583..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/UserChild.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; - -/** - * 用户子女关系实体类 - * 中间表,不使用逻辑删除和审计字段 - */ -@Data -@TableName("t_user_child") -public class UserChild implements Serializable { - - private static final long serialVersionUID = 1L; - - /** - * 父母用户 ID - */ - @TableField("parent_id") - private Long parentId; - - /** - * 子女用户 ID - */ - @TableField("child_user_id") - private Long childUserId; - - /** - * 与子女关系 - */ - @TableField("relationship") - private String relationship; - - /** - * 管控模式:full/control/free - */ - @TableField("control_mode") - private String controlMode; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/entity/UserRole.java b/java-backend/src/main/java/com/lesingle/creation/entity/UserRole.java deleted file mode 100644 index 1e8c116..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/entity/UserRole.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; - -import java.io.Serializable; - -/** - * 用户角色关联表实体类 - * 中间表,不使用逻辑删除和审计字段 - */ -@Data -@TableName("t_auth_user_role") -public class UserRole implements Serializable { - - private static final long serialVersionUID = 1L; - /** - * 主键 ID - */ - @TableId(type = IdType.AUTO) - private Long id; - - /** - * 用户 ID - */ - @TableField("user_id") - private Long userId; - - /** - * 角色 ID - */ - @TableField("role_id") - private Long roleId; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/AI3DTaskMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/AI3DTaskMapper.java deleted file mode 100644 index 83ac3b3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/AI3DTaskMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.AI3DTask; -import org.apache.ibatis.annotations.Mapper; - -/** - * AI 3D 任务 Mapper 接口 - */ -@Mapper -public interface AI3DTaskMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestAttachmentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestAttachmentMapper.java deleted file mode 100644 index 3bd7f7f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestAttachmentMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestAttachment; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 竞赛附件 Mapper 接口 - */ -@Mapper -public interface ContestAttachmentMapper extends BaseMapper { - - /** - * 根据竞赛 ID 查询附件列表 - * - * @param contestId 竞赛 ID - * @return 附件列表 - */ - @Select("SELECT * FROM t_biz_contest_attachment WHERE contest_id = #{contestId} AND deleted = 0 ORDER BY sort ASC") - List selectByContestId(@Param("contestId") Long contestId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestJudgeMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestJudgeMapper.java deleted file mode 100644 index 9661dba..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestJudgeMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestJudge; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛评委 Mapper 接口 - */ -@Mapper -public interface ContestJudgeMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestMapper.java deleted file mode 100644 index 811146d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Contest; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 竞赛 Mapper 接口 - */ -@Mapper -public interface ContestMapper extends BaseMapper { - - /** - * 根据竞赛名称查询竞赛 - * - * @param contestName 竞赛名称 - * @return 竞赛实体 - */ - @Select("SELECT * FROM t_biz_contest WHERE contest_name = #{contestName} AND deleted = 0") - Contest selectByContestName(@Param("contestName") String contestName); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestNoticeMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestNoticeMapper.java deleted file mode 100644 index c0f4792..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestNoticeMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestNotice; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛公告 Mapper 接口 - */ -@Mapper -public interface ContestNoticeMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestPresetCommentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestPresetCommentMapper.java deleted file mode 100644 index 30ba556..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestPresetCommentMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestPresetComment; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛预设评语 Mapper 接口 - */ -@Mapper -public interface ContestPresetCommentMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestRegistrationMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestRegistrationMapper.java deleted file mode 100644 index e51f699..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestRegistrationMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.entity.ContestRegistration; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -/** - * 竞赛报名 Mapper 接口 - */ -@Mapper -public interface ContestRegistrationMapper extends BaseMapper { - - /** - * 分页查询竞赛报名 - * - * @param page 分页对象 - * @param wrapper 查询条件 - * @return 分页结果 - */ - Page page(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper wrapper); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestRegistrationTeacherMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestRegistrationTeacherMapper.java deleted file mode 100644 index 1dfea8a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestRegistrationTeacherMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestRegistrationTeacher; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛报名指导老师 Mapper 接口 - */ -@Mapper -public interface ContestRegistrationTeacherMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestResultMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestResultMapper.java deleted file mode 100644 index 1818b12..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestResultMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestResult; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛结果 Mapper 接口 - */ -@Mapper -public interface ContestResultMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestReviewDimensionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestReviewDimensionMapper.java deleted file mode 100644 index 97cd78b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestReviewDimensionMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestReviewDimension; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛评审维度 Mapper 接口 - */ -@Mapper -public interface ContestReviewDimensionMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestReviewRuleMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestReviewRuleMapper.java deleted file mode 100644 index 25ea70f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestReviewRuleMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestReviewRule; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛评审规则 Mapper 接口 - */ -@Mapper -public interface ContestReviewRuleMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestTeamMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestTeamMapper.java deleted file mode 100644 index 34cafb2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestTeamMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestTeam; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛团队 Mapper 接口 - */ -@Mapper -public interface ContestTeamMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestTeamMemberMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestTeamMemberMapper.java deleted file mode 100644 index dcc2f35..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestTeamMemberMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestTeamMember; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛团队成员 Mapper 接口 - */ -@Mapper -public interface ContestTeamMemberMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkAssignmentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkAssignmentMapper.java deleted file mode 100644 index 7a2f202..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkAssignmentMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.entity.ContestWorkAssignment; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -/** - * 竞赛作品评审分配 Mapper 接口 - */ -@Mapper -public interface ContestWorkAssignmentMapper extends BaseMapper { - - /** - * 分页查询竞赛作品评审分配 - * - * @param page 分页对象 - * @param wrapper 查询条件 - * @return 分页结果 - */ - Page page(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper wrapper); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkAttachmentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkAttachmentMapper.java deleted file mode 100644 index b57fff6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkAttachmentMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestWorkAttachment; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛作品附件 Mapper 接口 - */ -@Mapper -public interface ContestWorkAttachmentMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkMapper.java deleted file mode 100644 index 03143fa..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.conditions.Wrapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.baomidou.mybatisplus.core.toolkit.Constants; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.entity.ContestWork; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -/** - * 竞赛作品 Mapper 接口 - */ -@Mapper -public interface ContestWorkMapper extends BaseMapper { - - /** - * 分页查询竞赛作品 - * - * @param page 分页对象 - * @param wrapper 查询条件 - * @return 分页结果 - */ - Page page(@Param("page") Page page, @Param(Constants.WRAPPER) Wrapper wrapper); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkScoreMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkScoreMapper.java deleted file mode 100644 index 2c30d19..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/ContestWorkScoreMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.ContestWorkScore; -import org.apache.ibatis.annotations.Mapper; - -/** - * 竞赛作品评分 Mapper 接口 - */ -@Mapper -public interface ContestWorkScoreMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java deleted file mode 100644 index eb24749..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/DepartmentMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Department; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 部门 Mapper 接口 - */ -@Mapper -public interface DepartmentMapper extends BaseMapper { - - /** - * 根据租户 ID 和部门编码查询部门 - * - * @param tenantId 租户 ID - * @param code 部门编码 - * @return 部门实体 - */ - @Select("SELECT * FROM t_biz_department WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Department selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 查询部门列表 - * - * @param tenantId 租户 ID - * @return 部门列表 - */ - @Select("SELECT * FROM t_biz_department WHERE tenant_id = #{tenantId} AND deleted = 0 ORDER BY sort ASC") - List selectByTenantId(@Param("tenantId") Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/DictItemMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/DictItemMapper.java deleted file mode 100644 index 641e7f6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/DictItemMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.DictItem; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 字典项 Mapper 接口 - */ -@Mapper -public interface DictItemMapper extends BaseMapper { - - /** - * 根据字典 ID 查询字典项列表 - * - * @param dictId 字典 ID - * @return 字典项列表 - */ - @Select("SELECT * FROM t_sys_dict_item WHERE dict_id = #{dictId} AND deleted = 0 ORDER BY sort ASC") - List selectByDictId(@Param("dictId") Long dictId); - - /** - * 批量插入字典项 - * - * @param dictItems 字典项列表 - * @return 插入数量 - */ - int insertBatch(@Param("list") List dictItems); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/DictMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/DictMapper.java deleted file mode 100644 index 794d4d0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/DictMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Dict; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 字典 Mapper 接口 - */ -@Mapper -public interface DictMapper extends BaseMapper { - - /** - * 根据租户 ID 和字典编码查询字典 - * - * @param tenantId 租户 ID - * @param code 字典编码 - * @return 字典实体 - */ - @Select("SELECT * FROM t_sys_dict WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Dict selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 和字典编码查询字典(排除指定 ID) - * - * @param tenantId 租户 ID - * @param code 字典编码 - * @param excludeId 排除的 ID - * @return 字典实体 - */ - @Select("SELECT * FROM t_sys_dict WHERE tenant_id = #{tenantId} AND code = #{code} AND id != #{excludeId} AND deleted = 0") - Dict selectByCodeExclude(@Param("tenantId") Long tenantId, @Param("code") String code, @Param("excludeId") Long excludeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java deleted file mode 100644 index 0459eb9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/GradeMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Grade; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 年级 Mapper 接口 - */ -@Mapper -public interface GradeMapper extends BaseMapper { - - /** - * 根据租户 ID 和年级编码查询年级 - * - * @param tenantId 租户 ID - * @param code 年级编码 - * @return 年级实体 - */ - @Select("SELECT * FROM t_biz_grade WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Grade selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 查询年级列表 - * - * @param tenantId 租户 ID - * @return 年级列表 - */ - @Select("SELECT * FROM t_biz_grade WHERE tenant_id = #{tenantId} AND deleted = 0 ORDER BY level ASC") - List selectByTenantId(@Param("tenantId") Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java deleted file mode 100644 index 10a679a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Homework; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业 Mapper 接口 - */ -@Mapper -public interface HomeworkMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java deleted file mode 100644 index b55284d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewDimensionMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkReviewDimension; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.math.BigDecimal; -import java.util.List; - -/** - * 作业评审维度 Mapper 接口 - */ -@Mapper -public interface HomeworkReviewDimensionMapper extends BaseMapper { - - /** - * 根据规则 ID 删除维度 - */ - void deleteByRuleId(@Param("ruleId") Long ruleId); - - /** - * 根据规则 ID 查询维度列表 - */ - List selectByRuleId(@Param("ruleId") Long ruleId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java deleted file mode 100644 index 46d9359..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkReviewRuleMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkReviewRule; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业评审规则 Mapper 接口 - */ -@Mapper -public interface HomeworkReviewRuleMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java deleted file mode 100644 index 52b71f1..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkScoreMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkScore; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业评分 Mapper 接口 - */ -@Mapper -public interface HomeworkScoreMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java deleted file mode 100644 index a82040f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/HomeworkSubmissionMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.HomeworkSubmission; -import org.apache.ibatis.annotations.Mapper; - -/** - * 作业提交 Mapper 接口 - */ -@Mapper -public interface HomeworkSubmissionMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/MenuMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/MenuMapper.java deleted file mode 100644 index 125f715..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/MenuMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Menu; -import org.apache.ibatis.annotations.Mapper; - -/** - * 菜单 Mapper 接口 - */ -@Mapper -public interface MenuMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/PermissionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/PermissionMapper.java deleted file mode 100644 index 7d98657..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/PermissionMapper.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Permission; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 权限 Mapper 接口 - */ -@Mapper -public interface PermissionMapper extends BaseMapper { - - /** - * 根据租户 ID 和权限编码查询权限 - * - * @param tenantId 租户 ID - * @param code 权限编码 - * @return 权限实体 - */ - @Select("SELECT * FROM t_auth_permission WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Permission selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 和资源操作查询权限 - * - * @param tenantId 租户 ID - * @param resource 资源名称 - * @param action 操作类型 - * @return 权限实体 - */ - @Select("SELECT * FROM t_auth_permission WHERE tenant_id = #{tenantId} AND resource = #{resource} AND action = #{action} AND deleted = 0") - Permission selectByResourceAction(@Param("tenantId") Long tenantId, @Param("resource") String resource, @Param("action") String action); - - /** - * 根据租户 ID 和权限编码查询权限(排除指定 ID) - * - * @param tenantId 租户 ID - * @param code 权限编码 - * @param excludeId 排除的 ID - * @return 权限实体 - */ - @Select("SELECT * FROM t_auth_permission WHERE tenant_id = #{tenantId} AND code = #{code} AND id != #{excludeId} AND deleted = 0") - Permission selectByCodeExclude(@Param("tenantId") Long tenantId, @Param("code") String code, @Param("excludeId") Long excludeId); - - /** - * 根据租户 ID 和资源操作查询权限(排除指定 ID) - * - * @param tenantId 租户 ID - * @param resource 资源名称 - * @param action 操作类型 - * @param excludeId 排除的 ID - * @return 权限实体 - */ - @Select("SELECT * FROM t_auth_permission WHERE tenant_id = #{tenantId} AND resource = #{resource} AND action = #{action} AND id != #{excludeId} AND deleted = 0") - Permission selectByResourceActionExclude(@Param("tenantId") Long tenantId, @Param("resource") String resource, @Param("action") String action, @Param("excludeId") Long excludeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/RoleMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/RoleMapper.java deleted file mode 100644 index 9142cb2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/RoleMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Role; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 角色 Mapper 接口 - */ -@Mapper -public interface RoleMapper extends BaseMapper { - - /** - * 根据租户 ID 和角色编码查询角色 - * - * @param tenantId 租户 ID - * @param code 角色编码 - * @return 角色实体 - */ - @Select("SELECT * FROM t_auth_role WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - Role selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据租户 ID 和角色编码查询角色(排除指定 ID) - * - * @param tenantId 租户 ID - * @param code 角色编码 - * @param excludeId 排除的 ID - * @return 角色实体 - */ - @Select("SELECT * FROM t_auth_role WHERE tenant_id = #{tenantId} AND code = #{code} AND id != #{excludeId} AND deleted = 0") - Role selectByCodeExclude(@Param("tenantId") Long tenantId, @Param("code") String code, @Param("excludeId") Long excludeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/RolePermissionMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/RolePermissionMapper.java deleted file mode 100644 index 32ac5b3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/RolePermissionMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.RolePermission; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -/** - * 角色权限 Mapper 接口 - */ -@Mapper -public interface RolePermissionMapper extends BaseMapper { - - /** - * 批量插入角色权限关联 - * - * @param rolePermissions 角色权限列表 - * @return 插入数量 - */ - int insertBatch(@Param("list") List rolePermissions); - - /** - * 批量保存角色权限关联 - * - * @param rolePermissions 角色权限列表 - * @return 插入数量 - */ - int saveBatch(@Param("list") List rolePermissions); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java deleted file mode 100644 index d0ca96f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolClassMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.SchoolClass; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -import java.util.List; - -/** - * 班级 Mapper 接口 - */ -@Mapper -public interface SchoolClassMapper extends BaseMapper { - - /** - * 根据租户 ID 和班级编码查询班级 - * - * @param tenantId 租户 ID - * @param code 班级编码 - * @return 班级实体 - */ - @Select("SELECT * FROM t_biz_class WHERE tenant_id = #{tenantId} AND code = #{code} AND deleted = 0") - SchoolClass selectByCode(@Param("tenantId") Long tenantId, @Param("code") String code); - - /** - * 根据年级 ID 查询班级列表 - * - * @param gradeId 年级 ID - * @return 班级列表 - */ - @Select("SELECT * FROM t_biz_class WHERE grade_id = #{gradeId} AND deleted = 0 ORDER BY name ASC") - List selectByGradeId(@Param("gradeId") Long gradeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java deleted file mode 100644 index b9fa279..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/SchoolMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.School; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 学校信息 Mapper 接口 - */ -@Mapper -public interface SchoolMapper extends BaseMapper { - - /** - * 根据租户 ID 查询学校 - * - * @param tenantId 租户 ID - * @return 学校实体 - */ - @Select("SELECT * FROM t_biz_school WHERE tenant_id = #{tenantId} AND deleted = 0") - School selectByTenantId(@Param("tenantId") Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java deleted file mode 100644 index 9f48aa0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/StudentMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Student; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 学生 Mapper 接口 - */ -@Mapper -public interface StudentMapper extends BaseMapper { - - /** - * 根据用户 ID 查询学生 - * - * @param userId 用户 ID - * @return 学生实体 - */ - @Select("SELECT * FROM t_biz_student WHERE user_id = #{userId} AND deleted = 0") - Student selectByUserId(@Param("userId") Long userId); - - /** - * 根据租户 ID 和学号查询学生 - * - * @param tenantId 租户 ID - * @param studentNo 学号 - * @return 学生实体 - */ - @Select("SELECT * FROM t_biz_student WHERE tenant_id = #{tenantId} AND student_no = #{studentNo} AND deleted = 0") - Student selectByStudentNo(@Param("tenantId") Long tenantId, @Param("studentNo") String studentNo); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/SysConfigMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/SysConfigMapper.java deleted file mode 100644 index f1f54f6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/SysConfigMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.SysConfig; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 系统配置 Mapper 接口 - */ -@Mapper -public interface SysConfigMapper extends BaseMapper { - - /** - * 根据租户 ID 和配置键查询配置 - * - * @param tenantId 租户 ID - * @param configKey 配置键 - * @return 配置实体 - */ - @Select("SELECT * FROM t_sys_config WHERE tenant_id = #{tenantId} AND config_key = #{configKey} AND deleted = 0") - SysConfig selectByKey(@Param("tenantId") Long tenantId, @Param("configKey") String configKey); - - /** - * 根据租户 ID 和配置键查询配置(排除指定 ID) - * - * @param tenantId 租户 ID - * @param configKey 配置键 - * @param excludeId 排除的 ID - * @return 配置实体 - */ - @Select("SELECT * FROM t_sys_config WHERE tenant_id = #{tenantId} AND config_key = #{configKey} AND id != #{excludeId} AND deleted = 0") - SysConfig selectByKeyExclude(@Param("tenantId") Long tenantId, @Param("configKey") String configKey, @Param("excludeId") Long excludeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/SysLogMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/SysLogMapper.java deleted file mode 100644 index c879f46..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/SysLogMapper.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.SysLog; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.Map; - -/** - * 系统日志 Mapper 接口 - */ -@Mapper -public interface SysLogMapper extends BaseMapper { - - /** - * 获取日志统计数据 - */ - Map getStatistics(@Param("days") Integer days); - - /** - * 获取按操作类型统计的日志 - */ - List> getActionStats(@Param("days") Integer days); - - /** - * 获取按天统计的日志 - */ - List> getDailyStats(@Param("days") Integer days); - - /** - * 清理过期日志 - */ - int deleteOldLogs(@Param("cutoffDate") LocalDateTime cutoffDate); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java deleted file mode 100644 index ebd9a0f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/TeacherMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Teacher; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 教师 Mapper 接口 - */ -@Mapper -public interface TeacherMapper extends BaseMapper { - - /** - * 根据用户 ID 查询教师 - * - * @param userId 用户 ID - * @return 教师实体 - */ - @Select("SELECT * FROM t_biz_teacher WHERE user_id = #{userId} AND deleted = 0") - Teacher selectByUserId(@Param("userId") Long userId); - - /** - * 根据租户 ID 和工号查询教师 - * - * @param tenantId 租户 ID - * @param employeeNo 工号 - * @return 教师实体 - */ - @Select("SELECT * FROM t_biz_teacher WHERE tenant_id = #{tenantId} AND employee_no = #{employeeNo} AND deleted = 0") - Teacher selectByEmployeeNo(@Param("tenantId") Long tenantId, @Param("employeeNo") String employeeNo); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/TenantMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/TenantMapper.java deleted file mode 100644 index e69637d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/TenantMapper.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.Tenant; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 租户 Mapper 接口 - */ -@Mapper -public interface TenantMapper extends BaseMapper { - - /** - * 根据编码查询租户 - * - * @param code 租户编码 - * @return 租户实体 - */ - @Select("SELECT * FROM t_sys_tenant WHERE code = #{code} AND deleted = 0") - Tenant selectByCode(@Param("code") String code); - - /** - * 根据域名查询租户 - * - * @param domain 租户域名 - * @return 租户实体 - */ - @Select("SELECT * FROM t_sys_tenant WHERE domain = #{domain} AND deleted = 0") - Tenant selectByDomain(@Param("domain") String domain); - - /** - * 根据编码查询租户(排除指定 ID,用于更新时检查重复) - * - * @param code 租户编码 - * @param excludeId 排除的 ID - * @return 租户实体 - */ - @Select("SELECT * FROM t_sys_tenant WHERE code = #{code} AND id != #{excludeId} AND deleted = 0") - Tenant selectByCodeExclude(@Param("code") String code, @Param("excludeId") Long excludeId); - - /** - * 根据域名查询租户(排除指定 ID,用于更新时检查重复) - * - * @param domain 租户域名 - * @param excludeId 排除的 ID - * @return 租户实体 - */ - @Select("SELECT * FROM t_sys_tenant WHERE domain = #{domain} AND id != #{excludeId} AND deleted = 0") - Tenant selectByDomainExclude(@Param("domain") String domain, @Param("excludeId") Long excludeId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/TenantMenuMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/TenantMenuMapper.java deleted file mode 100644 index b4c36ea..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/TenantMenuMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.TenantMenu; -import org.apache.ibatis.annotations.Mapper; - -/** - * 租户菜单 Mapper 接口 - */ -@Mapper -public interface TenantMenuMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/UserChildMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/UserChildMapper.java deleted file mode 100644 index 0ee9585..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/UserChildMapper.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.UserChild; -import org.apache.ibatis.annotations.Mapper; - -/** - * 用户子女关系 Mapper - */ -@Mapper -public interface UserChildMapper extends BaseMapper { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/UserMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/UserMapper.java deleted file mode 100644 index 31a0e3c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/UserMapper.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.User; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; - -/** - * 用户 Mapper 接口 - */ -@Mapper -public interface UserMapper extends BaseMapper { - - /** - * 根据用户名查询用户 - * - * @param tenantId 租户 ID - * @param username 用户名 - * @return 用户实体 - */ - @Select("SELECT * FROM t_sys_user WHERE tenant_id = #{tenantId} AND username = #{username} AND deleted = 0") - User selectByusername(@Param("tenantId") Long tenantId, @Param("username") String username); - - /** - * 根据用户名查询用户(排除指定 ID,用于更新时检查重复) - * - * @param tenantId 租户 ID - * @param username 用户名 - * @param excludeId 排除的 ID - * @return 用户实体 - */ - @Select("SELECT * FROM t_sys_user WHERE tenant_id = #{tenantId} AND username = #{username} AND id != #{excludeId} AND deleted = 0") - User selectByusernameExclude(@Param("tenantId") Long tenantId, @Param("username") String username, @Param("excludeId") Long excludeId); - - /** - * 根据邮箱查询用户 - * - * @param tenantId 租户 ID - * @param email 邮箱 - * @return 用户实体 - */ - @Select("SELECT * FROM t_sys_user WHERE tenant_id = #{tenantId} AND email = #{email} AND deleted = 0") - User selectByEmail(@Param("tenantId") Long tenantId, @Param("email") String email); - - /** - * 根据手机号查询用户 - * - * @param phone 手机号 - * @return 用户实体 - */ - @Select("SELECT * FROM t_sys_user WHERE phone = #{phone} AND deleted = 0") - User selectByPhone(@Param("phone") String phone); - - /** - * 根据邮箱查询用户(排除指定 ID,用于更新时检查重复) - * - * @param tenantId 租户 ID - * @param email 邮箱 - * @param excludeId 排除的 ID - * @return 用户实体 - */ - @Select("SELECT * FROM t_sys_user WHERE tenant_id = #{tenantId} AND email = #{email} AND id != #{excludeId} AND deleted = 0") - User selectByEmailExclude(@Param("tenantId") Long tenantId, @Param("email") String email, @Param("excludeId") Long excludeId); - - /** - * 根据用户名查询用户(不限制租户,用于公众用户注册登录) - * - * @param username 用户名 - * @return 用户实体 - */ - @Select("SELECT * FROM t_sys_user WHERE username = #{username} AND deleted = 0") - User selectByUsername(@Param("username") String username); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/mapper/UserRoleMapper.java b/java-backend/src/main/java/com/lesingle/creation/mapper/UserRoleMapper.java deleted file mode 100644 index 69d3a5a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/mapper/UserRoleMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.lesingle.creation.mapper; - -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import com.lesingle.creation.entity.UserRole; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; - -/** - * 用户角色 Mapper 接口 - */ -@Mapper -public interface UserRoleMapper extends BaseMapper { - - /** - * 批量插入用户角色关联 - * - * @param userRoles 用户角色列表 - * @return 插入数量 - */ - int insertBatch(@Param("list") List userRoles); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/AI3DTaskService.java b/java-backend/src/main/java/com/lesingle/creation/service/AI3DTaskService.java deleted file mode 100644 index 96220a1..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/AI3DTaskService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.ai3d.AI3DTaskQueryDTO; -import com.lesingle.creation.dto.ai3d.CreateAI3DTaskDTO; -import com.lesingle.creation.entity.AI3DTask; -import com.lesingle.creation.vo.ai3d.AI3DTaskVO; - -/** - * AI 3D 任务服务接口 - */ -public interface AI3DTaskService extends IService { - - /** - * 创建 AI 3D 任务 - * @param dto 创建任务请求 - * @param tenantId 租户 ID - * @param userId 用户 ID - * @return 任务详情 - */ - AI3DTaskVO create(CreateAI3DTaskDTO dto, Long tenantId, Long userId); - - /** - * 获取任务详情 - * @param id 任务 ID - * @param tenantId 租户 ID - * @return 任务详情 - */ - AI3DTaskVO getDetail(Long id, Long tenantId); - - /** - * 分页查询任务列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @param userId 用户 ID(可选,查询自己的任务) - * @return 任务列表 - */ - Page pageQuery(AI3DTaskQueryDTO queryDTO, Long tenantId, Long userId); - - /** - * 取消任务 - * @param id 任务 ID - * @param tenantId 租户 ID - */ - void cancel(Long id, Long tenantId); - - /** - * 重试失败的任务 - * @param id 任务 ID - * @param tenantId 租户 ID - * @return 任务详情 - */ - AI3DTaskVO retry(Long id, Long tenantId); - - /** - * 删除 AI 3D 任务 - * @param id 任务 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/AuthService.java b/java-backend/src/main/java/com/lesingle/creation/service/AuthService.java deleted file mode 100644 index c3a3d26..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/AuthService.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.auth.LoginDTO; -import com.lesingle.creation.vo.auth.LoginResponseVO; -import com.lesingle.creation.vo.auth.UserInfoVO; - -/** - * 认证服务接口 - */ -public interface AuthService { - - /** - * 用户登录 - * - * @param loginDTO 登录请求 - * @return 登录响应 - */ - LoginResponseVO login(LoginDTO loginDTO); - - /** - * 获取用户信息 - * - * @param userId 用户 ID - * @return 用户信息 - */ - UserInfoVO getUserInfo(Long userId); - - /** - * 用户登出 - * - * @param userId 用户 ID - */ - void logout(Long userId); - - /** - * 刷新 Token - * - * @param token 旧的 Token(去掉 Bearer 前缀) - * @return 新的登录响应 - */ - LoginResponseVO refreshToken(String token); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ConfigService.java b/java-backend/src/main/java/com/lesingle/creation/service/ConfigService.java deleted file mode 100644 index 757848e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ConfigService.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.config.CreateConfigDTO; -import com.lesingle.creation.dto.config.UpdateConfigDTO; -import com.lesingle.creation.entity.SysConfig; -import com.lesingle.creation.vo.config.ConfigDetailVO; -import com.lesingle.creation.vo.config.ConfigListVO; - -/** - * 系统配置服务接口 - */ -public interface ConfigService extends IService { - - /** - * 创建配置 - * - * @param dto 创建配置 DTO - * @param tenantId 租户 ID - * @param operatorId 操作人 ID - * @return 配置详情 VO - */ - ConfigDetailVO create(CreateConfigDTO dto, Long tenantId, Long operatorId); - - /** - * 分页查询配置列表 - * - * @param tenantId 租户 ID - * @param page 页码 - * @param pageSize 每页大小 - * @return 配置列表分页数据 - */ - Page pageList(Long tenantId, int page, int pageSize); - - /** - * 根据键查询配置 - * - * @param key 配置键 - * @param tenantId 租户 ID - * @return 配置详情 VO - */ - ConfigDetailVO getByKey(String key, Long tenantId); - - /** - * 根据 ID 查询配置详情 - * - * @param id 配置 ID - * @param tenantId 租户 ID - * @return 配置详情 VO - */ - ConfigDetailVO detail(Long id, Long tenantId); - - /** - * 更新配置 - * - * @param id 配置 ID - * @param dto 更新配置 DTO - * @param tenantId 租户 ID - * @return 配置详情 VO - */ - ConfigDetailVO update(Long id, UpdateConfigDTO dto, Long tenantId); - - /** - * 删除配置 - * - * @param id 配置 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestJudgeService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestJudgeService.java deleted file mode 100644 index 88df179..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestJudgeService.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.judge.*; -import com.lesingle.creation.vo.judge.JudgeVO; - -import java.util.List; - -/** - * 竞赛评委服务接口 - */ -public interface ContestJudgeService { - - /** - * 创建评委 - * @param dto 创建评委请求 - * @param creatorId 创建人 ID - * @return 评委详情 - */ - JudgeVO create(CreateJudgeDTO dto, Long creatorId); - - /** - * 更新评委 - * @param id 评委 ID - * @param dto 更新评委请求 - * @return 评委详情 - */ - JudgeVO update(Long id, UpdateJudgeDTO dto); - - /** - * 删除评委 - * @param id 评委 ID - */ - void delete(Long id); - - /** - * 批量删除评委 - * @param ids 评委 ID 列表 - */ - void batchDelete(List ids); - - /** - * 获取评委详情 - * @param id 评委 ID - * @return 评委详情 - */ - JudgeVO getDetail(Long id); - - /** - * 查询活动的评委列表 - * @param contestId 活动 ID - * @return 评委列表 - */ - List listByContest(Long contestId); - - /** - * 冻结评委 - * @param id 评委 ID - * @return 评委详情 - */ - JudgeVO freeze(Long id); - - /** - * 解冻评委 - * @param id 评委 ID - * @return 评委详情 - */ - JudgeVO unfreeze(Long id); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestNoticeService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestNoticeService.java deleted file mode 100644 index 579792b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestNoticeService.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.notice.*; -import com.lesingle.creation.vo.notice.NoticeVO; - -import java.util.List; - -/** - * 竞赛公告服务接口 - */ -public interface ContestNoticeService { - - /** - * 创建公告 - * @param dto 创建公告请求 - * @param creatorId 创建人 ID - * @return 公告详情 - */ - NoticeVO create(CreateNoticeDTO dto, Long creatorId); - - /** - * 更新公告 - * @param id 公告 ID - * @param dto 更新公告请求 - * @return 公告详情 - */ - NoticeVO update(Long id, UpdateNoticeDTO dto); - - /** - * 删除公告 - * @param id 公告 ID - */ - void delete(Long id); - - /** - * 发布公吿 - * @param id 公告 ID - * @return 公告详情 - */ - NoticeVO publish(Long id); - - /** - * 获取公告详情 - * @param id 公告 ID - * @return 公告详情 - */ - NoticeVO getDetail(Long id); - - /** - * 查询活动的公告列表 - * @param contestId 活动 ID - * @return 公告列表 - */ - List listByContest(Long contestId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestPresetCommentService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestPresetCommentService.java deleted file mode 100644 index 66443c7..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestPresetCommentService.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.presetcomment.*; -import com.lesingle.creation.vo.presetcomment.PresetCommentVO; - -import java.util.List; - -/** - * 竞赛预设评语服务接口 - */ -public interface ContestPresetCommentService { - - /** - * 创建预设评语 - * @param dto 创建预设评语请求 - * @param tenantId 租户 ID - * @return 预设评语详情 - */ - PresetCommentVO create(CreatePresetCommentDTO dto, Long tenantId); - - /** - * 删除预设评语 - * @param id 评语 ID - */ - void delete(Long id); - - /** - * 获取预设评语详情 - * @param id 评语 ID - * @return 预设评语详情 - */ - PresetCommentVO getDetail(Long id); - - /** - * 查询活动的预设评语列表 - * @param contestId 活动 ID - * @param tenantId 租户 ID - * @return 预设评语列表 - */ - List listByContest(Long contestId, Long tenantId); - - /** - * 查询通用评语列表 - * @param tenantId 租户 ID - * @return 通用评语列表 - */ - List listCommon(Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestRegistrationService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestRegistrationService.java deleted file mode 100644 index 8baae6e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestRegistrationService.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.registration.*; -import com.lesingle.creation.entity.ContestRegistration; -import com.lesingle.creation.vo.registration.RegistrationStatsVO; -import com.lesingle.creation.vo.registration.RegistrationVO; - -import java.util.List; - -/** - * 竞赛报名服务接口 - */ -public interface ContestRegistrationService { - - /** - * 创建报名 - * @param dto 创建报名请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 报名记录 - */ - RegistrationVO create(CreateRegistrationDTO dto, Long tenantId, Long creatorId); - - /** - * 报名统计 - * @param contestId 活动 ID(可选) - * @return 统计数据 - */ - RegistrationStatsVO getStats(Long contestId); - - /** - * 分页查询报名列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 报名列表 - */ - Page pageQuery(RegistrationQueryDTO queryDTO, Long tenantId); - - /** - * 获取报名详情 - * @param id 报名 ID - * @param tenantId 租户 ID - * @return 报名详情 - */ - RegistrationVO getDetail(Long id, Long tenantId); - - /** - * 审核报名 - * @param id 报名 ID - * @param dto 审核请求 - * @param operatorId 操作人 ID - * @param tenantId 租户 ID - * @return 报名记录 - */ - RegistrationVO review(Long id, ReviewRegistrationDTO dto, Long operatorId, Long tenantId); - - /** - * 删除报名 - * @param id 报名 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); - - /** - * 添加指导老师 - * @param registrationId 报名 ID - * @param teacherUserId 老师用户 ID - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 报名记录 - */ - RegistrationVO addTeacher(Long registrationId, Long teacherUserId, Long tenantId, Long creatorId); - - /** - * 移除指导老师 - * @param registrationId 报名 ID - * @param teacherUserId 老师用户 ID - * @param tenantId 租户 ID - */ - void removeTeacher(Long registrationId, Long teacherUserId, Long tenantId); - - /** - * 获取用户在某活动中的报名记录 - * @param contestId 活动 ID - * @param userId 用户 ID - * @return 报名记录 - */ - RegistrationVO getMyRegistration(Long contestId, Long userId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestResultService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestResultService.java deleted file mode 100644 index 39a85e3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestResultService.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.result.*; -import com.lesingle.creation.vo.result.ResultVO; - -import java.util.List; - -/** - * 竞赛结果服务接口 - */ -public interface ContestResultService { - - /** - * 创建竞赛结果 - * @param dto 创建竞赛结果请求 - * @param creatorId 创建人 ID - * @return 结果详情 - */ - ResultVO create(CreateResultDTO dto, Long creatorId); - - /** - * 更新竞赛结果 - * @param id 结果 ID - * @param dto 更新竞赛结果请求 - * @return 结果详情 - */ - ResultVO update(Long id, CreateResultDTO dto); - - /** - * 发布竞赛结果 - * @param id 结果 ID - * @return 结果详情 - */ - ResultVO publish(Long id); - - /** - * 删除竞赛结果 - * @param id 结果 ID - */ - void delete(Long id); - - /** - * 获取竞赛结果详情 - * @param id 结果 ID - * @return 结果详情 - */ - ResultVO getDetail(Long id); - - /** - * 查询活动的竞赛结果列表 - * @param contestId 活动 ID - * @return 结果列表 - */ - List listByContest(Long contestId); - - /** - * 查询获奖结果列表 - * @param contestId 活动 ID - * @return 获奖结果列表 - */ - List listWinners(Long contestId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestReviewRuleService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestReviewRuleService.java deleted file mode 100644 index 3bf5b64..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestReviewRuleService.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.reviewrule.*; -import com.lesingle.creation.vo.reviewrule.ReviewRuleVO; - -import java.util.List; - -/** - * 竞赛评审规则服务接口 - */ -public interface ContestReviewRuleService { - - /** - * 创建评审规则 - * @param dto 创建评审规则请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 评审规则详情 - */ - ReviewRuleVO create(CreateReviewRuleDTO dto, Long tenantId, Long creatorId); - - /** - * 删除评审规则 - * @param id 规则 ID - */ - void delete(Long id); - - /** - * 获取评审规则详情(含维度) - * @param id 规则 ID - * @return 评审规则详情 - */ - ReviewRuleVO getDetail(Long id); - - /** - * 查询评审规则列表 - * @param tenantId 租户 ID - * @return 评审规则列表 - */ - List list(Long tenantId); - - /** - * 查询可选的评审规则列表(仅返回有效规则) - * @param tenantId 租户 ID - * @return 评审规则列表 - */ - List listForSelect(Long tenantId); - - /** - * 添加评审维度 - * @param dto 创建评审维度请求 - * @return 评审规则详情 - */ - ReviewRuleVO addDimension(CreateReviewDimensionDTO dto); - - /** - * 删除评审维度 - * @param id 维度 ID - */ - void deleteDimension(Long id); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestReviewService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestReviewService.java deleted file mode 100644 index 416e2cc..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestReviewService.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.review.*; -import com.lesingle.creation.entity.ContestWorkAssignment; -import com.lesingle.creation.vo.review.ReviewAssignmentVO; -import com.lesingle.creation.vo.review.ReviewStatsVO; -import com.lesingle.creation.vo.review.WorkScoreVO; - -import java.util.List; - -/** - * 竞赛评审服务接口 - */ -public interface ContestReviewService { - - /** - * 分配作品给评委 - * @param contestId 活动 ID - * @param dto 分配请求 - * @param creatorId 创建人 ID - * @return 分配记录列表 - */ - List assignWork(Long contestId, AssignWorkDTO dto, Long creatorId); - - /** - * 批量分配作品 - * @param dto 批量分配请求 - * @param creatorId 创建人 ID - * @return 分配记录列表 - */ - List batchAssign(BatchAssignDTO dto, Long creatorId); - - /** - * 评分 - * @param dto 创建评分请求 - * @param judgeId 评委 ID - * @param tenantId 租户 ID - * @return 评分详情 - */ - WorkScoreVO score(CreateScoreDTO dto, Long judgeId, Long tenantId); - - /** - * 更新评分 - * @param scoreId 评分 ID - * @param dto 更新评分请求 - * @param tenantId 租户 ID - * @return 评分详情 - */ - WorkScoreVO updateScore(Long scoreId, CreateScoreDTO dto, Long tenantId); - - /** - * 分页查询评审分配列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 评审分配列表 - */ - Page pageQuery(ReviewAssignmentQueryDTO queryDTO, Long tenantId); - - /** - * 获取评委待评审作品列表 - * @param judgeId 评委 ID - * @param tenantId 租户 ID - * @return 评审分配列表 - */ - List getMyAssignments(Long judgeId, Long tenantId); - - /** - * 评审统计 - * @param contestId 活动 ID(可选) - * @return 统计数据 - */ - ReviewStatsVO getStats(Long contestId); - - /** - * 获取作品的评分列表 - * @param workId 作品 ID - * @param tenantId 租户 ID - * @return 评分列表 - */ - List getWorkScores(Long workId, Long tenantId); - - /** - * 获取作品的平均分 - * @param workId 作品 ID - * @param tenantId 租户 ID - * @return 平均分 - */ - java.math.BigDecimal getAverageScore(Long workId, Long tenantId); - - /** - * 自动分配作品给评委 - * @param contestId 活动 ID - * @param creatorId 创建人 ID - * @return 分配结果消息 - */ - String autoAssign(Long contestId, Long creatorId); - - /** - * 获取评审进度统计 - * @param contestId 活动 ID - * @param tenantId 租户 ID - * @return 评审进度统计 - */ - com.lesingle.creation.vo.review.ReviewProgressVO getReviewProgress(Long contestId, Long tenantId); - - /** - * 获取作品状态统计 - * @param contestId 活动 ID - * @param tenantId 租户 ID - * @return 作品状态统计 - */ - com.lesingle.creation.vo.review.WorkStatusStatsVO getWorkStatusStats(Long contestId, Long tenantId); - - /** - * 获取作品的最终得分 - * @param workId 作品 ID - * @param tenantId 租户 ID - * @return 最终得分 - */ - com.lesingle.creation.vo.review.FinalScoreVO getFinalScore(Long workId, Long tenantId); - - /** - * 替换评委 - * @param assignmentId 分配 ID - * @param newJudgeId 新评委 ID - * @param tenantId 租户 ID - */ - void replaceJudge(Long assignmentId, Long newJudgeId, Long tenantId); - - /** - * 获取评委参与的活动列表 - * @param judgeId 评委 ID - * @param tenantId 租户 ID - * @return 活动列表 - */ - List getJudgeContests(Long judgeId, Long tenantId); - - /** - * 获取评委在某个活动下的作品列表 - * @param contestId 活动 ID - * @param judgeId 评委 ID - * @param tenantId 租户 ID - * @return 作品列表分页数据 - */ - Page getJudgeContestWorks( - Long contestId, Long judgeId, Long tenantId, - com.lesingle.creation.dto.review.JudgeWorkQueryDTO queryDTO); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestService.java deleted file mode 100644 index af6eb53..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestService.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.contest.*; -import com.lesingle.creation.entity.Contest; -import com.lesingle.creation.vo.contest.*; - -/** - * 竞赛服务接口 - */ -public interface ContestService extends IService { - - /** - * 创建竞赛 - * - * @param dto 创建竞赛 DTO - * @param creatorId 创建人 ID - * @return 竞赛详情 VO - */ - ContestDetailVO create(CreateContestDTO dto, Long creatorId); - - /** - * 分页查询竞赛列表 - * - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 竞赛列表分页数据 - */ - Page pageList(ContestQueryDTO queryDTO, Long tenantId); - - /** - * 根据 ID 查询竞赛详情 - * - * @param id 竞赛 ID - * @param tenantId 租户 ID - * @return 竞赛详情 VO - */ - ContestDetailVO detail(Long id, Long tenantId); - - /** - * 更新竞赛 - * - * @param id 竞赛 ID - * @param dto 更新竞赛 DTO - * @param modifierId 修改人 ID - * @return 竞赛详情 VO - */ - ContestDetailVO update(Long id, UpdateContestDTO dto, Long modifierId); - - /** - * 发布/取消发布竞赛 - * - * @param id 竞赛 ID - * @param contestState 竞赛状态 - * @param modifierId 修改人 ID - * @return 竞赛详情 VO - */ - ContestDetailVO publish(Long id, String contestState, Long modifierId); - - /** - * 标记竞赛为完结 - * - * @param id 竞赛 ID - * @param modifierId 修改人 ID - * @return 竞赛详情 VO - */ - ContestDetailVO finish(Long id, Long modifierId); - - /** - * 重新开启已完结的竞赛 - * - * @param id 竞赛 ID - * @param modifierId 修改人 ID - * @return 竞赛详情 VO - */ - ContestDetailVO reopen(Long id, Long modifierId); - - /** - * 删除竞赛 - * - * @param id 竞赛 ID - */ - void delete(Long id); - - /** - * 获取竞赛统计信息 - * - * @return 统计信息 VO - */ - ContestStatsVO getStats(); - - /** - * 根据 ID 查询竞赛(不检查权限) - * - * @param id 竞赛 ID - * @return 竞赛实体 - */ - Contest getById(Long id); - - /** - * 查询我参与的活动列表 - * - * @param queryDTO 查询参数 - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 竞赛列表分页数据 - */ - Page myContests(ContestQueryDTO queryDTO, Long userId, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestTeamService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestTeamService.java deleted file mode 100644 index eedb9f1..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestTeamService.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.team.*; -import com.lesingle.creation.entity.ContestTeam; -import com.lesingle.creation.vo.team.TeamVO; - -import java.util.List; - -/** - * 竞赛团队服务接口 - */ -public interface ContestTeamService { - - /** - * 创建团队 - * @param dto 创建团队请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 团队详情 - */ - TeamVO create(CreateTeamDTO dto, Long tenantId, Long creatorId); - - /** - * 更新团队 - * @param id 团队 ID - * @param dto 更新团队请求 - * @param tenantId 租户 ID - * @return 团队详情 - */ - TeamVO update(Long id, UpdateTeamDTO dto, Long tenantId); - - /** - * 删除团队 - * @param id 团队 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); - - /** - * 获取团队详情 - * @param id 团队 ID - * @param tenantId 租户 ID - * @return 团队详情 - */ - TeamVO getDetail(Long id, Long tenantId); - - /** - * 查询团队列表 - * @param contestId 活动 ID - * @param tenantId 租户 ID - * @return 团队列表 - */ - List list(Long contestId, Long tenantId); - - /** - * 按竞赛查询团队列表 - * @param contestId 活动 ID - * @param tenantId 租户 ID - * @return 团队列表 - */ - List listByContest(Long contestId, Long tenantId); - - /** - * 邀请成员 - * @param teamId 团队 ID - * @param dto 邀请成员请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - */ - void inviteMember(Long teamId, InviteMemberDTO dto, Long tenantId, Long creatorId); - - /** - * 移除成员 - * @param teamId 团队 ID - * @param userId 成员用户 ID - * @param tenantId 租户 ID - */ - void removeMember(Long teamId, Long userId, Long tenantId); - - /** - * 获取用户在某活动中的团队 - * @param contestId 活动 ID - * @param userId 用户 ID - * @return 团队信息 - */ - TeamVO getMyTeam(Long contestId, Long userId, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/ContestWorkService.java b/java-backend/src/main/java/com/lesingle/creation/service/ContestWorkService.java deleted file mode 100644 index de39e9d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/ContestWorkService.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.work.*; -import com.lesingle.creation.vo.work.WorkStatsVO; -import com.lesingle.creation.vo.work.WorkVO; - -import java.util.List; - -/** - * 竞赛作品服务接口 - */ -public interface ContestWorkService { - - /** - * 提交作品 - * @param dto 提交作品请求 - * @param tenantId 租户 ID - * @param submitterUserId 提交人 ID - * @return 作品详情 - */ - WorkVO submit(SubmitWorkDTO dto, Long tenantId, Long submitterUserId); - - /** - * 作品统计 - * @param contestId 活动 ID(可选) - * @return 统计数据 - */ - WorkStatsVO getStats(Long contestId); - - /** - * 分页查询作品列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 作品列表 - */ - Page pageQuery(WorkQueryDTO queryDTO, Long tenantId); - - /** - * 获取作品详情 - * @param id 作品 ID - * @param tenantId 租户 ID - * @return 作品详情 - */ - WorkVO getDetail(Long id, Long tenantId); - - /** - * 退回作品 - * @param id 作品 ID - * @param tenantId 租户 ID - * @param reason 退回原因 - * @return 作品详情 - */ - WorkVO returnWork(Long id, Long tenantId, String reason); - - /** - * 删除作品 - * @param id 作品 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); - - /** - * 查询某报名的所有作品 - * @param registrationId 报名 ID - * @param tenantId 租户 ID - * @return 作品列表 - */ - List listByRegistration(Long registrationId, Long tenantId); - - /** - * 查询某报名的所有作品版本 - * @param registrationId 报名 ID - * @param tenantId 租户 ID - * @return 作品版本列表 - */ - List getVersionsByRegistration(Long registrationId, Long tenantId); - - /** - * 查询教师指导的作品列表 - * @param queryDTO 查询参数 - * @param userId 教师用户 ID - * @param tenantId 租户 ID - * @return 作品列表分页数据 - */ - Page getGuidedWorks(WorkQueryDTO queryDTO, Long userId, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java b/java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java deleted file mode 100644 index 1203ca4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/DepartmentService.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.entity.Department; -import com.lesingle.creation.dto.department.CreateDepartmentDTO; -import com.lesingle.creation.dto.department.UpdateDepartmentDTO; -import com.lesingle.creation.vo.department.DepartmentVO; - -import java.util.List; - -/** - * 部门服务接口 - */ -public interface DepartmentService extends IService { - - /** - * 创建部门 - */ - DepartmentVO create(CreateDepartmentDTO dto, Long tenantId, Long creatorId); - - /** - * 查询部门列表(分页) - */ - List list(Long tenantId, Long parentId); - - /** - * 查询部门树形结构 - */ - List tree(Long tenantId); - - /** - * 获取部门详情 - */ - DepartmentVO getDetail(Long id, Long tenantId); - - /** - * 更新部门 - */ - DepartmentVO update(Long id, UpdateDepartmentDTO dto, Long tenantId, Long modifierId); - - /** - * 删除部门 - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/DictService.java b/java-backend/src/main/java/com/lesingle/creation/service/DictService.java deleted file mode 100644 index 00acc79..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/DictService.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.dict.CreateDictDTO; -import com.lesingle.creation.dto.dict.UpdateDictDTO; -import com.lesingle.creation.entity.Dict; -import com.lesingle.creation.vo.dict.DictDetailVO; -import com.lesingle.creation.vo.dict.DictListVO; - -/** - * 字典服务接口 - */ -public interface DictService extends IService { - - /** - * 创建字典 - * - * @param dto 创建字典 DTO - * @param tenantId 租户 ID - * @param operatorId 操作人 ID - * @return 字典详情 VO - */ - DictDetailVO create(CreateDictDTO dto, Long tenantId, Long operatorId); - - /** - * 分页查询字典列表 - * - * @param tenantId 租户 ID - * @param page 页码 - * @param pageSize 每页大小 - * @return 字典列表分页数据 - */ - Page pageList(Long tenantId, int page, int pageSize); - - /** - * 根据编码查询字典 - * - * @param code 字典编码 - * @param tenantId 租户 ID - * @return 字典详情 VO - */ - DictDetailVO getByCode(String code, Long tenantId); - - /** - * 根据 ID 查询字典详情 - * - * @param id 字典 ID - * @param tenantId 租户 ID - * @return 字典详情 VO - */ - DictDetailVO detail(Long id, Long tenantId); - - /** - * 更新字典 - * - * @param id 字典 ID - * @param dto 更新字典 DTO - * @param tenantId 租户 ID - * @return 字典详情 VO - */ - DictDetailVO update(Long id, UpdateDictDTO dto, Long tenantId); - - /** - * 删除字典 - * - * @param id 字典 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/GradeService.java b/java-backend/src/main/java/com/lesingle/creation/service/GradeService.java deleted file mode 100644 index a05f09a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/GradeService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.grade.CreateGradeDTO; -import com.lesingle.creation.dto.grade.UpdateGradeDTO; -import com.lesingle.creation.vo.grade.GradeVO; - -/** - * 年级服务接口 - */ -public interface GradeService { - - /** - * 创建年级 - */ - GradeVO create(CreateGradeDTO dto, Long tenantId, Long creatorId); - - /** - * 分页查询年级列表 - */ - Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId); - - /** - * 获取年级详情 - */ - GradeVO getDetail(Long id, Long tenantId); - - /** - * 更新年级 - */ - GradeVO update(Long id, UpdateGradeDTO dto, Long tenantId, Long modifierId); - - /** - * 删除年级 - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java b/java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java deleted file mode 100644 index 3d8acb9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/HomeworkService.java +++ /dev/null @@ -1,208 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.homework.*; -import com.lesingle.creation.entity.Homework; -import com.lesingle.creation.vo.homework.HomeworkDetailVO; -import com.lesingle.creation.vo.homework.HomeworkListVO; -import com.lesingle.creation.vo.homework.ReviewRuleVO; -import com.lesingle.creation.vo.homework.SubmissionVO; - -import java.util.List; - -/** - * 作业服务接口 - */ -public interface HomeworkService extends IService { - - /** - * 创建作业 - * @param dto 创建作业请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 作业详情 - */ - HomeworkDetailVO create(CreateHomeworkDTO dto, Long tenantId, Long creatorId); - - /** - * 更新作业 - * @param id 作业 ID - * @param dto 更新作业请求 - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO update(Long id, UpdateHomeworkDTO dto, Long tenantId); - - /** - * 发布作业 - * @param id 作业 ID - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO publish(Long id, Long tenantId); - - /** - * 删除作业 - * @param id 作业 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); - - /** - * 获取作业详情 - * @param id 作业 ID - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO getDetail(Long id, Long tenantId); - - /** - * 分页查询作业列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 作业列表 - */ - Page pageQuery(HomeworkQueryDTO queryDTO, Long tenantId); - - /** - * 提交作业 - * @param dto 提交作业请求 - * @param tenantId 租户 ID - * @param studentId 学生 ID - * @return 提交详情 - */ - SubmissionVO submit(SubmitHomeworkDTO dto, Long tenantId, Long studentId); - - /** - * 批改作业 - * @param dto 批改作业请求 - * @param tenantId 租户 ID - * @param reviewerId 批改人 ID - * @return 提交详情 - */ - SubmissionVO review(ReviewHomeworkDTO dto, Long tenantId, Long reviewerId); - - /** - * 获取作业提交列表 - * @param homeworkId 作业 ID - * @param tenantId 租户 ID - * @return 提交列表 - */ - List getSubmissions(Long homeworkId, Long tenantId); - - /** - * 创建评审规则 - * @param ruleName 规则名称 - * @param ruleType 规则类型 - * @param totalScore 总分 - * @param description 规则描述 - * @param tenantId 租户 ID - * @return 评审规则 - */ - ReviewRuleVO createReviewRule(String ruleName, String ruleType, - java.math.BigDecimal totalScore, String description, Long tenantId); - - /** - * 获取评审规则列表 - * @param tenantId 租户 ID - * @return 评审规则列表 - */ - List getReviewRules(Long tenantId); - - /** - * 获取可选的评审规则 - * @param tenantId 租户 ID - * @return 评审规则列表 - */ - List getReviewRulesForSelect(Long tenantId); - - /** - * 更新评审规则 - * @param id 规则 ID - * @param dto 更新请求 - * @param tenantId 租户 ID - * @return 评审规则 - */ - ReviewRuleVO updateReviewRule(Long id, UpdateReviewRuleDTO dto, Long tenantId); - - /** - * 删除评审规则 - * @param id 规则 ID - * @param tenantId 租户 ID - */ - void deleteReviewRule(Long id, Long tenantId); - - /** - * 我的作业列表(学生端) - * @param queryDTO 查询参数 - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 作业列表 - */ - Page getMyHomeworks(HomeworkQueryDTO queryDTO, Long userId, Long tenantId); - - /** - * 取消发布作业 - * @param id 作业 ID - * @param tenantId 租户 ID - * @return 作业详情 - */ - HomeworkDetailVO unpublish(Long id, Long tenantId); - - /** - * 获取提交记录列表 - * @param queryDTO 查询参数 - * @param tenantId 租户 ID - * @return 提交记录列表 - */ - Page getSubmissionsList(SubmissionQueryDTO queryDTO, Long tenantId); - - /** - * 获取提交记录详情 - * @param id 提交 ID - * @param tenantId 租户 ID - * @return 提交详情 - */ - SubmissionVO getSubmissionDetail(Long id, Long tenantId); - - /** - * 获取班级树结构 - * @param tenantId 租户 ID - * @return 班级树 - */ - List getClassTree(Long tenantId); - - /** - * 获取我的提交记录 - * @param homeworkId 作业 ID - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 提交详情 - */ - SubmissionVO getMySubmission(Long homeworkId, Long userId, Long tenantId); - - /** - * 提交评分 - * @param dto 评分请求 - * @param tenantId 租户 ID - * @param reviewerId 批改人 ID - * @return 提交详情 - */ - SubmissionVO createScore(CreateScoreDTO dto, Long tenantId, Long reviewerId); - - /** - * 标记作品违规 - * @param submissionId 提交 ID - * @param reason 原因 - * @param tenantId 租户 ID - */ - void markViolation(Long submissionId, String reason, Long tenantId); - - /** - * 重置评分 - * @param submissionId 提交 ID - * @param tenantId 租户 ID - */ - void resetScore(Long submissionId, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/MenuService.java b/java-backend/src/main/java/com/lesingle/creation/service/MenuService.java deleted file mode 100644 index 847b3af..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/MenuService.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.menu.CreateMenuDTO; -import com.lesingle.creation.dto.menu.UpdateMenuDTO; -import com.lesingle.creation.entity.Menu; -import com.lesingle.creation.vo.menu.MenuDetailVO; -import com.lesingle.creation.vo.menu.MenuTreeVO; - -import java.util.List; - -/** - * 菜单服务接口 - */ -public interface MenuService extends IService { - - /** - * 创建菜单 - * - * @param dto 创建菜单 DTO - * @param operatorId 操作人 ID - * @return 菜单详情 VO - */ - MenuDetailVO create(CreateMenuDTO dto, Long operatorId); - - /** - * 获取菜单树 - * - * @return 菜单树 - */ - List tree(); - - /** - * 获取用户菜单(根据用户角色权限) - * - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 用户菜单树 - */ - List getUserMenus(Long userId, Long tenantId); - - /** - * 根据 ID 查询菜单详情 - * - * @param id 菜单 ID - * @return 菜单详情 VO - */ - MenuDetailVO detail(Long id); - - /** - * 更新菜单 - * - * @param id 菜单 ID - * @param dto 更新菜单 DTO - * @return 菜单详情 VO - */ - MenuDetailVO update(Long id, UpdateMenuDTO dto); - - /** - * 删除菜单 - * - * @param id 菜单 ID - */ - void delete(Long id); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/PermissionService.java b/java-backend/src/main/java/com/lesingle/creation/service/PermissionService.java deleted file mode 100644 index 94e4482..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/PermissionService.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.permission.CreatePermissionDTO; -import com.lesingle.creation.dto.permission.UpdatePermissionDTO; -import com.lesingle.creation.entity.Permission; -import com.lesingle.creation.vo.permission.PermissionDetailVO; -import com.lesingle.creation.vo.permission.PermissionListVO; - -import java.util.List; - -/** - * 权限服务接口 - */ -public interface PermissionService extends IService { - - /** - * 创建权限 - * - * @param dto 创建权限 DTO - * @param tenantId 租户 ID - * @param operatorId 操作人 ID - * @return 权限详情 VO - */ - PermissionDetailVO create(CreatePermissionDTO dto, Long tenantId, Long operatorId); - - /** - * 分页查询权限列表 - * - * @param tenantId 租户 ID - * @param page 页码 - * @param pageSize 每页大小 - * @return 权限列表分页数据 - */ - Page pageList(Long tenantId, int page, int pageSize); - - /** - * 根据 ID 查询权限详情 - * - * @param id 权限 ID - * @return 权限详情 VO - */ - PermissionDetailVO detail(Long id); - - /** - * 更新权限 - * - * @param id 权限 ID - * @param dto 更新权限 DTO - * @param tenantId 租户 ID - * @return 权限详情 VO - */ - PermissionDetailVO update(Long id, UpdatePermissionDTO dto, Long tenantId); - - /** - * 删除权限 - * - * @param id 权限 ID - */ - void delete(Long id); - - /** - * 获取所有权限列表 - * - * @param tenantId 租户 ID - * @return 权限列表 - */ - List list(Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/PublicService.java b/java-backend/src/main/java/com/lesingle/creation/service/PublicService.java deleted file mode 100644 index c719c37..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/PublicService.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.lesingle.creation.service; - -import com.lesingle.creation.dto.child.CreateChildDTO; -import com.lesingle.creation.dto.child.UpdateChildDTO; -import com.lesingle.creation.dto.publicuser.PublicLoginDTO; -import com.lesingle.creation.dto.publicuser.PublicRegisterDTO; -import com.lesingle.creation.dto.publicuser.PublicUserUpdateDTO; -import com.lesingle.creation.vo.child.ChildVO; -import com.lesingle.creation.vo.publicuser.LoginResponseVO; -import com.lesingle.creation.vo.publicuser.PublicUserVO; - -import java.util.List; - -/** - * 公众用户服务接口 - */ -public interface PublicService { - - /** - * 用户注册 - */ - LoginResponseVO register(PublicRegisterDTO dto); - - /** - * 用户登录 - */ - LoginResponseVO login(PublicLoginDTO dto); - - /** - * 获取用户信息 - */ - PublicUserVO getUserInfo(Long userId); - - /** - * 更新用户信息 - */ - PublicUserVO updateProfile(Long userId, PublicUserUpdateDTO dto); - - /** - * 获取子女列表 - */ - List getChildren(Long userId); - - /** - * 创建子女 - */ - ChildVO createChild(Long userId, CreateChildDTO dto); - - /** - * 获取子女详情 - */ - ChildVO getChild(Long userId, Long childId); - - /** - * 更新子女信息 - */ - ChildVO updateChild(Long userId, Long childId, UpdateChildDTO dto); - - /** - * 删除子女 - */ - void deleteChild(Long userId, Long childId); - - /** - * 创建子女独立账号 - */ - ChildVO createChildAccount(Long userId, CreateChildDTO dto); - - /** - * 获取子女账号列表 - */ - List getChildAccounts(Long userId); - - /** - * 更新子女账号信息 - */ - ChildVO updateChildAccount(Long userId, Long childId, UpdateChildDTO dto); - - /** - * 获取监护人信息 - */ - PublicUserVO getParentInfo(Long userId); - - /** - * 获取公开活动列表 - */ - Object getPublicActivities(Integer page, Integer pageSize, String keyword, String contestType, Long userId); - - /** - * 获取活动详情 - */ - Object getActivityDetail(Long id); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/RoleService.java b/java-backend/src/main/java/com/lesingle/creation/service/RoleService.java deleted file mode 100644 index efa2070..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/RoleService.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.role.CreateRoleDTO; -import com.lesingle.creation.dto.role.UpdateRoleDTO; -import com.lesingle.creation.entity.Role; -import com.lesingle.creation.vo.role.RoleDetailVO; -import com.lesingle.creation.vo.role.RoleListVO; - -import java.util.List; - -/** - * 角色服务接口 - */ -public interface RoleService extends IService { - - /** - * 创建角色 - * - * @param dto 创建角色 DTO - * @param tenantId 租户 ID - * @param operatorId 操作人 ID - * @return 角色详情 VO - */ - RoleDetailVO create(CreateRoleDTO dto, Long tenantId, Long operatorId); - - /** - * 分页查询角色列表 - * - * @param tenantId 租户 ID - * @param page 页码 - * @param pageSize 每页大小 - * @return 角色列表分页数据 - */ - Page pageList(Long tenantId, int page, int pageSize); - - /** - * 根据 ID 查询角色详情 - * - * @param id 角色 ID - * @return 角色详情 VO - */ - RoleDetailVO detail(Long id); - - /** - * 更新角色 - * - * @param id 角色 ID - * @param dto 更新角色 DTO - * @param tenantId 租户 ID - * @return 角色详情 VO - */ - RoleDetailVO update(Long id, UpdateRoleDTO dto, Long tenantId); - - /** - * 删除角色 - * - * @param id 角色 ID - */ - void delete(Long id); - - /** - * 获取所有角色列表 - * - * @param tenantId 租户 ID - * @return 角色列表 - */ - List list(Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java b/java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java deleted file mode 100644 index 1881027..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/SchoolClassService.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.schoolclass.CreateClassDTO; -import com.lesingle.creation.dto.schoolclass.UpdateClassDTO; -import com.lesingle.creation.vo.schoolclass.ClassVO; - -/** - * 班级服务接口 - */ -public interface SchoolClassService { - - /** - * 创建班级 - */ - ClassVO create(CreateClassDTO dto, Long tenantId, Long creatorId); - - /** - * 分页查询班级列表 - */ - Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId, Long gradeId, Integer type); - - /** - * 获取班级详情 - */ - ClassVO getDetail(Long id, Long tenantId); - - /** - * 更新班级 - */ - ClassVO update(Long id, UpdateClassDTO dto, Long tenantId, Long modifierId); - - /** - * 删除班级 - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java b/java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java deleted file mode 100644 index 56710e8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/SchoolService.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.school.CreateSchoolDTO; -import com.lesingle.creation.dto.school.UpdateSchoolDTO; -import com.lesingle.creation.entity.School; -import com.lesingle.creation.vo.school.SchoolVO; - -/** - * 学校服务接口 - */ -public interface SchoolService extends IService { - - /** - * 创建学校 - * - * @param dto 创建学校 DTO - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 学校 VO - */ - SchoolVO create(CreateSchoolDTO dto, Long tenantId, Long creatorId); - - /** - * 根据租户 ID 查询学校 - * - * @param tenantId 租户 ID - * @return 学校 VO - */ - SchoolVO getByTenantId(Long tenantId); - - /** - * 更新学校 - * - * @param dto 更新学校 DTO - * @param tenantId 租户 ID - * @param modifierId 修改人 ID - * @return 学校 VO - */ - SchoolVO update(UpdateSchoolDTO dto, Long tenantId, Long modifierId); - - /** - * 删除学校 - * - * @param tenantId 租户 ID - */ - void delete(Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/StudentService.java b/java-backend/src/main/java/com/lesingle/creation/service/StudentService.java deleted file mode 100644 index 7d9f89a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/StudentService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.student.CreateStudentDTO; -import com.lesingle.creation.dto.student.UpdateStudentDTO; -import com.lesingle.creation.entity.Student; -import com.lesingle.creation.vo.student.StudentVO; - -import java.util.List; - -/** - * 学生服务接口 - */ -public interface StudentService extends IService { - - /** - * 创建学生 - * - * @param dto 创建学生请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 学生 VO - */ - StudentVO create(CreateStudentDTO dto, Long tenantId, Long creatorId); - - /** - * 查询学生列表(分页) - * - * @param tenantId 租户 ID - * @param page 页码 - * @param pageSize 每页大小 - * @param classId 班级 ID(可选) - * @return 学生 VO 列表 - */ - List list(Long tenantId, Integer page, Integer pageSize, Long classId); - - /** - * 获取学生详情 - * - * @param id 学生 ID - * @param tenantId 租户 ID - * @return 学生 VO - */ - StudentVO getDetail(Long id, Long tenantId); - - /** - * 根据用户 ID 获取学生信息 - * - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 学生 VO - */ - StudentVO getByUserId(Long userId, Long tenantId); - - /** - * 更新学生 - * - * @param id 学生 ID - * @param dto 更新学生请求 - * @param tenantId 租户 ID - * @param modifierId 修改人 ID - * @return 学生 VO - */ - StudentVO update(Long id, UpdateStudentDTO dto, Long tenantId, Long modifierId); - - /** - * 删除学生 - * - * @param id 学生 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/SysLogService.java b/java-backend/src/main/java/com/lesingle/creation/service/SysLogService.java deleted file mode 100644 index d90668a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/SysLogService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.log.LogQueryDTO; -import com.lesingle.creation.vo.log.LogStatisticsVO; -import com.lesingle.creation.vo.log.LogVO; - -import java.util.List; - -/** - * 系统日志服务接口 - */ -public interface SysLogService { - - /** - * 分页查询日志列表 - */ - Page pageQuery(LogQueryDTO queryDTO, Long tenantId); - - /** - * 获取日志详情 - */ - LogVO getDetail(Long id, Long tenantId); - - /** - * 获取日志统计信息 - */ - LogStatisticsVO getStatistics(Integer days, Long tenantId); - - /** - * 批量删除日志 - */ - int deleteByIds(List ids, Long tenantId); - - /** - * 清理过期日志 - */ - int cleanOldLogs(Integer daysToKeep, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java b/java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java deleted file mode 100644 index 93189fd..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/TeacherService.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.teacher.CreateTeacherDTO; -import com.lesingle.creation.dto.teacher.UpdateTeacherDTO; -import com.lesingle.creation.entity.Teacher; -import com.lesingle.creation.vo.teacher.TeacherVO; - -import java.util.List; - -/** - * 教师服务接口 - */ -public interface TeacherService extends IService { - - /** - * 创建教师 - * - * @param dto 创建教师请求 - * @param tenantId 租户 ID - * @param creatorId 创建人 ID - * @return 教师 VO - */ - TeacherVO create(CreateTeacherDTO dto, Long tenantId, Long creatorId); - - /** - * 查询教师列表 - * - * @param tenantId 租户 ID - * @param departmentId 部门 ID(可选) - * @param nickname 昵称(可选) - * @param username 用户名(可选) - * @return 教师 VO 列表 - */ - List list(Long tenantId, Long departmentId, String nickname, String username); - - /** - * 获取教师详情 - * - * @param id 教师 ID - * @param tenantId 租户 ID - * @return 教师 VO - */ - TeacherVO getDetail(Long id, Long tenantId); - - /** - * 根据用户 ID 获取教师信息 - * - * @param userId 用户 ID - * @param tenantId 租户 ID - * @return 教师 VO - */ - TeacherVO getByUserId(Long userId, Long tenantId); - - /** - * 更新教师 - * - * @param id 教师 ID - * @param dto 更新教师请求 - * @param tenantId 租户 ID - * @param modifierId 修改人 ID - * @return 教师 VO - */ - TeacherVO update(Long id, UpdateTeacherDTO dto, Long tenantId, Long modifierId); - - /** - * 删除教师 - * - * @param id 教师 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/TenantMenuService.java b/java-backend/src/main/java/com/lesingle/creation/service/TenantMenuService.java deleted file mode 100644 index d292545..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/TenantMenuService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.entity.TenantMenu; - -/** - * 租户菜单服务接口 - */ -public interface TenantMenuService extends IService { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/TenantService.java b/java-backend/src/main/java/com/lesingle/creation/service/TenantService.java deleted file mode 100644 index c2d0fc8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/TenantService.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.tenant.CreateTenantDTO; -import com.lesingle.creation.dto.tenant.UpdateTenantDTO; -import com.lesingle.creation.entity.Tenant; -import com.lesingle.creation.vo.tenant.TenantDetailVO; -import com.lesingle.creation.vo.tenant.TenantListVO; - -import java.util.List; - -/** - * 租户服务接口 - */ -public interface TenantService extends IService { - - /** - * 创建租户 - * - * @param dto 创建租户 DTO - * @param creatorId 创建人 ID - * @return 租户详情 VO - */ - TenantDetailVO create(CreateTenantDTO dto, Long creatorId); - - /** - * 分页查询租户列表 - * - * @param page 页码 - * @param pageSize 每页大小 - * @return 租户列表分页数据 - */ - com.baomidou.mybatisplus.extension.plugins.pagination.Page pageList(int page, int pageSize); - - /** - * 根据 ID 查询租户详情 - * - * @param id 租户 ID - * @return 租户详情 VO - */ - TenantDetailVO detail(Long id); - - /** - * 根据编码查询租户 - * - * @param code 租户编码 - * @return 租户详情 VO - */ - TenantDetailVO getByCode(String code); - - /** - * 根据域名查询租户 - * - * @param domain 租户域名 - * @return 租户详情 VO - */ - TenantDetailVO getByDomain(String domain); - - /** - * 更新租户 - * - * @param id 租户 ID - * @param dto 更新租户 DTO - * @param modifierId 修改人 ID - * @return 租户详情 VO - */ - TenantDetailVO update(Long id, UpdateTenantDTO dto, Long modifierId); - - /** - * 删除租户 - * - * @param id 租户 ID - */ - void delete(Long id); - - /** - * 获取租户的菜单树 - * - * @param tenantId 租户 ID - * @return 菜单树 - */ - List getTenantMenus(Long tenantId); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/UserService.java b/java-backend/src/main/java/com/lesingle/creation/service/UserService.java deleted file mode 100644 index a17813f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/UserService.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.lesingle.creation.service; - -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.IService; -import com.lesingle.creation.dto.user.CreateUserDTO; -import com.lesingle.creation.dto.user.UpdateUserDTO; -import com.lesingle.creation.dto.user.UserQueryDTO; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.vo.user.UserDetailVO; -import com.lesingle.creation.vo.user.UserListVO; -import com.lesingle.creation.vo.user.UserStatsVO; - -/** - * 用户服务接口 - */ -public interface UserService extends IService { - - /** - * 创建用户 - * - * @param dto 创建用户 DTO - * @param tenantId 租户 ID - * @param operatorId 操作人 ID - * @return 用户详情 VO - */ - UserDetailVO create(CreateUserDTO dto, Long tenantId, Long operatorId); - - /** - * 分页查询用户列表 - * - * @param queryDTO 查询参数 - * @param tenantId 当前租户 ID - * @param isSuperTenant 是否超级租户 - * @return 用户列表分页数据 - */ - Page pageList(UserQueryDTO queryDTO, Long tenantId, boolean isSuperTenant); - - /** - * 根据 ID 查询用户详情 - * - * @param id 用户 ID - * @param tenantId 当前租户 ID - * @param isSuperTenant 是否超级租户 - * @return 用户详情 VO - */ - UserDetailVO detail(Long id, Long tenantId, boolean isSuperTenant); - - /** - * 更新用户状态 - * - * @param id 用户 ID - * @param status 状态 - * @param operatorId 操作人 ID - * @return 用户详情 VO - */ - UserDetailVO updateStatus(Long id, String status, Long operatorId); - - /** - * 更新用户 - * - * @param id 用户 ID - * @param dto 更新用户 DTO - * @param tenantId 租户 ID - * @return 用户详情 VO - */ - UserDetailVO update(Long id, UpdateUserDTO dto, Long tenantId); - - /** - * 删除用户 - * - * @param id 用户 ID - * @param tenantId 租户 ID - */ - void delete(Long id, Long tenantId); - - /** - * 用户统计(仅超管) - * - * @return 用户统计 VO - */ - UserStatsVO getStats(); -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/AI3DTaskServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/AI3DTaskServiceImpl.java deleted file mode 100644 index 49d3d1c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/AI3DTaskServiceImpl.java +++ /dev/null @@ -1,190 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.ai3d.AI3DTaskQueryDTO; -import com.lesingle.creation.dto.ai3d.CreateAI3DTaskDTO; -import com.lesingle.creation.entity.AI3DTask; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.AI3DTaskMapper; -import com.lesingle.creation.service.AI3DTaskService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.ai3d.AI3DTaskVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * AI 3D 任务服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class AI3DTaskServiceImpl extends ServiceImpl - implements AI3DTaskService { - - @Override - @Transactional(rollbackFor = Exception.class) - public AI3DTaskVO create(CreateAI3DTaskDTO dto, Long tenantId, Long userId) { - AI3DTask task = new AI3DTask(); - task.setTenantId(tenantId); - task.setUserId(userId); - task.setInputType(dto.getInputType()); - task.setInputContent(dto.getInputContent()); - task.setGenerateType(dto.getGenerateType()); - task.setStatus("pending"); - task.setRetryCount(0); - - this.save(task); - log.info("创建 AI 3D 任务成功,ID={}, 输入类型={}", task.getId(), dto.getInputType()); - - // TODO: 调用腾讯混元 AI 服务进行 3D 生成 - // 这里应该异步调用外部 AI 服务,并在完成后更新任务状态 - - return convertToVO(task); - } - - @Override - public AI3DTaskVO getDetail(Long id, Long tenantId) { - AI3DTask task = this.getById(id); - if (task == null || !task.getTenantId().equals(tenantId)) { - throw new BusinessException("任务不存在"); - } - - return convertToVO(task); - } - - @Override - public Page pageQuery(AI3DTaskQueryDTO queryDTO, Long tenantId, Long userId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(AI3DTask::getTenantId, tenantId) - .eq(AI3DTask::getDeleted, 0) - .eq(queryDTO.getStatus() != null, AI3DTask::getStatus, queryDTO.getStatus()) - .eq(queryDTO.getInputType() != null, AI3DTask::getInputType, queryDTO.getInputType()) - .eq(userId != null, AI3DTask::getUserId, userId) - .orderByDesc(AI3DTask::getCreateTime); - - Page resultPage = this.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void cancel(Long id, Long tenantId) { - AI3DTask task = this.getById(id); - if (task == null || !task.getTenantId().equals(tenantId)) { - throw new BusinessException("任务不存在"); - } - - // 只有 pending/processing 状态的任务可以取消 - if (!"pending".equals(task.getStatus()) && !"processing".equals(task.getStatus())) { - throw new BusinessException("当前状态无法取消任务"); - } - - task.setStatus("timeout"); - this.updateById(task); - log.info("取消 AI 3D 任务成功,ID={}", id); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public AI3DTaskVO retry(Long id, Long tenantId) { - AI3DTask task = this.getById(id); - if (task == null || !task.getTenantId().equals(tenantId)) { - throw new BusinessException("任务不存在"); - } - - // 只有 failed 状态的任务可以重试 - if (!"failed".equals(task.getStatus())) { - throw new BusinessException("只有失败的任务可以重试"); - } - - // 限制最大重试次数 - if (task.getRetryCount() >= 3) { - throw new BusinessException("已达到最大重试次数"); - } - - task.setStatus("pending"); - task.setRetryCount(task.getRetryCount() + 1); - task.setErrorMessage(null); - this.updateById(task); - log.info("重试 AI 3D 任务成功,ID={}, 重试次数={}", id, task.getRetryCount()); - - // TODO: 重新调用 AI 服务 - - return convertToVO(task); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - AI3DTask task = this.getById(id); - if (task == null || !task.getTenantId().equals(tenantId)) { - throw new BusinessException("任务不存在"); - } - - task.setDeleted(1); - this.updateById(task); - log.info("删除 AI 3D 任务成功,ID={}", id); - } - - /** - * 更新任务状态(供异步回调使用) - */ - @Transactional(rollbackFor = Exception.class) - public void updateTaskStatus(Long taskId, String status, String resultUrl, - String previewUrl, String errorMessage) { - AI3DTask task = this.getById(taskId); - if (task != null) { - task.setStatus(status); - if ("completed".equals(status)) { - task.setResultUrl(resultUrl); - task.setPreviewUrl(previewUrl); - task.setCompleteTime(LocalDateTime.now()); - } else if ("failed".equals(status)) { - task.setErrorMessage(errorMessage); - } - this.updateById(task); - log.info("更新 AI 3D 任务状态,ID={}, 状态={}", taskId, status); - } - } - - // ========== 转换方法 ========== - - private AI3DTaskVO convertToVO(AI3DTask task) { - AI3DTaskVO vo = new AI3DTaskVO(); - vo.setId(task.getId()); - vo.setInputType(task.getInputType()); - vo.setInputContent(task.getInputContent()); - vo.setGenerateType(task.getGenerateType()); - vo.setStatus(task.getStatus()); - vo.setResultUrl(task.getResultUrl()); - vo.setPreviewUrl(task.getPreviewUrl()); - vo.setResultUrls(task.getResultUrls()); - vo.setPreviewUrls(task.getPreviewUrls()); - vo.setErrorMessage(task.getErrorMessage()); - vo.setExternalTaskId(task.getExternalTaskId()); - vo.setRetryCount(task.getRetryCount()); - vo.setCreateTime(task.getCreateTime()); - vo.setCompleteTime(task.getCompleteTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/AuthServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/AuthServiceImpl.java deleted file mode 100644 index 71e3a3e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/AuthServiceImpl.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.common.enums.UserStatusEnum; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.common.util.JwtTokenUtil; -import com.lesingle.creation.dto.auth.LoginDTO; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.AuthService; -import com.lesingle.creation.vo.auth.LoginResponseVO; -import com.lesingle.creation.vo.auth.UserInfoVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 认证服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class AuthServiceImpl implements AuthService { - - private final UserMapper userMapper; - private final TenantMapper tenantMapper; - private final UserRoleMapper userRoleMapper; - private final RoleMapper roleMapper; - private final PermissionMapper permissionMapper; - private final RolePermissionMapper rolePermissionMapper; - private final JwtTokenUtil jwtTokenUtil; - private final PasswordEncoder passwordEncoder; - - @Override - @Transactional(rollbackFor = Exception.class) - public LoginResponseVO login(LoginDTO loginDTO) { - String username = loginDTO.getUsername(); - String password = loginDTO.getPassword(); - String tenantCode = loginDTO.getTenantCode(); - - log.info("登录请求:username={}, tenantCode={}", username, tenantCode); - - // 1. 确定租户(优先使用 tenantCode) - Tenant tenant = null; - Long tenantId = null; - if (tenantCode != null && !tenantCode.isEmpty()) { - tenant = tenantMapper.selectOne(new LambdaQueryWrapper() - .eq(Tenant::getCode, tenantCode) - .eq(Tenant::getDeleted, 0)); - if (tenant == null) { - throw new BusinessException("租户不存在"); - } - if (tenant.getValidState() != 1) { - throw new BusinessException("租户已失效"); - } - tenantId = tenant.getId(); - } - - // 2. 根据租户 + 用户名查询用户(避免跨租户同名导致 selectOne 返回多条) - User user; - if (tenantId != null) { - user = userMapper.selectOne(new LambdaQueryWrapper() - .eq(User::getTenantId, tenantId) - .eq(User::getUsername, username) - .eq(User::getDeleted, 0)); - } else { - // 未指定租户时,先查出所有同名用户 - List users = userMapper.selectList(new LambdaQueryWrapper() - .eq(User::getUsername, username) - .eq(User::getDeleted, 0)); - if (users == null || users.isEmpty()) { - log.warn("用户不存在:{}", username); - throw new BusinessException("用户名或密码错误"); - } - if (users.size() > 1) { - throw new BusinessException("存在同名用户,请指定租户编码"); - } - user = users.get(0); - tenantId = user.getTenantId(); - } - - if (user == null) { - log.warn("用户不存在:{}", username); - throw new BusinessException("用户名或密码错误"); - } - - log.info("用户查询成功,ID={}, tenantId={}", user.getId(), user.getTenantId()); - - // 3. 验证密码 - if (!passwordEncoder.matches(password, user.getPassword())) { - log.warn("密码不匹配,用户名:{}", username); - throw new BusinessException("用户名或密码错误"); - } - - // 4. 校验租户有效性(tenantCode 未传时也要校验一次) - if (tenant == null) { - tenant = tenantMapper.selectById(tenantId); - } - if (tenant == null || tenant.getDeleted() != 0) { - throw new BusinessException("租户不存在"); - } - if (tenant.getValidState() != 1) { - throw new BusinessException("租户已失效"); - } - - // 5. 验证用户是否属于该租户 - if (!user.getTenantId().equals(tenantId)) { - throw new BusinessException("用户不属于该租户"); - } - - // 6. 验证用户状态 - if (!UserStatusEnum.ENABLED.getCode().equals(user.getStatus())) { - throw new BusinessException("用户账号已停用"); - } - - // 7. 生成 JWT Token - String token = jwtTokenUtil.generateToken(user.getId(), tenantId, tenant.getCode()); - - // 8. 构建用户信息 - UserInfoVO userInfo = buildUserInfo(user, tenantId); - - LoginResponseVO response = new LoginResponseVO(); - response.setToken(token); - response.setUser(userInfo); - - log.info("用户登录成功,用户名={}, 租户编码={}", username, tenantCode); - - return response; - } - - @Override - public UserInfoVO getUserInfo(Long userId) { - User user = userMapper.selectById(userId); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - return buildUserInfo(user, user.getTenantId()); - } - - @Override - public void logout(Long userId) { - // TODO: 可以将 token 加入黑名单(使用 Redis) - log.info("用户登出成功,用户 ID={}", userId); - } - - @Override - public LoginResponseVO refreshToken(String token) { - try { - // 1. 解析 token 获取用户 ID - Long userId = jwtTokenUtil.getUserIdFromToken(token.replace("Bearer ", "")); - if (userId == null) { - throw new BusinessException("Token 无效"); - } - - // 2. 查询用户信息 - User user = userMapper.selectById(userId); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - // 3. 生成新的 token - String newToken = jwtTokenUtil.generateToken( - user.getId(), - user.getTenantId(), - tenantMapper.selectById(user.getTenantId()).getCode() - ); - - // 4. 构建响应 - UserInfoVO userInfo = buildUserInfo(user, user.getTenantId()); - LoginResponseVO response = new LoginResponseVO(); - response.setToken(newToken); - response.setUser(userInfo); - - log.info("刷新 Token 成功,用户 ID={}", userId); - return response; - - } catch (Exception e) { - log.error("刷新 Token 失败", e); - throw new BusinessException("刷新 Token 失败"); - } - } - - /** - * 构建用户信息 VO - */ - private UserInfoVO buildUserInfo(User user, Long tenantId) { - UserInfoVO vo = new UserInfoVO(); - vo.setId(user.getId()); - vo.setUsername(user.getUsername()); - vo.setNickname(user.getNickname()); - vo.setEmail(user.getEmail()); - vo.setAvatar(user.getAvatar()); - vo.setTenantId(user.getTenantId()); - - // 获取租户编码 - Tenant tenant = tenantMapper.selectById(tenantId); - if (tenant != null) { - vo.setTenantCode(tenant.getCode()); - } - - // 获取用户角色列表 - List roles = getUserRoles(user.getId()); - vo.setRoles(roles); - - // 获取用户权限列表 - List permissions = getUserPermissions(user.getId()); - vo.setPermissions(permissions); - - return vo; - } - - /** - * 获取用户角色列表 - */ - private List getUserRoles(Long userId) { - // 查询用户关联的角色 - List userRoles = userRoleMapper.selectList( - new LambdaQueryWrapper() - .eq(UserRole::getUserId, userId) - ); - - if (userRoles.isEmpty()) { - return new ArrayList<>(); - } - - // 获取角色 ID 列表 - List roleIds = userRoles.stream() - .map(UserRole::getRoleId) - .collect(Collectors.toList()); - - // 查询角色详情 - List roles = roleMapper.selectBatchIds(roleIds); - - // 返回角色编码列表(只返回有效的角色) - return roles.stream() - .filter(role -> role.getValidState() == 1) - .map(Role::getCode) - .collect(Collectors.toList()); - } - - /** - * 获取用户权限列表 - */ - private List getUserPermissions(Long userId) { - // 查询用户关联的角色 - List userRoles = userRoleMapper.selectList( - new LambdaQueryWrapper() - .eq(UserRole::getUserId, userId) - ); - - if (userRoles.isEmpty()) { - return new ArrayList<>(); - } - - // 获取角色 ID 列表 - List roleIds = userRoles.stream() - .map(UserRole::getRoleId) - .collect(Collectors.toList()); - - // 查询角色关联的权限 - List rolePermissions = rolePermissionMapper.selectList( - new LambdaQueryWrapper() - .in(RolePermission::getRoleId, roleIds) - ); - - if (rolePermissions.isEmpty()) { - return new ArrayList<>(); - } - - // 获取权限 ID 列表 - List permissionIds = rolePermissions.stream() - .map(RolePermission::getPermissionId) - .distinct() - .collect(Collectors.toList()); - - // 查询权限详情 - List permissions = permissionMapper.selectBatchIds(permissionIds); - - // 返回权限编码列表(只返回有效的权限) - return permissions.stream() - .filter(permission -> permission.getValidState() == 1) - .map(Permission::getCode) - .collect(Collectors.toList()); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ConfigServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ConfigServiceImpl.java deleted file mode 100644 index 1c93c99..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ConfigServiceImpl.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.config.CreateConfigDTO; -import com.lesingle.creation.dto.config.UpdateConfigDTO; -import com.lesingle.creation.entity.SysConfig; -import com.lesingle.creation.mapper.SysConfigMapper; -import com.lesingle.creation.service.ConfigService; -import com.lesingle.creation.vo.config.ConfigDetailVO; -import com.lesingle.creation.vo.config.ConfigListVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 系统配置服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ConfigServiceImpl extends ServiceImpl implements ConfigService { - - private final SysConfigMapper sysConfigMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public ConfigDetailVO create(CreateConfigDTO dto, Long tenantId, Long operatorId) { - log.info("开始创建配置,配置键:{}", dto.getConfigKey()); - - // 检查配置键是否已存在 - SysConfig existingConfig = sysConfigMapper.selectByKey(tenantId, dto.getConfigKey()); - if (existingConfig != null) { - throw new BusinessException("配置键已存在"); - } - - // 创建配置 - SysConfig sysConfig = new SysConfig(); - sysConfig.setTenantId(tenantId); - sysConfig.setConfigKey(dto.getConfigKey()); - sysConfig.setConfigValue(dto.getConfigValue()); - sysConfig.setConfigName(dto.getConfigName()); - sysConfig.setDescription(dto.getDescription()); - sysConfig.setValidState(1); - sysConfig.setCreateBy(String.valueOf(operatorId)); - - sysConfigMapper.insert(sysConfig); - log.info("配置创建成功,配置 ID: {}", sysConfig.getId()); - - return convertToDetailVO(sysConfig); - } - - @Override - public Page pageList(Long tenantId, int page, int pageSize) { - log.info("分页查询配置列表,租户 ID: {}, 页码:{}, 每页大小:{}", tenantId, page, pageSize); - - Page configPage = new Page<>(page, pageSize); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(SysConfig::getTenantId, tenantId) - .eq(SysConfig::getValidState, 1) - .orderByDesc(SysConfig::getCreateTime); - - Page resultPage = sysConfigMapper.selectPage(configPage, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public ConfigDetailVO getByKey(String key, Long tenantId) { - log.info("根据键查询配置,键:{}, 租户 ID: {}", key, tenantId); - - SysConfig sysConfig = sysConfigMapper.selectByKey(tenantId, key); - if (sysConfig == null) { - throw new BusinessException("配置不存在"); - } - - return convertToDetailVO(sysConfig); - } - - @Override - public ConfigDetailVO detail(Long id, Long tenantId) { - log.info("查询配置详情,配置 ID: {}", id); - - SysConfig sysConfig = sysConfigMapper.selectById(id); - if (sysConfig == null) { - throw new BusinessException("配置不存在"); - } - - return convertToDetailVO(sysConfig); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ConfigDetailVO update(Long id, UpdateConfigDTO dto, Long tenantId) { - log.info("更新配置,配置 ID: {}", id); - - SysConfig existingConfig = sysConfigMapper.selectById(id); - if (existingConfig == null) { - throw new BusinessException("配置不存在"); - } - - // 更新配置信息 - SysConfig sysConfig = new SysConfig(); - sysConfig.setId(id); - sysConfig.setConfigValue(dto.getConfigValue()); - sysConfig.setConfigName(dto.getConfigName()); - sysConfig.setDescription(dto.getDescription()); - - sysConfigMapper.updateById(sysConfig); - log.info("配置更新成功,配置 ID: {}", id); - - return convertToDetailVO(sysConfigMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - log.info("删除配置,配置 ID: {}", id); - - SysConfig sysConfig = sysConfigMapper.selectById(id); - if (sysConfig == null) { - throw new BusinessException("配置不存在"); - } - - // 删除配置(逻辑删除) - sysConfigMapper.deleteById(id); - log.info("配置删除成功,配置 ID: {}", id); - } - - /** - * 转换为详情 VO - */ - private ConfigDetailVO convertToDetailVO(SysConfig sysConfig) { - ConfigDetailVO vo = new ConfigDetailVO(); - vo.setId(sysConfig.getId()); - vo.setTenantId(sysConfig.getTenantId()); - vo.setConfigKey(sysConfig.getConfigKey()); - vo.setConfigValue(sysConfig.getConfigValue()); - vo.setConfigName(sysConfig.getConfigName()); - vo.setDescription(sysConfig.getDescription()); - vo.setValidState(sysConfig.getValidState()); - vo.setCreateBy(sysConfig.getCreateBy()); - vo.setCreateTime(sysConfig.getCreateTime()); - vo.setUpdateBy(sysConfig.getUpdateBy()); - vo.setUpdateTime(sysConfig.getUpdateTime()); - return vo; - } - - /** - * 转换为列表 VO - */ - private ConfigListVO convertToListVO(SysConfig sysConfig) { - ConfigListVO vo = new ConfigListVO(); - vo.setId(sysConfig.getId()); - vo.setTenantId(sysConfig.getTenantId()); - vo.setConfigKey(sysConfig.getConfigKey()); - vo.setConfigValue(sysConfig.getConfigValue()); - vo.setConfigName(sysConfig.getConfigName()); - vo.setDescription(sysConfig.getDescription()); - vo.setValidState(sysConfig.getValidState()); - vo.setCreateTime(sysConfig.getCreateTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestJudgeServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestJudgeServiceImpl.java deleted file mode 100644 index c4bb32f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestJudgeServiceImpl.java +++ /dev/null @@ -1,199 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.judge.CreateJudgeDTO; -import com.lesingle.creation.dto.judge.UpdateJudgeDTO; -import com.lesingle.creation.entity.Contest; -import com.lesingle.creation.entity.ContestJudge; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.ContestJudgeMapper; -import com.lesingle.creation.mapper.ContestMapper; -import com.lesingle.creation.service.ContestJudgeService; -import com.lesingle.creation.vo.judge.JudgeVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛评委服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestJudgeServiceImpl implements ContestJudgeService { - - private final ContestJudgeMapper contestJudgeMapper; - private final ContestMapper contestMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public JudgeVO create(CreateJudgeDTO dto, Long creatorId) { - // 验证活动是否存在 - Contest contest = contestMapper.selectById(dto.getContestId()); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - ContestJudge judge = new ContestJudge(); - judge.setContestId(dto.getContestId()); - judge.setTenantId(contest.getTenantId()); - judge.setJudgeName(dto.getJudgeName()); - judge.setTitle(dto.getTitle()); - judge.setOrganization(dto.getOrganization()); - judge.setPhone(dto.getPhone()); - judge.setEmail(dto.getEmail()); - judge.setSpecialty(dto.getSpecialty()); - judge.setWeight(dto.getWeight()); - judge.setStatus("1"); // 1-活跃 - judge.setValidState(1); - if (creatorId != null) { - judge.setCreateBy(creatorId.toString()); - } - - contestJudgeMapper.insert(judge); - log.info("创建评委成功,ID={}", judge.getId()); - - return convertToVO(judge); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public JudgeVO update(Long id, UpdateJudgeDTO dto) { - ContestJudge judge = contestJudgeMapper.selectById(id); - if (judge == null) { - throw new BusinessException("评委不存在"); - } - - if (dto.getJudgeName() != null) { - judge.setJudgeName(dto.getJudgeName()); - } - if (dto.getTitle() != null) { - judge.setTitle(dto.getTitle()); - } - if (dto.getOrganization() != null) { - judge.setOrganization(dto.getOrganization()); - } - if (dto.getPhone() != null) { - judge.setPhone(dto.getPhone()); - } - if (dto.getEmail() != null) { - judge.setEmail(dto.getEmail()); - } - if (dto.getSpecialty() != null) { - judge.setSpecialty(dto.getSpecialty()); - } - if (dto.getStatus() != null) { - judge.setStatus(dto.getStatus().toString()); - } - - contestJudgeMapper.updateById(judge); - log.info("更新评委成功,ID={}", id); - - return convertToVO(judge); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - ContestJudge judge = contestJudgeMapper.selectById(id); - if (judge == null) { - throw new BusinessException("评委不存在"); - } - - judge.setDeleted(1); - contestJudgeMapper.updateById(judge); - log.info("删除评委成功,ID={}", id); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void batchDelete(List ids) { - for (Long id : ids) { - ContestJudge judge = contestJudgeMapper.selectById(id); - if (judge != null) { - judge.setDeleted(1); - contestJudgeMapper.updateById(judge); - } - } - log.info("批量删除评委成功,删除数量={}", ids.size()); - } - - @Override - public JudgeVO freeze(Long id) { - ContestJudge judge = contestJudgeMapper.selectById(id); - if (judge == null) { - throw new BusinessException("评委不存在"); - } - - judge.setStatus("2"); // 2-不活跃 - contestJudgeMapper.updateById(judge); - log.info("冻结评委成功,ID={}", id); - - return convertToVO(judge); - } - - @Override - public JudgeVO unfreeze(Long id) { - ContestJudge judge = contestJudgeMapper.selectById(id); - if (judge == null) { - throw new BusinessException("评委不存在"); - } - - judge.setStatus("1"); // 1-活跃 - contestJudgeMapper.updateById(judge); - log.info("解冻评委成功,ID={}", id); - - return convertToVO(judge); - } - - @Override - public JudgeVO getDetail(Long id) { - ContestJudge judge = contestJudgeMapper.selectById(id); - if (judge == null) { - throw new BusinessException("评委不存在"); - } - return convertToVO(judge); - } - - @Override - public List listByContest(Long contestId) { - List judges = contestJudgeMapper.selectList(new LambdaQueryWrapper() - .eq(ContestJudge::getContestId, contestId) - .eq(ContestJudge::getValidState, 1) - .eq(ContestJudge::getDeleted, 0) - .orderByDesc(ContestJudge::getCreateTime)); - - return judges.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - // ========== 转换方法 ========== - - private JudgeVO convertToVO(ContestJudge judge) { - JudgeVO vo = new JudgeVO(); - vo.setId(judge.getId()); - vo.setContestId(judge.getContestId()); - vo.setJudgeId(judge.getJudgeId()); - vo.setJudgeName(judge.getJudgeName()); - vo.setTitle(judge.getTitle()); - vo.setOrganization(judge.getOrganization()); - vo.setPhone(judge.getPhone()); - vo.setEmail(judge.getEmail()); - vo.setSpecialty(judge.getSpecialty()); - vo.setStatus(judge.getStatus() != null ? Integer.parseInt(judge.getStatus()) : 1); - vo.setValidState(judge.getValidState()); - - // 获取活动名称 - Contest contest = contestMapper.selectById(judge.getContestId()); - if (contest != null) { - vo.setContestName(contest.getContestName()); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestNoticeServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestNoticeServiceImpl.java deleted file mode 100644 index 6472325..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestNoticeServiceImpl.java +++ /dev/null @@ -1,151 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.notice.CreateNoticeDTO; -import com.lesingle.creation.dto.notice.UpdateNoticeDTO; -import com.lesingle.creation.entity.Contest; -import com.lesingle.creation.entity.ContestNotice; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.ContestNoticeMapper; -import com.lesingle.creation.mapper.ContestMapper; -import com.lesingle.creation.service.ContestNoticeService; -import com.lesingle.creation.vo.notice.NoticeVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛公告服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestNoticeServiceImpl implements ContestNoticeService { - - private final ContestNoticeMapper contestNoticeMapper; - private final ContestMapper contestMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public NoticeVO create(CreateNoticeDTO dto, Long creatorId) { - // 验证活动是否存在 - Contest contest = contestMapper.selectById(dto.getContestId()); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - ContestNotice notice = new ContestNotice(); - notice.setContestId(dto.getContestId()); - notice.setTitle(dto.getTitle()); - notice.setContent(dto.getContent()); - notice.setNoticeType(dto.getNoticeType()); - notice.setPriority(dto.getPriority()); - notice.setValidState(1); - if (creatorId != null) { - notice.setCreateBy(creatorId.toString()); - } - - contestNoticeMapper.insert(notice); - log.info("创建公告成功,ID={}", notice.getId()); - - return convertToVO(notice); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public NoticeVO update(Long id, UpdateNoticeDTO dto) { - ContestNotice notice = contestNoticeMapper.selectById(id); - if (notice == null) { - throw new BusinessException("公告不存在"); - } - - notice.setTitle(dto.getTitle()); - notice.setContent(dto.getContent()); - if (dto.getPriority() != null) { - notice.setPriority(dto.getPriority()); - } - - contestNoticeMapper.updateById(notice); - log.info("更新公告成功,ID={}", id); - - return convertToVO(notice); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - ContestNotice notice = contestNoticeMapper.selectById(id); - if (notice == null) { - throw new BusinessException("公告不存在"); - } - - notice.setValidState(2); - contestNoticeMapper.updateById(notice); - log.info("删除公告成功,ID={}", id); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public NoticeVO publish(Long id) { - ContestNotice notice = contestNoticeMapper.selectById(id); - if (notice == null) { - throw new BusinessException("公告不存在"); - } - - notice.setPublishTime(LocalDateTime.now()); - contestNoticeMapper.updateById(notice); - log.info("发布公告成功,ID={}", id); - - return convertToVO(notice); - } - - @Override - public NoticeVO getDetail(Long id) { - ContestNotice notice = contestNoticeMapper.selectById(id); - if (notice == null) { - throw new BusinessException("公告不存在"); - } - return convertToVO(notice); - } - - @Override - public List listByContest(Long contestId) { - List notices = contestNoticeMapper.selectList(new LambdaQueryWrapper() - .eq(ContestNotice::getContestId, contestId) - .eq(ContestNotice::getValidState, 1) - .eq(ContestNotice::getDeleted, 0) - .orderByDesc(ContestNotice::getPriority) - .orderByDesc(ContestNotice::getPublishTime)); - - return notices.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - // ========== 转换方法 ========== - - private NoticeVO convertToVO(ContestNotice notice) { - NoticeVO vo = new NoticeVO(); - vo.setId(notice.getId()); - vo.setContestId(notice.getContestId()); - vo.setTitle(notice.getTitle()); - vo.setContent(notice.getContent()); - vo.setNoticeType(notice.getNoticeType()); - vo.setPriority(notice.getPriority()); - vo.setPublishTime(notice.getPublishTime()); - vo.setValidState(notice.getValidState()); - - // 获取活动名称 - Contest contest = contestMapper.selectById(notice.getContestId()); - if (contest != null) { - vo.setContestName(contest.getContestName()); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestPresetCommentServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestPresetCommentServiceImpl.java deleted file mode 100644 index d95e988..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestPresetCommentServiceImpl.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.presetcomment.CreatePresetCommentDTO; -import com.lesingle.creation.entity.ContestPresetComment; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.ContestPresetCommentMapper; -import com.lesingle.creation.service.ContestPresetCommentService; -import com.lesingle.creation.vo.presetcomment.PresetCommentVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛预设评语服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestPresetCommentServiceImpl implements ContestPresetCommentService { - - private final ContestPresetCommentMapper presetCommentMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public PresetCommentVO create(CreatePresetCommentDTO dto, Long tenantId) { - ContestPresetComment comment = new ContestPresetComment(); - comment.setTenantId(tenantId); - comment.setContestId(dto.getContestId()); - comment.setContent(dto.getContent()); - comment.setType(dto.getType()); - comment.setScoreRangeMin(dto.getScoreRangeMin()); - comment.setScoreRangeMax(dto.getScoreRangeMax()); - comment.setSort(dto.getSort()); - comment.setUsageCount(0); - - presetCommentMapper.insert(comment); - log.info("创建预设评语成功,ID={}", comment.getId()); - - return convertToVO(comment); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - ContestPresetComment comment = presetCommentMapper.selectById(id); - if (comment == null) { - throw new BusinessException("预设评语不存在"); - } - presetCommentMapper.deleteById(id); - log.info("删除预设评语成功,ID={}", id); - } - - @Override - public PresetCommentVO getDetail(Long id) { - ContestPresetComment comment = presetCommentMapper.selectById(id); - if (comment == null) { - throw new BusinessException("预设评语不存在"); - } - return convertToVO(comment); - } - - @Override - public List listByContest(Long contestId, Long tenantId) { - List comments = presetCommentMapper.selectList(new LambdaQueryWrapper() - .eq(ContestPresetComment::getTenantId, tenantId) - .eq(ContestPresetComment::getContestId, contestId) - .eq(ContestPresetComment::getDeleted, 0) - .orderByAsc(ContestPresetComment::getSort)); - - return comments.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - public List listCommon(Long tenantId) { - List comments = presetCommentMapper.selectList(new LambdaQueryWrapper() - .eq(ContestPresetComment::getTenantId, tenantId) - .isNull(ContestPresetComment::getContestId) - .eq(ContestPresetComment::getDeleted, 0) - .orderByAsc(ContestPresetComment::getSort)); - - return comments.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - // ========== 转换方法 ========== - - private PresetCommentVO convertToVO(ContestPresetComment comment) { - PresetCommentVO vo = new PresetCommentVO(); - vo.setId(comment.getId()); - vo.setTenantId(comment.getTenantId()); - vo.setContestId(comment.getContestId()); - vo.setContent(comment.getContent()); - vo.setType(comment.getType()); - vo.setScoreRangeMin(comment.getScoreRangeMin()); - vo.setScoreRangeMax(comment.getScoreRangeMax()); - vo.setSort(comment.getSort()); - vo.setUsageCount(comment.getUsageCount()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestRegistrationServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestRegistrationServiceImpl.java deleted file mode 100644 index cce6924..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestRegistrationServiceImpl.java +++ /dev/null @@ -1,404 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.enums.RegistrationStateEnum; -import com.lesingle.creation.common.enums.ContestStateEnum; -import com.lesingle.creation.dto.registration.*; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.ContestRegistrationService; -import com.lesingle.creation.vo.registration.RegistrationStatsVO; -import com.lesingle.creation.vo.registration.RegistrationVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛报名服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestRegistrationServiceImpl implements ContestRegistrationService { - - private final ContestRegistrationMapper registrationMapper; - private final ContestMapper contestMapper; - private final UserMapper userMapper; - private final ContestTeamMapper teamMapper; - private final ContestTeamMemberMapper teamMemberMapper; - private final ContestWorkMapper workMapper; - private final ContestRegistrationTeacherMapper teacherMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public RegistrationVO create(CreateRegistrationDTO dto, Long tenantId, Long creatorId) { - // 验证活动是否存在 - Contest contest = contestMapper.selectById(dto.getContestId()); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - // 检查活动是否已发布 - if (!ContestStateEnum.PUBLISHED.getCode().equals(contest.getContestState())) { - throw new BusinessException("活动未发布,无法报名"); - } - - // 检查报名时间 - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(contest.getRegisterStartTime()) || now.isAfter(contest.getRegisterEndTime())) { - throw new BusinessException("不在报名时间范围内"); - } - - // 验证用户是否存在 - User user = userMapper.selectById(dto.getUserId()); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - // 检查用户是否已报名(个人参与) - if ("individual".equals(dto.getRegistrationType())) { - ContestRegistration existing = registrationMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestRegistration::getContestId, dto.getContestId()) - .eq(ContestRegistration::getUserId, dto.getUserId()) - .eq(ContestRegistration::getRegistrationType, "individual") - .eq(ContestRegistration::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("您已报名该活动"); - } - } - - // 团队参与验证 - if ("team".equals(dto.getRegistrationType())) { - if (dto.getTeamId() == null) { - throw new BusinessException("团队参与必须指定团队 ID"); - } - - ContestTeam team = teamMapper.selectById(dto.getTeamId()); - if (team == null) { - throw new BusinessException("团队不存在"); - } - - if (!team.getTenantId().equals(tenantId)) { - throw new BusinessException("团队不属于当前租户"); - } - - if (!team.getContestId().equals(dto.getContestId())) { - throw new BusinessException("团队不属于该活动"); - } - - // 检查用户是否是团队成员 - List members = teamMemberMapper.selectList(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, dto.getTeamId()) - .eq(ContestTeamMember::getUserId, dto.getUserId())); - if (members.isEmpty()) { - throw new BusinessException("您不是该团队成员"); - } - } - - // 获取用户账号信息快照 - String accountNo = user.getUsername(); - String accountName = user.getNickname(); - - // 检查当前登录用户是否是老师,如果是则设置为指导老师(registrant) - Long registrantId = dto.getUserId(); - if (creatorId != null) { - User creator = userMapper.selectById(creatorId); - if (creator != null) { - // TODO: 检查创建者是否是老师(需要查询 teacher 表) - // 这里简化处理,假设有 teacher 标识 - registrantId = creatorId; - } - } - - // 创建报名记录 - ContestRegistration registration = new ContestRegistration(); - registration.setContestId(dto.getContestId()); - registration.setTenantId(tenantId); - registration.setRegistrationType(dto.getRegistrationType()); - registration.setTeamId(dto.getTeamId()); - if (dto.getTeamId() != null) { - ContestTeam team = teamMapper.selectById(dto.getTeamId()); - if (team != null) { - registration.setTeamName(team.getTeamName()); - } - } - registration.setUserId(dto.getUserId()); - registration.setAccountNo(accountNo); - registration.setAccountName(accountName); - registration.setRegistrationState(RegistrationStateEnum.PENDING.getCode()); - registration.setRegistrationTime(LocalDateTime.now()); - registration.setRegistrant(registrantId); - if (creatorId != null) { - registration.setCreateBy(creatorId.toString()); - } - - registrationMapper.insert(registration); - - // 如果创建者是老师,自动添加为默认指导老师 - if (creatorId != null) { - try { - ContestRegistrationTeacher teacher = new ContestRegistrationTeacher(); - teacher.setRegistrationId(registration.getId()); - teacher.setTenantId(tenantId); - teacher.setUserId(creatorId); - teacher.setIsDefault(true); - teacherMapper.insert(teacher); - } catch (Exception e) { - log.warn("创建默认指导老师失败:{}", e.getMessage()); - } - } - - log.info("创建报名成功,ID={}, 活动 ID={}, 用户 ID={}", registration.getId(), dto.getContestId(), dto.getUserId()); - - return convertToVO(registration); - } - - @Override - public RegistrationStatsVO getStats(Long contestId) { - LambdaQueryWrapper baseWrapper = new LambdaQueryWrapper() - .eq(ContestRegistration::getDeleted, 0); - if (contestId != null) { - baseWrapper.eq(ContestRegistration::getContestId, contestId); - } - - long total = registrationMapper.selectCount(baseWrapper); - long pending = registrationMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestRegistration::getRegistrationState, "pending") - .eq(ContestRegistration::getDeleted, 0) - .eq(contestId != null, ContestRegistration::getContestId, contestId)); - long passed = registrationMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestRegistration::getRegistrationState, "passed") - .eq(ContestRegistration::getDeleted, 0) - .eq(contestId != null, ContestRegistration::getContestId, contestId)); - long rejected = registrationMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestRegistration::getRegistrationState, "rejected") - .eq(ContestRegistration::getDeleted, 0) - .eq(contestId != null, ContestRegistration::getContestId, contestId)); - - RegistrationStatsVO vo = new RegistrationStatsVO(); - vo.setTotal((int) total); - vo.setPending((int) pending); - vo.setPassed((int) passed); - vo.setRejected((int) rejected); - return vo; - } - - @Override - public Page pageQuery(RegistrationQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(ContestRegistration::getDeleted, 0) - .eq(queryDTO.getContestId() != null, ContestRegistration::getContestId, queryDTO.getContestId()) - .eq(queryDTO.getRegistrationState() != null, ContestRegistration::getRegistrationState, queryDTO.getRegistrationState()) - .eq(queryDTO.getRegistrationType() != null, ContestRegistration::getRegistrationType, queryDTO.getRegistrationType()) - .eq(queryDTO.getUserId() != null, ContestRegistration::getUserId, queryDTO.getUserId()) - .like(queryDTO.getKeyword() != null, ContestRegistration::getAccountName, queryDTO.getKeyword()) - .orderByDesc(ContestRegistration::getRegistrationTime); - - // TODO: 租户隔离(非超管只能看自己租户的) - if (tenantId != null) { - // 检查是否是超管租户 - Tenant tenant = new Tenant(); // 简化处理 - if (tenant.getIsSuper() == null || tenant.getIsSuper() == 0) { - wrapper.eq(ContestRegistration::getTenantId, tenantId); - } - } - - Page resultPage = registrationMapper.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - return voPage; - } - - @Override - public RegistrationVO getDetail(Long id, Long tenantId) { - ContestRegistration registration = registrationMapper.selectById(id); - if (registration == null || !registration.getTenantId().equals(tenantId)) { - throw new BusinessException("报名记录不存在"); - } - return convertToVO(registration); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public RegistrationVO review(Long id, ReviewRegistrationDTO dto, Long operatorId, Long tenantId) { - ContestRegistration registration = registrationMapper.selectById(id); - if (registration == null) { - throw new BusinessException("报名记录不存在"); - } - - if (!RegistrationStateEnum.PENDING.getCode().equals(registration.getRegistrationState())) { - throw new BusinessException("只能审核待审核状态的报名"); - } - - registration.setRegistrationState(dto.getRegistrationState()); - registration.setReason(dto.getReason()); - registration.setOperator(operatorId); - registration.setOperationDate(LocalDateTime.now()); - registration.setUpdateBy(operatorId.toString()); - - registrationMapper.updateById(registration); - log.info("审核报名成功,ID={}, 状态={}", id, dto.getRegistrationState()); - - return convertToVO(registration); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - ContestRegistration registration = registrationMapper.selectById(id); - if (registration == null) { - throw new BusinessException("报名记录不存在"); - } - - // 检查是否有作品 - Long workCount = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getRegistrationId, id) - .eq(ContestWork::getDeleted, 0)); - if (workCount > 0) { - throw new BusinessException("该报名已有作品,无法删除"); - } - - registrationMapper.deleteById(id); - log.info("删除报名成功,ID={}", id); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public RegistrationVO addTeacher(Long registrationId, Long teacherUserId, Long tenantId, Long creatorId) { - ContestRegistration registration = registrationMapper.selectById(registrationId); - if (registration == null || !registration.getTenantId().equals(tenantId)) { - throw new BusinessException("报名记录不存在"); - } - - // 验证用户是否是老师 - User teacher = userMapper.selectById(teacherUserId); - if (teacher == null) { - throw new BusinessException("用户不存在"); - } - - // 检查是否已经添加过 - ContestRegistrationTeacher existing = teacherMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestRegistrationTeacher::getRegistrationId, registrationId) - .eq(ContestRegistrationTeacher::getUserId, teacherUserId)); - if (existing != null) { - throw new BusinessException("该老师已经添加过了"); - } - - // 添加指导老师 - ContestRegistrationTeacher teacherRel = new ContestRegistrationTeacher(); - teacherRel.setRegistrationId(registrationId); - teacherRel.setTenantId(tenantId); - teacherRel.setUserId(teacherUserId); - teacherRel.setIsDefault(false); - - teacherMapper.insert(teacherRel); - log.info("添加指导老师成功,报名 ID={}, 老师 ID={}", registrationId, teacherUserId); - - return convertToVO(registration); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void removeTeacher(Long registrationId, Long teacherUserId, Long tenantId) { - ContestRegistrationTeacher teacher = teacherMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestRegistrationTeacher::getRegistrationId, registrationId) - .eq(ContestRegistrationTeacher::getUserId, teacherUserId)); - - if (teacher == null) { - throw new BusinessException("指导老师记录不存在"); - } - - if (teacher.getIsDefault()) { - throw new BusinessException("默认指导老师不能移除"); - } - - teacherMapper.deleteById(teacher.getId()); - log.info("移除指导老师成功,报名 ID={}, 老师 ID={}", registrationId, teacherUserId); - } - - @Override - public RegistrationVO getMyRegistration(Long contestId, Long userId) { - // 1. 先查询个人参与报名 - ContestRegistration individualReg = registrationMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestRegistration::getContestId, contestId) - .eq(ContestRegistration::getUserId, userId) - .eq(ContestRegistration::getRegistrationType, "individual") - .eq(ContestRegistration::getRegistrationState, "passed") - .eq(ContestRegistration::getDeleted, 0)); - - if (individualReg != null) { - return convertToVO(individualReg); - } - - // 2. 查询用户所属的团队 - List teamMemberships = teamMemberMapper.selectList(new LambdaQueryWrapper() - .eq(ContestTeamMember::getUserId, userId)); - - if (teamMemberships.isEmpty()) { - return null; - } - - List validTeamIds = teamMemberships.stream() - .map(ContestTeamMember::getTeamId) - .collect(Collectors.toList()); - - // 3. 通过团队 ID 查询团队报名记录 - ContestRegistration teamReg = registrationMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestRegistration::getContestId, contestId) - .in(ContestRegistration::getTeamId, validTeamIds) - .eq(ContestRegistration::getRegistrationType, "team") - .eq(ContestRegistration::getRegistrationState, "passed") - .eq(ContestRegistration::getDeleted, 0)); - - if (teamReg != null) { - return convertToVO(teamReg); - } - - return null; - } - - // ========== 转换方法 ========== - - private RegistrationVO convertToVO(ContestRegistration registration) { - RegistrationVO vo = new RegistrationVO(); - vo.setId(registration.getId()); - vo.setContestId(registration.getContestId()); - vo.setTenantId(registration.getTenantId()); - vo.setRegistrationType(registration.getRegistrationType()); - vo.setTeamId(registration.getTeamId()); - vo.setTeamName(registration.getTeamName()); - vo.setUserId(registration.getUserId()); - vo.setAccountNo(registration.getAccountNo()); - vo.setAccountName(registration.getAccountName()); - vo.setRegistrationState(registration.getRegistrationState()); - vo.setRegistrationTime(registration.getRegistrationTime()); - vo.setReason(registration.getReason()); - vo.setOperator(registration.getOperator()); - vo.setOperationDate(registration.getOperationDate()); - vo.setRegistrant(registration.getRegistrant()); - - // 查询作品数量 - Long workCount = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getRegistrationId, registration.getId()) - .eq(ContestWork::getDeleted, 0)); - RegistrationVO.WorkCount workCountObj = new RegistrationVO.WorkCount(); - workCountObj.setWorks(workCount.intValue()); - vo.setWorkCount(workCountObj); - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestResultServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestResultServiceImpl.java deleted file mode 100644 index 41ce589..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestResultServiceImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.result.CreateResultDTO; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.ContestResultService; -import com.lesingle.creation.vo.result.ResultVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛结果服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestResultServiceImpl implements ContestResultService { - - private final ContestResultMapper resultMapper; - private final ContestMapper contestMapper; - private final ContestWorkMapper workMapper; - private final ContestRegistrationMapper registrationMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public ResultVO create(CreateResultDTO dto, Long creatorId) { - // 验证作品是否存在 - ContestWork work = workMapper.selectById(dto.getWorkId()); - if (work == null) { - throw new BusinessException("作品不存在"); - } - - // 验证报名是否存在 - ContestRegistration registration = registrationMapper.selectById(dto.getRegistrationId()); - if (registration == null) { - throw new BusinessException("报名记录不存在"); - } - - // 检查结果是否已存在 - ContestResult existing = resultMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestResult::getWorkId, dto.getWorkId()) - .eq(ContestResult::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("该作品已有结果记录"); - } - - ContestResult result = new ContestResult(); - result.setContestId(work.getContestId()); - result.setWorkId(dto.getWorkId()); - result.setRegistrationId(dto.getRegistrationId()); - result.setTotalScore(dto.getTotalScore()); - result.setAwardLevel(dto.getAwardLevel()); - result.setDescription(dto.getDescription()); - result.setIsWinner(dto.getIsWinner()); - result.setPublicState("pending"); - if (creatorId != null) { - result.setCreateBy(creatorId.toString()); - } - - resultMapper.insert(result); - log.info("创建竞赛结果成功,ID={}", result.getId()); - - return convertToVO(result); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ResultVO update(Long id, CreateResultDTO dto) { - ContestResult result = resultMapper.selectById(id); - if (result == null) { - throw new BusinessException("竞赛结果不存在"); - } - - result.setTotalScore(dto.getTotalScore()); - result.setAwardLevel(dto.getAwardLevel()); - result.setDescription(dto.getDescription()); - result.setIsWinner(dto.getIsWinner()); - - resultMapper.updateById(result); - log.info("更新竞赛结果成功,ID={}", id); - - return convertToVO(result); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ResultVO publish(Long id) { - ContestResult result = resultMapper.selectById(id); - if (result == null) { - throw new BusinessException("竞赛结果不存在"); - } - - result.setPublicState("published"); - result.setPublishTime(LocalDateTime.now()); - resultMapper.updateById(result); - log.info("发布竞赛结果成功,ID={}", id); - - return convertToVO(result); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - ContestResult result = resultMapper.selectById(id); - if (result == null) { - throw new BusinessException("竞赛结果不存在"); - } - resultMapper.deleteById(id); - log.info("删除竞赛结果成功,ID={}", id); - } - - @Override - public ResultVO getDetail(Long id) { - ContestResult result = resultMapper.selectById(id); - if (result == null) { - throw new BusinessException("竞赛结果不存在"); - } - return convertToVO(result); - } - - @Override - public List listByContest(Long contestId) { - List results = resultMapper.selectList(new LambdaQueryWrapper() - .eq(ContestResult::getContestId, contestId) - .eq(ContestResult::getDeleted, 0) - .orderByDesc(ContestResult::getTotalScore)); - - return results.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - public List listWinners(Long contestId) { - List results = resultMapper.selectList(new LambdaQueryWrapper() - .eq(ContestResult::getContestId, contestId) - .eq(ContestResult::getIsWinner, true) - .eq(ContestResult::getDeleted, 0) - .orderByDesc(ContestResult::getTotalScore)); - - return results.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - // ========== 转换方法 ========== - - private ResultVO convertToVO(ContestResult result) { - ResultVO vo = new ResultVO(); - vo.setId(result.getId()); - vo.setContestId(result.getContestId()); - vo.setWorkId(result.getWorkId()); - vo.setRegistrationId(result.getRegistrationId()); - vo.setTotalScore(result.getTotalScore()); - vo.setAwardLevel(result.getAwardLevel()); - vo.setDescription(result.getDescription()); - vo.setIsWinner(result.getIsWinner()); - vo.setPublicState(result.getPublicState()); - vo.setPublishTime(result.getPublishTime()); - - // 获取活动名称 - Contest contest = contestMapper.selectById(result.getContestId()); - if (contest != null) { - vo.setContestName(contest.getContestName()); - } - - // 获取作品标题 - ContestWork work = workMapper.selectById(result.getWorkId()); - if (work != null) { - vo.setWorkTitle(work.getTitle()); - } - - // 获取参赛者姓名 - ContestRegistration registration = registrationMapper.selectById(result.getRegistrationId()); - if (registration != null) { - vo.setParticipantName(registration.getAccountName()); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestReviewRuleServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestReviewRuleServiceImpl.java deleted file mode 100644 index 1bb5052..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestReviewRuleServiceImpl.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.reviewrule.CreateReviewDimensionDTO; -import com.lesingle.creation.dto.reviewrule.CreateReviewRuleDTO; -import com.lesingle.creation.entity.ContestReviewDimension; -import com.lesingle.creation.entity.ContestReviewRule; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.ContestReviewDimensionMapper; -import com.lesingle.creation.mapper.ContestReviewRuleMapper; -import com.lesingle.creation.service.ContestReviewRuleService; -import com.lesingle.creation.vo.reviewrule.ReviewDimensionVO; -import com.lesingle.creation.vo.reviewrule.ReviewRuleVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛评审规则服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestReviewRuleServiceImpl implements ContestReviewRuleService { - - private final ContestReviewRuleMapper reviewRuleMapper; - private final ContestReviewDimensionMapper dimensionMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public ReviewRuleVO create(CreateReviewRuleDTO dto, Long tenantId, Long creatorId) { - ContestReviewRule rule = new ContestReviewRule(); - rule.setTenantId(tenantId); - rule.setRuleName(dto.getRuleName()); - rule.setRuleType(dto.getRuleType()); - rule.setTotalScore(dto.getTotalScore()); - rule.setDescription(dto.getDescription()); - if (creatorId != null) { - rule.setCreateBy(creatorId.toString()); - } - - reviewRuleMapper.insert(rule); - log.info("创建评审规则成功,ID={}", rule.getId()); - - return convertToVO(rule); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - ContestReviewRule rule = reviewRuleMapper.selectById(id); - if (rule == null) { - throw new BusinessException("评审规则不存在"); - } - reviewRuleMapper.deleteById(id); - log.info("删除评审规则成功,ID={}", id); - } - - @Override - public ReviewRuleVO getDetail(Long id) { - ContestReviewRule rule = reviewRuleMapper.selectById(id); - if (rule == null) { - throw new BusinessException("评审规则不存在"); - } - return convertToVO(rule); - } - - @Override - public List list(Long tenantId) { - List rules = reviewRuleMapper.selectList(new LambdaQueryWrapper() - .eq(ContestReviewRule::getTenantId, tenantId) - .eq(ContestReviewRule::getDeleted, 0) - .orderByDesc(ContestReviewRule::getCreateTime)); - - return rules.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - public List listForSelect(Long tenantId) { - List rules = reviewRuleMapper.selectList(new LambdaQueryWrapper() - .eq(ContestReviewRule::getTenantId, tenantId) - .eq(ContestReviewRule::getDeleted, 0) - .eq(ContestReviewRule::getValidState, 1) - .orderByDesc(ContestReviewRule::getCreateTime)); - - return rules.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ReviewRuleVO addDimension(CreateReviewDimensionDTO dto) { - ContestReviewRule rule = reviewRuleMapper.selectById(dto.getRuleId()); - if (rule == null) { - throw new BusinessException("评审规则不存在"); - } - - ContestReviewDimension dimension = new ContestReviewDimension(); - dimension.setRuleId(dto.getRuleId()); - dimension.setDimensionName(dto.getDimensionName()); - dimension.setDescription(dto.getDescription()); - dimension.setWeight(dto.getWeight()); - dimension.setMaxScore(dto.getMaxScore()); - dimension.setSort(dto.getSort()); - - dimensionMapper.insert(dimension); - log.info("添加评审维度成功,ID={}", dimension.getId()); - - return convertToVO(rule); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteDimension(Long id) { - ContestReviewDimension dimension = dimensionMapper.selectById(id); - if (dimension == null) { - throw new BusinessException("评审维度不存在"); - } - dimensionMapper.deleteById(id); - log.info("删除评审维度成功,ID={}", id); - } - - // ========== 转换方法 ========== - - private ReviewRuleVO convertToVO(ContestReviewRule rule) { - ReviewRuleVO vo = new ReviewRuleVO(); - vo.setId(rule.getId()); - vo.setTenantId(rule.getTenantId()); - vo.setRuleName(rule.getRuleName()); - vo.setRuleType(rule.getRuleType()); - vo.setTotalScore(rule.getTotalScore()); - vo.setDescription(rule.getDescription()); - vo.setCreateTime(rule.getCreateTime()); - - // 获取维度列表 - List dimensions = dimensionMapper.selectList( - new LambdaQueryWrapper() - .eq(ContestReviewDimension::getRuleId, rule.getId()) - .eq(ContestReviewDimension::getDeleted, 0) - .orderByAsc(ContestReviewDimension::getSort)); - - List dimensionVOs = dimensions.stream() - .map(this::convertToDimensionVO) - .collect(Collectors.toList()); - vo.setDimensions(dimensionVOs); - - return vo; - } - - private ReviewDimensionVO convertToDimensionVO(ContestReviewDimension dimension) { - ReviewDimensionVO vo = new ReviewDimensionVO(); - vo.setId(dimension.getId()); - vo.setRuleId(dimension.getRuleId()); - vo.setDimensionName(dimension.getDimensionName()); - vo.setDescription(dimension.getDescription()); - vo.setWeight(dimension.getWeight()); - vo.setMaxScore(dimension.getMaxScore()); - vo.setSort(dimension.getSort()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestReviewServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestReviewServiceImpl.java deleted file mode 100644 index 5812c3f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestReviewServiceImpl.java +++ /dev/null @@ -1,748 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.enums.ContestStateEnum; -import com.lesingle.creation.dto.review.*; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.ContestReviewService; -import com.lesingle.creation.vo.review.*; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛评审服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestReviewServiceImpl implements ContestReviewService { - - private final ContestWorkAssignmentMapper assignmentMapper; - private final ContestWorkMapper workMapper; - private final ContestMapper contestMapper; - private final ContestJudgeMapper judgeMapper; - private final ContestWorkScoreMapper scoreMapper; - private final UserMapper userMapper; - private final ContestRegistrationMapper registrationMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public List assignWork(Long contestId, AssignWorkDTO dto, Long creatorId) { - // 验证作品是否存在 - ContestWork work = workMapper.selectById(dto.getWorkId()); - if (work == null) { - throw new BusinessException("作品不存在"); - } - - if (!work.getContestId().equals(contestId)) { - throw new BusinessException("作品不属于该活动"); - } - - // 检查评审时间 - Contest contest = contestMapper.selectById(contestId); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(contest.getReviewStartTime()) || now.isAfter(contest.getReviewEndTime())) { - throw new BusinessException("不在评审时间范围内"); - } - - // 验证评委是否存在且是该活动的评委 - List judges = judgeMapper.selectList(new LambdaQueryWrapper() - .eq(ContestJudge::getContestId, contestId) - .in(ContestJudge::getJudgeId, dto.getJudgeIds()) - .eq(ContestJudge::getValidState, 1) - .eq(ContestJudge::getDeleted, 0)); - - if (judges.size() != dto.getJudgeIds().size()) { - throw new BusinessException("部分评委不存在或不是该活动的评委"); - } - - // 创建分配记录 - List assignments = new ArrayList<>(); - for (Long judgeId : dto.getJudgeIds()) { - // 检查是否已分配 - ContestWorkAssignment existing = assignmentMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getWorkId, dto.getWorkId()) - .eq(ContestWorkAssignment::getJudgeId, judgeId) - .eq(ContestWorkAssignment::getDeleted, 0)); - - if (existing != null) { - continue; // 跳过已分配的 - } - - ContestWorkAssignment assignment = new ContestWorkAssignment(); - assignment.setContestId(contestId); - assignment.setWorkId(dto.getWorkId()); - assignment.setJudgeId(judgeId); - assignment.setStatus("assigned"); - assignment.setAssignTime(LocalDateTime.now()); - if (creatorId != null) { - assignment.setCreateBy(creatorId.toString()); - } - - assignmentMapper.insert(assignment); - assignments.add(convertToVO(assignment)); - } - - log.info("分配作品成功,作品 ID={}, 评委数={}", dto.getWorkId(), dto.getJudgeIds().size()); - - return assignments; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public List batchAssign(BatchAssignDTO dto, Long creatorId) { - List allAssignments = new ArrayList<>(); - - for (Long workId : dto.getWorkIds()) { - AssignWorkDTO assignWorkDTO = new AssignWorkDTO(); - assignWorkDTO.setWorkId(workId); - assignWorkDTO.setJudgeIds(dto.getJudgeIds()); - List assignments = assignWork(dto.getContestId(), assignWorkDTO, creatorId); - allAssignments.addAll(assignments); - } - - return allAssignments; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public WorkScoreVO score(CreateScoreDTO dto, Long judgeId, Long tenantId) { - // 验证分配记录是否存在 - ContestWorkAssignment assignment = assignmentMapper.selectById(dto.getAssignmentId()); - if (assignment == null || !assignment.getJudgeId().equals(judgeId)) { - throw new BusinessException("分配记录不存在"); - } - - if (!assignment.getWorkId().equals(dto.getWorkId())) { - throw new BusinessException("作品 ID 不匹配"); - } - - // 检查评审时间 - Contest contest = contestMapper.selectById(assignment.getContestId()); - if (contest != null) { - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(contest.getReviewStartTime()) || now.isAfter(contest.getReviewEndTime())) { - throw new BusinessException("不在评审时间范围内"); - } - } - - // 检查是否已评分 - ContestWorkScore existingScore = scoreMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestWorkScore::getAssignmentId, dto.getAssignmentId()) - .eq(ContestWorkScore::getDeleted, 0)); - if (existingScore != null) { - throw new BusinessException("该作品已评分,请使用更新接口"); - } - - // 获取评委信息 - User judge = userMapper.selectById(judgeId); - if (judge == null) { - throw new BusinessException("评委不存在"); - } - - // 创建评分记录 - ContestWorkScore score = new ContestWorkScore(); - score.setTenantId(tenantId); - score.setContestId(assignment.getContestId()); - score.setWorkId(dto.getWorkId()); - score.setAssignmentId(dto.getAssignmentId()); - score.setJudgeId(judgeId); - score.setScore(dto.getScore()); - score.setComment(dto.getComment()); - score.setDimensionScores(dto.getDimensionScores()); - score.setCreateBy(judgeId.toString()); - - scoreMapper.insert(score); - - // 更新分配状态为已完成 - assignment.setStatus("completed"); - assignment.setCompleteTime(LocalDateTime.now()); - assignmentMapper.updateById(assignment); - - // 更新作品状态为评审中 - ContestWork work = workMapper.selectById(dto.getWorkId()); - if (work != null && !"reviewing".equals(work.getStatus())) { - work.setStatus("reviewing"); - workMapper.updateById(work); - } - - log.info("评分成功,分配 ID={}, 分数={}", dto.getAssignmentId(), dto.getScore()); - - return convertToScoreVO(score, judge.getNickname()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public WorkScoreVO updateScore(Long scoreId, CreateScoreDTO dto, Long tenantId) { - ContestWorkScore score = scoreMapper.selectById(scoreId); - if (score == null || !score.getTenantId().equals(tenantId)) { - throw new BusinessException("评分记录不存在"); - } - - score.setScore(dto.getScore()); - score.setComment(dto.getComment()); - score.setDimensionScores(dto.getDimensionScores()); - - scoreMapper.updateById(score); - log.info("更新评分成功,ID={}", scoreId); - - return convertToScoreVO(score, null); - } - - @Override - public Page pageQuery(ReviewAssignmentQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getDeleted, 0) - .eq(queryDTO.getContestId() != null, ContestWorkAssignment::getContestId, queryDTO.getContestId()) - .eq(queryDTO.getWorkId() != null, ContestWorkAssignment::getWorkId, queryDTO.getWorkId()) - .eq(queryDTO.getJudgeId() != null, ContestWorkAssignment::getJudgeId, queryDTO.getJudgeId()) - .eq(queryDTO.getStatus() != null, ContestWorkAssignment::getStatus, queryDTO.getStatus()) - .orderByDesc(ContestWorkAssignment::getAssignTime); - - Page resultPage = assignmentMapper.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - return voPage; - } - - @Override - public List getMyAssignments(Long judgeId, Long tenantId) { - List assignments = assignmentMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getJudgeId, judgeId) - .eq(ContestWorkAssignment::getDeleted, 0) - .orderByDesc(ContestWorkAssignment::getAssignTime)); - - return assignments.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - public ReviewStatsVO getStats(Long contestId) { - LambdaQueryWrapper baseWrapper = new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getDeleted, 0); - if (contestId != null) { - baseWrapper.eq(ContestWorkAssignment::getContestId, contestId); - } - - long total = assignmentMapper.selectCount(baseWrapper); - long assigned = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getStatus, "assigned") - .eq(ContestWorkAssignment::getDeleted, 0) - .eq(contestId != null, ContestWorkAssignment::getContestId, contestId)); - long reviewing = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getStatus, "reviewing") - .eq(ContestWorkAssignment::getDeleted, 0) - .eq(contestId != null, ContestWorkAssignment::getContestId, contestId)); - long completed = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getStatus, "completed") - .eq(ContestWorkAssignment::getDeleted, 0) - .eq(contestId != null, ContestWorkAssignment::getContestId, contestId)); - long scored = scoreMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkScore::getDeleted, 0) - .eq(contestId != null, ContestWorkScore::getContestId, contestId)); - - ReviewStatsVO vo = new ReviewStatsVO(); - vo.setTotalWorks((int) total); - vo.setAssigned((int) assigned); - vo.setReviewing((int) reviewing); - vo.setCompleted((int) completed); - vo.setScored((int) scored); - return vo; - } - - @Override - public List getWorkScores(Long workId, Long tenantId) { - List scores = scoreMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWorkScore::getWorkId, workId) - .eq(ContestWorkScore::getTenantId, tenantId) - .eq(ContestWorkScore::getDeleted, 0) - .orderByDesc(ContestWorkScore::getCreateTime)); - - return scores.stream() - .map(score -> convertToScoreVO(score, null)) - .collect(Collectors.toList()); - } - - @Override - public java.math.BigDecimal getAverageScore(Long workId, Long tenantId) { - List scores = scoreMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWorkScore::getWorkId, workId) - .eq(ContestWorkScore::getTenantId, tenantId) - .eq(ContestWorkScore::getDeleted, 0)); - - if (scores.isEmpty()) { - return java.math.BigDecimal.ZERO; - } - - return scores.stream() - .map(ContestWorkScore::getScore) - .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add) - .divide(java.math.BigDecimal.valueOf(scores.size()), 2, java.math.BigDecimal.ROUND_HALF_UP); - } - - // ========== 转换方法 ========== - - private ReviewAssignmentVO convertToVO(ContestWorkAssignment assignment) { - ReviewAssignmentVO vo = new ReviewAssignmentVO(); - vo.setId(assignment.getId()); - vo.setContestId(assignment.getContestId()); - vo.setWorkId(assignment.getWorkId()); - vo.setJudgeId(assignment.getJudgeId()); - vo.setStatus(assignment.getStatus()); - vo.setAssignTime(assignment.getAssignTime()); - vo.setCompleteTime(assignment.getCompleteTime()); - - // 获取作品标题 - ContestWork work = workMapper.selectById(assignment.getWorkId()); - if (work != null) { - vo.setWorkTitle(work.getTitle()); - } - - // 获取评委姓名 - User judge = userMapper.selectById(assignment.getJudgeId()); - if (judge != null) { - vo.setJudgeName(judge.getNickname()); - } - - // 获取评分信息 - ContestWorkScore score = scoreMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestWorkScore::getAssignmentId, assignment.getId()) - .eq(ContestWorkScore::getDeleted, 0)); - if (score != null) { - vo.setScoreId(score.getId()); - vo.setScore(score.getScore()); - } - - return vo; - } - - private WorkScoreVO convertToScoreVO(ContestWorkScore score, String judgeName) { - WorkScoreVO vo = new WorkScoreVO(); - vo.setId(score.getId()); - vo.setTenantId(score.getTenantId()); - vo.setContestId(score.getContestId()); - vo.setWorkId(score.getWorkId()); - vo.setAssignmentId(score.getAssignmentId()); - vo.setJudgeId(score.getJudgeId()); - vo.setTotalScore(score.getScore()); - vo.setComment(score.getComment()); - vo.setDimensionScores(score.getDimensionScores()); - vo.setCreateTime(score.getCreateTime()); - - if (judgeName != null) { - vo.setJudgeName(judgeName); - } else { - User judge = userMapper.selectById(score.getJudgeId()); - if (judge != null) { - vo.setJudgeName(judge.getNickname()); - } - } - - return vo; - } - - @Override - public String autoAssign(Long contestId, Long creatorId) { - log.info("开始自动分配作品,活动 ID: {}", contestId); - - // 查询活动所有有效作品(最新版本的) - List works = workMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true)); - - // 查询活动所有有效评委 - List judges = judgeMapper.selectList(new LambdaQueryWrapper() - .eq(ContestJudge::getContestId, contestId) - .eq(ContestJudge::getValidState, 1) - .eq(ContestJudge::getDeleted, 0)); - - if (judges.isEmpty()) { - throw new BusinessException("该活动没有评委,无法自动分配"); - } - - if (works.isEmpty()) { - return "没有需要分配的作品"; - } - - int createdCount = 0; - int judgesPerWork = Math.max(1, 3); // 每个作品分配 3 个评委 - - // 轮询分配 - for (int i = 0; i < works.size(); i++) { - ContestWork work = works.get(i); - - // 查询该作品已分配的评委 ID 列表 - List assignedJudgeIds = assignmentMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getWorkId, work.getId()) - .eq(ContestWorkAssignment::getDeleted, 0)) - .stream() - .map(ContestWorkAssignment::getJudgeId) - .collect(Collectors.toList()); - - // 为每个作品分配 judgesPerWork 个评委 - for (int j = 0; j < judgesPerWork; j++) { - int judgeIndex = (i + j) % judges.size(); - ContestJudge judge = judges.get(judgeIndex); - - if (assignedJudgeIds.contains(judge.getJudgeId())) { - continue; // 已分配,跳过 - } - - // 检查是否已存在分配记录 - ContestWorkAssignment existing = assignmentMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getWorkId, work.getId()) - .eq(ContestWorkAssignment::getJudgeId, judge.getJudgeId()) - .eq(ContestWorkAssignment::getDeleted, 0)); - - if (existing != null) { - continue; - } - - ContestWorkAssignment assignment = new ContestWorkAssignment(); - assignment.setContestId(contestId); - assignment.setWorkId(work.getId()); - assignment.setJudgeId(judge.getJudgeId()); - assignment.setStatus("assigned"); - assignment.setAssignTime(LocalDateTime.now()); - if (creatorId != null) { - assignment.setCreateBy(creatorId.toString()); - } - assignmentMapper.insert(assignment); - createdCount++; - } - } - - log.info("自动分配完成,活动 ID={}, 作品数={}, 分配数={}", contestId, works.size(), createdCount); - return String.format("自动分配完成,共 %d 个作品,创建 %d 条分配记录", works.size(), createdCount); - } - - @Override - public ReviewProgressVO getReviewProgress(Long contestId, Long tenantId) { - log.info("获取评审进度统计,活动 ID: {}", contestId); - - ReviewProgressVO result = new ReviewProgressVO(); - - // 活动信息 - Contest contest = contestMapper.selectById(contestId); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - ReviewProgressVO.ContestInfo contestInfo = new ReviewProgressVO.ContestInfo(); - contestInfo.setId(contest.getId()); - contestInfo.setContestName(contest.getContestName()); - contestInfo.setReviewStartTime(contest.getReviewStartTime()); - contestInfo.setReviewEndTime(contest.getReviewEndTime()); - result.setContest(contestInfo); - - // 统计信息 - // 总作品数 - long totalWorks = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true)); - - // 已分配作品数 - long assignedWorksCount = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getContestId, contestId) - .eq(ContestWorkAssignment::getDeleted, 0) - .groupBy(ContestWorkAssignment::getWorkId)); - - // 已评分作品数 - long scoredWorksCount = scoreMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkScore::getContestId, contestId) - .eq(ContestWorkScore::getDeleted, 0) - .groupBy(ContestWorkScore::getWorkId)); - - // 评委总数 - long totalJudges = judgeMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestJudge::getContestId, contestId) - .eq(ContestJudge::getValidState, 1) - .eq(ContestJudge::getDeleted, 0)); - - // 总分配数 - long totalAssignments = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getContestId, contestId) - .eq(ContestWorkAssignment::getDeleted, 0)); - - // 总评分数 - long totalScores = scoreMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkScore::getContestId, contestId) - .eq(ContestWorkScore::getDeleted, 0)); - - // 待评分数 - long pendingScoresCount = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getContestId, contestId) - .eq(ContestWorkAssignment::getStatus, "assigned") - .eq(ContestWorkAssignment::getDeleted, 0)); - - ReviewProgressVO.ReviewSummary summary = new ReviewProgressVO.ReviewSummary(); - summary.setTotalWorks((int) totalWorks); - summary.setAssignedWorksCount((int) assignedWorksCount); - summary.setScoredWorksCount((int) scoredWorksCount); - summary.setUnassignedWorksCount((int) (totalWorks - assignedWorksCount)); - summary.setTotalJudges((int) totalJudges); - summary.setTotalAssignments((int) totalAssignments); - summary.setTotalScores((int) totalScores); - summary.setPendingScoresCount((int) pendingScoresCount); - result.setSummary(summary); - - // 进度百分比 - ReviewProgressVO.Progress progress = new ReviewProgressVO.Progress(); - progress.setAssignmentProgress(totalWorks > 0 ? (double) assignedWorksCount / totalWorks * 100 : 0); - progress.setScoringProgress(assignedWorksCount > 0 ? (double) totalScores / (assignedWorksCount * 3) * 100 : 0); - progress.setOverallProgress(totalWorks > 0 ? (double) scoredWorksCount / totalWorks * 100 : 0); - result.setProgress(progress); - - // 评委进度(简化) - result.setJudgeProgress(new ArrayList<>()); - - // 待分配作品 - result.setUnassignedWorks(new ArrayList<>()); - - // 待评审分配 - result.setPendingAssignments(new ArrayList<>()); - - return result; - } - - @Override - public WorkStatusStatsVO getWorkStatusStats(Long contestId, Long tenantId) { - log.info("获取作品状态统计,活动 ID: {}", contestId); - - WorkStatusStatsVO vo = new WorkStatusStatsVO(); - - // 总作品数 - long total = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true)); - - // 已提交 - long submitted = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getStatus, "submitted") - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true)); - - // 评审中 - long reviewing = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getStatus, "reviewing") - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true)); - - // 已评审 - long reviewed = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getStatus, "reviewed") - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true)); - - vo.setTotal((int) total); - vo.setSubmitted((int) submitted); - vo.setReviewing((int) reviewing); - vo.setReviewed((int) reviewed); - vo.setAwarded(0); // 简化处理 - - return vo; - } - - @Override - public FinalScoreVO getFinalScore(Long workId, Long tenantId) { - log.info("获取作品最终得分,作品 ID: {}", workId); - - FinalScoreVO vo = new FinalScoreVO(); - vo.setWorkId(workId); - - // 获取该作品的所有评分 - List scores = scoreMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWorkScore::getWorkId, workId) - .eq(ContestWorkScore::getTenantId, tenantId) - .eq(ContestWorkScore::getDeleted, 0)); - - if (scores.isEmpty()) { - vo.setFinalScore(java.math.BigDecimal.ZERO); - vo.setScoreCount(0); - vo.setCalculationRule("average"); - return vo; - } - - // 计算平均分 - java.math.BigDecimal totalScore = scores.stream() - .map(ContestWorkScore::getScore) - .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add); - - java.math.BigDecimal avgScore = totalScore.divide( - java.math.BigDecimal.valueOf(scores.size()), 2, java.math.BigDecimal.ROUND_HALF_UP); - - vo.setFinalScore(avgScore); - vo.setScoreCount(scores.size()); - vo.setCalculationRule("average"); - vo.setRank(0); // 简化处理,实际需要计算排名 - - return vo; - } - - @Override - public void replaceJudge(Long assignmentId, Long newJudgeId, Long tenantId) { - log.info("替换评委,分配 ID: {}, 新评委 ID: {}", assignmentId, newJudgeId); - - ContestWorkAssignment assignment = assignmentMapper.selectById(assignmentId); - if (assignment == null) { - throw new BusinessException("分配记录不存在"); - } - - // 检查新评委是否是该活动的评委 - ContestJudge judge = judgeMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestJudge::getContestId, assignment.getContestId()) - .eq(ContestJudge::getJudgeId, newJudgeId) - .eq(ContestJudge::getValidState, 1) - .eq(ContestJudge::getDeleted, 0)); - - if (judge == null) { - throw new BusinessException("该用户不是该活动的评委"); - } - - // 删除原分配记录 - assignment.setDeleted(1); - assignmentMapper.updateById(assignment); - - // 创建新分配记录 - ContestWorkAssignment newAssignment = new ContestWorkAssignment(); - newAssignment.setContestId(assignment.getContestId()); - newAssignment.setWorkId(assignment.getWorkId()); - newAssignment.setJudgeId(newJudgeId); - newAssignment.setStatus("assigned"); - newAssignment.setAssignTime(LocalDateTime.now()); - assignmentMapper.insert(newAssignment); - - log.info("评委替换成功"); - } - - @Override - public List getJudgeContests(Long judgeId, Long tenantId) { - log.info("获取评委参与的活动列表,评委 ID: {}", judgeId); - - // 查询该评委参与的活动 ID 列表 - List contestJudges = judgeMapper.selectList(new LambdaQueryWrapper() - .eq(ContestJudge::getJudgeId, judgeId) - .eq(ContestJudge::getValidState, 1) - .eq(ContestJudge::getDeleted, 0)); - - List result = new ArrayList<>(); - for (ContestJudge contestJudge : contestJudges) { - Contest contest = contestMapper.selectById(contestJudge.getContestId()); - if (contest == null) { - continue; - } - - JudgeContestVO vo = new JudgeContestVO(); - vo.setId(contest.getId()); - vo.setContestName(contest.getContestName()); - vo.setStatus(contest.getStatus()); - vo.setReviewStartTime(contest.getReviewStartTime()); - vo.setReviewEndTime(contest.getReviewEndTime()); - - // 统计该评委在该活动中的作品分配情况 - long assignedCount = assignmentMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getContestId, contest.getId()) - .eq(ContestWorkAssignment::getJudgeId, judgeId) - .eq(ContestWorkAssignment::getDeleted, 0)); - - long scoredCount = scoreMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWorkScore::getContestId, contest.getId()) - .eq(ContestWorkScore::getJudgeId, judgeId) - .eq(ContestWorkScore::getDeleted, 0)); - - vo.setAssignedWorksCount((int) assignedCount); - vo.setScoredWorksCount((int) scoredCount); - vo.setPendingWorksCount((int) (assignedCount - scoredCount)); - - result.add(vo); - } - - return result; - } - - @Override - public Page getJudgeContestWorks(Long contestId, Long judgeId, Long tenantId, JudgeWorkQueryDTO queryDTO) { - log.info("获取评委在某个活动下的作品列表,活动 ID: {}, 评委 ID: {}", contestId, judgeId); - - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - // 查询该评委在该活动中的分配记录 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(ContestWorkAssignment::getContestId, contestId) - .eq(ContestWorkAssignment::getJudgeId, judgeId) - .eq(ContestWorkAssignment::getDeleted, 0) - .orderByDesc(ContestWorkAssignment::getAssignTime); - - Page resultPage = assignmentMapper.page(page, wrapper); - - List voList = new ArrayList<>(); - for (ContestWorkAssignment assignment : resultPage.getRecords()) { - JudgeWorkVO vo = new JudgeWorkVO(); - vo.setId(assignment.getWorkId()); - vo.setAssignmentStatus(assignment.getStatus()); - vo.setAssignmentTime(assignment.getAssignTime()); - - // 获取作品信息 - ContestWork work = workMapper.selectById(assignment.getWorkId()); - if (work != null) { - vo.setWorkNo(work.getWorkNo()); - vo.setTitle(work.getTitle()); - } - - // 获取评分信息 - ContestWorkScore score = scoreMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestWorkScore::getAssignmentId, assignment.getId()) - .eq(ContestWorkScore::getDeleted, 0)); - if (score != null) { - vo.setScoreStatus("scored"); - vo.setScore(score.getScore()); - vo.setComments(score.getComment()); - } else { - vo.setScoreStatus("pending"); - } - - // 获取参赛者信息 - if (work != null) { - ContestRegistration registration = registrationMapper.selectById(work.getRegistrationId()); - if (registration != null) { - vo.setParticipantName(registration.getAccountName()); - vo.setParticipantType("team".equals(registration.getRegistrationType()) ? "team" : "personal"); - } - } - - voList.add(vo); - } - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - return voPage; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestServiceImpl.java deleted file mode 100644 index 13b8108..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestServiceImpl.java +++ /dev/null @@ -1,627 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.contest.*; -import com.lesingle.creation.entity.Contest; -import com.lesingle.creation.entity.ContestAttachment; -import com.lesingle.creation.entity.ContestRegistration; -import com.lesingle.creation.entity.ContestTeamMember; -import com.lesingle.creation.mapper.ContestMapper; -import com.lesingle.creation.mapper.ContestRegistrationMapper; -import com.lesingle.creation.mapper.ContestTeamMemberMapper; -import com.lesingle.creation.service.ContestService; -import com.lesingle.creation.vo.contest.*; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeanUtils; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestServiceImpl extends ServiceImpl implements ContestService { - - private final ContestMapper contestMapper; - private final ContestRegistrationMapper contestRegistrationMapper; - private final ContestTeamMemberMapper contestTeamMemberMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public ContestDetailVO create(CreateContestDTO dto, Long creatorId) { - log.info("开始创建竞赛,竞赛名称:{}", dto.getContestName()); - - // 检查竞赛名称是否已存在 - Contest existingContest = contestMapper.selectByContestName(dto.getContestName()); - if (existingContest != null) { - throw new BusinessException("竞赛名称已存在"); - } - - // 验证时间顺序 - validateTimeOrder(dto); - - // 创建竞赛 - Contest contest = new Contest(); - BeanUtils.copyProperties(dto, contest); - - // 处理 JSON 字段 - if (dto.getContestTenants() != null && !dto.getContestTenants().isEmpty()) { - contest.setContestTenants(listToJson(dto.getContestTenants())); - } - if (dto.getTargetCities() != null && !dto.getTargetCities().isEmpty()) { - contest.setTargetCities(listToJson(dto.getTargetCities())); - } - if (dto.getAllowedGrades() != null && !dto.getAllowedGrades().isEmpty()) { - contest.setAllowedGrades(listToJson(dto.getAllowedGrades())); - } - if (dto.getAllowedClasses() != null && !dto.getAllowedClasses().isEmpty()) { - contest.setAllowedClasses(listToJson(dto.getAllowedClasses())); - } - if (dto.getOrganizers() != null) { - contest.setOrganizers("[\"" + dto.getOrganizers() + "\"]"); - } - if (dto.getCoOrganizers() != null) { - contest.setCoOrganizers("[\"" + dto.getCoOrganizers() + "\"]"); - } - if (dto.getSponsors() != null) { - contest.setSponsors("[\"" + dto.getSponsors() + "\"]"); - } - - contest.setContestState("unpublished"); - contest.setStatus("ongoing"); - contest.setResultState("unpublished"); - contest.setRequireAudit(dto.getRequireAudit() != null ? dto.getRequireAudit() : true); - contest.setSubmitRule(dto.getSubmitRule() != null ? dto.getSubmitRule() : "once"); - contest.setCreateBy(String.valueOf(creatorId)); - - contestMapper.insert(contest); - log.info("竞赛创建成功,竞赛 ID: {}", contest.getId()); - - return convertToDetailVO(contest); - } - - @Override - public Page pageList(ContestQueryDTO queryDTO, Long tenantId) { - log.info("分页查询竞赛列表,页码:{}, 每页大小:{}", queryDTO.getPage(), queryDTO.getPageSize()); - - int page = queryDTO.getPage() != null ? queryDTO.getPage() : 1; - int pageSize = queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10; - - Page contestPage = new Page<>(page, pageSize); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - - wrapper.eq(Contest::getValidState, 1); - - // 关键字查询 - if (StringUtils.hasText(queryDTO.getContestName())) { - wrapper.like(Contest::getContestName, queryDTO.getContestName()); - } - - // 状态筛选 - if (StringUtils.hasText(queryDTO.getContestState())) { - wrapper.eq(Contest::getContestState, queryDTO.getContestState()); - } - - // 类型筛选 - if (StringUtils.hasText(queryDTO.getContestType())) { - wrapper.eq(Contest::getContestType, queryDTO.getContestType()); - } - - // 进度状态筛选 - if (StringUtils.hasText(queryDTO.getStatus())) { - wrapper.eq(Contest::getStatus, queryDTO.getStatus()); - } - - // 可见范围筛选 - if (StringUtils.hasText(queryDTO.getVisibility())) { - wrapper.eq(Contest::getVisibility, queryDTO.getVisibility()); - } - - wrapper.orderByDesc(Contest::getCreateTime); - - Page resultPage = contestMapper.selectPage(contestPage, wrapper); - - // 转换为 VO 并计算阶段 - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public ContestDetailVO detail(Long id, Long tenantId) { - log.info("查询竞赛详情,竞赛 ID: {}", id); - - Contest contest = contestMapper.selectById(id); - if (contest == null) { - throw new BusinessException("竞赛不存在"); - } - - return convertToDetailVO(contest); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ContestDetailVO update(Long id, UpdateContestDTO dto, Long modifierId) { - log.info("更新竞赛,竞赛 ID: {}", id); - - Contest existingContest = contestMapper.selectById(id); - if (existingContest == null) { - throw new BusinessException("竞赛不存在"); - } - - // 如果更新了竞赛名称,检查是否重复 - if (StringUtils.hasText(dto.getContestName()) && - !dto.getContestName().equals(existingContest.getContestName())) { - Contest conflictContest = contestMapper.selectByContestName(dto.getContestName()); - if (conflictContest != null) { - throw new BusinessException("竞赛名称已存在"); - } - } - - // 验证时间顺序 - validateTimeOrder(dto); - - // 更新竞赛信息 - Contest contest = new Contest(); - contest.setId(id); - BeanUtils.copyProperties(dto, contest, "id"); - - // 处理 JSON 字段 - if (dto.getContestTenants() != null) { - contest.setContestTenants(dto.getContestTenants().isEmpty() ? null : listToJson(dto.getContestTenants())); - } - if (dto.getTargetCities() != null) { - contest.setTargetCities(dto.getTargetCities().isEmpty() ? null : listToJson(dto.getTargetCities())); - } - if (dto.getAllowedGrades() != null) { - contest.setAllowedGrades(dto.getAllowedGrades().isEmpty() ? null : listToJson(dto.getAllowedGrades())); - } - if (dto.getAllowedClasses() != null) { - contest.setAllowedClasses(dto.getAllowedClasses().isEmpty() ? null : listToJson(dto.getAllowedClasses())); - } - if (dto.getOrganizers() != null) { - contest.setOrganizers("[\"" + dto.getOrganizers() + "\"]"); - } - if (dto.getCoOrganizers() != null) { - contest.setCoOrganizers("[\"" + dto.getCoOrganizers() + "\"]"); - } - if (dto.getSponsors() != null) { - contest.setSponsors("[\"" + dto.getSponsors() + "\"]"); - } - - contest.setUpdateBy(String.valueOf(modifierId)); - - contestMapper.updateById(contest); - log.info("竞赛更新成功,竞赛 ID: {}", id); - - return convertToDetailVO(contestMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ContestDetailVO publish(Long id, String contestState, Long modifierId) { - log.info("发布/取消发布竞赛,竞赛 ID: {}, 状态:{}", id, contestState); - - Contest contest = contestMapper.selectById(id); - if (contest == null) { - throw new BusinessException("竞赛不存在"); - } - - Contest updateContest = new Contest(); - updateContest.setId(id); - updateContest.setContestState(contestState); - updateContest.setUpdateBy(String.valueOf(modifierId)); - - contestMapper.updateById(updateContest); - log.info("竞赛发布状态更新成功,竞赛 ID: {}", id); - - return convertToDetailVO(contestMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ContestDetailVO finish(Long id, Long modifierId) { - log.info("标记竞赛为完结,竞赛 ID: {}", id); - - Contest contest = contestMapper.selectById(id); - if (contest == null) { - throw new BusinessException("竞赛不存在"); - } - - if (!"published".equals(contest.getContestState())) { - throw new BusinessException("只有已发布的竞赛才能标记为完结"); - } - - if ("finished".equals(contest.getStatus())) { - throw new BusinessException("竞赛已经完结"); - } - - Contest updateContest = new Contest(); - updateContest.setId(id); - updateContest.setStatus("finished"); - updateContest.setUpdateBy(String.valueOf(modifierId)); - - contestMapper.updateById(updateContest); - log.info("竞赛标记为完结,竞赛 ID: {}", id); - - return convertToDetailVO(contestMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ContestDetailVO reopen(Long id, Long modifierId) { - log.info("重新开启竞赛,竞赛 ID: {}", id); - - Contest contest = contestMapper.selectById(id); - if (contest == null) { - throw new BusinessException("竞赛不存在"); - } - - if (!"finished".equals(contest.getStatus())) { - throw new BusinessException("只有已完结的竞赛才能重新开启"); - } - - Contest updateContest = new Contest(); - updateContest.setId(id); - updateContest.setStatus("ongoing"); - updateContest.setUpdateBy(String.valueOf(modifierId)); - - contestMapper.updateById(updateContest); - log.info("竞赛重新开启,竞赛 ID: {}", id); - - return convertToDetailVO(contestMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - log.info("删除竞赛,竞赛 ID: {}", id); - - Contest contest = contestMapper.selectById(id); - if (contest == null) { - throw new BusinessException("竞赛不存在"); - } - - // 逻辑删除竞赛 - contestMapper.deleteById(id); - log.info("竞赛删除成功,竞赛 ID: {}", id); - } - - @Override - public ContestStatsVO getStats() { - log.info("获取竞赛统计信息"); - - ContestStatsVO stats = new ContestStatsVO(); - - // 查询所有有效竞赛 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Contest::getValidState, 1); - List contests = contestMapper.selectList(wrapper); - - stats.setTotal(contests.size()); - - int unpublished = 0, registering = 0, submitting = 0, reviewing = 0, finished = 0; - LocalDateTime now = LocalDateTime.now(); - - for (Contest contest : contests) { - String stage = getContestStage(contest, now); - if ("unpublished".equals(stage)) { - unpublished++; - } else if ("registering".equals(stage)) { - registering++; - } else if ("submitting".equals(stage)) { - submitting++; - } else if ("reviewing".equals(stage)) { - reviewing++; - } else if ("finished".equals(stage)) { - finished++; - } - } - - stats.setUnpublished(unpublished); - stats.setRegistering(registering); - stats.setSubmitting(submitting); - stats.setReviewing(reviewing); - stats.setFinished(finished); - - return stats; - } - - @Override - public Contest getById(Long id) { - return contestMapper.selectById(id); - } - - /** - * 判断竞赛当前阶段 - */ - private String getContestStage(Contest contest, LocalDateTime now) { - if ("unpublished".equals(contest.getContestState())) { - return "unpublished"; - } - if ("finished".equals(contest.getStatus())) { - return "finished"; - } - - if (contest.getRegisterStartTime() != null && contest.getRegisterEndTime() != null && - now.isAfter(contest.getRegisterStartTime()) && now.isBefore(contest.getRegisterEndTime())) { - return "registering"; - } - - if (contest.getSubmitStartTime() != null && contest.getSubmitEndTime() != null && - now.isAfter(contest.getSubmitStartTime()) && now.isBefore(contest.getSubmitEndTime())) { - return "submitting"; - } - - if (contest.getReviewStartTime() != null && contest.getReviewEndTime() != null && - now.isAfter(contest.getReviewStartTime()) && now.isBefore(contest.getReviewEndTime())) { - return "reviewing"; - } - - if (contest.getReviewEndTime() != null && now.isAfter(contest.getReviewEndTime())) { - return "finished"; - } - - return "published"; - } - - /** - * 验证时间顺序 - */ - private void validateTimeOrder(CreateContestDTO dto) { - if (dto.getRegisterStartTime().isAfter(dto.getRegisterEndTime()) || - dto.getRegisterStartTime().isEqual(dto.getRegisterEndTime())) { - throw new BusinessException("报名开始时间必须早于报名结束时间"); - } - - if (dto.getRegisterEndTime().isAfter(dto.getSubmitStartTime()) || - dto.getRegisterEndTime().isEqual(dto.getSubmitStartTime())) { - throw new BusinessException("报名结束时间必须早于作品提交开始时间"); - } - - if (dto.getSubmitStartTime().isAfter(dto.getSubmitEndTime()) || - dto.getSubmitStartTime().isEqual(dto.getSubmitEndTime())) { - throw new BusinessException("作品提交开始时间必须早于作品提交结束时间"); - } - - if (dto.getSubmitEndTime().isAfter(dto.getReviewStartTime()) || - dto.getSubmitEndTime().isEqual(dto.getReviewStartTime())) { - throw new BusinessException("作品提交结束时间必须早于评审开始时间"); - } - - if (dto.getReviewStartTime().isAfter(dto.getReviewEndTime()) || - dto.getReviewStartTime().isEqual(dto.getReviewEndTime())) { - throw new BusinessException("评审开始时间必须早于评审结束时间"); - } - - if (dto.getStartTime().isAfter(dto.getEndTime()) || - dto.getStartTime().isEqual(dto.getEndTime())) { - throw new BusinessException("竞赛开始时间必须早于竞赛结束时间"); - } - } - - /** - * 验证时间顺序(UpdateContestDTO) - */ - private void validateTimeOrder(UpdateContestDTO dto) { - // 简化版本,实际需要根据现有数据和更新数据合并验证 - } - - /** - * List 转 JSON 字符串 - */ - private String listToJson(List list) { - if (list == null || list.isEmpty()) { - return null; - } - return list.stream() - .map(item -> item instanceof Integer ? item.toString() : "\"" + item + "\"") - .collect(Collectors.joining(",", "[", "]")); - } - - /** - * 转换为详情 VO - */ - private ContestDetailVO convertToDetailVO(Contest contest) { - ContestDetailVO vo = new ContestDetailVO(); - vo.setId(contest.getId()); - vo.setContestName(contest.getContestName()); - vo.setContestType(contest.getContestType()); - vo.setContestState(contest.getContestState()); - vo.setStatus(contest.getStatus()); - vo.setStage(getContestStage(contest, LocalDateTime.now())); - vo.setStartTime(contest.getStartTime()); - vo.setEndTime(contest.getEndTime()); - vo.setAddress(contest.getAddress()); - vo.setContent(contest.getContent()); - vo.setContestTenants(jsonToList(contest.getContestTenants(), Integer.class)); - vo.setCoverUrl(contest.getCoverUrl()); - vo.setPosterUrl(contest.getPosterUrl()); - vo.setContactName(contest.getContactName()); - vo.setContactPhone(contest.getContactPhone()); - vo.setContactQrcode(contest.getContactQrcode()); - vo.setOrganizers(jsonToList(contest.getOrganizers(), String.class)); - vo.setCoOrganizers(jsonToList(contest.getCoOrganizers(), String.class)); - vo.setSponsors(jsonToList(contest.getSponsors(), String.class)); - vo.setVisibility(contest.getVisibility()); - vo.setTargetCities(jsonToList(contest.getTargetCities(), String.class)); - vo.setAgeMin(contest.getAgeMin()); - vo.setAgeMax(contest.getAgeMax()); - vo.setRegisterStartTime(contest.getRegisterStartTime()); - vo.setRegisterEndTime(contest.getRegisterEndTime()); - vo.setRegisterState(contest.getRegisterState()); - vo.setRequireAudit(contest.getRequireAudit()); - vo.setAllowedGrades(jsonToList(contest.getAllowedGrades(), Integer.class)); - vo.setAllowedClasses(jsonToList(contest.getAllowedClasses(), Integer.class)); - vo.setTeamMinMembers(contest.getTeamMinMembers()); - vo.setTeamMaxMembers(contest.getTeamMaxMembers()); - vo.setSubmitRule(contest.getSubmitRule()); - vo.setSubmitStartTime(contest.getSubmitStartTime()); - vo.setSubmitEndTime(contest.getSubmitEndTime()); - vo.setWorkType(contest.getWorkType()); - vo.setWorkRequirement(contest.getWorkRequirement()); - vo.setReviewRuleId(contest.getReviewRuleId()); - vo.setReviewStartTime(contest.getReviewStartTime()); - vo.setReviewEndTime(contest.getReviewEndTime()); - vo.setResultState(contest.getResultState()); - vo.setResultPublishTime(contest.getResultPublishTime()); - vo.setValidState(contest.getValidState()); - vo.setCreator(Long.parseLong(contest.getCreateBy())); - vo.setCreateTime(contest.getCreateTime()); - vo.setModifier(Long.parseLong(contest.getUpdateBy())); - vo.setModifyTime(contest.getUpdateTime()); - - // TODO: 统计人数 - vo.setRegistrationCount(0); - vo.setWorksCount(0); - vo.setTeamsCount(0); - vo.setJudgesCount(0); - vo.setTotalWorksCount(0); - vo.setReviewedCount(0); - - vo.setAttachments(new ArrayList<>()); - - return vo; - } - - /** - * 转换为列表 VO - */ - private ContestListVO convertToListVO(Contest contest) { - ContestListVO vo = new ContestListVO(); - vo.setId(contest.getId()); - vo.setContestName(contest.getContestName()); - vo.setContestType(contest.getContestType()); - vo.setContestState(contest.getContestState()); - vo.setStatus(contest.getStatus()); - vo.setStage(getContestStage(contest, LocalDateTime.now())); - vo.setStartTime(contest.getStartTime()); - vo.setEndTime(contest.getEndTime()); - vo.setCoverUrl(contest.getCoverUrl()); - vo.setPosterUrl(contest.getPosterUrl()); - vo.setOrganizers(contest.getOrganizers()); - vo.setVisibility(contest.getVisibility()); - vo.setRegisterStartTime(contest.getRegisterStartTime()); - vo.setRegisterEndTime(contest.getRegisterEndTime()); - vo.setSubmitStartTime(contest.getSubmitStartTime()); - vo.setSubmitEndTime(contest.getSubmitEndTime()); - vo.setReviewStartTime(contest.getReviewStartTime()); - vo.setReviewEndTime(contest.getReviewEndTime()); - vo.setValidState(contest.getValidState()); - vo.setCreateTime(contest.getCreateTime()); - - // TODO: 统计人数 - vo.setRegistrationCount(0); - vo.setWorksCount(0); - vo.setTeamsCount(0); - vo.setJudgesCount(0); - vo.setTotalWorksCount(0); - vo.setReviewedCount(0); - - vo.setAttachments(new ArrayList<>()); - - return vo; - } - - /** - * JSON 字符串转 List - */ - private List jsonToList(String json, Class clazz) { - if (json == null || json.isEmpty()) { - return new ArrayList<>(); - } - // 简化处理,实际需要更完善的 JSON 解析 - List list = new ArrayList<>(); - String content = json.replaceAll("[\\[\\]\"]", ""); - if (content.isEmpty()) { - return list; - } - String[] items = content.split(","); - for (String item : items) { - if (clazz == Integer.class) { - list.add(clazz.cast(Integer.parseInt(item.trim()))); - } else { - list.add(clazz.cast(item.trim())); - } - } - return list; - } - - @Override - public Page myContests(ContestQueryDTO queryDTO, Long userId, Long tenantId) { - log.info("查询我参与的活动列表,用户 ID: {}", userId); - - // 查询用户参与的竞赛 ID 列表(通过报名记录) - LambdaQueryWrapper registrationWrapper = new LambdaQueryWrapper<>(); - registrationWrapper.eq(ContestRegistration::getUserId, userId); - - List registrations = contestRegistrationMapper.selectList(registrationWrapper); - List registrationContestIds = registrations.stream() - .map(ContestRegistration::getContestId) - .collect(Collectors.toList()); - - // 查询用户参与的团队对应的竞赛 ID(通过团队成员身份) - LambdaQueryWrapper teamMemberWrapper = new LambdaQueryWrapper<>(); - teamMemberWrapper.eq(ContestTeamMember::getUserId, userId); - - List teamMembers = contestTeamMemberMapper.selectList(teamMemberWrapper); - List teamContestIds = teamMembers.stream() - .map(ContestTeamMember::getTeamId) - .collect(Collectors.toList()); - - // 合并竞赛 ID 列表 - List contestIds = new ArrayList<>(); - contestIds.addAll(registrationContestIds); - contestIds.addAll(teamContestIds); - contestIds = contestIds.stream().distinct().collect(Collectors.toList()); - - if (contestIds.isEmpty()) { - // 如果用户没有参与任何竞赛,返回空列表 - return new Page<>(queryDTO.getPage() != null ? queryDTO.getPage() : 1, - queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10); - } - - // 分页查询这些竞赛 - int page = queryDTO.getPage() != null ? queryDTO.getPage() : 1; - int pageSize = queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10; - - // 在内存中分页 - int start = (page - 1) * pageSize; - int end = Math.min(start + pageSize, contestIds.size()); - List pageContestIds = contestIds.subList(start, end); - - // 查询竞赛详情 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.in(Contest::getId, pageContestIds); - wrapper.eq(Contest::getValidState, 1); - List contests = contestMapper.selectList(wrapper); - - // 转换为 VO - List voList = contests.stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(page, pageSize, (long) contestIds.size()); - voPage.setRecords(voList); - - return voPage; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestTeamServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestTeamServiceImpl.java deleted file mode 100644 index 21d67c2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestTeamServiceImpl.java +++ /dev/null @@ -1,373 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.common.enums.ContestTypeEnum; -import com.lesingle.creation.dto.team.*; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.ContestTeamService; -import com.lesingle.creation.vo.team.TeamMemberVO; -import com.lesingle.creation.vo.team.TeamVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛团队服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestTeamServiceImpl implements ContestTeamService { - - private final ContestTeamMapper teamMapper; - private final ContestMapper contestMapper; - private final UserMapper userMapper; - private final ContestTeamMemberMapper memberMapper; - private final ContestRegistrationMapper registrationMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public TeamVO create(CreateTeamDTO dto, Long tenantId, Long creatorId) { - // 验证活动是否存在 - Contest contest = contestMapper.selectById(dto.getContestId()); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - // 检查活动类型 - if (!ContestTypeEnum.TEAM.getCode().equals(contest.getContestType())) { - throw new BusinessException("该活动不是团队参与"); - } - - // 检查团队名称是否已存在(同一活动、同一租户内) - ContestTeam existing = teamMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestTeam::getTenantId, tenantId) - .eq(ContestTeam::getContestId, dto.getContestId()) - .eq(ContestTeam::getTeamName, dto.getTeamName()) - .eq(ContestTeam::getValidState, 1) - .eq(ContestTeam::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("团队名称已存在"); - } - - // 验证队长用户是否存在 - User leader = userMapper.selectById(dto.getLeaderId()); - if (leader == null) { - throw new BusinessException("队长用户不存在"); - } - - // 创建团队 - ContestTeam team = new ContestTeam(); - team.setTenantId(tenantId); - team.setContestId(dto.getContestId()); - team.setTeamName(dto.getTeamName()); - team.setLeaderUserId(dto.getLeaderId()); - team.setMaxMembers(dto.getMaxMembers()); - team.setValidState(1); - - teamMapper.insert(team); - - // 自动添加队长为成员 - ContestTeamMember leaderMember = new ContestTeamMember(); - leaderMember.setTenantId(tenantId); - leaderMember.setTeamId(team.getId()); - leaderMember.setUserId(dto.getLeaderId()); - leaderMember.setRole("leader"); - memberMapper.insert(leaderMember); - - // 添加其他队员(排除队长) - if (dto.getMemberIds() != null && !dto.getMemberIds().isEmpty()) { - for (Long memberId : dto.getMemberIds()) { - if (!memberId.equals(dto.getLeaderId())) { - ContestTeamMember member = new ContestTeamMember(); - member.setTenantId(tenantId); - member.setTeamId(team.getId()); - member.setUserId(memberId); - member.setRole("member"); - memberMapper.insert(member); - } - } - } - - // 添加指导老师 - if (dto.getTeacherIds() != null && !dto.getTeacherIds().isEmpty()) { - for (Long teacherId : dto.getTeacherIds()) { - ContestTeamMember teacherMember = new ContestTeamMember(); - teacherMember.setTenantId(tenantId); - teacherMember.setTeamId(team.getId()); - teacherMember.setUserId(teacherId); - teacherMember.setRole("mentor"); - memberMapper.insert(teacherMember); - } - } - - // 自动创建团队报名记录 - String accountNo = leader.getUsername(); - String accountName = leader.getNickname(); - - ContestRegistration registration = new ContestRegistration(); - registration.setContestId(dto.getContestId()); - registration.setTenantId(tenantId); - registration.setRegistrationType("team"); - registration.setTeamId(team.getId()); - registration.setTeamName(dto.getTeamName()); - registration.setUserId(dto.getLeaderId()); - registration.setAccountNo(accountNo); - registration.setAccountName(accountName); - registration.setRegistrationState("pending"); - registration.setRegistrant(dto.getLeaderId()); - if (creatorId != null) { - registration.setCreateBy(creatorId.toString()); - } - - registrationMapper.insert(registration); - - log.info("创建团队成功,ID={}, 名称={}", team.getId(), dto.getTeamName()); - - return convertToVO(team, contest.getContestName()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public TeamVO update(Long id, UpdateTeamDTO dto, Long tenantId) { - ContestTeam team = teamMapper.selectById(id); - if (team == null || !team.getTenantId().equals(tenantId)) { - throw new BusinessException("团队不存在"); - } - - team.setTeamName(dto.getTeamName()); - team.setMaxMembers(dto.getMaxMembers()); - - // 更新队员 - if (dto.getMemberIds() != null && !dto.getMemberIds().isEmpty()) { - // 删除原有队员(保留队长和指导老师) - memberMapper.delete(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, id) - .eq(ContestTeamMember::getRole, "member")); - - // 添加新队员 - for (Long memberId : dto.getMemberIds()) { - ContestTeamMember member = new ContestTeamMember(); - member.setTenantId(tenantId); - member.setTeamId(id); - member.setUserId(memberId); - member.setRole("member"); - memberMapper.insert(member); - } - } - - // 更新指导老师 - if (dto.getTeacherIds() != null && !dto.getTeacherIds().isEmpty()) { - // 删除原有指导老师 - memberMapper.delete(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, id) - .eq(ContestTeamMember::getRole, "mentor")); - - // 添加新指导老师 - for (Long teacherId : dto.getTeacherIds()) { - ContestTeamMember teacherMember = new ContestTeamMember(); - teacherMember.setTenantId(tenantId); - teacherMember.setTeamId(id); - teacherMember.setUserId(teacherId); - teacherMember.setRole("mentor"); - memberMapper.insert(teacherMember); - } - } - - teamMapper.updateById(team); - log.info("更新团队成功,ID={}", id); - - Contest contest = contestMapper.selectById(team.getContestId()); - return convertToVO(team, contest != null ? contest.getContestName() : null); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - ContestTeam team = teamMapper.selectById(id); - if (team == null || !team.getTenantId().equals(tenantId)) { - throw new BusinessException("团队不存在"); - } - - // 检查是否有作品 - // 简化处理,直接逻辑删除团队和成员 - - team.setValidState(2); - teamMapper.updateById(team); - - // 删除团队成员 - memberMapper.delete(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, id)); - - log.info("删除团队成功,ID={}", id); - } - - @Override - public TeamVO getDetail(Long id, Long tenantId) { - ContestTeam team = teamMapper.selectById(id); - if (team == null || !team.getTenantId().equals(tenantId)) { - throw new BusinessException("团队不存在"); - } - - Contest contest = contestMapper.selectById(team.getContestId()); - return convertToVO(team, contest != null ? contest.getContestName() : null); - } - - @Override - public List list(Long contestId, Long tenantId) { - List teams = teamMapper.selectList(new LambdaQueryWrapper() - .eq(ContestTeam::getTenantId, tenantId) - .eq(contestId != null, ContestTeam::getContestId, contestId) - .eq(ContestTeam::getValidState, 1) - .eq(ContestTeam::getDeleted, 0) - .orderByDesc(ContestTeam::getCreateTime)); - - return teams.stream() - .map(team -> convertToVO(team, null)) - .collect(Collectors.toList()); - } - - @Override - public List listByContest(Long contestId, Long tenantId) { - log.info("按竞赛查询团队列表,活动 ID: {}", contestId); - - List teams = teamMapper.selectList(new LambdaQueryWrapper() - .eq(ContestTeam::getTenantId, tenantId) - .eq(ContestTeam::getContestId, contestId) - .eq(ContestTeam::getValidState, 1) - .eq(ContestTeam::getDeleted, 0) - .orderByDesc(ContestTeam::getCreateTime)); - - return teams.stream() - .map(team -> convertToVO(team, null)) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void inviteMember(Long teamId, InviteMemberDTO dto, Long tenantId, Long creatorId) { - ContestTeam team = teamMapper.selectById(teamId); - if (team == null || !team.getTenantId().equals(tenantId)) { - throw new BusinessException("团队不存在"); - } - - // 检查成员是否已满 - Long currentCount = memberMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, teamId) - .in(ContestTeamMember::getRole, "leader", "member")); - if (currentCount >= team.getMaxMembers()) { - throw new BusinessException("团队成员已满"); - } - - // 检查用户是否已是成员 - ContestTeamMember existing = memberMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, teamId) - .eq(ContestTeamMember::getUserId, dto.getUserId())); - if (existing != null) { - throw new BusinessException("该用户已是团队成员"); - } - - ContestTeamMember member = new ContestTeamMember(); - member.setTenantId(tenantId); - member.setTeamId(teamId); - member.setUserId(dto.getUserId()); - member.setRole(dto.getRole()); - - memberMapper.insert(member); - log.info("邀请成员成功,团队 ID={}, 用户 ID={}", teamId, dto.getUserId()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void removeMember(Long teamId, Long userId, Long tenantId) { - ContestTeamMember member = memberMapper.selectOne(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, teamId) - .eq(ContestTeamMember::getUserId, userId)); - - if (member == null) { - throw new BusinessException("成员不在该团队中"); - } - - // 队长不能移除 - if ("leader".equals(member.getRole())) { - throw new BusinessException("队长不能移除"); - } - - memberMapper.deleteById(member.getId()); - log.info("移除成员成功,团队 ID={}, 用户 ID={}", teamId, userId); - } - - @Override - public TeamVO getMyTeam(Long contestId, Long userId, Long tenantId) { - // 查询用户所在的团队 - List memberships = memberMapper.selectList(new LambdaQueryWrapper() - .eq(ContestTeamMember::getUserId, userId)); - - for (ContestTeamMember membership : memberships) { - ContestTeam team = teamMapper.selectById(membership.getTeamId()); - if (team != null && team.getContestId().equals(contestId) && team.getTenantId().equals(tenantId)) { - Contest contest = contestMapper.selectById(team.getContestId()); - return convertToVO(team, contest != null ? contest.getContestName() : null); - } - } - - return null; - } - - // ========== 转换方法 ========== - - private TeamVO convertToVO(ContestTeam team, String contestName) { - TeamVO vo = new TeamVO(); - vo.setId(team.getId()); - vo.setTenantId(team.getTenantId()); - vo.setContestId(team.getContestId()); - vo.setContestName(contestName); - vo.setTeamName(team.getTeamName()); - vo.setLeaderUserId(team.getLeaderUserId()); - vo.setMaxMembers(team.getMaxMembers()); - vo.setValidState(team.getValidState()); - vo.setCreateTime(team.getCreateTime()); - - // 获取队长姓名 - User leader = userMapper.selectById(team.getLeaderUserId()); - if (leader != null) { - vo.setLeaderName(leader.getNickname()); - } - - // 获取成员列表 - List members = memberMapper.selectList(new LambdaQueryWrapper() - .eq(ContestTeamMember::getTeamId, team.getId())); - - List memberVOs = new ArrayList<>(); - int currentCount = 0; - for (ContestTeamMember member : members) { - TeamMemberVO memberVO = new TeamMemberVO(); - memberVO.setId(member.getId()); - memberVO.setTeamId(team.getId()); - memberVO.setUserId(member.getUserId()); - memberVO.setRole(member.getRole()); - - User memberUser = userMapper.selectById(member.getUserId()); - if (memberUser != null) { - memberVO.setUserName(memberUser.getNickname()); - } - - memberVOs.add(memberVO); - - if ("leader".equals(member.getRole()) || "member".equals(member.getRole())) { - currentCount++; - } - } - vo.setCurrentMembers(currentCount); - vo.setMembers(memberVOs); - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestWorkServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestWorkServiceImpl.java deleted file mode 100644 index 03c9f53..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/ContestWorkServiceImpl.java +++ /dev/null @@ -1,395 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.common.enums.RegistrationStateEnum; -import com.lesingle.creation.dto.work.*; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.ContestWorkService; -import com.lesingle.creation.vo.work.WorkAttachmentVO; -import com.lesingle.creation.vo.work.WorkStatsVO; -import com.lesingle.creation.vo.work.WorkVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 竞赛作品服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class ContestWorkServiceImpl implements ContestWorkService { - - private final ContestWorkMapper workMapper; - private final ContestWorkAttachmentMapper attachmentMapper; - private final ContestRegistrationMapper registrationMapper; - private final ContestMapper contestMapper; - private final UserMapper userMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public WorkVO submit(SubmitWorkDTO dto, Long tenantId, Long submitterUserId) { - // 验证报名记录是否存在 - ContestRegistration registration = registrationMapper.selectById(dto.getRegistrationId()); - if (registration == null) { - throw new BusinessException("报名记录不存在"); - } - - if (!registration.getTenantId().equals(tenantId)) { - throw new BusinessException("报名记录不属于当前租户"); - } - - // 检查报名状态 - if (!RegistrationStateEnum.PASSED.getCode().equals(registration.getRegistrationState())) { - throw new BusinessException("报名未通过审核,无法提交作品"); - } - - // 检查提交时间 - Contest contest = contestMapper.selectById(registration.getContestId()); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(contest.getSubmitStartTime()) || now.isAfter(contest.getSubmitEndTime())) { - throw new BusinessException("不在作品提交时间范围内"); - } - - // 检查提交规则 - List existingWorks = workMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWork::getRegistrationId, dto.getRegistrationId()) - .eq(ContestWork::getValidState, 1) - .orderByDesc(ContestWork::getVersion)); - - if ("once".equals(contest.getSubmitRule()) && !existingWorks.isEmpty()) { - throw new BusinessException("该活动只允许提交一次作品"); - } - - // 如果已有作品,将旧版本标记为非最新 - if (!existingWorks.isEmpty()) { - LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() - .set(ContestWork::getIsLatest, false) - .eq(ContestWork::getRegistrationId, dto.getRegistrationId()) - .eq(ContestWork::getValidState, 1); - workMapper.update(null, updateWrapper); - } - - // 生成作品编号 - String workNo = generateWorkNo(registration.getContestId(), tenantId); - - // 获取提交人信息 - User submitter = userMapper.selectById(submitterUserId); - if (submitter == null) { - throw new BusinessException("提交人不存在"); - } - - // 创建新版本作品 - ContestWork work = new ContestWork(); - work.setTenantId(tenantId); - work.setContestId(registration.getContestId()); - work.setRegistrationId(dto.getRegistrationId()); - work.setWorkNo(workNo); - work.setTitle(dto.getTitle()); - work.setDescription(dto.getDescription()); - work.setFiles(dto.getFiles()); - work.setVersion(existingWorks.isEmpty() ? 1 : existingWorks.get(0).getVersion() + 1); - work.setIsLatest(true); - work.setStatus("submitted"); - work.setSubmitTime(LocalDateTime.now()); - work.setSubmitterUserId(submitterUserId); - work.setSubmitterAccountNo(submitter.getUsername()); - work.setSubmitSource("student"); - work.setPreviewUrl(dto.getPreviewUrl()); - work.setPreviewUrls(dto.getPreviewUrls()); - work.setAiModelMeta(dto.getAiModelMeta()); - work.setValidState(1); - work.setCreateBy(submitterUserId.toString()); - - workMapper.insert(work); - - // 创建附件记录 - if (dto.getAttachments() != null && !dto.getAttachments().isEmpty()) { - for (SubmitWorkDTO.AttachmentDTO attachment : dto.getAttachments()) { - ContestWorkAttachment workAttachment = new ContestWorkAttachment(); - workAttachment.setTenantId(tenantId); - workAttachment.setContestId(registration.getContestId()); - workAttachment.setWorkId(work.getId()); - workAttachment.setFileName(attachment.getFileName()); - workAttachment.setFileUrl(attachment.getFileUrl()); - workAttachment.setFileType(attachment.getFileType()); - workAttachment.setSize(attachment.getSize()); - workAttachment.setCreateBy(submitterUserId.toString()); - attachmentMapper.insert(workAttachment); - } - } - - log.info("提交作品成功,ID={}, 报名 ID={}", work.getId(), dto.getRegistrationId()); - - return convertToVO(work); - } - - @Override - public WorkStatsVO getStats(Long contestId) { - LambdaQueryWrapper baseWrapper = new LambdaQueryWrapper() - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true); - if (contestId != null) { - baseWrapper.eq(ContestWork::getContestId, contestId); - } - - long total = workMapper.selectCount(baseWrapper); - long submitted = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getStatus, "submitted") - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true) - .eq(contestId != null, ContestWork::getContestId, contestId)); - long reviewing = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getStatus, "reviewing") - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true) - .eq(contestId != null, ContestWork::getContestId, contestId)); - long returned = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getStatus, "returned") - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true) - .eq(contestId != null, ContestWork::getContestId, contestId)); - - WorkStatsVO vo = new WorkStatsVO(); - vo.setTotal((int) total); - vo.setSubmitted((int) submitted); - vo.setReviewing((int) reviewing); - vo.setReturned((int) returned); - return vo; - } - - @Override - public Page pageQuery(WorkQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(ContestWork::getTenantId, tenantId) - .eq(ContestWork::getValidState, 1) - .eq(queryDTO.getLatestOnly(), ContestWork::getIsLatest, true) - .eq(queryDTO.getContestId() != null, ContestWork::getContestId, queryDTO.getContestId()) - .eq(queryDTO.getRegistrationId() != null, ContestWork::getRegistrationId, queryDTO.getRegistrationId()) - .like(queryDTO.getTitleKeyword() != null, ContestWork::getTitle, queryDTO.getTitleKeyword()) - .eq(queryDTO.getSubmitterId() != null, ContestWork::getSubmitterUserId, queryDTO.getSubmitterId()) - .orderByDesc(ContestWork::getSubmitTime); - - Page resultPage = workMapper.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - return voPage; - } - - @Override - public WorkVO getDetail(Long id, Long tenantId) { - ContestWork work = workMapper.selectById(id); - if (work == null || !work.getTenantId().equals(tenantId)) { - throw new BusinessException("作品不存在"); - } - return convertToVO(work); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public WorkVO returnWork(Long id, Long tenantId, String reason) { - ContestWork work = workMapper.selectById(id); - if (work == null || !work.getTenantId().equals(tenantId)) { - throw new BusinessException("作品不存在"); - } - - work.setStatus("returned"); - // 这里可以将 reason 存储到某个字段,或者添加到 aiModelMeta 等 JSON 字段中 - work.setAiModelMeta(reason); // 简化处理 - - workMapper.updateById(work); - log.info("退回作品成功,ID={}, 原因={}", id, reason); - - return convertToVO(work); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - ContestWork work = workMapper.selectById(id); - if (work == null || !work.getTenantId().equals(tenantId)) { - throw new BusinessException("作品不存在"); - } - - work.setValidState(2); - workMapper.updateById(work); - - // 删除附件 - attachmentMapper.delete(new LambdaQueryWrapper() - .eq(ContestWorkAttachment::getWorkId, id) - .eq(ContestWorkAttachment::getDeleted, 0)); - - log.info("删除作品成功,ID={}", id); - } - - @Override - public List listByRegistration(Long registrationId, Long tenantId) { - List works = workMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWork::getTenantId, tenantId) - .eq(ContestWork::getRegistrationId, registrationId) - .eq(ContestWork::getValidState, 1) - .eq(ContestWork::getIsLatest, true) - .orderByDesc(ContestWork::getSubmitTime)); - - return works.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - public List getVersionsByRegistration(Long registrationId, Long tenantId) { - log.info("查询报名的所有作品版本,报名 ID: {}", registrationId); - - // 查询该报名下的所有作品版本(包括历史版本) - List works = workMapper.selectList(new LambdaQueryWrapper() - .eq(ContestWork::getTenantId, tenantId) - .eq(ContestWork::getRegistrationId, registrationId) - .eq(ContestWork::getValidState, 1) - .orderByDesc(ContestWork::getVersion)); - - return works.stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - } - - @Override - public Page getGuidedWorks(WorkQueryDTO queryDTO, Long userId, Long tenantId) { - log.info("查询教师指导的作品列表,教师 ID: {}", userId); - - // 查询教师指导的报名记录 ID 列表 - // 注:这里假设报名表中有一个指导老师的字段,或者有一个单独的报名表 - 老师关联表 - // 简化处理:假设通过某种方式可以获取到教师指导的报名 ID 列表 - // 实际需要查询 ContestRegistrationTeacher 关联表 - - // 查询该教师指导的所有报名记录 - List registrations = registrationMapper.selectList( - new LambdaQueryWrapper() - .eq(ContestRegistration::getValidState, 1) - .like(ContestRegistration::getTeacherIds, userId != null ? userId.toString() : "") - ); - - List registrationIds = registrations.stream() - .map(ContestRegistration::getId) - .collect(Collectors.toList()); - - if (registrationIds.isEmpty()) { - return new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - } - - // 分页查询作品 - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(ContestWork::getTenantId, tenantId) - .eq(ContestWork::getValidState, 1) - .eq(queryDTO.getLatestOnly(), ContestWork::getIsLatest, true) - .in(ContestWork::getRegistrationId, registrationIds) - .eq(queryDTO.getContestId() != null, ContestWork::getContestId, queryDTO.getContestId()) - .like(queryDTO.getTitleKeyword() != null, ContestWork::getTitle, queryDTO.getTitleKeyword()) - .orderByDesc(ContestWork::getSubmitTime); - - Page resultPage = workMapper.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - return voPage; - } - - // ========== 辅助方法 ========== - - /** - * 生成作品编号 - */ - private String generateWorkNo(Long contestId, Long tenantId) { - String prefix = "WORK-" + contestId + "-" + tenantId + "-"; - long count = workMapper.selectCount(new LambdaQueryWrapper() - .eq(ContestWork::getContestId, contestId) - .eq(ContestWork::getTenantId, tenantId)); - return prefix + String.format("%06d", count + 1); - } - - // ========== 转换方法 ========== - - private WorkVO convertToVO(ContestWork work) { - WorkVO vo = new WorkVO(); - vo.setId(work.getId()); - vo.setTenantId(work.getTenantId()); - vo.setContestId(work.getContestId()); - vo.setRegistrationId(work.getRegistrationId()); - vo.setWorkNo(work.getWorkNo()); - vo.setTitle(work.getTitle()); - vo.setDescription(work.getDescription()); - vo.setFiles(work.getFiles()); - vo.setVersion(work.getVersion()); - vo.setIsLatest(work.getIsLatest()); - vo.setStatus(work.getStatus()); - vo.setSubmitTime(work.getSubmitTime()); - vo.setSubmitterUserId(work.getSubmitterUserId()); - vo.setSubmitterAccountNo(work.getSubmitterAccountNo()); - vo.setSubmitSource(work.getSubmitSource()); - vo.setPreviewUrl(work.getPreviewUrl()); - vo.setPreviewUrls(work.getPreviewUrls()); - vo.setAiModelMeta(work.getAiModelMeta()); - vo.setValidState(work.getValidState()); - - // 获取活动名称 - Contest contest = contestMapper.selectById(work.getContestId()); - if (contest != null) { - vo.setContestName(contest.getContestName()); - } - - // 获取附件列表 - List attachments = attachmentMapper.selectList( - new LambdaQueryWrapper() - .eq(ContestWorkAttachment::getWorkId, work.getId()) - .eq(ContestWorkAttachment::getDeleted, 0)); - List attachmentVOs = attachments.stream() - .map(this::convertToAttachmentVO) - .collect(Collectors.toList()); - vo.setAttachments(attachmentVOs); - - // 获取参赛者信息 - ContestRegistration registration = registrationMapper.selectById(work.getRegistrationId()); - if (registration != null) { - vo.setParticipantName(registration.getAccountName()); - vo.setParticipantType("team".equals(registration.getRegistrationType()) ? "team" : "personal"); - } - - return vo; - } - - private WorkAttachmentVO convertToAttachmentVO(ContestWorkAttachment attachment) { - WorkAttachmentVO vo = new WorkAttachmentVO(); - vo.setId(attachment.getId()); - vo.setFileName(attachment.getFileName()); - vo.setFileUrl(attachment.getFileUrl()); - vo.setFileType(attachment.getFileType()); - vo.setSize(attachment.getSize()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java deleted file mode 100644 index 8d53040..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/DepartmentServiceImpl.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.dto.department.CreateDepartmentDTO; -import com.lesingle.creation.dto.department.UpdateDepartmentDTO; -import com.lesingle.creation.entity.Department; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.DepartmentMapper; -import com.lesingle.creation.service.DepartmentService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.department.DepartmentVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 部门服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class DepartmentServiceImpl extends ServiceImpl implements DepartmentService { - - private final DepartmentMapper departmentMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public DepartmentVO create(CreateDepartmentDTO dto, Long tenantId, Long creatorId) { - // 检查部门编码是否已存在 - Department existing = departmentMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null) { - throw new BusinessException("部门编码已存在"); - } - - Department department = new Department(); - department.setTenantId(tenantId); - department.setName(dto.getName()); - department.setCode(dto.getCode()); - department.setParentId(dto.getParentId()); - department.setDescription(dto.getDescription()); - department.setSort(dto.getSort() != null ? dto.getSort() : 0); - department.setValidState(1); - - departmentMapper.insert(department); - log.info("创建部门成功,ID={}, 名称={}", department.getId(), dto.getName()); - - return convertToVO(department); - } - - @Override - public List list(Long tenantId, Long parentId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Department::getTenantId, tenantId) - .eq(Department::getDeleted, 0) - .eq(parentId != null, Department::getParentId, parentId) - .orderByAsc(Department::getSort); - - List departments = this.list(wrapper); - return departments.stream().map(this::convertToVO).collect(Collectors.toList()); - } - - @Override - public List tree(Long tenantId) { - // 查询所有顶级部门(parentId 为 null 或 0) - List allDepartments = this.list(new LambdaQueryWrapper() - .eq(Department::getTenantId, tenantId) - .eq(Department::getDeleted, 0) - .orderByAsc(Department::getSort)); - - // 构建树形结构 - return buildDepartmentTree(allDepartments, null); - } - - @Override - public DepartmentVO getDetail(Long id, Long tenantId) { - Department department = this.getById(id); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - return convertToVO(department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public DepartmentVO update(Long id, UpdateDepartmentDTO dto, Long tenantId, Long modifierId) { - Department department = this.getById(id); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - - if (dto.getCode() != null) { - // 检查新编码是否已被其他部门使用 - Department existing = departmentMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null && !existing.getId().equals(id)) { - throw new BusinessException("部门编码已存在"); - } - department.setCode(dto.getCode()); - } - if (dto.getName() != null) { - department.setName(dto.getName()); - } - if (dto.getParentId() != null) { - // 不能将自己设置为父部门 - if (dto.getParentId().equals(id)) { - throw new BusinessException("不能将自己设置为父部门"); - } - department.setParentId(dto.getParentId()); - } - if (dto.getDescription() != null) { - department.setDescription(dto.getDescription()); - } - if (dto.getSort() != null) { - department.setSort(dto.getSort()); - } - if (dto.getValidState() != null) { - department.setValidState(dto.getValidState()); - } - - this.updateById(department); - log.info("更新部门成功,ID={}", id); - - return convertToVO(department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Department department = this.getById(id); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - - // 检查是否有子部门 - Long childCount = this.count(new LambdaQueryWrapper() - .eq(Department::getParentId, id) - .eq(Department::getDeleted, 0)); - if (childCount > 0) { - throw new BusinessException("存在子部门,无法删除"); - } - - department.setDeleted(1); - this.updateById(department); - log.info("删除部门成功,ID={}", id); - } - - private DepartmentVO convertToVO(Department department) { - DepartmentVO vo = new DepartmentVO(); - vo.setId(department.getId()); - vo.setTenantId(department.getTenantId()); - vo.setName(department.getName()); - vo.setCode(department.getCode()); - vo.setParentId(department.getParentId()); - vo.setDescription(department.getDescription()); - vo.setSort(department.getSort()); - vo.setValidState(department.getValidState()); - vo.setCreateTime(department.getCreateTime()); - vo.setUpdateTime(department.getUpdateTime()); - return vo; - } - - private List buildDepartmentTree(List allDepartments, Long parentId) { - List tree = allDepartments.stream() - .filter(dept -> { - if (parentId == null) { - return dept.getParentId() == null || dept.getParentId() == 0; - } - return parentId.equals(dept.getParentId()); - }) - .map(this::convertToVO) - .sorted(Comparator.comparing(DepartmentVO::getSort)) - .collect(Collectors.toList()); - - // 递归构建子部门 - for (DepartmentVO node : tree) { - List children = buildDepartmentTree(allDepartments, node.getId()); - if (!children.isEmpty()) { - node.setChildren(children); - } - } - - return tree; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/DictServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/DictServiceImpl.java deleted file mode 100644 index d2e3e54..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/DictServiceImpl.java +++ /dev/null @@ -1,268 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.dict.CreateDictDTO; -import com.lesingle.creation.dto.dict.UpdateDictDTO; -import com.lesingle.creation.entity.Dict; -import com.lesingle.creation.entity.DictItem; -import com.lesingle.creation.mapper.DictMapper; -import com.lesingle.creation.mapper.DictItemMapper; -import com.lesingle.creation.service.DictService; -import com.lesingle.creation.vo.dict.DictDetailVO; -import com.lesingle.creation.vo.dict.DictItemVO; -import com.lesingle.creation.vo.dict.DictListVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 字典服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class DictServiceImpl extends ServiceImpl implements DictService { - - private final DictMapper dictMapper; - private final DictItemMapper dictItemMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public DictDetailVO create(CreateDictDTO dto, Long tenantId, Long operatorId) { - log.info("开始创建字典,字典编码:{}", dto.getCode()); - - // 检查字典编码是否已存在 - Dict existingDict = dictMapper.selectByCode(tenantId, dto.getCode()); - if (existingDict != null) { - throw new BusinessException("字典编码已存在"); - } - - // 创建字典 - Dict dict = new Dict(); - dict.setTenantId(tenantId); - dict.setName(dto.getName()); - dict.setCode(dto.getCode()); - dict.setDescription(dto.getDescription()); - dict.setValidState(1); - dict.setCreateBy(String.valueOf(operatorId)); - - dictMapper.insert(dict); - log.info("字典创建成功,字典 ID: {}", dict.getId()); - - // 如果提供了字典项,创建字典项 - if (!CollectionUtils.isEmpty(dto.getItems())) { - List dictItems = dto.getItems().stream() - .map(itemDTO -> { - DictItem item = new DictItem(); - item.setDictId(dict.getId()); - item.setLabel(itemDTO.getLabel()); - item.setValue(itemDTO.getValue()); - item.setSort(itemDTO.getSort() != null ? itemDTO.getSort() : 0); - item.setValidState(1); - return item; - }) - .collect(Collectors.toList()); - dictItemMapper.insertBatch(dictItems); - log.info("字典项创建成功,字典项数量:{}", dto.getItems().size()); - } - - return convertToDetailVO(dict); - } - - @Override - public Page pageList(Long tenantId, int page, int pageSize) { - log.info("分页查询字典列表,租户 ID: {}, 页码:{}, 每页大小:{}", tenantId, page, pageSize); - - Page dictPage = new Page<>(page, pageSize); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Dict::getTenantId, tenantId) - .eq(Dict::getValidState, 1) - .orderByDesc(Dict::getCreateTime); - - Page resultPage = dictMapper.selectPage(dictPage, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public DictDetailVO getByCode(String code, Long tenantId) { - log.info("根据编码查询字典,编码:{}, 租户 ID: {}", code, tenantId); - - Dict dict = dictMapper.selectByCode(tenantId, code); - if (dict == null) { - throw new BusinessException("字典不存在"); - } - - return convertToDetailVO(dict); - } - - @Override - public DictDetailVO detail(Long id, Long tenantId) { - log.info("查询字典详情,字典 ID: {}", id); - - Dict dict = dictMapper.selectById(id); - if (dict == null) { - throw new BusinessException("字典不存在"); - } - - return convertToDetailVO(dict); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public DictDetailVO update(Long id, UpdateDictDTO dto, Long tenantId) { - log.info("更新字典,字典 ID: {}", id); - - Dict existingDict = dictMapper.selectById(id); - if (existingDict == null) { - throw new BusinessException("字典不存在"); - } - - // 如果更新了 code,检查是否冲突 - if (StringUtils.hasText(dto.getCode())) { - Dict conflictDict = dictMapper.selectByCodeExclude(tenantId, dto.getCode(), id); - if (conflictDict != null) { - throw new BusinessException("字典编码已存在"); - } - } - - // 更新字典信息 - Dict dict = new Dict(); - dict.setId(id); - dict.setName(dto.getName()); - dict.setCode(dto.getCode()); - dict.setDescription(dto.getDescription()); - - dictMapper.updateById(dict); - log.info("字典更新成功,字典 ID: {}", id); - - // 如果提供了字典项,更新字典项 - if (dto.getItems() != null) { - // 先删除现有字典项 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(DictItem::getDictId, id); - dictItemMapper.delete(wrapper); - log.info("已删除字典原有字典项"); - - // 创建新的字典项 - if (!dto.getItems().isEmpty()) { - List dictItems = dto.getItems().stream() - .map(itemDTO -> { - DictItem item = new DictItem(); - item.setDictId(id); - if (itemDTO.getId() != null) { - item.setId(itemDTO.getId()); - } - item.setLabel(itemDTO.getLabel()); - item.setValue(itemDTO.getValue()); - item.setSort(itemDTO.getSort() != null ? itemDTO.getSort() : 0); - item.setValidState(1); - return item; - }) - .collect(Collectors.toList()); - dictItemMapper.insertBatch(dictItems); - log.info("字典新字典项创建成功,字典项数量:{}", dto.getItems().size()); - } - } - - return convertToDetailVO(dictMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - log.info("删除字典,字典 ID: {}", id); - - Dict dict = dictMapper.selectById(id); - if (dict == null) { - throw new BusinessException("字典不存在"); - } - - // 删除字典项 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(DictItem::getDictId, id); - dictItemMapper.delete(wrapper); - log.info("字典项删除成功"); - - // 删除字典(逻辑删除) - dictMapper.deleteById(id); - log.info("字典删除成功,字典 ID: {}", id); - } - - /** - * 转换为详情 VO - */ - private DictDetailVO convertToDetailVO(Dict dict) { - DictDetailVO vo = new DictDetailVO(); - vo.setId(dict.getId()); - vo.setTenantId(dict.getTenantId()); - vo.setName(dict.getName()); - vo.setCode(dict.getCode()); - vo.setDescription(dict.getDescription()); - vo.setValidState(dict.getValidState()); - vo.setCreateBy(dict.getCreateBy()); - vo.setCreateTime(dict.getCreateTime()); - vo.setUpdateBy(dict.getUpdateBy()); - vo.setUpdateTime(dict.getUpdateTime()); - - // 获取字典项 - List items = dictItemMapper.selectByDictId(dict.getId()); - if (!CollectionUtils.isEmpty(items)) { - List itemVOs = items.stream() - .sorted(Comparator.comparingInt(DictItem::getSort)) - .map(this::convertItemToVO) - .collect(Collectors.toList()); - vo.setItems(itemVOs); - } - - return vo; - } - - /** - * 转换为列表 VO - */ - private DictListVO convertToListVO(Dict dict) { - DictListVO vo = new DictListVO(); - vo.setId(dict.getId()); - vo.setTenantId(dict.getTenantId()); - vo.setName(dict.getName()); - vo.setCode(dict.getCode()); - vo.setDescription(dict.getDescription()); - vo.setValidState(dict.getValidState()); - vo.setCreateTime(dict.getCreateTime()); - return vo; - } - - /** - * 转换为字典项 VO - */ - private DictItemVO convertItemToVO(DictItem item) { - DictItemVO vo = new DictItemVO(); - vo.setId(item.getId()); - vo.setDictId(item.getDictId()); - vo.setLabel(item.getLabel()); - vo.setValue(item.getValue()); - vo.setSort(item.getSort()); - vo.setValidState(item.getValidState()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java deleted file mode 100644 index 39fe952..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/GradeServiceImpl.java +++ /dev/null @@ -1,152 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.grade.CreateGradeDTO; -import com.lesingle.creation.dto.grade.UpdateGradeDTO; -import com.lesingle.creation.entity.Grade; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.GradeMapper; -import com.lesingle.creation.service.GradeService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.grade.GradeVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 年级服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class GradeServiceImpl extends ServiceImpl implements GradeService { - - private final GradeMapper gradeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public GradeVO create(CreateGradeDTO dto, Long tenantId, Long creatorId) { - // 检查年级编码是否已存在 - Grade existing = gradeMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null) { - throw new BusinessException("年级编码已存在"); - } - - // 检查年级级别是否已存在 - Grade existingByLevel = this.getOne(new LambdaQueryWrapper() - .eq(Grade::getTenantId, tenantId) - .eq(Grade::getLevel, dto.getLevel()) - .eq(Grade::getDeleted, 0)); - if (existingByLevel != null) { - throw new BusinessException("年级级别已存在"); - } - - Grade grade = new Grade(); - grade.setTenantId(tenantId); - grade.setName(dto.getName()); - grade.setCode(dto.getCode()); - grade.setLevel(dto.getLevel()); - grade.setDescription(dto.getDescription()); - grade.setValidState(1); - - gradeMapper.insert(grade); - log.info("创建年级成功,ID={}, 名称={}", grade.getId(), dto.getName()); - - return convertToVO(grade); - } - - @Override - public Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId) { - Page page = new Page<>(pageNum, pageSize); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Grade::getTenantId, tenantId) - .eq(Grade::getDeleted, 0) - .orderByAsc(Grade::getLevel); - - Page resultPage = this.page(page, wrapper); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(resultPage.getRecords().stream().map(this::convertToVO).toList()); - return voPage; - } - - @Override - public GradeVO getDetail(Long id, Long tenantId) { - Grade grade = this.getById(id); - if (grade == null || !grade.getTenantId().equals(tenantId)) { - throw new BusinessException("年级不存在"); - } - return convertToVO(grade); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public GradeVO update(Long id, UpdateGradeDTO dto, Long tenantId, Long modifierId) { - Grade grade = this.getById(id); - if (grade == null || !grade.getTenantId().equals(tenantId)) { - throw new BusinessException("年级不存在"); - } - - if (dto.getName() != null) { - grade.setName(dto.getName()); - } - if (dto.getCode() != null) { - // 检查新编码是否已被其他年级使用 - Grade existing = gradeMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null && !existing.getId().equals(id)) { - throw new BusinessException("年级编码已存在"); - } - grade.setCode(dto.getCode()); - } - if (dto.getLevel() != null) { - // 检查新级别是否已被其他年级使用 - Grade existing = this.getOne(new LambdaQueryWrapper() - .eq(Grade::getTenantId, tenantId) - .eq(Grade::getLevel, dto.getLevel()) - .eq(Grade::getDeleted, 0) - .ne(Grade::getId, id)); - if (existing != null) { - throw new BusinessException("年级级别已存在"); - } - grade.setLevel(dto.getLevel()); - } - if (dto.getDescription() != null) { - grade.setDescription(dto.getDescription()); - } - - this.updateById(grade); - log.info("更新年级成功,ID={}", id); - - return convertToVO(grade); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Grade grade = this.getById(id); - if (grade == null || !grade.getTenantId().equals(tenantId)) { - throw new BusinessException("年级不存在"); - } - - grade.setDeleted(1); - this.updateById(grade); - log.info("删除年级成功,ID={}", id); - } - - private GradeVO convertToVO(Grade grade) { - GradeVO vo = new GradeVO(); - vo.setId(grade.getId()); - vo.setTenantId(grade.getTenantId()); - vo.setName(grade.getName()); - vo.setCode(grade.getCode()); - vo.setLevel(grade.getLevel()); - vo.setDescription(grade.getDescription()); - vo.setValidState(grade.getValidState()); - vo.setCreateTime(grade.getCreateTime()); - vo.setUpdateTime(grade.getUpdateTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java deleted file mode 100644 index 9a2f68b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/HomeworkServiceImpl.java +++ /dev/null @@ -1,633 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.lesingle.creation.common.enums.ValidStateEnum; -import com.lesingle.creation.dto.homework.*; -import com.lesingle.creation.entity.Homework; -import com.lesingle.creation.entity.HomeworkReviewDimension; -import com.lesingle.creation.entity.HomeworkReviewRule; -import com.lesingle.creation.entity.HomeworkSubmission; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.HomeworkMapper; -import com.lesingle.creation.mapper.HomeworkReviewDimensionMapper; -import com.lesingle.creation.mapper.HomeworkReviewRuleMapper; -import com.lesingle.creation.mapper.HomeworkSubmissionMapper; -import com.lesingle.creation.service.HomeworkService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.homework.HomeworkDetailVO; -import com.lesingle.creation.vo.homework.HomeworkListVO; -import com.lesingle.creation.vo.homework.ReviewDimensionVO; -import com.lesingle.creation.vo.homework.ReviewRuleVO; -import com.lesingle.creation.vo.homework.SubmissionVO; -import com.lesingle.creation.vo.school.ClassTreeNodeVO; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 作业服务实现类 - */ -@Slf4j -@Service -public class HomeworkServiceImpl extends ServiceImpl - implements HomeworkService { - - private final HomeworkSubmissionMapper homeworkSubmissionMapper; - private final HomeworkReviewRuleMapper homeworkReviewRuleMapper; - private final HomeworkReviewDimensionMapper homeworkReviewDimensionMapper; - - public HomeworkServiceImpl(HomeworkSubmissionMapper homeworkSubmissionMapper, - HomeworkReviewRuleMapper homeworkReviewRuleMapper, - HomeworkReviewDimensionMapper homeworkReviewDimensionMapper) { - this.homeworkSubmissionMapper = homeworkSubmissionMapper; - this.homeworkReviewRuleMapper = homeworkReviewRuleMapper; - this.homeworkReviewDimensionMapper = homeworkReviewDimensionMapper; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO create(CreateHomeworkDTO dto, Long tenantId, Long creatorId) { - // 验证时间顺序 - if (dto.getSubmitStartTime().isAfter(dto.getSubmitEndTime())) { - throw new BusinessException("提交开始时间不能晚于结束时间"); - } - - // 检查作业名称是否已存在 - Homework existing = this.getOne(new LambdaQueryWrapper() - .eq(Homework::getTenantId, tenantId) - .eq(Homework::getName, dto.getName()) - .eq(Homework::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("作业名称已存在"); - } - - // 创建作业 - Homework homework = new Homework(); - homework.setTenantId(tenantId); - homework.setName(dto.getName()); - homework.setContent(dto.getContent()); - homework.setStatus("unpublished"); - homework.setSubmitStartTime(dto.getSubmitStartTime()); - homework.setSubmitEndTime(dto.getSubmitEndTime()); - homework.setAttachments(dto.getAttachments()); - homework.setPublishScope(dto.getPublishScope()); - homework.setReviewRuleId(dto.getReviewRuleId()); - homework.setValidState(ValidStateEnum.VALID.getCode()); - - this.save(homework); - log.info("创建作业成功,ID={}, 名称={}", homework.getId(), dto.getName()); - - return convertToDetailVO(homework); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO update(Long id, UpdateHomeworkDTO dto, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - // 已发布的作业不能修改 - if ("published".equals(homework.getStatus())) { - throw new BusinessException("已发布的作业不能修改"); - } - - homework.setName(dto.getName()); - homework.setContent(dto.getContent()); - if (dto.getSubmitStartTime() != null) { - homework.setSubmitStartTime(dto.getSubmitStartTime()); - } - if (dto.getSubmitEndTime() != null) { - homework.setSubmitEndTime(dto.getSubmitEndTime()); - } - homework.setAttachments(dto.getAttachments()); - homework.setPublishScope(dto.getPublishScope()); - if (dto.getReviewRuleId() != null) { - homework.setReviewRuleId(dto.getReviewRuleId()); - } - - this.updateById(homework); - log.info("更新作业成功,ID={}", id); - - return convertToDetailVO(homework); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO publish(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - homework.setStatus("published"); - homework.setPublishTime(LocalDateTime.now()); - this.updateById(homework); - log.info("发布作业成功,ID={}", id); - - return convertToDetailVO(homework); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - this.removeById(id); - log.info("删除作业成功,ID={}", id); - } - - @Override - public HomeworkDetailVO getDetail(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - return convertToDetailVO(homework); - } - - @Override - public Page pageQuery(HomeworkQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Homework::getTenantId, tenantId) - .eq(Homework::getDeleted, 0) - .like(queryDTO.getNameKeyword() != null, Homework::getName, queryDTO.getNameKeyword()) - .eq(queryDTO.getStatus() != null, Homework::getStatus, queryDTO.getStatus()) - .eq(queryDTO.getValidState() != null, Homework::getValidState, queryDTO.getValidState()) - .orderByDesc(Homework::getCreateTime); - - Page resultPage = this.page(page, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SubmissionVO submit(SubmitHomeworkDTO dto, Long tenantId, Long studentId) { - Homework homework = this.getById(dto.getHomeworkId()); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - // 检查是否已提交 - HomeworkSubmission existing = homeworkSubmissionMapper.selectOne(new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, dto.getHomeworkId()) - .eq(HomeworkSubmission::getStudentId, studentId) - .eq(HomeworkSubmission::getDeleted, 0)); - if (existing != null) { - throw new BusinessException("您已经提交过该作业"); - } - - // 检查提交时间 - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(homework.getSubmitStartTime())) { - throw new BusinessException("还未到提交开始时间"); - } - if (now.isAfter(homework.getSubmitEndTime())) { - throw new BusinessException("已错过提交截止时间"); - } - - HomeworkSubmission submission = new HomeworkSubmission(); - submission.setTenantId(tenantId); - submission.setHomeworkId(dto.getHomeworkId()); - submission.setStudentId(studentId); - submission.setContent(dto.getContent()); - submission.setAttachments(dto.getAttachments()); - submission.setStatus("submitted"); - submission.setSubmitTime(LocalDateTime.now()); - - homeworkSubmissionMapper.insert(submission); - log.info("提交作业成功,ID={}, 学生 ID={}", submission.getId(), studentId); - - return convertToSubmissionVO(submission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SubmissionVO review(ReviewHomeworkDTO dto, Long tenantId, Long reviewerId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(dto.getSubmissionId()); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - submission.setReviewerId(reviewerId); - submission.setReviewComment(dto.getComment()); - submission.setReviewScore(dto.getScore()); - submission.setReviewTime(LocalDateTime.now()); - submission.setStatus("reviewing"); - - homeworkSubmissionMapper.updateById(submission); - log.info("批改作业成功,提交 ID={}, 分数={}", dto.getSubmissionId(), dto.getScore()); - - return convertToSubmissionVO(submission); - } - - @Override - public List getSubmissions(Long homeworkId, Long tenantId) { - List submissions = homeworkSubmissionMapper.selectList( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homeworkId) - .eq(HomeworkSubmission::getTenantId, tenantId) - .eq(HomeworkSubmission::getDeleted, 0) - .orderByDesc(HomeworkSubmission::getSubmitTime) - ); - - return submissions.stream() - .map(this::convertToSubmissionVO) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ReviewRuleVO createReviewRule(String ruleName, String ruleType, - java.math.BigDecimal totalScore, String description, Long tenantId) { - HomeworkReviewRule rule = new HomeworkReviewRule(); - rule.setTenantId(tenantId); - rule.setRuleName(ruleName); - rule.setRuleType(ruleType); - rule.setTotalScore(totalScore); - rule.setDescription(description); - - homeworkReviewRuleMapper.insert(rule); - log.info("创建评审规则成功,ID={}", rule.getId()); - - return convertToReviewRuleVO(rule); - } - - @Override - public List getReviewRules(Long tenantId) { - List rules = homeworkReviewRuleMapper.selectList( - new LambdaQueryWrapper() - .eq(HomeworkReviewRule::getTenantId, tenantId) - .eq(HomeworkReviewRule::getDeleted, 0) - .orderByDesc(HomeworkReviewRule::getCreateTime) - ); - - return rules.stream() - .map(this::convertToReviewRuleVO) - .collect(Collectors.toList()); - } - - // ========== 转换方法 ========== - - private HomeworkDetailVO convertToDetailVO(Homework homework) { - HomeworkDetailVO vo = new HomeworkDetailVO(); - vo.setId(homework.getId()); - vo.setName(homework.getName()); - vo.setContent(homework.getContent()); - vo.setStatus(homework.getStatus()); - vo.setPublishTime(homework.getPublishTime()); - vo.setSubmitStartTime(homework.getSubmitStartTime()); - vo.setSubmitEndTime(homework.getSubmitEndTime()); - vo.setAttachments(homework.getAttachments()); - vo.setPublishScope(homework.getPublishScope()); - vo.setReviewRuleId(homework.getReviewRuleId()); - vo.setCreateTime(homework.getCreateTime()); - - // 统计提交人数和批改人数 - Long submissionCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getDeleted, 0) - ); - Long reviewedCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getStatus, "reviewing") - .eq(HomeworkSubmission::getDeleted, 0) - ); - vo.setSubmissionCount(submissionCount.intValue()); - vo.setReviewedCount(reviewedCount.intValue()); - - return vo; - } - - private HomeworkListVO convertToListVO(Homework homework) { - HomeworkListVO vo = new HomeworkListVO(); - vo.setId(homework.getId()); - vo.setName(homework.getName()); - vo.setStatus(homework.getStatus()); - vo.setPublishTime(homework.getPublishTime()); - vo.setSubmitStartTime(homework.getSubmitStartTime()); - vo.setSubmitEndTime(homework.getSubmitEndTime()); - vo.setCreateTime(homework.getCreateTime()); - - // 统计提交人数和批改人数 - Long submissionCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getDeleted, 0) - ); - Long reviewedCount = homeworkSubmissionMapper.selectCount( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getHomeworkId, homework.getId()) - .eq(HomeworkSubmission::getStatus, "reviewing") - .eq(HomeworkSubmission::getDeleted, 0) - ); - vo.setSubmissionCount(submissionCount.intValue()); - vo.setReviewedCount(reviewedCount.intValue()); - - return vo; - } - - private SubmissionVO convertToSubmissionVO(HomeworkSubmission submission) { - SubmissionVO vo = new SubmissionVO(); - vo.setId(submission.getId()); - vo.setHomeworkId(submission.getHomeworkId()); - vo.setStudentId(submission.getStudentId()); - vo.setStudentName(submission.getStudentName()); - vo.setContent(submission.getContent()); - vo.setAttachments(submission.getAttachments()); - vo.setStatus(submission.getStatus()); - vo.setSubmitTime(submission.getSubmitTime()); - vo.setReviewTime(submission.getReviewTime()); - vo.setReviewerId(submission.getReviewerId()); - vo.setReviewComment(submission.getReviewComment()); - vo.setReviewScore(submission.getReviewScore()); - return vo; - } - - private ReviewRuleVO convertToReviewRuleVO(HomeworkReviewRule rule) { - ReviewRuleVO vo = new ReviewRuleVO(); - vo.setId(rule.getId()); - vo.setRuleName(rule.getRuleName()); - vo.setRuleType(rule.getRuleType()); - vo.setTotalScore(rule.getTotalScore()); - vo.setDescription(rule.getDescription()); - - // 查询关联的维度列表 - List dimensions = homeworkReviewDimensionMapper.selectByRuleId(rule.getId()); - if (dimensions != null && !dimensions.isEmpty()) { - vo.setDimensions(dimensions.stream().map(this::convertToReviewDimensionVO).collect(Collectors.toList())); - } - - return vo; - } - - private ReviewDimensionVO convertToReviewDimensionVO(HomeworkReviewDimension dimension) { - ReviewDimensionVO vo = new ReviewDimensionVO(); - vo.setId(dimension.getId()); - vo.setName(dimension.getName()); - vo.setMaxScore(dimension.getMaxScore()); - vo.setDescription(dimension.getDescription()); - vo.setSortOrder(dimension.getSortOrder()); - return vo; - } - - // ========== 新增方法实现 ========== - - @Override - public List getReviewRulesForSelect(Long tenantId) { - // 获取所有有效的评审规则,用于下拉选择 - List rules = homeworkReviewRuleMapper.selectList( - new LambdaQueryWrapper() - .eq(HomeworkReviewRule::getTenantId, tenantId) - .eq(HomeworkReviewRule::getDeleted, 0) - .orderByDesc(HomeworkReviewRule::getCreateTime) - ); - return rules.stream() - .map(this::convertToReviewRuleVO) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ReviewRuleVO updateReviewRule(Long id, UpdateReviewRuleDTO dto, Long tenantId) { - HomeworkReviewRule rule = homeworkReviewRuleMapper.selectById(id); - if (rule == null || !rule.getTenantId().equals(tenantId)) { - throw new BusinessException("评审规则不存在"); - } - - if (dto.getRuleName() != null) { - rule.setRuleName(dto.getRuleName()); - } - if (dto.getDescription() != null) { - rule.setDescription(dto.getDescription()); - } - // 注意:维度列表需要单独处理 - if (dto.getDimensions() != null && !dto.getDimensions().isEmpty()) { - // 删除原有维度 - homeworkReviewDimensionMapper.deleteByRuleId(id); - // 插入新维度 - int sortOrder = 0; - for (ReviewDimensionDTO dim : dto.getDimensions()) { - HomeworkReviewDimension dimension = new HomeworkReviewDimension(); - dimension.setRuleId(id); - dimension.setTenantId(tenantId); - dimension.setName(dim.getName()); - dimension.setMaxScore(dim.getMaxScore()); - dimension.setDescription(dim.getDescription()); - dimension.setSortOrder(sortOrder++); - homeworkReviewDimensionMapper.insert(dimension); - } - } - - homeworkReviewRuleMapper.updateById(rule); - log.info("更新评审规则成功,ID={}", id); - - return convertToReviewRuleVO(rule); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteReviewRule(Long id, Long tenantId) { - HomeworkReviewRule rule = homeworkReviewRuleMapper.selectById(id); - if (rule == null || !rule.getTenantId().equals(tenantId)) { - throw new BusinessException("评审规则不存在"); - } - - // 删除关联的维度 - homeworkReviewDimensionMapper.deleteByRuleId(id); - // 逻辑删除规则 - rule.setDeleted(1); - homeworkReviewRuleMapper.updateById(rule); - log.info("删除评审规则成功,ID={}", id); - } - - @Override - public Page getMyHomeworks(HomeworkQueryDTO queryDTO, Long userId, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - // TODO: 需要根据用户 ID 查询关联的班级/年级,进而查询作业 - // 这里简化处理:查询所有已发布的作业 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Homework::getTenantId, tenantId) - .eq(Homework::getDeleted, 0) - .eq(Homework::getStatus, "published") - .like(queryDTO.getNameKeyword() != null, Homework::getName, queryDTO.getNameKeyword()) - .orderByDesc(Homework::getCreateTime); - - Page resultPage = this.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public HomeworkDetailVO unpublish(Long id, Long tenantId) { - Homework homework = this.getById(id); - if (homework == null || !homework.getTenantId().equals(tenantId)) { - throw new BusinessException("作业不存在"); - } - - homework.setStatus("unpublished"); - this.updateById(homework); - log.info("撤销发布作业成功,ID={}", id); - - return convertToDetailVO(homework); - } - - @Override - public Page getSubmissionsList(SubmissionQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(HomeworkSubmission::getTenantId, tenantId) - .eq(HomeworkSubmission::getDeleted, 0) - .eq(queryDTO.getHomeworkId() != null, HomeworkSubmission::getHomeworkId, queryDTO.getHomeworkId()) - .like(queryDTO.getStudentName() != null, HomeworkSubmission::getStudentName, queryDTO.getStudentName()) - .eq(queryDTO.getStatus() != null, HomeworkSubmission::getStatus, queryDTO.getStatus()) - .orderByDesc(HomeworkSubmission::getSubmitTime); - - Page resultPage = homeworkSubmissionMapper.selectPage(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToSubmissionVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>( - resultPage.getCurrent(), - resultPage.getSize(), - resultPage.getTotal() - ); - voPage.setRecords(voList); - return voPage; - } - - @Override - public SubmissionVO getSubmissionDetail(Long id, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(id); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - return convertToSubmissionVO(submission); - } - - @Override - public List getClassTree(Long tenantId) { - // TODO: 需要实现班级树查询逻辑 - // 这里返回空列表,后续需要根据实际的班级/年级表实现 - log.warn("getClassTree 方法暂未实现,tenantId={}", tenantId); - return List.of(); - } - - @Override - public SubmissionVO getMySubmission(Long homeworkId, Long userId, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectOne( - new LambdaQueryWrapper() - .eq(HomeworkSubmission::getTenantId, tenantId) - .eq(HomeworkSubmission::getHomeworkId, homeworkId) - .eq(HomeworkSubmission::getStudentId, userId) - .eq(HomeworkSubmission::getDeleted, 0) - ); - - if (submission == null) { - return null; - } - - return convertToSubmissionVO(submission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SubmissionVO createScore(CreateScoreDTO dto, Long tenantId, Long reviewerId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(dto.getSubmissionId()); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - // TODO: 保存维度评分到 homework_dimension_scores 表 - // 这里先更新总分和评语 - if (dto.getDimensionScores() != null && !dto.getDimensionScores().isEmpty()) { - java.math.BigDecimal totalScore = dto.getDimensionScores().stream() - .map(com.lesingle.creation.dto.homework.DimensionScoreDTO::getScore) - .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add); - submission.setReviewScore(totalScore); - } - submission.setReviewComment(dto.getComments()); - submission.setReviewerId(reviewerId); - submission.setStatus("reviewing"); - submission.setReviewTime(LocalDateTime.now()); - - homeworkSubmissionMapper.updateById(submission); - log.info("创建评分成功,提交 ID={}, 评审人 ID={}", dto.getSubmissionId(), reviewerId); - - return convertToSubmissionVO(submission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void markViolation(Long submissionId, String reason, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(submissionId); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - submission.setStatus("violation"); - submission.setReviewComment("违规:" + reason); - homeworkSubmissionMapper.updateById(submission); - log.info("标记违规成功,提交 ID={}, 原因={}", submissionId, reason); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void resetScore(Long submissionId, Long tenantId) { - HomeworkSubmission submission = homeworkSubmissionMapper.selectById(submissionId); - if (submission == null || !submission.getTenantId().equals(tenantId)) { - throw new BusinessException("提交记录不存在"); - } - - submission.setReviewScore(null); - submission.setReviewComment(null); - submission.setReviewerId(null); - submission.setStatus("submitted"); - homeworkSubmissionMapper.updateById(submission); - log.info("重置评分成功,提交 ID={}", submissionId); - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/MenuServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/MenuServiceImpl.java deleted file mode 100644 index 8edad6b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/MenuServiceImpl.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.menu.CreateMenuDTO; -import com.lesingle.creation.dto.menu.UpdateMenuDTO; -import com.lesingle.creation.entity.*; -import com.lesingle.creation.mapper.*; -import com.lesingle.creation.service.MenuService; -import com.lesingle.creation.vo.menu.MenuDetailVO; -import com.lesingle.creation.vo.menu.MenuTreeVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 菜单服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class MenuServiceImpl extends ServiceImpl implements MenuService { - - private final MenuMapper menuMapper; - private final UserRoleMapper userRoleMapper; - private final RolePermissionMapper rolePermissionMapper; - private final PermissionMapper permissionMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public MenuDetailVO create(CreateMenuDTO dto, Long operatorId) { - log.info("开始创建菜单,菜单名称:{}", dto.getName()); - - // 创建菜单 - Menu menu = new Menu(); - menu.setName(dto.getName()); - menu.setPath(dto.getPath()); - menu.setIcon(dto.getIcon()); - menu.setComponent(dto.getComponent()); - menu.setParentId(dto.getParentId() != null ? dto.getParentId() : 0L); - menu.setPermission(dto.getPermission()); - menu.setSort(dto.getSort() != null ? dto.getSort() : 0); - menu.setValidState(1); - menu.setCreateBy(String.valueOf(operatorId)); - - menuMapper.insert(menu); - log.info("菜单创建成功,菜单 ID: {}", menu.getId()); - - return convertToDetailVO(menu); - } - - @Override - public List tree() { - log.info("查询菜单树"); - - // 查询所有菜单 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Menu::getValidState, 1) - .orderByAsc(Menu::getSort, Menu::getId); - - List allMenus = menuMapper.selectList(wrapper); - - // 构建树形结构 - return buildTree(allMenus, 0L); - } - - @Override - public List getUserMenus(Long userId, Long tenantId) { - log.info("查询用户菜单,用户 ID: {}, 租户 ID: {}", userId, tenantId); - - // 1. 查询用户关联的角色 - List userRoles = userRoleMapper.selectList( - new LambdaQueryWrapper() - .eq(UserRole::getUserId, userId) - ); - - if (userRoles.isEmpty()) { - // 用户没有角色,返回空菜单 - log.warn("用户没有任何角色,用户 ID: {}", userId); - return new ArrayList<>(); - } - - // 2. 获取角色 ID 列表 - List roleIds = userRoles.stream() - .map(UserRole::getRoleId) - .collect(Collectors.toList()); - - // 3. 查询角色关联的权限 - List rolePermissions = rolePermissionMapper.selectList( - new LambdaQueryWrapper() - .in(RolePermission::getRoleId, roleIds) - ); - - if (rolePermissions.isEmpty()) { - // 角色没有关联权限,返回空菜单 - log.warn("用户角色没有关联任何权限,用户 ID: {}", userId); - return new ArrayList<>(); - } - - // 4. 获取权限 ID 列表 - List permissionIds = rolePermissions.stream() - .map(RolePermission::getPermissionId) - .distinct() - .collect(Collectors.toList()); - - // 5. 查询权限详情,检查是否有 super_admin 权限 - List permissions = permissionMapper.selectBatchIds(permissionIds); - boolean hasSuperAdmin = permissions.stream() - .anyMatch(p -> "super_admin".equals(p.getCode())); - - // 6. 查询菜单 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Menu::getValidState, 1) - .orderByAsc(Menu::getSort, Menu::getId); - - List allMenus; - if (hasSuperAdmin) { - // 超管:查询所有菜单 - log.info("用户是超级管理员,返回所有菜单"); - allMenus = menuMapper.selectList(wrapper); - } else { - // 非超管:只查询有权限的菜单 - // 获取有权限的菜单编码 - List permissionCodes = permissions.stream() - .map(Permission::getCode) - .collect(Collectors.toList()); - - // 筛选条件:菜单权限为空(所有人都可见)或 菜单权限在用户权限列表中 - wrapper.and(w -> - w.isNull(Menu::getPermission) - .or() - .in(Menu::getPermission, permissionCodes) - ); - - log.info("非超管用户,根据权限过滤菜单,权限编码数量:{}", permissionCodes.size()); - allMenus = menuMapper.selectList(wrapper); - } - - // 7. 构建树形结构 - return buildTree(allMenus, 0L); - } - - @Override - public MenuDetailVO detail(Long id) { - log.info("查询菜单详情,菜单 ID: {}", id); - - Menu menu = menuMapper.selectById(id); - if (menu == null) { - throw new BusinessException("菜单不存在"); - } - - return convertToDetailVO(menu); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public MenuDetailVO update(Long id, UpdateMenuDTO dto) { - log.info("更新菜单,菜单 ID: {}", id); - - Menu existingMenu = menuMapper.selectById(id); - if (existingMenu == null) { - throw new BusinessException("菜单不存在"); - } - - // 更新菜单信息 - Menu menu = new Menu(); - menu.setId(id); - menu.setName(dto.getName()); - menu.setPath(dto.getPath()); - menu.setIcon(dto.getIcon()); - menu.setComponent(dto.getComponent()); - menu.setParentId(dto.getParentId()); - menu.setPermission(dto.getPermission()); - menu.setSort(dto.getSort()); - - menuMapper.updateById(menu); - log.info("菜单更新成功,菜单 ID: {}", id); - - return convertToDetailVO(menuMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - log.info("删除菜单,菜单 ID: {}", id); - - Menu menu = menuMapper.selectById(id); - if (menu == null) { - throw new BusinessException("菜单不存在"); - } - - // 检查是否有子菜单 - LambdaQueryWrapper childWrapper = new LambdaQueryWrapper<>(); - childWrapper.eq(Menu::getParentId, id); - Long childCount = menuMapper.selectCount(childWrapper); - if (childCount > 0) { - throw new BusinessException("存在子菜单,无法删除"); - } - - // 删除菜单(逻辑删除) - menuMapper.deleteById(id); - log.info("菜单删除成功,菜单 ID: {}", id); - } - - /** - * 构建树形结构 - */ - private List buildTree(List menus, Long parentId) { - return menus.stream() - .filter(menu -> { - Long pid = menu.getParentId(); - // 兼容历史数据:parent_id 为空视为根节点(0) - if (pid == null) { - pid = 0L; - } - return pid.equals(parentId); - }) - .map(this::convertToTreeVO) - .peek(vo -> vo.setChildren(buildTree(menus, vo.getId()))) - .collect(Collectors.toList()); - } - - /** - * 转换为详情 VO - */ - private MenuDetailVO convertToDetailVO(Menu menu) { - MenuDetailVO vo = new MenuDetailVO(); - vo.setId(menu.getId()); - vo.setName(menu.getName()); - vo.setPath(menu.getPath()); - vo.setIcon(menu.getIcon()); - vo.setComponent(menu.getComponent()); - vo.setParentId(menu.getParentId()); - vo.setPermission(menu.getPermission()); - vo.setSort(menu.getSort()); - vo.setValidState(menu.getValidState()); - vo.setCreateBy(menu.getCreateBy()); - vo.setCreateTime(menu.getCreateTime()); - vo.setUpdateBy(menu.getUpdateBy()); - vo.setUpdateTime(menu.getUpdateTime()); - return vo; - } - - /** - * 转换为树 VO - */ - private MenuTreeVO convertToTreeVO(Menu menu) { - MenuTreeVO vo = new MenuTreeVO(); - vo.setId(menu.getId()); - vo.setName(menu.getName()); - vo.setPath(menu.getPath()); - vo.setIcon(menu.getIcon()); - vo.setComponent(menu.getComponent()); - vo.setParentId(menu.getParentId()); - vo.setPermission(menu.getPermission()); - vo.setSort(menu.getSort()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/PermissionServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/PermissionServiceImpl.java deleted file mode 100644 index 7378a06..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/PermissionServiceImpl.java +++ /dev/null @@ -1,210 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.permission.CreatePermissionDTO; -import com.lesingle.creation.dto.permission.UpdatePermissionDTO; -import com.lesingle.creation.entity.Permission; -import com.lesingle.creation.mapper.PermissionMapper; -import com.lesingle.creation.service.PermissionService; -import com.lesingle.creation.vo.permission.PermissionDetailVO; -import com.lesingle.creation.vo.permission.PermissionListVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 权限服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class PermissionServiceImpl extends ServiceImpl implements PermissionService { - - private final PermissionMapper permissionMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public PermissionDetailVO create(CreatePermissionDTO dto, Long tenantId, Long operatorId) { - log.info("开始创建权限,权限编码:{}", dto.getCode()); - - // 检查权限编码是否已存在 - Permission existingPermission = permissionMapper.selectByCode(tenantId, dto.getCode()); - if (existingPermission != null) { - throw new BusinessException("权限编码已存在"); - } - - // 检查资源 + 操作组合是否已存在 - Permission existingResource = permissionMapper.selectByResourceAction(tenantId, dto.getResource(), dto.getAction()); - if (existingResource != null) { - throw new BusinessException("该资源的操作类型已存在"); - } - - // 创建权限 - Permission permission = new Permission(); - permission.setTenantId(tenantId); - permission.setName(dto.getName()); - permission.setCode(dto.getCode()); - permission.setResource(dto.getResource()); - permission.setAction(dto.getAction()); - permission.setDescription(dto.getDescription()); - permission.setValidState(1); - permission.setCreateBy(String.valueOf(operatorId)); - - permissionMapper.insert(permission); - log.info("权限创建成功,权限 ID: {}", permission.getId()); - - return convertToDetailVO(permission); - } - - @Override - public Page pageList(Long tenantId, int page, int pageSize) { - log.info("分页查询权限列表,租户 ID: {}, 页码:{}, 每页大小:{}", tenantId, page, pageSize); - - Page permissionPage = new Page<>(page, pageSize); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Permission::getTenantId, tenantId) - .eq(Permission::getValidState, 1) - .orderByAsc(Permission::getResource, Permission::getAction); - - Page resultPage = permissionMapper.selectPage(permissionPage, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public PermissionDetailVO detail(Long id) { - log.info("查询权限详情,权限 ID: {}", id); - - Permission permission = permissionMapper.selectById(id); - if (permission == null) { - throw new BusinessException("权限不存在"); - } - - return convertToDetailVO(permission); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public PermissionDetailVO update(Long id, UpdatePermissionDTO dto, Long tenantId) { - log.info("更新权限,权限 ID: {}", id); - - Permission existingPermission = permissionMapper.selectById(id); - if (existingPermission == null) { - throw new BusinessException("权限不存在"); - } - - // 如果更新了 code,检查是否冲突 - if (StringUtils.hasText(dto.getCode())) { - Permission conflictPermission = permissionMapper.selectByCodeExclude(tenantId, dto.getCode(), id); - if (conflictPermission != null) { - throw new BusinessException("权限编码已存在"); - } - } - - // 如果更新了资源 + 操作,检查是否冲突 - if (StringUtils.hasText(dto.getResource()) && StringUtils.hasText(dto.getAction())) { - Permission conflictResource = permissionMapper.selectByResourceActionExclude(tenantId, dto.getResource(), dto.getAction(), id); - if (conflictResource != null) { - throw new BusinessException("该资源的操作类型已存在"); - } - } - - // 更新权限信息 - Permission permission = new Permission(); - permission.setId(id); - permission.setName(dto.getName()); - permission.setCode(dto.getCode()); - permission.setResource(dto.getResource()); - permission.setAction(dto.getAction()); - permission.setDescription(dto.getDescription()); - - permissionMapper.updateById(permission); - log.info("权限更新成功,权限 ID: {}", id); - - return convertToDetailVO(permissionMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - log.info("删除权限,权限 ID: {}", id); - - Permission permission = permissionMapper.selectById(id); - if (permission == null) { - throw new BusinessException("权限不存在"); - } - - // 删除权限(逻辑删除) - permissionMapper.deleteById(id); - log.info("权限删除成功,权限 ID: {}", id); - } - - @Override - public List list(Long tenantId) { - log.info("查询权限列表,租户 ID: {}", tenantId); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Permission::getTenantId, tenantId) - .eq(Permission::getValidState, 1) - .orderByAsc(Permission::getResource, Permission::getAction); - - List permissions = permissionMapper.selectList(wrapper); - - return permissions.stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - } - - /** - * 转换为详情 VO - */ - private PermissionDetailVO convertToDetailVO(Permission permission) { - PermissionDetailVO vo = new PermissionDetailVO(); - vo.setId(permission.getId()); - vo.setTenantId(permission.getTenantId()); - vo.setName(permission.getName()); - vo.setCode(permission.getCode()); - vo.setResource(permission.getResource()); - vo.setAction(permission.getAction()); - vo.setDescription(permission.getDescription()); - vo.setValidState(permission.getValidState()); - vo.setCreateBy(permission.getCreateBy()); - vo.setCreateTime(permission.getCreateTime()); - vo.setUpdateBy(permission.getUpdateBy()); - vo.setUpdateTime(permission.getUpdateTime()); - return vo; - } - - /** - * 转换为列表 VO - */ - private PermissionListVO convertToListVO(Permission permission) { - PermissionListVO vo = new PermissionListVO(); - vo.setId(permission.getId()); - vo.setTenantId(permission.getTenantId()); - vo.setName(permission.getName()); - vo.setCode(permission.getCode()); - vo.setResource(permission.getResource()); - vo.setAction(permission.getAction()); - vo.setDescription(permission.getDescription()); - vo.setValidState(permission.getValidState()); - vo.setCreateTime(permission.getCreateTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/PublicServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/PublicServiceImpl.java deleted file mode 100644 index 60c78d4..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/PublicServiceImpl.java +++ /dev/null @@ -1,361 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.common.util.JwtTokenUtil; -import com.lesingle.creation.dto.child.CreateChildDTO; -import com.lesingle.creation.dto.child.UpdateChildDTO; -import com.lesingle.creation.dto.publicuser.PublicLoginDTO; -import com.lesingle.creation.dto.publicuser.PublicRegisterDTO; -import com.lesingle.creation.dto.publicuser.PublicUserUpdateDTO; -import com.lesingle.creation.entity.Contest; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.entity.UserChild; -import com.lesingle.creation.mapper.ContestMapper; -import com.lesingle.creation.mapper.UserChildMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.service.PublicService; -import com.lesingle.creation.vo.child.ChildVO; -import com.lesingle.creation.vo.publicuser.LoginResponseVO; -import com.lesingle.creation.vo.publicuser.PublicUserVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDateTime; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 公众用户服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class PublicServiceImpl implements PublicService { - - private final UserMapper userMapper; - private final UserChildMapper userChildMapper; - private final ContestMapper contestMapper; - private final PasswordEncoder passwordEncoder; - private final JwtTokenUtil jwtTokenUtil; - - @Override - @Transactional(rollbackFor = Exception.class) - public LoginResponseVO register(PublicRegisterDTO dto) { - // 检查用户名是否已存在 - User existingUser = userMapper.selectByUsername(dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("用户名已存在"); - } - - // 创建用户 - User user = new User(); - user.setTenantId(1L); - user.setUsername(dto.getUsername()); - user.setPassword(passwordEncoder.encode(dto.getPassword())); - user.setNickname(dto.getNickname()); - user.setPhone(dto.getPhone()); - user.setEmail(dto.getEmail()); - user.setAvatar(dto.getAvatar()); - user.setGender(dto.getGender()); - user.setCity(dto.getCity()); - user.setUserType("adult"); - user.setUserSource("self_registered"); - user.setStatus("active"); - - userMapper.insert(user); - log.info("用户注册成功,ID={}, 用户名={}", user.getId(), dto.getUsername()); - - return generateLoginResponse(user); - } - - @Override - public LoginResponseVO login(PublicLoginDTO dto) { - // 根据用户名或手机号查询用户 - User user = userMapper.selectByUsername(dto.getUsername()); - if (user == null) { - throw new BusinessException("用户名或密码错误"); - } - - // 验证密码 - if (!passwordEncoder.matches(dto.getPassword(), user.getPassword())) { - throw new BusinessException("用户名或密码错误"); - } - - // 检查用户状态 - if (!"active".equals(user.getStatus())) { - throw new BusinessException("账号已被禁用"); - } - - log.info("用户登录成功,ID={}, 用户名={}", user.getId(), user.getUsername()); - - return generateLoginResponse(user); - } - - @Override - public PublicUserVO getUserInfo(Long userId) { - User user = userMapper.selectById(userId); - if (user == null) { - throw new BusinessException("用户不存在"); - } - return convertToPublicUserVO(user); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public PublicUserVO updateProfile(Long userId, PublicUserUpdateDTO dto) { - User user = userMapper.selectById(userId); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - if (dto.getNickname() != null) { - user.setNickname(dto.getNickname()); - } - if (dto.getCity() != null) { - user.setCity(dto.getCity()); - } - if (dto.getAvatar() != null) { - user.setAvatar(dto.getAvatar()); - } - if (dto.getGender() != null) { - user.setGender(dto.getGender()); - } - - userMapper.updateById(user); - log.info("更新用户信息成功,ID={}", userId); - - return convertToPublicUserVO(user); - } - - @Override - public List getChildren(Long userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(UserChild::getParentId, userId); - - List userChildren = userChildMapper.selectList(wrapper); - return userChildren.stream() - .map(this::convertToChildVO) - .collect(Collectors.toList()); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ChildVO createChild(Long userId, CreateChildDTO dto) { - // 检查子女用户名是否已存在 - User existingUser = userMapper.selectByUsername(dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("子女用户名已存在"); - } - - // 创建子女用户账号 - User childUser = new User(); - childUser.setTenantId(1L); - childUser.setUsername(dto.getUsername()); - childUser.setPassword(passwordEncoder.encode(dto.getPassword())); - childUser.setNickname(dto.getNickname()); - childUser.setGender(dto.getGender()); - childUser.setBirthday(dto.getBirthday()); - childUser.setCity(dto.getCity()); - childUser.setAvatar(dto.getAvatar()); - childUser.setUserType("child"); - childUser.setUserSource("parent_created"); - childUser.setStatus("active"); - - userMapper.insert(childUser); - - // 创建亲子关系 - UserChild userChild = new UserChild(); - userChild.setParentId(userId); - userChild.setChildUserId(childUser.getId()); - userChild.setRelationship(dto.getRelationship()); - userChild.setControlMode("full"); - - userChildMapper.insert(userChild); - log.info("创建子女成功,子女 ID={}, 父母 ID={}", childUser.getId(), userId); - - return convertToChildVO(userChild); - } - - @Override - public ChildVO getChild(Long userId, Long childId) { - UserChild userChild = userChildMapper.selectById(childId); - if (userChild == null || !userChild.getParentId().equals(userId)) { - throw new BusinessException("子女不存在"); - } - return convertToChildVO(userChild); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ChildVO updateChild(Long userId, Long childId, UpdateChildDTO dto) { - UserChild userChild = userChildMapper.selectById(childId); - if (userChild == null || !userChild.getParentId().equals(userId)) { - throw new BusinessException("子女不存在"); - } - - // 更新子女用户信息 - User childUser = userMapper.selectById(userChild.getChildUserId()); - if (childUser != null) { - if (dto.getNickname() != null) { - childUser.setNickname(dto.getNickname()); - } - if (dto.getPassword() != null && !dto.getPassword().isEmpty()) { - childUser.setPassword(passwordEncoder.encode(dto.getPassword())); - } - if (dto.getGender() != null) { - childUser.setGender(dto.getGender()); - } - if (dto.getBirthday() != null) { - childUser.setBirthday(dto.getBirthday()); - } - if (dto.getCity() != null) { - childUser.setCity(dto.getCity()); - } - if (dto.getAvatar() != null) { - childUser.setAvatar(dto.getAvatar()); - } - userMapper.updateById(childUser); - } - - // 更新亲子关系信息 - if (dto.getControlMode() != null) { - userChild.setControlMode(dto.getControlMode()); - } - userChildMapper.updateById(userChild); - - log.info("更新子女信息成功,ID={}", childId); - - return convertToChildVO(userChild); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void deleteChild(Long userId, Long childId) { - UserChild userChild = userChildMapper.selectById(childId); - if (userChild == null || !userChild.getParentId().equals(userId)) { - throw new BusinessException("子女不存在"); - } - - // 物理删除亲子关系 - userChildMapper.deleteById(userChild); - - // 禁用子女账号 - User childUser = userMapper.selectById(userChild.getChildUserId()); - if (childUser != null) { - childUser.setStatus("disabled"); - userMapper.updateById(childUser); - } - - log.info("删除子女成功,ID={}", childId); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ChildVO createChildAccount(Long userId, CreateChildDTO dto) { - // 这个方法与 createChild 类似,但专门用于创建独立账号 - return createChild(userId, dto); - } - - @Override - public List getChildAccounts(Long userId) { - return getChildren(userId); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ChildVO updateChildAccount(Long userId, Long childId, UpdateChildDTO dto) { - return updateChild(userId, childId, dto); - } - - @Override - public PublicUserVO getParentInfo(Long userId) { - return getUserInfo(userId); - } - - @Override - public Object getPublicActivities(Integer page, Integer pageSize, String keyword, String contestType, Long userId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Contest::getValidState, 1) - .eq(Contest::getContestState, "published") - .orderByDesc(Contest::getCreateTime); - - if (keyword != null && !keyword.isEmpty()) { - wrapper.and(w -> w.like(Contest::getContestName, keyword) - .or().like(Contest::getContent, keyword)); - } - - if (contestType != null && !contestType.isEmpty()) { - wrapper.eq(Contest::getContestType, contestType); - } - - List contests = contestMapper.selectList(wrapper); - return contests.stream() - .map(this::convertToActivityVO) - .collect(Collectors.toList()); - } - - @Override - public Object getActivityDetail(Long id) { - Contest contest = contestMapper.selectById(id); - if (contest == null) { - throw new BusinessException("活动不存在"); - } - return convertToActivityVO(contest); - } - - // ========== 转换方法 ========== - - private LoginResponseVO generateLoginResponse(User user) { - LoginResponseVO response = new LoginResponseVO(); - String token = jwtTokenUtil.generateToken(user.getId(), user.getUsername()); - response.setAccessToken(token); - response.setTokenType("Bearer"); - response.setExpiresIn(7200L); // 2 小时 - response.setUser(convertToPublicUserVO(user)); - return response; - } - - private PublicUserVO convertToPublicUserVO(User user) { - PublicUserVO vo = new PublicUserVO(); - vo.setId(user.getId()); - vo.setUsername(user.getUsername()); - vo.setNickname(user.getNickname()); - vo.setPhone(user.getPhone()); - vo.setEmail(user.getEmail()); - vo.setAvatar(user.getAvatar()); - vo.setGender(user.getGender()); - vo.setCity(user.getCity()); - vo.setUserType(user.getUserType()); - return vo; - } - - private ChildVO convertToChildVO(UserChild userChild) { - ChildVO vo = new ChildVO(); - vo.setId(userChild.getChildUserId()); - vo.setParentId(userChild.getParentId()); - vo.setRelationship(userChild.getRelationship()); - vo.setControlMode(userChild.getControlMode()); - - // 关联查询子女用户信息 - User childUser = userMapper.selectById(userChild.getChildUserId()); - if (childUser != null) { - vo.setUsername(childUser.getUsername()); - vo.setNickname(childUser.getNickname()); - vo.setGender(childUser.getGender()); - vo.setBirthday(childUser.getBirthday()); - vo.setCity(childUser.getCity()); - vo.setAvatar(childUser.getAvatar()); - } - - return vo; - } - - private Object convertToActivityVO(Contest contest) { - // 这里简单返回 Contest 对象,实际应该转换为 ActivityVO - return contest; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/RoleServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/RoleServiceImpl.java deleted file mode 100644 index 23b10d8..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/RoleServiceImpl.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.role.CreateRoleDTO; -import com.lesingle.creation.dto.role.UpdateRoleDTO; -import com.lesingle.creation.entity.Role; -import com.lesingle.creation.entity.RolePermission; -import com.lesingle.creation.mapper.RoleMapper; -import com.lesingle.creation.mapper.RolePermissionMapper; -import com.lesingle.creation.service.RoleService; -import com.lesingle.creation.vo.role.RoleDetailVO; -import com.lesingle.creation.vo.role.RoleListVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 角色服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class RoleServiceImpl extends ServiceImpl implements RoleService { - - private final RoleMapper roleMapper; - private final RolePermissionMapper rolePermissionMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public RoleDetailVO create(CreateRoleDTO dto, Long tenantId, Long operatorId) { - log.info("开始创建角色,角色编码:{}", dto.getCode()); - - // 检查角色编码是否已存在 - Role existingRole = roleMapper.selectByCode(tenantId, dto.getCode()); - if (existingRole != null) { - throw new BusinessException("角色编码已存在"); - } - - // 创建角色 - Role role = new Role(); - role.setTenantId(tenantId); - role.setName(dto.getName()); - role.setCode(dto.getCode()); - role.setDescription(dto.getDescription()); - role.setValidState(1); - role.setCreateBy(String.valueOf(operatorId)); - - roleMapper.insert(role); - log.info("角色创建成功,角色 ID: {}", role.getId()); - - // 如果提供了权限 ID,创建权限关联 - if (!CollectionUtils.isEmpty(dto.getPermissionIds())) { - List rolePermissions = dto.getPermissionIds().stream() - .map(permissionId -> { - RolePermission rp = new RolePermission(); - rp.setRoleId(role.getId()); - rp.setPermissionId(permissionId); - return rp; - }) - .collect(Collectors.toList()); - rolePermissionMapper.saveBatch(rolePermissions); - log.info("角色权限关联创建成功,权限数量:{}", dto.getPermissionIds().size()); - } - - return convertToDetailVO(role); - } - - @Override - public Page pageList(Long tenantId, int page, int pageSize) { - log.info("分页查询角色列表,租户 ID: {}, 页码:{}, 每页大小:{}", tenantId, page, pageSize); - - Page rolePage = new Page<>(page, pageSize); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Role::getTenantId, tenantId) - .eq(Role::getValidState, 1) - .orderByDesc(Role::getCreateTime); - - Page resultPage = roleMapper.selectPage(rolePage, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public RoleDetailVO detail(Long id) { - log.info("查询角色详情,角色 ID: {}", id); - - Role role = roleMapper.selectById(id); - if (role == null) { - throw new BusinessException("角色不存在"); - } - - return convertToDetailVO(role); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public RoleDetailVO update(Long id, UpdateRoleDTO dto, Long tenantId) { - log.info("更新角色,角色 ID: {}", id); - - Role existingRole = roleMapper.selectById(id); - if (existingRole == null) { - throw new BusinessException("角色不存在"); - } - - // 如果更新了 code,检查是否冲突 - if (dto.getCode() != null && !dto.getCode().isEmpty()) { - Role conflictRole = roleMapper.selectByCodeExclude(tenantId, dto.getCode(), id); - if (conflictRole != null) { - throw new BusinessException("角色编码已存在"); - } - } - - // 更新角色信息 - Role role = new Role(); - role.setId(id); - role.setName(dto.getName()); - role.setCode(dto.getCode()); - role.setDescription(dto.getDescription()); - - roleMapper.updateById(role); - log.info("角色更新成功,角色 ID: {}", id); - - // 如果提供了 permissionIds,更新权限关联 - if (dto.getPermissionIds() != null) { - // 先删除现有权限关联 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(RolePermission::getRoleId, id); - rolePermissionMapper.delete(wrapper); - log.info("已删除角色原有权限关联"); - - // 创建新的权限关联 - if (!dto.getPermissionIds().isEmpty()) { - List rolePermissions = dto.getPermissionIds().stream() - .map(permissionId -> { - RolePermission rp = new RolePermission(); - rp.setRoleId(id); - rp.setPermissionId(permissionId); - return rp; - }) - .collect(Collectors.toList()); - rolePermissionMapper.saveBatch(rolePermissions); - log.info("角色新权限关联创建成功,权限数量:{}", dto.getPermissionIds().size()); - } - } - - return convertToDetailVO(roleMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - log.info("删除角色,角色 ID: {}", id); - - Role role = roleMapper.selectById(id); - if (role == null) { - throw new BusinessException("角色不存在"); - } - - // 删除角色关联 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(RolePermission::getRoleId, id); - rolePermissionMapper.delete(wrapper); - - // 删除角色(逻辑删除) - roleMapper.deleteById(id); - log.info("角色删除成功,角色 ID: {}", id); - } - - @Override - public List list(Long tenantId) { - log.info("查询角色列表,租户 ID: {}", tenantId); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(Role::getTenantId, tenantId) - .eq(Role::getValidState, 1) - .orderByAsc(Role::getCode); - - List roles = roleMapper.selectList(wrapper); - - return roles.stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - } - - /** - * 转换为详情 VO - */ - private RoleDetailVO convertToDetailVO(Role role) { - RoleDetailVO vo = new RoleDetailVO(); - vo.setId(role.getId()); - vo.setTenantId(role.getTenantId()); - vo.setName(role.getName()); - vo.setCode(role.getCode()); - vo.setDescription(role.getDescription()); - vo.setValidState(role.getValidState()); - vo.setCreateBy(role.getCreateBy()); - vo.setCreateTime(role.getCreateTime()); - vo.setUpdateBy(role.getUpdateBy()); - vo.setUpdateTime(role.getUpdateTime()); - - // TODO: 获取角色权限 - vo.setPermissionIds(new ArrayList<>()); - vo.setPermissionNames(new ArrayList<>()); - - return vo; - } - - /** - * 转换为列表 VO - */ - private RoleListVO convertToListVO(Role role) { - RoleListVO vo = new RoleListVO(); - vo.setId(role.getId()); - vo.setTenantId(role.getTenantId()); - vo.setName(role.getName()); - vo.setCode(role.getCode()); - vo.setDescription(role.getDescription()); - vo.setValidState(role.getValidState()); - vo.setCreateTime(role.getCreateTime()); - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java deleted file mode 100644 index 761b226..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolClassServiceImpl.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.schoolclass.CreateClassDTO; -import com.lesingle.creation.dto.schoolclass.UpdateClassDTO; -import com.lesingle.creation.entity.Grade; -import com.lesingle.creation.entity.SchoolClass; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.GradeMapper; -import com.lesingle.creation.mapper.SchoolClassMapper; -import com.lesingle.creation.service.SchoolClassService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.grade.GradeVO; -import com.lesingle.creation.vo.schoolclass.ClassVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 班级服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class SchoolClassServiceImpl extends ServiceImpl implements SchoolClassService { - - private final SchoolClassMapper schoolClassMapper; - private final GradeMapper gradeMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public ClassVO create(CreateClassDTO dto, Long tenantId, Long creatorId) { - // 检查班级编码是否已存在 - SchoolClass existing = schoolClassMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null) { - throw new BusinessException("班级编码已存在"); - } - - // 验证年级是否存在 - Grade grade = gradeMapper.selectById(dto.getGradeId()); - if (grade == null) { - throw new BusinessException("年级不存在"); - } - - SchoolClass schoolClass = new SchoolClass(); - schoolClass.setTenantId(tenantId); - schoolClass.setGradeId(dto.getGradeId()); - schoolClass.setName(dto.getName()); - schoolClass.setCode(dto.getCode()); - schoolClass.setType(dto.getType()); - schoolClass.setCapacity(dto.getCapacity()); - schoolClass.setDescription(dto.getDescription()); - schoolClass.setValidState(1); - - schoolClassMapper.insert(schoolClass); - log.info("创建班级成功,ID={}, 名称={}", schoolClass.getId(), dto.getName()); - - return convertToVO(schoolClass); - } - - @Override - public Page pageQuery(Integer pageNum, Integer pageSize, Long tenantId, Long gradeId, Integer type) { - Page page = new Page<>(pageNum, pageSize); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(SchoolClass::getTenantId, tenantId) - .eq(SchoolClass::getDeleted, 0) - .eq(gradeId != null, SchoolClass::getGradeId, gradeId) - .eq(type != null, SchoolClass::getType, type) - .orderByAsc(SchoolClass::getName); - - Page resultPage = this.page(page, wrapper); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(resultPage.getRecords().stream().map(this::convertToVO).toList()); - return voPage; - } - - @Override - public ClassVO getDetail(Long id, Long tenantId) { - SchoolClass schoolClass = this.getById(id); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - return convertToVO(schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public ClassVO update(Long id, UpdateClassDTO dto, Long tenantId, Long modifierId) { - SchoolClass schoolClass = this.getById(id); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - - if (dto.getGradeId() != null) { - // 验证年级是否存在 - Grade grade = gradeMapper.selectById(dto.getGradeId()); - if (grade == null) { - throw new BusinessException("年级不存在"); - } - schoolClass.setGradeId(dto.getGradeId()); - } - if (dto.getName() != null) { - schoolClass.setName(dto.getName()); - } - if (dto.getCode() != null) { - // 检查新编码是否已被其他班级使用 - SchoolClass existing = schoolClassMapper.selectByCode(tenantId, dto.getCode()); - if (existing != null && !existing.getId().equals(id)) { - throw new BusinessException("班级编码已存在"); - } - schoolClass.setCode(dto.getCode()); - } - if (dto.getType() != null) { - schoolClass.setType(dto.getType()); - } - if (dto.getCapacity() != null) { - schoolClass.setCapacity(dto.getCapacity()); - } - if (dto.getDescription() != null) { - schoolClass.setDescription(dto.getDescription()); - } - - this.updateById(schoolClass); - log.info("更新班级成功,ID={}", id); - - return convertToVO(schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - SchoolClass schoolClass = this.getById(id); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - - schoolClass.setDeleted(1); - this.updateById(schoolClass); - log.info("删除班级成功,ID={}", id); - } - - private ClassVO convertToVO(SchoolClass schoolClass) { - ClassVO vo = new ClassVO(); - vo.setId(schoolClass.getId()); - vo.setTenantId(schoolClass.getTenantId()); - vo.setGradeId(schoolClass.getGradeId()); - vo.setName(schoolClass.getName()); - vo.setCode(schoolClass.getCode()); - vo.setType(schoolClass.getType()); - vo.setCapacity(schoolClass.getCapacity()); - vo.setDescription(schoolClass.getDescription()); - vo.setValidState(schoolClass.getValidState()); - vo.setCreateTime(schoolClass.getCreateTime()); - vo.setUpdateTime(schoolClass.getUpdateTime()); - - // 关联查询年级信息 - Grade grade = gradeMapper.selectById(schoolClass.getGradeId()); - if (grade != null) { - GradeVO gradeVO = new GradeVO(); - gradeVO.setId(grade.getId()); - gradeVO.setName(grade.getName()); - gradeVO.setCode(grade.getCode()); - gradeVO.setLevel(grade.getLevel()); - vo.setGrade(gradeVO); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java deleted file mode 100644 index e4ca6bf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/SchoolServiceImpl.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.school.CreateSchoolDTO; -import com.lesingle.creation.dto.school.UpdateSchoolDTO; -import com.lesingle.creation.entity.School; -import com.lesingle.creation.mapper.SchoolMapper; -import com.lesingle.creation.service.SchoolService; -import com.lesingle.creation.vo.school.SchoolVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * 学校服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class SchoolServiceImpl extends ServiceImpl implements SchoolService { - - private final SchoolMapper schoolMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public SchoolVO create(CreateSchoolDTO dto, Long tenantId, Long creatorId) { - log.info("开始创建学校,租户 ID: {}", tenantId); - - // 检查租户是否已有学校信息 - School existingSchool = schoolMapper.selectByTenantId(tenantId); - if (existingSchool != null) { - throw new BusinessException("该租户已存在学校信息"); - } - - // 创建学校 - School school = new School(); - school.setTenantId(tenantId); - school.setAddress(dto.getAddress()); - school.setPhone(dto.getPhone()); - school.setPrincipal(dto.getPrincipal()); - school.setEstablished(dto.getEstablished()); - school.setDescription(dto.getDescription()); - school.setLogo(dto.getLogo()); - school.setWebsite(dto.getWebsite()); - school.setValidState(1); - school.setCreateBy(String.valueOf(creatorId)); - - schoolMapper.insert(school); - log.info("学校创建成功,学校 ID: {}", school.getId()); - - return convertToVO(school); - } - - @Override - public SchoolVO getByTenantId(Long tenantId) { - log.info("查询学校信息,租户 ID: {}", tenantId); - - School school = schoolMapper.selectByTenantId(tenantId); - if (school == null) { - throw new BusinessException("学校信息不存在"); - } - - return convertToVO(school); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public SchoolVO update(UpdateSchoolDTO dto, Long tenantId, Long modifierId) { - log.info("更新学校信息,租户 ID: {}", tenantId); - - School existingSchool = schoolMapper.selectByTenantId(tenantId); - if (existingSchool == null) { - throw new BusinessException("学校信息不存在"); - } - - // 更新学校信息 - School school = new School(); - school.setId(existingSchool.getId()); - school.setAddress(dto.getAddress()); - school.setPhone(dto.getPhone()); - school.setPrincipal(dto.getPrincipal()); - school.setEstablished(dto.getEstablished()); - school.setDescription(dto.getDescription()); - school.setLogo(dto.getLogo()); - school.setWebsite(dto.getWebsite()); - school.setUpdateBy(String.valueOf(modifierId)); - - schoolMapper.updateById(school); - log.info("学校更新成功,学校 ID: {}", school.getId()); - - return convertToVO(schoolMapper.selectById(school.getId())); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long tenantId) { - log.info("删除学校信息,租户 ID: {}", tenantId); - - School school = schoolMapper.selectByTenantId(tenantId); - if (school == null) { - throw new BusinessException("学校信息不存在"); - } - - // 删除学校(逻辑删除) - schoolMapper.deleteById(school.getId()); - log.info("学校删除成功,学校 ID: {}", school.getId()); - } - - /** - * 转换为 VO - */ - private SchoolVO convertToVO(School school) { - SchoolVO vo = new SchoolVO(); - vo.setId(school.getId()); - vo.setTenantId(school.getTenantId()); - vo.setAddress(school.getAddress()); - vo.setPhone(school.getPhone()); - vo.setPrincipal(school.getPrincipal()); - vo.setEstablished(school.getEstablished()); - vo.setDescription(school.getDescription()); - vo.setLogo(school.getLogo()); - vo.setWebsite(school.getWebsite()); - vo.setValidState(school.getValidState()); - vo.setCreateBy(school.getCreateBy()); - vo.setCreateTime(school.getCreateTime()); - vo.setUpdateBy(school.getUpdateBy()); - vo.setUpdateTime(school.getUpdateTime()); - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java deleted file mode 100644 index 2c11dd5..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/StudentServiceImpl.java +++ /dev/null @@ -1,293 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.dto.student.CreateStudentDTO; -import com.lesingle.creation.dto.student.UpdateStudentDTO; -import com.lesingle.creation.entity.SchoolClass; -import com.lesingle.creation.entity.Student; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.StudentMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.mapper.SchoolClassMapper; -import com.lesingle.creation.service.SchoolClassService; -import com.lesingle.creation.service.StudentService; -import com.lesingle.creation.vo.student.StudentVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 学生服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class StudentServiceImpl extends ServiceImpl implements StudentService { - - private final StudentMapper studentMapper; - private final UserMapper userMapper; - private final SchoolClassService schoolClassService; - private final SchoolClassMapper schoolClassMapper; - private final PasswordEncoder passwordEncoder; - - @Override - @Transactional(rollbackFor = Exception.class) - public StudentVO create(CreateStudentDTO dto, Long tenantId, Long creatorId) { - // 检查用户名是否已存在 - User existingUser = userMapper.selectByUsername(dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("用户名已存在"); - } - - // 检查学号是否已存在 - Student existingStudent = studentMapper.selectByStudentNo(tenantId, dto.getStudentNo()); - if (existingStudent != null) { - throw new BusinessException("学号已存在"); - } - - // 检查班级是否存在 - SchoolClass schoolClass = schoolClassMapper.selectById(dto.getClassId()); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - - // 创建用户账号 - User user = new User(); - user.setTenantId(tenantId); - user.setUsername(dto.getUsername()); - user.setPassword(passwordEncoder.encode(dto.getPassword())); - user.setNickname(dto.getNickname()); - user.setEmail(dto.getEmail()); - user.setAvatar(dto.getAvatar()); - user.setUserType("student"); // 学生用户 - user.setStatus("active"); - user.setUserSource("admin_created"); - - userMapper.insert(user); - log.info("创建用户账号成功,ID={}, 用户名={}", user.getId(), dto.getUsername()); - - // 创建学生信息 - Student student = new Student(); - student.setTenantId(tenantId); - student.setUserId(user.getId()); - student.setClassId(dto.getClassId()); - student.setStudentNo(dto.getStudentNo()); - student.setPhone(dto.getPhone()); - student.setIdCard(dto.getIdCard()); - student.setGender(dto.getGender()); - student.setBirthDate(dto.getBirthDate()); - student.setEnrollmentDate(dto.getEnrollmentDate()); - student.setParentName(dto.getParentName()); - student.setParentPhone(dto.getParentPhone()); - student.setAddress(dto.getAddress()); - student.setDescription(dto.getDescription()); - student.setValidState(1); - - studentMapper.insert(student); - log.info("创建学生成功,ID={}, 学号={}", student.getId(), dto.getStudentNo()); - - return convertToVO(student, user, schoolClass); - } - - @Override - public List list(Long tenantId, Integer page, Integer pageSize, Long classId) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Student::getTenantId, tenantId) - .eq(Student::getDeleted, 0) - .eq(classId != null, Student::getClassId, classId) - .orderByDesc(Student::getCreateTime); - - Page studentPage = this.page(new Page<>(page, pageSize), wrapper); - - // 转换为 VO - return studentPage.getRecords().stream() - .map(student -> { - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - return convertToVO(student, user, schoolClass); - }) - .collect(Collectors.toList()); - } - - @Override - public StudentVO getDetail(Long id, Long tenantId) { - Student student = this.getById(id); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - - return convertToVO(student, user, schoolClass); - } - - @Override - public StudentVO getByUserId(Long userId, Long tenantId) { - Student student = studentMapper.selectByUserId(userId); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - - return convertToVO(student, user, schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public StudentVO update(Long id, UpdateStudentDTO dto, Long tenantId, Long modifierId) { - Student student = this.getById(id); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - // 检查学号是否已被其他学生使用 - if (dto.getStudentNo() != null) { - Student existingStudent = studentMapper.selectByStudentNo(tenantId, dto.getStudentNo()); - if (existingStudent != null && !existingStudent.getId().equals(id)) { - throw new BusinessException("学号已存在"); - } - student.setStudentNo(dto.getStudentNo()); - } - - // 更新学生信息 - if (dto.getClassId() != null) { - SchoolClass schoolClass = schoolClassMapper.selectById(dto.getClassId()); - if (schoolClass == null || !schoolClass.getTenantId().equals(tenantId)) { - throw new BusinessException("班级不存在"); - } - student.setClassId(dto.getClassId()); - } - if (dto.getPhone() != null) { - student.setPhone(dto.getPhone()); - } - if (dto.getIdCard() != null) { - student.setIdCard(dto.getIdCard()); - } - if (dto.getGender() != null) { - student.setGender(dto.getGender()); - } - if (dto.getBirthDate() != null) { - student.setBirthDate(dto.getBirthDate()); - } - if (dto.getEnrollmentDate() != null) { - student.setEnrollmentDate(dto.getEnrollmentDate()); - } - if (dto.getParentName() != null) { - student.setParentName(dto.getParentName()); - } - if (dto.getParentPhone() != null) { - student.setParentPhone(dto.getParentPhone()); - } - if (dto.getAddress() != null) { - student.setAddress(dto.getAddress()); - } - if (dto.getDescription() != null) { - student.setDescription(dto.getDescription()); - } - if (dto.getValidState() != null) { - student.setValidState(dto.getValidState()); - } - - // 更新用户信息(如果有) - if (dto.getNickname() != null || dto.getEmail() != null || dto.getAvatar() != null) { - User user = userMapper.selectById(student.getUserId()); - if (user != null) { - if (dto.getNickname() != null) { - user.setNickname(dto.getNickname()); - } - if (dto.getEmail() != null) { - user.setEmail(dto.getEmail()); - } - if (dto.getAvatar() != null) { - user.setAvatar(dto.getAvatar()); - } - userMapper.updateById(user); - } - } - - this.updateById(student); - log.info("更新学生成功,ID={}", id); - - User user = userMapper.selectById(student.getUserId()); - SchoolClass schoolClass = schoolClassMapper.selectById(student.getClassId()); - return convertToVO(student, user, schoolClass); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Student student = this.getById(id); - if (student == null || !student.getTenantId().equals(tenantId)) { - throw new BusinessException("学生不存在"); - } - - // 逻辑删除学生 - student.setDeleted(1); - this.updateById(student); - - // 同时禁用关联的用户账号 - User user = userMapper.selectById(student.getUserId()); - if (user != null) { - user.setStatus("disabled"); // 禁用状态 - userMapper.updateById(user); - } - - log.info("删除学生成功,ID={}, 用户 ID={}", id, student.getUserId()); - } - - /** - * 转换为 VO - */ - private StudentVO convertToVO(Student student, User user, SchoolClass schoolClass) { - StudentVO vo = new StudentVO(); - vo.setId(student.getId()); - vo.setUserId(student.getUserId()); - vo.setTenantId(student.getTenantId()); - vo.setClassId(student.getClassId()); - vo.setStudentNo(student.getStudentNo()); - vo.setPhone(student.getPhone()); - vo.setIdCard(student.getIdCard()); - vo.setGender(student.getGender()); - vo.setBirthDate(student.getBirthDate()); - vo.setEnrollmentDate(student.getEnrollmentDate()); - vo.setParentName(student.getParentName()); - vo.setParentPhone(student.getParentPhone()); - vo.setAddress(student.getAddress()); - vo.setDescription(student.getDescription()); - vo.setValidState(student.getValidState()); - vo.setCreateTime(student.getCreateTime()); - vo.setUpdateTime(student.getUpdateTime()); - - // 用户信息 - if (user != null) { - StudentVO.UserInfo userInfo = new StudentVO.UserInfo(); - userInfo.setUsername(user.getUsername()); - userInfo.setNickname(user.getNickname()); - userInfo.setEmail(user.getEmail()); - userInfo.setAvatar(user.getAvatar()); - vo.setUserInfo(userInfo); - } - - // 班级信息 - if (schoolClass != null) { - StudentVO.ClassInfo classInfo = new StudentVO.ClassInfo(); - classInfo.setId(schoolClass.getId()); - classInfo.setName(schoolClass.getName()); - classInfo.setCode(schoolClass.getCode()); - vo.setClassInfo(classInfo); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/SysLogServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/SysLogServiceImpl.java deleted file mode 100644 index 70ab648..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/SysLogServiceImpl.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.lesingle.creation.dto.log.LogQueryDTO; -import com.lesingle.creation.entity.SysLog; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.SysLogMapper; -import com.lesingle.creation.service.SysLogService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.vo.log.LogStatisticsVO; -import com.lesingle.creation.vo.log.LogVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * 系统日志服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class SysLogServiceImpl extends ServiceImpl implements SysLogService { - - private final SysLogMapper sysLogMapper; - - @Override - public Page pageQuery(LogQueryDTO queryDTO, Long tenantId) { - Page page = new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()); - - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(SysLog::getTenantId, tenantId) - .eq(queryDTO.getUserId() != null, SysLog::getUserId, queryDTO.getUserId()) - .like(queryDTO.getAction() != null, SysLog::getAction, queryDTO.getAction()) - .like(queryDTO.getIp() != null, SysLog::getIp, queryDTO.getIp()) - .like(queryDTO.getKeyword() != null, SysLog::getContent, queryDTO.getKeyword()) - .between( - queryDTO.getStartTime() != null && queryDTO.getEndTime() != null, - SysLog::getCreateTime, - parseDateTime(queryDTO.getStartTime(), LocalTime.MIN), - parseDateTime(queryDTO.getEndTime(), LocalTime.MAX) - ) - .orderByDesc(SysLog::getCreateTime); - - Page resultPage = this.page(page, wrapper); - - List voList = resultPage.getRecords().stream() - .map(this::convertToVO) - .toList(); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - return voPage; - } - - @Override - public LogVO getDetail(Long id, Long tenantId) { - SysLog sysLog = this.getById(id); - if (sysLog == null || !sysLog.getTenantId().equals(tenantId)) { - throw new BusinessException("日志记录不存在"); - } - return convertToVO(sysLog); - } - - @Override - public LogStatisticsVO getStatistics(Integer days, Long tenantId) { - if (days == null) { - days = 7; - } - - LogStatisticsVO vo = new LogStatisticsVO(); - vo.setDays(days); - - // 获取统计数据 - Map stats = sysLogMapper.getStatistics(days); - vo.setTotalCount(((Number) stats.get("total_count")).longValue()); - vo.setRecentCount(((Number) stats.get("recent_count")).longValue()); - - // 获取操作类型统计 - List> actionStatsData = sysLogMapper.getActionStats(days); - List actionStats = new ArrayList<>(); - for (Map row : actionStatsData) { - LogStatisticsVO.ActionStatVO stat = new LogStatisticsVO.ActionStatVO(); - stat.setAction((String) row.get("action")); - stat.setCount(((Number) row.get("count")).longValue()); - actionStats.add(stat); - } - vo.setActionStats(actionStats); - - // 获取按天统计 - List> dailyStatsData = sysLogMapper.getDailyStats(days); - List dailyStats = new ArrayList<>(); - for (Map row : dailyStatsData) { - LogStatisticsVO.DailyStatVO stat = new LogStatisticsVO.DailyStatVO(); - stat.setDate(row.get("date").toString()); - stat.setCount(((Number) row.get("count")).longValue()); - dailyStats.add(stat); - } - vo.setDailyStats(dailyStats); - - return vo; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public int deleteByIds(List ids, Long tenantId) { - if (ids == null || ids.isEmpty()) { - return 0; - } - - // 验证所有日志都属于该租户 - List logs = this.listByIds(ids); - for (SysLog log : logs) { - if (!log.getTenantId().equals(tenantId)) { - throw new BusinessException("无权删除其他租户的日志"); - } - } - - return this.removeByIds(ids) ? logs.size() : 0; - } - - @Override - @Transactional(rollbackFor = Exception.class) - public int cleanOldLogs(Integer daysToKeep, Long tenantId) { - if (daysToKeep == null) { - daysToKeep = 90; - } - - LocalDateTime cutoffDate = LocalDateTime.now().minusDays(daysToKeep); - return sysLogMapper.deleteOldLogs(cutoffDate); - } - - private LogVO convertToVO(SysLog sysLog) { - LogVO vo = new LogVO(); - vo.setId(sysLog.getId()); - vo.setTenantId(sysLog.getTenantId()); - vo.setUserId(sysLog.getUserId()); - vo.setUsername(sysLog.getUsername()); - vo.setModule(sysLog.getModule()); - vo.setAction(sysLog.getAction()); - vo.setContent(sysLog.getContent()); - vo.setIp(sysLog.getIp()); - vo.setUserAgent(sysLog.getUserAgent()); - vo.setRequestMethod(sysLog.getRequestMethod()); - vo.setRequestUrl(sysLog.getRequestUrl()); - vo.setDuration(sysLog.getDuration()); - vo.setStatus(sysLog.getStatus()); - vo.setErrorMessage(sysLog.getErrorMessage()); - vo.setCreateTime(sysLog.getCreateTime()); - return vo; - } - - private LocalDateTime parseDateTime(String dateStr, LocalTime defaultTime) { - if (dateStr == null || dateStr.isEmpty()) { - return null; - } - try { - LocalDate date = LocalDate.parse(dateStr, DateTimeFormatter.ISO_LOCAL_DATE); - return date.atTime(defaultTime); - } catch (Exception e) { - log.warn("日期解析失败:{}", dateStr); - return null; - } - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java deleted file mode 100644 index f4e94be..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/TeacherServiceImpl.java +++ /dev/null @@ -1,307 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.dto.teacher.CreateTeacherDTO; -import com.lesingle.creation.dto.teacher.UpdateTeacherDTO; -import com.lesingle.creation.entity.Department; -import com.lesingle.creation.entity.Teacher; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.mapper.TeacherMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.service.DepartmentService; -import com.lesingle.creation.service.TeacherService; -import com.lesingle.creation.vo.teacher.TeacherVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * 教师服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class TeacherServiceImpl extends ServiceImpl implements TeacherService { - - private final TeacherMapper teacherMapper; - private final UserMapper userMapper; - private final DepartmentService departmentService; - private final PasswordEncoder passwordEncoder; - - @Override - @Transactional(rollbackFor = Exception.class) - public TeacherVO create(CreateTeacherDTO dto, Long tenantId, Long creatorId) { - // 检查用户名是否已存在 - User existingUser = userMapper.selectByUsername(dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("用户名已存在"); - } - - // 检查工号是否已存在 - Teacher existingTeacher = teacherMapper.selectByEmployeeNo(tenantId, dto.getEmployeeNo()); - if (existingTeacher != null) { - throw new BusinessException("工号已存在"); - } - - // 检查部门是否存在 - Department department = departmentService.getById(dto.getDepartmentId()); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - - // 创建用户账号 - User user = new User(); - user.setTenantId(tenantId); - user.setUsername(dto.getUsername()); - user.setPassword(passwordEncoder.encode(dto.getPassword())); - user.setNickname(dto.getNickname()); - user.setEmail(dto.getEmail()); - user.setAvatar(dto.getAvatar()); - user.setUserType("teacher"); // 教师用户 - user.setStatus("active"); - user.setUserSource("admin_created"); - - userMapper.insert(user); - log.info("创建用户账号成功,ID={}, 用户名={}", user.getId(), dto.getUsername()); - - // 创建教师信息 - Teacher teacher = new Teacher(); - teacher.setTenantId(tenantId); - teacher.setUserId(user.getId()); - teacher.setDepartmentId(dto.getDepartmentId()); - teacher.setEmployeeNo(dto.getEmployeeNo()); - teacher.setPhone(dto.getPhone()); - teacher.setIdCard(dto.getIdCard()); - teacher.setGender(dto.getGender()); - teacher.setBirthDate(dto.getBirthDate()); - teacher.setHireDate(dto.getHireDate()); - teacher.setSubject(dto.getSubject()); - teacher.setTitle(dto.getTitle()); - teacher.setDescription(dto.getDescription()); - teacher.setValidState(1); - - teacherMapper.insert(teacher); - log.info("创建教师成功,ID={}, 工号={}", teacher.getId(), dto.getEmployeeNo()); - - return convertToVO(teacher, user, department); - } - - @Override - public List list(Long tenantId, Long departmentId, String nickname, String username) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .eq(Teacher::getTenantId, tenantId) - .eq(Teacher::getDeleted, 0) - .eq(departmentId != null, Teacher::getDepartmentId, departmentId) - .orderByDesc(Teacher::getCreateTime); - - List teachers = this.list(wrapper); - - // 过滤用户名和昵称 - if (username != null || nickname != null) { - List userIds = teachers.stream().map(Teacher::getUserId).collect(Collectors.toList()); - LambdaQueryWrapper userWrapper = new LambdaQueryWrapper() - .in(User::getId, userIds) - .eq(User::getDeleted, 0); - - if (username != null && !username.isEmpty()) { - userWrapper.like(User::getUsername, username); - } - if (nickname != null && !nickname.isEmpty()) { - userWrapper.like(User::getNickname, nickname); - } - - List users = userMapper.selectList(userWrapper); - List validUserIds = users.stream().map(User::getId).collect(Collectors.toList()); - - teachers = teachers.stream() - .filter(t -> validUserIds.contains(t.getUserId())) - .collect(Collectors.toList()); - } - - // 转换为 VO - return teachers.stream() - .map(teacher -> { - User user = userMapper.selectById(teacher.getUserId()); - Department dept = departmentService.getById(teacher.getDepartmentId()); - return convertToVO(teacher, user, dept); - }) - .collect(Collectors.toList()); - } - - @Override - public TeacherVO getDetail(Long id, Long tenantId) { - Teacher teacher = this.getById(id); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - User user = userMapper.selectById(teacher.getUserId()); - Department department = departmentService.getById(teacher.getDepartmentId()); - - return convertToVO(teacher, user, department); - } - - @Override - public TeacherVO getByUserId(Long userId, Long tenantId) { - Teacher teacher = teacherMapper.selectByUserId(userId); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - User user = userMapper.selectById(teacher.getUserId()); - Department department = departmentService.getById(teacher.getDepartmentId()); - - return convertToVO(teacher, user, department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public TeacherVO update(Long id, UpdateTeacherDTO dto, Long tenantId, Long modifierId) { - Teacher teacher = this.getById(id); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - // 检查工号是否已被其他教师使用 - if (dto.getEmployeeNo() != null) { - Teacher existingTeacher = teacherMapper.selectByEmployeeNo(tenantId, dto.getEmployeeNo()); - if (existingTeacher != null && !existingTeacher.getId().equals(id)) { - throw new BusinessException("工号已存在"); - } - teacher.setEmployeeNo(dto.getEmployeeNo()); - } - - // 更新教师信息 - if (dto.getDepartmentId() != null) { - Department department = departmentService.getById(dto.getDepartmentId()); - if (department == null || !department.getTenantId().equals(tenantId)) { - throw new BusinessException("部门不存在"); - } - teacher.setDepartmentId(dto.getDepartmentId()); - } - if (dto.getPhone() != null) { - teacher.setPhone(dto.getPhone()); - } - if (dto.getIdCard() != null) { - teacher.setIdCard(dto.getIdCard()); - } - if (dto.getGender() != null) { - teacher.setGender(dto.getGender()); - } - if (dto.getBirthDate() != null) { - teacher.setBirthDate(dto.getBirthDate()); - } - if (dto.getHireDate() != null) { - teacher.setHireDate(dto.getHireDate()); - } - if (dto.getSubject() != null) { - teacher.setSubject(dto.getSubject()); - } - if (dto.getTitle() != null) { - teacher.setTitle(dto.getTitle()); - } - if (dto.getDescription() != null) { - teacher.setDescription(dto.getDescription()); - } - if (dto.getValidState() != null) { - teacher.setValidState(dto.getValidState()); - } - - // 更新用户信息(如果有) - if (dto.getNickname() != null || dto.getEmail() != null || dto.getAvatar() != null) { - User user = userMapper.selectById(teacher.getUserId()); - if (user != null) { - if (dto.getNickname() != null) { - user.setNickname(dto.getNickname()); - } - if (dto.getEmail() != null) { - user.setEmail(dto.getEmail()); - } - if (dto.getAvatar() != null) { - user.setAvatar(dto.getAvatar()); - } - userMapper.updateById(user); - } - } - - this.updateById(teacher); - log.info("更新教师成功,ID={}", id); - - User user = userMapper.selectById(teacher.getUserId()); - Department department = departmentService.getById(teacher.getDepartmentId()); - return convertToVO(teacher, user, department); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - Teacher teacher = this.getById(id); - if (teacher == null || !teacher.getTenantId().equals(tenantId)) { - throw new BusinessException("教师不存在"); - } - - // 逻辑删除教师 - teacher.setDeleted(1); - this.updateById(teacher); - - // 同时禁用关联的用户账号 - User user = userMapper.selectById(teacher.getUserId()); - if (user != null) { - user.setStatus("disabled"); // 禁用状态 - userMapper.updateById(user); - } - - log.info("删除教师成功,ID={}, 用户 ID={}", id, teacher.getUserId()); - } - - /** - * 转换为 VO - */ - private TeacherVO convertToVO(Teacher teacher, User user, Department department) { - TeacherVO vo = new TeacherVO(); - vo.setId(teacher.getId()); - vo.setUserId(teacher.getUserId()); - vo.setTenantId(teacher.getTenantId()); - vo.setDepartmentId(teacher.getDepartmentId()); - vo.setEmployeeNo(teacher.getEmployeeNo()); - vo.setPhone(teacher.getPhone()); - vo.setIdCard(teacher.getIdCard()); - vo.setGender(teacher.getGender()); - vo.setBirthDate(teacher.getBirthDate()); - vo.setHireDate(teacher.getHireDate()); - vo.setSubject(teacher.getSubject()); - vo.setTitle(teacher.getTitle()); - vo.setDescription(teacher.getDescription()); - vo.setValidState(teacher.getValidState()); - vo.setCreateTime(teacher.getCreateTime()); - vo.setUpdateTime(teacher.getUpdateTime()); - - // 用户信息 - if (user != null) { - TeacherVO.UserInfo userInfo = new TeacherVO.UserInfo(); - userInfo.setUsername(user.getUsername()); - userInfo.setNickname(user.getNickname()); - userInfo.setEmail(user.getEmail()); - userInfo.setAvatar(user.getAvatar()); - vo.setUserInfo(userInfo); - } - - // 部门信息 - if (department != null) { - TeacherVO.DepartmentInfo deptInfo = new TeacherVO.DepartmentInfo(); - deptInfo.setId(department.getId()); - deptInfo.setName(department.getName()); - deptInfo.setCode(department.getCode()); - vo.setDepartment(deptInfo); - } - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/TenantMenuServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/TenantMenuServiceImpl.java deleted file mode 100644 index 8732a05..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/TenantMenuServiceImpl.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.entity.TenantMenu; -import com.lesingle.creation.mapper.TenantMenuMapper; -import com.lesingle.creation.service.TenantMenuService; -import org.springframework.stereotype.Service; - -/** - * 租户菜单服务实现类 - */ -@Service -public class TenantMenuServiceImpl extends ServiceImpl implements TenantMenuService { - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/TenantServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/TenantServiceImpl.java deleted file mode 100644 index a264552..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/TenantServiceImpl.java +++ /dev/null @@ -1,293 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.tenant.CreateTenantDTO; -import com.lesingle.creation.dto.tenant.UpdateTenantDTO; -import com.lesingle.creation.entity.Tenant; -import com.lesingle.creation.entity.TenantMenu; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.mapper.TenantMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.service.TenantMenuService; -import com.lesingle.creation.service.TenantService; -import com.lesingle.creation.vo.tenant.TenantDetailVO; -import com.lesingle.creation.vo.tenant.TenantListVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 租户服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class TenantServiceImpl extends ServiceImpl implements TenantService { - - private final TenantMapper tenantMapper; - private final TenantMenuService tenantMenuService; - private final UserMapper userMapper; - - @Override - @Transactional(rollbackFor = Exception.class) - public TenantDetailVO create(CreateTenantDTO dto, Long creatorId) { - log.info("开始创建租户,租户编码:{}", dto.getCode()); - - // 检查租户编码是否已存在 - Tenant existingTenant = tenantMapper.selectByCode(dto.getCode()); - if (existingTenant != null) { - throw new BusinessException("租户编码已存在"); - } - - // 如果提供了域名,检查域名是否已存在 - if (dto.getDomain() != null && !dto.getDomain().isEmpty()) { - Tenant existingDomain = tenantMapper.selectByDomain(dto.getDomain()); - if (existingDomain != null) { - throw new BusinessException("租户域名已存在"); - } - } - - // 创建租户 - Tenant tenant = new Tenant(); - tenant.setName(dto.getName()); - tenant.setCode(dto.getCode()); - tenant.setDomain(dto.getDomain()); - tenant.setDescription(dto.getDescription()); - tenant.setTenantType(dto.getTenantType() != null ? dto.getTenantType() : "other"); - tenant.setValidState(1); - tenant.setCreateBy(creatorId != null ? String.valueOf(creatorId) : "system"); - - tenantMapper.insert(tenant); - log.info("租户创建成功,租户 ID: {}", tenant.getId()); - - // 如果提供了菜单 ID,创建菜单关联 - if (!CollectionUtils.isEmpty(dto.getMenuIds())) { - List tenantMenus = dto.getMenuIds().stream() - .map(menuId -> { - TenantMenu tm = new TenantMenu(); - tm.setTenantId(tenant.getId()); - tm.setMenuId(menuId); - return tm; - }) - .collect(Collectors.toList()); - tenantMenuService.saveBatch(tenantMenus); - log.info("租户菜单关联创建成功,菜单数量:{}", dto.getMenuIds().size()); - } - - return convertToDetailVO(tenant); - } - - @Override - public Page pageList(int page, int pageSize) { - log.info("分页查询租户列表,页码:{}, 每页大小:{}", page, pageSize); - - Page tenantPage = new Page<>(page, pageSize); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.orderByDesc(Tenant::getCreateTime); - - Page resultPage = tenantMapper.selectPage(tenantPage, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public TenantDetailVO detail(Long id) { - log.info("查询租户详情,租户 ID: {}", id); - - Tenant tenant = tenantMapper.selectById(id); - if (tenant == null) { - throw new BusinessException("租户不存在"); - } - - return convertToDetailVO(tenant); - } - - @Override - public TenantDetailVO getByCode(String code) { - log.info("根据编码查询租户,编码:{}", code); - - Tenant tenant = tenantMapper.selectByCode(code); - if (tenant == null) { - throw new BusinessException("租户不存在"); - } - - return convertToDetailVO(tenant); - } - - @Override - public TenantDetailVO getByDomain(String domain) { - log.info("根据域名查询租户,域名:{}", domain); - - Tenant tenant = tenantMapper.selectByDomain(domain); - if (tenant == null) { - throw new BusinessException("租户不存在"); - } - - return convertToDetailVO(tenant); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public TenantDetailVO update(Long id, UpdateTenantDTO dto, Long modifierId) { - log.info("更新租户,租户 ID: {}, 修改人 ID: {}", id, modifierId); - - // 检查租户是否存在 - Tenant existingTenant = tenantMapper.selectById(id); - if (existingTenant == null) { - throw new BusinessException("租户不存在"); - } - - // 如果更新了 code,检查是否冲突 - if (dto.getCode() != null && !dto.getCode().isEmpty()) { - Tenant conflictTenant = tenantMapper.selectByCodeExclude(dto.getCode(), id); - if (conflictTenant != null) { - throw new BusinessException("租户编码已存在"); - } - } - - // 如果更新了 domain,检查是否冲突 - if (dto.getDomain() != null && !dto.getDomain().isEmpty()) { - Tenant conflictDomain = tenantMapper.selectByDomainExclude(dto.getDomain(), id); - if (conflictDomain != null) { - throw new BusinessException("租户域名已存在"); - } - } - - // 更新租户信息 - Tenant tenant = new Tenant(); - tenant.setId(id); - tenant.setName(dto.getName()); - tenant.setCode(dto.getCode()); - tenant.setDomain(dto.getDomain()); - tenant.setDescription(dto.getDescription()); - tenant.setValidState(dto.getValidState()); - tenant.setUpdateBy(modifierId != null ? String.valueOf(modifierId) : "system"); - - tenantMapper.updateById(tenant); - log.info("租户更新成功,租户 ID: {}", id); - - // 如果提供了 menuIds,更新菜单关联 - if (dto.getMenuIds() != null) { - // 先删除现有菜单关联 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(TenantMenu::getTenantId, id); - tenantMenuService.remove(wrapper); - log.info("已删除租户原有菜单关联"); - - // 创建新的菜单关联 - if (!dto.getMenuIds().isEmpty()) { - List tenantMenus = dto.getMenuIds().stream() - .map(menuId -> { - TenantMenu tm = new TenantMenu(); - tm.setTenantId(id); - tm.setMenuId(menuId); - return tm; - }) - .collect(Collectors.toList()); - tenantMenuService.saveBatch(tenantMenus); - log.info("租户新菜单关联创建成功,菜单数量:{}", dto.getMenuIds().size()); - } - } - - return convertToDetailVO(tenantMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id) { - log.info("删除租户,租户 ID: {}", id); - - // 检查租户是否存在 - Tenant tenant = tenantMapper.selectById(id); - if (tenant == null) { - throw new BusinessException("租户不存在"); - } - - // 检查是否为超级租户 - if (tenant.getIsSuper() != null && tenant.getIsSuper() == 1) { - throw new BusinessException("不能删除超级租户"); - } - - // 删除租户(逻辑删除) - tenantMapper.deleteById(id); - log.info("租户删除成功,租户 ID: {}", id); - } - - @Override - public List getTenantMenus(Long tenantId) { - log.info("获取租户菜单,租户 ID: {}", tenantId); - - // 检查租户是否存在 - Tenant tenant = tenantMapper.selectById(tenantId); - if (tenant == null) { - throw new BusinessException("租户不存在"); - } - - // TODO: 实现获取租户菜单树逻辑 - return new ArrayList<>(); - } - - /** - * 转换为详情 VO - */ - private TenantDetailVO convertToDetailVO(Tenant tenant) { - TenantDetailVO vo = new TenantDetailVO(); - vo.setId(tenant.getId()); - vo.setName(tenant.getName()); - vo.setCode(tenant.getCode()); - vo.setDomain(tenant.getDomain()); - vo.setDescription(tenant.getDescription()); - vo.setIsSuper(tenant.getIsSuper()); - vo.setTenantType(tenant.getTenantType()); - vo.setValidState(tenant.getValidState()); - vo.setCreateBy(tenant.getCreateBy()); - vo.setCreateTime(tenant.getCreateTime()); - vo.setUpdateBy(tenant.getUpdateBy()); - vo.setUpdateTime(tenant.getUpdateTime()); - - // 统计用户数量和角色数量(需要时实现) - vo.setUserCount(0); - vo.setRoleCount(0); - - return vo; - } - - /** - * 转换为列表 VO - */ - private TenantListVO convertToListVO(Tenant tenant) { - TenantListVO vo = new TenantListVO(); - vo.setId(tenant.getId()); - vo.setName(tenant.getName()); - vo.setCode(tenant.getCode()); - vo.setDomain(tenant.getDomain()); - vo.setDescription(tenant.getDescription()); - vo.setIsSuper(tenant.getIsSuper()); - vo.setTenantType(tenant.getTenantType()); - vo.setValidState(tenant.getValidState()); - vo.setCreateTime(tenant.getCreateTime()); - - // 统计用户数量和角色数量(需要时实现) - vo.setUserCount(0); - vo.setRoleCount(0); - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/UserDetailsServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/UserDetailsServiceImpl.java deleted file mode 100644 index 3460de2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/UserDetailsServiceImpl.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.lesingle.creation.common.security.UserPrincipal; -import com.lesingle.creation.entity.Permission; -import com.lesingle.creation.entity.Tenant; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.entity.UserRole; -import com.lesingle.creation.entity.RolePermission; -import com.lesingle.creation.mapper.TenantMapper; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.mapper.UserRoleMapper; -import com.lesingle.creation.mapper.RolePermissionMapper; -import com.lesingle.creation.mapper.PermissionMapper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.stereotype.Service; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Spring Security UserDetailsService 实现类 - * 用于加载用户信息进行认证 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class UserDetailsServiceImpl implements UserDetailsService { - - private final UserMapper userMapper; - private final TenantMapper tenantMapper; - private final UserRoleMapper userRoleMapper; - private final RolePermissionMapper rolePermissionMapper; - private final PermissionMapper permissionMapper; - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - log.debug("加载用户信息:{}", username); - - // 支持通过用户 ID 或用户名查询 - User user; - try { - // 尝试通过用户 ID 查询(JWT token 中 subject 是用户 ID) - Long userId = Long.parseLong(username); - user = userMapper.selectById(userId); - if (user != null && user.getDeleted() == 0) { - log.debug("通过用户 ID 找到用户:{}, username: {}", userId, user.getUsername()); - } else { - // 如果通过 ID 没找到,尝试通过用户名查询 - List users = userMapper.selectList(new LambdaQueryWrapper() - .eq(User::getUsername, username) - .eq(User::getDeleted, 0)); - if (users.size() > 1) { - throw new UsernameNotFoundException("存在同名用户,请使用用户ID进行认证"); - } - user = users.isEmpty() ? null : users.get(0); - log.debug("通过用户名查询用户:{}, 结果:{}", username, user != null ? "找到" : "未找到"); - } - } catch (NumberFormatException e) { - // 不是数字,通过用户名查询 - List users = userMapper.selectList(new LambdaQueryWrapper() - .eq(User::getUsername, username) - .eq(User::getDeleted, 0)); - if (users.size() > 1) { - throw new UsernameNotFoundException("存在同名用户,请使用用户ID进行认证"); - } - user = users.isEmpty() ? null : users.get(0); - log.debug("通过用户名查询用户:{}, 结果:{}", username, user != null ? "找到" : "未找到"); - } - - if (user == null) { - log.warn("用户不存在:{}", username); - throw new UsernameNotFoundException("用户不存在:" + username); - } - - // 查询租户信息 - Tenant tenant = tenantMapper.selectById(user.getTenantId()); - String tenantCode = tenant != null ? tenant.getCode() : "default"; - - // 查询用户角色 - List userRoles = userRoleMapper.selectList(new LambdaQueryWrapper() - .eq(UserRole::getUserId, user.getId())); - - // 查询角色权限 - List permissionCodes = new ArrayList<>(); - if (!userRoles.isEmpty()) { - List roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList()); - List rolePermissions = rolePermissionMapper.selectList( - new LambdaQueryWrapper() - .in(RolePermission::getRoleId, roleIds) - ); - - if (!rolePermissions.isEmpty()) { - List permissionIds = rolePermissions.stream() - .map(RolePermission::getPermissionId) - .collect(Collectors.toList()); - List permissions = permissionMapper.selectList( - new LambdaQueryWrapper() - .in(Permission::getId, permissionIds) - .eq(Permission::getDeleted, 0) - ); - permissionCodes = permissions.stream() - .map(Permission::getCode) - .collect(Collectors.toList()); - } - } - - // 构建 authorities - List authorities = permissionCodes.stream() - .map(code -> new SimpleGrantedAuthority(code)) - .collect(Collectors.toList()); - - log.debug("用户 {} 的权限列表:{}", user.getUsername(), permissionCodes); - - // 构建 UserPrincipal 对象(包含用户 ID、租户 ID、租户编码等信息) - UserPrincipal userPrincipal = new UserPrincipal( - user.getId(), - user.getUsername(), - user.getPassword(), - authorities, - user.getTenantId(), - tenantCode, - "platform".equals(tenantCode) // platform 租户为超级租户 - ); - - log.debug("用户加载成功:{}, 租户 ID: {}", user.getUsername(), user.getTenantId()); - - return userPrincipal; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java b/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java deleted file mode 100644 index a067db9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/service/impl/UserServiceImpl.java +++ /dev/null @@ -1,345 +0,0 @@ -package com.lesingle.creation.service.impl; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.dto.user.CreateUserDTO; -import com.lesingle.creation.dto.user.UpdateUserDTO; -import com.lesingle.creation.dto.user.UserQueryDTO; -import com.lesingle.creation.entity.User; -import com.lesingle.creation.entity.UserRole; -import com.lesingle.creation.mapper.UserMapper; -import com.lesingle.creation.mapper.UserRoleMapper; -import com.lesingle.creation.service.UserService; -import com.lesingle.creation.vo.user.UserDetailVO; -import com.lesingle.creation.vo.user.UserListVO; -import com.lesingle.creation.vo.user.UserStatsVO; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.StringUtils; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -/** - * 用户服务实现类 - */ -@Slf4j -@Service -@RequiredArgsConstructor -public class UserServiceImpl extends ServiceImpl implements UserService { - - private final UserMapper userMapper; - private final UserRoleMapper userRoleMapper; - private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - - @Override - @Transactional(rollbackFor = Exception.class) - public UserDetailVO create(CreateUserDTO dto, Long tenantId, Long operatorId) { - log.info("开始创建用户,用户名:{}", dto.getUsername()); - - // 检查用户名是否已存在 - User existingUser = userMapper.selectByusername(tenantId, dto.getUsername()); - if (existingUser != null) { - throw new BusinessException("用户名已存在"); - } - - // 如果提供了邮箱,检查邮箱是否已存在 - if (StringUtils.hasText(dto.getEmail())) { - User existingEmail = userMapper.selectByEmail(tenantId, dto.getEmail()); - if (existingEmail != null) { - throw new BusinessException("邮箱已被使用"); - } - } - - // 如果提供了手机号,检查手机号是否已存在 - if (StringUtils.hasText(dto.getPhone())) { - User existingPhone = userMapper.selectByPhone(dto.getPhone()); - if (existingPhone != null) { - throw new BusinessException("手机号已被使用"); - } - } - - // 创建用户 - User user = new User(); - user.setTenantId(tenantId); - user.setUsername(dto.getUsername()); - user.setPassword(passwordEncoder.encode(dto.getPassword())); - user.setNickname(dto.getNickname()); - user.setEmail(dto.getEmail()); - user.setPhone(dto.getPhone()); - user.setGender(dto.getGender()); - user.setAvatar(dto.getAvatar()); - user.setStatus(dto.getStatus() != null ? dto.getStatus() : "enabled"); - user.setValidState(1); - user.setCreateBy(String.valueOf(operatorId)); - - userMapper.insert(user); - log.info("用户创建成功,用户 ID: {}", user.getId()); - - // 如果提供了角色 ID,创建角色关联 - if (dto.getRoleIds() != null && !dto.getRoleIds().isEmpty()) { - List userRoles = dto.getRoleIds().stream() - .map(roleId -> { - UserRole ur = new UserRole(); - ur.setUserId(user.getId()); - ur.setRoleId(roleId); - return ur; - }) - .collect(Collectors.toList()); - userRoleMapper.insertBatch(userRoles); - log.info("用户角色关联创建成功,角色数量:{}", dto.getRoleIds().size()); - } - - return convertToDetailVO(user); - } - - @Override - public Page pageList(UserQueryDTO queryDTO, Long tenantId, boolean isSuperTenant) { - log.info("分页查询用户列表,页码:{}, 每页大小:{}", queryDTO.getPage(), queryDTO.getPageSize()); - - Page userPage = new Page<>(queryDTO.getPage(), queryDTO.getPageSize()); - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - - // 超级租户可以查询所有用户,普通租户只能查询本租户用户 - if (!isSuperTenant) { - wrapper.eq(User::getTenantId, tenantId); - } - - // 关键字查询 - if (StringUtils.hasText(queryDTO.getKeyword())) { - wrapper.and(w -> w - .like(User::getUsername, queryDTO.getKeyword()) - .or() - .like(User::getNickname, queryDTO.getKeyword()) - .or() - .like(User::getEmail, queryDTO.getKeyword()) - .or() - .like(User::getPhone, queryDTO.getKeyword()) - ); - } - - // 用户类型筛选 - if (StringUtils.hasText(queryDTO.getUserType())) { - wrapper.eq(User::getUserType, queryDTO.getUserType()); - } - - // 用户来源筛选 - if (StringUtils.hasText(queryDTO.getUserSource())) { - wrapper.eq(User::getUserSource, queryDTO.getUserSource()); - } - - // 账号状态筛选 - if (StringUtils.hasText(queryDTO.getStatus())) { - wrapper.eq(User::getStatus, queryDTO.getStatus()); - } - - wrapper.orderByDesc(User::getCreateTime); - - Page resultPage = userMapper.selectPage(userPage, wrapper); - - // 转换为 VO - List voList = resultPage.getRecords().stream() - .map(this::convertToListVO) - .collect(Collectors.toList()); - - Page voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal()); - voPage.setRecords(voList); - - return voPage; - } - - @Override - public UserDetailVO detail(Long id, Long tenantId, boolean isSuperTenant) { - log.info("查询用户详情,用户 ID: {}", id); - - User user = userMapper.selectById(id); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - // 非超级租户只能查看本租户用户 - if (!isSuperTenant && !user.getTenantId().equals(tenantId)) { - throw new BusinessException("无权查看该用户信息"); - } - - return convertToDetailVO(user); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public UserDetailVO updateStatus(Long id, String status, Long operatorId) { - log.info("更新用户状态,用户 ID: {}, 新状态:{}", id, status); - - User user = userMapper.selectById(id); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - User updateUser = new User(); - updateUser.setId(id); - updateUser.setStatus(status); - updateUser.setUpdateBy(String.valueOf(operatorId)); - - userMapper.updateById(updateUser); - log.info("用户状态更新成功,用户 ID: {}", id); - - return convertToDetailVO(userMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public UserDetailVO update(Long id, UpdateUserDTO dto, Long tenantId) { - log.info("更新用户,用户 ID: {}", id); - - User existingUser = userMapper.selectById(id); - if (existingUser == null) { - throw new BusinessException("用户不存在"); - } - - // 如果更新了用户名,检查是否冲突 - if (StringUtils.hasText(dto.getUsername())) { - User conflictUser = userMapper.selectByusernameExclude(tenantId, dto.getUsername(), id); - if (conflictUser != null) { - throw new BusinessException("用户名已存在"); - } - } - - // 如果更新了邮箱,检查是否冲突 - if (StringUtils.hasText(dto.getEmail())) { - User conflictEmail = userMapper.selectByEmailExclude(tenantId, dto.getEmail(), id); - if (conflictEmail != null) { - throw new BusinessException("邮箱已被使用"); - } - } - - // 更新用户信息 - User user = new User(); - user.setId(id); - user.setUsername(dto.getUsername()); - if (StringUtils.hasText(dto.getPassword())) { - user.setPassword(passwordEncoder.encode(dto.getPassword())); - } - user.setNickname(dto.getNickname()); - user.setEmail(dto.getEmail()); - user.setPhone(dto.getPhone()); - user.setGender(dto.getGender()); - user.setAvatar(dto.getAvatar()); - user.setStatus(dto.getStatus()); - - userMapper.updateById(user); - log.info("用户更新成功,用户 ID: {}", id); - - // 如果提供了 roleIds,更新角色关联 - if (dto.getRoleIds() != null) { - // 先删除现有角色关联 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(UserRole::getUserId, id); - userRoleMapper.delete(wrapper); - log.info("已删除用户原有角色关联"); - - // 创建新的角色关联 - if (!dto.getRoleIds().isEmpty()) { - List userRoles = dto.getRoleIds().stream() - .map(roleId -> { - UserRole ur = new UserRole(); - ur.setUserId(id); - ur.setRoleId(roleId); - return ur; - }) - .collect(Collectors.toList()); - userRoleMapper.insertBatch(userRoles); - log.info("用户新角色关联创建成功,角色数量:{}", dto.getRoleIds().size()); - } - } - - return convertToDetailVO(userMapper.selectById(id)); - } - - @Override - @Transactional(rollbackFor = Exception.class) - public void delete(Long id, Long tenantId) { - log.info("删除用户,用户 ID: {}", id); - - User user = userMapper.selectById(id); - if (user == null) { - throw new BusinessException("用户不存在"); - } - - // 删除用户(逻辑删除) - userMapper.deleteById(id); - log.info("用户删除成功,用户 ID: {}", id); - } - - @Override - public UserStatsVO getStats() { - log.info("获取用户统计信息"); - - UserStatsVO stats = new UserStatsVO(); - - // TODO: 实现用户统计逻辑 - // 需要统计总用户数、平台用户数、机构用户数、评委用户数等 - - return stats; - } - - /** - * 转换为详情 VO - */ - private UserDetailVO convertToDetailVO(User user) { - UserDetailVO vo = new UserDetailVO(); - vo.setId(user.getId()); - vo.setTenantId(user.getTenantId()); - vo.setUsername(user.getUsername()); - vo.setNickname(user.getNickname()); - vo.setEmail(user.getEmail()); - vo.setPhone(user.getPhone()); - vo.setGender(user.getGender()); - vo.setAvatar(user.getAvatar()); - vo.setCity(user.getCity()); - vo.setBirthday(user.getBirthday()); - vo.setUserSource(user.getUserSource()); - vo.setUserType(user.getUserType()); - vo.setOrganization(user.getOrganization()); - vo.setStatus(user.getStatus()); - vo.setValidState(user.getValidState()); - vo.setCreateBy(user.getCreateBy()); - vo.setCreateTime(user.getCreateTime()); - vo.setUpdateBy(user.getUpdateBy()); - vo.setUpdateTime(user.getUpdateTime()); - - // TODO: 获取用户角色 - vo.setRoleIds(new ArrayList<>()); - vo.setRoleNames(new ArrayList<>()); - - return vo; - } - - /** - * 转换为列表 VO - */ - private UserListVO convertToListVO(User user) { - UserListVO vo = new UserListVO(); - vo.setId(user.getId()); - vo.setTenantId(user.getTenantId()); - vo.setUsername(user.getUsername()); - vo.setNickname(user.getNickname()); - vo.setEmail(user.getEmail()); - vo.setPhone(user.getPhone()); - vo.setGender(user.getGender()); - vo.setAvatar(user.getAvatar()); - vo.setUserType(user.getUserType()); - vo.setStatus(user.getStatus()); - vo.setCreateTime(user.getCreateTime()); - - // TODO: 获取用户角色名称 - vo.setRoleNames(new ArrayList<>()); - - return vo; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/util/SecurityUtils.java b/java-backend/src/main/java/com/lesingle/creation/util/SecurityUtils.java deleted file mode 100644 index 0057d4c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/util/SecurityUtils.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.lesingle.creation.util; - -import com.lesingle.creation.common.exception.BusinessException; -import com.lesingle.creation.common.security.UserPrincipal; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; - -/** - * 用户上下文工具类 - * - * @author lesingle - * @since 1.0.0 - */ -@Component -public class SecurityUtils { - - /** - * 获取当前登录用户 ID - * - * @return 用户 ID - */ - public Long getCurrentUserId() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - throw new BusinessException("用户未登录"); - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return ((UserPrincipal) principal).getUserId(); - } - throw new BusinessException("获取用户 ID 失败"); - } - - /** - * 获取当前登录用户 ID(字符串格式) - *

- * 用于 MyBatis-Plus 自动填充场景,非登录场景返回 "0" - * - * @return 用户 ID(字符串格式) - */ - public String getCurrentUserIdStr() { - try { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - return "0"; - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return String.valueOf(((UserPrincipal) principal).getUserId()); - } - return "0"; - } catch (Exception e) { - return "0"; - } - } - - /** - * 获取当前登录用户名 - *

- * 用于 MyBatis-Plus 自动填充审计字段,非登录场景返回 "system" - * - * @return 用户名 - */ - public String getCurrentUsernameStr() { - try { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - return "system"; - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return ((UserPrincipal) principal).getUsername(); - } - return "system"; - } catch (Exception e) { - return "system"; - } - } - - /** - * 获取当前租户 ID - * - * @return 租户 ID - */ - public Long getCurrentTenantId() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - throw new BusinessException("用户未登录"); - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return ((UserPrincipal) principal).getTenantId(); - } - throw new BusinessException("获取租户 ID 失败"); - } - - /** - * 获取当前登录用户名 - * - * @return 用户名 - */ - public String getCurrentUsername() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - throw new BusinessException("用户未登录"); - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return ((UserPrincipal) principal).getDisplayName(); - } - throw new BusinessException("获取用户名失败"); - } - - /** - * 判断当前用户是否为超级管理员 - * - * @return 是否为超级管理员 - */ - public boolean isSuperAdmin() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - return false; - } - - // 检查是否有 super_admin 角色 - return authentication.getAuthorities().stream() - .anyMatch(grantedAuthority -> "ROLE_super_admin".equals(grantedAuthority.getAuthority())); - } - - /** - * 判断当前用户是否为超级租户 - * - * @return 是否为超级租户 - */ - public boolean isSuperTenant() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - return false; - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return ((UserPrincipal) principal).isSuperTenant(); - } - return false; - } - - /** - * 获取当前租户编码 - * - * @return 租户编码 - */ - public String getCurrentTenantCode() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (authentication == null || !authentication.isAuthenticated()) { - throw new BusinessException("用户未登录"); - } - - Object principal = authentication.getPrincipal(); - if (principal instanceof UserPrincipal) { - return ((UserPrincipal) principal).getTenantCode(); - } - throw new BusinessException("获取租户编码失败"); - } - -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/ai3d/AI3DTaskVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/ai3d/AI3DTaskVO.java deleted file mode 100644 index 8fd3957..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/ai3d/AI3DTaskVO.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.lesingle.creation.vo.ai3d; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * AI 3D 任务 VO - */ -@Data -@Schema(description = "AI 3D 任务响应") -public class AI3DTaskVO { - - @Schema(description = "任务 ID") - private Long id; - - @Schema(description = "输入类型:text/image") - private String inputType; - - @Schema(description = "输入内容") - private String inputContent; - - @Schema(description = "生成类型:Normal/Geometry/LowPoly/Sketch") - private String generateType; - - @Schema(description = "任务状态:pending/processing/completed/failed/timeout") - private String status; - - @Schema(description = "生成的 3D 模型 URL") - private String resultUrl; - - @Schema(description = "预览图 URL") - private String previewUrl; - - @Schema(description = "生成的 3D 模型 URL 数组(JSON)") - private String resultUrls; - - @Schema(description = "预览图 URL 数组(JSON)") - private String previewUrls; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "外部 AI 服务任务 ID") - private String externalTaskId; - - @Schema(description = "已重试次数") - private Integer retryCount; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "完成时间") - private LocalDateTime completeTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/auth/LoginResponseVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/auth/LoginResponseVO.java deleted file mode 100644 index ee7f394..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/auth/LoginResponseVO.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.lesingle.creation.vo.auth; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 登录响应 VO - */ -@Data -@Schema(description = "登录响应") -public class LoginResponseVO { - - @Schema(description = "JWT Token") - private String token; - - @Schema(description = "用户信息") - private UserInfoVO user; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/auth/UserInfoVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/auth/UserInfoVO.java deleted file mode 100644 index 4f0e8f0..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/auth/UserInfoVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.auth; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 用户信息 VO - */ -@Data -@Schema(description = "用户信息") -public class UserInfoVO { - - @Schema(description = "用户 ID") - private Long id; - - @Schema(description = "用户名") - private String username; - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "租户编码") - private String tenantCode; - - @Schema(description = "角色编码列表") - private List roles; - - @Schema(description = "权限编码列表") - private List permissions; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/child/ChildVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/child/ChildVO.java deleted file mode 100644 index 4b8ef96..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/child/ChildVO.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.vo.child; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 子女响应 VO - */ -@Data -@Schema(description = "子女信息") -public class ChildVO { - - @Schema(description = "子女用户 ID") - private Long id; - - @Schema(description = "监护人用户 ID") - private Long parentId; - - @Schema(description = "用户名") - private String username; - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "性别:male/female") - private String gender; - - @Schema(description = "出生日期") - private LocalDate birthday; - - @Schema(description = "所在城市") - private String city; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "与监护人关系") - private String relationship; - - @Schema(description = "管控模式:full/control/free") - private String controlMode; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/config/ConfigDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/config/ConfigDetailVO.java deleted file mode 100644 index 0d14860..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/config/ConfigDetailVO.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.lesingle.creation.vo.config; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 配置详情 VO - */ -@Data -@Schema(description = "配置详情响应") -public class ConfigDetailVO { - - @Schema(description = "配置 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "配置键") - private String configKey; - - @Schema(description = "配置值") - private String configValue; - - @Schema(description = "配置名称") - private String configName; - - @Schema(description = "配置描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/config/ConfigListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/config/ConfigListVO.java deleted file mode 100644 index bd965b6..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/config/ConfigListVO.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.lesingle.creation.vo.config; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 配置列表 VO - */ -@Data -@Schema(description = "配置列表响应") -public class ConfigListVO { - - @Schema(description = "配置 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "配置键") - private String configKey; - - @Schema(description = "配置值") - private String configValue; - - @Schema(description = "配置名称") - private String configName; - - @Schema(description = "配置描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestAttachmentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestAttachmentVO.java deleted file mode 100644 index 3dc4fbf..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestAttachmentVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.vo.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 竞赛附件 VO - */ -@Data -@Schema(description = "竞赛附件响应") -public class ContestAttachmentVO { - - @Schema(description = "附件 ID") - private Long id; - - @Schema(description = "附件名称") - private String name; - - @Schema(description = "附件 URL") - private String url; - - @Schema(description = "附件类型") - private String type; - - @Schema(description = "文件大小(字节)") - private Long size; - - @Schema(description = "排序") - private Integer sort; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestDetailVO.java deleted file mode 100644 index 34c5206..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestDetailVO.java +++ /dev/null @@ -1,174 +0,0 @@ -package com.lesingle.creation.vo.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 竞赛详情 VO - */ -@Data -@Schema(description = "竞赛详情响应") -public class ContestDetailVO { - - @Schema(description = "竞赛 ID") - private Long id; - - @Schema(description = "竞赛名称") - private String contestName; - - @Schema(description = "竞赛类型:individual/team") - private String contestType; - - @Schema(description = "竞赛状态:unpublished/published") - private String contestState; - - @Schema(description = "进度状态:ongoing/finished") - private String status; - - @Schema(description = "当前阶段:unpublished/registering/submitting/reviewing/finished") - private String stage; - - @Schema(description = "竞赛开始时间") - private LocalDateTime startTime; - - @Schema(description = "竞赛结束时间") - private LocalDateTime endTime; - - @Schema(description = "线下地址") - private String address; - - @Schema(description = "竞赛详情") - private String content; - - @Schema(description = "授权租户 ID 列表") - private List contestTenants; - - @Schema(description = "封面 URL") - private String coverUrl; - - @Schema(description = "海报 URL") - private String posterUrl; - - @Schema(description = "联系人") - private String contactName; - - @Schema(description = "联系电话") - private String contactPhone; - - @Schema(description = "联系人二维码") - private String contactQrcode; - - @Schema(description = "主办单位列表") - private List organizers; - - @Schema(description = "协办单位列表") - private List coOrganizers; - - @Schema(description = "赞助单位列表") - private List sponsors; - - @Schema(description = "可见范围:public/designated/internal") - private String visibility; - - @Schema(description = "目标城市列表") - private List targetCities; - - @Schema(description = "最小年龄限制") - private Integer ageMin; - - @Schema(description = "最大年龄限制") - private Integer ageMax; - - @Schema(description = "报名开始时间") - private LocalDateTime registerStartTime; - - @Schema(description = "报名结束时间") - private LocalDateTime registerEndTime; - - @Schema(description = "报名状态:open/closed") - private String registerState; - - @Schema(description = "是否需要审核") - private Boolean requireAudit; - - @Schema(description = "允许报名的年级 ID 列表") - private List allowedGrades; - - @Schema(description = "允许报名的班级 ID 列表") - private List allowedClasses; - - @Schema(description = "团队最少成员数") - private Integer teamMinMembers; - - @Schema(description = "团队最多成员数") - private Integer teamMaxMembers; - - @Schema(description = "提交规则:once/resubmit") - private String submitRule; - - @Schema(description = "作品提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "作品提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "作品类型") - private String workType; - - @Schema(description = "作品要求说明") - private String workRequirement; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; - - @Schema(description = "评审开始时间") - private LocalDateTime reviewStartTime; - - @Schema(description = "评审结束时间") - private LocalDateTime reviewEndTime; - - @Schema(description = "赛果状态:unpublished/published") - private String resultState; - - @Schema(description = "结果发布时间") - private LocalDateTime resultPublishTime; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人 ID") - private Long creator; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "修改人 ID") - private Long modifier; - - @Schema(description = "更新时间") - private LocalDateTime modifyTime; - - @Schema(description = "报名人数") - private Integer registrationCount; - - @Schema(description = "作品数量") - private Integer worksCount; - - @Schema(description = "团队数量") - private Integer teamsCount; - - @Schema(description = "评委数量") - private Integer judgesCount; - - @Schema(description = "总作品数(已提交或评审中)") - private Integer totalWorksCount; - - @Schema(description = "已完成评审作品数") - private Integer reviewedCount; - - @Schema(description = "附件列表") - private List attachments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestListVO.java deleted file mode 100644 index 905e6e9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestListVO.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.lesingle.creation.vo.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 竞赛列表 VO - */ -@Data -@Schema(description = "竞赛列表响应") -public class ContestListVO { - - @Schema(description = "竞赛 ID") - private Long id; - - @Schema(description = "竞赛名称") - private String contestName; - - @Schema(description = "竞赛类型:individual/team") - private String contestType; - - @Schema(description = "竞赛状态:unpublished/published") - private String contestState; - - @Schema(description = "进度状态:ongoing/finished") - private String status; - - @Schema(description = "当前阶段:unpublished/registering/submitting/reviewing/finished") - private String stage; - - @Schema(description = "竞赛开始时间") - private LocalDateTime startTime; - - @Schema(description = "竞赛结束时间") - private LocalDateTime endTime; - - @Schema(description = "封面 URL") - private String coverUrl; - - @Schema(description = "海报 URL") - private String posterUrl; - - @Schema(description = "主办单位") - private String organizers; - - @Schema(description = "可见范围:public/designated/internal") - private String visibility; - - @Schema(description = "报名开始时间") - private LocalDateTime registerStartTime; - - @Schema(description = "报名结束时间") - private LocalDateTime registerEndTime; - - @Schema(description = "作品提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "作品提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "评审开始时间") - private LocalDateTime reviewStartTime; - - @Schema(description = "评审结束时间") - private LocalDateTime reviewEndTime; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "报名人数") - private Integer registrationCount; - - @Schema(description = "作品数量") - private Integer worksCount; - - @Schema(description = "团队数量") - private Integer teamsCount; - - @Schema(description = "评委数量") - private Integer judgesCount; - - @Schema(description = "总作品数") - private Integer totalWorksCount; - - @Schema(description = "已完成评审作品数") - private Integer reviewedCount; - - @Schema(description = "附件列表(前 5 个)") - private List attachments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestStatsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestStatsVO.java deleted file mode 100644 index 0149b05..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/contest/ContestStatsVO.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.lesingle.creation.vo.contest; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 竞赛统计 VO - */ -@Data -@Schema(description = "竞赛统计响应") -public class ContestStatsVO { - - @Schema(description = "总竞赛数") - private Integer total; - - @Schema(description = "未发布数") - private Integer unpublished; - - @Schema(description = "报名中数") - private Integer registering; - - @Schema(description = "作品提交中数") - private Integer submitting; - - @Schema(description = "评审中数") - private Integer reviewing; - - @Schema(description = "已完结数") - private Integer finished; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java deleted file mode 100644 index 983a69b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/department/DepartmentVO.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.lesingle.creation.vo.department; - -import com.fasterxml.jackson.annotation.JsonInclude; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 部门响应 VO - */ -@Data -@Schema(description = "部门响应") -@JsonInclude(JsonInclude.Include.NON_NULL) -public class DepartmentVO { - - @Schema(description = "部门 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "部门名称") - private String name; - - @Schema(description = "部门编码") - private String code; - - @Schema(description = "父部门 ID") - private Long parentId; - - @Schema(description = "部门描述") - private String description; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "子部门列表") - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictDetailVO.java deleted file mode 100644 index 35fa11c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictDetailVO.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.vo.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 字典详情 VO - */ -@Data -@Schema(description = "字典详情响应") -public class DictDetailVO { - - @Schema(description = "字典 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "字典名称") - private String name; - - @Schema(description = "字典编码") - private String code; - - @Schema(description = "字典描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "字典项列表") - private List items; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictItemVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictItemVO.java deleted file mode 100644 index 4f1753d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictItemVO.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lesingle.creation.vo.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 字典项 VO - */ -@Data -@Schema(description = "字典项响应") -public class DictItemVO { - - @Schema(description = "字典项 ID") - private Long id; - - @Schema(description = "字典 ID") - private Long dictId; - - @Schema(description = "字典项标签") - private String label; - - @Schema(description = "字典项值") - private String value; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictListVO.java deleted file mode 100644 index 2f4320e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/dict/DictListVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.vo.dict; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 字典列表 VO - */ -@Data -@Schema(description = "字典列表响应") -public class DictListVO { - - @Schema(description = "字典 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "字典名称") - private String name; - - @Schema(description = "字典编码") - private String code; - - @Schema(description = "字典描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java deleted file mode 100644 index 59e89fe..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/grade/GradeVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.grade; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 年级响应 VO - */ -@Data -@Schema(description = "年级响应") -public class GradeVO { - - @Schema(description = "年级 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "年级名称") - private String name; - - @Schema(description = "年级编码") - private String code; - - @Schema(description = "年级级别") - private Integer level; - - @Schema(description = "年级描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java deleted file mode 100644 index 3e2e46b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkDetailVO.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 作业详情 VO - */ -@Data -@Schema(description = "作业详情响应") -public class HomeworkDetailVO { - - @Schema(description = "作业 ID") - private Long id; - - @Schema(description = "作业名称") - private String name; - - @Schema(description = "作业内容(富文本)") - private String content; - - @Schema(description = "作业状态:unpublished/published") - private String status; - - @Schema(description = "发布时间") - private LocalDateTime publishTime; - - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "公开范围(班级 ID 数组 JSON)") - private String publishScope; - - @Schema(description = "评审规则 ID") - private Long reviewRuleId; - - @Schema(description = "提交人数") - private Integer submissionCount; - - @Schema(description = "已批改人数") - private Integer reviewedCount; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java deleted file mode 100644 index c90f3ad..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/HomeworkListVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 作业列表 VO - */ -@Data -@Schema(description = "作业列表响应") -public class HomeworkListVO { - - @Schema(description = "作业 ID") - private Long id; - - @Schema(description = "作业名称") - private String name; - - @Schema(description = "作业状态:unpublished/published") - private String status; - - @Schema(description = "发布时间") - private LocalDateTime publishTime; - - @Schema(description = "提交开始时间") - private LocalDateTime submitStartTime; - - @Schema(description = "提交结束时间") - private LocalDateTime submitEndTime; - - @Schema(description = "提交人数") - private Integer submissionCount; - - @Schema(description = "已批改人数") - private Integer reviewedCount; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java deleted file mode 100644 index ab19548..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewDimensionVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; - -/** - * 作业评审维度 VO - */ -@Data -@Schema(description = "作业评审维度响应") -public class ReviewDimensionVO { - - @Schema(description = "维度 ID") - private Long id; - - @Schema(description = "维度名称") - private String name; - - @Schema(description = "满分") - private BigDecimal maxScore; - - @Schema(description = "维度描述") - private String description; - - @Schema(description = "排序顺序") - private Integer sortOrder; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java deleted file mode 100644 index 9fedc2e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/ReviewRuleVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.util.List; - -/** - * 作业评审规则 VO - */ -@Data -@Schema(description = "作业评审规则响应") -public class ReviewRuleVO { - - @Schema(description = "规则 ID") - private Long id; - - @Schema(description = "规则名称") - private String ruleName; - - @Schema(description = "规则类型:default/custom") - private String ruleType; - - @Schema(description = "总分") - private BigDecimal totalScore; - - @Schema(description = "规则描述") - private String description; - - @Schema(description = "评审维度列表") - private List dimensions; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java deleted file mode 100644 index 68e464d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/homework/SubmissionVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.homework; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 作业提交 VO - */ -@Data -@Schema(description = "作业提交响应") -public class SubmissionVO { - - @Schema(description = "提交 ID") - private Long id; - - @Schema(description = "作业 ID") - private Long homeworkId; - - @Schema(description = "学生 ID") - private Long studentId; - - @Schema(description = "学生姓名") - private String studentName; - - @Schema(description = "提交内容") - private String content; - - @Schema(description = "提交附件列表(JSON 数组)") - private String attachments; - - @Schema(description = "提交状态:submitted/reviewing/returned") - private String status; - - @Schema(description = "提交时间") - private LocalDateTime submitTime; - - @Schema(description = "批改时间") - private LocalDateTime reviewTime; - - @Schema(description = "批改人 ID") - private Long reviewerId; - - @Schema(description = "批改评语") - private String reviewComment; - - @Schema(description = "批改分数") - private BigDecimal reviewScore; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/judge/JudgeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/judge/JudgeVO.java deleted file mode 100644 index 46b0e29..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/judge/JudgeVO.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.lesingle.creation.vo.judge; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; - -/** - * 评委 VO - */ -@Data -@Schema(description = "评委响应") -public class JudgeVO { - - @Schema(description = "评委 ID") - private Long id; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "评委用户 ID") - private Long judgeId; - - @Schema(description = "评委姓名") - private String judgeName; - - @Schema(description = "职称") - private String title; - - @Schema(description = "所属单位") - private String organization; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "专业领域") - private String specialty; - - @Schema(description = "权重", example = "1.0") - private BigDecimal weight; - - @Schema(description = "状态:1-活跃,2-不活跃") - private Integer status; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/log/LogStatisticsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/log/LogStatisticsVO.java deleted file mode 100644 index d6ac801..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/log/LogStatisticsVO.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.lesingle.creation.vo.log; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 日志统计响应 VO - */ -@Data -@Schema(description = "日志统计响应") -public class LogStatisticsVO { - - @Schema(description = "总日志数") - private Long totalCount; - - @Schema(description = "近期日志数") - private Long recentCount; - - @Schema(description = "统计天数") - private Integer days; - - @Schema(description = "按操作类型统计列表") - private List actionStats; - - @Schema(description = "按天统计列表") - private List dailyStats; - - /** - * 操作类型统计 VO - */ - @Data - @Schema(description = "操作类型统计") - public static class ActionStatVO { - @Schema(description = "操作类型") - private String action; - @Schema(description = "数量") - private Long count; - } - - /** - * 按天统计 VO - */ - @Data - @Schema(description = "按天统计") - public static class DailyStatVO { - @Schema(description = "日期") - private String date; - @Schema(description = "数量") - private Long count; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/log/LogVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/log/LogVO.java deleted file mode 100644 index e0c4d7b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/log/LogVO.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.lesingle.creation.vo.log; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 日志响应 VO - */ -@Data -@Schema(description = "日志响应") -public class LogVO { - - @Schema(description = "日志 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "用户名") - private String username; - - @Schema(description = "操作模块") - private String module; - - @Schema(description = "操作类型") - private String action; - - @Schema(description = "操作描述") - private String content; - - @Schema(description = "请求 IP") - private String ip; - - @Schema(description = "用户代理") - private String userAgent; - - @Schema(description = "请求方法") - private String requestMethod; - - @Schema(description = "请求 URL") - private String requestUrl; - - @Schema(description = "操作时长 (ms)") - private Long duration; - - @Schema(description = "操作状态") - private String status; - - @Schema(description = "错误信息") - private String errorMessage; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/menu/MenuDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/menu/MenuDetailVO.java deleted file mode 100644 index d6cf813..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/menu/MenuDetailVO.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.vo.menu; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 菜单详情 VO - */ -@Data -@Schema(description = "菜单详情响应") -public class MenuDetailVO { - - @Schema(description = "菜单 ID") - private Long id; - - @Schema(description = "菜单名称") - private String name; - - @Schema(description = "路由路径") - private String path; - - @Schema(description = "图标") - private String icon; - - @Schema(description = "组件路径") - private String component; - - @Schema(description = "父菜单 ID") - private Long parentId; - - @Schema(description = "权限编码") - private String permission; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/menu/MenuTreeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/menu/MenuTreeVO.java deleted file mode 100644 index 38ebdf2..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/menu/MenuTreeVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.vo.menu; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 菜单树 VO - */ -@Data -@Schema(description = "菜单树响应") -public class MenuTreeVO { - - @Schema(description = "菜单 ID") - private Long id; - - @Schema(description = "菜单名称") - private String name; - - @Schema(description = "路由路径") - private String path; - - @Schema(description = "图标") - private String icon; - - @Schema(description = "组件路径") - private String component; - - @Schema(description = "父菜单 ID") - private Long parentId; - - @Schema(description = "权限编码") - private String permission; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "子菜单列表") - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/notice/NoticeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/notice/NoticeVO.java deleted file mode 100644 index bd52f10..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/notice/NoticeVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.notice; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 公告 VO - */ -@Data -@Schema(description = "公告响应") -public class NoticeVO { - - @Schema(description = "公告 ID") - private Long id; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "公告标题") - private String title; - - @Schema(description = "公告内容") - private String content; - - @Schema(description = "公告类型:manual/system") - private String noticeType; - - @Schema(description = "优先级") - private Integer priority; - - @Schema(description = "发布时间") - private LocalDateTime publishTime; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/permission/PermissionDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/permission/PermissionDetailVO.java deleted file mode 100644 index 32bbc7c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/permission/PermissionDetailVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.permission; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 权限详情 VO - */ -@Data -@Schema(description = "权限详情响应") -public class PermissionDetailVO { - - @Schema(description = "权限 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "权限名称") - private String name; - - @Schema(description = "权限编码") - private String code; - - @Schema(description = "资源名称") - private String resource; - - @Schema(description = "操作类型") - private String action; - - @Schema(description = "权限描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/permission/PermissionListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/permission/PermissionListVO.java deleted file mode 100644 index 6748329..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/permission/PermissionListVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.permission; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 权限列表 VO - */ -@Data -@Schema(description = "权限列表响应") -public class PermissionListVO { - - @Schema(description = "权限 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "权限名称") - private String name; - - @Schema(description = "权限编码") - private String code; - - @Schema(description = "资源名称") - private String resource; - - @Schema(description = "操作类型") - private String action; - - @Schema(description = "权限描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/presetcomment/PresetCommentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/presetcomment/PresetCommentVO.java deleted file mode 100644 index 0cf99da..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/presetcomment/PresetCommentVO.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.lesingle.creation.vo.presetcomment; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; - -/** - * 预设评语 VO - */ -@Data -@Schema(description = "预设评语响应") -public class PresetCommentVO { - - @Schema(description = "评语 ID") - private Long id; - - @Schema(description = "活动 ID(为空表示通用评语)") - private Long contestId; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "评语内容") - private String content; - - @Schema(description = "评语类型:positive/neutral/negative") - private String type; - - @Schema(description = "适用分数范围最小值") - private BigDecimal scoreRangeMin; - - @Schema(description = "适用分数范围最大值") - private BigDecimal scoreRangeMax; - - @Schema(description = "排序") - private Integer sort; - - @Schema(description = "使用次数") - private Integer usageCount; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/publicuser/LoginResponseVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/publicuser/LoginResponseVO.java deleted file mode 100644 index 2ec178e..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/publicuser/LoginResponseVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.vo.publicuser; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 登录响应 VO - */ -@Data -@Schema(description = "登录响应") -public class LoginResponseVO { - - @Schema(description = "访问令牌") - private String accessToken; - - @Schema(description = "刷新令牌") - private String refreshToken; - - @Schema(description = "令牌类型") - private String tokenType; - - @Schema(description = "过期时间(秒)") - private Long expiresIn; - - @Schema(description = "用户信息") - private PublicUserVO user; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/publicuser/PublicUserVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/publicuser/PublicUserVO.java deleted file mode 100644 index 6143c6a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/publicuser/PublicUserVO.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.lesingle.creation.vo.publicuser; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 公众用户响应 VO - */ -@Data -@Schema(description = "公众用户信息") -public class PublicUserVO { - - @Schema(description = "用户 ID") - private Long id; - - @Schema(description = "用户名") - private String username; - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "手机号") - private String phone; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "性别:male/female") - private String gender; - - @Schema(description = "所在城市") - private String city; - - @Schema(description = "用户类型") - private String userType; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/registration/RegistrationStatsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/registration/RegistrationStatsVO.java deleted file mode 100644 index 081a177..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/registration/RegistrationStatsVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.vo.registration; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 报名统计 VO - */ -@Data -@Schema(description = "报名统计响应") -public class RegistrationStatsVO { - - @Schema(description = "总报名人数") - private Integer total; - - @Schema(description = "待审核人数") - private Integer pending; - - @Schema(description = "通过人数") - private Integer passed; - - @Schema(description = "驳回人数") - private Integer rejected; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/registration/RegistrationVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/registration/RegistrationVO.java deleted file mode 100644 index bc18b91..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/registration/RegistrationVO.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.lesingle.creation.vo.registration; - -import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 报名记录 VO - */ -@Data -@Schema(description = "报名记录响应") -public class RegistrationVO { - - @Schema(description = "报名 ID") - private Long id; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "参与类型:individual/team") - private String registrationType; - - @Schema(description = "团队 ID") - private Long teamId; - - @Schema(description = "团队名称") - private String teamName; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "用户账号") - private String accountNo; - - @Schema(description = "用户姓名") - private String accountName; - - @Schema(description = "审核状态:pending/passed/rejected") - private String registrationState; - - @Schema(description = "报名时间") - private LocalDateTime registrationTime; - - @Schema(description = "审核原因") - private String reason; - - @Schema(description = "操作人 ID") - private Long operator; - - @Schema(description = "操作时间") - private LocalDateTime operationDate; - - @Schema(description = "指导老师 ID") - private Long registrant; - - @Schema(description = "作品数量") - @JsonProperty("_count") - private WorkCount workCount; - - @Data - @Schema(description = "作品数量") - public static class WorkCount { - @Schema(description = "作品数量") - private Integer works; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/result/ResultVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/result/ResultVO.java deleted file mode 100644 index 8c0f04a..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/result/ResultVO.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.lesingle.creation.vo.result; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 竞赛结果 VO - */ -@Data -@Schema(description = "竞赛结果响应") -public class ResultVO { - - @Schema(description = "结果 ID") - private Long id; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "作品 ID") - private Long workId; - - @Schema(description = "作品标题") - private String workTitle; - - @Schema(description = "报名 ID") - private Long registrationId; - - @Schema(description = "参赛者姓名") - private String participantName; - - @Schema(description = "总分") - private BigDecimal totalScore; - - @Schema(description = "奖项等级") - private String awardLevel; - - @Schema(description = "获奖描述") - private String description; - - @Schema(description = "是否获奖") - private Boolean isWinner; - - @Schema(description = "公示状态:pending/published/withdrawn") - private String publicState; - - @Schema(description = "发布时间") - private LocalDateTime publishTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/FinalScoreVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/FinalScoreVO.java deleted file mode 100644 index 98a7286..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/FinalScoreVO.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; - -/** - * 最终得分 VO - */ -@Data -@Schema(description = "最终得分") -public class FinalScoreVO { - - @Schema(description = "作品 ID") - private Long workId; - - @Schema(description = "最终得分") - private BigDecimal finalScore; - - @Schema(description = "评分数量") - private Integer scoreCount; - - @Schema(description = "计算规则") - private String calculationRule; - - @Schema(description = "排名") - private Integer rank; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/JudgeContestVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/JudgeContestVO.java deleted file mode 100644 index 4f56231..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/JudgeContestVO.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 评委参与的活动 VO - */ -@Data -@Schema(description = "评委参与的活动") -public class JudgeContestVO { - - @Schema(description = "活动 ID") - private Long id; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "活动状态") - private String status; - - @Schema(description = "评审开始时间") - private java.time.LocalDateTime reviewStartTime; - - @Schema(description = "评审结束时间") - private java.time.LocalDateTime reviewEndTime; - - @Schema(description = "分配的作品数") - private Integer assignedWorksCount; - - @Schema(description = "已评分的作品数") - private Integer scoredWorksCount; - - @Schema(description = "待评分的作品数") - private Integer pendingWorksCount; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/JudgeWorkVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/JudgeWorkVO.java deleted file mode 100644 index 1f63dff..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/JudgeWorkVO.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 评委的作品列表 VO - */ -@Data -@Schema(description = "评委的作品") -public class JudgeWorkVO { - - @Schema(description = "作品 ID") - private Long id; - - @Schema(description = "作品编号") - private String workNo; - - @Schema(description = "作品标题") - private String title; - - @Schema(description = "分配状态") - private String assignmentStatus; - - @Schema(description = "评分状态") - private String scoreStatus; - - @Schema(description = "分配时间") - private java.time.LocalDateTime assignmentTime; - - @Schema(description = "参赛者姓名") - private String participantName; - - @Schema(description = "参赛者类型") - private String participantType; - - @Schema(description = "得分") - private java.math.BigDecimal score; - - @Schema(description = "评语") - private String comments; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewAssignmentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewAssignmentVO.java deleted file mode 100644 index 6d133c9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewAssignmentVO.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 评审分配 VO - */ -@Data -@Schema(description = "评审分配响应") -public class ReviewAssignmentVO { - - @Schema(description = "分配 ID") - private Long id; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "作品 ID") - private Long workId; - - @Schema(description = "作品标题") - private String workTitle; - - @Schema(description = "评委 ID") - private Long judgeId; - - @Schema(description = "评委姓名") - private String judgeName; - - @Schema(description = "分配状态:assigned/reviewing/completed") - private String status; - - @Schema(description = "分配时间") - private LocalDateTime assignTime; - - @Schema(description = "完成时间") - private LocalDateTime completeTime; - - @Schema(description = "评分 ID") - private Long scoreId; - - @Schema(description = "评分分数") - private java.math.BigDecimal score; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewProgressVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewProgressVO.java deleted file mode 100644 index 4808756..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewProgressVO.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 评审进度统计 VO - */ -@Data -@Schema(description = "评审进度统计") -public class ReviewProgressVO { - - @Schema(description = "活动信息") - private ContestInfo contest; - - @Schema(description = "评审摘要统计") - private ReviewSummary summary; - - @Schema(description = "进度百分比") - private Progress progress; - - @Schema(description = "评委进度列表") - private List judgeProgress; - - @Schema(description = "待分配作品列表") - private List unassignedWorks; - - @Schema(description = "待评审分配列表") - private List pendingAssignments; - - @Data - @Schema(description = "活动信息") - public static class ContestInfo { - @Schema(description = "活动 ID") - private Long id; - @Schema(description = "活动名称") - private String contestName; - @Schema(description = "评审开始时间") - private java.time.LocalDateTime reviewStartTime; - @Schema(description = "评审结束时间") - private java.time.LocalDateTime reviewEndTime; - } - - @Data - @Schema(description = "评审摘要统计") - public static class ReviewSummary { - @Schema(description = "总作品数") - private int totalWorks; - @Schema(description = "已分配作品数") - private int assignedWorksCount; - @Schema(description = "已评分作品数") - private int scoredWorksCount; - @Schema(description = "未分配作品数") - private int unassignedWorksCount; - @Schema(description = "评委总数") - private int totalJudges; - @Schema(description = "总分配数") - private int totalAssignments; - @Schema(description = "总评分数") - private int totalScores; - @Schema(description = "待评分数") - private int pendingScoresCount; - } - - @Data - @Schema(description = "进度百分比") - public static class Progress { - @Schema(description = "分配进度百分比") - private double assignmentProgress; - @Schema(description = "评分进度百分比") - private double scoringProgress; - @Schema(description = "总体进度百分比") - private double overallProgress; - } - - @Data - @Schema(description = "评委进度项") - public static class JudgeProgressItem { - @Schema(description = "评委 ID") - private Long judgeId; - @Schema(description = "评委姓名") - private String judgeName; - @Schema(description = "专业") - private String specialty; - @Schema(description = "权重") - private Double weight; - @Schema(description = "已分配数") - private int assignedCount; - @Schema(description = "已评分数") - private int scoredCount; - @Schema(description = "待评分数") - private int pendingCount; - @Schema(description = "进度百分比") - private double progress; - } - - @Data - @Schema(description = "待分配作品") - public static class UnassignedWork { - @Schema(description = "作品 ID") - private Long id; - @Schema(description = "作品编号") - private String workNo; - @Schema(description = "作品标题") - private String title; - @Schema(description = "创建时间") - private java.time.LocalDateTime createTime; - @Schema(description = "参赛者信息") - private ParticipantInfo registration; - } - - @Data - @Schema(description = "参赛者信息") - public static class ParticipantInfo { - @Schema(description = "用户 ID") - private Long id; - @Schema(description = "用户名") - private String username; - @Schema(description = "昵称") - private String nickname; - @Schema(description = "团队 ID") - private Long teamId; - @Schema(description = "团队名称") - private String teamName; - } - - @Data - @Schema(description = "待评审分配") - public static class PendingAssignment { - @Schema(description = "分配 ID") - private Long id; - @Schema(description = "作品 ID") - private Long workId; - @Schema(description = "作品编号") - private String workNo; - @Schema(description = "作品标题") - private String workTitle; - @Schema(description = "评委 ID") - private Long judgeId; - @Schema(description = "评委姓名") - private String judgeName; - @Schema(description = "分配状态") - private String status; - @Schema(description = "分配时间") - private java.time.LocalDateTime assignmentTime; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewStatsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewStatsVO.java deleted file mode 100644 index e1d2593..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/ReviewStatsVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 评审统计 VO - */ -@Data -@Schema(description = "评审统计响应") -public class ReviewStatsVO { - - @Schema(description = "总作品数") - private Integer totalWorks; - - @Schema(description = "已分配数") - private Integer assigned; - - @Schema(description = "评审中数") - private Integer reviewing; - - @Schema(description = "已完成数") - private Integer completed; - - @Schema(description = "已评分数") - private Integer scored; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/WorkScoreVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/WorkScoreVO.java deleted file mode 100644 index dde27f3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/WorkScoreVO.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.time.LocalDateTime; - -/** - * 作品评分 VO - */ -@Data -@Schema(description = "作品评分响应") -public class WorkScoreVO { - - @Schema(description = "评分 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "作品 ID") - private Long workId; - - @Schema(description = "分配 ID") - private Long assignmentId; - - @Schema(description = "评委 ID") - private Long judgeId; - - @Schema(description = "评委姓名") - private String judgeName; - - @Schema(description = "总分") - private BigDecimal totalScore; - - @Schema(description = "评语") - private String comment; - - @Schema(description = "各维度评分(JSON)") - private String dimensionScores; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/review/WorkStatusStatsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/review/WorkStatusStatsVO.java deleted file mode 100644 index 2678524..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/review/WorkStatusStatsVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.vo.review; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 作品状态统计 VO - */ -@Data -@Schema(description = "作品状态统计") -public class WorkStatusStatsVO { - - @Schema(description = "已提交作品数") - private Integer submitted; - - @Schema(description = "评审中作品数") - private Integer reviewing; - - @Schema(description = "已评审作品数") - private Integer reviewed; - - @Schema(description = "获奖作品数") - private Integer awarded; - - @Schema(description = "总作品数") - private Integer total; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/reviewrule/ReviewDimensionVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/reviewrule/ReviewDimensionVO.java deleted file mode 100644 index 39e17ac..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/reviewrule/ReviewDimensionVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.vo.reviewrule; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; - -/** - * 评审维度 VO - */ -@Data -@Schema(description = "评审维度响应") -public class ReviewDimensionVO { - - @Schema(description = "维度 ID") - private Long id; - - @Schema(description = "规则 ID") - private Long ruleId; - - @Schema(description = "维度名称") - private String dimensionName; - - @Schema(description = "维度描述") - private String description; - - @Schema(description = "权重") - private BigDecimal weight; - - @Schema(description = "满分") - private BigDecimal maxScore; - - @Schema(description = "排序") - private Integer sort; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/reviewrule/ReviewRuleVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/reviewrule/ReviewRuleVO.java deleted file mode 100644 index 21602c9..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/reviewrule/ReviewRuleVO.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.lesingle.creation.vo.reviewrule; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.util.List; - -/** - * 评审规则 VO - */ -@Data -@Schema(description = "评审规则响应") -public class ReviewRuleVO { - - @Schema(description = "规则 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "规则名称") - private String ruleName; - - @Schema(description = "规则类型:default/custom") - private String ruleType; - - @Schema(description = "总分") - private BigDecimal totalScore; - - @Schema(description = "规则描述") - private String description; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "维度列表") - private List dimensions; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/role/RoleDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/role/RoleDetailVO.java deleted file mode 100644 index 0a51542..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/role/RoleDetailVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 角色详情 VO - */ -@Data -@Schema(description = "角色详情响应") -public class RoleDetailVO { - - @Schema(description = "角色 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "角色名称") - private String name; - - @Schema(description = "角色编码") - private String code; - - @Schema(description = "角色描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "权限 ID 列表") - private List permissionIds; - - @Schema(description = "权限名称列表") - private List permissionNames; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/role/RoleListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/role/RoleListVO.java deleted file mode 100644 index d00357d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/role/RoleListVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.lesingle.creation.vo.role; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 角色列表 VO - */ -@Data -@Schema(description = "角色列表响应") -public class RoleListVO { - - @Schema(description = "角色 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "角色名称") - private String name; - - @Schema(description = "角色编码") - private String code; - - @Schema(description = "角色描述") - private String description; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java deleted file mode 100644 index 2bb2b71..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/school/ClassTreeNodeVO.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.lesingle.creation.vo.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.util.List; - -/** - * 班级树节点 VO - */ -@Data -@Schema(description = "班级树节点") -public class ClassTreeNodeVO { - - @Schema(description = "班级 ID") - private Long id; - - @Schema(description = "班级名称") - private String name; - - @Schema(description = "班级编码") - private String code; - - @Schema(description = "年级 ID") - private Long gradeId; - - @Schema(description = "年级名称") - private String gradeName; - - @Schema(description = "子节点(小班、中班、大班等)") - private List children; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java deleted file mode 100644 index 6662a1c..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/school/SchoolVO.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.lesingle.creation.vo.school; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 学校信息 VO - */ -@Data -@Schema(description = "学校信息响应") -public class SchoolVO { - - @Schema(description = "学校 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "学校地址") - private String address; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "校长姓名") - private String principal; - - @Schema(description = "建校时间") - private LocalDate established; - - @Schema(description = "学校描述") - private String description; - - @Schema(description = "学校 Logo URL") - private String logo; - - @Schema(description = "学校网站") - private String website; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java deleted file mode 100644 index f2a0f20..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/schoolclass/ClassVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.schoolclass; - -import com.lesingle.creation.vo.grade.GradeVO; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 班级响应 VO - */ -@Data -@Schema(description = "班级响应") -public class ClassVO { - - @Schema(description = "班级 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "年级 ID") - private Long gradeId; - - @Schema(description = "班级名称") - private String name; - - @Schema(description = "班级编码") - private String code; - - @Schema(description = "班级类型:1-行政班级,2-兴趣班") - private Integer type; - - @Schema(description = "班级容量") - private Integer capacity; - - @Schema(description = "班级描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "关联年级信息") - private GradeVO grade; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java deleted file mode 100644 index 7747825..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/student/StudentVO.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.lesingle.creation.vo.student; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 学生响应 VO - */ -@Data -@Schema(description = "学生响应") -public class StudentVO { - - @Schema(description = "学生 ID") - private Long id; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "行政班级 ID") - private Long classId; - - @Schema(description = "学号") - private String studentNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入学日期") - private LocalDate enrollmentDate; - - @Schema(description = "家长姓名") - private String parentName; - - @Schema(description = "家长电话") - private String parentPhone; - - @Schema(description = "家庭地址") - private String address; - - @Schema(description = "学生描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "用户信息") - private UserInfo userInfo; - - @Schema(description = "班级信息") - private ClassInfo classInfo; - - /** - * 用户信息嵌套 VO - */ - @Data - @Schema(description = "用户信息") - public static class UserInfo { - @Schema(description = "用户名") - private String username; - @Schema(description = "昵称") - private String nickname; - @Schema(description = "邮箱") - private String email; - @Schema(description = "头像 URL") - private String avatar; - } - - /** - * 班级信息嵌套 VO - */ - @Data - @Schema(description = "班级信息") - public static class ClassInfo { - @Schema(description = "班级 ID") - private Long id; - @Schema(description = "班级名称") - private String name; - @Schema(description = "班级编码") - private String code; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java deleted file mode 100644 index 9ce7515..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/teacher/TeacherVO.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.lesingle.creation.vo.teacher; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 教师响应 VO - */ -@Data -@Schema(description = "教师响应") -public class TeacherVO { - - @Schema(description = "教师 ID") - private Long id; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "部门 ID") - private Long departmentId; - - @Schema(description = "工号") - private String employeeNo; - - @Schema(description = "联系电话") - private String phone; - - @Schema(description = "身份证号") - private String idCard; - - @Schema(description = "性别:1-男,2-女") - private Integer gender; - - @Schema(description = "出生日期") - private LocalDate birthDate; - - @Schema(description = "入职日期") - private LocalDate hireDate; - - @Schema(description = "任教科目") - private String subject; - - @Schema(description = "职称") - private String title; - - @Schema(description = "教师描述") - private String description; - - @Schema(description = "有效状态") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "用户信息") - private UserInfo userInfo; - - @Schema(description = "部门信息") - private DepartmentInfo department; - - /** - * 用户信息嵌套 VO - */ - @Data - @Schema(description = "用户信息") - public static class UserInfo { - @Schema(description = "用户名") - private String username; - @Schema(description = "昵称") - private String nickname; - @Schema(description = "邮箱") - private String email; - @Schema(description = "头像 URL") - private String avatar; - } - - /** - * 部门信息嵌套 VO - */ - @Data - @Schema(description = "部门信息") - public static class DepartmentInfo { - @Schema(description = "部门 ID") - private Long id; - @Schema(description = "部门名称") - private String name; - @Schema(description = "部门编码") - private String code; - } -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/team/TeamMemberVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/team/TeamMemberVO.java deleted file mode 100644 index d7a3bbe..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/team/TeamMemberVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.vo.team; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 团队成员 VO - */ -@Data -@Schema(description = "团队成员响应") -public class TeamMemberVO { - - @Schema(description = "成员 ID") - private Long id; - - @Schema(description = "团队 ID") - private Long teamId; - - @Schema(description = "用户 ID") - private Long userId; - - @Schema(description = "用户姓名") - private String userName; - - @Schema(description = "角色:leader/member/mentor") - private String role; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/team/TeamVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/team/TeamVO.java deleted file mode 100644 index e6df346..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/team/TeamVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.team; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 团队 VO - */ -@Data -@Schema(description = "团队响应") -public class TeamVO { - - @Schema(description = "团队 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "团队名称") - private String teamName; - - @Schema(description = "队长用户 ID") - private Long leaderUserId; - - @Schema(description = "队长姓名") - private String leaderName; - - @Schema(description = "最大人数") - private Integer maxMembers; - - @Schema(description = "当前人数") - private Integer currentMembers; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "成员列表") - private List members; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/tenant/TenantDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/tenant/TenantDetailVO.java deleted file mode 100644 index 3d49bb3..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/tenant/TenantDetailVO.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.lesingle.creation.vo.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 租户详情 VO - */ -@Data -@Schema(description = "租户详情响应") -public class TenantDetailVO { - - @Schema(description = "租户 ID") - private Long id; - - @Schema(description = "租户名称") - private String name; - - @Schema(description = "租户编码") - private String code; - - @Schema(description = "租户域名") - private String domain; - - @Schema(description = "租户描述") - private String description; - - @Schema(description = "是否为超级租户:0-否,1-是") - private Integer isSuper; - - @Schema(description = "租户类型") - private String tenantType; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "用户数量") - private Integer userCount; - - @Schema(description = "角色数量") - private Integer roleCount; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/tenant/TenantListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/tenant/TenantListVO.java deleted file mode 100644 index 3744250..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/tenant/TenantListVO.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.lesingle.creation.vo.tenant; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -/** - * 租户列表 VO - */ -@Data -@Schema(description = "租户列表响应") -public class TenantListVO { - - @Schema(description = "租户 ID") - private Long id; - - @Schema(description = "租户名称") - private String name; - - @Schema(description = "租户编码") - private String code; - - @Schema(description = "租户域名") - private String domain; - - @Schema(description = "租户描述") - private String description; - - @Schema(description = "是否为超级租户:0-否,1-是") - private Integer isSuper; - - @Schema(description = "租户类型") - private String tenantType; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "用户数量") - private Integer userCount; - - @Schema(description = "角色数量") - private Integer roleCount; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/upload/UploadResponseVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/upload/UploadResponseVO.java deleted file mode 100644 index 98b0d3f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/upload/UploadResponseVO.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.lesingle.creation.vo.upload; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 文件上传响应 VO - */ -@Data -@Schema(description = "文件上传响应") -public class UploadResponseVO { - - @Schema(description = "文件访问 URL") - private String url; - - @Schema(description = "文件名称") - private String fileName; - - @Schema(description = "文件大小(字节)") - private Long size; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/user/UserDetailVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/user/UserDetailVO.java deleted file mode 100644 index 4a7fa0d..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/user/UserDetailVO.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.lesingle.creation.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; - -/** - * 用户详情 VO - */ -@Data -@Schema(description = "用户详情响应") -public class UserDetailVO { - - @Schema(description = "用户 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "用户名") - private String username; - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "手机号") - private String phone; - - @Schema(description = "性别:male-男,female-女") - private String gender; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "所在城市") - private String city; - - @Schema(description = "出生日期") - private LocalDate birthday; - - @Schema(description = "用户来源") - private String userSource; - - @Schema(description = "用户类型:adult/child") - private String userType; - - @Schema(description = "所属单位") - private String organization; - - @Schema(description = "账号状态:enabled-启用,disabled-停用") - private String status; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "创建人") - private String createBy; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "更新人") - private String updateBy; - - @Schema(description = "更新时间") - private LocalDateTime updateTime; - - @Schema(description = "角色 ID 列表") - private List roleIds; - - @Schema(description = "角色名称列表") - private List roleNames; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/user/UserListVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/user/UserListVO.java deleted file mode 100644 index 38a3a2b..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/user/UserListVO.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.lesingle.creation.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * 用户列表 VO - */ -@Data -@Schema(description = "用户列表响应") -public class UserListVO { - - @Schema(description = "用户 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "用户名") - private String username; - - @Schema(description = "昵称") - private String nickname; - - @Schema(description = "邮箱") - private String email; - - @Schema(description = "手机号") - private String phone; - - @Schema(description = "性别:male-男,female-女") - private String gender; - - @Schema(description = "头像 URL") - private String avatar; - - @Schema(description = "用户类型:adult/child") - private String userType; - - @Schema(description = "账号状态:enabled-启用,disabled-停用") - private String status; - - @Schema(description = "创建时间") - private LocalDateTime createTime; - - @Schema(description = "角色名称列表") - private java.util.List roleNames; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/user/UserStatsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/user/UserStatsVO.java deleted file mode 100644 index 8a92157..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/user/UserStatsVO.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.lesingle.creation.vo.user; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 用户统计 VO - */ -@Data -@Schema(description = "用户统计响应") -public class UserStatsVO { - - @Schema(description = "总用户数") - private Integer total; - - @Schema(description = "平台用户数") - private Integer platform; - - @Schema(description = "机构用户数") - private Integer org; - - @Schema(description = "评委用户数") - private Integer judge; - - @Schema(description = "公共用户数") - private Integer publicCount; - - @Schema(description = "成人用户数") - private Integer adult; - - @Schema(description = "子女用户数") - private Integer child; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkAttachmentVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkAttachmentVO.java deleted file mode 100644 index a84b917..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkAttachmentVO.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.lesingle.creation.vo.work; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 作品附件 VO - */ -@Data -@Schema(description = "作品附件响应") -public class WorkAttachmentVO { - - @Schema(description = "附件 ID") - private Long id; - - @Schema(description = "文件名称") - private String fileName; - - @Schema(description = "文件 URL") - private String fileUrl; - - @Schema(description = "文件类型") - private String fileType; - - @Schema(description = "文件大小(字节)") - private Long size; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkStatsVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkStatsVO.java deleted file mode 100644 index 75f8561..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkStatsVO.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lesingle.creation.vo.work; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -/** - * 作品统计 VO - */ -@Data -@Schema(description = "作品统计响应") -public class WorkStatsVO { - - @Schema(description = "总作品数") - private Integer total; - - @Schema(description = "已提交数") - private Integer submitted; - - @Schema(description = "评审中数") - private Integer reviewing; - - @Schema(description = "已退回数") - private Integer returned; -} diff --git a/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkVO.java b/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkVO.java deleted file mode 100644 index 34caf3f..0000000 --- a/java-backend/src/main/java/com/lesingle/creation/vo/work/WorkVO.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.lesingle.creation.vo.work; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; -import java.util.List; - -/** - * 作品 VO - */ -@Data -@Schema(description = "作品响应") -public class WorkVO { - - @Schema(description = "作品 ID") - private Long id; - - @Schema(description = "租户 ID") - private Long tenantId; - - @Schema(description = "活动 ID") - private Long contestId; - - @Schema(description = "活动名称") - private String contestName; - - @Schema(description = "报名 ID") - private Long registrationId; - - @Schema(description = "作品编号") - private String workNo; - - @Schema(description = "作品标题") - private String title; - - @Schema(description = "作品描述") - private String description; - - @Schema(description = "文件列表(JSON)") - private String files; - - @Schema(description = "版本号") - private Integer version; - - @Schema(description = "是否最新版本") - private Boolean isLatest; - - @Schema(description = "作品状态:submitted/reviewing/returned") - private String status; - - @Schema(description = "提交时间") - private LocalDateTime submitTime; - - @Schema(description = "提交人 ID") - private Long submitterUserId; - - @Schema(description = "提交人账号") - private String submitterAccountNo; - - @Schema(description = "提交来源:student/teacher/parent") - private String submitSource; - - @Schema(description = "预览图 URL") - private String previewUrl; - - @Schema(description = "预览图 URL 数组(JSON)") - private String previewUrls; - - @Schema(description = "AI 模型元数据(JSON)") - private String aiModelMeta; - - @Schema(description = "有效状态:1-有效,2-失效") - private Integer validState; - - @Schema(description = "附件列表") - private List attachments; - - @Schema(description = "参赛者姓名") - private String participantName; - - @Schema(description = "参赛者类型:personal/team") - private String participantType; -} diff --git a/java-backend/src/main/resources/application-dev.yml b/java-backend/src/main/resources/application-dev.yml deleted file mode 100644 index 9c66914..0000000 --- a/java-backend/src/main/resources/application-dev.yml +++ /dev/null @@ -1,99 +0,0 @@ -# 开发环境配置 -spring: - # 数据源配置 - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://192.168.1.250:3306/lesingle-creation-test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true - username: lesingle-creation-test - password: 8ErFZiPBGbyrTHsy - druid: - # 初始连接数 - initial-size: 5 - # 最小空闲连接数 - min-idle: 5 - # 最大活跃连接数 - max-active: 20 - # 获取连接等待超时时间 - max-wait: 60000 - # 检测间隔 - time-between-eviction-runs-millis: 60000 - # 连接最小生存时间 - min-evictable-idle-time-millis: 300000 - # 检测连接是否有效 - validation-query: SELECT 1 - # 检测时机 - test-while-idle: true - # 申请连接时检测 - test-on-borrow: false - # 归还连接时检测 - test-on-return: false - # 开启 P6Spy SQL 性能分析(开发环境) - # filter: - # slf4j: - # enabled: true - - # Redis 配置 - data: - redis: - host: ${REDIS_HOST:192.168.1.250} - port: ${REDIS_PORT:6379} - password: ${REDIS_PASSWORD:QWErty123} - database: ${REDIS_DB:8} - timeout: 5000ms - lettuce: - pool: - max-active: 20 - max-idle: 20 - min-idle: 5 - max-wait: -1ms - - # Flyway 配置 - flyway: - enabled: true - locations: classpath:db/migration - # 启用 repair 模式 - repair-on-migrate: true - # 开发环境允许 Clean 操作 - clean-disabled: true - # SQL 执行前是否校验 - 禁用 - validate-on-migrate: false - # 编码 - encoding: UTF-8 - -# JWT 配置(开发环境默认密钥) -jwt: - secret: creation-development-secret-key-please-change-in-production - expiration: 86400000 # 24 小时 - token-prefix: "Bearer " - header: Authorization - -# MyBatis-Plus 开发配置 -mybatis-plus: - configuration: - # 开启 SQL 日志 - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - -# SpringDoc 开发环境开启 -springdoc: - api-docs: - enabled: true - swagger-ui: - enabled: true - -# 日志级别(开发环境 DEBUG) -logging: - level: - root: INFO - com.lesingle.creation: DEBUG - com.lesingle.creation.mapper: DEBUG - -# 阿里云 OSS 配置(开发环境) -aliyun: - oss: - endpoint: oss-cn-hangzhou.aliyuncs.com - access-key-id: ${OSS_ACCESS_KEY_ID:your-access-key-id} - access-key-secret: ${OSS_ACCESS_KEY_SECRET:your-access-key-secret} - bucket-name: your-bucket-name - custom-domain: - root-dir: uploads diff --git a/java-backend/src/main/resources/application-prod.yml b/java-backend/src/main/resources/application-prod.yml deleted file mode 100644 index 6da69e3..0000000 --- a/java-backend/src/main/resources/application-prod.yml +++ /dev/null @@ -1,78 +0,0 @@ -# 生产环境配置 -spring: - # 数据源配置 - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: ${DATABASE_URL:jdbc:mysql://localhost:3306/creation_db?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true} - username: ${DB_USERNAME} - password: ${DB_PASSWORD} - druid: - initial-size: 10 - min-idle: 10 - max-active: 50 - max-wait: 60000 - time-between-eviction-runs-millis: 60000 - min-evictable-idle-time-millis: 300000 - validation-query: SELECT 1 - test-while-idle: true - test-on-borrow: false - test-on-return: false - # 开启防火墙模式 - wall: - config: - delete-where-none-check: true - - # Redis 配置 - data: - redis: - host: ${REDIS_HOST} - port: ${REDIS_PORT:6379} - password: ${REDIS_PASSWORD} - database: ${REDIS_DB:0} - timeout: 5000ms - lettuce: - pool: - max-active: 20 - max-idle: 20 - min-idle: 5 - max-wait: -1ms - - # Flyway 配置 - flyway: - enabled: true - locations: classpath:db/migration - baseline-on-migrate: true - baseline-version: 0 - # 生产环境严格禁止 Clean 操作 - clean-disabled: true - validate-on-migrate: true - encoding: UTF-8 - -# JWT 配置(生产环境必须使用环境变量) -jwt: - # 生产环境必须设置强密钥 - secret: ${JWT_SECRET:LfqBlB7UUwRFzgCf17bB919VonKLk0xknxAIFlHRFpJJVFYrgGI1bUCT2eYpBSuO} - expiration: 86400000 - token-prefix: "Bearer " - header: Authorization - -# MyBatis-Plus 生产配置 -mybatis-plus: - configuration: - # 关闭 SQL 日志提升性能 - log-impl: org.slf4j.impl.SimpleLogger - -# SpringDoc 生产环境关闭 -springdoc: - api-docs: - enabled: false - swagger-ui: - enabled: false - -# 日志级别(生产环境 INFO) -logging: - level: - root: WARN - com.lesingle.creation: INFO - com.lesingle.creation.mapper: WARN diff --git a/java-backend/src/main/resources/application-test.yml b/java-backend/src/main/resources/application-test.yml deleted file mode 100644 index 340d9bb..0000000 --- a/java-backend/src/main/resources/application-test.yml +++ /dev/null @@ -1,73 +0,0 @@ -# 测试环境配置 -spring: - # 数据源配置 - datasource: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://192.168.1.250:3306/lesingle-creation-test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true - username: lesingle-creation-test - password: 8ErFZiPBGbyrTHsy - druid: - initial-size: 5 - min-idle: 5 - max-active: 20 - max-wait: 60000 - time-between-eviction-runs-millis: 60000 - min-evictable-idle-time-millis: 300000 - validation-query: SELECT 1 - test-while-idle: true - test-on-borrow: false - test-on-return: false - - # Redis 配置 - data: - redis: - host: ${REDIS_HOST:192.168.1.250} - port: ${REDIS_PORT:6379} - password: ${REDIS_PASSWORD:QWErty123} - database: ${REDIS_DB:8} - timeout: 5000ms - lettuce: - pool: - max-active: 8 - max-idle: 8 - min-idle: 0 - max-wait: -1ms - - # Flyway 配置 - flyway: - enabled: true - locations: classpath:db/migration - baseline-on-migrate: true - baseline-version: 0 - # 测试环境禁止 Clean 操作 - clean-disabled: true - validate-on-migrate: true - encoding: UTF-8 - -# JWT 配置 -jwt: - secret: ${JWT_SECRET:creation-test-secret-key} - expiration: 86400000 - token-prefix: "Bearer " - header: Authorization - -# MyBatis-Plus 测试配置 -mybatis-plus: - configuration: - # 开启 SQL 日志便于调试 - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - -# SpringDoc 测试环境开启 -springdoc: - api-docs: - enabled: true - swagger-ui: - enabled: true - -# 日志级别(测试环境 DEBUG) -logging: - level: - root: INFO - com.lesingle.creation: DEBUG - com.lesingle.creation.mapper: DEBUG diff --git a/java-backend/src/main/resources/application.yml b/java-backend/src/main/resources/application.yml deleted file mode 100644 index f4f7096..0000000 --- a/java-backend/src/main/resources/application.yml +++ /dev/null @@ -1,55 +0,0 @@ -# 应用配置 -spring: - application: - name: creation - # 激活的环境配置 - profiles: - active: dev - # 文件上传配置 - servlet: - multipart: - max-file-size: 100MB - max-request-size: 100MB - -# 服务器配置 -server: - port: 8580 - servlet: - context-path: / - -# MyBatis-Plus 配置 -mybatis-plus: - # Mapper XML 文件位置 - mapper-locations: classpath*:/mapper/**/*.xml - # 实体类包路径 - type-aliases-package: com.lesingle.creation.entity - configuration: - # 开启驼峰命名转换 - map-underscore-to-camel-case: true - # 开启日志 - log-impl: org.apache.ibatis.logging.stdout.StdOutImpl - global-config: - db-config: - # 主键类型(自增) - id-type: auto - # 逻辑删除字段 - logic-delete-field: deleted - logic-delete-value: 1 - logic-not-delete-value: 0 - # 关闭 Banner - banner: false - -# SpringDoc OpenAPI 配置(API 文档) -springdoc: - api-docs: - enabled: true - path: /v3/api-docs - swagger-ui: - enabled: true - path: /swagger-ui.html - # 设置中文语言 - default-locale: zh-CN - -# 日志配置 -logging: - config: classpath:logback-spring.xml diff --git a/java-backend/src/main/resources/db/migration/V10__create_biz_contest_work_judge_rule.sql b/java-backend/src/main/resources/db/migration/V10__create_biz_contest_work_judge_rule.sql deleted file mode 100644 index 1e5d342..0000000 --- a/java-backend/src/main/resources/db/migration/V10__create_biz_contest_work_judge_rule.sql +++ /dev/null @@ -1,118 +0,0 @@ --- 竞赛作品表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_work` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '作品所属租户 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `registration_id` BIGINT NOT NULL COMMENT '报名记录 ID', - `work_no` VARCHAR(50) DEFAULT NULL COMMENT '作品编号(展示用唯一编号)', - `title` VARCHAR(200) NOT NULL COMMENT '作品标题', - `description` TEXT DEFAULT NULL COMMENT '作品说明', - `files` JSON DEFAULT NULL COMMENT '作品文件列表', - `version` INT DEFAULT 1 COMMENT '作品版本号', - `is_latest` TINYINT DEFAULT 1 COMMENT '是否最新版本', - `status` VARCHAR(50) DEFAULT 'submitted' COMMENT '作品状态:submitted/locked/reviewing/rejected/accepted', - `submit_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '提交时间', - `submitter_user_id` BIGINT DEFAULT NULL COMMENT '提交人用户 ID', - `submitter_account_no` VARCHAR(50) DEFAULT NULL COMMENT '提交人账号', - `submit_source` VARCHAR(50) DEFAULT 'teacher' COMMENT '提交来源:teacher/student/team_leader', - `preview_url` TEXT DEFAULT NULL COMMENT '作品预览 URL', - `preview_urls` JSON DEFAULT NULL COMMENT '作品预览图 URL 列表', - `ai_model_meta` JSON DEFAULT NULL COMMENT 'AI 建模元数据', - `user_work_id` BIGINT DEFAULT NULL COMMENT '关联用户作品库 ID', - -- 赛果相关字段 - `final_score` DECIMAL(10,2) DEFAULT NULL COMMENT '最终得分', - `rank` INT DEFAULT NULL COMMENT '排名', - `award_level` VARCHAR(50) DEFAULT NULL COMMENT '奖项等级:first/second/third/excellent/none', - `award_name` VARCHAR(100) DEFAULT NULL COMMENT '奖项名称', - `certificate_url` VARCHAR(500) DEFAULT NULL COMMENT '证书 URL', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_work_no` (`work_no`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_registration_id` (`registration_id`), - KEY `idx_status` (`status`), - KEY `idx_is_latest` (`is_latest`), - KEY `idx_submit_time` (`submit_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛作品表'; - --- 竞赛作品附件表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_work_attachment` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `work_id` BIGINT NOT NULL COMMENT '作品 ID', - `name` VARCHAR(100) NOT NULL COMMENT '附件名称', - `url` VARCHAR(500) NOT NULL COMMENT '附件 URL', - `type` VARCHAR(50) DEFAULT NULL COMMENT '附件类型', - `size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)', - `sort` INT DEFAULT 0 COMMENT '排序', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_work_id` (`work_id`), - KEY `idx_sort` (`sort`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛作品附件表'; - --- 竞赛评委表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_judge` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `judge_id` BIGINT NOT NULL COMMENT '评委用户 ID', - `judge_name` VARCHAR(100) NOT NULL COMMENT '评委姓名', - `title` VARCHAR(50) DEFAULT NULL COMMENT '职称', - `organization` VARCHAR(200) DEFAULT NULL COMMENT '所属单位', - `phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话', - `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱', - `specialty` VARCHAR(200) DEFAULT NULL COMMENT '专业领域', - `status` VARCHAR(50) DEFAULT 'active' COMMENT '状态:active/inactive', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_contest_judge` (`contest_id`, `judge_id`), - KEY `idx_tenant_id` (`tenant_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛评委表'; - --- 评审规则表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_review_rule` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT DEFAULT NULL COMMENT '竞赛 ID(为空表示默认规则)', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `rule_name` VARCHAR(100) NOT NULL COMMENT '规则名称', - `rule_type` VARCHAR(50) DEFAULT 'custom' COMMENT '规则类型:default/custom', - `total_score` DECIMAL(10,2) DEFAULT 100 COMMENT '总分', - `pass_score` DECIMAL(10,2) DEFAULT 60 COMMENT '及格分', - `description` VARCHAR(500) DEFAULT NULL COMMENT '规则描述', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_tenant_id` (`tenant_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='评审规则表'; - --- 评审维度表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_review_dimension` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `rule_id` BIGINT NOT NULL COMMENT '评审规则 ID', - `dimension_name` VARCHAR(100) NOT NULL COMMENT '维度名称', - `dimension_code` VARCHAR(50) NOT NULL COMMENT '维度编码', - `weight` DECIMAL(5,2) DEFAULT NULL COMMENT '权重(百分比)', - `max_score` DECIMAL(10,2) NOT NULL COMMENT '满分', - `description` VARCHAR(500) DEFAULT NULL COMMENT '维度说明', - `sort` INT DEFAULT 0 COMMENT '排序', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_rule_id` (`rule_id`), - KEY `idx_sort` (`sort`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='评审维度表'; diff --git a/java-backend/src/main/resources/db/migration/V11__create_biz_contest_review_result.sql b/java-backend/src/main/resources/db/migration/V11__create_biz_contest_review_result.sql deleted file mode 100644 index cdad90c..0000000 --- a/java-backend/src/main/resources/db/migration/V11__create_biz_contest_review_result.sql +++ /dev/null @@ -1,104 +0,0 @@ --- 竞赛作品评审分配表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_work_assignment` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `work_id` BIGINT NOT NULL COMMENT '作品 ID', - `judge_id` BIGINT NOT NULL COMMENT '评委用户 ID', - `judge_name` VARCHAR(100) DEFAULT NULL COMMENT '评委姓名', - `assignment_status` VARCHAR(50) DEFAULT 'pending' COMMENT '分配状态:pending/reviewing/completed', - `assigned_by` BIGINT DEFAULT NULL COMMENT '分配人 ID', - `assigned_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '分配时间', - `review_time` DATETIME DEFAULT NULL COMMENT '评审时间', - `score` DECIMAL(10,2) DEFAULT NULL COMMENT '评分', - `comment` TEXT DEFAULT NULL COMMENT '评语', - `preset_comment_id` BIGINT DEFAULT NULL COMMENT '预设评语 ID', - `custom_comment` VARCHAR(500) DEFAULT NULL COMMENT '自定义评语', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_work_judge` (`work_id`, `judge_id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_judge_id` (`judge_id`), - KEY `idx_assignment_status` (`assignment_status`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛作品评审分配表'; - --- 竞赛作品评分表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_work_score` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `work_id` BIGINT NOT NULL COMMENT '作品 ID', - `assignment_id` BIGINT DEFAULT NULL COMMENT '评审分配 ID', - `judge_id` BIGINT NOT NULL COMMENT '评委用户 ID', - `judge_name` VARCHAR(100) DEFAULT NULL COMMENT '评委姓名', - `dimension_id` BIGINT DEFAULT NULL COMMENT '评审维度 ID', - `dimension_name` VARCHAR(100) DEFAULT NULL COMMENT '评审维度名称', - `score` DECIMAL(10,2) NOT NULL COMMENT '得分', - `comment` VARCHAR(500) DEFAULT NULL COMMENT '评语', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_work_id` (`work_id`), - KEY `idx_judge_id` (`judge_id`), - KEY `idx_dimension_id` (`dimension_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛作品评分表'; - --- 竞赛结果表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_result` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `work_id` BIGINT NOT NULL COMMENT '作品 ID', - `registration_id` BIGINT DEFAULT NULL COMMENT '报名 ID', - `team_id` BIGINT DEFAULT NULL COMMENT '团队 ID', - `award_level` VARCHAR(50) NOT NULL COMMENT '奖项等级:first/second/third/excellent', - `award_name` VARCHAR(100) NOT NULL COMMENT '奖项名称', - `rank` INT DEFAULT NULL COMMENT '排名', - `final_score` DECIMAL(10,2) DEFAULT NULL COMMENT '最终得分', - `certificate_url` VARCHAR(500) DEFAULT NULL COMMENT '证书 URL', - `publish_time` DATETIME DEFAULT NULL COMMENT '发布时间', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_contest_work` (`contest_id`, `work_id`), - KEY `idx_award_level` (`award_level`), - KEY `idx_rank` (`rank`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛结果表'; - --- 竞赛公告表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_notice` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `title` VARCHAR(200) NOT NULL COMMENT '公告标题', - `content` TEXT NOT NULL COMMENT '公告内容', - `priority` INT DEFAULT 0 COMMENT '优先级(数字越大越优先)', - `publish_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '发布时间', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_priority` (`priority`), - KEY `idx_publish_time` (`publish_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛公告表'; - --- 竞赛预设评语表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_preset_comment` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT DEFAULT NULL COMMENT '赛事 ID(为空表示通用评语)', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `content` VARCHAR(500) NOT NULL COMMENT '评语内容', - `type` VARCHAR(50) DEFAULT 'positive' COMMENT '评语类型:positive/neutral/negative', - `score_range_min` DECIMAL(10,2) DEFAULT NULL COMMENT '适用分数范围最小值', - `score_range_max` DECIMAL(10,2) DEFAULT NULL COMMENT '适用分数范围最大值', - `sort` INT DEFAULT 0 COMMENT '排序', - `usage_count` INT DEFAULT 0 COMMENT '使用次数', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_type` (`type`), - KEY `idx_sort` (`sort`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛预设评语表'; diff --git a/java-backend/src/main/resources/db/migration/V12__create_biz_homework.sql b/java-backend/src/main/resources/db/migration/V12__create_biz_homework.sql deleted file mode 100644 index d756599..0000000 --- a/java-backend/src/main/resources/db/migration/V12__create_biz_homework.sql +++ /dev/null @@ -1,83 +0,0 @@ --- 作业表 -CREATE TABLE IF NOT EXISTS `t_biz_homework` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(200) NOT NULL COMMENT '作业名称', - `content` TEXT DEFAULT NULL COMMENT '作业内容(富文本)', - `status` VARCHAR(50) DEFAULT 'unpublished' COMMENT '作业状态:unpublished/published', - `publish_time` DATETIME DEFAULT NULL COMMENT '发布时间', - `submit_start_time` DATETIME NOT NULL COMMENT '提交开始时间', - `submit_end_time` DATETIME NOT NULL COMMENT '提交结束时间', - `attachments` JSON DEFAULT NULL COMMENT '附件列表', - `publish_scope` JSON DEFAULT NULL COMMENT '公开范围(班级 ID 数组)', - `review_rule_id` BIGINT DEFAULT NULL COMMENT '评审规则 ID', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_status` (`status`), - KEY `idx_valid_state` (`valid_state`), - KEY `idx_publish_time` (`publish_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业表'; - --- 作业提交表 -CREATE TABLE IF NOT EXISTS `t_biz_homework_submission` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `homework_id` BIGINT NOT NULL COMMENT '作业 ID', - `student_id` BIGINT NOT NULL COMMENT '学生用户 ID', - `student_name` VARCHAR(100) DEFAULT NULL COMMENT '学生姓名', - `content` TEXT DEFAULT NULL COMMENT '提交内容', - `attachments` JSON DEFAULT NULL COMMENT '提交附件列表', - `status` VARCHAR(50) DEFAULT 'submitted' COMMENT '提交状态:submitted/reviewing/returned', - `submit_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '提交时间', - `review_time` DATETIME DEFAULT NULL COMMENT '批改时间', - `reviewer_id` BIGINT DEFAULT NULL COMMENT '批改人 ID', - `review_comment` TEXT DEFAULT NULL COMMENT '批改评语', - `review_score` DECIMAL(10,2) DEFAULT NULL COMMENT '批改分数', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_homework_id` (`homework_id`), - KEY `idx_student_id` (`student_id`), - KEY `idx_status` (`status`), - KEY `idx_submit_time` (`submit_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业提交表'; - --- 作业评审规则表 -CREATE TABLE IF NOT EXISTS `t_biz_homework_review_rule` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `rule_name` VARCHAR(100) NOT NULL COMMENT '规则名称', - `rule_type` VARCHAR(50) DEFAULT 'custom' COMMENT '规则类型:default/custom', - `total_score` DECIMAL(10,2) DEFAULT 100 COMMENT '总分', - `description` VARCHAR(500) DEFAULT NULL COMMENT '规则描述', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业评审规则表'; - --- 作业评分表 -CREATE TABLE IF NOT EXISTS `t_biz_homework_score` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `submission_id` BIGINT NOT NULL COMMENT '提交 ID', - `homework_id` BIGINT NOT NULL COMMENT '作业 ID', - `reviewer_id` BIGINT NOT NULL COMMENT '评分人 ID', - `score` DECIMAL(10,2) NOT NULL COMMENT '得分', - `comment` VARCHAR(500) DEFAULT NULL COMMENT '评语', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_submission_id` (`submission_id`), - KEY `idx_homework_id` (`homework_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业评分表'; diff --git a/java-backend/src/main/resources/db/migration/V13__create_biz_ai3d_task.sql b/java-backend/src/main/resources/db/migration/V13__create_biz_ai3d_task.sql deleted file mode 100644 index 935abc3..0000000 --- a/java-backend/src/main/resources/db/migration/V13__create_biz_ai3d_task.sql +++ /dev/null @@ -1,25 +0,0 @@ --- AI 3D 任务表 -CREATE TABLE IF NOT EXISTS `t_biz_ai3d_task` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `user_id` BIGINT NOT NULL COMMENT '用户 ID', - `input_type` VARCHAR(50) NOT NULL COMMENT '输入类型:text/image', - `input_content` TEXT NOT NULL COMMENT '输入内容:文字描述或图片 URL', - `generate_type` VARCHAR(50) DEFAULT 'Normal' COMMENT '生成类型:Normal/Geometry/LowPoly/Sketch', - `status` VARCHAR(50) DEFAULT 'pending' COMMENT '任务状态:pending/processing/completed/failed/timeout', - `result_url` TEXT DEFAULT NULL COMMENT '生成的 3D 模型 URL(单结果)', - `preview_url` TEXT DEFAULT NULL COMMENT '预览图 URL(单结果)', - `result_urls` JSON DEFAULT NULL COMMENT '生成的 3D 模型 URL 数组(多结果)', - `preview_urls` JSON DEFAULT NULL COMMENT '预览图 URL 数组(多结果)', - `error_message` TEXT DEFAULT NULL COMMENT '失败错误信息', - `external_task_id` VARCHAR(100) DEFAULT NULL COMMENT '外部 AI 服务任务 ID', - `retry_count` INT DEFAULT 0 COMMENT '已重试次数', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `complete_time` DATETIME DEFAULT NULL COMMENT '完成时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_user_id` (`user_id`), - KEY `idx_status` (`status`), - KEY `idx_create_time` (`create_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='AI 3D 任务表'; diff --git a/java-backend/src/main/resources/db/migration/V14__create_biz_homework_review_dimension.sql b/java-backend/src/main/resources/db/migration/V14__create_biz_homework_review_dimension.sql deleted file mode 100644 index 600aa7a..0000000 --- a/java-backend/src/main/resources/db/migration/V14__create_biz_homework_review_dimension.sql +++ /dev/null @@ -1,15 +0,0 @@ --- 作业评审维度表 -CREATE TABLE IF NOT EXISTS `t_biz_homework_review_dimension` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `rule_id` BIGINT NOT NULL COMMENT '规则 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(100) NOT NULL COMMENT '维度名称', - `max_score` DECIMAL(10,2) NOT NULL COMMENT '满分', - `description` VARCHAR(500) DEFAULT NULL COMMENT '维度描述', - `sort_order` INT DEFAULT 0 COMMENT '排序顺序', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识', - PRIMARY KEY (`id`), - KEY `idx_rule_id` (`rule_id`), - KEY `idx_tenant_id` (`tenant_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作业评审维度表'; diff --git a/java-backend/src/main/resources/db/migration/V15__create_sys_log.sql b/java-backend/src/main/resources/db/migration/V15__create_sys_log.sql deleted file mode 100644 index e938f3a..0000000 --- a/java-backend/src/main/resources/db/migration/V15__create_sys_log.sql +++ /dev/null @@ -1,23 +0,0 @@ --- 系统日志表 -CREATE TABLE IF NOT EXISTS `t_sys_log` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `user_id` BIGINT DEFAULT NULL COMMENT '用户 ID', - `username` VARCHAR(100) DEFAULT NULL COMMENT '用户名', - `module` VARCHAR(50) DEFAULT NULL COMMENT '操作模块', - `action` VARCHAR(50) DEFAULT NULL COMMENT '操作类型', - `content` VARCHAR(500) DEFAULT NULL COMMENT '操作描述', - `ip` VARCHAR(50) DEFAULT NULL COMMENT '请求 IP', - `user_agent` VARCHAR(500) DEFAULT NULL COMMENT '用户代理', - `request_method` VARCHAR(10) DEFAULT NULL COMMENT '请求方法', - `request_url` VARCHAR(200) DEFAULT NULL COMMENT '请求 URL', - `duration` BIGINT DEFAULT NULL COMMENT '操作时长 (ms)', - `status` VARCHAR(20) DEFAULT NULL COMMENT '操作状态:success/failure', - `error_message` VARCHAR(1000) DEFAULT NULL COMMENT '错误信息', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_user_id` (`user_id`), - KEY `idx_create_time` (`create_time`), - KEY `idx_action` (`action`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统日志表'; diff --git a/java-backend/src/main/resources/db/migration/V16__init_auth_data.sql b/java-backend/src/main/resources/db/migration/V16__init_auth_data.sql deleted file mode 100644 index 4f926a2..0000000 --- a/java-backend/src/main/resources/db/migration/V16__init_auth_data.sql +++ /dev/null @@ -1,118 +0,0 @@ --- ============================================ --- 权限系统初始化数据 --- 包含:用户 - 角色关联、角色 - 权限关联、菜单数据 --- ============================================ - --- 1. 初始化用户 - 角色关联 --- admin 用户 (id=1) 关联 super_admin 角色 (id=1) -INSERT INTO t_auth_user_role (user_id, role_id) VALUES -(1, 1) -- admin 用户 -> super_admin 角色 -ON DUPLICATE KEY UPDATE `user_id` = VALUES(`user_id`); - --- 2. 初始化角色 - 权限关联 --- super_admin 角色 (id=1) 关联所有权限 -INSERT INTO t_auth_role_permission (role_id, permission_id) VALUES -(1, 1), -- user:create -(1, 2), -- user:read -(1, 3), -- user:update -(1, 4), -- user:delete -(1, 5), -- user:manage -(1, 6), -- role:create -(1, 7), -- role:read -(1, 8), -- role:update -(1, 9), -- role:delete -(1, 10), -- tenant:create -(1, 11), -- tenant:read -(1, 12), -- tenant:update -(1, 13), -- tenant:delete -(1, 14) -- super_admin -ON DUPLICATE KEY UPDATE `role_id` = VALUES(`role_id`); - --- admin 角色 (id=2) 关联基础业务权限(不含租户管理和超管权限) -INSERT INTO t_auth_role_permission (role_id, permission_id) VALUES -(2, 1), -- user:create -(2, 2), -- user:read -(2, 3), -- user:update -(2, 4), -- user:delete -(2, 5), -- user:manage -(2, 6), -- role:create -(2, 7), -- role:read -(2, 8), -- role:update -(2, 9) -- role:delete -ON DUPLICATE KEY UPDATE `role_id` = VALUES(`role_id`); - --- user 角色 (id=3) 关联只读权限 -INSERT INTO t_auth_role_permission (role_id, permission_id) VALUES -(3, 2), -- user:read -(3, 7) -- role:read -ON DUPLICATE KEY UPDATE `role_id` = VALUES(`role_id`); - --- 3. 初始化菜单数据 --- ============================================ --- 一级菜单:工作台 (id=1) --- ============================================ -INSERT INTO t_auth_menu (id, name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -(1, '工作台', 'workbench', 'Dashboard', 'workbench/Index', 0, NULL, 1, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- ============================================ --- 一级菜单:活动管理 (id=2) --- ============================================ -INSERT INTO t_auth_menu (id, name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -(2, '活动管理', 'contests', 'Trophy', NULL, 0, NULL, 2, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- 活动管理子菜单 -INSERT INTO t_auth_menu (name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -('活动列表', '', 'Appstore', 'contests/Index', 2, 'contest:read', 1, 1), -('创建活动', 'create', 'Plus', 'contests/Create', 2, 'contest:create', 2, 1), -('报名管理', 'registrations', 'Team', 'contests/registrations/Index', 2, 'contest:registration', 3, 1), -('作品管理', 'works', 'FileText', 'contests/works/Index', 2, 'contest:work', 4, 1), -('评审管理', 'reviews', 'CheckSquare', 'contests/reviews/Index', 2, 'contest:review', 5, 1), -('评委管理', 'judges', 'User', 'contests/judges/Index', 2, 'contest:judge', 6, 1), -('评审结果', 'results', 'BarChart', 'contests/results/Index', 2, 'contest:result', 7, 1), -('评审规则', 'rules', 'Setting', 'contests/ReviewRules', 2, 'contest:rule', 8, 1), -('公告管理', 'notices', 'Bell', 'contests/notices/Index', 2, 'contest:notice', 9, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- ============================================ --- 一级菜单:学校管理 (id=12) --- ============================================ -INSERT INTO t_auth_menu (id, name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -(12, '学校管理', 'school', 'School', NULL, 0, NULL, 3, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- 学校管理子菜单 -INSERT INTO t_auth_menu (name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -('学校信息', '', 'Home', 'school/schools/Index', 12, 'school:read', 1, 1), -('部门管理', 'departments', 'Building', 'school/departments/Index', 12, 'department:read', 2, 1), -('年级管理', 'grades', 'Layer', 'school/grades/Index', 12, 'grade:read', 3, 1), -('班级管理', 'classes', 'Team', 'school/classes/Index', 12, 'class:read', 4, 1), -('教师管理', 'teachers', 'User', 'school/teachers/Index', 12, 'teacher:read', 5, 1), -('学生管理', 'students', 'Team', 'school/students/Index', 12, 'student:read', 6, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- ============================================ --- 一级菜单:系统管理 (id=19) - 仅 super_admin 可见 --- ============================================ -INSERT INTO t_auth_menu (id, name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -(19, '系统管理', 'system', 'Setting', NULL, 0, 'super_admin', 4, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- 系统管理子菜单 -INSERT INTO t_auth_menu (name, path, icon, component, parent_id, permission, sort, valid_state) VALUES -('用户管理', 'users', 'User', 'system/users/Index', 19, 'user:read', 1, 1), -('角色管理', 'roles', 'Team', 'system/roles/Index', 19, 'role:read', 2, 1), -('权限管理', 'permissions', 'Lock', 'system/permissions/Index', 19, 'permission:read', 3, 1), -('菜单管理', 'menus', 'Menu', 'system/menus/Index', 19, 'menu:read', 4, 1), -('租户管理', 'tenants', 'Cluster', 'system/tenants/Index', 19, 'tenant:read', 5, 1), -('字典管理', 'dict', 'Book', 'system/dict/Index', 19, 'dict:read', 6, 1), -('配置管理', 'config', 'Setting', 'system/config/Index', 19, 'config:read', 7, 1), -('日志管理', 'logs', 'FileText', 'system/logs/Index', 19, 'log:read', 8, 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- 4. 初始化租户 - 菜单关联(租户 ID=1 关联所有菜单) --- 获取所有菜单 ID 并关联到租户 1 -INSERT INTO t_auth_tenant_menu (tenant_id, menu_id) -SELECT 1, id FROM t_auth_menu WHERE deleted = 0 -ON DUPLICATE KEY UPDATE `tenant_id` = VALUES(`tenant_id`); diff --git a/java-backend/src/main/resources/db/migration/V17__update_admin_password.sql b/java-backend/src/main/resources/db/migration/V17__update_admin_password.sql deleted file mode 100644 index bd0477c..0000000 --- a/java-backend/src/main/resources/db/migration/V17__update_admin_password.sql +++ /dev/null @@ -1,7 +0,0 @@ --- ============================================ --- 更新 admin 用户密码为 admin123 的 bcrypt 哈希 --- ============================================ - -UPDATE t_sys_user -SET password = '$2b$10$nRv5HtaFbmaUAVxZrOOJOOPyONlDbBl4SQqA.NjcchNux72TcqZja' -WHERE username = 'admin' AND tenant_id = 1; diff --git a/java-backend/src/main/resources/db/migration/V1__create_sys_tenant.sql b/java-backend/src/main/resources/db/migration/V1__create_sys_tenant.sql deleted file mode 100644 index d714975..0000000 --- a/java-backend/src/main/resources/db/migration/V1__create_sys_tenant.sql +++ /dev/null @@ -1,36 +0,0 @@ --- 租户表 -CREATE TABLE IF NOT EXISTS `t_sys_tenant` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `name` VARCHAR(100) NOT NULL COMMENT '租户名称', - `code` VARCHAR(50) NOT NULL COMMENT '租户编码(唯一,用于访问链接)', - `domain` VARCHAR(100) DEFAULT NULL COMMENT '租户域名(可选,用于子域名访问)', - `description` VARCHAR(500) DEFAULT NULL COMMENT '租户描述', - `is_super` TINYINT DEFAULT 0 COMMENT '是否为超级租户:0-否,1-是', - `tenant_type` VARCHAR(50) DEFAULT 'other' COMMENT '租户类型:platform/library/kindergarten/school/institution/other', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_code` (`code`), - UNIQUE KEY `uk_domain` (`domain`), - KEY `idx_tenant_type` (`tenant_type`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='租户表'; - --- 租户菜单关联表 -CREATE TABLE IF NOT EXISTS `t_auth_tenant_menu` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `menu_id` BIGINT NOT NULL COMMENT '菜单 ID', - PRIMARY KEY (`id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_menu_id` (`menu_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='租户菜单关联表'; - --- 初始化超级租户 -INSERT INTO `t_sys_tenant` (`name`, `code`, `description`, `is_super`, `tenant_type`, `valid_state`) -VALUES ('平台管理员', 'platform', '平台超级租户', 1, 'platform', 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); diff --git a/java-backend/src/main/resources/db/migration/V2__create_sys_user.sql b/java-backend/src/main/resources/db/migration/V2__create_sys_user.sql deleted file mode 100644 index af644c0..0000000 --- a/java-backend/src/main/resources/db/migration/V2__create_sys_user.sql +++ /dev/null @@ -1,50 +0,0 @@ --- 用户表 -CREATE TABLE IF NOT EXISTS `t_sys_user` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `username` VARCHAR(50) NOT NULL COMMENT '用户名(在租户内唯一)', - `password` VARCHAR(100) NOT NULL COMMENT '密码(加密存储)', - `nickname` VARCHAR(50) DEFAULT NULL COMMENT '昵称', - `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱(在租户内唯一,可选)', - `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号(全局唯一,用于手机号登录)', - `wx_openid` VARCHAR(100) DEFAULT NULL COMMENT '微信 OpenID', - `wx_unionid` VARCHAR(100) DEFAULT NULL COMMENT '微信 UnionID', - `user_source` VARCHAR(50) DEFAULT 'admin_created' COMMENT '用户来源:admin_created/self_registered/child_migrated', - `user_type` VARCHAR(20) DEFAULT 'adult' COMMENT '用户类型:adult/child', - `city` VARCHAR(50) DEFAULT NULL COMMENT '所在城市', - `birthday` DATE DEFAULT NULL COMMENT '出生日期', - `gender` VARCHAR(10) DEFAULT NULL COMMENT '性别:male-男,female-女', - `avatar` VARCHAR(500) DEFAULT NULL COMMENT '头像 URL', - `organization` VARCHAR(100) DEFAULT NULL COMMENT '所属单位(用于评委等独立用户)', - `status` VARCHAR(20) DEFAULT 'enabled' COMMENT '账号状态:enabled-启用,disabled-停用', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_username` (`tenant_id`, `username`), - UNIQUE KEY `uk_tenant_email` (`tenant_id`, `email`), - UNIQUE KEY `uk_phone` (`phone`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_user_type` (`user_type`), - KEY `idx_user_source` (`user_source`), - KEY `idx_status` (`status`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'; - --- 用户角色关联表 -CREATE TABLE IF NOT EXISTS `t_auth_user_role` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `user_id` BIGINT NOT NULL COMMENT '用户 ID', - `role_id` BIGINT NOT NULL COMMENT '角色 ID', - PRIMARY KEY (`id`), - KEY `idx_user_id` (`user_id`), - KEY `idx_role_id` (`role_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户角色关联表'; - --- 初始化管理员账户(密码为 admin123,使用 bcrypt 加密) -INSERT INTO `t_sys_user` (`tenant_id`, `username`, `password`, `nickname`, `status`, `valid_state`) -VALUES (1, 'admin', '$2a$10$N.zmdr9k7uOCQb376NoUnuTJ8iAt6Z5EHsM8lqkkO9QS3TzCjH3rS', '管理员', 'enabled', 1) -ON DUPLICATE KEY UPDATE `username` = VALUES(`username`); diff --git a/java-backend/src/main/resources/db/migration/V3__create_auth_role_permission_menu.sql b/java-backend/src/main/resources/db/migration/V3__create_auth_role_permission_menu.sql deleted file mode 100644 index 48a30d9..0000000 --- a/java-backend/src/main/resources/db/migration/V3__create_auth_role_permission_menu.sql +++ /dev/null @@ -1,100 +0,0 @@ --- 角色表 -CREATE TABLE IF NOT EXISTS `t_auth_role` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(50) NOT NULL COMMENT '角色名称(在租户内唯一)', - `code` VARCHAR(50) NOT NULL COMMENT '角色编码(在租户内唯一)', - `description` VARCHAR(200) DEFAULT NULL COMMENT '角色描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_code` (`tenant_id`, `code`), - UNIQUE KEY `uk_tenant_name` (`tenant_id`, `name`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色表'; - --- 权限表 -CREATE TABLE IF NOT EXISTS `t_auth_permission` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(50) NOT NULL COMMENT '权限名称', - `code` VARCHAR(50) NOT NULL COMMENT '权限编码(在租户内唯一)', - `resource` VARCHAR(50) NOT NULL COMMENT '资源名称,如 user, role, menu', - `action` VARCHAR(50) NOT NULL COMMENT '操作类型,如 create, read, update, delete', - `description` VARCHAR(200) DEFAULT NULL COMMENT '权限描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_code` (`tenant_id`, `code`), - UNIQUE KEY `uk_tenant_resource_action` (`tenant_id`, `resource`, `action`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_resource_action` (`resource`, `action`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='权限表'; - --- 菜单表 -CREATE TABLE IF NOT EXISTS `t_auth_menu` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `name` VARCHAR(50) NOT NULL COMMENT '菜单名称', - `path` VARCHAR(200) DEFAULT NULL COMMENT '路由路径', - `icon` VARCHAR(50) DEFAULT NULL COMMENT '图标', - `component` VARCHAR(200) DEFAULT NULL COMMENT '组件路径', - `parent_id` BIGINT DEFAULT NULL COMMENT '父菜单 ID', - `permission` VARCHAR(50) DEFAULT NULL COMMENT '权限编码(用于控制菜单显示)', - `sort` INT DEFAULT 0 COMMENT '排序', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - KEY `idx_parent_id` (`parent_id`), - KEY `idx_sort` (`sort`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='菜单表'; - --- 角色权限关联表 -CREATE TABLE IF NOT EXISTS `t_auth_role_permission` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `role_id` BIGINT NOT NULL COMMENT '角色 ID', - `permission_id` BIGINT NOT NULL COMMENT '权限 ID', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_role_permission` (`role_id`, `permission_id`), - KEY `idx_role_id` (`role_id`), - KEY `idx_permission_id` (`permission_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色权限关联表'; - --- 初始化默认角色 -INSERT INTO `t_auth_role` (`tenant_id`, `name`, `code`, `description`, `valid_state`) VALUES -(1, '超级管理员', 'super_admin', '系统超级管理员角色', 1), -(1, '管理员', 'admin', '系统管理员角色', 1), -(1, '普通用户', 'user', '普通用户角色', 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - --- 初始化基础权限 -INSERT INTO `t_auth_permission` (`tenant_id`, `name`, `code`, `resource`, `action`, `description`, `valid_state`) VALUES -(1, '用户创建', 'user:create', 'user', 'create', '创建用户权限', 1), -(1, '用户查询', 'user:read', 'user', 'read', '查询用户权限', 1), -(1, '用户更新', 'user:update', 'user', 'update', '更新用户权限', 1), -(1, '用户删除', 'user:delete', 'user', 'delete', '删除用户权限', 1), -(1, '用户管理', 'user:manage', 'user', 'manage', '用户管理权限', 1), -(1, '角色创建', 'role:create', 'role', 'create', '创建角色权限', 1), -(1, '角色查询', 'role:read', 'role', 'read', '查询角色权限', 1), -(1, '角色更新', 'role:update', 'role', 'update', '更新角色权限', 1), -(1, '角色删除', 'role:delete', 'role', 'delete', '删除角色权限', 1), -(1, '租户创建', 'tenant:create', 'tenant', 'create', '创建租户权限', 1), -(1, '租户查询', 'tenant:read', 'tenant', 'read', '查询租户权限', 1), -(1, '租户更新', 'tenant:update', 'tenant', 'update', '更新租户权限', 1), -(1, '租户删除', 'tenant:delete', 'tenant', 'delete', '删除租户权限', 1), -(1, '超级管理员权限', 'super_admin', 'system', 'all', '系统超级管理员权限', 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); diff --git a/java-backend/src/main/resources/db/migration/V4__create_sys_dict.sql b/java-backend/src/main/resources/db/migration/V4__create_sys_dict.sql deleted file mode 100644 index 661f14e..0000000 --- a/java-backend/src/main/resources/db/migration/V4__create_sys_dict.sql +++ /dev/null @@ -1,54 +0,0 @@ --- 字典表 -CREATE TABLE IF NOT EXISTS `t_sys_dict` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(50) NOT NULL COMMENT '字典名称', - `code` VARCHAR(50) NOT NULL COMMENT '字典编码(在租户内唯一)', - `description` VARCHAR(200) DEFAULT NULL COMMENT '字典描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_code` (`tenant_id`, `code`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_code` (`code`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典表'; - --- 字典项表 -CREATE TABLE IF NOT EXISTS `t_sys_dict_item` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `dict_id` BIGINT NOT NULL COMMENT '字典 ID', - `label` VARCHAR(100) NOT NULL COMMENT '字典项标签', - `value` VARCHAR(100) NOT NULL COMMENT '字典项值', - `sort` INT DEFAULT 0 COMMENT '排序', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - KEY `idx_dict_id` (`dict_id`), - KEY `idx_sort` (`sort`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='字典项表'; - --- 初始化基础字典数据 -INSERT INTO `t_sys_dict` (`tenant_id`, `name`, `code`, `description`, `valid_state`) VALUES -(1, '性别', 'gender', '性别字典', 1), -(1, '用户类型', 'user_type', '用户类型字典', 1), -(1, '账号状态', 'user_status', '账号状态字典', 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); - -INSERT INTO `t_sys_dict_item` (`dict_id`, `label`, `value`, `sort`, `valid_state`) VALUES -(1, '男', 'male', 1, 1), -(1, '女', 'female', 2, 1), -(2, '成人', 'adult', 1, 1), -(2, '儿童', 'child', 2, 1), -(3, '启用', 'enabled', 1, 1), -(3, '禁用', 'disabled', 2, 1) -ON DUPLICATE KEY UPDATE `label` = VALUES(`label`); diff --git a/java-backend/src/main/resources/db/migration/V5__create_sys_config.sql b/java-backend/src/main/resources/db/migration/V5__create_sys_config.sql deleted file mode 100644 index 303e1f2..0000000 --- a/java-backend/src/main/resources/db/migration/V5__create_sys_config.sql +++ /dev/null @@ -1,29 +0,0 @@ --- 系统配置表 -CREATE TABLE IF NOT EXISTS `t_sys_config` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `config_key` VARCHAR(100) NOT NULL COMMENT '配置键(在租户内唯一)', - `config_value` VARCHAR(500) DEFAULT NULL COMMENT '配置值', - `config_name` VARCHAR(100) DEFAULT NULL COMMENT '配置名称', - `description` VARCHAR(200) DEFAULT NULL COMMENT '配置描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_config_key` (`tenant_id`, `config_key`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_config_key` (`config_key`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='系统配置表'; - --- 初始化基础配置数据 -INSERT INTO `t_sys_config` (`tenant_id`, `config_key`, `config_value`, `config_name`, `description`, `valid_state`) VALUES -(1, 'system.title', '图书馆创作平台', '系统标题', '平台名称显示', 1), -(1, 'system.logo', '', '系统 Logo', '平台 Logo URL', 1), -(1, 'system.footer', '© 2024 图书馆创作平台', '系统页脚', '页脚版权信息', 1), -(1, 'user.default_avatar', '', '默认头像', '新用户默认头像 URL', 1), -(1, 'user.initial_password', '123456', '初始密码', '管理员创建用户时的默认密码', 1) -ON DUPLICATE KEY UPDATE `config_value` = VALUES(`config_value`); diff --git a/java-backend/src/main/resources/db/migration/V6__create_biz_school_grade_class_department.sql b/java-backend/src/main/resources/db/migration/V6__create_biz_school_grade_class_department.sql deleted file mode 100644 index 1fbc5d5..0000000 --- a/java-backend/src/main/resources/db/migration/V6__create_biz_school_grade_class_department.sql +++ /dev/null @@ -1,100 +0,0 @@ --- 学校信息表 -CREATE TABLE IF NOT EXISTS `t_biz_school` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID(一对一)', - `address` VARCHAR(500) DEFAULT NULL COMMENT '学校地址', - `phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话', - `principal` VARCHAR(50) DEFAULT NULL COMMENT '校长姓名', - `established` DATE DEFAULT NULL COMMENT '建校时间', - `description` VARCHAR(1000) DEFAULT NULL COMMENT '学校描述', - `logo` VARCHAR(500) DEFAULT NULL COMMENT '学校 Logo URL', - `website` VARCHAR(200) DEFAULT NULL COMMENT '学校网站', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_id` (`tenant_id`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学校信息表'; - --- 年级表 -CREATE TABLE IF NOT EXISTS `t_biz_grade` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(50) NOT NULL COMMENT '年级名称(如:一年级、二年级)', - `code` VARCHAR(50) NOT NULL COMMENT '年级编码(在租户内唯一,如:grade_1, grade_2)', - `level` INT NOT NULL COMMENT '年级级别(用于排序,如:1, 2, 3)', - `description` VARCHAR(200) DEFAULT NULL COMMENT '年级描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_code` (`tenant_id`, `code`), - UNIQUE KEY `uk_tenant_level` (`tenant_id`, `level`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_level` (`level`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='年级表'; - --- 班级表 -CREATE TABLE IF NOT EXISTS `t_biz_class` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `grade_id` BIGINT NOT NULL COMMENT '年级 ID', - `name` VARCHAR(50) NOT NULL COMMENT '班级名称(如:一年级 1 班、二年级 2 班)', - `code` VARCHAR(50) NOT NULL COMMENT '班级编码(在租户内唯一)', - `type` TINYINT DEFAULT 1 COMMENT '班级类型:1-行政班级(教学班级),2-兴趣班', - `capacity` INT DEFAULT NULL COMMENT '班级容量(可选)', - `description` VARCHAR(200) DEFAULT NULL COMMENT '班级描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_code` (`tenant_id`, `code`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_grade_id` (`grade_id`), - KEY `idx_type` (`type`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='班级表'; - --- 部门表 -CREATE TABLE IF NOT EXISTS `t_biz_department` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `name` VARCHAR(50) NOT NULL COMMENT '部门名称', - `code` VARCHAR(50) NOT NULL COMMENT '部门编码(在租户内唯一)', - `parent_id` BIGINT DEFAULT NULL COMMENT '父部门 ID(支持树形结构)', - `description` VARCHAR(200) DEFAULT NULL COMMENT '部门描述', - `sort` INT DEFAULT 0 COMMENT '排序', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_code` (`tenant_id`, `code`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_parent_id` (`parent_id`), - KEY `idx_sort` (`sort`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='部门表'; - --- 初始化年级数据 -INSERT INTO `t_biz_grade` (`tenant_id`, `name`, `code`, `level`, `description`, `valid_state`) VALUES -(1, '一年级', 'grade_1', 1, '小学一年级', 1), -(1, '二年级', 'grade_2', 2, '小学二年级', 1), -(1, '三年级', 'grade_3', 3, '小学三年级', 1), -(1, '四年级', 'grade_4', 4, '小学四年级', 1), -(1, '五年级', 'grade_5', 5, '小学五年级', 1), -(1, '六年级', 'grade_6', 6, '小学六年级', 1) -ON DUPLICATE KEY UPDATE `name` = VALUES(`name`); diff --git a/java-backend/src/main/resources/db/migration/V7__create_biz_teacher_student.sql b/java-backend/src/main/resources/db/migration/V7__create_biz_teacher_student.sql deleted file mode 100644 index 8c0fbe3..0000000 --- a/java-backend/src/main/resources/db/migration/V7__create_biz_teacher_student.sql +++ /dev/null @@ -1,69 +0,0 @@ --- 教师表 -CREATE TABLE IF NOT EXISTS `t_biz_teacher` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `user_id` BIGINT NOT NULL COMMENT '用户 ID(一对一)', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `department_id` BIGINT NOT NULL COMMENT '部门 ID', - `employee_no` VARCHAR(50) DEFAULT NULL COMMENT '工号(在租户内唯一)', - `phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话', - `id_card` VARCHAR(50) DEFAULT NULL COMMENT '身份证号', - `gender` TINYINT DEFAULT NULL COMMENT '性别:1-男,2-女', - `birth_date` DATE DEFAULT NULL COMMENT '出生日期', - `hire_date` DATE DEFAULT NULL COMMENT '入职日期', - `subject` VARCHAR(50) DEFAULT NULL COMMENT '任教科目(可选,如:语文、数学)', - `title` VARCHAR(50) DEFAULT NULL COMMENT '职称(可选,如:高级教师、一级教师)', - `description` VARCHAR(1000) DEFAULT NULL COMMENT '教师描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_user_id` (`user_id`), - UNIQUE KEY `uk_tenant_employee_no` (`tenant_id`, `employee_no`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_department_id` (`department_id`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='教师表'; - --- 学生表 -CREATE TABLE IF NOT EXISTS `t_biz_student` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `user_id` BIGINT NOT NULL COMMENT '用户 ID(一对一)', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `class_id` BIGINT NOT NULL COMMENT '行政班级 ID', - `student_no` VARCHAR(50) DEFAULT NULL COMMENT '学号(在租户内唯一)', - `phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话', - `id_card` VARCHAR(50) DEFAULT NULL COMMENT '身份证号', - `gender` TINYINT DEFAULT NULL COMMENT '性别:1-男,2-女', - `birth_date` DATE DEFAULT NULL COMMENT '出生日期', - `enrollment_date` DATE DEFAULT NULL COMMENT '入学日期', - `parent_name` VARCHAR(50) DEFAULT NULL COMMENT '家长姓名', - `parent_phone` VARCHAR(50) DEFAULT NULL COMMENT '家长电话', - `address` VARCHAR(500) DEFAULT NULL COMMENT '家庭地址', - `description` VARCHAR(1000) DEFAULT NULL COMMENT '学生描述', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_user_id` (`user_id`), - UNIQUE KEY `uk_tenant_student_no` (`tenant_id`, `student_no`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_class_id` (`class_id`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学生表'; - --- 学生兴趣班关联表 -CREATE TABLE IF NOT EXISTS `t_biz_student_interest_class` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `student_id` BIGINT NOT NULL COMMENT '学生 ID', - `class_id` BIGINT NOT NULL COMMENT '兴趣班 ID', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_student_class` (`student_id`, `class_id`), - KEY `idx_student_id` (`student_id`), - KEY `idx_class_id` (`class_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='学生兴趣班关联表'; diff --git a/java-backend/src/main/resources/db/migration/V8__create_biz_contest.sql b/java-backend/src/main/resources/db/migration/V8__create_biz_contest.sql deleted file mode 100644 index b6cde0d..0000000 --- a/java-backend/src/main/resources/db/migration/V8__create_biz_contest.sql +++ /dev/null @@ -1,85 +0,0 @@ --- 竞赛/活动表 -CREATE TABLE IF NOT EXISTS `t_biz_contest` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_name` VARCHAR(200) NOT NULL COMMENT '赛事名称', - `contest_type` VARCHAR(50) NOT NULL COMMENT '赛事类型:individual/team', - `contest_state` VARCHAR(50) DEFAULT 'unpublished' COMMENT '赛事状态:unpublished/published', - `status` VARCHAR(50) DEFAULT 'ongoing' COMMENT '赛事进度状态:ongoing/finished', - `start_time` DATETIME NOT NULL COMMENT '赛事开始时间', - `end_time` DATETIME NOT NULL COMMENT '赛事结束时间', - `address` VARCHAR(500) DEFAULT NULL COMMENT '线下地址', - `content` TEXT DEFAULT NULL COMMENT '赛事详情', - `contest_tenants` JSON DEFAULT NULL COMMENT '授权租户 ID 数组', - `cover_url` VARCHAR(500) DEFAULT NULL COMMENT '封面 URL', - `poster_url` VARCHAR(500) DEFAULT NULL COMMENT '海报 URL', - `contact_name` VARCHAR(50) DEFAULT NULL COMMENT '联系人', - `contact_phone` VARCHAR(50) DEFAULT NULL COMMENT '联系电话', - `contact_qrcode` VARCHAR(500) DEFAULT NULL COMMENT '联系人二维码', - `organizers` JSON DEFAULT NULL COMMENT '主办单位数组', - `co_organizers` JSON DEFAULT NULL COMMENT '协办单位数组', - `sponsors` JSON DEFAULT NULL COMMENT '赞助单位数组', - -- 报名配置 - `register_start_time` DATETIME NOT NULL COMMENT '报名开始时间', - `register_end_time` DATETIME NOT NULL COMMENT '报名结束时间', - `register_state` VARCHAR(50) DEFAULT NULL COMMENT '报名任务状态:started/closed', - `require_audit` TINYINT DEFAULT 1 COMMENT '报名是否需要审核', - `allowed_grades` JSON DEFAULT NULL COMMENT '允许报名的年级 ID 数组', - `allowed_classes` JSON DEFAULT NULL COMMENT '允许报名的班级 ID 数组', - `team_min_members` INT DEFAULT NULL COMMENT '团队最少成员数', - `team_max_members` INT DEFAULT NULL COMMENT '团队最多成员数', - -- 定向推送条件 - `target_cities` JSON DEFAULT NULL COMMENT '目标城市列表', - `age_min` INT DEFAULT NULL COMMENT '最小年龄限制', - `age_max` INT DEFAULT NULL COMMENT '最大年龄限制', - -- 作品配置 - `submit_rule` VARCHAR(50) DEFAULT 'once' COMMENT '提交规则:once/resubmit', - `submit_start_time` DATETIME NOT NULL COMMENT '作品提交开始时间', - `submit_end_time` DATETIME NOT NULL COMMENT '作品提交结束时间', - `work_type` VARCHAR(50) DEFAULT NULL COMMENT '作品类型:image/video/document/code/other', - `work_requirement` TEXT DEFAULT NULL COMMENT '作品要求说明', - -- 评审配置 - `review_rule_id` BIGINT DEFAULT NULL COMMENT '评审规则 ID', - `review_start_time` DATETIME DEFAULT NULL COMMENT '评审开始时间', - `review_end_time` DATETIME DEFAULT NULL COMMENT '评审结束时间', - -- 赛果配置 - `result_state` VARCHAR(50) DEFAULT 'unpublished' COMMENT '赛果状态:unpublished/published', - `result_publish_time` DATETIME DEFAULT NULL COMMENT '结果发布时间', - -- 可见范围 - `visibility` VARCHAR(50) DEFAULT 'designated' COMMENT '可见范围:public/designated/internal', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `creator` BIGINT DEFAULT NULL COMMENT '创建人 ID', - `modifier` BIGINT DEFAULT NULL COMMENT '修改人 ID', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `modify_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_contest_name` (`contest_name`), - KEY `idx_contest_state` (`contest_state`), - KEY `idx_status` (`status`), - KEY `idx_contest_type` (`contest_type`), - KEY `idx_visibility` (`visibility`), - KEY `idx_valid_state` (`valid_state`), - KEY `idx_start_time` (`start_time`), - KEY `idx_end_time` (`end_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛/活动表'; - --- 竞赛附件表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_attachment` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '竞赛 ID', - `name` VARCHAR(100) NOT NULL COMMENT '附件名称', - `url` VARCHAR(500) NOT NULL COMMENT '附件 URL', - `type` VARCHAR(50) DEFAULT NULL COMMENT '附件类型', - `size` BIGINT DEFAULT NULL COMMENT '文件大小(字节)', - `sort` INT DEFAULT 0 COMMENT '排序', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_sort` (`sort`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛附件表'; diff --git a/java-backend/src/main/resources/db/migration/V9__create_biz_contest_registration_team.sql b/java-backend/src/main/resources/db/migration/V9__create_biz_contest_registration_team.sql deleted file mode 100644 index 98e2a94..0000000 --- a/java-backend/src/main/resources/db/migration/V9__create_biz_contest_registration_team.sql +++ /dev/null @@ -1,82 +0,0 @@ --- 竞赛报名表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_registration` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `tenant_id` BIGINT NOT NULL COMMENT '所属租户 ID', - `registration_type` VARCHAR(50) DEFAULT NULL COMMENT '报名类型:individual/team', - `team_id` BIGINT DEFAULT NULL COMMENT '团队 ID', - `team_name` VARCHAR(100) DEFAULT NULL COMMENT '团队名称快照(团队赛)', - `user_id` BIGINT NOT NULL COMMENT '账号 ID', - `account_no` VARCHAR(50) NOT NULL COMMENT '报名账号', - `account_name` VARCHAR(100) NOT NULL COMMENT '报名账号名称', - `role` VARCHAR(50) DEFAULT NULL COMMENT '报名角色快照:leader/member/mentor', - `registration_state` VARCHAR(50) DEFAULT 'pending' COMMENT '报名状态:pending/passed/rejected/withdrawn', - `participant_type` VARCHAR(50) DEFAULT 'self' COMMENT '参与者类型:self-自己/child-代子女报名', - `child_id` BIGINT DEFAULT NULL COMMENT '子女 ID', - `registrant` BIGINT DEFAULT NULL COMMENT '实际报名人用户 ID', - `registration_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '报名时间', - `reason` VARCHAR(1023) DEFAULT NULL COMMENT '审核理由', - `operator` BIGINT DEFAULT NULL COMMENT '审核人用户 ID', - `operation_date` DATETIME DEFAULT NULL COMMENT '审核时间', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_user_id` (`user_id`), - KEY `idx_team_id` (`team_id`), - KEY `idx_registration_state` (`registration_state`), - KEY `idx_registration_time` (`registration_time`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛报名表'; - --- 竞赛报名指导老师关联表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_registration_teacher` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `registration_id` BIGINT NOT NULL COMMENT '报名 ID', - `user_id` BIGINT NOT NULL COMMENT '老师用户 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `is_default` TINYINT DEFAULT 0 COMMENT '是否默认指导老师', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_registration_user` (`registration_id`, `user_id`), - KEY `idx_user_id` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛报名指导老师关联表'; - --- 竞赛团队表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_team` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '团队所属租户 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `team_name` VARCHAR(100) NOT NULL COMMENT '团队名称', - `leader_user_id` BIGINT NOT NULL COMMENT '团队负责人用户 ID', - `max_members` INT DEFAULT NULL COMMENT '团队最大成员数', - `create_by` VARCHAR(50) DEFAULT NULL COMMENT '创建人', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - `update_by` VARCHAR(50) DEFAULT NULL COMMENT '更新人', - `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', - `valid_state` TINYINT DEFAULT 1 COMMENT '有效状态:1-有效,2-失效', - `deleted` TINYINT DEFAULT 0 COMMENT '逻辑删除标识(0-未删除,1-已删除)', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_tenant_contest_team` (`tenant_id`, `contest_id`, `team_name`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_leader_user_id` (`leader_user_id`), - KEY `idx_valid_state` (`valid_state`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛团队表'; - --- 竞赛团队成员表 -CREATE TABLE IF NOT EXISTS `t_biz_contest_team_member` ( - `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键 ID', - `tenant_id` BIGINT NOT NULL COMMENT '租户 ID', - `team_id` BIGINT NOT NULL COMMENT '团队 ID', - `contest_id` BIGINT NOT NULL COMMENT '赛事 ID', - `user_id` BIGINT NOT NULL COMMENT '用户 ID', - `role` VARCHAR(50) DEFAULT 'member' COMMENT '团队角色:leader/member/mentor', - `join_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '加入时间', - PRIMARY KEY (`id`), - UNIQUE KEY `uk_team_user` (`team_id`, `user_id`), - KEY `idx_tenant_id` (`tenant_id`), - KEY `idx_contest_id` (`contest_id`), - KEY `idx_user_id` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='竞赛团队成员表'; diff --git a/java-backend/src/main/resources/logback-spring.xml b/java-backend/src/main/resources/logback-spring.xml deleted file mode 100644 index eebdfa5..0000000 --- a/java-backend/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - ${CONSOLE_LOG_PATTERN} - UTF-8 - - - - - - logs/creation-info.log - - ${LOG_PATTERN} - UTF-8 - - - INFO - ACCEPT - DENY - - - logs/creation-info.%d{yyyy-MM-dd}.log - 30 - 1GB - - - - - - logs/creation-error.log - - ${LOG_PATTERN} - UTF-8 - - - ERROR - ACCEPT - DENY - - - logs/creation-error.%d{yyyy-MM-dd}.log - 30 - 500MB - - - - - - - 512 - 0 - - - - - 512 - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/java-backend/src/main/resources/mapper/ContestRegistrationMapper.xml b/java-backend/src/main/resources/mapper/ContestRegistrationMapper.xml deleted file mode 100644 index 79e63f5..0000000 --- a/java-backend/src/main/resources/mapper/ContestRegistrationMapper.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/java-backend/src/main/resources/mapper/ContestWorkAssignmentMapper.xml b/java-backend/src/main/resources/mapper/ContestWorkAssignmentMapper.xml deleted file mode 100644 index baa4bab..0000000 --- a/java-backend/src/main/resources/mapper/ContestWorkAssignmentMapper.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/java-backend/src/main/resources/mapper/ContestWorkMapper.xml b/java-backend/src/main/resources/mapper/ContestWorkMapper.xml deleted file mode 100644 index 94ee852..0000000 --- a/java-backend/src/main/resources/mapper/ContestWorkMapper.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - diff --git a/java-backend/src/main/resources/mapper/DictItemMapper.xml b/java-backend/src/main/resources/mapper/DictItemMapper.xml deleted file mode 100644 index ce6ca53..0000000 --- a/java-backend/src/main/resources/mapper/DictItemMapper.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - INSERT INTO t_sys_dict_item (dict_id, label, value, sort, valid_state) - VALUES - - (#{item.dictId}, #{item.label}, #{item.value}, #{item.sort}, #{item.validState}) - - - - diff --git a/java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml b/java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml deleted file mode 100644 index 2f1b1e8..0000000 --- a/java-backend/src/main/resources/mapper/HomeworkReviewDimensionMapper.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - UPDATE t_biz_homework_review_dimension SET deleted = 1 WHERE rule_id = #{ruleId} - - - - - - diff --git a/java-backend/src/main/resources/mapper/RolePermissionMapper.xml b/java-backend/src/main/resources/mapper/RolePermissionMapper.xml deleted file mode 100644 index cfd9d2c..0000000 --- a/java-backend/src/main/resources/mapper/RolePermissionMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - INSERT INTO t_auth_role_permission (role_id, permission_id) - VALUES - - (#{item.roleId}, #{item.permissionId}) - - - - - INSERT INTO t_auth_role_permission (role_id, permission_id) - VALUES - - (#{item.roleId}, #{item.permissionId}) - - - - diff --git a/java-backend/src/main/resources/mapper/SysLogMapper.xml b/java-backend/src/main/resources/mapper/SysLogMapper.xml deleted file mode 100644 index e834a48..0000000 --- a/java-backend/src/main/resources/mapper/SysLogMapper.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DELETE FROM t_sys_log - WHERE create_time < #{cutoffDate} - AND (deleted = 0 OR deleted IS NULL) - - - diff --git a/java-backend/src/main/resources/mapper/UserRoleMapper.xml b/java-backend/src/main/resources/mapper/UserRoleMapper.xml deleted file mode 100644 index e8822ce..0000000 --- a/java-backend/src/main/resources/mapper/UserRoleMapper.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - INSERT INTO t_auth_user_role (user_id, role_id) - VALUES - - (#{item.userId}, #{item.roleId}) - - - - diff --git a/java-frontend/.cursor/rules/frontend-specific.mdc b/java-frontend/.cursor/rules/frontend-specific.mdc deleted file mode 100644 index 68ba710..0000000 --- a/java-frontend/.cursor/rules/frontend-specific.mdc +++ /dev/null @@ -1,237 +0,0 @@ ---- -description: 前端特定的开发规范(仅作用于 frontend 目录) -globs: -alwaysApply: true ---- - -# 前端特定规范 - -本规则仅作用于 `frontend/` 目录。 - -## Ant Design Vue 组件使用 - -### 表格组件 - -```vue - -``` - -### 表单组件 - -```vue - -``` - -### Modal 弹窗 - -```vue - -``` - -## 消息提示 - -```typescript -import { message, notification } from 'ant-design-vue'; - -// 成功提示 -message.success('操作成功'); - -// 错误提示 -message.error('操作失败'); - -// 通知 -notification.success({ - message: '成功', - description: '用户创建成功', -}); -``` - -## Tailwind CSS 常用类 - -```html - -

-
-
- - -
- - -

- - -\n" - + " \n" - + "

\n" - + " 企业模拟C端(iframe 4TAB模式)→\n" - + " "; - } - - // ══════════════════════════════════════════ - // 功能6:Token 刷新接口 - // ══════════════════════════════════════════ - - /** - * Token 刷新接口(供企业前端 JS 在 TOKEN_EXPIRED 时调用) - */ - @GetMapping("/api/refresh-token") - @ResponseBody - public Map refreshToken(@RequestParam String phone) throws Exception { - String token = exchangeToken(phone); - Map result = new HashMap<>(); - result.put("token", token); - result.put("orgId", ORG_ID); - return result; - } - - // ══════════════════════════════════════════ - // 功能2:认证回调(H5 token 失效后跳回) - // ══════════════════════════════════════════ - - /** - * H5 token 失效后,H5 自动跳转到此页面(企业在管理后台配置的"认证回调URL")。 - * - * 流程: - * 1. 验证用户身份(企业自身的登录/session 机制) - * 2. 重新调 auth/session 换取新 token - * 3. 重定向回 H5(带 returnPath 恢复创作进度) - * - * H5 跳转过来的 URL 格式: - * /leai-auth?returnPath=/creating&orgId=ORG001 - */ - @GetMapping("/leai-auth") - public void authCallback(@RequestParam(required = false) String returnPath, - @RequestParam(required = false) String orgId, - HttpServletRequest request, - HttpServletResponse response) throws Exception { - // 1. 验证用户身份 - // 生产环境: 检查企业 session/JWT, 获取用户手机号 - // demo 中简化处理, 返回测试手机号 - String phone = getPhoneFromSession(request); - if (phone == null || phone.isEmpty()) { - response.setContentType("text/html;charset=UTF-8"); - response.setStatus(401); - response.getWriter().write("

请先登录企业系统

" - + "

token 已失效, 请 返回首页 重新进入。

"); - return; - } - - // 2. 重新换 token - String newToken = exchangeToken(phone); - - // 3. 重定向回 H5(带 returnPath 恢复创作进度) - // returnPath 必须原样传回, H5 用它恢复到用户之前的创作页面 - StringBuilder url = new StringBuilder(LEAI_H5_URL) - .append("/?token=").append(URLEncoder.encode(newToken, "UTF-8")) - .append("&orgId=").append(URLEncoder.encode(ORG_ID, "UTF-8")) - .append("&phone=").append(URLEncoder.encode(phone, "UTF-8")); - if (returnPath != null && !returnPath.isEmpty()) { - url.append("&returnPath=").append(URLEncoder.encode(returnPath, "UTF-8")); - } - - log.info("[AuthCallback] Re-authenticated phone=" + phone - + ", returnPath=" + returnPath); - response.sendRedirect(url.toString()); - } - - // ══════════════════════════════════════════ - // 功能3:Webhook 接收 + HMAC-SHA256 签名验证 - // ══════════════════════════════════════════ - - /** - * 接收乐读派 Webhook 回调。 - * - * Header: - * X-Webhook-Id: 事件唯一 ID (如 evt_190368671438289) - * X-Webhook-Event: 事件类型 (work.status_changed / work.progress) - * X-Webhook-Timestamp: 毫秒时间戳 - * X-Webhook-Signature: HMAC-SHA256={hex} - * - * 签名体: "{X-Webhook-Id}.{X-Webhook-Timestamp}.{请求body原文}" - * 签名值: HMAC-SHA256(签名体, appSecret).toHex() - */ - @PostMapping("/webhook/leai") - @ResponseBody - public Map webhook( - @RequestBody String rawBody, - @RequestHeader("X-Webhook-Id") String webhookId, - @RequestHeader("X-Webhook-Event") String webhookEvent, - @RequestHeader("X-Webhook-Timestamp") String timestamp, - @RequestHeader("X-Webhook-Signature") String signature) { - - log.info("[Webhook] Received event=" + webhookEvent + ", id=" + webhookId); - - // 1. 时间窗口检查(5分钟, 防重放攻击) - long ts; - try { - ts = Long.parseLong(timestamp); - } catch (NumberFormatException e) { - log.warning("[Webhook] Invalid timestamp: " + timestamp); - throw new RuntimeException("invalid timestamp"); - } - if (Math.abs(System.currentTimeMillis() - ts) > 300_000) { - log.warning("[Webhook] Timestamp expired: " + timestamp); - throw new RuntimeException("timestamp expired"); - } - - // 2. 幂等去重 - if (processedEvents.contains(webhookId)) { - log.info("[Webhook] Duplicate event, skipping: " + webhookId); - return Collections.singletonMap("status", "duplicate"); - } - - // 3. 验证 HMAC-SHA256 签名 - String signData = webhookId + "." + timestamp + "." + rawBody; - String expected = "HMAC-SHA256=" + hmacSha256(signData, APP_SECRET); - if (!MessageDigest.isEqual(expected.getBytes(StandardCharsets.UTF_8), - signature.getBytes(StandardCharsets.UTF_8))) { - log.warning("[Webhook] Signature mismatch! expected=" + expected); - throw new RuntimeException("invalid signature"); - } - - // 4. 解析事件 payload - // 简易 JSON 解析(生产环境建议使用 Jackson 或 Gson) - Map payload = parseJsonObject(rawBody); - String event = toString(payload.get("event"), ""); - @SuppressWarnings("unchecked") - Map data = (Map) payload.get("data"); - if (data == null) { - data = new HashMap<>(); - } - - String workId = toString(data.get("work_id"), null); - - // 5. 按 V4.0 同步规则处理 - // ════════════════════════════════════════════════════════════ - // TODO [企业开发者]: 将下面的 syncWork() 替换为你的数据库操作 - // 示例: - // if (remoteStatus == -1) → UPDATE your_table SET status=-1, fail_reason=? WHERE work_id=? - // if (remoteStatus == 2) → UPDATE your_table SET status=2, progress=? WHERE work_id=? - // if (remoteStatus > localStatus) → UPDATE your_table SET status=?, title=?, page_list=? WHERE work_id=? - // 本 Demo 使用内存 Map 存储,生产环境请替换为 MyBatis/JPA 数据库操作 - // ════════════════════════════════════════════════════════════ - if (workId != null && !workId.isEmpty()) { - syncWork(workId, data, "Webhook[" + event + "]"); - } - - // 6. 标记已处理 - processedEvents.add(webhookId); - return Collections.singletonMap("status", "ok"); - } - - // ══════════════════════════════════════════ - // 功能4:B3 定时对账(每30分钟) - // ══════════════════════════════════════════ - - /** - * 每30分钟调用 B3 接口(GET /api/v1/query/works)对账,补偿 Webhook 遗漏。 - * - *

为什么用30分钟而不是5分钟: - *

    - *
  • Webhook 是主通道,实时性已经足够;B3 对账只是兜底补偿偶发遗漏。
  • - *
  • 5分钟轮询对乐读派 API 造成不必要的查询压力,尤其在并发机构较多时。
  • - *
  • 30分钟已能覆盖绝大多数 Webhook 重试超时场景(乐读派 Webhook 重试策略最长约10分钟)。
  • - *
- * 建议:生产环境不要低于30分钟;如需更高实时性,应优先接入 Webhook,而非缩短 B3 轮询间隔。 - * - *

查询范围:最近2小时内更新的作品(覆盖2个对账周期,确保不遗漏边界数据)。 - */ - @Scheduled(fixedRate = 30 * 60 * 1000, initialDelay = 60 * 1000) - public void b3Reconcile() { - log.info("[B3] Starting reconciliation..."); - try { - // 每30分钟对账一次(兜底补偿Webhook遗漏) - // 建议不要低于30分钟,避免对乐读派API造成查询压力 - // 查询范围:最近2小时内更新的作品(覆盖2个对账周期) - Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - cal.add(Calendar.HOUR_OF_DAY, -2); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - String updatedAfter = sdf.format(cal.getTime()); - - // 构建查询参数 - Map queryParams = new TreeMap<>(); - queryParams.put("orgId", ORG_ID); - queryParams.put("updatedAfter", updatedAfter); - queryParams.put("page", "1"); - queryParams.put("size", "100"); - - // 生成 HMAC 签名头 - Map hmacHeaders = buildHmacHeaders(queryParams); - - // 拼接 URL(手动 URLEncode 参数值) - StringBuilder queryString = new StringBuilder(); - for (Map.Entry e : queryParams.entrySet()) { - if (queryString.length() > 0) queryString.append("&"); - queryString.append(URLEncoder.encode(e.getKey(), "UTF-8")) - .append("=") - .append(URLEncoder.encode(e.getValue(), "UTF-8")); - } - String url = LEAI_API_URL + "/api/v1/query/works?" + queryString.toString(); - - // ★★★ 重要: 如果你使用 Spring RestTemplate,URL 已经手动编码过, - // 必须传 URI 对象,否则 RestTemplate 会二次编码导致签名校验失败! - // 错误: restTemplate.getForObject(url, String.class) ← 会二次编码 %3A → %253A - // 正确: restTemplate.getForObject(URI.create(url), String.class) ← 不会二次编码 - // 或者: 不手动编码,用 UriComponentsBuilder 让 Spring 统一处理: - // URI uri = UriComponentsBuilder.fromHttpUrl(LEAI_API_URL + "/api/v1/query/works") - // .queryParam("orgId", ORG_ID) - // .queryParam("updatedAfter", updatedAfter) // 原始值,不要 encode - // .queryParam("page", "1").queryParam("size", "100") - // .build().encode().toUri(); - // restTemplate.getForObject(uri, String.class); - - // 本 Demo 使用 HttpURLConnection(JDK原生),不存在二次编码问题 - String responseBody = httpGet(url, hmacHeaders); - Map responseJson = parseJsonObject(responseBody); - - int code = toInt(responseJson.get("code"), 0); - if (code != 200) { - log.warning("[B3] API error: " + toString(responseJson.get("msg"), "unknown")); - return; - } - - // B3 返回分页对象: { records: [...], total, page, pageSize } - @SuppressWarnings("unchecked") - Map dataMap = (Map) responseJson.get("data"); - Object recordsObj = (dataMap != null) ? dataMap.get("records") : null; - if (recordsObj instanceof Object[]) { - Object[] records = (Object[]) recordsObj; - int synced = 0; - for (Object record : records) { - @SuppressWarnings("unchecked") - Map r = (Map) record; - String workId = toString(r.get("workId"), null); - if (workId == null) continue; - - int remoteStatus = toInt(r.get("status"), 0); - // TODO [企业开发者]: 替换为你的数据库查询和更新操作 - // 1. 从你的数据库查询本地作品: SELECT status FROM your_table WHERE work_id = ? - // 2. 按V4.0规则判断是否需要同步: remote_status > local_status || remote_status == 2 || remote_status == -1 - // 3. 如需同步,调B2获取完整数据: GET /api/v1/query/work/{workId} - // 4. 更新到你的数据库: UPDATE your_table SET ... WHERE work_id = ? - Map local = worksDb.get(workId); - int localStatus = (local != null) ? toInt(local.get("status"), 0) : Integer.MIN_VALUE; - - // 需要同步: 新作品, 或符合 V4.0 同步规则 - boolean needSync = (local == null) - || (remoteStatus == STATUS_FAILED) - || (remoteStatus == STATUS_PROCESSING) - || (remoteStatus > localStatus); - - if (needSync) { - // 如果B3返回的是摘要信息, 可调 B2 获取完整数据 - // 这里简化处理, 直接用B3返回的数据更新 - try { - Map fullData = fetchB2Detail(workId); - if (fullData != null) { - // 转为 snake_case 存储 - Map normalized = normalizeB2Response(fullData); - worksDb.put(workId, normalized); - synced++; - log.info("[B3] Synced work " + workId - + ": status " + localStatus + " -> " + remoteStatus); - } - } catch (Exception e) { - // B2 调用失败时, 用 B3 摘要数据做简易同步 - Map normalized = normalizeB3Summary(r); - worksDb.put(workId, normalized); - synced++; - log.info("[B3] Synced work " + workId + " (from B3 summary)"); - } - } - } - log.info("[B3] Reconciliation complete: checked " + records.length - + " works, synced " + synced); - } else { - log.info("[B3] No data returned or unexpected format"); - } - - } catch (Exception e) { - log.log(Level.WARNING, "[B3] Reconciliation error", e); - } - } - - // ══════════════════════════════════════════════════════════════ - // V4.0 核心同步逻辑(Webhook 和 B3 共用) - // ══════════════════════════════════════════════════════════════ - - /** - * V4.0 核心同步逻辑(Webhook 和 B3 对账共用) - * - * 企业开发者请将此方法中的 worksDb(内存Map)替换为你的数据库操作。 - * - * ═══════════════════════════════════════════════════════════════ - * 【各事件处理指南】 - * - * 1. work.status_changed 事件(状态变更,最重要) - * - status=1 (PENDING): 作品刚提交,创建本地记录 - * → INSERT INTO your_table (work_id, status, phone, style, org_id) VALUES (...) - * - * - status=2 (PROCESSING): AI创作进行中(此状态通常由work.progress推送) - * → UPDATE your_table SET status=2 WHERE work_id=? - * - * - status=3 (COMPLETED): 图片生成完成,作品可预览 - * → UPDATE your_table SET status=3, title=?, pages=?, page_list=? WHERE work_id=? - * → 此时 page_list 包含所有页面的图片URL,企业应保存 - * - * - status=4 (CATALOGED): 用户完成编目(填写了作者/标题等) - * → UPDATE your_table SET status=4, title=?, author=?, tags=? WHERE work_id=? - * - * - status=5 (DUBBED): 用户完成配音(乐读派终态) - * → UPDATE your_table SET status=5, page_list=? WHERE work_id=? - * → page_list 中的 audio_url 字段此时已填充 - * → 企业可从 status>=5 开始自己的二次编辑状态(6,7,8...) - * - * - status=-1 (FAILED): 创作失败 - * → UPDATE your_table SET status=-1, fail_reason=? WHERE work_id=? - * - * 2. work.progress 事件(创作进度,可选处理) - * - 在PROCESSING阶段推送,包含 progress(百分比) 和 progress_message(阶段描述) - * - progress=30 → "故事生成完成,开始绘制插画" - * - progress=70 → "插画绘制完成,开始配音合成" - * - progress=90 → "配音合成完成" - * → UPDATE your_table SET progress=?, progress_message=? WHERE work_id=? - * - * 3. work.video_completed 事件(视频合成完成,可选) - * - 仅在调用A4视频合成后触发 - * → UPDATE your_table SET video_status='COMPLETED', video_url=? WHERE work_id=? - * - * ═══════════════════════════════════════════════════════════════ - * 【并发安全】 - * - * Webhook 和 B3 对账可能同时触发同一个作品的更新。建议: - * 1. 使用数据库行锁: SELECT ... FOR UPDATE WHERE work_id=? - * 2. 或使用 CAS 乐观锁: UPDATE ... SET status=? WHERE work_id=? AND status < ? - * 3. 使用 webhook_event_id 做幂等去重,避免同一事件重复处理 - * - * 示例SQL(CAS乐观锁): - * UPDATE your_table - * SET status = #{remoteStatus}, title = #{title}, page_list = #{pageList} - * WHERE work_id = #{workId} - * AND (status < #{remoteStatus} OR #{remoteStatus} = 2 OR #{remoteStatus} = -1) - * ═══════════════════════════════════════════════════════════════ - */ - private void syncWork(String workId, Map remoteData, String source) { - int remoteStatus = toInt(remoteData.get("status"), 0); - Map local = worksDb.get(workId); - - if (local == null) { - // ★ 新作品:首次收到此workId,创建本地记录 - // TODO [企业开发者]: INSERT INTO your_table (...) VALUES (...) - worksDb.put(workId, new HashMap<>(remoteData)); - log.info("[" + source + "] INSERT work " + workId + " status=" + remoteStatus); - return; - } - - int localStatus = toInt(local.get("status"), 0); - - if (remoteStatus == STATUS_FAILED) { - // ★ FAILED(-1): 创作失败,强制更新(无视状态比较) - // TODO [企业开发者]: UPDATE your_table SET status=-1, fail_reason=? WHERE work_id=? - local.putAll(remoteData); - log.info("[" + source + "] FORCE UPDATE (FAILED) work " + workId); - return; - } - - if (remoteStatus == STATUS_PROCESSING) { - // ★ PROCESSING(2): 创作进行中,强制更新进度 - // data 中包含 progress(百分比) 和 progress_message(阶段描述) - // TODO [企业开发者]: UPDATE your_table SET status=2, progress=?, progress_message=? WHERE work_id=? - local.put("status", remoteStatus); - if (remoteData.containsKey("progress")) { - local.put("progress", remoteData.get("progress")); - } - if (remoteData.containsKey("progress_message")) { - local.put("progress_message", remoteData.get("progress_message")); - } - log.info("[" + source + "] FORCE UPDATE (PROCESSING) work " + workId - + " progress=" + remoteData.get("progress")); - return; - } - - if (remoteStatus > localStatus) { - // ★ 状态前进: 全量覆盖所有字段 - // status=3(COMPLETED): page_list包含图片URL - // status=4(CATALOGED): title/author/tags已更新 - // status=5(DUBBED): page_list中audio_url已填充 - // TODO [企业开发者]: - // UPDATE your_table SET status=?, title=?, author=?, tags=?, - // page_list=?, phone=?, ... WHERE work_id=? AND status < ? - local.putAll(remoteData); - log.info("[" + source + "] UPDATE work " + workId - + " status: " + localStatus + " -> " + remoteStatus); - return; - } - - // 旧数据或重复推送,忽略 - log.info("[" + source + "] SKIP work " + workId - + " remote=" + remoteStatus + " <= local=" + localStatus); - } - - // ══════════════════════════════════════════ - // 工具方法:令牌交换 - // ══════════════════════════════════════════ - - /** - * 调用乐读派 POST /api/v1/auth/session 换取 sessionToken - * - * 请求: { "orgId": "xxx", "appSecret": "xxx", "phone": "138xxx" } - * 响应: { "code": 200, "data": { "sessionToken": "sess_xxx", "expiresIn": 7200 } } - */ - private String exchangeToken(String phone) throws Exception { - String jsonBody = "{\"orgId\":\"" + jsonEscape(ORG_ID) - + "\",\"appSecret\":\"" + jsonEscape(APP_SECRET) - + "\",\"phone\":\"" + jsonEscape(phone) + "\"}"; - - String url = LEAI_API_URL + "/api/v1/auth/session"; - HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); - conn.setRequestMethod("POST"); - conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); - conn.setConnectTimeout(10_000); - conn.setReadTimeout(10_000); - conn.setDoOutput(true); - - try (OutputStream os = conn.getOutputStream()) { - os.write(jsonBody.getBytes(StandardCharsets.UTF_8)); - os.flush(); - } - - int httpCode = conn.getResponseCode(); - String responseBody = readStream(conn); - - if (httpCode != 200) { - throw new RuntimeException("令牌交换失败: HTTP " + httpCode + ", body=" + responseBody); - } - - // 解析 JSON 响应 - Map response = parseJsonObject(responseBody); - int code = toInt(response.get("code"), 0); - if (code != 200) { - throw new RuntimeException("令牌交换失败: code=" + code - + ", msg=" + toString(response.get("msg"), "unknown")); - } - - @SuppressWarnings("unchecked") - Map data = (Map) response.get("data"); - if (data == null) { - throw new RuntimeException("令牌交换失败: data 为 null"); - } - - String sessionToken = toString(data.get("sessionToken"), null); - if (sessionToken == null || sessionToken.isEmpty()) { - throw new RuntimeException("令牌交换失败: sessionToken 为空"); - } - - log.info("[Token] Exchanged token for phone=" + phone + ", expires=" - + data.get("expiresIn") + "s"); - return sessionToken; - } - - // ══════════════════════════════════════════ - // 工具方法:B2 单作品查询 - // ══════════════════════════════════════════ - - /** - * 调用 B2 GET /api/v1/query/work/{workId} 获取完整作品数据 - * 使用 HMAC 认证 - * - * ★ 签名规则: queryParams 中放原始值(未编码),签名用原始值计算。 - * URL 拼接时再做 URLEncode。 - * 如果使用 RestTemplate,务必传 URI.create(url) 而非 String url, - * 否则会导致二次编码使签名校验失败(详见 B3 方法注释)。 - */ - private Map fetchB2Detail(String workId) throws Exception { - Map queryParams = new TreeMap<>(); - queryParams.put("orgId", ORG_ID); - - Map hmacHeaders = buildHmacHeaders(queryParams); - - // URL 手动编码(HttpURLConnection 不会二次编码,RestTemplate 会!) - String url = LEAI_API_URL + "/api/v1/query/work/" + URLEncoder.encode(workId, "UTF-8") - + "?orgId=" + URLEncoder.encode(ORG_ID, "UTF-8"); - - String responseBody = httpGet(url, hmacHeaders); - Map response = parseJsonObject(responseBody); - - int code = toInt(response.get("code"), 0); - if (code != 200) { - return null; - } - - @SuppressWarnings("unchecked") - Map data = (Map) response.get("data"); - return data; - } - - // ══════════════════════════════════════════ - // 工具方法:HMAC-SHA256 签名 - // ══════════════════════════════════════════ - - /** - * HMAC-SHA256 签名 - * @param data 待签名字符串 - * @param secret 密钥 - * @return hex 编码的签名值 - */ - private String hmacSha256(String data, String secret) { - try { - Mac mac = Mac.getInstance("HmacSHA256"); - SecretKeySpec keySpec = new SecretKeySpec( - secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); - mac.init(keySpec); - byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); - // 转 hex - StringBuilder sb = new StringBuilder(hash.length * 2); - for (byte b : hash) { - sb.append(String.format("%02x", b & 0xff)); - } - return sb.toString(); - } catch (Exception e) { - throw new RuntimeException("HMAC-SHA256 error", e); - } - } - - /** - * 生成 C 端 API HMAC 签名请求头 - * - * 签名字符串: 所有 query params(含 nonce, timestamp)按 key 字母序排列, - * 用 & 拼接成 "key1=val1&key2=val2&..." 格式 - * 签名算法: HMAC-SHA256(签名字符串, appSecret), hex 编码 - * - * ★ 重要: queryParams 中的 value 必须是原始值(未 URLEncode),不是编码后的值! - * 例: "2026-04-08T03:48:38Z"(正确) 而非 "2026-04-08T03%3A48%3A38Z"(错误) - * 签名用原始值计算,URL 拼接时再做 URLEncode,两步分开。 - * - * 返回4个 Header: - * X-App-Key: 机构ID - * X-Timestamp: 毫秒时间戳 - * X-Nonce: 随机串 - * X-Signature: 签名值 - */ - private Map buildHmacHeaders(Map queryParams) { - String ts = String.valueOf(System.currentTimeMillis()); - String nonce = Long.toHexString(System.currentTimeMillis()) + Long.toHexString(System.nanoTime()); - - // 将 timestamp 和 nonce 加入签名参数 - TreeMap allParams = new TreeMap<>(queryParams); - allParams.put("timestamp", ts); - allParams.put("nonce", nonce); - - // 按 key 排序后拼接 - StringBuilder signStr = new StringBuilder(); - for (Map.Entry entry : allParams.entrySet()) { - if (signStr.length() > 0) signStr.append("&"); - signStr.append(entry.getKey()).append("=").append(entry.getValue()); - } - - String sig = hmacSha256(signStr.toString(), APP_SECRET); - - Map headers = new LinkedHashMap<>(); - headers.put("X-App-Key", ORG_ID); - headers.put("X-Timestamp", ts); - headers.put("X-Nonce", nonce); - headers.put("X-Signature", sig); - return headers; - } - - // ══════════════════════════════════════════ - // 工具方法:HTTP 请求 - // ══════════════════════════════════════════ - - private String httpGet(String url, Map headers) throws Exception { - HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); - conn.setRequestMethod("GET"); - conn.setConnectTimeout(10_000); - conn.setReadTimeout(10_000); - for (Map.Entry h : headers.entrySet()) { - conn.setRequestProperty(h.getKey(), h.getValue()); - } - return readStream(conn); - } - - private String readStream(HttpURLConnection conn) throws Exception { - BufferedReader reader; - try { - reader = new BufferedReader(new InputStreamReader( - conn.getInputStream(), StandardCharsets.UTF_8)); - } catch (Exception e) { - // 读取错误流 - if (conn.getErrorStream() != null) { - reader = new BufferedReader(new InputStreamReader( - conn.getErrorStream(), StandardCharsets.UTF_8)); - } else { - throw e; - } - } - StringBuilder sb = new StringBuilder(); - String line; - while ((line = reader.readLine()) != null) { - sb.append(line); - } - reader.close(); - return sb.toString(); - } - - // ══════════════════════════════════════════ - // 工具方法:企业 Session(demo 简化实现) - // ══════════════════════════════════════════ - - /** - * 从企业 session 获取用户手机号。 - * - * 生产环境: 读取企业自身的 session/JWT 中的用户手机号。 - * Demo 中: 返回硬编码的测试手机号。 - * - * 如果用户未登录(session 中没有手机号), 返回 null。 - */ - private String getPhoneFromSession(HttpServletRequest request) { - // ── 生产环境示例 ── - // HttpSession session = request.getSession(false); - // if (session == null) return null; - // return (String) session.getAttribute("phone"); - - // ── Demo: 返回测试手机号 ── - return "13800001111"; - } - - // ══════════════════════════════════════════ - // 工具方法:B2/B3 响应字段归一化 - // ══════════════════════════════════════════ - - /** - * 将 B2 返回的 camelCase 字段转为 snake_case 内部存储格式 - */ - private Map normalizeB2Response(Map b2Data) { - Map normalized = new HashMap<>(); - normalized.put("work_id", b2Data.get("workId")); - normalized.put("status", b2Data.get("status")); - normalized.put("progress", b2Data.get("progress")); - normalized.put("title", b2Data.get("title")); - normalized.put("phone", b2Data.get("phone")); - normalized.put("page_list", b2Data.get("pageList")); - normalized.put("original_image_url", b2Data.get("originalImageUrl")); - normalized.put("fail_reason", b2Data.get("failReason")); - normalized.put("author", b2Data.get("author")); - return normalized; - } - - /** - * 将 B3 摘要的 camelCase 字段转为 snake_case 内部存储格式 - */ - private Map normalizeB3Summary(Map b3Data) { - Map normalized = new HashMap<>(); - normalized.put("work_id", b3Data.get("workId")); - normalized.put("status", b3Data.get("status")); - normalized.put("title", b3Data.get("title")); - normalized.put("phone", b3Data.get("phone")); - normalized.put("original_image_url", b3Data.get("originalImageUrl")); - return normalized; - } - - // ══════════════════════════════════════════ - // 工具方法:简易 JSON 解析 - // - // 注意: 这是一个极简的 JSON 解析器, 仅处理 demo 所需的基本场景。 - // 生产环境请务必使用 Jackson (spring-boot-starter-web 已内置) - // 或 Gson 等成熟的 JSON 库。 - // - // Jackson 示例: - // ObjectMapper mapper = new ObjectMapper(); - // Map result = mapper.readValue(json, new TypeReference>(){}); - // - // Gson 示例: - // Gson gson = new Gson(); - // Map result = gson.fromJson(json, new TypeToken>(){}.getType()); - // ══════════════════════════════════════════ - - /** - * 简易 JSON 对象解析器。 - * 支持: 嵌套对象, 数组, 字符串, 数字, boolean, null。 - * 不支持: Unicode 转义 (\\uXXXX), 科学计数法等边缘情况。 - * - * 生产环境请替换为 Jackson ObjectMapper。 - */ - private Map parseJsonObject(String json) { - if (json == null || json.trim().isEmpty()) { - return new HashMap<>(); - } - JsonParser parser = new JsonParser(json.trim()); - Object result = parser.parseValue(); - if (result instanceof Map) { - @SuppressWarnings("unchecked") - Map map = (Map) result; - return map; - } - return new HashMap<>(); - } - - /** - * 极简递归下降 JSON 解析器(内部类)。 - * 仅用于 demo 演示, 避免引入额外依赖。 - */ - private static class JsonParser { - private final String json; - private int pos; - - JsonParser(String json) { - this.json = json; - this.pos = 0; - } - - Object parseValue() { - skipWhitespace(); - if (pos >= json.length()) return null; - char c = json.charAt(pos); - if (c == '{') return parseObject(); - if (c == '[') return parseArray(); - if (c == '"') return parseString(); - if (c == 't' || c == 'f') return parseBoolean(); - if (c == 'n') return parseNull(); - return parseNumber(); - } - - Map parseObject() { - Map map = new LinkedHashMap<>(); - pos++; // skip { - skipWhitespace(); - if (pos < json.length() && json.charAt(pos) == '}') { - pos++; - return map; - } - while (pos < json.length()) { - skipWhitespace(); - String key = parseString(); - skipWhitespace(); - if (pos < json.length() && json.charAt(pos) == ':') pos++; - skipWhitespace(); - Object value = parseValue(); - map.put(key, value); - skipWhitespace(); - if (pos < json.length() && json.charAt(pos) == ',') { - pos++; - } else { - break; - } - } - if (pos < json.length() && json.charAt(pos) == '}') pos++; - return map; - } - - Object[] parseArray() { - java.util.List list = new java.util.ArrayList<>(); - pos++; // skip [ - skipWhitespace(); - if (pos < json.length() && json.charAt(pos) == ']') { - pos++; - return list.toArray(); - } - while (pos < json.length()) { - skipWhitespace(); - list.add(parseValue()); - skipWhitespace(); - if (pos < json.length() && json.charAt(pos) == ',') { - pos++; - } else { - break; - } - } - if (pos < json.length() && json.charAt(pos) == ']') pos++; - return list.toArray(); - } - - String parseString() { - if (pos >= json.length() || json.charAt(pos) != '"') return ""; - pos++; // skip opening quote - StringBuilder sb = new StringBuilder(); - while (pos < json.length()) { - char c = json.charAt(pos); - if (c == '\\' && pos + 1 < json.length()) { - pos++; - char escaped = json.charAt(pos); - switch (escaped) { - case '"': sb.append('"'); break; - case '\\': sb.append('\\'); break; - case '/': sb.append('/'); break; - case 'n': sb.append('\n'); break; - case 'r': sb.append('\r'); break; - case 't': sb.append('\t'); break; - case 'b': sb.append('\b'); break; - case 'f': sb.append('\f'); break; - default: sb.append(escaped); break; - } - } else if (c == '"') { - pos++; - return sb.toString(); - } else { - sb.append(c); - } - pos++; - } - return sb.toString(); - } - - Object parseNumber() { - int start = pos; - if (pos < json.length() && json.charAt(pos) == '-') pos++; - while (pos < json.length() && Character.isDigit(json.charAt(pos))) pos++; - boolean isFloat = false; - if (pos < json.length() && json.charAt(pos) == '.') { - isFloat = true; - pos++; - while (pos < json.length() && Character.isDigit(json.charAt(pos))) pos++; - } - String numStr = json.substring(start, pos); - if (isFloat) { - return Double.parseDouble(numStr); - } - long val = Long.parseLong(numStr); - if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE) { - return (int) val; - } - return val; - } - - Boolean parseBoolean() { - if (json.startsWith("true", pos)) { - pos += 4; - return Boolean.TRUE; - } - if (json.startsWith("false", pos)) { - pos += 5; - return Boolean.FALSE; - } - return Boolean.FALSE; - } - - Object parseNull() { - if (json.startsWith("null", pos)) { - pos += 4; - } - return null; - } - - void skipWhitespace() { - while (pos < json.length() && Character.isWhitespace(json.charAt(pos))) { - pos++; - } - } - } - - // ══════════════════════════════════════════ - // 工具方法:杂项 - // ══════════════════════════════════════════ - - private static int toInt(Object obj, int defaultValue) { - if (obj == null) return defaultValue; - if (obj instanceof Number) return ((Number) obj).intValue(); - try { - return Integer.parseInt(obj.toString()); - } catch (NumberFormatException e) { - return defaultValue; - } - } - - private static String toString(Object obj, String defaultValue) { - if (obj == null) return defaultValue; - return obj.toString(); - } - - private static String jsonEscape(String s) { - if (s == null) return ""; - return s.replace("\\", "\\\\").replace("\"", "\\\""); - } - - private static String escapeHtml(String s) { - if (s == null) return ""; - return s.replace("&", "&").replace("<", "<") - .replace(">", ">").replace("\"", """); - } - - private static String statusName(int status) { - switch (status) { - case STATUS_FAILED: return "FAILED"; - case STATUS_PENDING: return "PENDING"; - case STATUS_PROCESSING: return "PROCESSING"; - case STATUS_COMPLETED: return "COMPLETED"; - case STATUS_CATALOGED: return "CATALOGED"; - case STATUS_DUBBED: return "DUBBED"; - default: return "UNKNOWN(" + status + ")"; - } - } - - private static String statusStyle(int status) { - switch (status) { - case STATUS_FAILED: return "color:#DC2626;font-weight:600;"; - case STATUS_PENDING: return "color:#2563EB;"; - case STATUS_PROCESSING: return "color:#FF6B35;font-weight:600;"; - case STATUS_COMPLETED: return "color:#059669;"; - case STATUS_CATALOGED: return "color:#059669;font-weight:600;"; - case STATUS_DUBBED: return "color:#7C3AED;font-weight:600;"; - default: return "color:#6B7280;"; - } - } -} diff --git a/lesingle-aicreate-backend-demo/aicreate-demo/src/main/resources/application.properties b/lesingle-aicreate-backend-demo/aicreate-demo/src/main/resources/application.properties deleted file mode 100644 index 42fe537..0000000 --- a/lesingle-aicreate-backend-demo/aicreate-demo/src/main/resources/application.properties +++ /dev/null @@ -1,2 +0,0 @@ -server.port=9090 -spring.application.name=LeAI-Enterprise-Demo diff --git a/lesingle-aicreate-backend-demo/aicreate-demo/src/main/resources/static/enterprise-sim.html b/lesingle-aicreate-backend-demo/aicreate-demo/src/main/resources/static/enterprise-sim.html deleted file mode 100644 index fab569f..0000000 --- a/lesingle-aicreate-backend-demo/aicreate-demo/src/main/resources/static/enterprise-sim.html +++ /dev/null @@ -1,236 +0,0 @@ - - - - -企业模拟C端 - - - - - -
-
用户: 加载中...
-
机构: LESINGLE888888888
-
- - -
- - -
-
-
🏠
-
广场
-
-
-
-
创作
-
-
-
📚
-
作品
-
-
-
👤
-
我的
-
-
- - - -
- - - diff --git a/lesingle-aicreate-backend-demo/aicreate-demo/start.bat b/lesingle-aicreate-backend-demo/aicreate-demo/start.bat deleted file mode 100644 index 090ef41..0000000 --- a/lesingle-aicreate-backend-demo/aicreate-demo/start.bat +++ /dev/null @@ -1,65 +0,0 @@ -@echo off -setlocal enabledelayedexpansion -title LeAI Enterprise Demo (Port 9090) - -echo ======================================================== -echo LeAI Enterprise Demo - Port 9090 -echo Auth callback + Webhook + iframe embed -echo ======================================================== -echo. - -:: --- JDK --- -set "JAVA_HOME=M:\SDK\jdk8u482-b08" -if not exist "%JAVA_HOME%\bin\java.exe" ( - echo [ERROR] JDK not found: %JAVA_HOME% - echo Please edit JAVA_HOME in this script - pause - exit /b 1 -) -set "PATH=%JAVA_HOME%\bin;%PATH%" -echo [OK] JDK: %JAVA_HOME% - -:: --- Kill port 9090 --- -for /f "tokens=5" %%a in ('netstat -aon ^| findstr ":9090 " ^| findstr "LISTENING"') do ( - echo [!] Killing PID %%a on port 9090 - taskkill /F /PID %%a >nul 2>&1 -) - -:: --- Maven build --- -echo. -echo [*] Building with Maven... -if exist "mvnw.cmd" ( - call mvnw.cmd clean package -DskipTests -q -) else ( - call mvn clean package -DskipTests -q -) - -:: --- Find JAR --- -set "JAR_FILE=" -for /f "delims=" %%f in ('dir /b /s target\*.jar 2^>nul ^| findstr /v "original"') do ( - set "JAR_FILE=%%f" -) -if "!JAR_FILE!"=="" ( - echo [ERROR] JAR file not found. Build may have failed. - pause - exit /b 1 -) -echo [OK] JAR: !JAR_FILE! - -:: --- Start --- -echo. -echo ======================================================== -echo Starting Enterprise Demo... -echo. -echo Home: http://192.168.1.120:9090 -echo iframe: http://192.168.1.120:9090/enterprise-sim.html -echo Auth: http://192.168.1.120:9090/leai-auth -echo Webhook: http://192.168.1.120:9090/webhook/leai -echo. -echo Requires: LeAI backend(8080) + H5 frontend(3001) -echo ======================================================== -echo. - -java -jar -Xms128m -Xmx256m "!JAR_FILE!" - -pause diff --git a/lesingle-aicreate-backend-demo/enterprise-sim.html b/lesingle-aicreate-backend-demo/enterprise-sim.html deleted file mode 100644 index e4628c1..0000000 --- a/lesingle-aicreate-backend-demo/enterprise-sim.html +++ /dev/null @@ -1,235 +0,0 @@ - - - - -企业模拟C端 - - - - - -
-
用户: 18911223344
-
机构: LESINGLE888888888
-
- - -
- - -
-
-
🏠
-
广场
-
-
-
-
创作
-
-
-
📚
-
作品
-
-
-
👤
-
我的
-
-
- - - -
- - - diff --git a/lesingle-aicreate-backend-demo/test-iframe.html b/lesingle-aicreate-backend-demo/test-iframe.html deleted file mode 100644 index 28edb15..0000000 --- a/lesingle-aicreate-backend-demo/test-iframe.html +++ /dev/null @@ -1,113 +0,0 @@ - -iframe嵌入测试 - - -
- 企业iframe测试: - - - - - 等待加载... -
- -
- - - diff --git a/lesingle-aicreate-backend-demo/企业同步创作数据_核心三步_V4.0(1).md b/lesingle-aicreate-backend-demo/企业同步创作数据_核心三步_V4.0(1).md deleted file mode 100644 index 8d6a174..0000000 --- a/lesingle-aicreate-backend-demo/企业同步创作数据_核心三步_V4.0(1).md +++ /dev/null @@ -1,383 +0,0 @@ -# 企业同步创作数据 — 核心三步 - -> 基于《AI绘本创作系统 企业后端集成指南 V4.0》,提炼企业同步乐读派创作数据的核心实现路径。 -> -> 三层防线共用同一套同步判断规则,区别仅在于触发方式和时机。 - ---- - -## 前置知识:5步状态机与同步判断规则 - -### 状态定义 - -| 数值 | 状态名 | 含义 | -|------|--------|------| -| -1 | FAILED | 创作失败(异常状态) | -| 1 | PENDING | 已提交,排队等待 | -| 2 | PROCESSING | AI创作中(进度变化) | -| 3 | COMPLETED | 图片完成,待编目 | -| 4 | CATALOGED | 编目完成,待配音 | -| 5 | DUBBED | 配音完成(乐读派终态) | - -正常流转:`1 → 2 → 3 → 4 → 5`,严格单向递增,不可回退。 - -### 统一同步判断规则(三步通用) - -``` -if (本地无记录) → INSERT(新作品) -if (remote_status == -1) → 强制UPDATE(失败通知,无条件处理) -if (remote_status == 2) → 强制UPDATE(进度变化,无条件更新) -if (remote_status > local_status) → 全量UPDATE(状态前进) -其他 → SKIP(旧数据/重复,忽略) -``` - -> **重点**:PROCESSING(2) 和 FAILED(-1) 是特殊状态,**不参与数值大小比较**,收到即强制更新。 - ---- - -## 第一步:Webhook 回调推送(实时主通道) - -### 作用 - -乐读派后端在作品状态变更时,**主动** POST 推送到企业配置的 Webhook URL,实现秒级数据同步。 - -### 触发时机 - -每次 status 发生变化时自动推送,包括: -- 状态前进:1→2、2→3、3→4、4→5 -- 创作失败:any→-1 - -### 两种事件类型 - -| 事件 | 触发时机 | 频率 | 说明 | -|------|----------|------|------| -| `work.status_changed` | 状态变更 | 每次状态变更1次 | 核心事件,携带完整作品数据(含 page_list) | -| `work.progress` | PROCESSING 阶段进度变化 | 多次/作品 | 进度里程碑推送(10%/30%/50%/70%/90%) | - -### Webhook 请求格式 - -``` -POST {企业webhook_url} -Content-Type: application/json -X-Webhook-Id: evt_190368671438289 -X-Webhook-Event: work.status_changed -X-Webhook-Timestamp: 1712000000000 -X-Webhook-Signature: HMAC-SHA256=a3f8c2d1... -``` - -### 企业处理逻辑(Java 伪代码) - -```java -@Transactional -public void handleWebhook(JSONObject data) { - String workId = data.getString("work_id"); - int remoteStatus = data.getIntValue("status"); - - // 1. 幂等去重(用 event_id,防止重复处理) - if (processedEvents.contains(eventId)) return; - - // 2. 查本地记录(建议 SELECT ... FOR UPDATE 行锁) - WorkRecord local = db.selectForUpdate(workId); - - // 3. 新作品 → 直接入库 - if (local == null) { - db.insert(buildRecord(data)); - return; - } - - // 4. FAILED(-1) → 强制更新,无条件 - if (remoteStatus == -1) { - local.setStatus(-1); - local.setFailReason(data.getString("fail_reason")); - db.update(local); - return; - } - - // 5. PROCESSING(2) → 强制更新进度,无条件 - if (remoteStatus == 2) { - local.setProgress(data.getIntValue("progress")); - local.setProgressMessage(data.getString("progress_message")); - db.update(local); - return; - } - - // 6. 状态前进 → 全量覆盖 - if (remoteStatus > local.getStatus()) { - updateAllFields(local, data); // 更新 title/author/page_list 等 - db.update(local); - return; - } - - // 7. 旧数据/重复 → 忽略 - log.info("skip: remote={} <= local={}", remoteStatus, local.getStatus()); -} -``` - -### 各状态下企业应保存的关键数据 - -| 状态 | 企业需保存的字段 | 用途 | -|------|--------------|------| -| 1 PENDING | work_id, phone, org_id, style, original_image_url | 创建本地记录,关联企业用户 | -| 2 PROCESSING | progress, progress_message | 显示创作进度(可选) | -| 3 COMPLETED | title, pages, page_list(含 image_url) | 作品图片已生成,可预览展示 | -| 4 CATALOGED | title, author, subtitle, intro, tags | 用户填写的编目信息 | -| 5 DUBBED | page_list(含 audio_url) | 配音URL已填充,作品完整可用 | -| -1 FAILED | fail_reason | 记录失败原因,通知用户 | - -### 签名验证(必须实现) - -``` -签名体 = "{X-Webhook-Id}.{X-Webhook-Timestamp}.{请求body原文}" -期望签名 = HMAC-SHA256(签名体, app_secret).toHex() -``` - -安全检查清单: -- **时间窗口**:`|当前时间 - X-Webhook-Timestamp| ≤ 5分钟`,防重放 -- **幂等去重**:用 `X-Webhook-Id` 记录已处理事件 -- **常量时间比较**:用 `MessageDigest.isEqual()` 而非 `.equals()`,防时序攻击 -- **原始body**:签名时使用 HTTP body 原文,不要反序列化再序列化 - -### 重试策略 - -首次发送 + 5次重试 = 共6次尝试。 - -延迟间隔:`10s → 30s → 2min → 10min → 30min → 30min` - -全部失败后需通过**第二步 B3 批量拉取**兜底。 - ---- - -## 第二步:B3 批量查询兜底(定时对账) - -### 作用 - -Webhook 可能因网络问题、企业服务宕机等原因丢失。B3 定时批量拉取作为兜底通道,确保数据**最终一致**。 - -### 接口信息 - -``` -GET /api/v1/query/works?orgId=ORG001&updatedAfter=2026-04-05T00:00:00 -认证方式:HMAC-SHA256 签名 -``` - -返回指定时间之后有变更的所有作品列表。 - -### 建议配置 - -| 配置项 | 推荐值 | 说明 | -|--------|--------|------| -| 对账频率 | 每 30 分钟 | 不低于 15 分钟,避免对 API 造成查询压力 | -| 查询范围 | 最近 2 小时 | 覆盖 2 个对账周期,防止边界遗漏 | - -### 企业实现伪代码(Java) - -```java -@Scheduled(fixedRate = 30 * 60 * 1000) // 每30分钟执行 -public void reconcile() { - // 查询最近2小时内有变更的作品 - String since = twoHoursAgo.format(ISO_FORMAT); - List remoteList = callB3(since); - - for (RemoteWork remote : remoteList) { - WorkRecord local = db.get(remote.workId); - - // 同步判断规则与 Webhook 完全一致 - if (local == null - || remote.status > local.getStatus() - || remote.status == 2 - || remote.status == -1) { - db.upsert(remote); - } - } - lastSyncTime = now(); -} -``` - -### B3 调用签名示例 - -```java -Map params = new LinkedHashMap<>(); -params.put("orgId", ORG_ID); -params.put("updatedAfter", "2026-04-05T00:00:00"); - -// 生成 HMAC 签名头(4个 Header) -Map headers = buildHmacHeaders(params, ORG_ID, APP_SECRET); - -String url = API_URL + "/api/v1/query/works?orgId=" + ORG_ID - + "&updatedAfter=" + URLEncoder.encode("2026-04-05T00:00:00", "UTF-8"); - -// 注意:传 URI 对象,避免 RestTemplate 双重编码 -restTemplate.getForObject(URI.create(url), String.class); -``` - -### 并发安全(Webhook + B3 同时触发) - -推荐两种方案防止同一作品被并发更新: - -```sql --- 方案1: 行锁(推荐,简单可靠) -SELECT * FROM enterprise_work WHERE work_id = ? FOR UPDATE; --- 然后按同步规则判断和更新 - --- 方案2: CAS 乐观锁(无锁,适合高并发) -UPDATE enterprise_work -SET status = #{remoteStatus}, title = #{title}, page_list = #{pageList} -WHERE work_id = #{workId} - AND (status < #{remoteStatus} OR #{remoteStatus} = 2 OR #{remoteStatus} = -1); --- rows=0 表示被其他线程抢先更新了,安全忽略 -``` - ---- - -## 第三步:详情页进入时强制 B2 拉取(用户触发兜底) - -### 作用 - -当用户点击进入作品详情页,且本地状态尚未完成(`status < 3`),企业**强制调用 B2 单条查询**拉取最新数据,确保用户看到的是最新状态。 - -### 为什么需要这一步 - -- status 1/2 期间状态变化最快(排队 → 创作中 → 完成),是 Webhook 丢失的**高风险窗口** -- B3 对账有 30 分钟延迟,用户可能在此期间打开详情页 -- 用户主动触发,**即时补偿**,体验最佳 - -### 触发条件 - -``` -用户点击作品详情页 && local_status < 3 -``` - -`status >= 3` 后变化由用户主动操作驱动(编目/配音),Webhook + B3 已足够覆盖,无需额外拉取。 - -### 接口信息 - -``` -GET /api/v1/query/work/{workId}?orgId=ORG001 -认证方式:HMAC-SHA256 签名 或 Session Token -``` - -### 企业实现伪代码(Java) - -```java -/** - * 用户点击作品详情页时调用 - */ -public WorkRecord getWorkDetail(String workId) { - WorkRecord local = db.get(workId); - - // 本地状态 < 3(PENDING 或 PROCESSING),强制从乐读派拉取最新 - if (local != null && local.getStatus() < 3) { - RemoteWork remote = callB2(workId); - - // 同步判断规则与 Webhook、B3 完全一致 - if (remote.status > local.getStatus() - || remote.status == 2 - || remote.status == -1) { - updateAllFields(local, remote); - db.update(local); - } - } - - // 返回最新的本地记录,渲染详情页 - return db.get(workId); -} -``` - -### 前端配合(可选) - -如果企业有自建 C 端,可在作品列表页面根据 status 做路由跳转: - -```javascript -switch (work.status) { - case 1: case 2: // 排队/创作中 - navigate('/creating/' + workId); // → 进度等待页 - break; - case 3: // 图片完成 - navigate('/catalog/' + workId); // → 编目编辑页(强制) - break; - case 4: // 编目完成 - navigate('/dubbing/' + workId); // → 配音编辑页(强制) - break; - case 5: // 配音完成(终态) - navigate('/reader/' + workId); // → 阅读页 - break; - case -1: // 失败 - showError(work.failReason); - break; -} -``` - ---- - -## 三步协同总览 - -``` -┌──────────────────────────────────────────────────────────────────┐ -│ 企业同步三层防线 │ -├──────────────────────────────────────────────────────────────────┤ -│ │ -│ 第一步 Webhook 推送 秒级实时 ← 主通道(可能丢失) │ -│ ↓ 漏网之鱼 │ -│ 第二步 B3 定时对账 30分钟兜底 ← 保障通道(高可靠) │ -│ ↓ 用户等不及 │ -│ 第三步 B2 详情页强制拉取 用户触发 ← 即时补偿(status<3时) │ -│ │ -├──────────────────────────────────────────────────────────────────┤ -│ 三层共用统一同步规则: │ -│ · remote > local → 全量更新 │ -│ · remote == 2 (进度) → 强制更新 │ -│ · remote == -1 (失败) → 强制更新 │ -│ · 其他 → 忽略 │ -└──────────────────────────────────────────────────────────────────┘ -``` - -### 数据流对比 - -| 维度 | 第一步 Webhook | 第二步 B3 对账 | 第三步 B2 强制拉取 | -|------|-------------|------------|---------------| -| 触发方式 | 乐读派主动推送 | 企业定时轮询 | 用户打开详情页 | -| 实时性 | 秒级 | 30分钟级 | 即时 | -| 可靠性 | 可能丢失 | 高可靠 | 高可靠 | -| 触发条件 | 状态变更时自动 | 定时任务 | `local_status < 3` | -| 数据范围 | 单条作品 | 时间范围内批量 | 单条作品 | -| 认证方式 | 签名验证(被动接收) | HMAC 签名(主动请求) | HMAC/Token(主动请求) | - ---- - -## 企业推荐表结构 - -```sql -CREATE TABLE `enterprise_work` ( - `work_id` VARCHAR(32) PRIMARY KEY, - `status` INT NOT NULL DEFAULT 0 COMMENT '状态: 乐读派1-5, 企业>=6', - `progress` INT DEFAULT 0 COMMENT '创作进度0-100', - `title` VARCHAR(200), - `author` VARCHAR(50), - `tags` JSON, - `page_list` JSON COMMENT '页面数据(含image_url/audio_url)', - `original_image_url` VARCHAR(500) COMMENT '用户原创作品图片URL', - `phone` VARCHAR(20) COMMENT '用户手机号(关联企业用户)', - `fail_reason` VARCHAR(500), - `webhook_event_id` VARCHAR(64) COMMENT '最近一次webhook事件ID(幂等去重)', - `synced_at` DATETIME COMMENT '最近同步时间', - `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP, - `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - INDEX `idx_status` (`status`), - INDEX `idx_phone` (`phone`) -); -``` - ---- - -## 管理后台配置项 - -企业需在乐读派管理后台「机构管理」中配置以下 2 项: - -| 配置项 | 填写内容 | 说明 | -|--------|--------|------| -| Webhook URL | `https://你的域名/webhook/leai` | 接收作品状态变更推送(第一步) | -| 认证回调URL | `https://你的域名/leai-auth` | H5 token 失效后跳回重新认证 | - ---- - -> 完整接口规范、签名算法、代码示例请参考《AI绘本创作系统 企业后端集成指南 V4.0》及随附的 `enterprise-demo/java-demo/` 目录。 diff --git a/lesingle-aicreate-client/.env.development b/lesingle-aicreate-client/.env.development deleted file mode 100644 index 8d6df9f..0000000 --- a/lesingle-aicreate-client/.env.development +++ /dev/null @@ -1,5 +0,0 @@ -# 开发环境 -# 与主项目同源的父页面 origin(iframe postMessage 校验目标),局域网调试可改为 http://192.168.1.119:3000 -VITE_CREATE_POST_MESSAGE_URL=http://localhost:3000 -# 子应用部署路径前缀,须与主项目代理路径 /ai-web 一致 -VITE_APP_BASE=/ai-web/ diff --git a/lesingle-aicreate-client/.env.production b/lesingle-aicreate-client/.env.production deleted file mode 100644 index 580bd45..0000000 --- a/lesingle-aicreate-client/.env.production +++ /dev/null @@ -1,4 +0,0 @@ -# 生产环境 -VITE_CREATE_POST_MESSAGE_URL=http://localhost:3000 -# 若静态资源挂在主站 /ai-web 下,保持与开发一致;独立域名部署可改为 / -VITE_APP_BASE=/ai-web/ diff --git a/lesingle-aicreate-client/AI绘本创作系统_企业后端集成指南_V4.0.pdf b/lesingle-aicreate-client/AI绘本创作系统_企业后端集成指南_V4.0.pdf deleted file mode 100644 index 48fa34f..0000000 Binary files a/lesingle-aicreate-client/AI绘本创作系统_企业后端集成指南_V4.0.pdf and /dev/null differ diff --git a/lesingle-aicreate-client/demo/CreationApi.js b/lesingle-aicreate-client/demo/CreationApi.js deleted file mode 100644 index 256f101..0000000 --- a/lesingle-aicreate-client/demo/CreationApi.js +++ /dev/null @@ -1,175 +0,0 @@ -/** - * 乐读派 AI 创作系统 — C 端 API 封装 - * - * 调用流程: - * 1. B1 校验额度 → 2. A1/A2/A3 创作 → 3. 进度追踪 → 4. B2 获取结果 - * - * 所有 API 均需 HMAC-SHA256 签名(除 B6 画风列表) - */ - -import { generateSignHeaders } from './HmacSigner.js' - -export default class CreationApi { - /** - * @param {string} serverUrl - 服务器地址 - * @param {string} appKey - 机构 App Key (orgId) - * @param {string} appSecret - 机构密钥 - */ - constructor(serverUrl, appKey, appSecret) { - this.serverUrl = serverUrl - this.appKey = appKey - this.appSecret = appSecret - } - - // ─── 通用请求方法 ───────────────────────────────────────────────── - - async _get(path, queryParams = {}) { - const signHeaders = generateSignHeaders(this.appKey, this.appSecret, queryParams) - const qs = Object.entries(queryParams).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&') - const url = `${this.serverUrl}${path}${qs ? '?' + qs : ''}` - - const res = await fetch(url, { - method: 'GET', - headers: { ...signHeaders, 'Content-Type': 'application/json' } - }) - return this._handleResponse(res) - } - - async _post(path, body, queryParams = {}) { - // POST 的 JSON body 不参与签名,只有 query params 参与 - const signHeaders = generateSignHeaders(this.appKey, this.appSecret, queryParams) - const qs = Object.entries(queryParams).map(([k, v]) => `${k}=${encodeURIComponent(v)}`).join('&') - const url = `${this.serverUrl}${path}${qs ? '?' + qs : ''}` - - const res = await fetch(url, { - method: 'POST', - headers: { ...signHeaders, 'Content-Type': 'application/json' }, - body: JSON.stringify(body) - }) - return this._handleResponse(res) - } - - async _handleResponse(res) { - if (!res.ok) { - throw new Error(`HTTP ${res.status}: ${res.statusText}`) - } - const json = await res.json() - if (json.code !== 200) { - const err = new Error(json.msg || 'API Error') - err.code = json.code - throw err - } - return json.data - } - - // ─── B 类接口(查询) ───────────────────────────────────────────── - - /** - * B1 - 创作请求校验(检查额度是否充足) - * @param {string} orgId - * @param {string} phone - * @returns {Promise<{valid: boolean, reason?: string, remainQuota?: number}>} - */ - async validate(orgId, phone) { - return this._post('/api/v1/query/validate', { orgId, phone }) - } - - /** - * B2 - 查询作品详情(含实时进度) - * @param {string} workId - * @returns {Promise} - * - * CreationResultVO 结构: - * { - * workId, status, title, author, pages, style, - * videoStatus, videoUrl, failReason, durationMs, retryCount, - * progress, // 0-100 进度百分比,-1 表示失败 - * progressMessage, // "正在绘制第3/7页..." - * pageList: [{pageNum, text, imageUrl, audioUrl}] // 仅 COMPLETED 时有值 - * } - */ - async getWork(workId) { - return this._get(`/api/v1/query/work/${workId}`, { orgId: this.appKey }) - } - - /** - * B3 - 作品列表 - */ - async listWorks(phone, page = 1, pageSize = 20) { - return this._get('/api/v1/query/works', { - orgId: this.appKey, phone, page, pageSize - }) - } - - /** - * B6 - 画风列表(无需签名) - */ - async getStyles() { - const res = await fetch(`${this.serverUrl}/api/v1/query/styles`) - return this._handleResponse(res) - } - - // ─── A 类接口(创作) ───────────────────────────────────────────── - - /** - * A1 - 一句话创作 - * @param {Object} params - * @param {string} params.orgId - * @param {string} params.phone - * @param {string} params.sentence - 故事描述 - * @param {string} params.style - 画风标识 (如 style_cartoon) - * @param {boolean} [params.enableVoice=false] - 是否配音 - * @param {string} [params.author] - 作者名 - * @param {number} [params.age] - 适龄 - * @returns {Promise<{workId: string, status: string}>} - */ - async createBySentence(params) { - return this._post('/api/v1/creation/one-sentence', params) - } - - /** - * A2 - 四要素创作 - * @param {Object} params - * @param {string} params.orgId - * @param {string} params.phone - * @param {string} params.time - 时间 - * @param {string} params.place - 地点 - * @param {string} params.character - 角色 - * @param {string} params.event - 事件 - * @param {string} params.style - * @param {boolean} [params.enableVoice=false] - * @returns {Promise<{workId: string, status: string}>} - */ - async createByElements(params) { - return this._post('/api/v1/creation/scene-elements', params) - } - - /** - * A3 - 图片故事创作 - * @param {Object} params - * @param {string} params.orgId - * @param {string} params.phone - * @param {string} params.imageUrl - 参考图片 URL - * @param {string} [params.storyHint] - 故事方向提示 - * @param {string} params.style - * @param {boolean} [params.enableVoice=false] - * @param {string} [params.heroCharId] - 主角 charId (来自 A5/A6) - * @param {Array<{charId, imageUrl, name}>} [params.characterRefs] - 角色引用列表 - * @returns {Promise<{workId: string, status: string}>} - */ - async createByImage(params) { - return this._post('/api/v1/creation/image-story', params) - } - - /** - * A4 - 视频合成 - * @param {Object} params - * @param {string} params.orgId - * @param {string} params.phone - * @param {string} params.workId - * @returns {Promise<{workId: string}>} - */ - async createVideo(params) { - return this._post('/api/v1/creation/video', params) - } -} diff --git a/lesingle-aicreate-client/demo/CreationProgressTracker.js b/lesingle-aicreate-client/demo/CreationProgressTracker.js deleted file mode 100644 index 2fe5d54..0000000 --- a/lesingle-aicreate-client/demo/CreationProgressTracker.js +++ /dev/null @@ -1,280 +0,0 @@ -/** - * 创作进度追踪器 - * - * 三级通信策略: - * Level 1: WebSocket (STOMP) — 首选,实时推送,自动重连 - * Level 2: B2 HTTP 轮询 — WebSocket 断连期间临时补位 - * Level 3: Redis 进度数据 — 断连期间进度不丢失,重连后立刻获取最新状态 - * - * 使用示例: - * const tracker = new CreationProgressTracker({ - * serverUrl: 'https://your-server.com', - * orgId: 'ORG001', - * appKey: 'ORG001', - * appSecret: 'your-secret', - * workId: '2034987994917769216', - * onProgress: (progress, message) => { - * console.log(`${progress}% - ${message}`) - * }, - * onComplete: (result) => { - * // result.status === 'COMPLETED' => result.pageList 包含完整作品 - * // result.status === 'FAILED' => result.failReason 包含失败原因 - * }, - * onError: (error) => { - * console.error('Tracker error:', error) - * } - * }) - * tracker.start() - * - * // 用户退出页面时 - * tracker.stop() - */ - -import SockJS from 'sockjs-client/dist/sockjs.min.js' -import { Client } from '@stomp/stompjs' -import { generateSignHeaders } from './HmacSigner.js' - -export default class CreationProgressTracker { - /** - * @param {Object} options - * @param {string} options.serverUrl - 服务器地址 (如 https://your-server.com) - * @param {string} options.orgId - 机构ID - * @param {string} options.appKey - HMAC 签名 App Key (通常等于 orgId) - * @param {string} options.appSecret - HMAC 签名密钥 - * @param {string} options.workId - 作品ID - * @param {Function} options.onProgress - 进度回调 (progress: number, message: string) - * @param {Function} options.onComplete - 完成回调 (result: CreationResultVO) - * @param {Function} [options.onError] - 错误回调 (error: Error) - * @param {number} [options.pollInterval=5000] - B2 轮询间隔 (ms) - * @param {number} [options.reconnectDelay=3000] - WebSocket 重连延迟 (ms) - * @param {number} [options.maxPollTimeout=600000] - 最大轮询时间 (ms),默认10分钟 - */ - constructor(options) { - this.serverUrl = options.serverUrl - this.orgId = options.orgId - this.appKey = options.appKey - this.appSecret = options.appSecret - this.workId = options.workId - this.onProgress = options.onProgress || (() => {}) - this.onComplete = options.onComplete || (() => {}) - this.onError = options.onError || (() => {}) - this.pollInterval = options.pollInterval || 5000 - this.reconnectDelay = options.reconnectDelay || 3000 - this.maxPollTimeout = options.maxPollTimeout || 600000 - - this._stompClient = null - this._pollTimer = null - this._wsConnected = false - this._stopped = false - this._startTime = 0 - this._lastProgress = -1 - } - - /** - * 启动进度追踪 - */ - start() { - this._stopped = false - this._startTime = Date.now() - - // 尝试 WebSocket 连接 - this._connectWebSocket() - - // 安全网:5秒内 WS 未连上则启动轮询 - setTimeout(() => { - if (!this._wsConnected && !this._stopped) { - this._startPolling() - } - }, 5000) - } - - /** - * 停止追踪(用户离开页面时调用) - */ - stop() { - this._stopped = true - this._stopPolling() - this._disconnectWebSocket() - } - - // ─── WebSocket (Level 1) ────────────────────────────────────────── - - _connectWebSocket() { - if (this._stopped) return - - try { - const wsUrl = `${this.serverUrl}/ws?orgId=${this.orgId}` - - this._stompClient = new Client({ - webSocketFactory: () => new SockJS(wsUrl), - reconnectDelay: this.reconnectDelay, - heartbeatIncoming: 10000, - heartbeatOutgoing: 10000, - - onConnect: () => { - this._wsConnected = true - this._stopPolling() // WS 连上了,停止轮询 - - // 订阅进度 topic - this._stompClient.subscribe( - `/topic/progress/${this.workId}`, - (msg) => { - try { - const data = JSON.parse(msg.body) - this._handleProgressData(data) - } catch (e) { - // ignore parse errors - } - } - ) - - // 重连成功后,立即查一次 B2 获取断连期间可能错过的最终状态 - this._pollOnce() - }, - - onDisconnect: () => { - this._wsConnected = false - if (!this._stopped) { - this._startPolling() // WS 断了,启动轮询补位 - } - }, - - onStompError: (frame) => { - this._wsConnected = false - if (!this._stopped) { - this._startPolling() - } - }, - - onWebSocketError: () => { - this._wsConnected = false - if (!this._stopped) { - this._startPolling() - } - } - }) - - this._stompClient.activate() - } catch (e) { - // WebSocket 不可用(如被防火墙阻断),降级为纯轮询 - this._startPolling() - } - } - - _disconnectWebSocket() { - if (this._stompClient) { - try { - this._stompClient.deactivate() - } catch (e) { - // ignore - } - this._stompClient = null - } - this._wsConnected = false - } - - // ─── B2 HTTP 轮询 (Level 2) ─────────────────────────────────────── - - _startPolling() { - if (this._pollTimer || this._stopped) return - this._pollTimer = setInterval(() => this._pollOnce(), this.pollInterval) - } - - _stopPolling() { - if (this._pollTimer) { - clearInterval(this._pollTimer) - this._pollTimer = null - } - } - - async _pollOnce() { - if (this._stopped) return - - // 超时保护 - if (Date.now() - this._startTime > this.maxPollTimeout) { - this.stop() - this.onError(new Error('进度查询超时')) - return - } - - try { - const queryParams = { orgId: this.orgId } - const signHeaders = generateSignHeaders(this.appKey, this.appSecret, queryParams) - - const res = await fetch( - `${this.serverUrl}/api/v1/query/work/${this.workId}?orgId=${this.orgId}`, - { headers: { ...signHeaders, 'Content-Type': 'application/json' } } - ) - - if (!res.ok) return - - const json = await res.json() - if (json.code !== 200 || !json.data) return - - const data = json.data - - // 推送进度 - if (data.progress != null && data.progress !== this._lastProgress) { - this._handleProgressData({ - progress: data.progress, - message: data.progressMessage || '' - }) - } - - // 检查是否终态 - if (data.status === 'COMPLETED' || data.status === 'FAILED') { - this.stop() - this.onComplete(data) - } - } catch (e) { - // 网络错误,不中断轮询 - } - } - - // ─── 进度处理 ───────────────────────────────────────────────────── - - _handleProgressData(data) { - if (this._stopped) return - - const progress = data.progress != null ? data.progress : 0 - const message = data.message || '' - - // 去重:相同进度不重复回调 - if (progress === this._lastProgress) return - this._lastProgress = progress - - // 回调 - this.onProgress(progress, message) - - // 终态检测(WebSocket 推送的 progress=100 或 -1) - if (progress === 100) { - // 完成,再查一次 B2 获取完整数据(含 pageList) - setTimeout(() => this._fetchFinalResult(), 1000) - } else if (progress === -1) { - // 失败,查一次 B2 获取 failReason - setTimeout(() => this._fetchFinalResult(), 1000) - } - } - - async _fetchFinalResult() { - try { - const queryParams = { orgId: this.orgId } - const signHeaders = generateSignHeaders(this.appKey, this.appSecret, queryParams) - - const res = await fetch( - `${this.serverUrl}/api/v1/query/work/${this.workId}?orgId=${this.orgId}`, - { headers: { ...signHeaders, 'Content-Type': 'application/json' } } - ) - - if (!res.ok) return - - const json = await res.json() - if (json.code === 200 && json.data) { - this.stop() - this.onComplete(json.data) - } - } catch (e) { - this.onError(e) - } - } -} diff --git a/lesingle-aicreate-client/demo/HmacSigner.js b/lesingle-aicreate-client/demo/HmacSigner.js deleted file mode 100644 index 9dc44e1..0000000 --- a/lesingle-aicreate-client/demo/HmacSigner.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * HMAC-SHA256 签名工具 - * - * 签名规则: - * 1. 将 GET 的 Query 参数 + nonce + timestamp 按 key 字母序排列 - * 2. 格式: key1=value1&key2=value2&... - * 3. POST/PUT 的 JSON body 不参与签名 - * 4. 使用 HMAC-SHA256 算法,以 appSecret 为密钥,输出 hex 小写 - */ - -import CryptoJS from 'crypto-js' - -export function generateSignHeaders(appKey, appSecret, queryParams = {}) { - const timestamp = Date.now().toString() - const nonce = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) - - // Build signature string: sorted query params + nonce + timestamp - const signParams = { ...queryParams, nonce, timestamp } - const sortedKeys = Object.keys(signParams).sort() - const signString = sortedKeys.map(k => `${k}=${signParams[k]}`).join('&') - - // HMAC-SHA256 - const signature = CryptoJS.HmacSHA256(signString, appSecret).toString(CryptoJS.enc.Hex) - - return { - 'X-App-Key': appKey, - 'X-Timestamp': timestamp, - 'X-Nonce': nonce, - 'X-Signature': signature - } -} diff --git a/lesingle-aicreate-client/demo/README.md b/lesingle-aicreate-client/demo/README.md deleted file mode 100644 index 68e476e..0000000 --- a/lesingle-aicreate-client/demo/README.md +++ /dev/null @@ -1,94 +0,0 @@ -# C 端接入 Demo - -乐读派 AI 创作系统 C 端接入参考代码。 - -## 文件说明 - -| 文件 | 说明 | -|------|------| -| `HmacSigner.js` | HMAC-SHA256 签名工具(所有 C 端 API 均需签名) | -| `CreationApi.js` | API 封装(A1-A4 创作 + B1-B6 查询) | -| `CreationProgressTracker.js` | 创作进度追踪器(WebSocket + HTTP 双通道) | -| `example-usage.js` | 完整接入示例(4 个场景) | - -## 快速接入 - -### 1. 安装依赖 - -```bash -npm install crypto-js sockjs-client @stomp/stompjs -``` - -### 2. 最简接入(纯 HTTP 轮询) - -```javascript -import CreationApi from './CreationApi.js' - -const api = new CreationApi('https://server.com', 'ORG001', 'your-secret') - -// 创作 -const { workId } = await api.createBySentence({ - orgId: 'ORG001', phone: '13800138000', - sentence: '小恐龙学游泳', style: 'style_cartoon' -}) - -// 轮询直到完成 -const poll = setInterval(async () => { - const data = await api.getWork(workId) - console.log(`${data.progress}% - ${data.progressMessage}`) - if (data.status === 'COMPLETED' || data.status === 'FAILED') { - clearInterval(poll) - console.log(data.status === 'COMPLETED' ? data.pageList : data.failReason) - } -}, 5000) -``` - -### 3. 最佳体验(WebSocket + 自动降级) - -```javascript -import CreationApi from './CreationApi.js' -import CreationProgressTracker from './CreationProgressTracker.js' - -const api = new CreationApi('https://server.com', 'ORG001', 'your-secret') -const { workId } = await api.createBySentence({ ... }) - -const tracker = new CreationProgressTracker({ - serverUrl: 'https://server.com', - orgId: 'ORG001', appKey: 'ORG001', appSecret: 'your-secret', - workId, - onProgress: (pct, msg) => updateUI(pct, msg), - onComplete: (result) => showResult(result) -}) -tracker.start() - -// 用户离开页面时 -tracker.stop() -``` - -## 接口清单 - -| 接口 | 方法 | 路径 | 签名 | 说明 | -|------|------|------|------|------| -| B1 | POST | /api/v1/query/validate | 需要 | 校验额度 | -| B2 | GET | /api/v1/query/work/{workId} | 需要 | 作品详情+实时进度 | -| B3 | GET | /api/v1/query/works | 需要 | 作品列表 | -| B6 | GET | /api/v1/query/styles | 不需要 | 画风列表 | -| A1 | POST | /api/v1/creation/one-sentence | 需要 | 一句话创作 | -| A2 | POST | /api/v1/creation/scene-elements | 需要 | 四要素创作 | -| A3 | POST | /api/v1/creation/image-story | 需要 | 图片故事创作 | -| A4 | POST | /api/v1/creation/video | 需要 | 视频合成 | - -## 进度追踪策略 - -``` -WebSocket 连接成功 - │ 实时推送 progress + message - │ - ├─ 断连 → 自动重连(3秒间隔) - │ 同时启动 B2 HTTP 轮询补位(5秒间隔) - │ - ├─ 重连成功 → 停止轮询,恢复 WebSocket - │ 立即查一次 B2 补齐断连期间状态 - │ - └─ progress=100 或 -1 → 查 B2 获取完整数据 → onComplete 回调 -``` diff --git a/lesingle-aicreate-client/demo/example-usage.js b/lesingle-aicreate-client/demo/example-usage.js deleted file mode 100644 index 67f525e..0000000 --- a/lesingle-aicreate-client/demo/example-usage.js +++ /dev/null @@ -1,197 +0,0 @@ -/** - * 乐读派 AI 创作系统 — C 端接入完整示例 - * - * 依赖安装: - * npm install crypto-js sockjs-client @stomp/stompjs - * - * 本示例演示完整的创作流程: - * 1. 校验额度 - * 2. 获取画风列表 - * 3. 发起 A1/A3 创作 - * 4. WebSocket + HTTP 轮询双通道追踪进度 - * 5. 获取创作结果 - */ - -import CreationApi from './CreationApi.js' -import CreationProgressTracker from './CreationProgressTracker.js' - -// ═══════════════════════════════════════════════════════════════════ -// 配置(替换为实际值) -// ═══════════════════════════════════════════════════════════════════ -const CONFIG = { - serverUrl: 'https://your-server.com', // 替换为实际服务器地址 - appKey: 'ORG001', // 机构 App Key - appSecret: 'your-app-secret', // 机构密钥(联系管理员获取) - phone: '13800138000' // 用户手机号 -} - -const api = new CreationApi(CONFIG.serverUrl, CONFIG.appKey, CONFIG.appSecret) - -// ═══════════════════════════════════════════════════════════════════ -// 示例 1: A1 一句话创作(最简单的接入方式) -// ═══════════════════════════════════════════════════════════════════ -async function exampleA1Creation() { - console.log('=== A1 一句话创作 ===') - - // Step 1: 校验额度 - const validation = await api.validate(CONFIG.appKey, CONFIG.phone) - if (!validation.valid) { - console.error('额度不足:', validation.reason) - return - } - console.log('额度校验通过,剩余:', validation.remainQuota) - - // Step 2: 获取画风列表 - const styles = await api.getStyles() - console.log('可用画风:', styles.map(s => s.styleName).join(', ')) - - // Step 3: 发起创作 - const result = await api.createBySentence({ - orgId: CONFIG.appKey, - phone: CONFIG.phone, - sentence: '小恐龙学游泳', - style: 'style_cartoon', - enableVoice: false, - author: '小朋友', - age: 5 - }) - console.log('创作已提交,workId:', result.workId) - - // Step 4: 追踪进度(WebSocket + HTTP 双通道) - const tracker = new CreationProgressTracker({ - serverUrl: CONFIG.serverUrl, - orgId: CONFIG.appKey, - appKey: CONFIG.appKey, - appSecret: CONFIG.appSecret, - workId: result.workId, - - onProgress: (progress, message) => { - // 更新 UI 进度条 - console.log(`[${progress}%] ${message}`) - // updateProgressBar(progress) - // updateStatusText(message) - }, - - onComplete: (data) => { - if (data.status === 'COMPLETED') { - console.log('创作完成!') - console.log('标题:', data.title) - console.log('页数:', data.pageList.length) - console.log('耗时:', Math.round(data.durationMs / 1000), '秒') - - // 展示绘本 - data.pageList.forEach(page => { - console.log(` P${page.pageNum}: ${page.text}`) - console.log(` 图片: ${page.imageUrl}`) - if (page.audioUrl) console.log(` 音频: ${page.audioUrl}`) - }) - } else { - console.error('创作失败:', data.failReason) - if (data.retryCount > 0) { - console.log(`(已自动重试 ${data.retryCount} 次)`) - } - } - }, - - onError: (err) => { - console.error('追踪异常:', err.message) - } - }) - - tracker.start() -} - -// ═══════════════════════════════════════════════════════════════════ -// 示例 2: A3 图片故事创作(带角色引用) -// ═══════════════════════════════════════════════════════════════════ -async function exampleA3Creation() { - console.log('=== A3 图片故事创作 ===') - - const result = await api.createByImage({ - orgId: CONFIG.appKey, - phone: CONFIG.phone, - imageUrl: 'https://your-oss.com/upload/child-drawing.png', - storyHint: '小兔子去森林冒险', - style: 'style_watercolor', - enableVoice: true, - // 可选: 从 A5/A6 提取的角色引用 - // heroCharId: 'char_123', - // characterRefs: [{ charId: 'char_123', imageUrl: 'https://...', name: '小兔子' }] - }) - - console.log('A3 创作已提交,workId:', result.workId) - - // 使用 tracker 追踪进度(同示例1) - const tracker = new CreationProgressTracker({ - serverUrl: CONFIG.serverUrl, - orgId: CONFIG.appKey, - appKey: CONFIG.appKey, - appSecret: CONFIG.appSecret, - workId: result.workId, - onProgress: (p, m) => console.log(`[${p}%] ${m}`), - onComplete: (data) => console.log('完成:', data.status, data.title) - }) - tracker.start() -} - -// ═══════════════════════════════════════════════════════════════════ -// 示例 3: 纯 B2 轮询(不使用 WebSocket,最简单接入) -// ═══════════════════════════════════════════════════════════════════ -async function exampleSimplePolling(workId) { - console.log('=== 纯 HTTP 轮询模式 ===') - - const poll = async () => { - const data = await api.getWork(workId) - console.log(`[${data.progress}%] ${data.progressMessage}`) - - if (data.status === 'COMPLETED') { - console.log('完成! 标题:', data.title, '页数:', data.pageList.length) - return - } - if (data.status === 'FAILED') { - console.error('失败:', data.failReason) - return - } - - // 继续轮询 - setTimeout(poll, 5000) - } - - poll() -} - -// ═══════════════════════════════════════════════════════════════════ -// 示例 4: A4 视频合成(基于已完成的作品) -// ═══════════════════════════════════════════════════════════════════ -async function exampleVideoCreation(workId) { - console.log('=== A4 视频合成 ===') - - const result = await api.createVideo({ - orgId: CONFIG.appKey, - phone: CONFIG.phone, - workId: workId - }) - - console.log('视频合成已提交,轮询视频状态...') - - const poll = async () => { - const data = await api.getWork(workId) - if (data.videoStatus === 'VIDEO_COMPLETED') { - console.log('视频完成:', data.videoUrl) - return - } - if (data.videoStatus === 'VIDEO_FAILED') { - console.error('视频失败:', data.failReason) - return - } - setTimeout(poll, 5000) - } - - poll() -} - -// 运行示例 -// exampleA1Creation() -// exampleA3Creation() -// exampleSimplePolling('your-work-id') -// exampleVideoCreation('your-work-id') diff --git a/lesingle-aicreate-client/index.html b/lesingle-aicreate-client/index.html deleted file mode 100644 index 5019931..0000000 --- a/lesingle-aicreate-client/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - 乐读派 - AI智能儿童绘本创作 - - - -
- - - - - diff --git a/lesingle-aicreate-client/package-lock.json b/lesingle-aicreate-client/package-lock.json deleted file mode 100644 index 894e263..0000000 --- a/lesingle-aicreate-client/package-lock.json +++ /dev/null @@ -1,2790 +0,0 @@ -{ - "name": "lesingle-aicreate-client", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "lesingle-aicreate-client", - "version": "1.0.0", - "dependencies": { - "@stomp/stompjs": "^7.3.0", - "ali-oss": "^6.23.0", - "axios": "^1.7.0", - "crypto-js": "^4.2.0", - "vue": "^3.5.0", - "vue-router": "^4.5.0" - }, - "devDependencies": { - "@vitejs/plugin-basic-ssl": "^2.3.0", - "@vitejs/plugin-vue": "^5.2.0", - "sass": "^1.80.0", - "vite": "^6.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@parcel/watcher": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", - "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "detect-libc": "^2.0.3", - "is-glob": "^4.0.3", - "node-addon-api": "^7.0.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "@parcel/watcher-android-arm64": "2.5.6", - "@parcel/watcher-darwin-arm64": "2.5.6", - "@parcel/watcher-darwin-x64": "2.5.6", - "@parcel/watcher-freebsd-x64": "2.5.6", - "@parcel/watcher-linux-arm-glibc": "2.5.6", - "@parcel/watcher-linux-arm-musl": "2.5.6", - "@parcel/watcher-linux-arm64-glibc": "2.5.6", - "@parcel/watcher-linux-arm64-musl": "2.5.6", - "@parcel/watcher-linux-x64-glibc": "2.5.6", - "@parcel/watcher-linux-x64-musl": "2.5.6", - "@parcel/watcher-win32-arm64": "2.5.6", - "@parcel/watcher-win32-ia32": "2.5.6", - "@parcel/watcher-win32-x64": "2.5.6" - } - }, - "node_modules/@parcel/watcher-android-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", - "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", - "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-darwin-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", - "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-freebsd-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", - "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", - "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", - "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", - "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-arm64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", - "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-glibc": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", - "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-linux-x64-musl": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", - "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-arm64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", - "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-ia32": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", - "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@parcel/watcher-win32-x64": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", - "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.0.tgz", - "integrity": "sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.0.tgz", - "integrity": "sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.0.tgz", - "integrity": "sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.0.tgz", - "integrity": "sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.0.tgz", - "integrity": "sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.0.tgz", - "integrity": "sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.0.tgz", - "integrity": "sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.0.tgz", - "integrity": "sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.0.tgz", - "integrity": "sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.0.tgz", - "integrity": "sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.0.tgz", - "integrity": "sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.0.tgz", - "integrity": "sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.0.tgz", - "integrity": "sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.0.tgz", - "integrity": "sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.0.tgz", - "integrity": "sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.0.tgz", - "integrity": "sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.0.tgz", - "integrity": "sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.0.tgz", - "integrity": "sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.0.tgz", - "integrity": "sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.0.tgz", - "integrity": "sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.0.tgz", - "integrity": "sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.0.tgz", - "integrity": "sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.0.tgz", - "integrity": "sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.0.tgz", - "integrity": "sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.0.tgz", - "integrity": "sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@stomp/stompjs": { - "version": "7.3.0", - "resolved": "https://registry.npmmirror.com/@stomp/stompjs/-/stompjs-7.3.0.tgz", - "integrity": "sha512-nKMLoFfJhrQAqkvvKd1vLq/cVBGCMwPRCD0LqW7UT1fecRx9C3GoKEIR2CYwVuErGeZu8w0kFkl2rlhPlqHVgQ==" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitejs/plugin-basic-ssl": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-2.3.0.tgz", - "integrity": "sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "peerDependencies": { - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@vitejs/plugin-vue": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", - "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "vite": "^5.0.0 || ^6.0.0", - "vue": "^3.2.25" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.30.tgz", - "integrity": "sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@vue/shared": "3.5.30", - "entities": "^7.0.1", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.30.tgz", - "integrity": "sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g==", - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.30", - "@vue/shared": "3.5.30" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.30.tgz", - "integrity": "sha512-LqmFPDn89dtU9vI3wHJnwaV6GfTRD87AjWpTWpyrdVOObVtjIuSeZr181z5C4PmVx/V3j2p+0f7edFKGRMpQ5A==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@vue/compiler-core": "3.5.30", - "@vue/compiler-dom": "3.5.30", - "@vue/compiler-ssr": "3.5.30", - "@vue/shared": "3.5.30", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.21", - "postcss": "^8.5.8", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.30.tgz", - "integrity": "sha512-NsYK6OMTnx109PSL2IAyf62JP6EUdk4Dmj6AkWcJGBvN0dQoMYtVekAmdqgTtWQgEJo+Okstbf/1p7qZr5H+bA==", - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.30", - "@vue/shared": "3.5.30" - } - }, - "node_modules/@vue/devtools-api": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", - "license": "MIT" - }, - "node_modules/@vue/reactivity": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.30.tgz", - "integrity": "sha512-179YNgKATuwj9gB+66snskRDOitDiuOZqkYia7mHKJaidOMo/WJxHKF8DuGc4V4XbYTJANlfEKb0yxTQotnx4Q==", - "license": "MIT", - "dependencies": { - "@vue/shared": "3.5.30" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.30.tgz", - "integrity": "sha512-e0Z+8PQsUTdwV8TtEsLzUM7SzC7lQwYKePydb7K2ZnmS6jjND+WJXkmmfh/swYzRyfP1EY3fpdesyYoymCzYfg==", - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.5.30", - "@vue/shared": "3.5.30" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.30.tgz", - "integrity": "sha512-2UIGakjU4WSQ0T4iwDEW0W7vQj6n7AFn7taqZ9Cvm0Q/RA2FFOziLESrDL4GmtI1wV3jXg5nMoJSYO66egDUBw==", - "license": "MIT", - "dependencies": { - "@vue/reactivity": "3.5.30", - "@vue/runtime-core": "3.5.30", - "@vue/shared": "3.5.30", - "csstype": "^3.2.3" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.30.tgz", - "integrity": "sha512-v+R34icapydRwbZRD0sXwtHqrQJv38JuMB4JxbOxd8NEpGLny7cncMp53W9UH/zo4j8eDHjQ1dEJXwzFQknjtQ==", - "license": "MIT", - "dependencies": { - "@vue/compiler-ssr": "3.5.30", - "@vue/shared": "3.5.30" - }, - "peerDependencies": { - "vue": "3.5.30" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.30.tgz", - "integrity": "sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ==", - "license": "MIT" - }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "3.5.3", - "resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-3.5.3.tgz", - "integrity": "sha512-yqXL+k5rr8+ZRpOAntkaaRgWgE5o8ESAj5DyRmVTCSoZxXmqemb9Dd7T4i5UzwuERdLAJUy6XzR9zFVuf0kzkw==", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/ali-oss": { - "version": "6.23.0", - "resolved": "https://registry.npmmirror.com/ali-oss/-/ali-oss-6.23.0.tgz", - "integrity": "sha512-FipRmyd16Pr/tEey/YaaQ/24Pc3HEpLM9S1DRakEuXlSLXNIJnu1oJtHM53eVYpvW3dXapSjrip3xylZUTIZVQ==", - "dependencies": { - "address": "^1.2.2", - "agentkeepalive": "^3.4.1", - "bowser": "^1.6.0", - "copy-to": "^2.0.1", - "dateformat": "^2.0.0", - "debug": "^4.3.4", - "destroy": "^1.0.4", - "end-or-error": "^1.0.1", - "get-ready": "^1.0.0", - "humanize-ms": "^1.2.0", - "is-type-of": "^1.4.0", - "js-base64": "^2.5.2", - "jstoxml": "^2.0.0", - "lodash": "^4.17.21", - "merge-descriptors": "^1.0.1", - "mime": "^2.4.5", - "platform": "^1.3.1", - "pump": "^3.0.0", - "qs": "^6.4.0", - "sdk-base": "^2.0.1", - "stream-http": "2.8.2", - "stream-wormhole": "^1.0.4", - "urllib": "^2.44.0", - "utility": "^1.18.0", - "xml2js": "^0.6.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.6.tgz", - "integrity": "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/bowser": { - "version": "1.9.4", - "resolved": "https://registry.npmmirror.com/bowser/-/bowser-1.9.4.tgz", - "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" - }, - "node_modules/builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==" - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/copy-to": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/copy-to/-/copy-to-2.0.1.tgz", - "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/default-user-agent": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/default-user-agent/-/default-user-agent-1.0.0.tgz", - "integrity": "sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==", - "dependencies": { - "os-name": "~1.0.3" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/digest-header": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/digest-header/-/digest-header-1.1.0.tgz", - "integrity": "sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==", - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/end-or-error": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/end-or-error/-/end-or-error-1.0.1.tgz", - "integrity": "sha512-OclLMSug+k2A0JKuf494im25ANRBVW8qsjmwbgX7lQ8P82H21PQ1PWkoYwb9y5yMBS69BPlwtzdIFClo3+7kOQ==", - "engines": { - "node": ">= 0.11.14" - } - }, - "node_modules/entities": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", - "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/formstream": { - "version": "1.5.2", - "resolved": "https://registry.npmmirror.com/formstream/-/formstream-1.5.2.tgz", - "integrity": "sha512-NASf0lgxC1AyKNXQIrXTEYkiX99LhCEXTkiGObXAkpBui86a4u8FjH1o2bGb3PpqI3kafC+yw4zWeK6l6VHTgg==", - "dependencies": { - "destroy": "^1.0.4", - "mime": "^2.5.2", - "node-hex": "^1.0.1", - "pause-stream": "~0.0.11" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-ready": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/get-ready/-/get-ready-1.0.0.tgz", - "integrity": "sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==" - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/immutable": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", - "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", - "dev": true, - "license": "MIT" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is-class-hotfix": { - "version": "0.0.6", - "resolved": "https://registry.npmmirror.com/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz", - "integrity": "sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==" - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmmirror.com/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-type-of": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/is-type-of/-/is-type-of-1.4.0.tgz", - "integrity": "sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==", - "dependencies": { - "core-util-is": "^1.0.2", - "is-class-hotfix": "~0.0.6", - "isstream": "~0.1.2" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==" - }, - "node_modules/jstoxml": { - "version": "2.2.9", - "resolved": "https://registry.npmmirror.com/jstoxml/-/jstoxml-2.2.9.tgz", - "integrity": "sha512-OYWlK0j+roh+eyaMROlNbS5cd5R25Y+IUpdl7cNdB8HNrkgwQzIS7L9MegxOiWNBj9dQhA/yAxiMwCC5mwNoBw==" - }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==" - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmmirror.com/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmmirror.com/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/node-hex": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/node-hex/-/node-hex-1.0.1.tgz", - "integrity": "sha512-iwpZdvW6Umz12ICmu9IYPRxg0tOLGmU3Tq2tKetejCj3oZd7b2nUXwP3a7QA5M9glWy8wlPS1G3RwM/CdsUbdQ==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/os-name": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/os-name/-/os-name-1.0.3.tgz", - "integrity": "sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==", - "dependencies": { - "osx-release": "^1.0.0", - "win-release": "^1.0.0" - }, - "bin": { - "os-name": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/osx-release": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/osx-release/-/osx-release-1.1.0.tgz", - "integrity": "sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==", - "dependencies": { - "minimist": "^1.1.0" - }, - "bin": { - "osx-release": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmmirror.com/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/platform": { - "version": "1.3.6", - "resolved": "https://registry.npmmirror.com/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmmirror.com/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/rollup": { - "version": "4.60.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.0.tgz", - "integrity": "sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.0", - "@rollup/rollup-android-arm64": "4.60.0", - "@rollup/rollup-darwin-arm64": "4.60.0", - "@rollup/rollup-darwin-x64": "4.60.0", - "@rollup/rollup-freebsd-arm64": "4.60.0", - "@rollup/rollup-freebsd-x64": "4.60.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.0", - "@rollup/rollup-linux-arm-musleabihf": "4.60.0", - "@rollup/rollup-linux-arm64-gnu": "4.60.0", - "@rollup/rollup-linux-arm64-musl": "4.60.0", - "@rollup/rollup-linux-loong64-gnu": "4.60.0", - "@rollup/rollup-linux-loong64-musl": "4.60.0", - "@rollup/rollup-linux-ppc64-gnu": "4.60.0", - "@rollup/rollup-linux-ppc64-musl": "4.60.0", - "@rollup/rollup-linux-riscv64-gnu": "4.60.0", - "@rollup/rollup-linux-riscv64-musl": "4.60.0", - "@rollup/rollup-linux-s390x-gnu": "4.60.0", - "@rollup/rollup-linux-x64-gnu": "4.60.0", - "@rollup/rollup-linux-x64-musl": "4.60.0", - "@rollup/rollup-openbsd-x64": "4.60.0", - "@rollup/rollup-openharmony-arm64": "4.60.0", - "@rollup/rollup-win32-arm64-msvc": "4.60.0", - "@rollup/rollup-win32-ia32-msvc": "4.60.0", - "@rollup/rollup-win32-x64-gnu": "4.60.0", - "@rollup/rollup-win32-x64-msvc": "4.60.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sass": { - "version": "1.98.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.98.0.tgz", - "integrity": "sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": "^4.0.0", - "immutable": "^5.1.5", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "@parcel/watcher": "^2.4.1" - } - }, - "node_modules/sax": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/sax/-/sax-1.6.0.tgz", - "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", - "engines": { - "node": ">=11.0.0" - } - }, - "node_modules/sdk-base": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/sdk-base/-/sdk-base-2.0.1.tgz", - "integrity": "sha512-eeG26wRwhtwYuKGCDM3LixCaxY27Pa/5lK4rLKhQa7HBjJ3U3Y+f81MMZQRsDw/8SC2Dao/83yJTXJ8aULuN8Q==", - "dependencies": { - "get-ready": "~1.0.0" - } - }, - "node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmmirror.com/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/stream-http": { - "version": "2.8.2", - "resolved": "https://registry.npmmirror.com/stream-http/-/stream-http-2.8.2.tgz", - "integrity": "sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/stream-wormhole": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/stream-wormhole/-/stream-wormhole-1.1.0.tgz", - "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmmirror.com/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmmirror.com/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==" - }, - "node_modules/unescape": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/unescape/-/unescape-1.0.1.tgz", - "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", - "dependencies": { - "extend-shallow": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/urllib": { - "version": "2.44.0", - "resolved": "https://registry.npmmirror.com/urllib/-/urllib-2.44.0.tgz", - "integrity": "sha512-zRCJqdfYllRDA9bXUtx+vccyRqtJPKsw85f44zH7zPD28PIvjMqIgw9VwoTLV7xTBWZsbebUFVHU5ghQcWku2A==", - "dependencies": { - "any-promise": "^1.3.0", - "content-type": "^1.0.2", - "default-user-agent": "^1.0.0", - "digest-header": "^1.0.0", - "ee-first": "~1.1.1", - "formstream": "^1.1.0", - "humanize-ms": "^1.2.0", - "iconv-lite": "^0.6.3", - "pump": "^3.0.0", - "qs": "^6.4.0", - "statuses": "^1.3.1", - "utility": "^1.16.1" - }, - "engines": { - "node": ">= 0.10.0" - }, - "peerDependencies": { - "proxy-agent": "^5.0.0" - }, - "peerDependenciesMeta": { - "proxy-agent": { - "optional": true - } - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/utility": { - "version": "1.18.0", - "resolved": "https://registry.npmmirror.com/utility/-/utility-1.18.0.tgz", - "integrity": "sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==", - "dependencies": { - "copy-to": "^2.0.1", - "escape-html": "^1.0.3", - "mkdirp": "^0.5.1", - "mz": "^2.7.0", - "unescape": "^1.0.1" - }, - "engines": { - "node": ">= 0.12.0" - } - }, - "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vue": { - "version": "3.5.30", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.30.tgz", - "integrity": "sha512-hTHLc6VNZyzzEH/l7PFGjpcTvUgiaPK5mdLkbjrTeWSRcEfxFrv56g/XckIYlE9ckuobsdwqd5mk2g1sBkMewg==", - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.30", - "@vue/compiler-sfc": "3.5.30", - "@vue/runtime-dom": "3.5.30", - "@vue/server-renderer": "3.5.30", - "@vue/shared": "3.5.30" - }, - "peerDependencies": { - "typescript": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/vue-router": { - "version": "4.6.4", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", - "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", - "license": "MIT", - "dependencies": { - "@vue/devtools-api": "^6.6.4" - }, - "funding": { - "url": "https://github.com/sponsors/posva" - }, - "peerDependencies": { - "vue": "^3.5.0" - } - }, - "node_modules/win-release": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/win-release/-/win-release-1.1.1.tgz", - "integrity": "sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==", - "dependencies": { - "semver": "^5.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/xml2js": { - "version": "0.6.2", - "resolved": "https://registry.npmmirror.com/xml2js/-/xml2js-0.6.2.tgz", - "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "engines": { - "node": ">=0.4" - } - } - } -} diff --git a/lesingle-aicreate-client/package.json b/lesingle-aicreate-client/package.json deleted file mode 100644 index 923240c..0000000 --- a/lesingle-aicreate-client/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "lesingle-aicreate-client", - "private": true, - "version": "1.0.0", - "type": "module", - "scripts": { - "dev": "vite --port 3001", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "@stomp/stompjs": "^7.3.0", - "ali-oss": "^6.23.0", - "axios": "^1.7.0", - "crypto-js": "^4.2.0", - "vue": "^3.5.0", - "vue-router": "^4.5.0" - }, - "devDependencies": { - "@vitejs/plugin-basic-ssl": "^2.3.0", - "@vitejs/plugin-vue": "^5.2.0", - "sass": "^1.80.0", - "vite": "^6.0.0" - } -} diff --git a/lesingle-aicreate-client/pnpm-lock.yaml b/lesingle-aicreate-client/pnpm-lock.yaml deleted file mode 100644 index 784cb22..0000000 --- a/lesingle-aicreate-client/pnpm-lock.yaml +++ /dev/null @@ -1,1863 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@stomp/stompjs': - specifier: ^7.3.0 - version: 7.3.0 - ali-oss: - specifier: ^6.23.0 - version: 6.23.0 - axios: - specifier: ^1.7.0 - version: 1.14.0 - crypto-js: - specifier: ^4.2.0 - version: 4.2.0 - vue: - specifier: ^3.5.0 - version: 3.5.31 - vue-router: - specifier: ^4.5.0 - version: 4.6.4(vue@3.5.31) - devDependencies: - '@vitejs/plugin-basic-ssl': - specifier: ^2.3.0 - version: 2.3.0(vite@6.4.1(sass@1.98.0)) - '@vitejs/plugin-vue': - specifier: ^5.2.0 - version: 5.2.4(vite@6.4.1(sass@1.98.0))(vue@3.5.31) - sass: - specifier: ^1.80.0 - version: 1.98.0 - vite: - specifier: ^6.0.0 - version: 6.4.1(sass@1.98.0) - -packages: - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@parcel/watcher-android-arm64@2.5.6': - resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [android] - - '@parcel/watcher-darwin-arm64@2.5.6': - resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [darwin] - - '@parcel/watcher-darwin-x64@2.5.6': - resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [darwin] - - '@parcel/watcher-freebsd-x64@2.5.6': - resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [freebsd] - - '@parcel/watcher-linux-arm-glibc@2.5.6': - resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@parcel/watcher-linux-arm-musl@2.5.6': - resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} - engines: {node: '>= 10.0.0'} - cpu: [arm] - os: [linux] - libc: [musl] - - '@parcel/watcher-linux-arm64-glibc@2.5.6': - resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@parcel/watcher-linux-arm64-musl@2.5.6': - resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@parcel/watcher-linux-x64-glibc@2.5.6': - resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@parcel/watcher-linux-x64-musl@2.5.6': - resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@parcel/watcher-win32-arm64@2.5.6': - resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} - engines: {node: '>= 10.0.0'} - cpu: [arm64] - os: [win32] - - '@parcel/watcher-win32-ia32@2.5.6': - resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - - '@parcel/watcher-win32-x64@2.5.6': - resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} - engines: {node: '>= 10.0.0'} - cpu: [x64] - os: [win32] - - '@parcel/watcher@2.5.6': - resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} - engines: {node: '>= 10.0.0'} - - '@rollup/rollup-android-arm-eabi@4.60.1': - resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.60.1': - resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.60.1': - resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.60.1': - resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.60.1': - resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.60.1': - resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.60.1': - resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.60.1': - resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.60.1': - resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.60.1': - resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.60.1': - resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.60.1': - resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.60.1': - resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.60.1': - resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.60.1': - resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.60.1': - resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.60.1': - resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.60.1': - resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.60.1': - resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.60.1': - resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.60.1': - resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.60.1': - resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.60.1': - resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.60.1': - resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.60.1': - resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==} - cpu: [x64] - os: [win32] - - '@stomp/stompjs@7.3.0': - resolution: {integrity: sha512-nKMLoFfJhrQAqkvvKd1vLq/cVBGCMwPRCD0LqW7UT1fecRx9C3GoKEIR2CYwVuErGeZu8w0kFkl2rlhPlqHVgQ==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@vitejs/plugin-basic-ssl@2.3.0': - resolution: {integrity: sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - peerDependencies: - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - - '@vitejs/plugin-vue@5.2.4': - resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} - engines: {node: ^18.0.0 || >=20.0.0} - peerDependencies: - vite: ^5.0.0 || ^6.0.0 - vue: ^3.2.25 - - '@vue/compiler-core@3.5.31': - resolution: {integrity: sha512-k/ueL14aNIEy5Onf0OVzR8kiqF/WThgLdFhxwa4e/KF/0qe38IwIdofoSWBTvvxQOesaz6riAFAUaYjoF9fLLQ==} - - '@vue/compiler-dom@3.5.31': - resolution: {integrity: sha512-BMY/ozS/xxjYqRFL+tKdRpATJYDTTgWSo0+AJvJNg4ig+Hgb0dOsHPXvloHQ5hmlivUqw1Yt2pPIqp4e0v1GUw==} - - '@vue/compiler-sfc@3.5.31': - resolution: {integrity: sha512-M8wpPgR9UJ8MiRGjppvx9uWJfLV7A/T+/rL8s/y3QG3u0c2/YZgff3d6SuimKRIhcYnWg5fTfDMlz2E6seUW8Q==} - - '@vue/compiler-ssr@3.5.31': - resolution: {integrity: sha512-h0xIMxrt/LHOvJKMri+vdYT92BrK3HFLtDqq9Pr/lVVfE4IyKZKvWf0vJFW10Yr6nX02OR4MkJwI0c1HDa1hog==} - - '@vue/devtools-api@6.6.4': - resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} - - '@vue/reactivity@3.5.31': - resolution: {integrity: sha512-DtKXxk9E/KuVvt8VxWu+6Luc9I9ETNcqR1T1oW1gf02nXaZ1kuAx58oVu7uX9XxJR0iJCro6fqBLw9oSBELo5g==} - - '@vue/runtime-core@3.5.31': - resolution: {integrity: sha512-AZPmIHXEAyhpkmN7aWlqjSfYynmkWlluDNPHMCZKFHH+lLtxP/30UJmoVhXmbDoP1Ng0jG0fyY2zCj1PnSSA6Q==} - - '@vue/runtime-dom@3.5.31': - resolution: {integrity: sha512-xQJsNRmGPeDCJq/u813tyonNgWBFjzfVkBwDREdEWndBnGdHLHgkwNBQxLtg4zDrzKTEcnikUy1UUNecb3lJ6g==} - - '@vue/server-renderer@3.5.31': - resolution: {integrity: sha512-GJuwRvMcdZX/CriUnyIIOGkx3rMV3H6sOu0JhdKbduaeCji6zb60iOGMY7tFoN24NfsUYoFBhshZtGxGpxO4iA==} - peerDependencies: - vue: 3.5.31 - - '@vue/shared@3.5.31': - resolution: {integrity: sha512-nBxuiuS9Lj5bPkPbWogPUnjxxWpkRniX7e5UBQDWl6Fsf4roq9wwV+cR7ezQ4zXswNvPIlsdj1slcLB7XCsRAw==} - - address@1.2.2: - resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} - engines: {node: '>= 10.0.0'} - - agentkeepalive@3.5.3: - resolution: {integrity: sha512-yqXL+k5rr8+ZRpOAntkaaRgWgE5o8ESAj5DyRmVTCSoZxXmqemb9Dd7T4i5UzwuERdLAJUy6XzR9zFVuf0kzkw==} - engines: {node: '>= 4.0.0'} - - ali-oss@6.23.0: - resolution: {integrity: sha512-FipRmyd16Pr/tEey/YaaQ/24Pc3HEpLM9S1DRakEuXlSLXNIJnu1oJtHM53eVYpvW3dXapSjrip3xylZUTIZVQ==} - engines: {node: '>=8'} - - any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - axios@1.14.0: - resolution: {integrity: sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==} - - bowser@1.9.4: - resolution: {integrity: sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==} - - builtin-status-codes@3.0.0: - resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} - - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - - chokidar@4.0.3: - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} - engines: {node: '>= 14.16.0'} - - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - - copy-to@2.0.1: - resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==} - - core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - crypto-js@4.2.0: - resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - - dateformat@2.2.0: - resolution: {integrity: sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - default-user-agent@1.0.0: - resolution: {integrity: sha512-bDF7bg6OSNcSwFWPu4zYKpVkJZQYVrAANMYB8bc9Szem1D0yKdm4sa/rOCs2aC9+2GMqQ7KnwtZRvDhmLF0dXw==} - engines: {node: '>= 0.10.0'} - - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - - destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - digest-header@1.1.0: - resolution: {integrity: sha512-glXVh42vz40yZb9Cq2oMOt70FIoWiv+vxNvdKdU8CwjLad25qHM3trLxhl9bVjdr6WaslIXhWpn0NO8T/67Qjg==} - engines: {node: '>= 8.0.0'} - - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - - end-of-stream@1.4.5: - resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} - - end-or-error@1.0.1: - resolution: {integrity: sha512-OclLMSug+k2A0JKuf494im25ANRBVW8qsjmwbgX7lQ8P82H21PQ1PWkoYwb9y5yMBS69BPlwtzdIFClo3+7kOQ==} - engines: {node: '>= 0.11.14'} - - entities@7.0.1: - resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} - engines: {node: '>=0.12'} - - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} - engines: {node: '>= 0.4'} - - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - engines: {node: '>= 0.4'} - - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} - engines: {node: '>= 0.4'} - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true - - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - - extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} - - formstream@1.5.2: - resolution: {integrity: sha512-NASf0lgxC1AyKNXQIrXTEYkiX99LhCEXTkiGObXAkpBui86a4u8FjH1o2bGb3PpqI3kafC+yw4zWeK6l6VHTgg==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} - - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} - - get-ready@1.0.0: - resolution: {integrity: sha512-mFXCZPJIlcYcth+N8267+mghfYN9h3EhsDa6JSnbA3Wrhh/XFpuowviFcsDeYZtKspQyWyJqfs4O6P8CHeTwzw==} - - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} - engines: {node: '>= 0.4'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - - humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - immutable@5.1.5: - resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==} - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-class-hotfix@0.0.6: - resolution: {integrity: sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ==} - - is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-type-of@1.4.0: - resolution: {integrity: sha512-EddYllaovi5ysMLMEN7yzHEKh8A850cZ7pykrY1aNRQGn/CDjRDE9qEWbIdt7xGEVJmjBXzU/fNnC4ABTm8tEQ==} - - isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - isstream@0.1.2: - resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - - js-base64@2.6.4: - resolution: {integrity: sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==} - - jstoxml@2.2.9: - resolution: {integrity: sha512-OYWlK0j+roh+eyaMROlNbS5cd5R25Y+IUpdl7cNdB8HNrkgwQzIS7L9MegxOiWNBj9dQhA/yAxiMwCC5mwNoBw==} - - lodash@4.18.1: - resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - - merge-descriptors@1.0.3: - resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - - mime@2.6.0: - resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==} - engines: {node: '>=4.0.0'} - hasBin: true - - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - node-addon-api@7.1.1: - resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} - - node-hex@1.0.1: - resolution: {integrity: sha512-iwpZdvW6Umz12ICmu9IYPRxg0tOLGmU3Tq2tKetejCj3oZd7b2nUXwP3a7QA5M9glWy8wlPS1G3RwM/CdsUbdQ==} - engines: {node: '>=8.0.0'} - - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - os-name@1.0.3: - resolution: {integrity: sha512-f5estLO2KN8vgtTRaILIgEGBoBrMnZ3JQ7W9TMZCnOIGwHe8TRGSpcagnWDo+Dfhd/z08k9Xe75hvciJJ8Qaew==} - engines: {node: '>=0.10.0'} - hasBin: true - - osx-release@1.1.0: - resolution: {integrity: sha512-ixCMMwnVxyHFQLQnINhmIpWqXIfS2YOXchwQrk+OFzmo6nDjQ0E4KXAyyUh0T0MZgV4bUhkRrAbVqlE4yLVq4A==} - engines: {node: '>=0.10.0'} - hasBin: true - - pause-stream@0.0.11: - resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} - - platform@1.3.6: - resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} - - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - - process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - proxy-from-env@2.1.0: - resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} - engines: {node: '>=10'} - - pump@3.0.4: - resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} - - qs@6.15.0: - resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} - engines: {node: '>=0.6'} - - readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - - readdirp@4.1.2: - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} - engines: {node: '>= 14.18.0'} - - rollup@4.60.1: - resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - sass@1.98.0: - resolution: {integrity: sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A==} - engines: {node: '>=14.0.0'} - hasBin: true - - sax@1.6.0: - resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} - engines: {node: '>=11.0.0'} - - sdk-base@2.0.1: - resolution: {integrity: sha512-eeG26wRwhtwYuKGCDM3LixCaxY27Pa/5lK4rLKhQa7HBjJ3U3Y+f81MMZQRsDw/8SC2Dao/83yJTXJ8aULuN8Q==} - - semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - statuses@1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - - stream-http@2.8.2: - resolution: {integrity: sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==} - - stream-wormhole@1.1.0: - resolution: {integrity: sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==} - engines: {node: '>=4.0.0'} - - string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - - thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - - thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - to-arraybuffer@1.0.1: - resolution: {integrity: sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==} - - unescape@1.0.1: - resolution: {integrity: sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==} - engines: {node: '>=0.10.0'} - - urllib@2.44.0: - resolution: {integrity: sha512-zRCJqdfYllRDA9bXUtx+vccyRqtJPKsw85f44zH7zPD28PIvjMqIgw9VwoTLV7xTBWZsbebUFVHU5ghQcWku2A==} - engines: {node: '>= 0.10.0'} - peerDependencies: - proxy-agent: ^5.0.0 - peerDependenciesMeta: - proxy-agent: - optional: true - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - utility@1.18.0: - resolution: {integrity: sha512-PYxZDA+6QtvRvm//++aGdmKG/cI07jNwbROz0Ql+VzFV1+Z0Dy55NI4zZ7RHc9KKpBePNFwoErqIuqQv/cjiTA==} - engines: {node: '>= 0.12.0'} - - vite@6.4.1: - resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - jiti: '>=1.21.0' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vue-router@4.6.4: - resolution: {integrity: sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==} - peerDependencies: - vue: ^3.5.0 - - vue@3.5.31: - resolution: {integrity: sha512-iV/sU9SzOlmA/0tygSmjkEN6Jbs3nPoIPFhCMLD2STrjgOU8DX7ZtzMhg4ahVwf5Rp9KoFzcXeB1ZrVbLBp5/Q==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - win-release@1.1.1: - resolution: {integrity: sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==} - engines: {node: '>=0.10.0'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - xml2js@0.6.2: - resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} - engines: {node: '>=4.0.0'} - - xmlbuilder@11.0.1: - resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} - engines: {node: '>=4.0'} - - xtend@4.0.2: - resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} - engines: {node: '>=0.4'} - -snapshots: - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/parser@7.29.2': - dependencies: - '@babel/types': 7.29.0 - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@esbuild/aix-ppc64@0.25.12': - optional: true - - '@esbuild/android-arm64@0.25.12': - optional: true - - '@esbuild/android-arm@0.25.12': - optional: true - - '@esbuild/android-x64@0.25.12': - optional: true - - '@esbuild/darwin-arm64@0.25.12': - optional: true - - '@esbuild/darwin-x64@0.25.12': - optional: true - - '@esbuild/freebsd-arm64@0.25.12': - optional: true - - '@esbuild/freebsd-x64@0.25.12': - optional: true - - '@esbuild/linux-arm64@0.25.12': - optional: true - - '@esbuild/linux-arm@0.25.12': - optional: true - - '@esbuild/linux-ia32@0.25.12': - optional: true - - '@esbuild/linux-loong64@0.25.12': - optional: true - - '@esbuild/linux-mips64el@0.25.12': - optional: true - - '@esbuild/linux-ppc64@0.25.12': - optional: true - - '@esbuild/linux-riscv64@0.25.12': - optional: true - - '@esbuild/linux-s390x@0.25.12': - optional: true - - '@esbuild/linux-x64@0.25.12': - optional: true - - '@esbuild/netbsd-arm64@0.25.12': - optional: true - - '@esbuild/netbsd-x64@0.25.12': - optional: true - - '@esbuild/openbsd-arm64@0.25.12': - optional: true - - '@esbuild/openbsd-x64@0.25.12': - optional: true - - '@esbuild/openharmony-arm64@0.25.12': - optional: true - - '@esbuild/sunos-x64@0.25.12': - optional: true - - '@esbuild/win32-arm64@0.25.12': - optional: true - - '@esbuild/win32-ia32@0.25.12': - optional: true - - '@esbuild/win32-x64@0.25.12': - optional: true - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@parcel/watcher-android-arm64@2.5.6': - optional: true - - '@parcel/watcher-darwin-arm64@2.5.6': - optional: true - - '@parcel/watcher-darwin-x64@2.5.6': - optional: true - - '@parcel/watcher-freebsd-x64@2.5.6': - optional: true - - '@parcel/watcher-linux-arm-glibc@2.5.6': - optional: true - - '@parcel/watcher-linux-arm-musl@2.5.6': - optional: true - - '@parcel/watcher-linux-arm64-glibc@2.5.6': - optional: true - - '@parcel/watcher-linux-arm64-musl@2.5.6': - optional: true - - '@parcel/watcher-linux-x64-glibc@2.5.6': - optional: true - - '@parcel/watcher-linux-x64-musl@2.5.6': - optional: true - - '@parcel/watcher-win32-arm64@2.5.6': - optional: true - - '@parcel/watcher-win32-ia32@2.5.6': - optional: true - - '@parcel/watcher-win32-x64@2.5.6': - optional: true - - '@parcel/watcher@2.5.6': - dependencies: - detect-libc: 2.1.2 - is-glob: 4.0.3 - node-addon-api: 7.1.1 - picomatch: 4.0.4 - optionalDependencies: - '@parcel/watcher-android-arm64': 2.5.6 - '@parcel/watcher-darwin-arm64': 2.5.6 - '@parcel/watcher-darwin-x64': 2.5.6 - '@parcel/watcher-freebsd-x64': 2.5.6 - '@parcel/watcher-linux-arm-glibc': 2.5.6 - '@parcel/watcher-linux-arm-musl': 2.5.6 - '@parcel/watcher-linux-arm64-glibc': 2.5.6 - '@parcel/watcher-linux-arm64-musl': 2.5.6 - '@parcel/watcher-linux-x64-glibc': 2.5.6 - '@parcel/watcher-linux-x64-musl': 2.5.6 - '@parcel/watcher-win32-arm64': 2.5.6 - '@parcel/watcher-win32-ia32': 2.5.6 - '@parcel/watcher-win32-x64': 2.5.6 - optional: true - - '@rollup/rollup-android-arm-eabi@4.60.1': - optional: true - - '@rollup/rollup-android-arm64@4.60.1': - optional: true - - '@rollup/rollup-darwin-arm64@4.60.1': - optional: true - - '@rollup/rollup-darwin-x64@4.60.1': - optional: true - - '@rollup/rollup-freebsd-arm64@4.60.1': - optional: true - - '@rollup/rollup-freebsd-x64@4.60.1': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.60.1': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.60.1': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.60.1': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.60.1': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.60.1': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.60.1': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.60.1': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.60.1': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.60.1': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.60.1': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.60.1': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.60.1': - optional: true - - '@rollup/rollup-linux-x64-musl@4.60.1': - optional: true - - '@rollup/rollup-openbsd-x64@4.60.1': - optional: true - - '@rollup/rollup-openharmony-arm64@4.60.1': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.60.1': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.60.1': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.60.1': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.60.1': - optional: true - - '@stomp/stompjs@7.3.0': {} - - '@types/estree@1.0.8': {} - - '@vitejs/plugin-basic-ssl@2.3.0(vite@6.4.1(sass@1.98.0))': - dependencies: - vite: 6.4.1(sass@1.98.0) - - '@vitejs/plugin-vue@5.2.4(vite@6.4.1(sass@1.98.0))(vue@3.5.31)': - dependencies: - vite: 6.4.1(sass@1.98.0) - vue: 3.5.31 - - '@vue/compiler-core@3.5.31': - dependencies: - '@babel/parser': 7.29.2 - '@vue/shared': 3.5.31 - entities: 7.0.1 - estree-walker: 2.0.2 - source-map-js: 1.2.1 - - '@vue/compiler-dom@3.5.31': - dependencies: - '@vue/compiler-core': 3.5.31 - '@vue/shared': 3.5.31 - - '@vue/compiler-sfc@3.5.31': - dependencies: - '@babel/parser': 7.29.2 - '@vue/compiler-core': 3.5.31 - '@vue/compiler-dom': 3.5.31 - '@vue/compiler-ssr': 3.5.31 - '@vue/shared': 3.5.31 - estree-walker: 2.0.2 - magic-string: 0.30.21 - postcss: 8.5.8 - source-map-js: 1.2.1 - - '@vue/compiler-ssr@3.5.31': - dependencies: - '@vue/compiler-dom': 3.5.31 - '@vue/shared': 3.5.31 - - '@vue/devtools-api@6.6.4': {} - - '@vue/reactivity@3.5.31': - dependencies: - '@vue/shared': 3.5.31 - - '@vue/runtime-core@3.5.31': - dependencies: - '@vue/reactivity': 3.5.31 - '@vue/shared': 3.5.31 - - '@vue/runtime-dom@3.5.31': - dependencies: - '@vue/reactivity': 3.5.31 - '@vue/runtime-core': 3.5.31 - '@vue/shared': 3.5.31 - csstype: 3.2.3 - - '@vue/server-renderer@3.5.31(vue@3.5.31)': - dependencies: - '@vue/compiler-ssr': 3.5.31 - '@vue/shared': 3.5.31 - vue: 3.5.31 - - '@vue/shared@3.5.31': {} - - address@1.2.2: {} - - agentkeepalive@3.5.3: - dependencies: - humanize-ms: 1.2.1 - - ali-oss@6.23.0: - dependencies: - address: 1.2.2 - agentkeepalive: 3.5.3 - bowser: 1.9.4 - copy-to: 2.0.1 - dateformat: 2.2.0 - debug: 4.4.3 - destroy: 1.2.0 - end-or-error: 1.0.1 - get-ready: 1.0.0 - humanize-ms: 1.2.1 - is-type-of: 1.4.0 - js-base64: 2.6.4 - jstoxml: 2.2.9 - lodash: 4.18.1 - merge-descriptors: 1.0.3 - mime: 2.6.0 - platform: 1.3.6 - pump: 3.0.4 - qs: 6.15.0 - sdk-base: 2.0.1 - stream-http: 2.8.2 - stream-wormhole: 1.1.0 - urllib: 2.44.0 - utility: 1.18.0 - xml2js: 0.6.2 - transitivePeerDependencies: - - proxy-agent - - supports-color - - any-promise@1.3.0: {} - - asynckit@0.4.0: {} - - axios@1.14.0: - dependencies: - follow-redirects: 1.15.11 - form-data: 4.0.5 - proxy-from-env: 2.1.0 - transitivePeerDependencies: - - debug - - bowser@1.9.4: {} - - builtin-status-codes@3.0.0: {} - - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - - chokidar@4.0.3: - dependencies: - readdirp: 4.1.2 - - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - - content-type@1.0.5: {} - - copy-to@2.0.1: {} - - core-util-is@1.0.3: {} - - crypto-js@4.2.0: {} - - csstype@3.2.3: {} - - dateformat@2.2.0: {} - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - default-user-agent@1.0.0: - dependencies: - os-name: 1.0.3 - - delayed-stream@1.0.0: {} - - destroy@1.2.0: {} - - detect-libc@2.1.2: - optional: true - - digest-header@1.1.0: {} - - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - - ee-first@1.1.1: {} - - end-of-stream@1.4.5: - dependencies: - once: 1.4.0 - - end-or-error@1.0.1: {} - - entities@7.0.1: {} - - es-define-property@1.0.1: {} - - es-errors@1.3.0: {} - - es-object-atoms@1.1.1: - dependencies: - es-errors: 1.3.0 - - es-set-tostringtag@2.1.0: - dependencies: - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - esbuild@0.25.12: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - - escape-html@1.0.3: {} - - estree-walker@2.0.2: {} - - extend-shallow@2.0.1: - dependencies: - is-extendable: 0.1.1 - - fdir@6.5.0(picomatch@4.0.4): - optionalDependencies: - picomatch: 4.0.4 - - follow-redirects@1.15.11: {} - - form-data@4.0.5: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - es-set-tostringtag: 2.1.0 - hasown: 2.0.2 - mime-types: 2.1.35 - - formstream@1.5.2: - dependencies: - destroy: 1.2.0 - mime: 2.6.0 - node-hex: 1.0.1 - pause-stream: 0.0.11 - - fsevents@2.3.3: - optional: true - - function-bind@1.1.2: {} - - get-intrinsic@1.3.0: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-define-property: 1.0.1 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - get-ready@1.0.0: {} - - gopd@1.2.0: {} - - has-symbols@1.1.0: {} - - has-tostringtag@1.0.2: - dependencies: - has-symbols: 1.1.0 - - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - - humanize-ms@1.2.1: - dependencies: - ms: 2.1.3 - - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - - immutable@5.1.5: {} - - inherits@2.0.4: {} - - is-class-hotfix@0.0.6: {} - - is-extendable@0.1.1: {} - - is-extglob@2.1.1: - optional: true - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - optional: true - - is-type-of@1.4.0: - dependencies: - core-util-is: 1.0.3 - is-class-hotfix: 0.0.6 - isstream: 0.1.2 - - isarray@1.0.0: {} - - isstream@0.1.2: {} - - js-base64@2.6.4: {} - - jstoxml@2.2.9: {} - - lodash@4.18.1: {} - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - math-intrinsics@1.1.0: {} - - merge-descriptors@1.0.3: {} - - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - - mime@2.6.0: {} - - minimist@1.2.8: {} - - mkdirp@0.5.6: - dependencies: - minimist: 1.2.8 - - ms@2.1.3: {} - - mz@2.7.0: - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - - nanoid@3.3.11: {} - - node-addon-api@7.1.1: - optional: true - - node-hex@1.0.1: {} - - object-assign@4.1.1: {} - - object-inspect@1.13.4: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - os-name@1.0.3: - dependencies: - osx-release: 1.1.0 - win-release: 1.1.1 - - osx-release@1.1.0: - dependencies: - minimist: 1.2.8 - - pause-stream@0.0.11: - dependencies: - through: 2.3.8 - - picocolors@1.1.1: {} - - picomatch@4.0.4: {} - - platform@1.3.6: {} - - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - process-nextick-args@2.0.1: {} - - proxy-from-env@2.1.0: {} - - pump@3.0.4: - dependencies: - end-of-stream: 1.4.5 - once: 1.4.0 - - qs@6.15.0: - dependencies: - side-channel: 1.1.0 - - readable-stream@2.3.8: - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - readdirp@4.1.2: {} - - rollup@4.60.1: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.60.1 - '@rollup/rollup-android-arm64': 4.60.1 - '@rollup/rollup-darwin-arm64': 4.60.1 - '@rollup/rollup-darwin-x64': 4.60.1 - '@rollup/rollup-freebsd-arm64': 4.60.1 - '@rollup/rollup-freebsd-x64': 4.60.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.60.1 - '@rollup/rollup-linux-arm-musleabihf': 4.60.1 - '@rollup/rollup-linux-arm64-gnu': 4.60.1 - '@rollup/rollup-linux-arm64-musl': 4.60.1 - '@rollup/rollup-linux-loong64-gnu': 4.60.1 - '@rollup/rollup-linux-loong64-musl': 4.60.1 - '@rollup/rollup-linux-ppc64-gnu': 4.60.1 - '@rollup/rollup-linux-ppc64-musl': 4.60.1 - '@rollup/rollup-linux-riscv64-gnu': 4.60.1 - '@rollup/rollup-linux-riscv64-musl': 4.60.1 - '@rollup/rollup-linux-s390x-gnu': 4.60.1 - '@rollup/rollup-linux-x64-gnu': 4.60.1 - '@rollup/rollup-linux-x64-musl': 4.60.1 - '@rollup/rollup-openbsd-x64': 4.60.1 - '@rollup/rollup-openharmony-arm64': 4.60.1 - '@rollup/rollup-win32-arm64-msvc': 4.60.1 - '@rollup/rollup-win32-ia32-msvc': 4.60.1 - '@rollup/rollup-win32-x64-gnu': 4.60.1 - '@rollup/rollup-win32-x64-msvc': 4.60.1 - fsevents: 2.3.3 - - safe-buffer@5.1.2: {} - - safer-buffer@2.1.2: {} - - sass@1.98.0: - dependencies: - chokidar: 4.0.3 - immutable: 5.1.5 - source-map-js: 1.2.1 - optionalDependencies: - '@parcel/watcher': 2.5.6 - - sax@1.6.0: {} - - sdk-base@2.0.1: - dependencies: - get-ready: 1.0.0 - - semver@5.7.2: {} - - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - - source-map-js@1.2.1: {} - - statuses@1.5.0: {} - - stream-http@2.8.2: - dependencies: - builtin-status-codes: 3.0.0 - inherits: 2.0.4 - readable-stream: 2.3.8 - to-arraybuffer: 1.0.1 - xtend: 4.0.2 - - stream-wormhole@1.1.0: {} - - string_decoder@1.1.1: - dependencies: - safe-buffer: 5.1.2 - - thenify-all@1.6.0: - dependencies: - thenify: 3.3.1 - - thenify@3.3.1: - dependencies: - any-promise: 1.3.0 - - through@2.3.8: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - - to-arraybuffer@1.0.1: {} - - unescape@1.0.1: - dependencies: - extend-shallow: 2.0.1 - - urllib@2.44.0: - dependencies: - any-promise: 1.3.0 - content-type: 1.0.5 - default-user-agent: 1.0.0 - digest-header: 1.1.0 - ee-first: 1.1.1 - formstream: 1.5.2 - humanize-ms: 1.2.1 - iconv-lite: 0.6.3 - pump: 3.0.4 - qs: 6.15.0 - statuses: 1.5.0 - utility: 1.18.0 - - util-deprecate@1.0.2: {} - - utility@1.18.0: - dependencies: - copy-to: 2.0.1 - escape-html: 1.0.3 - mkdirp: 0.5.6 - mz: 2.7.0 - unescape: 1.0.1 - - vite@6.4.1(sass@1.98.0): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - postcss: 8.5.8 - rollup: 4.60.1 - tinyglobby: 0.2.15 - optionalDependencies: - fsevents: 2.3.3 - sass: 1.98.0 - - vue-router@4.6.4(vue@3.5.31): - dependencies: - '@vue/devtools-api': 6.6.4 - vue: 3.5.31 - - vue@3.5.31: - dependencies: - '@vue/compiler-dom': 3.5.31 - '@vue/compiler-sfc': 3.5.31 - '@vue/runtime-dom': 3.5.31 - '@vue/server-renderer': 3.5.31(vue@3.5.31) - '@vue/shared': 3.5.31 - - win-release@1.1.1: - dependencies: - semver: 5.7.2 - - wrappy@1.0.2: {} - - xml2js@0.6.2: - dependencies: - sax: 1.6.0 - xmlbuilder: 11.0.1 - - xmlbuilder@11.0.1: {} - - xtend@4.0.2: {} diff --git a/lesingle-aicreate-client/public/config.js b/lesingle-aicreate-client/public/config.js deleted file mode 100644 index 3fe7b2e..0000000 --- a/lesingle-aicreate-client/public/config.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * 乐读派 AI 创作系统 — 运行时配置 - * 企业上线只需修改此文件,无需重新编译。 - */ -window.__LEAI_CONFIG__ = { - // ━━━ 认证模式(决定使用哪组服务地址)━━━━━━━━━ - // "hmac" = 开发调试(HMAC签名 + 局域网地址) ← 默认 - // "token" = 生产环境(Bearer Token + 正式地址) - authMode: "token", - - // ━━━ 开发环境配置(authMode=hmac 时生效)━━━━━ - dev: { - apiBaseUrl: "http://192.168.1.120:8080", - wsBaseUrl: "ws://192.168.1.120:8080", - orgId: "LESINGLE888888888", - appSecret: "", // 开发时填入,生产环境不需要(token模式不使用) - phone: "18911223344" - }, - - // ━━━ 生产环境配置(authMode=token 时生效)━━━━ - // orgId/phone 由企业重定向URL参数动态传入,无需在此配置 - // appSecret 仅在企业服务端使用,绝不到达浏览器 - prod: { - apiBaseUrl: "http://192.168.1.120:8080", - wsBaseUrl: "ws://192.168.1.120:8080" - }, - - // ━━━ 品牌定制(两种模式通用)━━━━━━━━━━━━━━━━━ - brand: { - title: "乐读派", - subtitle: "AI智能儿童绘本创作", - slogan: "让想象力飞翔", - favicon: "/favicon.ico" - }, - - // ━━━ 嵌入模式(iframe集成时启用)━━━━━━━━━━━━━ - // "standalone" = 独立页面模式(默认,redirect认证) - // "iframe" = iframe嵌入模式(postMessage通信) - embedMode: "iframe", - - // iframe模式下允许的父页面域名(安全校验用) - // 例: ["https://enterprise.com", "https://admin.enterprise.com"] - parentOrigins: [] -} diff --git a/lesingle-aicreate-client/src/App.vue b/lesingle-aicreate-client/src/App.vue deleted file mode 100644 index f340d19..0000000 --- a/lesingle-aicreate-client/src/App.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/lesingle-aicreate-client/src/api/index.js b/lesingle-aicreate-client/src/api/index.js deleted file mode 100644 index 1a74a56..0000000 --- a/lesingle-aicreate-client/src/api/index.js +++ /dev/null @@ -1,305 +0,0 @@ -import axios from 'axios' -import OSS from 'ali-oss' -import { signRequest } from '@/utils/hmac' -import { store } from '@/utils/store' -import config from '@/utils/config' -import bridge from '@/utils/bridge' - -const api = axios.create({ - baseURL: config.apiBaseUrl ? config.apiBaseUrl + '/api/v1' : '/api/v1', - timeout: 120000 -}) - -// 双模式认证拦截器: -// 1. 有 sessionToken → Bearer Token(企业生产环境,通过 auth/session 换取) -// 2. 有 appSecret → HMAC 签名(开发调试 / 直连后端模式) -api.interceptors.request.use(config => { - if (store.sessionToken) { - config.headers['Authorization'] = 'Bearer ' + store.sessionToken - } else if (store.orgId && store.appSecret) { - const queryParams = {} - if (config.params) { - Object.entries(config.params).forEach(([k, v]) => { - if (v != null) queryParams[k] = String(v) - }) - } - const headers = signRequest(store.orgId, store.appSecret, queryParams) - Object.assign(config.headers, headers) - } - return config -}) - -// ─── Token 刷新状态管理(双模式)─── -let isRefreshing = false -let pendingRequests = [] - -function handleTokenExpired_standalone() { - if (isRefreshing) return - isRefreshing = true - store.saveRecoveryState() - store.clearSession() - const redirectUrl = store.authRedirectUrl - if (redirectUrl) { - const returnPath = encodeURIComponent(window.location.pathname || '/') - window.location.href = redirectUrl + (redirectUrl.includes('?') ? '&' : '?') - + 'returnPath=' + returnPath + '&orgId=' + encodeURIComponent(store.orgId) - } else { - window.location.href = import.meta.env.BASE_URL || '/' // 与 Vite base(/ai-web/)一致 - } - setTimeout(() => { isRefreshing = false }, 3000) -} - -function handleTokenExpired_iframe(failedConfig) { - if (!isRefreshing) { - isRefreshing = true - bridge.requestTokenRefresh() - .then(({ token, orgId, phone }) => { - store.setSession(orgId || store.orgId, token) - if (phone) store.setPhone(phone) - isRefreshing = false - pendingRequests.forEach(cb => cb(token)) - pendingRequests = [] - }) - .catch(() => { - isRefreshing = false - pendingRequests.forEach(cb => cb(null)) - pendingRequests = [] - }) - } - return new Promise((resolve, reject) => { - // 队列上限防止内存泄漏 - if (pendingRequests.length >= 20) { - reject(new Error('TOO_MANY_PENDING_REQUESTS')) - return - } - pendingRequests.push(newToken => { - if (newToken) { - // 防止无限重试:标记已重试,最多重试1次 - if (failedConfig.__retried) { - reject(new Error('TOKEN_REFRESH_FAILED')) - return - } - failedConfig.__retried = true - failedConfig.headers['Authorization'] = 'Bearer ' + newToken - // 清除可能残留的HMAC头 - delete failedConfig.headers['X-App-Key'] - delete failedConfig.headers['X-Timestamp'] - delete failedConfig.headers['X-Nonce'] - delete failedConfig.headers['X-Signature'] - resolve(api(failedConfig)) - } else { - reject(new Error('TOKEN_REFRESH_FAILED')) - } - }) - }) -} - -api.interceptors.response.use( - res => { - const d = res.data - if (d?.code !== 0 && d?.code !== 200) { - if (config.isTokenMode && (d?.code === 20010 || d?.code === 20009)) { - if (bridge.isEmbedded) { - return handleTokenExpired_iframe(res.config) - } - handleTokenExpired_standalone() - return Promise.reject(new Error('TOKEN_EXPIRED')) - } - return Promise.reject(new Error(d?.msg || '请求失败')) - } - return d - }, - err => { - if (config.isTokenMode && err.response?.status === 401) { - if (bridge.isEmbedded) { - return handleTokenExpired_iframe(err.config) - } - handleTokenExpired_standalone() - return Promise.reject(new Error('TOKEN_EXPIRED')) - } - return Promise.reject(err) - } -) - -// ─── 图片上传 ─── -export function uploadImage(file) { - const form = new FormData() - form.append('file', file) - return api.post('/creation/upload', form, { - headers: { 'Content-Type': 'multipart/form-data' }, - timeout: 30000 - }) -} - -// ─── A6 角色提取(JSON方式,传 imageUrl) ─── -export function extractCharacters(imageUrl, { saveOriginal, title } = {}) { - const body = { - orgId: store.orgId, - phone: store.phone, - imageUrl - } - if (saveOriginal) body.saveOriginal = true - if (title) body.title = title - return api.post('/creation/extract-original', body, { timeout: 120000 }) -} - -// ─── 批量更新配音URL(录音直传OSS后调用) ─── -export function batchUpdateAudio(workId, pages) { - return api.post('/update/batch-audio', { - orgId: store.orgId, - phone: store.phone, - workId, - pages - }) -} - -// ─── A3 图片故事创作 ─── -export function createStory({ imageUrl, storyHint, style, title, author, heroCharId, extractId, refAdaptMode = 'enhanced' }) { - const body = { - orgId: store.orgId, - phone: store.phone, - imageUrl, - storyHint, - style, - title, - refAdaptMode, - enableVoice: false - } - if (author) body.author = author - if (heroCharId) body.heroCharId = heroCharId - if (extractId) body.extractId = extractId - return api.post('/creation/image-story', body) -} - -// ─── B2 查询作品详情 ─── -export function getWorkDetail(workId) { - return api.get(`/query/work/${workId}`, { - params: { orgId: store.orgId, phone: store.phone } - }) -} - -// ─── B1 额度校验 ─── -export function checkQuota() { - return api.post('/query/validate', { - orgId: store.orgId, - phone: store.phone, - apiType: 'A3' - }) -} - -// ─── C1 编辑绘本信息(推进状态 COMPLETED→CATALOGED) ─── -export function updateWork(workId, data) { - return api.put(`/update/work/${workId}`, data) -} - -// ─── C2 完成配音(推进状态 CATALOGED→DUBBED,允许空 pages) ─── -export function finishDubbing(workId) { - return api.post('/update/batch-audio', { - orgId: store.orgId, - phone: store.phone, - workId, - pages: [] - }) -} - -// ─── A20 AI配音 ─── -export function voicePage(data) { - return api.post('/creation/voice', { - orgId: store.orgId, - phone: store.phone, - ...data - }, { timeout: 120000 }) -} - -// ─── STS 临时凭证 ─── -export function getStsToken() { - return api.post('/oss/sts-token', { - orgId: store.orgId, - phone: store.phone - }) -} - -// ─── OSS 直传(STS 模式) ─── -let _ossClient = null -let _stsData = null - -async function getOssClient() { - // 复用未过期的 client - if (_ossClient && _stsData) { - const expireTime = new Date(_stsData.expiration).getTime() - if (Date.now() < expireTime - 5 * 60 * 1000) { - return { client: _ossClient, prefix: _stsData.uploadPrefix } - } - } - const res = await getStsToken() - _stsData = res.data - _ossClient = new OSS({ - region: _stsData.region, - accessKeyId: _stsData.accessKeyId, - accessKeySecret: _stsData.accessKeySecret, - stsToken: _stsData.securityToken, - bucket: _stsData.bucket, - endpoint: _stsData.endpoint, - refreshSTSToken: async () => { - const r = await getStsToken() - _stsData = r.data - return { - accessKeyId: _stsData.accessKeyId, - accessKeySecret: _stsData.accessKeySecret, - stsToken: _stsData.securityToken - } - }, - refreshSTSTokenInterval: 300000 - }) - return { client: _ossClient, prefix: _stsData.uploadPrefix } -} - -/** - * STS 直传文件到 OSS - * @param {File|Blob} file - 要上传的文件 - * @param {Object} [opts] - 选项 - * @param {string} [opts.type='img'] - 文件类型前缀: img=图片, aud=音频 - * @param {Function} [opts.onProgress] - 进度回调 (0-100) - * @param {string} [opts.ext] - 强制指定扩展名(Blob 无 name 时使用) - * @returns {Promise} 文件的完整 OSS URL - */ -export async function ossUpload(file, opts = {}) { - const { type = 'img', onProgress, ext: forceExt } = opts - const { client, prefix } = await getOssClient() - const ext = forceExt || (file.name ? file.name.split('.').pop() : 'bin').toLowerCase() - const date = new Date().toISOString().slice(0, 10) - const rand = Math.random().toString(36).slice(2, 10) - const key = `${prefix}${date}/${type}_${Date.now()}_${rand}.${ext}` - await client.put(key, file, { - headers: { 'x-oss-object-acl': 'public-read' }, - progress: (p) => { if (onProgress) onProgress(Math.round(p * 100)) } - }) - // 返回完整 URL - if (_stsData.cdnDomain) { - return `${_stsData.cdnDomain}/${key}` - } - return `https://${_stsData.bucket}.${_stsData.endpoint.replace('https://', '')}/${key}` -} - -/** - * STS 列举用户目录下的文件 - * @returns {Promise} 文件列表 [{name, size, lastModified, url}] - */ -export async function ossListFiles() { - const { client, prefix } = await getOssClient() - const result = await client.list({ prefix, 'max-keys': 100 }) - return (result.objects || []).map(obj => ({ - name: obj.name.replace(prefix, ''), - size: obj.size, - lastModified: obj.lastModified, - url: obj.url - })) -} - -export async function getOrgConfig(orgId) { - const baseUrl = config.apiBaseUrl || '' - const res = await axios.get(baseUrl + '/api/v1/query/org-config', { params: { orgId } }) - return res.data -} - -export default api diff --git a/lesingle-aicreate-client/src/assets/global.scss b/lesingle-aicreate-client/src/assets/global.scss deleted file mode 100644 index b41d687..0000000 --- a/lesingle-aicreate-client/src/assets/global.scss +++ /dev/null @@ -1,139 +0,0 @@ -// 乐读派 C端 — 全局样式 -// 暖橙 + 奶油白 儿童绘本风格 - -:root { - --primary: #FF6B35; - --primary-light: #FFF0E8; - --secondary: #6C63FF; - --accent: #FFD166; - --success: #2EC4B6; - --bg: #FFFDF7; - --card: #FFFFFF; - --text: #2D2D3F; - --text-sub: #8E8EA0; - --border: #F0EDE8; - --radius: 20px; - --radius-sm: 14px; - --shadow: 0 8px 32px rgba(255, 107, 53, 0.12); - --shadow-soft: 0 4px 20px rgba(0, 0, 0, 0.06); - --gradient: linear-gradient(135deg, #FF6B35 0%, #FF8F65 50%, #FFB088 100%); - --gradient-purple: linear-gradient(135deg, #6C63FF 0%, #9B93FF 100%); - --font: 'PingFang SC', 'Noto Sans SC', 'Microsoft YaHei', -apple-system, sans-serif; -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; - -webkit-tap-highlight-color: transparent; -} - -body { - font-family: var(--font); - background: #F0ECE3; - color: var(--text); - -webkit-font-smoothing: antialiased; - overscroll-behavior: none; -} - -input, textarea, select, button { - font-family: var(--font); -} - -img { - display: block; - max-width: 100%; -} - -// 通用按钮 -.btn-primary { - display: block; - width: 100%; - padding: 16px 0; - border: none; - border-radius: 50px; - background: var(--gradient); - color: #fff; - font-size: 17px; - font-weight: 700; - letter-spacing: 1px; - cursor: pointer; - box-shadow: var(--shadow); - transition: all 0.3s ease; - - &:disabled { - opacity: 0.45; - cursor: not-allowed; - } - - &:active:not(:disabled) { - transform: scale(0.97); - } -} - -.btn-ghost { - @extend .btn-primary; - background: var(--primary-light); - color: var(--primary); - box-shadow: none; -} - -// 通用卡片 -.card { - background: var(--card); - border-radius: var(--radius); - box-shadow: var(--shadow-soft); -} - -// 安全区底部 -.safe-bottom { - padding-bottom: env(safe-area-inset-bottom, 20px); -} - -// ═══ 全屏自适应布局框架 ═══ -// 解决移动端页面内容超出屏幕、底部按钮被推出视口的问题 -// 用法: 页面根元素加 .page-fullscreen,底部按钮区域加 .page-bottom - -.page-fullscreen { - display: flex; - flex-direction: column; - height: 100dvh; // 移动端动态视口高度(排除地址栏) - height: 100vh; // 降级:不支持 dvh 的浏览器 - min-height: 0 !important; // 覆盖各页面的 min-height: 100vh - overflow: hidden; - - // 可滚动的内容区域(自动填充剩余空间) - > .page-content { - flex: 1; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - } - - // 固定在底部的按钮区域(不参与滚动) - > .page-bottom { - flex-shrink: 0; - padding: 12px 20px; - padding-bottom: max(12px, env(safe-area-inset-bottom)); - background: var(--bg, #FFFDF7); - } -} - -// 动画 -@keyframes fadeInUp { - from { opacity: 0; transform: translateY(20px); } - to { opacity: 1; transform: translateY(0); } -} - -@keyframes pulse { - 0%, 100% { transform: scale(1); } - 50% { transform: scale(1.05); } -} - -@keyframes bounce { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-8px); } -} - -@keyframes spin { - to { transform: rotate(360deg); } -} diff --git a/lesingle-aicreate-client/src/components/PageHeader.vue b/lesingle-aicreate-client/src/components/PageHeader.vue deleted file mode 100644 index 9c8bdd2..0000000 --- a/lesingle-aicreate-client/src/components/PageHeader.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - - - diff --git a/lesingle-aicreate-client/src/components/StepBar.vue b/lesingle-aicreate-client/src/components/StepBar.vue deleted file mode 100644 index d754f6e..0000000 --- a/lesingle-aicreate-client/src/components/StepBar.vue +++ /dev/null @@ -1,38 +0,0 @@ - - - - - diff --git a/lesingle-aicreate-client/src/main.js b/lesingle-aicreate-client/src/main.js deleted file mode 100644 index 7799932..0000000 --- a/lesingle-aicreate-client/src/main.js +++ /dev/null @@ -1,11 +0,0 @@ -import { createApp } from 'vue' -import App from './App.vue' -import router from './router' -import './assets/global.scss' - -import bridge from '@/utils/bridge' - -createApp(App).use(router).mount('#app') - -// 通知父页面 H5 已加载完毕(iframe 模式下生效) -bridge.send('READY') diff --git a/lesingle-aicreate-client/src/router/index.js b/lesingle-aicreate-client/src/router/index.js deleted file mode 100644 index 8cbeddf..0000000 --- a/lesingle-aicreate-client/src/router/index.js +++ /dev/null @@ -1,123 +0,0 @@ -import { createRouter, createWebHistory } from 'vue-router' -import { store } from '@/utils/store' - -// base 由 Vite 的 import.meta.env.BASE_URL(如 /ai-web/)注入,路由表内不要再写 /ai-web 前缀 -const router = createRouter({ - history: createWebHistory(import.meta.env.BASE_URL), - routes: [ - { - path: '/', - name: 'Welcome', - component: () => import('@/views/Welcome.vue') - }, - { - path: '/upload', - name: 'Upload', - component: () => import('@/views/Upload.vue') - }, - { - path: '/characters', - name: 'Characters', - component: () => import('@/views/Characters.vue') - }, - { - path: '/style', - name: 'Style', - component: () => import('@/views/StyleSelect.vue') - }, - { - path: '/story', - name: 'Story', - component: () => import('@/views/StoryInput.vue') - }, - { - path: '/creating', - name: 'Creating', - component: () => import('@/views/Creating.vue') - }, - { - path: '/preview/:workId?', - name: 'Preview', - component: () => import('@/views/Preview.vue') - }, - { - path: '/edit-info/:workId', - name: 'EditInfo', - component: () => import('@/views/EditInfo.vue') - }, - { - path: '/save-success/:workId', - name: 'SaveSuccess', - component: () => import('@/views/SaveSuccess.vue') - }, - { - path: '/dubbing/:workId', - name: 'Dubbing', - component: () => import('@/views/Dubbing.vue') - }, - { - path: '/read/:workId', - name: 'Read', - component: () => import('@/views/BookReader.vue'), - meta: { noAuth: true } - } - ] -}) - -// Auth guard: 全局 token 初始化 + 双模式认证检查 -router.beforeEach((to, from, next) => { - // 持久化 from 参数(所有页面通用,含 noAuth 页面) - const sp = new URLSearchParams(window.location.search) - const urlFrom = sp.get('from') - if (urlFrom) sessionStorage.setItem('le_from', urlFrom) - - if (to.meta.noAuth) { - next() - return - } - - // ─── 全局 token 初始化:从 URL query 读取 ─── - // 支持 iframe src 直接带 token 加载任意页面 - // 例: /edit-info/190xxx?token=xxx&orgId=xxx&phone=xxx&embed=1 - const searchParams = new URLSearchParams(window.location.search) - const urlToken = searchParams.get('token') - const urlOrgId = searchParams.get('orgId') - const urlPhone = searchParams.get('phone') - - if (urlToken && urlOrgId && !store.sessionToken) { - store.setSession(urlOrgId, urlToken) - if (urlPhone) store.setPhone(urlPhone) - window.history.replaceState({}, '', window.location.pathname + window.location.hash) - } - - // hash 路由参数兼容(hash模式下参数在 #/?token=xxx 中) - if (!store.sessionToken && !store.appSecret) { - const hashQuery = window.location.hash.split('?')[1] || '' - if (hashQuery) { - const hp = new URLSearchParams(hashQuery) - const hToken = hp.get('token') - const hOrgId = hp.get('orgId') - const hPhone = hp.get('phone') - if (hToken && hOrgId) { - store.setSession(hOrgId, hToken) - if (hPhone) store.setPhone(hPhone) - window.history.replaceState({}, '', window.location.pathname + '#' + to.path) - } - } - } - - // ─── 认证检查 ─── - if (to.name === 'Welcome') { - next() - return - } - - // 有 sessionToken 或 appSecret 任一即可通过 - if (store.sessionToken || store.appSecret) { - next() - } else { - next({ name: 'Welcome' }) - } -}) - -export default router diff --git a/lesingle-aicreate-client/src/utils/bridge.js b/lesingle-aicreate-client/src/utils/bridge.js deleted file mode 100644 index e75094f..0000000 --- a/lesingle-aicreate-client/src/utils/bridge.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * iframe postMessage 通信�? - * 封装 H5 与企业父页面的双向通信 - */ -import config from './config' -// const VITE_CREATE_POST_MESSAGE_URL = import.meta.env.VITE_CREATE_POST_MESSAGE_URL; -const VITE_CREATE_POST_MESSAGE_URL = location.origin; -const SOURCE = 'leai-creation' -const VERSION = 1 -const TIMEOUT = 30000 - -const pendingCallbacks = new Map() - -export const isEmbedded = config.isEmbedded - -// 目标 origin:配置了白名单用第一个,未配置用 '*' -const targetOrigin = config.parentOrigins.length > 0 ? config.parentOrigins[0] : '*' - -export function send(type, payload = {}) { - if (!isEmbedded) return - window.parent.postMessage({ source: SOURCE, version: VERSION, type, payload }, VITE_CREATE_POST_MESSAGE_URL) -} -export function request(type, payload = {}) { - if (!isEmbedded) return Promise.reject(new Error('Not in iframe')) - const messageId = 'msg_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8) - return new Promise((resolve, reject) => { - const timer = setTimeout(() => { - pendingCallbacks.delete(messageId) - reject(new Error('TIMEOUT')) - }, TIMEOUT) - pendingCallbacks.set(messageId, { resolve, reject, timer }) - send(type, { ...payload, messageId }) - }) -} - -export function requestTokenRefresh() { - return request('TOKEN_EXPIRED') -} - -function onMessage(event) { - if (event.origin !== VITE_CREATE_POST_MESSAGE_URL) { - console.log('event.origin', event.origin); - return - } - console.log('onMessage', event); - if (config.parentOrigins.length > 0 && !config.parentOrigins.includes(event.origin)) { - return - } - const msg = event.data - if (!msg || msg.source !== SOURCE) return - - switch (msg.type) { - case 'TOKEN_REFRESHED': { - const messageId = msg.payload?.messageId - const cb = pendingCallbacks.get(messageId) - if (cb) { - clearTimeout(cb.timer) - pendingCallbacks.delete(messageId) - cb.resolve(msg.payload) - } - break - } - case 'INIT': { - if (msg.payload?.token && window.__LEAI_INIT_CALLBACK__) { - window.__LEAI_INIT_CALLBACK__(msg.payload) - } - break - } - } -} - -if (isEmbedded) { - window.addEventListener('message', onMessage) -} - -export default { isEmbedded, send, request, requestTokenRefresh } diff --git a/lesingle-aicreate-client/src/utils/config.js b/lesingle-aicreate-client/src/utils/config.js deleted file mode 100644 index de42f67..0000000 --- a/lesingle-aicreate-client/src/utils/config.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * 运行时配置读取工具 - * 从 window.__LEAI_CONFIG__(public/config.js)读取配置 - */ -const raw = window.__LEAI_CONFIG__ || {} -const authMode = raw.authMode || 'hmac' -const isTokenMode = authMode === 'token' -const env = isTokenMode ? (raw.prod || {}) : (raw.dev || {}) - -const config = { - authMode, - isTokenMode, - apiBaseUrl: env.apiBaseUrl || '', - wsBaseUrl: env.wsBaseUrl || '', - brand: raw.brand || { title: '乐读派', subtitle: 'AI智能儿童绘本创作', slogan: '让想象力飞翔' }, - dev: isTokenMode ? null : (raw.dev || {}), - embedMode: raw.embedMode || 'standalone', - parentOrigins: raw.parentOrigins || [], - isEmbedded: (raw.embedMode === 'iframe') || (window.self !== window.top) -} - -export default config diff --git a/lesingle-aicreate-client/src/utils/hmac.js b/lesingle-aicreate-client/src/utils/hmac.js deleted file mode 100644 index 8ac6d5e..0000000 --- a/lesingle-aicreate-client/src/utils/hmac.js +++ /dev/null @@ -1,25 +0,0 @@ -import CryptoJS from 'crypto-js' - -/** - * HMAC-SHA256 签名工具 - * 签名规则:排序的 query params + nonce + timestamp,用 & 拼接 - * POST JSON body 不参与签名 - */ -export function signRequest(orgId, appSecret, queryParams = {}) { - const timestamp = String(Date.now()) - const nonce = Math.random().toString(36).substring(2, 15) + Date.now().toString(36) - - // Build sign string: sorted params + nonce + timestamp - const allParams = { ...queryParams, nonce, timestamp } - const sorted = Object.keys(allParams).sort() - const signStr = sorted.map(k => `${k}=${allParams[k]}`).join('&') - - const signature = CryptoJS.HmacSHA256(signStr, appSecret).toString(CryptoJS.enc.Hex) - - return { - 'X-App-Key': orgId, - 'X-Timestamp': timestamp, - 'X-Nonce': nonce, - 'X-Signature': signature - } -} diff --git a/lesingle-aicreate-client/src/utils/status.js b/lesingle-aicreate-client/src/utils/status.js deleted file mode 100644 index 9a6d84b..0000000 --- a/lesingle-aicreate-client/src/utils/status.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * V4.0 作品状态常量(数值型) - * - * 状态流转: PENDING(1) -> PROCESSING(2) -> COMPLETED(3) -> CATALOGED(4) -> DUBBED(5) - * 任意阶段可能 -> FAILED(-1) - * - * COMPLETED(3) = 图片生成完成,需要进入编目(EditInfo) - * CATALOGED(4) = 编目完成,需要进入配音(Dubbing) - * DUBBED(5) = 配音完成(最终状态),可阅读 - */ -export const STATUS = { - FAILED: -1, - PENDING: 1, - PROCESSING: 2, - COMPLETED: 3, // 图片完成,待编目 - CATALOGED: 4, // 编目完成,待配音 - DUBBED: 5 // 配音完成(最终态) -} - -/** - * 根据作品状态决定应导航到的路由 - * @param {number} status - 作品状态值 - * @param {string} workId - 作品ID - * @returns {{ name: string, params?: object } | null} 路由对象,null 表示状态异常 - */ -export function getRouteByStatus(status, workId) { - switch (status) { - case STATUS.PENDING: - case STATUS.PROCESSING: - return { name: 'Creating' } - case STATUS.COMPLETED: - return { name: 'Preview', params: { workId } } - case STATUS.CATALOGED: - return { name: 'Dubbing', params: { workId } } - case STATUS.DUBBED: - return { name: 'Read', params: { workId } } - case STATUS.FAILED: - return null // 调用方自行处理失败提示 - default: - return null - } -} diff --git a/lesingle-aicreate-client/src/utils/store.js b/lesingle-aicreate-client/src/utils/store.js deleted file mode 100644 index d0613fe..0000000 --- a/lesingle-aicreate-client/src/utils/store.js +++ /dev/null @@ -1,108 +0,0 @@ -import { reactive } from 'vue' - -/** - * 简单全局状态(不用 Pinia,C端足够轻量) - * - * ★ 企业集成关键: - * - phone: 当前登录用户手机号(企业从自己的登录系统获取) - * - orgId: 机构ID(乐读派分配给企业的唯一标识) - * - sessionToken: 会话令牌(企业后端调用 /api/v1/auth/session 换取,短期有效) - * - * 企业集成流程: - * 1. 企业后端调用 POST /api/v1/auth/session { orgId, appSecret, phone } 换取 sessionToken - * 2. 企业重定向用户到 H5: ?token=sess_xxx&phone=138xxx - * 3. H5 自动读取 token,所有 API 调用使用 Authorization: Bearer sess_xxx - * - * 安全说明: appSecret 只存在于企业服务端,不会到达浏览器 - */ -export const store = reactive({ - phone: localStorage.getItem('le_phone') || '', - orgId: localStorage.getItem('le_orgId') || '', - appSecret: localStorage.getItem('le_appSecret') || '', - sessionToken: sessionStorage.getItem('le_sessionToken') || '', // 企业生产模式用 - - // 创作流程数据 - imageUrl: '', - extractId: '', - characters: [], - selectedCharacter: null, - selectedStyle: '', - storyData: null, - workId: '', - workDetail: null, - - setPhone(phone) { - this.phone = phone - localStorage.setItem('le_phone', phone) - }, - - // 开发调试模式:直接设 orgId + appSecret(HMAC 签名) - setOrg(orgId, appSecret) { - this.orgId = orgId - this.appSecret = appSecret - localStorage.setItem('le_orgId', orgId) - localStorage.setItem('le_appSecret', appSecret) - }, - - // 企业生产模式:通过 auth/session 换取 sessionToken(Bearer Token) - setSession(orgId, sessionToken) { - this.orgId = orgId - this.sessionToken = sessionToken - localStorage.setItem('le_orgId', orgId) - sessionStorage.setItem('le_orgId', orgId) - sessionStorage.setItem('le_sessionToken', sessionToken) - }, - - reset() { - this.imageUrl = '' - this.extractId = '' - this.characters = [] - this.selectedCharacter = null - this.selectedStyle = '' - this.storyData = null - this.workId = '' - this.workDetail = null - localStorage.removeItem('le_workId') - }, - - // 企业认证回调URL - authRedirectUrl: '', - - clearSession() { - this.sessionToken = '' - sessionStorage.removeItem('le_sessionToken') - }, - - saveRecoveryState() { - const recovery = { - path: window.location.pathname || '/', - workId: this.workId || localStorage.getItem('le_workId') || '', - imageUrl: this.imageUrl || '', - extractId: this.extractId || '', - selectedStyle: this.selectedStyle || '', - savedAt: Date.now() - } - sessionStorage.setItem('le_recovery', JSON.stringify(recovery)) - }, - - restoreRecoveryState() { - const raw = sessionStorage.getItem('le_recovery') - if (!raw) return null - try { - const recovery = JSON.parse(raw) - if (Date.now() - recovery.savedAt > 30 * 60 * 1000) { - sessionStorage.removeItem('le_recovery') - return null - } - if (recovery.workId) this.workId = recovery.workId - if (recovery.imageUrl) this.imageUrl = recovery.imageUrl - if (recovery.extractId) this.extractId = recovery.extractId - if (recovery.selectedStyle) this.selectedStyle = recovery.selectedStyle - sessionStorage.removeItem('le_recovery') - return recovery - } catch { - sessionStorage.removeItem('le_recovery') - return null - } - } -}) diff --git a/lesingle-aicreate-client/src/views/BookReader.vue b/lesingle-aicreate-client/src/views/BookReader.vue deleted file mode 100644 index e774d65..0000000 --- a/lesingle-aicreate-client/src/views/BookReader.vue +++ /dev/null @@ -1,393 +0,0 @@ - - - - - diff --git a/lesingle-aicreate-client/src/views/Characters.vue b/lesingle-aicreate-client/src/views/Characters.vue deleted file mode 100644 index 7924a2e..0000000 --- a/lesingle-aicreate-client/src/views/Characters.vue +++ /dev/null @@ -1,373 +0,0 @@ - - - - - diff --git a/lesingle-aicreate-client/src/views/Creating.vue b/lesingle-aicreate-client/src/views/Creating.vue deleted file mode 100644 index c77dec1..0000000 --- a/lesingle-aicreate-client/src/views/Creating.vue +++ /dev/null @@ -1,486 +0,0 @@ - - - - - diff --git a/lesingle-aicreate-client/src/views/Dubbing.vue b/lesingle-aicreate-client/src/views/Dubbing.vue deleted file mode 100644 index 513dceb..0000000 --- a/lesingle-aicreate-client/src/views/Dubbing.vue +++ /dev/null @@ -1,956 +0,0 @@ - - - - - diff --git a/lesingle-aicreate-client/src/views/EditInfo.vue b/lesingle-aicreate-client/src/views/EditInfo.vue deleted file mode 100644 index 5f5b9b4..0000000 --- a/lesingle-aicreate-client/src/views/EditInfo.vue +++ /dev/null @@ -1,361 +0,0 @@ -