# 校园活动组织与报名系统 - 答辩文档

## 一、整体框架结构

### 1.1 技术栈

- **后端框架**: Spring Boot 3.1.8
- **数据库**: MySQL 8.0
- **ORM框架**: MyBatis-Plus 3.5.5
- **安全框架**: Spring Security + JWT
- **API文档**: Knife4j (Swagger)
- **工具库**: Hutool、Lombok
- **其他**: ZXing（二维码生成）、iText（PDF生成）、EasyExcel（Excel导出）

### 1.2 项目结构

```
server/
├── src/main/java/com/campus/activity/
│   ├── CampusActivityApplication.java          # 启动类
│   ├── common/                                 # 通用类
│   │   ├── Result.java                         # 统一响应结果
│   │   ├── PageResult.java                     # 分页结果
│   │   └── ResultCode.java                     # 响应状态码
│   ├── config/                                 # 配置类
│   │   ├── SecurityConfig.java                 # Spring Security配置
│   │   ├── CorsConfig.java                     # 跨域配置
│   │   ├── Knife4jConfig.java                  # API文档配置
│   │   ├── MybatisPlusConfig.java              # MyBatis-Plus配置
│   │   └── MyMetaObjectHandler.java            # 自动填充处理器
│   ├── controller/                             # 控制器层
│   │   ├── AuthController.java                 # 认证模块
│   │   ├── ActivityController.java             # 活动模块
│   │   ├── RegistrationController.java         # 报名模块
│   │   ├── CheckInController.java              # 签到模块
│   │   ├── ReviewController.java               # 评价模块（我负责）
│   │   └── StatisticsController.java           # 统计模块（我负责）
│   ├── dto/                                    # 数据传输对象
│   │   ├── request/                            # 请求DTO
│   │   │   ├── ReviewRequest.java              # 评价请求
│   │   │   └── ...
│   │   └── response/                           # 响应DTO
│   │       └── ...
│   ├── entity/                                 # 实体类
│   │   ├── User.java                           # 用户实体
│   │   ├── Activity.java                       # 活动实体
│   │   ├── Registration.java                   # 报名实体
│   │   ├── CheckIn.java                        # 签到实体
│   │   └── Review.java                         # 评价实体
│   ├── exception/                              # 异常处理
│   │   ├── BusinessException.java              # 业务异常
│   │   └── GlobalExceptionHandler.java         # 全局异常处理器
│   ├── mapper/                                 # 数据访问层
│   │   ├── UserMapper.java
│   │   ├── ActivityMapper.java
│   │   ├── RegistrationMapper.java
│   │   ├── CheckInMapper.java
│   │   └── ReviewMapper.java                   # 评价Mapper（我负责）
│   ├── security/                               # 安全相关
│   │   ├── JwtTokenProvider.java               # JWT令牌提供者
│   │   ├── JwtAuthenticationFilter.java        # JWT认证过滤器
│   │   └── UserDetailsServiceImpl.java         # 用户详情服务
│   ├── service/                                # 服务层
│   │   ├── AuthService.java
│   │   ├── ActivityService.java
│   │   ├── RegistrationService.java
│   │   ├── CheckInService.java
│   │   ├── ReviewService.java                  # 评价服务接口（我负责）
│   │   └── StatisticsService.java              # 统计服务接口（我负责）
│   ├── service/impl/                           # 服务实现层
│   │   ├── AuthServiceImpl.java
│   │   ├── ActivityServiceImpl.java
│   │   ├── RegistrationServiceImpl.java
│   │   ├── CheckInServiceImpl.java
│   │   ├── ReviewServiceImpl.java              # 评价服务实现（我负责）
│   │   └── StatisticsServiceImpl.java          # 统计服务实现（我负责）
│   ├── util/                                   # 工具类
│   │   ├── QrCodeUtil.java                     # 二维码工具
│   │   ├── PdfUtil.java                        # PDF工具
│   │   └── CsvUtil.java                        # CSV工具（我负责）
│   └── vo/                                     # 视图对象
│       ├── ReviewVO.java                       # 评价视图对象（我负责）
│       ├── ActivityStatisticsVO.java           # 活动统计视图对象（我负责）
│       └── OverviewStatisticsVO.java           # 总体统计视图对象（我负责）
├── src/main/resources/
│   ├── application.yml                         # 应用配置
│   └── mapper/                                 # MyBatis XML映射文件
│       ├── ReviewMapper.xml                    # 评价Mapper XML（我负责）
│       └── ...
└── pom.xml                                     # Maven配置
```

### 1.3 分层架构

系统采用经典的分层架构：

1. **Controller层**: 接收HTTP请求，参数校验，调用Service层，返回响应
2. **Service层**: 业务逻辑处理，事务管理
3. **Mapper层**: 数据库访问，使用MyBatis-Plus简化CRUD操作
4. **Entity层**: 数据库实体映射
5. **DTO层**: 数据传输对象，用于接口交互
6. **VO层**: 视图对象，用于返回给前端的数据封装

---

## 二、我负责的模块

### 2.1 模块5.4：活动评分与评论模块

#### 2.1.1 功能概述

活动结束后，学生可对参加过的活动进行评价。每个学生对同一活动只能评价一次，管理员可查看所有评价。

#### 2.1.2 核心功能

1. **提交评价**
   - 学生对已参加的活动进行评分（1-5分）
   - 可选填写评论内容（最多500字符）
   - 每个学生对同一活动只能评价一次
   - 只有签到过的学生才能评价

2. **获取活动评价列表**
   - 分页查询某个活动的所有评价
   - 显示评价者信息、评分、评论内容、评价时间

3. **获取我的评价列表**
   - 学生查看自己的所有评价记录
   - 支持分页查询

#### 2.1.3 实现细节

**Controller层** (`ReviewController.java`):

```java
@RestController
@RequestMapping("/api/v1/reviews")
public class ReviewController {
    
    // 提交评价
    @PostMapping
    public Result<ReviewVO> createReview(@Valid @RequestBody ReviewRequest request)
    
    // 获取活动评价列表
    @GetMapping("/activity/{activityId}")
    public Result<IPage<ReviewVO>> getActivityReviews(...)
    
    // 获取我的评价列表
    @GetMapping("/my")
    public Result<IPage<ReviewVO>> getMyReviews(...)
}
```

**Service层** (`ReviewServiceImpl.java`):

核心业务逻辑：
1. 验证活动是否存在
2. 检查用户是否已评价该活动（通过唯一约束）
3. 验证用户是否已签到该活动（只有参加过的学生才能评价）
4. 插入评价记录
5. 返回评价详情（包含用户信息和活动信息）

**数据验证**:

```java
@NotNull(message = "活动ID不能为空")
private Long activityId;

@NotNull(message = "评分不能为空")
@Min(value = 1, message = "评分最小为1")
@Max(value = 5, message = "评分最大为5")
private Integer rating;

@Size(max = 500, message = "评论内容不能超过500个字符")
private String content;
```

**数据库设计**:

```sql
CREATE TABLE `review` (
    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
    `user_id` BIGINT NOT NULL,
    `activity_id` BIGINT NOT NULL,
    `rating` TINYINT NOT NULL COMMENT '评分（1-5）',
    `content` TEXT COMMENT '评论内容',
    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
    `updated_at` DATETIME ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY `uk_user_activity` (`user_id`, `activity_id`),
    FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
    FOREIGN KEY (`activity_id`) REFERENCES `activity` (`id`)
);
```

通过唯一索引 `uk_user_activity` 确保每个学生对同一活动只能评价一次。

**MyBatis XML映射** (`ReviewMapper.xml`):

```xml
<!-- 查询活动评价列表（关联用户和活动信息） -->
<select id="selectActivityReviews" resultType="com.campus.activity.vo.ReviewVO">
    SELECT 
        r.id,
        r.user_id,
        u.name AS user_name,
        u.avatar AS user_avatar,
        r.activity_id,
        a.title AS activity_title,
        r.rating,
        r.content,
        r.created_at
    FROM review r
    LEFT JOIN user u ON r.user_id = u.id
    LEFT JOIN activity a ON r.activity_id = a.id
    WHERE r.activity_id = #{activityId}
    ORDER BY r.created_at DESC
</select>
```

#### 2.1.4 技术亮点

1. **数据一致性保证**: 通过数据库唯一约束和业务双重验证，确保评价的唯一性
2. **权限控制**: 只有签到过的学生才能评价，防止虚假评价
3. **分页查询**: 使用MyBatis-Plus的分页插件，提高大数据量查询性能
4. **关联查询优化**: 在Mapper XML中使用LEFT JOIN一次性获取用户和活动信息，减少N+1查询问题
5. **数据验证**: 使用Jakarta Validation进行参数校验，提高代码健壮性

---

### 2.2 模块5.5：数据统计与导出

#### 2.2.1 功能概述

系统具备基本统计能力，例如每个活动的报名人数、实际签到人数、平均评分。管理员可导出活动数据（CSV格式）。

#### 2.2.2 核心功能

1. **获取活动统计数据**
   - 报名人数（已报名+已签到）
   - 签到人数
   - 签到率（签到人数/报名人数）
   - 评价人数
   - 平均评分
   - 评分分布（1-5星各有多少人）

2. **导出活动数据**
   - 支持CSV格式导出
   - 包含活动基本信息、统计数据
   - 支持Excel直接打开（使用UTF-8 BOM头）
   - 文件名格式: `activity_{activityId}_statistics.csv`

3. **获取总体统计**
   - 总活动数
   - 总报名数
   - 总签到数
   - 总评价数
   - 全平台平均评分
   - 最近6个月的月度统计（活动和报名数量趋势）

#### 2.2.3 实现细节

**Controller层** (`StatisticsController.java`):

```java
@RestController
@RequestMapping("/api/v1/statistics")
public class StatisticsController {
    
    // 获取活动统计数据（管理员）
    @GetMapping("/activity/{activityId}")
    @PreAuthorize("hasRole('ADMIN')")
    public Result<ActivityStatisticsVO> getActivityStatistics(@PathVariable Long activityId)
    
    // 导出活动数据（管理员）
    @GetMapping("/activity/{activityId}/export")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<byte[]> exportActivityData(...)
    
    // 获取总体统计（管理员）
    @GetMapping("/overview")
    @PreAuthorize("hasRole('ADMIN')")
    public Result<OverviewStatisticsVO> getOverviewStatistics()
}
```

**Service层** (`StatisticsServiceImpl.java`):

核心业务逻辑：

1. **活动统计** (`getActivityStatistics`):
   - 统计报名人数（状态为1或2的报名记录）
   - 统计签到人数
   - 计算签到率（保留两位小数）
   - 统计评价人数和平均评分（保留一位小数）
   - 计算评分分布（1-5星各有多少人）

2. **数据导出** (`exportActivityData`):
   - 调用 `CsvUtil` 生成CSV文件
   - 设置响应头（Content-Disposition、Content-Type）
   - 返回文件流

3. **总体统计** (`getOverviewStatistics`):
   - 统计全平台的活动、报名、签到、评价总数
   - 计算全平台平均评分
   - 计算最近6个月的月度统计数据

**CSV导出工具类** (`CsvUtil.java`):

核心功能：
1. 生成UTF-8 BOM头（让Excel正确识别中文）
2. 写入表头（活动ID、活动名称、开始时间、结束时间、活动地点、报名人数上限、报名人数、签到人数、签到率、评价人数、平均评分、1星、2星、3星、4星、5星）
3. 写入数据行（转义特殊字符，处理逗号、引号、换行符）
4. 支持Excel直接打开

```java
// 写入BOM头，让Excel正确识别UTF-8编码
outputStream.write(0xEF);
outputStream.write(0xBB);
outputStream.write(0xBF);

// 写入表头
StringBuilder header = new StringBuilder();
header.append("活动ID,活动名称,开始时间,结束时间,活动地点,报名人数上限,报名人数,签到人数,签到率,评价人数,平均评分,1星,2星,3星,4星,5星");
outputStream.write(header.toString().getBytes(StandardCharsets.UTF_8));

// CSV转义处理
private String escapeCsv(String value) {
    if (value == null) return "";
    if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
        return "\"" + value.replace("\"", "\"\"") + "\"";
    }
    return value;
}
```

**视图对象**:

1. **ActivityStatisticsVO**: 活动统计数据视图对象
   - 活动ID、活动标题
   - 报名人数、签到人数、签到率
   - 评价人数、平均评分
   - 评分分布（Map<Integer, Long>）

2. **OverviewStatisticsVO**: 总体统计数据视图对象
   - 总活动数、总报名数、总签到数、总评价数
   - 平均评分
   - 月度统计列表（MonthlyStats内部类）

#### 2.2.4 技术亮点

1. **权限控制**: 使用 `@PreAuthorize("hasRole('ADMIN')")` 注解，确保只有管理员可以访问统计和导出功能
2. **性能优化**:
   - 使用流式处理（Stream）计算平均评分和评分分布
   - 一次性查询所有数据，避免多次数据库访问
3. **数据精度控制**:
   - 签到率保留两位小数
   - 平均评分保留一位小数
4. **CSV导出优化**:
   - 添加UTF-8 BOM头，解决Excel中文乱码问题
   - 实现CSV转义处理，正确处理包含逗号、引号、换行符的数据
   - 使用ByteArrayOutputStream提高性能
5. **月度统计算法**:
   - 动态计算最近6个月的起止时间
   - 使用DateTimeFormatter格式化月份
   - 支持跨年统计

---

## 三、答辩模拟

### 3.1 自我介绍

各位老师好，我是XXX，负责校园活动组织与报名系统的模块5.4（活动评分与评论模块）和模块5.5（数据统计与导出模块）的开发工作。

### 3.2 模块5.4：活动评分与评论模块

**老师提问**: 请介绍一下你负责的评分与评论模块的设计思路。

**我的回答**:

评分与评论模块的核心功能是让学生对已参加的活动进行评价。我在设计时考虑了以下几点：

1. **数据一致性**: 通过数据库唯一索引 `uk_user_activity` 确保每个学生对同一活动只能评价一次，防止重复评价。

2. **权限控制**: 只有签到过的学生才能评价，防止虚假评价。在 `ReviewServiceImpl.createReview` 方法中，我会先查询签到表，验证用户是否已签到该活动。

3. **数据验证**: 使用Jakarta Validation注解对评分和评论内容进行校验，评分必须在1-5分之间，评论内容不能超过500字符。

4. **分页查询**: 使用MyBatis-Plus的分页插件，支持活动评价列表和我的评价列表的分页查询，提高大数据量查询性能。

5. **关联查询优化**: 在 `ReviewMapper.xml` 中使用LEFT JOIN一次性获取用户和活动信息，避免N+1查询问题。

**老师提问**: 如何防止学生评价自己没有参加的活动？

**我的回答**:

在 `ReviewServiceImpl.createReview` 方法中，我会先查询签到表：

```java
CheckIn checkIn = checkInMapper.selectOne(
    new LambdaQueryWrapper<CheckIn>()
        .eq(CheckIn::getUserId, currentUser.getId())
        .eq(CheckIn::getActivityId, request.getActivityId())
);

if (checkIn == null) {
    throw new BusinessException(ResultCode.NOT_PARTICIPATED);
}
```

如果签到记录不存在，说明用户没有参加该活动，抛出业务异常，返回错误码 `NOT_PARTICIPATED`（您未参加该活动，无法评价）。

**老师提问**: 评分分布是如何计算的？

**我的回答**:

评分分布在统计模块中计算，使用Java Stream的 `Collectors.groupingBy` 方法：

```java
Map<Integer, Long> ratingDistribution = reviews.stream()
    .collect(Collectors.groupingBy(Review::getRating, Collectors.counting()));

for (int i = 1; i <= 5; i++) {
    ratingDistribution.putIfAbsent(i, 0L);
}
```

首先按评分分组统计，然后确保1-5星都有数据（没有的设为0），最后返回给前端展示。

### 3.3 模块5.5：数据统计与导出

**老师提问**: 请介绍一下统计模块的功能和实现方式。

**我的回答**:

统计模块提供三个核心功能：

1. **活动统计**: 统计单个活动的报名人数、签到人数、签到率、评价人数、平均评分和评分分布。

2. **数据导出**: 支持将活动统计数据导出为CSV格式，方便管理员进行数据分析。

3. **总体统计**: 统计全平台的活动、报名、签到、评价总数，以及最近6个月的月度趋势。

实现上，我使用了MyBatis-Plus的LambdaQueryWrapper进行条件查询，使用Java Stream进行数据聚合计算，确保查询效率和代码可读性。

**老师提问**: CSV导出时如何解决Excel中文乱码问题？

**我的回答**:

在 `CsvUtil.exportActivityData` 方法中，我添加了UTF-8 BOM头：

```java
// 写入BOM头，让Excel正确识别UTF-8编码
outputStream.write(0xEF);
outputStream.write(0xBB);
outputStream.write(0xBF);
```

BOM（Byte Order Mark）是UTF-8编码的特殊标记，Excel会自动识别BOM头，从而正确显示中文字符。

**老师提问**: 如果数据中包含逗号、引号或换行符，如何处理？

**我的回答**:

我实现了 `escapeCsv` 方法进行CSV转义处理：

```java
private String escapeCsv(String value) {
    if (value == null) return "";
    // 如果包含逗号、引号或换行符，需要用引号包裹并转义
    if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
        return "\"" + value.replace("\"", "\"\"") + "\"";
    }
    return value;
}
```

如果数据中包含逗号、引号或换行符，就用双引号包裹，并将原有的双引号替换为两个双引号（CSV标准转义方式）。

**老师提问**: 月度统计是如何计算的？

**我的回答**:

在 `calculateMonthlyStats` 方法中，我动态计算最近6个月的起止时间：

```java
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

for (int i = 5; i >= 0; i--) {
    LocalDateTime monthStart = now.minusMonths(i).withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0);
    LocalDateTime monthEnd = monthStart.plusMonths(1).minusSeconds(1);
    String monthKey = monthStart.format(formatter);
    
    // 统计该月的活动数和报名数
    Long activityCount = activityMapper.selectCount(
        new LambdaQueryWrapper<Activity>()
            .eq(Activity::getDeleted, 0)
            .between(Activity::getCreatedAt, monthStart, monthEnd)
    );
    
    Long registrationCount = registrationMapper.selectCount(
        new LambdaQueryWrapper<Registration>()
            .eq(Registration::getStatus, 1)
            .between(Registration::getCreatedAt, monthStart, monthEnd)
    );
    
    stats.add(OverviewStatisticsVO.MonthlyStats.builder()
        .month(monthKey)
        .activityCount(activityCount)
        .registrationCount(registrationCount)
        .build());
}
```

使用 `minusMonths` 方法计算过去6个月，使用 `withDayOfMonth(1)` 获取每月第一天，使用 `plusMonths(1).minusSeconds(1)` 获取每月最后一秒，然后统计该月创建的活动和报名数量。

### 3.4 技术难点与解决方案

**老师提问**: 在开发过程中遇到了哪些技术难点？你是如何解决的？

**我的回答**:

1. **CSV导出中文乱码问题**: 通过添加UTF-8 BOM头解决，让Excel正确识别中文字符。

2. **CSV转义问题**: 实现了 `escapeCsv` 方法，正确处理包含逗号、引号、换行符的数据，符合CSV标准。

3. **评分分布计算**: 使用Java Stream的 `groupingBy` 方法进行分组统计，确保代码简洁高效。

4. **月度统计跨年问题**: 使用 `DateTimeFormatter` 格式化月份，支持跨年统计（如2025-12到2026-01）。

5. **数据精度控制**: 使用 `Math.round` 方法保留指定小数位数，确保签到率保留两位小数，平均评分保留一位小数。

### 3.5 总结

**老师提问**: 总结一下你在项目中的收获。

**我的回答**:

通过参与校园活动组织与报名系统的开发，我收获了很多：

1. **技术能力提升**: 熟练掌握了Spring Boot、MyBatis-Plus、Spring Security等框架的使用，深入理解了分层架构设计。

2. **业务理解能力**: 通过需求分析和数据库设计，提升了业务理解和抽象能力。

3. **问题解决能力**: 在开发过程中遇到了CSV导出、数据统计等技术难点，通过查阅文档和调试，成功解决了这些问题。

4. **团队协作能力**: 与团队成员密切配合，共同完成了系统的开发和测试工作。

5. **文档编写能力**: 编写了详细的API文档和答辩文档，提升了文档编写能力。

这次项目开发让我对软件工程有了更深入的理解，也为我今后的学习和工作打下了坚实的基础。

---

## 四、项目演示

### 4.1 API文档访问

系统使用Knife4j生成API文档，访问地址：`http://localhost:8080/doc.html`

### 4.2 模块5.4 API接口

1. **提交评价**
   - 接口: `POST /api/v1/reviews`
   - 权限: 需要认证
   - 请求体:
   ```json
   {
     "activityId": 1,
     "rating": 5,
     "content": "非常精彩的活动！"
   }
   ```

2. **获取活动评价列表**
   - 接口: `GET /api/v1/reviews/activity/{activityId}`
   - 权限: 公开
   - 参数: current, size

3. **获取我的评价列表**
   - 接口: `GET /api/v1/reviews/my`
   - 权限: 需要认证
   - 参数: current, size

### 4.3 模块5.5 API接口

1. **获取活动统计数据**
   - 接口: `GET /api/v1/statistics/activity/{activityId}`
   - 权限: 管理员

2. **导出活动数据**
   - 接口: `GET /api/v1/statistics/activity/{activityId}/export`
   - 权限: 管理员
   - 参数: format (csv)

3. **获取总体统计**
   - 接口: `GET /api/v1/statistics/overview`
   - 权限: 管理员

---

## 五、数据库表结构

### 5.1 评价表 (review)

| 字段名 | 类型 | 约束 | 说明 |
|--------|------|------|------|
| id | BIGINT | PK, AUTO_INCREMENT | 评价ID |
| user_id | BIGINT | FK, NOT NULL | 用户ID |
| activity_id | BIGINT | FK, NOT NULL | 活动ID |
| rating | TINYINT | NOT NULL | 评分（1-5） |
| content | TEXT | | 评论内容 |
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | 评价时间 |
| updated_at | DATETIME | ON UPDATE CURRENT_TIMESTAMP | 更新时间 |

**索引**:
- `uk_user_activity` (user_id, activity_id) UNIQUE - 确保每个学生对同一活动只能评价一次
- `idx_activity_id` (activity_id)

### 5.2 关联表

- **user**: 用户表
- **activity**: 活动表
- **registration**: 报名表
- **check_in**: 签到表

---

## 六、核心代码位置

### 6.1 模块5.4（评价模块）

- Controller: `src/main/java/com/campus/activity/controller/ReviewController.java`
- Service接口: `src/main/java/com/campus/activity/service/ReviewService.java`
- Service实现: `src/main/java/com/campus/activity/service/impl/ReviewServiceImpl.java`
- Mapper接口: `src/main/java/com/campus/activity/mapper/ReviewMapper.java`
- Mapper XML: `src/main/resources/mapper/ReviewMapper.xml`
- Entity: `src/main/java/com/campus/activity/entity/Review.java`
- VO: `src/main/java/com/campus/activity/vo/ReviewVO.java`
- Request DTO: `src/main/java/com/campus/activity/dto/request/ReviewRequest.java`

### 6.2 模块5.5（统计模块）

- Controller: `src/main/java/com/campus/activity/controller/StatisticsController.java`
- Service接口: `src/main/java/com/campus/activity/service/StatisticsService.java`
- Service实现: `src/main/java/com/campus/activity/service/impl/StatisticsServiceImpl.java`
- VO: `src/main/java/com/campus/activity/vo/ActivityStatisticsVO.java`
- VO: `src/main/java/com/campus/activity/vo/OverviewStatisticsVO.java`
- Util: `src/main/java/com/campus/activity/util/CsvUtil.java`

---

## 七、测试建议

### 7.1 评价模块测试

1. **正常评价**: 学生对已参加的活动进行评价，验证评价成功
2. **重复评价**: 同一学生对同一活动再次评价，验证返回错误
3. **未参加评价**: 学生对未参加的活动进行评价，验证返回错误
4. **评分边界测试**: 测试评分为1和5的情况
5. **评论长度测试**: 测试评论内容超过500字符的情况
6. **分页查询**: 测试活动评价列表和我的评价列表的分页功能

### 7.2 统计模块测试

1. **活动统计**: 验证报名人数、签到人数、签到率、平均评分计算正确
2. **评分分布**: 验证1-5星分布统计正确
3. **数据导出**: 验证CSV文件生成正确，Excel可以打开
4. **中文乱码**: 验证CSV文件中文显示正常
5. **总体统计**: 验证全平台统计数据正确
6. **月度统计**: 验证最近6个月统计数据正确，支持跨年

---

## 八、总结

本次答辩文档详细介绍了校园活动组织与报名系统的整体框架结构，以及我负责的模块5.4（活动评分与评论模块）和模块5.5（数据统计与导出模块）的设计与实现。

在开发过程中，我深入理解了Spring Boot、MyBatis-Plus、Spring Security等框架的使用，掌握了分层架构设计、数据验证、权限控制、CSV导出等技术，提升了自己的技术能力和问题解决能力。

通过本次项目开发，我对软件工程有了更深入的理解，也为我今后的学习和工作打下了坚实的基础。

谢谢各位老师！