From 1de42a261a3a0ff1a5ea5268de551cca88ecdebc Mon Sep 17 00:00:00 2001 From: momen Date: Tue, 19 May 2026 16:30:41 +0800 Subject: [PATCH] feat(reviews): show reviewer avatars --- .../plans/2026-05-19-review-avatar-display.md | 141 ++++++++++++++++++ src/__tests__/unit/ReviewsPanel.test.ts | 35 +++++ src/components/ReviewsPanel.vue | 44 +++++- 3 files changed, 212 insertions(+), 8 deletions(-) create mode 100644 docs/superpowers/plans/2026-05-19-review-avatar-display.md diff --git a/docs/superpowers/plans/2026-05-19-review-avatar-display.md b/docs/superpowers/plans/2026-05-19-review-avatar-display.md new file mode 100644 index 00000000..6866de79 --- /dev/null +++ b/docs/superpowers/plans/2026-05-19-review-avatar-display.md @@ -0,0 +1,141 @@ +# Review Avatar Display Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Show cached backend user avatar URLs beside comments in the app review list. + +**Architecture:** Use the existing `AppReview.userAvatarUrl` field returned by the backend. `ReviewsPanel.vue` renders an avatar image when present and a stable fallback when missing or failed; tests cover the rendered avatar contract. + +**Tech Stack:** Vue 3 SFC, Tailwind CSS utilities, Vitest, Testing Library Vue. + +--- + +## File Structure + +- Modify: `src/components/ReviewsPanel.vue` - render reviewer avatar/fallback in each review card and handle broken avatar images. +- Modify: `src/__tests__/unit/ReviewsPanel.test.ts` - add test coverage for avatar display. + +## Task 1: Add Avatar Rendering Test + +**Files:** +- Modify: `src/__tests__/unit/ReviewsPanel.test.ts` + +- [ ] **Step 1: Add review with avatar test** + +Append this test inside `describe("ReviewsPanel", () => { ... })` before the final closing brace: + +```ts + it("shows reviewer avatars when available", async () => { + vi.mocked(fetchRatingSummary).mockResolvedValue({ + averageRating: 5, + reviewCount: 1, + starCounts: { 5: 1 }, + }); + vi.mocked(fetchReviews).mockResolvedValue([ + { + id: 3, + rating: 5, + content: "头像正常显示", + version: tags.version, + packageArch: tags.packageArch, + clientArch: tags.clientArch, + distro: tags.distro, + origin: tags.origin, + category: tags.category, + createdAt: "2026-05-19T00:00:00Z", + updatedAt: "2026-05-19T00:00:00Z", + userDisplayName: "Avatar User", + userAvatarUrl: "https://bbs.spark-app.store/avatar.png", + }, + ]); + + render(ReviewsPanel, { + props: { appKey: "apm:amd64-apm:office:wps", tags, loggedIn: true }, + }); + + const avatar = await screen.findByAltText("Avatar User 的头像"); + expect(avatar).toHaveAttribute("src", "https://bbs.spark-app.store/avatar.png"); + }); +``` + +- [ ] **Step 2: Run test to verify failure** + +Run: `npm run test -- --run src/__tests__/unit/ReviewsPanel.test.ts` + +Expected: FAIL because no avatar image with alt text is rendered. + +## Task 2: Render Review Avatars + +**Files:** +- Modify: `src/components/ReviewsPanel.vue` +- Modify: `src/__tests__/unit/ReviewsPanel.test.ts` + +- [ ] **Step 1: Update review article layout** + +In `src/components/ReviewsPanel.vue`, replace the review `
` body with this structure: + +```vue +
+ + +
+
+ + {{ review.userDisplayName || "星火用户" }} + + {{ review.rating }} 星 +
+

+ {{ review.content || "暂无评论内容" }} +

+
+
+``` + +- [ ] **Step 2: Add avatar error handler** + +In the `