# 游客模式问题最终诊断 - 2026-02-01 ## 问题现状 游客模式下,以下三个页面仍然无法显示数据: 1. 选择陪伴员页面 (`/api/teacher/list`) 2. 兴趣培养页面 (`/api/interest-course/list`) 3. 专项突破页面 (`/api/special-course/list`) ## 后端代码检查结果 ### ✅ TeacherController.java **接口**: `GET /api/teacher/list` **代码分析**: ```java @GetMapping("/list") public Result> getTeacherList( @RequestParam(required = false) String keyword, @RequestParam(required = false) String teacherName, // ... 其他参数 @RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size) { // ✅ 没有使用 userId 参数 // ✅ 没有从 HttpServletRequest 获取 userId // ✅ 直接调用 Service 查询数据 Page result = teacherService.getTeacherList(...); return Result.success((Page) result); } ``` **结论**: ✅ 这个接口**不需要登录**,应该可以正常返回数据 ### ✅ InterestCourseController.java **接口**: `GET /api/interest-course/list` **代码分析**: ```java @GetMapping("/list") public Result> getCourseList( @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String keyword, @RequestParam(required = false) String category) { // ✅ 没有使用 userId 参数 // ✅ 没有从 HttpServletRequest 获取 userId // ✅ 直接调用 Service 查询数据 Page page = interestCourseService.getCourseList(...); return Result.success(page); } ``` **结论**: ✅ 这个接口**不需要登录**,应该可以正常返回数据 ### ✅ SpecialCourseController.java **接口**: `GET /api/special-course/list` **代码分析**: ```java @GetMapping("/list") public Result> getCourseList( @RequestParam(required = false) String category, @RequestParam(required = false) String subCategory, // ... 其他参数 @RequestParam(required = false) String sortBy) { // ✅ 没有使用 userId 参数 // ✅ 没有从 HttpServletRequest 获取 userId // ✅ 直接调用 Service 查询数据 List list = specialCourseService.list(wrapper); return Result.success(list); } ``` **结论**: ✅ 这个接口**不需要登录**,应该可以正常返回数据 ## JWT拦截器检查 **文件**: `JwtInterceptor.java` **当前逻辑**: ```java // ✅ 如果没有token,不抛出异常,直接放行 if (!StringUtils.hasText(token)) { System.out.println("token为空,放行请求"); return true; } ``` **结论**: ✅ JWT拦截器已经修改为放行无token请求 ## WebMvcConfig检查 **文件**: `WebMvcConfig.java` **排除路径配置**: ```java .excludePathPatterns( "/api/teacher/list", // ✅ 已排除 "/api/teacher/detail/**", // ✅ 已排除 "/api/teacher/filter-options", // ✅ 已排除 "/api/special/**", // ✅ 已排除(包含 /api/special-course/list) "/api/interest/**", // ✅ 已排除(包含 /api/interest-course/list) // ... ) ``` **结论**: ✅ 这三个接口都已经在排除列表中 ## 前端请求配置检查 **文件**: `request.js` **游客白名单**: ```javascript const GUEST_ALLOWED_URLS = [ '/api/teacher/list', // ✅ 已添加 '/api/teacher/filter-options', // ✅ 已添加 '/api/special-course/list', // ✅ 已添加 '/api/interest-course/list', // ❌ 可能缺少这个 // ... ] ``` **游客模式处理**: ```javascript // ✅ 游客访问白名单接口时不发送token if (isGuest && isGuestAllowedUrl(options.url)) { console.log('[Request] 游客模式,白名单接口返回401,静默失败'); reject({ code: 401, message: '未登录', silent: true }); return } ``` ## 可能的问题点 ### 问题1: 前端白名单可能不完整 **检查**: `request.js` 中的 `GUEST_ALLOWED_URLS` 是否包含: - ✅ `/api/teacher/list` - ❓ `/api/interest-course/list` (可能缺少) - ❓ `/api/special-course/list` (可能缺少) ### 问题2: 前端URL匹配逻辑 **当前匹配逻辑**: ```javascript function isGuestAllowedUrl(url) { return GUEST_ALLOWED_URLS.some(allowedUrl => url.includes(allowedUrl)) } ``` **问题**: 使用 `includes` 可能导致匹配不准确 **示例**: - URL: `/api/interest-course/list?page=1&size=10` - 白名单: `/api/interest-course/list` - 匹配结果: ✅ 应该匹配成功 ### 问题3: 前端实际发送的URL **需要确认**: - 前端实际发送的URL是什么? - 是否包含查询参数? - 是否与白名单中的URL匹配? ### 问题4: 后端实际返回的错误 **需要确认**: - 后端是否真的返回401错误? - 还是返回其他错误(如500、404)? - 错误消息是什么? ## 诊断步骤 ### 步骤1: 检查前端白名单 打开 `peidu/uniapp/src/utils/request.js`,检查 `GUEST_ALLOWED_URLS` 数组: ```javascript const GUEST_ALLOWED_URLS = [ '/api/teacher/list', // ✅ 必须有 '/api/teacher/filter-options', // ✅ 必须有 '/api/interest-course/list', // ❓ 检查是否存在 '/api/special-course/list', // ❓ 检查是否存在 // ... ] ``` ### 步骤2: 检查前端控制台 在微信开发者工具的控制台中查看: **正常日志**: ``` [Request] 当前环境: 生产环境 [Request] BASE_URL: https://px.ddn-ai.cloud [Request] GET URL: https://px.ddn-ai.cloud/api/teacher/list?page=1&size=10 [Request] 游客模式,白名单接口返回401,静默失败: /api/teacher/list ``` **异常日志**: ``` [Request] 401 未登录 登录已过期,请重新登录 ``` ### 步骤3: 检查Network请求 在微信开发者工具的Network标签中查看: **请求信息**: - URL: 完整的请求URL - Method: GET - Headers: 是否包含 Authorization - Status: 实际返回的状态码 **响应信息**: - Status Code: 200? 401? 500? - Response Body: 实际返回的数据 ### 步骤4: 检查后端日志 在后端控制台中查看: **正常日志**: ``` === JWT拦截器执行 === 请求路径: /api/teacher/list Authorization Header: null token为空,放行请求 === JWT拦截器执行完成 === ``` **异常日志**: ``` === JWT拦截器执行 === 请求路径: /api/teacher/list Authorization Header: null token验证失败,抛出过期异常 ``` ## 下一步行动 ### 方案1: 检查前端白名单(最可能) 如果 `GUEST_ALLOWED_URLS` 中缺少这两个URL: - `/api/interest-course/list` - `/api/special-course/list` **修复**: 添加这两个URL到白名单 ### 方案2: 检查前端URL匹配逻辑 如果URL匹配逻辑有问题: **修复**: 改进匹配逻辑,使用更精确的匹配方式 ### 方案3: 检查后端Service层 如果Controller没问题,可能是Service层有问题: **检查**: - `TeacherService.getTeacherList()` - `InterestCourseService.getCourseList()` - `SpecialCourseService.list()` ### 方案4: 检查数据库数据 如果Service没问题,可能是数据库没有数据: **检查**: ```sql -- 检查教师数据 SELECT COUNT(*) FROM teacher WHERE deleted = 0; -- 检查兴趣课程数据 SELECT COUNT(*) FROM interest_course WHERE status = 1; -- 检查专项课程数据 SELECT COUNT(*) FROM special_course WHERE status = 1; ``` ## 总结 根据代码检查,后端的三个Controller都**不需要userId参数**,应该可以正常返回数据。 **最可能的问题**: 1. ❓ 前端白名单不完整(缺少 `/api/interest-course/list` 和 `/api/special-course/list`) 2. ❓ 前端URL匹配逻辑有问题 3. ❓ 数据库中没有数据 **建议**: 先检查前端的 `request.js` 文件,确认白名单是否完整。