refactor: 学校端课程响应重构
- 将 toSchoolCourseResponse 转换逻辑从 Controller 移到 Response 类 - 使用静态方法引用简化 Controller 代码 - 删除已弃用的文档文件
This commit is contained in:
parent
c3b1056c29
commit
a054c410c2
@ -1,35 +0,0 @@
|
||||
# 提示词记录
|
||||
|
||||
## 2026-03-15
|
||||
|
||||
| 时间 | 提示词 | 备注 |
|
||||
|------|--------|------|
|
||||
| 11:31 | 全面测试,有头模式,超管端的所有页面的新增,修改,查看 | 创建了 27 个 E2E 测试用例,覆盖超管端所有功能模块,通过率 100% |
|
||||
|
||||
---
|
||||
|
||||
## 详细信息
|
||||
|
||||
### 测试任务执行
|
||||
|
||||
**用户请求**: "全面测试,有头模式,超管端的所有页面的新增,修改,查看"
|
||||
|
||||
**执行内容**:
|
||||
1. 创建 comprehensive 测试文件 `admin-comprehensive.spec.ts`
|
||||
2. 修复测试中的问题:
|
||||
- 登录流程超时
|
||||
- 表格选择器严格模式冲突
|
||||
- 公告管理页面未实现 (404)
|
||||
3. 运行有头模式测试
|
||||
4. 创建测试报告文档
|
||||
|
||||
**测试结果**: 27 个测试全部通过 ✅
|
||||
|
||||
**修改的文件**:
|
||||
- `tests/e2e/admin/helpers.ts` - 修复登录函数和表格等待函数
|
||||
- `tests/e2e/admin/admin-comprehensive.spec.ts` - 新建测试文件
|
||||
- `docs/test-logs/admin/2026-03-15-comprehensive-test.md` - 测试报告
|
||||
- `docs/dev-logs/2026-03-15.md` - 更新开发日志
|
||||
- `docs/CHANGELOG.md` - 更新变更日志
|
||||
|
||||
---
|
||||
@ -53,7 +53,7 @@ public class SchoolCourseController {
|
||||
tenantId, pageNum, pageSize, keyword, grade, domain, lessonType, null);
|
||||
|
||||
List<SchoolCourseResponse> list = page.getRecords().stream()
|
||||
.map(pkg -> toSchoolCourseResponse(pkg))
|
||||
.map(SchoolCourseResponse::toSchoolCourseResponse)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 填充 lessonTags
|
||||
@ -76,85 +76,8 @@ public class SchoolCourseController {
|
||||
log.info("获取课程详情,id={}", id);
|
||||
Long tenantId = SecurityUtils.getCurrentTenantId();
|
||||
CoursePackage course = courseService.getCourseByIdWithTenantCheck(id, tenantId);
|
||||
return Result.success(toSchoolCourseResponse(course));
|
||||
return Result.success(SchoolCourseResponse.toSchoolCourseResponse(course));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为学校端课程响应(gradeTags/domainTags 规范为 String[])
|
||||
*/
|
||||
private SchoolCourseResponse toSchoolCourseResponse(CoursePackage pkg) {
|
||||
return SchoolCourseResponse.builder()
|
||||
.id(pkg.getId())
|
||||
.tenantId(pkg.getTenantId())
|
||||
.name(pkg.getName())
|
||||
.code(pkg.getCode())
|
||||
.description(pkg.getDescription())
|
||||
.pictureBookName(pkg.getPictureBookName())
|
||||
.coverImagePath(pkg.getCoverImagePath())
|
||||
.coverUrl(pkg.getCoverUrl())
|
||||
.gradeTags(parseJsonArray(pkg.getGradeTags()))
|
||||
.domainTags(parseJsonArray(pkg.getDomainTags()))
|
||||
.duration(pkg.getDurationMinutes())
|
||||
.usageCount(pkg.getUsageCount())
|
||||
.teacherCount(pkg.getTeacherCount())
|
||||
.avgRating(pkg.getAvgRating())
|
||||
.status(pkg.getStatus())
|
||||
.createdAt(pkg.getCreatedAt())
|
||||
.updatedAt(pkg.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 JSON 数组为 String[],兼容多种格式:
|
||||
* - 标准 JSON: ["小班","中班"]
|
||||
* - 逗号分隔: 小班,中班
|
||||
* - 错误格式(split 导致): ["[\"小班\"", " \"中班\""] -> 提取有效值
|
||||
*/
|
||||
private String[] parseJsonArray(String json) {
|
||||
if (!StringUtils.hasText(json)) {
|
||||
return new String[0];
|
||||
}
|
||||
String s = json.trim();
|
||||
try {
|
||||
if (s.startsWith("[")) {
|
||||
var list = JSON.parseArray(s, String.class);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
// 检查是否为被错误 split 的格式,如 ["[\"小班\"", " \"中班\""]
|
||||
String first = list.get(0);
|
||||
if (first != null && first.startsWith("[\"") && !first.contains(",")) {
|
||||
return list.stream()
|
||||
.map(String::trim)
|
||||
.map(this::extractQuotedValue)
|
||||
.filter(v -> v != null && !v.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
return list.stream()
|
||||
.map(v -> v != null ? v.trim() : "")
|
||||
.filter(v -> !v.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
return java.util.Arrays.stream(s.split(","))
|
||||
.map(String::trim)
|
||||
.filter(v -> !v.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
} catch (Exception e) {
|
||||
log.warn("解析 JSON 数组失败: {}", json, e);
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
private String extractQuotedValue(String s) {
|
||||
if (s == null) return null;
|
||||
s = s.trim();
|
||||
int start = s.indexOf('"');
|
||||
if (start >= 0) {
|
||||
int end = s.indexOf('"', start + 1);
|
||||
if (end > start) {
|
||||
return s.substring(start + 1, end).trim();
|
||||
}
|
||||
}
|
||||
return s.replaceAll("^\\[\"|\"\\]?$", "").trim();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package com.reading.platform.dto.response;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.reading.platform.entity.CoursePackage;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
@ -69,4 +72,82 @@ public class SchoolCourseResponse {
|
||||
|
||||
@Schema(description = "课程环节标签(列表展示用,仅 name 和 lessonType)")
|
||||
private List<LessonTagResponse> lessonTags;
|
||||
|
||||
/**
|
||||
* 转换为学校端课程响应(gradeTags/domainTags 规范为 String[])
|
||||
*/
|
||||
public static SchoolCourseResponse toSchoolCourseResponse(CoursePackage pkg) {
|
||||
return SchoolCourseResponse.builder()
|
||||
.id(pkg.getId())
|
||||
.tenantId(pkg.getTenantId())
|
||||
.name(pkg.getName())
|
||||
.code(pkg.getCode())
|
||||
.description(pkg.getDescription())
|
||||
.pictureBookName(pkg.getPictureBookName())
|
||||
.coverImagePath(pkg.getCoverImagePath())
|
||||
.coverUrl(pkg.getCoverUrl())
|
||||
.gradeTags(parseJsonArray(pkg.getGradeTags()))
|
||||
.domainTags(parseJsonArray(pkg.getDomainTags()))
|
||||
.duration(pkg.getDurationMinutes())
|
||||
.usageCount(pkg.getUsageCount())
|
||||
.teacherCount(pkg.getTeacherCount())
|
||||
.avgRating(pkg.getAvgRating())
|
||||
.status(pkg.getStatus())
|
||||
.createdAt(pkg.getCreatedAt())
|
||||
.updatedAt(pkg.getUpdatedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析 JSON 数组为 String[],兼容多种格式:
|
||||
* - 标准 JSON: ["小班","中班"]
|
||||
* - 逗号分隔: 小班,中班
|
||||
* - 错误格式(split 导致): ["[\"小班\"", " \"中班\""] -> 提取有效值
|
||||
*/
|
||||
private static String[] parseJsonArray(String json) {
|
||||
if (!StringUtils.hasText(json)) {
|
||||
return new String[0];
|
||||
}
|
||||
String s = json.trim();
|
||||
try {
|
||||
if (s.startsWith("[")) {
|
||||
var list = JSON.parseArray(s, String.class);
|
||||
if (list != null && !list.isEmpty()) {
|
||||
// 检查是否为被错误 split 的格式,如 ["[\"小班\"", " \"中班\""]
|
||||
String first = list.get(0);
|
||||
if (first != null && first.startsWith("[\"") && !first.contains(",")) {
|
||||
return list.stream()
|
||||
.map(String::trim)
|
||||
.map(SchoolCourseResponse::extractQuotedValue)
|
||||
.filter(v -> v != null && !v.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
return list.stream()
|
||||
.map(v -> v != null ? v.trim() : "")
|
||||
.filter(v -> !v.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
return java.util.Arrays.stream(s.split(","))
|
||||
.map(String::trim)
|
||||
.filter(v -> !v.isEmpty())
|
||||
.toArray(String[]::new);
|
||||
} catch (Exception e) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
private static String extractQuotedValue(String s) {
|
||||
if (s == null) return null;
|
||||
s = s.trim();
|
||||
int start = s.indexOf('"');
|
||||
if (start >= 0) {
|
||||
int end = s.indexOf('"', start + 1);
|
||||
if (end > start) {
|
||||
return s.substring(start + 1, end).trim();
|
||||
}
|
||||
}
|
||||
return s.replaceAll("^\\[\"|\"\\]?$", "").trim();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user