Files
campus-activity-system/server/docs/业务流程图.md
2026-01-19 23:15:20 +08:00

47 KiB
Raw Permalink Blame History

校园活动系统 - 业务流程图

系统架构概览

本系统采用典型的分层架构,包含以下层次:

  • 表现层Controller层处理HTTP请求和响应
  • 业务逻辑层Service层:实现核心业务逻辑
  • 数据访问层Mapper层:与数据库交互
  • 实体层Entity层:数据模型定义
  • 安全层Security层JWT认证和授权

1. 用户认证流程

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Controller as AuthController<br/>认证控制器
    participant Service as AuthServiceImpl<br/>认证服务
    participant Security as SecurityConfig<br/>安全配置
    participant JwtProvider as JwtTokenProvider<br/>JWT令牌提供者
    participant Mapper as UserMapper<br/>用户数据访问
    participant DB as MySQL数据库

    Note over Client,DB: 1. 用户注册流程
    Client->>Controller: POST /api/v1/auth/register<br/>RegisterRequest
    Controller->>Service: register(request)
    Service->>Mapper: 检查用户名是否存在<br/>selectCount(username)
    Mapper->>DB: SELECT COUNT(*) FROM user<br/>WHERE username = ?
    DB-->>Mapper: 返回数量
    Mapper-->>Service: 返回数量
    alt 用户名已存在
        Service-->>Controller: 抛出异常<br/>USER_ALREADY_EXISTS
        Controller-->>Client: 400 错误
    else 用户名不存在
        Service->>Mapper: 检查学号是否存在<br/>selectCount(studentId)
        Mapper->>DB: SELECT COUNT(*) FROM user<br/>WHERE student_id = ?
        DB-->>Mapper: 返回数量
        Mapper-->>Service: 返回数量
        alt 学号已存在
            Service-->>Controller: 抛出异常<br/>STUDENT_ID_ALREADY_EXISTS
            Controller-->>Client: 400 错误
        else 学号不存在
            Service->>Service: 创建用户对象<br/>passwordEncoder.encode()
            Service->>Mapper: insert(user)
            Mapper->>DB: INSERT INTO user(...)
            DB-->>Mapper: 返回插入ID
            Mapper-->>Service: 返回结果
            Service-->>Controller: 注册成功
            Controller-->>Client: 200 成功
        end
    end

    Note over Client,DB: 2. 用户登录流程
    Client->>Controller: POST /api/v1/auth/login<br/>LoginRequest
    Controller->>Security: authenticationManager.authenticate()
    Security->>Mapper: 加载用户信息<br/>loadUserByUsername()
    Mapper->>DB: SELECT * FROM user<br/>WHERE username = ?
    DB-->>Mapper: 返回用户信息
    Mapper-->>Security: 返回UserDetails
    Security->>Security: 验证密码<br/>passwordEncoder.matches()
    alt 密码错误
        Security-->>Controller: 抛出异常
        Controller-->>Client: 401 未授权
    else 密码正确
        Security-->>Controller: 认证成功
        Controller->>Service: login(request)
        Service->>Mapper: 查询用户<br/>selectById(username)
        Mapper->>DB: SELECT * FROM user<br/>WHERE username = ?
        DB-->>Mapper: 返回用户信息
        Mapper-->>Service: 返回User对象
        Service->>JwtProvider: generateToken(userId, username, role)
        JwtProvider-->>Service: 返回accessToken
        Service->>JwtProvider: generateRefreshToken(userId)
        JwtProvider-->>Service: 返回refreshToken
        Service-->>Controller: 返回LoginResponse
        Controller-->>Client: 200 成功<br/>(包含accessToken和refreshToken)
    end

    Note over Client,DB: 3. Token刷新流程
    Client->>Controller: POST /api/v1/auth/refresh<br/>RefreshTokenRequest
    Controller->>Service: refreshToken(request)
    Service->>JwtProvider: validateToken(refreshToken)
    JwtProvider-->>Service: 返回验证结果
    alt Token无效
        Service-->>Controller: 抛出异常<br/>UNAUTHORIZED
        Controller-->>Client: 401 未授权
    else Token有效
        Service->>JwtProvider: getUsernameFromToken(refreshToken)
        JwtProvider-->>Service: 返回userId
        Service->>Mapper: selectById(userId)
        Mapper->>DB: SELECT * FROM user<br/>WHERE id = ?
        DB-->>Mapper: 返回用户信息
        Mapper-->>Service: 返回User对象
        Service->>JwtProvider: generateToken(userId, username, role)
        JwtProvider-->>Service: 返回新accessToken
        Service-->>Controller: 返回RefreshTokenResponse
        Controller-->>Client: 200 成功
    end

    Note over Client,DB: 4. 获取当前用户信息
    Client->>Controller: GET /api/v1/auth/me<br/>Header: Authorization: Bearer token
    Controller->>Security: JwtAuthenticationFilter<br/>验证token
    Security->>JwtProvider: validateToken(accessToken)
    JwtProvider-->>Security: 验证通过
    Security->>Security: 设置SecurityContext
    Controller->>Service: getCurrentUser()
    Service->>Mapper: selectById(userId)
    Mapper->>DB: SELECT * FROM user<br/>WHERE id = ?
    DB-->>Mapper: 返回用户信息
    Mapper-->>Service: 返回User对象
    Service-->>Controller: 返回用户信息
    Controller-->>Client: 200 成功

2. 活动管理流程

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Controller as ActivityController<br/>活动控制器
    participant Service as ActivityServiceImpl<br/>活动服务
    participant Mapper as ActivityMapper<br/>活动数据访问
    participant RegMapper as RegistrationMapper<br/>报名数据访问
    participant UserMapper as UserMapper<br/>用户数据访问
    participant Auth as AuthService<br/>认证服务
    participant DB as MySQL数据库

    Note over Client,DB: 1. 获取活动列表
    Client->>Controller: GET /api/v1/activities<br/>(current, size, status, keyword, category, startDate, endDate)
    Controller->>Service: pageActivities(page, params)
    Service->>Mapper: selectActivityPage(page, params)
    Mapper->>DB: SELECT * FROM activity<br/>WHERE conditions<br/>LIMIT offset, size
    DB-->>Mapper: 返回活动列表
    Mapper-->>Service: 返回IPage<Activity>
    Service->>Service: 转换为ActivityVO列表<br/>convertToVO()
    Service-->>Controller: 返回IPage<ActivityVO>
    Controller-->>Client: 200 成功

    Note over Client,DB: 2. 获取活动详情
    Client->>Controller: GET /api/v1/activities/{id}
    Controller->>Service: getActivityById(id)
    Service->>Mapper: selectById(id)
    Mapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
    DB-->>Mapper: 返回活动信息
    Mapper-->>Service: 返回Activity对象
    Service->>UserMapper: selectById(adminId)
    UserMapper->>DB: SELECT * FROM user<br/>WHERE id = ?
    DB-->>UserMapper: 返回管理员信息
    UserMapper-->>Service: 返回User对象
    alt 用户已登录
        Service->>Auth: getCurrentUser()
        Auth-->>Service: 返回当前用户
        Service->>RegMapper: 检查是否已报名<br/>selectOne(userId, activityId)
        RegMapper->>DB: SELECT * FROM registration<br/>WHERE user_id = ? AND activity_id = ?
        DB-->>RegMapper: 返回报名记录
        RegMapper-->>Service: 返回Registration对象
    end
    Service->>Service: 转换为ActivityVO<br/>convertToVO()
    Service-->>Controller: 返回ActivityVO
    Controller-->>Client: 200 成功

    Note over Client,DB: 3. 创建活动(管理员)
    Client->>Controller: POST /api/v1/activities<br/>ActivityCreateRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: createActivity(request)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    alt 用户不是管理员
        Service-->>Controller: 抛出异常<br/>FORBIDDEN
        Controller-->>Client: 403 禁止访问
    else 用户是管理员
        Service->>Service: 验证时间参数
        alt 开始时间晚于结束时间
            Service-->>Controller: 抛出异常<br/>BAD_REQUEST
            Controller-->>Client: 400 错误
        else 时间参数正确
            Service->>Service: checkConflict(startTime, endTime)
            Service->>Mapper: selectConflictActivities(startTime, endTime)
            Mapper->>DB: SELECT * FROM activity<br/>WHERE time_conflict
            DB-->>Mapper: 返回冲突活动列表
            Mapper-->>Service: 返回冲突活动
            alt 存在时间冲突
                Service-->>Controller: 抛出异常<br/>ACTIVITY_TIME_CONFLICT
                Controller-->>Client: 409 冲突
            else 无冲突
                Service->>Service: 创建Activity对象
                Service->>Mapper: insert(activity)
                Mapper->>DB: INSERT INTO activity(...)
                DB-->>Mapper: 返回插入ID
                Mapper-->>Service: 返回activityId
                Service-->>Controller: 返回activityId
                Controller-->>Client: 200 成功
            end
        end
    end

    Note over Client,DB: 4. 更新活动(管理员)
    Client->>Controller: PUT /api/v1/activities/{id}<br/>ActivityUpdateRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: updateActivity(id, request)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    alt 用户不是管理员
        Service-->>Controller: 抛出异常<br/>FORBIDDEN
        Controller-->>Client: 403 禁止访问
    else 用户是管理员
        Service->>Mapper: selectById(id)
        Mapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
        DB-->>Mapper: 返回活动信息
        Mapper-->>Service: 返回Activity对象
        alt 活动不存在或已删除
            Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
            Controller-->>Client: 404 未找到
        else 活动存在
            alt 不是活动创建者
                Service-->>Controller: 抛出异常<br/>FORBIDDEN
                Controller-->>Client: 403 禁止访问
            else 是活动创建者
                Service->>Service: 验证时间参数
                Service->>Service: checkConflict(startTime, endTime, excludeActivityId)
                Service->>Mapper: selectConflictActivities(startTime, endTime, excludeActivityId)
                Mapper->>DB: SELECT * FROM activity<br/>WHERE time_conflict AND id != ?
                DB-->>Mapper: 返回冲突活动列表
                Mapper-->>Service: 返回冲突活动
                alt 存在时间冲突
                    Service-->>Controller: 抛出异常<br/>ACTIVITY_TIME_CONFLICT
                    Controller-->>Client: 409 冲突
                else 无冲突
                    Service->>Service: 更新Activity对象
                    Service->>Mapper: updateById(activity)
                    Mapper->>DB: UPDATE activity SET ...<br/>WHERE id = ?
                    DB-->>Mapper: 返回更新结果
                    Mapper-->>Service: 返回成功
                    Service-->>Controller: 更新成功
                    Controller-->>Client: 200 成功
                end
            end
        end
    end

    Note over Client,DB: 5. 删除活动(管理员)
    Client->>Controller: DELETE /api/v1/activities/{id}<br/>Header: Authorization: Bearer token
    Controller->>Service: deleteActivity(id)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    alt 用户不是管理员
        Service-->>Controller: 抛出异常<br/>FORBIDDEN
        Controller-->>Client: 403 禁止访问
    else 用户是管理员
        Service->>Mapper: selectById(id)
        Mapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
        DB-->>Mapper: 返回活动信息
        Mapper-->>Service: 返回Activity对象
        alt 活动不存在或已删除
            Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
            Controller-->>Client: 404 未找到
        else 活动存在
            alt 不是活动创建者
                Service-->>Controller: 抛出异常<br/>FORBIDDEN
                Controller-->>Client: 403 禁止访问
            else 是活动创建者
                Service->>Mapper: deleteById(id)
                Mapper->>DB: UPDATE activity SET deleted = 1<br/>WHERE id = ?
                DB-->>Mapper: 返回删除结果
                Mapper-->>Service: 返回成功
                Service-->>Controller: 删除成功
                Controller-->>Client: 200 成功
            end
        end
    end

    Note over Client,DB: 6. 检测时间冲突(管理员)
    Client->>Controller: POST /api/v1/activities/check-conflict<br/>CheckConflictRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: checkConflict(request)
    Service->>Service: 验证时间参数
    Service->>Mapper: selectConflictActivities(startTime, endTime, excludeActivityId)
    Mapper->>DB: SELECT * FROM activity<br/>WHERE time_conflict AND id != ?
    DB-->>Mapper: 返回冲突活动列表
    Mapper-->>Service: 返回冲突活动
    Service->>Service: 构建ConflictCheckVO
    Service-->>Controller: 返回ConflictCheckVO
    Controller-->>Client: 200 成功

3. 活动报名流程

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Controller as RegistrationController<br/>报名控制器
    participant Service as RegistrationServiceImpl<br/>报名服务
    participant Mapper as RegistrationMapper<br/>报名数据访问
    participant ActMapper as ActivityMapper<br/>活动数据访问
    participant Auth as AuthService<br/>认证服务
    participant PdfUtil as PdfUtil<br/>PDF工具类
    participant DB as MySQL数据库

    Note over Client,DB: 1. 报名活动
    Client->>Controller: POST /api/v1/registrations<br/>RegistrationRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: register(request)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    Service->>ActMapper: selectById(activityId)
    ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
    DB-->>ActMapper: 返回活动信息
    ActMapper-->>Service: 返回Activity对象
    alt 活动不存在或已删除
        Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
        Controller-->>Client: 404 未找到
    else 活动存在
        alt 活动不在报名中
            Service-->>Controller: 抛出异常<br/>BAD_REQUEST
            Controller-->>Client: 400 错误
        else 活动在报名中
            alt 报名已截止
                Service-->>Controller: 抛出异常<br/>BAD_REQUEST
                Controller-->>Client: 400 错误
            else 报名未截止
                alt 报名人数已满
                    Service-->>Controller: 抛出异常<br/>ACTIVITY_FULL
                    Controller-->>Client: 409 冲突
                else 报名未满
                    Service->>Mapper: 检查是否已报名<br/>selectOne(userId, activityId)
                    Mapper->>DB: SELECT * FROM registration<br/>WHERE user_id = ? AND activity_id = ?<br/>AND status IN (1, 2)
                    DB-->>Mapper: 返回报名记录
                    Mapper-->>Service: 返回Registration对象
                    alt 已报名该活动
                        Service-->>Controller: 抛出异常<br/>ALREADY_REGISTERED
                        Controller-->>Client: 409 冲突
                    else 未报名该活动
                        Service->>Mapper: 查询用户所有报名<br/>selectList(userId, status=1)
                        Mapper->>DB: SELECT * FROM registration<br/>WHERE user_id = ? AND status = 1
                        DB-->>Mapper: 返回报名列表
                        Mapper-->>Service: 返回List<Registration>
                        loop 遍历报名列表
                            Service->>ActMapper: selectById(reg.activityId)
                            ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
                            DB-->>ActMapper: 返回活动信息
                            ActMapper-->>Service: 返回Activity对象
                            Service->>Service: isTimeConflict(activity1, activity2)
                            alt 存在时间冲突
                                Service-->>Controller: 抛出异常<br/>ACTIVITY_TIME_CONFLICT
                                Controller-->>Client: 409 冲突
                            end
                        end
                        Service->>Service: 创建Registration对象<br/>generateTicketCode()
                        Service->>Mapper: insert(registration)
                        Mapper->>DB: INSERT INTO registration(...)
                        DB-->>Mapper: 返回插入ID
                        Mapper-->>Service: 返回registrationId
                        Service->>ActMapper: 更新活动报名人数<br/>updateById(activity)
                        ActMapper->>DB: UPDATE activity SET<br/>current_participants = current_participants + 1<br/>WHERE id = ?
                        DB-->>ActMapper: 返回更新结果
                        ActMapper-->>Service: 返回成功
                        Service->>Service: convertToVO()
                        Service-->>Controller: 返回RegistrationVO
                        Controller-->>Client: 200 成功
                    end
                end
            end
        end
    end

    Note over Client,DB: 2. 取消报名
    Client->>Controller: DELETE /api/v1/registrations/{id}<br/>Header: Authorization: Bearer token
    Controller->>Service: cancelRegistration(id)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    Service->>Mapper: selectById(id)
    Mapper->>DB: SELECT * FROM registration<br/>WHERE id = ?
    DB-->>Mapper: 返回报名记录
    Mapper-->>Service: 返回Registration对象
    alt 报名记录不存在
        Service-->>Controller: 抛出异常<br/>REGISTRATION_NOT_FOUND
        Controller-->>Client: 404 未找到
    else 报名记录存在
        alt 不是自己的报名
            Service-->>Controller: 抛出异常<br/>FORBIDDEN
            Controller-->>Client: 403 禁止访问
        else 是自己的报名
            alt 报名状态不是已报名
                Service-->>Controller: 抛出异常<br/>BAD_REQUEST
                Controller-->>Client: 400 错误
            else 报名状态是已报名
                Service->>ActMapper: selectById(activityId)
                ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
                DB-->>ActMapper: 返回活动信息
                ActMapper-->>Service: 返回Activity对象
                alt 活动已开始
                    Service-->>Controller: 抛出异常<br/>ACTIVITY_ALREADY_STARTED
                    Controller-->>Client: 409 冲突
                else 活动未开始
                    Service->>Mapper: 更新报名状态<br/>updateById(registration)
                    Mapper->>DB: UPDATE registration SET<br/>status = 0, canceled_at = NOW()<br/>WHERE id = ?
                    DB-->>Mapper: 返回更新结果
                    Mapper-->>Service: 返回成功
                    Service->>ActMapper: 减少活动报名人数<br/>updateById(activity)
                    ActMapper->>DB: UPDATE activity SET<br/>current_participants = current_participants - 1<br/>WHERE id = ?
                    DB-->>ActMapper: 返回更新结果
                    ActMapper-->>Service: 返回成功
                    Service-->>Controller: 取消成功
                    Controller-->>Client: 200 成功
                end
            end
        end
    end

    Note over Client,DB: 3. 下载电子票PDF
    Client->>Controller: GET /api/v1/registrations/{id}/ticket<br/>Header: Authorization: Bearer token
    Controller->>Service: generateTicketPdf(id)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    Service->>Mapper: selectById(id)
    Mapper->>DB: SELECT * FROM registration<br/>WHERE id = ?
    DB-->>Mapper: 返回报名记录
    Mapper-->>Service: 返回Registration对象
    alt 报名记录不存在
        Service-->>Controller: 抛出异常<br/>REGISTRATION_NOT_FOUND
        Controller-->>Client: 404 未找到
    else 报名记录存在
        alt 不是自己的报名
            Service-->>Controller: 抛出异常<br/>FORBIDDEN
            Controller-->>Client: 403 禁止访问
        else 是自己的报名
            alt 报名状态不是已报名
                Service-->>Controller: 抛出异常<br/>BAD_REQUEST
                Controller-->>Client: 400 错误
            else 报名状态是已报名
                Service->>ActMapper: selectById(activityId)
                ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
                DB-->>ActMapper: 返回活动信息
                ActMapper-->>Service: 返回Activity对象
                Service->>PdfUtil: generateTicketPdf(user, activity, registration)
                PdfUtil-->>Service: 返回PDF字节数组
                Service-->>Controller: 返回PDF字节数组
                Controller-->Client: 200 成功<br/>Content-Type: application/pdf
            end
        end
    end

4. 签到管理流程

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Controller as CheckInController<br/>签到控制器
    participant Service as CheckInServiceImpl<br/>签到服务
    participant Mapper as CheckInMapper<br/>签到数据访问
    participant RegMapper as RegistrationMapper<br/>报名数据访问
    participant ActMapper as ActivityMapper<br/>活动数据访问
    participant Auth as AuthService<br/>认证服务
    participant QrUtil as QrCodeUtil<br/>二维码工具类
    participant DB as MySQL数据库

    Note over Client,DB: 1. 生成签到二维码(管理员)
    Client->>Controller: POST /api/v1/checkin/qrcode/{activityId}<br/>Header: Authorization: Bearer token
    Controller->>Service: generateQrCode(activityId)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    alt 用户不是管理员
        Service-->>Controller: 抛出异常<br/>FORBIDDEN
        Controller-->>Client: 403 禁止访问
    else 用户是管理员
        Service->>ActMapper: selectById(activityId)
        ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
        DB-->>ActMapper: 返回活动信息
        ActMapper-->>Service: 返回Activity对象
        alt 活动不存在或已删除
            Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
            Controller-->>Client: 404 未找到
        else 活动存在
            alt 不是活动创建者
                Service-->>Controller: 抛出异常<br/>FORBIDDEN
                Controller-->>Client: 403 禁止访问
            else 是活动创建者
                Service->>QrUtil: generateQrCodeContent(activityId)
                QrUtil-->>Service: 返回二维码内容
                Service->>Service: 构建QrCodeVO
                Service-->>Controller: 返回QrCodeVO
                Controller-->>Client: 200 成功
            end
        end
    end

    Note over Client,DB: 2. 学生扫码签到
    Client->>Controller: POST /api/v1/checkin/scan<br/>ScanCheckInRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: scanCheckIn(request)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    Service->>QrUtil: parseActivityIdFromQrCode(qrCodeContent)
    QrUtil-->>Service: 返回activityId
    alt 二维码无效
        Service-->>Controller: 抛出异常<br/>BAD_REQUEST
        Controller-->>Client: 400 错误
    else 二维码有效
        Service->>ActMapper: selectById(activityId)
        ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
        DB-->>ActMapper: 返回活动信息
        ActMapper-->>Service: 返回Activity对象
        alt 活动不存在或已删除
            Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
            Controller-->>Client: 404 未找到
        else 活动存在
            Service->>Service: 检查签到时间<br/>startTime - 1小时 <= now <= endTime
            alt 签到时间已过期
                Service-->>Controller: 抛出异常<br/>CHECKIN_TIME_EXPIRED
                Controller-->>Client: 400 错误
            else 签到时间有效
                Service->>RegMapper: 查询报名记录<br/>selectOne(userId, activityId, status=1)
                RegMapper->>DB: SELECT * FROM registration<br/>WHERE user_id = ? AND activity_id = ?<br/>AND status = 1
                DB-->>RegMapper: 返回报名记录
                RegMapper-->>Service: 返回Registration对象
                alt 未报名该活动
                    Service-->>Controller: 抛出异常<br/>NOT_REGISTERED
                    Controller-->>Client: 400 错误
                else 已报名该活动
                    Service->>Mapper: 检查是否已签到<br/>selectOne(registrationId)
                    Mapper->>DB: SELECT * FROM check_in<br/>WHERE registration_id = ?
                    DB-->>Mapper: 返回签到记录
                    Mapper-->>Service: 返回CheckIn对象
                    alt 已签到
                        Service-->>Controller: 抛出异常<br/>ALREADY_CHECKED_IN
                        Controller-->>Client: 409 冲突
                    else 未签到
                        Service->>Service: performCheckIn(registration, user, activityId, method=0)
                        Service->>Mapper: insert(checkIn)
                        Mapper->>DB: INSERT INTO check_in(...)
                        DB-->>Mapper: 返回插入ID
                        Mapper-->>Service: 返回checkInId
                        Service->>RegMapper: 更新报名状态为已签到<br/>updateById(registration)
                        RegMapper->>DB: UPDATE registration SET status = 2<br/>WHERE id = ?
                        DB-->>RegMapper: 返回更新结果
                        RegMapper-->>Service: 返回成功
                        Service->>Service: convertToVO()
                        Service-->>Controller: 返回CheckInVO
                        Controller-->>Client: 200 成功
                    end
                end
            end
        end
    end

    Note over Client,DB: 3. 管理员扫学生票签到
    Client->>Controller: POST /api/v1/checkin/ticket<br/>TicketCheckInRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: ticketCheckIn(request)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    alt 用户不是管理员
        Service-->>Controller: 抛出异常<br/>FORBIDDEN
        Controller-->>Client: 403 禁止访问
    else 用户是管理员
        Service->>ActMapper: selectById(activityId)
        ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
        DB-->>ActMapper: 返回活动信息
        ActMapper-->>Service: 返回Activity对象
        alt 活动不存在或已删除
            Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
            Controller-->>Client: 404 未找到
        else 活动存在
            alt 不是活动创建者
                Service-->>Controller: 抛出异常<br/>FORBIDDEN
                Controller-->>Client: 403 禁止访问
            else 是活动创建者
                Service->>Service: 检查签到时间
                alt 签到时间已过期
                    Service-->>Controller: 抛出异常<br/>CHECKIN_TIME_EXPIRED
                    Controller-->>Client: 400 错误
                else 签到时间有效
                    Service->>RegMapper: selectByTicketCode(ticketCode)
                    RegMapper->>DB: SELECT * FROM registration<br/>WHERE ticket_code = ?
                    DB-->>RegMapper: 返回报名记录
                    RegMapper-->>Service: 返回Registration对象
                    alt 电子票无效
                        Service-->>Controller: 抛出异常<br/>BAD_REQUEST
                        Controller-->>Client: 400 错误
                    else 电子票有效
                        alt 电子票与活动不匹配
                            Service-->>Controller: 抛出异常<br/>BAD_REQUEST
                            Controller-->>Client: 400 错误
                        else 电子票与活动匹配
                            Service->>Mapper: 检查是否已签到<br/>selectOne(registrationId)
                            Mapper->>DB: SELECT * FROM check_in<br/>WHERE registration_id = ?
                            DB-->>Mapper: 返回签到记录
                            Mapper-->>Service: 返回CheckIn对象
                            alt 已签到
                                Service-->>Controller: 抛出异常<br/>ALREADY_CHECKED_IN
                                Controller-->>Client: 409 冲突
                            else 未签到
                                Service->>Auth: getUserById(userId)
                                Auth-->>Service: 返回学生信息
                                Service->>Service: performCheckIn(registration, student, activityId, method=1)
                                Service->>Mapper: insert(checkIn)
                                Mapper->>DB: INSERT INTO check_in(...)
                                DB-->>Mapper: 返回插入ID
                                Mapper-->>Service: 返回checkInId
                                Service->>RegMapper: 更新报名状态<br/>updateById(registration)
                                RegMapper->>DB: UPDATE registration SET status = 2<br/>WHERE id = ?
                                DB-->>RegMapper: 返回更新结果
                                RegMapper-->>Service: 返回成功
                                Service->>Service: convertToVO()
                                Service-->>Controller: 返回CheckInVO
                                Controller-->>Client: 200 成功
                            end
                        end
                    end
                end
            end
        end
    end

5. 评价管理流程

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Controller as ReviewController<br/>评价控制器
    participant Service as ReviewServiceImpl<br/>评价服务
    participant Mapper as ReviewMapper<br/>评价数据访问
    participant ActMapper as ActivityMapper<br/>活动数据访问
    participant CheckInMapper as CheckInMapper<br/>签到数据访问
    participant Auth as AuthService<br/>认证服务
    participant DB as MySQL数据库

    Note over Client,DB: 1. 提交评价
    Client->>Controller: POST /api/v1/reviews<br/>ReviewRequest<br/>Header: Authorization: Bearer token
    Controller->>Service: createReview(request)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    Service->>ActMapper: selectById(activityId)
    ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
    DB-->>ActMapper: 返回活动信息
    ActMapper-->>Service: 返回Activity对象
    alt 活动不存在或已删除
        Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
        Controller-->>Client: 404 未找到
    else 活动存在
        Service->>Mapper: 检查是否已评价<br/>selectOne(userId, activityId)
        Mapper->>DB: SELECT * FROM review<br/>WHERE user_id = ? AND activity_id = ?
        DB-->>Mapper: 返回评价记录
        Mapper-->>Service: 返回Review对象
        alt 已评价该活动
            Service-->>Controller: 抛出异常<br/>REVIEW_ALREADY_EXISTS
            Controller-->>Client: 409 冲突
        else 未评价该活动
            Service->>CheckInMapper: 检查是否已签到<br/>selectOne(userId, activityId)
            CheckInMapper->>DB: SELECT * FROM check_in<br/>WHERE user_id = ? AND activity_id = ?
            DB-->>CheckInMapper: 返回签到记录
            CheckInMapper-->>Service: 返回CheckIn对象
            alt 未参加该活动
                Service-->>Controller: 抛出异常<br/>NOT_PARTICIPATED
                Controller-->>Client: 400 错误
            else 已参加该活动
                Service->>Service: 创建Review对象
                Service->>Mapper: insert(review)
                Mapper->>DB: INSERT INTO review(...)
                DB-->>Mapper: 返回插入ID
                Mapper-->>Service: 返回reviewId
                Service->>Service: convertToVO()
                Service-->>Controller: 返回ReviewVO
                Controller-->>Client: 200 成功
            end
        end
    end

    Note over Client,DB: 2. 获取活动评价列表
    Client->>Controller: GET /api/v1/reviews/activity/{activityId}<br/>(current, size)
    Controller->>Service: getActivityReviews(page, activityId)
    Service->>Mapper: selectActivityReviews(page, activityId)
    Mapper->>DB: SELECT * FROM review<br/>WHERE activity_id = ?<br/>LIMIT offset, size
    DB-->>Mapper: 返回评价列表
    Mapper-->>Service: 返回IPage<ReviewVO>
    Service-->>Controller: 返回IPage<ReviewVO>
    Controller-->>Client: 200 成功

    Note over Client,DB: 3. 获取我的评价列表
    Client->>Controller: GET /api/v1/reviews/my<br/>(current, size)<br/>Header: Authorization: Bearer token
    Controller->>Service: getMyReviews(page)
    Service->>Auth: getCurrentUser()
    Auth-->>Service: 返回当前用户
    Service->>Mapper: selectMyReviews(page, userId)
    Mapper->>DB: SELECT * FROM review<br/>WHERE user_id = ?<br/>LIMIT offset, size
    DB-->>Mapper: 返回评价列表
    Mapper-->>Service: 返回IPage<ReviewVO>
    Service-->>Controller: 返回IPage<ReviewVO>
    Controller-->>Client: 200 成功

6. 统计数据流程

sequenceDiagram
    autonumber
    participant Client as 客户端
    participant Controller as StatisticsController<br/>统计控制器
    participant Service as StatisticsServiceImpl<br/>统计服务
    participant RegMapper as RegistrationMapper<br/>报名数据访问
    participant CheckInMapper as CheckInMapper<br/>签到数据访问
    participant ReviewMapper as ReviewMapper<br/>评价数据访问
    participant ActMapper as ActivityMapper<br/>活动数据访问
    participant CsvUtil as CsvUtil<br/>CSV工具类
    participant DB as MySQL数据库

    Note over Client,DB: 1. 获取活动统计数据(管理员)
    Client->>Controller: GET /api/v1/statistics/activity/{activityId}<br/>Header: Authorization: Bearer token
    Controller->>Service: getActivityStatistics(activityId)
    Service->>ActMapper: selectById(activityId)
    ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
    DB-->>ActMapper: 返回活动信息
    ActMapper-->>Service: 返回Activity对象
    alt 活动不存在或已删除
        Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
        Controller-->>Client: 404 未找到
    else 活动存在
        Service->>RegMapper: 统计报名人数<br/>selectCount(activityId, status IN (1,2))
        RegMapper->>DB: SELECT COUNT(*) FROM registration<br/>WHERE activity_id = ?<br/>AND status IN (1, 2)
        DB-->>RegMapper: 返回报名人数
        RegMapper-->>Service: 返回registeredCount

        Service->>CheckInMapper: 查询所有签到记录<br/>selectList(activityId)
        CheckInMapper->>DB: SELECT * FROM check_in<br/>WHERE activity_id = ?
        DB-->>CheckInMapper: 返回签到列表
        CheckInMapper-->>Service: 返回List<CheckIn>
        Service->>Service: 计算签到人数

        Service->>ReviewMapper: 统计评价数量<br/>selectCount(activityId)
        ReviewMapper->>DB: SELECT COUNT(*) FROM review<br/>WHERE activity_id = ?
        DB-->>ReviewMapper: 返回评价数量
        ReviewMapper-->>Service: 返回reviewCount

        Service->>ReviewMapper: 查询所有评价<br/>selectList(activityId)
        ReviewMapper->>DB: SELECT * FROM review<br/>WHERE activity_id = ?
        DB-->>ReviewMapper: 返回评价列表
        ReviewMapper-->>Service: 返回List<Review>
        Service->>Service: 计算平均评分
        Service->>Service: 计算评分分布
        Service->>Service: 计算签到率
        Service->>Service: 构建ActivityStatisticsVO
        Service-->>Controller: 返回ActivityStatisticsVO
        Controller-->>Client: 200 成功
    end

    Note over Client,DB: 2. 导出活动数据(管理员)
    Client->>Controller: GET /api/v1/statistics/activity/{activityId}/export<br/>Header: Authorization: Bearer token
    Controller->>Service: exportActivityData(activityId, format)
    Service->>ActMapper: selectById(activityId)
    ActMapper->>DB: SELECT * FROM activity<br/>WHERE id = ?
    DB-->>ActMapper: 返回活动信息
    ActMapper-->>Service: 返回Activity对象
    alt 活动不存在或已删除
        Service-->>Controller: 抛出异常<br/>ACTIVITY_NOT_FOUND
        Controller-->>Client: 404 未找到
    else 活动存在
        Service->>RegMapper: 查询活动报名列表<br/>selectList(activityId)
        RegMapper->>DB: SELECT * FROM registration<br/>WHERE activity_id = ?
        DB-->>RegMapper: 返回报名列表
        RegMapper-->>Service: 返回List<Registration>

        Service->>CheckInMapper: 查询活动签到列表<br/>selectList(activityId)
        CheckInMapper->>DB: SELECT * FROM check_in<br/>WHERE activity_id = ?
        DB-->>CheckInMapper: 返回签到列表
        CheckInMapper-->>Service: 返回List<CheckIn>

        Service->>ReviewMapper: 查询活动评价列表<br/>selectList(activityId)
        ReviewMapper->>DB: SELECT * FROM review<br/>WHERE activity_id = ?
        DB-->>ReviewMapper: 返回评价列表
        ReviewMapper-->>Service: 返回List<Review>

        Service->>CsvUtil: exportActivityData(activity, registrations, checkIns, reviews)
        CsvUtil-->>Service: 返回CSV字节数组
        Service-->>Controller: 返回CSV字节数组
        Controller->>Client: 200 成功<br/>Content-Type: text/csv
    end

    Note over Client,DB: 3. 获取总体统计(管理员)
    Client->>Controller: GET /api/v1/statistics/overview<br/>Header: Authorization: Bearer token
    Controller->>Service: getOverviewStatistics()

    Service->>ActMapper: 统计活动总数<br/>selectCount(deleted=0)
    ActMapper->>DB: SELECT COUNT(*) FROM activity<br/>WHERE deleted = 0
    DB-->>ActMapper: 返回活动总数
    ActMapper-->>Service: 返回totalActivities

    Service->>RegMapper: 统计报名总数<br/>selectCount(status=1)
    RegMapper->>DB: SELECT COUNT(*) FROM registration<br/>WHERE status = 1
    DB-->>RegMapper: 返回报名总数
    RegMapper-->>Service: 返回totalRegistrations

    Service->>CheckInMapper: 统计签到总数<br/>selectCount()
    CheckInMapper->>DB: SELECT COUNT(*) FROM check_in
    DB-->>CheckInMapper: 返回签到总数
    CheckInMapper-->>Service: 返回totalCheckIns

    Service->>ReviewMapper: 统计评价总数<br/>selectCount()
    ReviewMapper->>DB: SELECT COUNT(*) FROM review
    DB-->>ReviewMapper: 返回评价总数
    ReviewMapper-->>Service: 返回totalReviews

    Service->>ReviewMapper: 查询所有评价<br/>selectList()
    ReviewMapper->>DB: SELECT * FROM review
    DB-->>ReviewMapper: 返回评价列表
    ReviewMapper-->>Service: 返回List<Review>
    Service->>Service: 计算平均评分

    Service->>Service: calculateMonthlyStats()
    loop 最近6个月
        Service->>ActMapper: 统计月活动数<br/>selectCount(createdAt BETWEEN monthStart AND monthEnd)
        ActMapper->>DB: SELECT COUNT(*) FROM activity<br/>WHERE created_at BETWEEN ? AND ?
        DB-->>ActMapper: 返回月活动数
        ActMapper-->>Service: 返回activityCount

        Service->>RegMapper: 统计月报名数<br/>selectCount(createdAt BETWEEN monthStart AND monthEnd)
        RegMapper->>DB: SELECT COUNT(*) FROM registration<br/>WHERE created_at BETWEEN ? AND ?
        DB-->>RegMapper: 返回月报名数
        RegMapper-->>Service: 返回registrationCount
    end
    Service->>Service: 构建OverviewStatisticsVO
    Service-->>Controller: 返回OverviewStatisticsVO
    Controller-->>Client: 200 成功

系统分层架构图

graph TB
    subgraph "表现层 (Controller Layer)"
        A1[AuthController<br/>认证控制器]
        A2[ActivityController<br/>活动控制器]
        A3[RegistrationController<br/>报名控制器]
        A4[CheckInController<br/>签到控制器]
        A5[ReviewController<br/>评价控制器]
        A6[StatisticsController<br/>统计控制器]
    end

    subgraph "业务逻辑层 (Service Layer)"
        B1[AuthServiceImpl<br/>认证服务]
        B2[ActivityServiceImpl<br/>活动服务]
        B3[RegistrationServiceImpl<br/>报名服务]
        B4[CheckInServiceImpl<br/>签到服务]
        B5[ReviewServiceImpl<br/>评价服务]
        B6[StatisticsServiceImpl<br/>统计服务]
    end

    subgraph "数据访问层 (Mapper Layer)"
        C1[UserMapper<br/>用户数据访问]
        C2[ActivityMapper<br/>活动数据访问]
        C3[RegistrationMapper<br/>报名数据访问]
        C4[CheckInMapper<br/>签到数据访问]
        C5[ReviewMapper<br/>评价数据访问]
    end

    subgraph "实体层 (Entity Layer)"
        D1[User<br/>用户实体]
        D2[Activity<br/>活动实体]
        D3[Registration<br/>报名实体]
        D4[CheckIn<br/>签到实体]
        D5[Review<br/>评价实体]
    end

    subgraph "工具层 (Util Layer)"
        E1[JwtTokenProvider<br/>JWT令牌提供者]
        E2[PdfUtil<br/>PDF工具类]
        E3[QrCodeUtil<br/>二维码工具类]
        E4[CsvUtil<br/>CSV工具类]
    end

    subgraph "安全层 (Security Layer)"
        F1[SecurityConfig<br/>安全配置]
        F2[JwtAuthenticationFilter<br/>JWT认证过滤器]
        F3[UserDetailsServiceImpl<br/>用户详情服务]
    end

    subgraph "数据库层 (Database Layer)"
        G1[(MySQL数据库)]
    end

    A1 --> B1
    A2 --> B2
    A3 --> B3
    A4 --> B4
    A5 --> B5
    A6 --> B6

    B1 --> C1
    B1 --> E1
    B2 --> C2
    B2 --> C1
    B2 --> C3
    B3 --> C3
    B3 --> C2
    B3 --> E2
    B4 --> C4
    B4 --> C3
    B4 --> C2
    B4 --> E3
    B5 --> C5
    B5 --> C2
    B5 --> C4
    B6 --> C3
    B6 --> C4
    B6 --> C5
    B6 --> C2
    B6 --> E4

    C1 --> D1
    C2 --> D2
    C3 --> D3
    C4 --> D4
    C5 --> D5

    C1 --> G1
    C2 --> G1
    C3 --> G1
    C4 --> G1
    C5 --> G1

    F1 --> F2
    F1 --> F3
    F2 --> E1
    F3 --> C1

    style A1 fill:#e1f5ff
    style A2 fill:#e1f5ff
    style A3 fill:#e1f5ff
    style A4 fill:#e1f5ff
    style A5 fill:#e1f5ff
    style A6 fill:#e1f5ff
    style B1 fill:#fff4e1
    style B2 fill:#fff4e1
    style B3 fill:#fff4e1
    style B4 fill:#fff4e1
    style B5 fill:#fff4e1
    style B6 fill:#fff4e1
    style C1 fill:#e8f5e9
    style C2 fill:#e8f5e9
    style C3 fill:#e8f5e9
    style C4 fill:#e8f5e9
    style C5 fill:#e8f5e9
    style D1 fill:#f3e5f5
    style D2 fill:#f3e5f5
    style D3 fill:#f3e5f5
    style D4 fill:#f3e5f5
    style D5 fill:#f3e5f5
    style E1 fill:#fce4ec
    style E2 fill:#fce4ec
    style E3 fill:#fce4ec
    style E4 fill:#fce4ec
    style F1 fill:#fff9c4
    style F2 fill:#fff9c4
    style F3 fill:#fff9c4
    style G1 fill:#cfd8dc

核心业务流程总览

graph LR
    subgraph "用户认证"
        A[注册] --> B[登录]
        B --> C[获取Token]
    end

    subgraph "活动管理"
        D[创建活动] --> E[发布活动]
        E --> F[时间冲突检测]
        F --> G[活动列表]
        G --> H[活动详情]
        H --> I[更新活动]
        I --> J[删除活动]
    end

    subgraph "报名流程"
        K[浏览活动] --> L[报名活动]
        L --> M[生成电子票]
        M --> N[下载PDF]
        N --> O[取消报名]
    end

    subgraph "签到流程"
        P[生成二维码] --> Q[学生扫码]
        Q --> R[管理员扫码]
        R --> S[签到成功]
    end

    subgraph "评价流程"
        T[参加活动] --> U[签到完成]
        U --> V[提交评价]
        V --> W[查看评价]
    end

    subgraph "统计分析"
        X[活动统计] --> Y[数据导出]
        Y --> Z[总体统计]
    end

    C --> K
    C --> D
    C --> P
    C --> V
    C --> X

    style A fill:#4CAF50,color:#fff
    style B fill:#4CAF50,color:#fff
    style C fill:#4CAF50,color:#fff
    style D fill:#2196F3,color:#fff
    style E fill:#2196F3,color:#fff
    style F fill:#2196F3,color:#fff
    style G fill:#2196F3,color:#fff
    style H fill:#2196F3,color:#fff
    style I fill:#2196F3,color:#fff
    style J fill:#2196F3,color:#fff
    style K fill:#FF9800,color:#fff
    style L fill:#FF9800,color:#fff
    style M fill:#FF9800,color:#fff
    style N fill:#FF9800,color:#fff
    style O fill:#FF9800,color:#fff
    style P fill:#9C27B0,color:#fff
    style Q fill:#9C27B0,color:#fff
    style R fill:#9C27B0,color:#fff
    style S fill:#9C27B0,color:#fff
    style T fill:#E91E63,color:#fff
    style U fill:#E91E63,color:#fff
    style V fill:#E91E63,color:#fff
    style W fill:#E91E63,color:#fff
    style X fill:#607D8B,color:#fff
    style Y fill:#607D8B,color:#fff
    style Z fill:#607D8B,color:#fff

代码文件索引

Controller层

  • AuthController.java - 认证控制器
  • ActivityController.java - 活动控制器
  • RegistrationController.java - 报名控制器
  • CheckInController.java - 签到控制器
  • ReviewController.java - 评价控制器
  • StatisticsController.java - 统计控制器

Service层

  • AuthServiceImpl.java - 认证服务实现
  • ActivityServiceImpl.java - 活动服务实现
  • RegistrationServiceImpl.java - 报名服务实现
  • CheckInServiceImpl.java - 签到服务实现
  • ReviewServiceImpl.java - 评价服务实现
  • StatisticsServiceImpl.java - 统计服务实现

Mapper层

  • UserMapper.java - 用户数据访问
  • ActivityMapper.java - 活动数据访问
  • RegistrationMapper.java - 报名数据访问
  • CheckInMapper.java - 签到数据访问
  • ReviewMapper.java - 评价数据访问

Entity层

  • User.java - 用户实体
  • Activity.java - 活动实体
  • Registration.java - 报名实体
  • CheckIn.java - 签到实体
  • Review.java - 评价实体

Security层

  • SecurityConfig.java - 安全配置
  • JwtAuthenticationFilter.java - JWT认证过滤器
  • JwtTokenProvider.java - JWT令牌提供者
  • UserDetailsServiceImpl.java - 用户详情服务

Util层

  • PdfUtil.java - PDF工具类
  • QrCodeUtil.java - 二维码工具类
  • CsvUtil.java - CSV工具类

总结

本业务流程图详细展示了校园活动系统的核心业务流程,包括:

  1. 用户认证流程注册、登录、Token刷新、获取用户信息
  2. 活动管理流程:创建、查询、更新、删除活动,时间冲突检测
  3. 活动报名流程报名、取消报名、生成电子票、下载PDF
  4. 签到管理流程:生成二维码、学生扫码签到、管理员扫码签到
  5. 评价管理流程:提交评价、查看活动评价、查看我的评价
  6. 统计数据流程:活动统计、数据导出、总体统计

每个流程都详细标注了涉及的代码文件、方法名和数据库操作清晰地展示了从Controller层到Service层、Mapper层最后到数据库的完整调用链路。

系统采用标准的分层架构,各层职责清晰:

  • Controller层处理HTTP请求和响应
  • Service层:实现核心业务逻辑
  • Mapper层:与数据库交互
  • Entity层:数据模型定义
  • Security层JWT认证和授权
  • Util层:提供工具类支持

这种架构设计保证了代码的可维护性、可扩展性和可测试性。