修改bug
This commit is contained in:
171
docs/功能缺陷审查报告.md
Normal file
171
docs/功能缺陷审查报告.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# 汪圈小程序 — 功能逻辑缺陷审查报告
|
||||
|
||||
> 审查日期:2026-06-18
|
||||
> 审查范围:全部 10 个页面、10 个 Service、23 个云函数、3 个类型文件、关键组件
|
||||
> 审查分支:`master`
|
||||
|
||||
---
|
||||
|
||||
## 一、广场页 `pages/plaza/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **Feed 无分页 / 无限滚动** | 🔴 高 | `loadFeed()` (L34-38) | `getFeedList` 云函数返回 `CursorResponse<T>` 含 `nextCursor` 分页字段,但页面完全没有使用分页机制。只加载第一页数据,用户无法浏览更多帖子。Feed 是社交应用的核心功能,此为致命缺陷。 |
|
||||
| 2 | **话题列表硬编码** | 🟡 中 | `topics` (L24) | `['全部', '滨江公园', '金毛日常', ...]` 写死在组件中,不会从云端动态获取热门话题,运营新增的话题无法展示。 |
|
||||
| 3 | **广告卡片位置固定** | 🟡 中 | `PostCard` 渲染逻辑 (L130-133) | `FeedAdCard` 写死在 `index === 0` 的位置。每次 `loadFeed` 刷新后数据重置,广告位置永远在第一条帖子后,缺乏真实广告系统的随机插入和频次控制。 |
|
||||
| 4 | **收藏功能存在但入口缺失** | 🟡 中 | `PostCard` + `PlazaPage` | `feed.service.ts` 导出了 `setPostLike` / `setPostFavorite`,`Post` 类型有 `favoritedByMe` 字段,但 `PostCard` 和 `PlazaPage` 均没有收藏操作的 UI 入口,收藏功能全链路断裂。 |
|
||||
| 5 | **没有帖子详情页** | 🟡 中 | `commentPost()` (L86-113) | 评论通过 `Taro.showModal` 弹窗实现,无法查看评论列表、历史记录,也无法点击图片查看大图预览。社交类帖子的完整交互(评论链、转发、分享)均缺失。 |
|
||||
| 6 | **点赞乐观更新存在竞态** | 🟡 中 | `likePost()` (L54-84) | 连续两次 `setPosts`(乐观更新 → 服务端返回覆盖),期间若 `useDidShow` 触发 `loadFeed`,可能覆盖掉刚点赞的中间状态。应考虑用 `postId` 粒度的状态管理或防抖。 |
|
||||
| 7 | **搜索栏无功能** | 🟡 中 | `<SearchBar>` (L118) | `SearchBar` 组件已渲染但没有绑定 `onInput` / `onSubmit` 回调,搜索框为纯装饰。 |
|
||||
|
||||
---
|
||||
|
||||
## 二、附近页 `pages/nearby/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **没有调用 `updateLocation` 上报自身位置** | 🔴 高 | 整个页面 | `nearby.service.ts` 导出了 `updateLocation(location, visible)`,用户位置变化**从未上报云端**。其他用户看不到"我"在附近地图上出现,双向发现功能完全失效。应在获取到位置后调用上报,并在 relocate 时重复上报。 |
|
||||
| 2 | **没有尊重 `preferences.nearbyVisible` 偏好** | 🔴 高 | 整个页面 | 用户在个人资料中可关闭"附近可见"(`preferences.nearbyVisible`),但附近页完全不考虑此设置。即使关闭,仍请求并展示附近宠物,自身位置也没有根据偏好控制是否上报。应在 `useEffect` 中读取偏好,决定是否请求附近数据。 |
|
||||
| 3 | **`likePet` 没有乐观更新和错误回滚** | 🟡 中 | `likePet()` (L89-92) | 只调用了 `likeNearbyPet(id)`,没有先更新 UI 状态(不像 `PlazaPage.likePost` 做了乐观更新 + 回滚)。网络慢时用户看不到反馈,快速点击可能重复请求。 |
|
||||
| 4 | **`filter: 'online'` 后端过滤能力不确定** | 🟡 中 | `loadPets()` (L41-46) | 前端传 `{ type: 'online' }`,但 `nearbyPets` 云函数是否支持此过滤逻辑取决于后端实现。如果后端不识别此 filter,返回的数据未做二次前端过滤,展示可能不准确。 |
|
||||
| 5 | **搜索仅前端过滤** | 🟡 中 | `visiblePets` (L139-142) | 只按 `name` 和 `breed` 过滤,不支持按距离排序或更丰富的筛选组合。筛选器仅有 all/dog/cat/online 四种,缺少按距离、年龄段、标签等维度。 |
|
||||
|
||||
---
|
||||
|
||||
## 三、发布页 `pages/publish/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **没有恢复草稿的逻辑** | 🔴 高 | `useEffect` (L44-50) | `publish.service.ts` 导出了 `getDraft()`,但发布页 `mount` 时**从未调用它**。用户保存的草稿在下次进入发布页时不会被恢复。应添加逻辑:进入时检测未提交内容 → 提示恢复草稿 → 调用 `getDraft()` 回填表单。 |
|
||||
| 2 | **没有内容字数上限预警** | 🟡 中 | `ComposerToolbar` `count` prop | `isValidPostContent` 限制 1–2000 字,但 `content.length` 仅展示数字,没有在接近上限(如 >1800 字)时给出警告样式或禁用输入。 |
|
||||
| 3 | **图片上传失败静默跳过** | 🟡 中 | `uploadPostMedia()` (`publish.service.ts` L24-38) | 单张图片上传失败时 `catch` 返回原 `item`,用户不知道哪张图没上传成功。帖子可能携带本地临时路径 `wxfile://...` 发布,其他用户无法查看。应在 UI 上展示上传失败提示。 |
|
||||
| 4 | **返回没有未保存提示** | 🟡 中 | 关闭按钮 (L148-150) | 点击 `navigateBack()` 直接返回,如果用户已输入内容但未发布,不会提醒"是否保存为草稿"。应检测 `hasContent`,有内容时弹窗确认。 |
|
||||
|
||||
---
|
||||
|
||||
## 四、消息页 `pages/messages/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **`markConversationRead` 是 fire-and-forget** | 🟡 中 | `openConversation()` (L48-54) | 调用了 `markConversationRead` 但没有 `await`,且 `openConversation` 是 `async` 函数却没有 `try-catch`。如果 `navigateTo` 失败(如页面栈满),异常不会被捕获。 |
|
||||
| 2 | **没有区分 single / system 会话交互** | 🟡 中 | `openConversation()` (L48-54) | `Conversation` 有 `type: 'single' \| 'system'`,系统消息(如"汪圈小助手")不应有"发起聊天"行为,但 UI 上没有区分处理——点击系统消息也会跳转到 chat 页面。 |
|
||||
| 3 | **没有消息通知 / 推送机制** | 🟡 中 | 整个页面 | 没有接入微信订阅消息或任何推送通知机制。`preferences.notifications` 偏好存在但无实际功能接入,用户即使打开通知设置也不会收到新消息提醒。 |
|
||||
| 4 | **搜索不会过滤 activeUsers** | 🟡 中 | `kw` 过滤逻辑 (L64-69) | 搜索只过滤 `conversations`,不搜索 `activeUsers`。有搜索关键词时 `activeUsers` 被隐藏(`kw ? null : <ActiveUserRow>`),但清空搜索后立即恢复,交互上不连贯。 |
|
||||
|
||||
---
|
||||
|
||||
## 五、聊天页 `pages/chat/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **消息列表没有分页加载历史** | 🔴 高 | `load()` (L26-35) | 只调用一次 `getThread()` 获取当前消息,没有向上滚动加载更早消息的机制。长时间对话的历史消息无法查看。应实现 `ScrollView` 到顶触发加载上一页。 |
|
||||
| 2 | **轮询频率固定 5 秒,无智能调节** | 🟡 中 | `useDidShow` (L43-45) | 不管页面是否在前台活跃、消息密度如何,都固定 5 秒轮询一次。高频轮询消耗资源,低频则延迟高。对于聊天场景,建议使用 WebSocket 或根据消息活跃度动态调整轮询间隔。 |
|
||||
| 3 | **发送失败时输入框闪空** | 🟡 中 | `send()` (L53-71) | 发送时先 `setDraft('')` 清空输入框,失败后 `setDraft(text)` 恢复。在发送到失败的间隙,输入框会先空再恢复,视觉闪烁。建议先不清空,成功后再清空。 |
|
||||
| 4 | **没有消息发送状态指示** | 🟡 中 | 聊天气泡 UI (L92-103) | `sending` 状态变量存在但没有用在 UI 上。用户发送消息后没有 loading / 发送中指示器,不知道消息是否正在发送。 |
|
||||
| 5 | **`scrollTop` 递增 hack 不可靠** | 🟡 中 | `setScrollTop(prev => prev + 100000)` (L34) | 通过不断递增 `scrollTop` 强制滚动到底部。`Number.MAX_SAFE_INTEGER` 为 `9007199254740991`,每次 +100000 约可调用 9×10¹⁰ 次才溢出——虽然实际不太可能触发,但设计上应改用 ref 记录并 toggle 一个标志位。 |
|
||||
| 6 | **不支持图片 / 表情消息** | 🟡 中 | 输入栏 UI (L108-119) | 只支持纯文本输入,没有图片、表情等富媒体消息功能。`ChatMessage.type` 字段存在但没有被使用,输入区域也没有附件按钮。 |
|
||||
|
||||
---
|
||||
|
||||
## 六、个人资料页 `pages/profile/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **偏好 `changePreference` 无错误回滚** | 🟡 中 | `changePreference()` (L92-102) | 先乐观更新 UI 再 `await updateProfile`,但整个函数没有 `try-catch`。如果云端更新失败,UI 状态已改但数据未持久化,下次加载会回滚,造成用户困惑(以为保存了但实际没有)。 |
|
||||
| 2 | **"关于"功能是空壳** | 🟢 低 | `handleAction('about')` (L89) | 只弹 `toast: '敬请期待新功能'`。MVP 阶段可接受,但应在版本规划中补充。 |
|
||||
|
||||
---
|
||||
|
||||
## 七、资料编辑页 `pages/profile-edit/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **`type='nickname'` 仅真机生效** | 🟡 中 | `<Input type='nickname'>` (L116) | `type='nickname'` 是微信小程序获取微信昵称的特殊能力,仅在真机上有效。H5 预览 / 开发工具中用户可手动输入任意昵称(绕过微信身份验证)。应在非真机环境增加校验提示。 |
|
||||
| 2 | **`avatarUrl` 与 `avatarKey` 共存冲突** | 🟡 中 | `submit()` (L56-82) | 编辑后 `uploadAvatar` 返回 `fileID` 赋给 `patch.avatarUrl`,但 `avatarKey` 没有被更新或清除。如果 `Avatar` 组件优先读 `avatarUrl`,则 `avatarKey` 多余;若优先读 `avatarKey`,可能显示旧头像。需要明确两者的优先级关系。 |
|
||||
| 3 | **没有未保存离开提示** | 🟡 中 | 关闭按钮 (L88-90) | 直接 `navigateBack()` 没有检测是否有未保存修改。应比较当前表单值与初始值的差异,有差异时弹窗确认。 |
|
||||
|
||||
---
|
||||
|
||||
## 八、宠物编辑页 `pages/pet-edit/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **没有宠物数量上限限制** | 🟡 中 | `submit()` (L132-168) | 没有检查用户已添加的宠物数量。用户可以无限添加宠物,可能导致数据膨胀。建议在后端限制(如最多 5 只),前端也做预检提示。 |
|
||||
| 2 | **照片隐式非必填但交互暗示必填** | 🟡 中 | `choosePhoto()` + 验证逻辑 | 提交验证只检查 `name` 和 `breed`,无照片也能保存。但展示逻辑依赖 `photoKey` 的兜底图,用户可能以为照片是必须的。建议明确标注照片为"可选",或在空照片时展示更友好的占位。 |
|
||||
|
||||
---
|
||||
|
||||
## 九、联系人页 `pages/contacts/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **"发现"搜索需手动提交,不支持实时搜索** | 🟡 中 | `<Input onConfirm>` (L101-102) | 搜索需要点击键盘"搜索"按钮才触发 (`onConfirm`),没有 `onInput` 实时触发搜索。对于"发现陌生人"场景,用户期望输入即搜索,应增加防抖实时搜索。 |
|
||||
| 2 | **点击用户只能发起聊天,无个人主页入口** | 🟡 中 | `openChat()` (L63-67) | 点击用户头像/名称只能跳转到聊天页,没有查看对方个人主页(宠物列表、帖子等)的选项。用户想了解对方更多信息需要退出再找,交互断裂。 |
|
||||
| 3 | **互关后 `isFriend` 未即时更新** | 🟡 中 | `onFollow()` (L51-61) | `toggleFollow` 返回 `{ mutual }` 但只更新了 `isFollowing`,没有同步更新 `isFriend`。互关后列表中不会立即显示"汪友"标签,需手动刷新页面才能看到。 |
|
||||
|
||||
---
|
||||
|
||||
## 十、我的动态页 `pages/my-posts/index.tsx`
|
||||
|
||||
| # | 缺陷 | 严重程度 | 位置 | 说明 |
|
||||
|---|------|----------|------|------|
|
||||
| 1 | **没有分页加载** | 🔴 高 | `load()` (L19-23) | 只加载一次 `getUserPosts()`,没有翻页。如果用户帖子很多,无法查看全部历史帖子。应实现 `ScrollView` 到底触发加载下一页。 |
|
||||
| 2 | **`useDidShow` 首次触发导致重复加载** | 🔴 高 | `useDidShow(load)` (L31) | `useDidShow` 没有用 `firstShow` ref 跳过首次加载(对比 `PlazaPage` 和 `MessagesPage` 有此保护),首次进入页面时 `load()` 会被调用**两次**(`useEffect` + `useDidShow`),浪费一次网络请求。 |
|
||||
| 3 | **`likePost` 没有错误回滚** | 🟡 中 | `likePost()` (L33-47) | 乐观更新后调用 `setPostLike`,但如果失败不会回滚到之前的状态。对比 `PlazaPage.likePost` 有 `previousPosts` 回滚逻辑,此处遗漏了。 |
|
||||
|
||||
---
|
||||
|
||||
## 十一、跨页面系统性问题
|
||||
|
||||
| # | 问题 | 影响范围 | 说明 |
|
||||
|---|------|----------|------|
|
||||
| 1 | **全应用没有全局登录态守卫** | 所有页面 | 所有 service 通过 `canUseCloud()` 判断是否可用,但没有统一的"未登录则拦截/跳转"逻辑。只有 `ProfilePage` 单独处理了登录态,其他页面(广场、附近、消息、发布等)均假定已登录,未登录用户可能看到空数据或报错。 |
|
||||
| 2 | **`Post.favoritedByMe` 收藏能力全链路断裂** | PlazaPage, PostCard | 类型定义有 `favoritedByMe` 字段,`feed.service.ts` 导出 `setPostFavorite` 方法,但 `PostCard` 组件和 `PlazaPage` 均没有收藏操作的 UI 入口,前端从未调用过该 service 方法。 |
|
||||
| 3 | **草稿系统断裂** | PublishPage | `draftSave` → `draftGet` 云函数完整存在,`publish.service.ts` 导出了 `getDraft()`,但发布页 `mount` 时从不调用它。草稿保存后永远无法恢复,草稿功能形同虚设。 |
|
||||
| 4 | **`StatsRow` 数据可能与子页面不同步** | ProfilePage → ContactsPage, MyPostsPage | 个人资料页 `stats.posts/following/followers` 来自 `getProfile()`,跳转到 `contacts?tab=following` 时 `getFollowList()` 可能因缓存延迟返回不同计数,造成数字前后不一致。 |
|
||||
| 5 | **没有全局错误边界** | 全应用 | 任何 service 层未处理的异常会直接在页面崩溃。没有 React ErrorBoundary 或全局 Toast 兜底机制,用户体验差。 |
|
||||
| 6 | **`CloudFunctionName` 联合类型缺少 `commentCreate`** | feed.service.ts L43 | `createPostComment` 调用了 `callCloud('commentCreate', ...)`,但 `CloudFunctionName` 联合类型中是否包含 `commentCreate` 取决于 `cloud.ts` 的定义。如果未声明,TypeScript 不会报错但运行时可能失败。 |
|
||||
|
||||
---
|
||||
|
||||
## 十二、修复优先级建议
|
||||
|
||||
### P0 — 必须立即修复(影响核心功能)
|
||||
|
||||
1. **Feed / 我的动态分页** — 社交应用内容流的基础能力
|
||||
2. **发布页草稿恢复** — `getDraft()` 已存在,只需在页面 mount 时调用
|
||||
3. **附近页上报自身位置** — `updateLocation()` 已存在,只需在获取位置后调用
|
||||
|
||||
### P1 — 短期内修复(影响用户体验)
|
||||
|
||||
4. 我的动态页 `useDidShow` 重复加载 → 添加 `firstShow` ref
|
||||
5. 我的动态页 `likePost` 错误回滚
|
||||
6. 附近页 `likePet` 添加乐观更新
|
||||
7. 附近页尊重 `nearbyVisible` 偏好
|
||||
8. 聊天页消息分页加载
|
||||
9. 个人资料页 `changePreference` 添加 `try-catch`
|
||||
10. 收藏功能 UI 入口补全
|
||||
|
||||
### P2 — 中期迭代(完善产品体验)
|
||||
|
||||
11. 搜索栏功能实现(广场页)
|
||||
12. 联系人页实时搜索
|
||||
13. 聊天页发送状态指示 + 发送失败 UX
|
||||
14. 未保存离开提示(发布页、编辑页)
|
||||
15. 全局登录态守卫
|
||||
16. 全局错误边界
|
||||
17. 消息通知 / 推送接入
|
||||
|
||||
### P3 — 长期优化(性能和扩展性)
|
||||
|
||||
18. 话题列表动态化
|
||||
19. 广告系统正规化
|
||||
20. 图片 / 富媒体消息
|
||||
21. 帖子详情页 + 评论列表
|
||||
22. 聊天页轮询策略优化(WebSocket)
|
||||
23. 宠物数量上限
|
||||
24. 用户个人主页入口(从联系人页)
|
||||
|
||||
---
|
||||
|
||||
> 本报告基于源码静态审查生成,所有问题均指向代码层面的逻辑缺陷,不涉及 UI/UX 视觉设计层面的评审。
|
||||
Reference in New Issue
Block a user