feat: 玩家备注与遇见记录,及 Sentry 首次同意弹窗#71
Conversation
issue #67:按 puuid 本地存"备注 + 颜色标记"(友好/一般/小心/拉黑), 复用 config IPC(零 Rust 改动)。对局玩家卡、玩家详情页、战绩详情页每个 玩家行均可标记;保存时把当前对局记入"遇见记录"(gameId/英雄/KDA/胜负/ 敌我/日期/队列),按 gameId 去重、最近在前,复用 MettingPlayersCard 在 徽标气泡与设置页"我标记过的人"列表展示。备注变更通过 player-notes-changed 事件跨窗口广播,详情独立窗口与主窗口实时同步。 Sentry(#70 已默认关闭的 opt-in)补首次启动同意弹窗:等客户端连接、首屏 就绪后弹一次,预选"启用"但保留真实拒绝、不强制;选择后写 errorReportingConsentShown 不再弹。
There was a problem hiding this comment.
Pull request overview
该 PR 在前端侧新增“玩家备注/标记”能力(按 puuid 本地持久化备注+颜色档位,并在多处 UI 接入),并补充“遇见记录”用于复用现有“遇见过”卡片展示;同时为 Sentry opt-in 增加首次启动的同意弹窗,以提升透明度与开启率。
Changes:
- 新增玩家备注数据模型 + Pinia store(复用 config IPC 落盘),并通过 Tauri event 实现跨窗口实时同步。
- 在 PlayerCard / UserRecord / MatchDetailModal 等入口接入
PlayerNoteBadge,并新增设置页“我标记过的人”集中管理与遇见记录展开。 - 新增 Sentry 首次同意弹窗组件,并在
Framework.vue中按连接状态与兜底超时触发一次性展示。
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| lol-record-analysis-tauri/src/views/settings/PlayerNotes.vue | 新增设置页表格:集中查看/编辑/删除玩家备注与展开遇见记录 |
| lol-record-analysis-tauri/src/views/Settings.vue | 设置菜单新增“我标记过的人”入口 |
| lol-record-analysis-tauri/src/types/domain/playerNote.ts | 新增玩家备注领域模型与标签元信息映射 |
| lol-record-analysis-tauri/src/router/index.ts | 新增 PlayerNotes 路由 |
| lol-record-analysis-tauri/src/pinia/playerNotes.ts | 新增玩家备注 store:落盘、遇见记录合并、跨窗口同步 |
| lol-record-analysis-tauri/src/pinia/tests/playerNotes.spec.ts | 新增 playerNotes store 单测(含 encounters 合并) |
| lol-record-analysis-tauri/src/main.ts | 启动时初始化 playerNotes store |
| lol-record-analysis-tauri/src/composables/useMatchDetailPlayers.ts | 详情页玩家模型补充 puuid/gameName/tagLine 供备注功能使用 |
| lol-record-analysis-tauri/src/components/record/UserRecord.vue | 玩家详情页接入 PlayerNoteBadge |
| lol-record-analysis-tauri/src/components/record/MatchDetailModal.vue | 对局详情行接入 PlayerNoteBadge,并构造 encounter 写入遇见记录 |
| lol-record-analysis-tauri/src/components/gaming/PlayerCard.vue | 对局玩家卡接入 PlayerNoteBadge |
| lol-record-analysis-tauri/src/components/Framework.vue | 新增 Sentry 首次同意弹窗触发与持久化逻辑 |
| lol-record-analysis-tauri/src/components/common/PlayerNoteBadge.vue | 新增备注徽标组件(颜色档位+文本编辑+遇见记录展示) |
| lol-record-analysis-tauri/src/components/common/ErrorReportingConsentDialog.vue | 新增 Sentry 首次同意弹窗视觉组件 |
| docs/superpowers/specs/2026-05-29-player-notes-and-sentry-consent-design.md | 新增功能设计文档 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async function loadFromConfig(): Promise<void> { | ||
| try { | ||
| const saved = await getConfigByIpc<PlayerNotesMap>(STORAGE_KEY) | ||
| notes.value = saved && typeof saved === 'object' ? saved : {} | ||
| } catch (error) { | ||
| console.error('Failed to load player notes:', error) | ||
| notes.value = {} | ||
| } | ||
| } |
There was a problem hiding this comment.
已修复(6e6e669):loadFromConfig 读取后把 lastTs 顶到 max(updatedAt),跨窗口/重载后单调时钟不回退。加了回归测试:载入一条大 updatedAt 后再保存,断言新值更大且排在前面。
| async function persist(): Promise<void> { | ||
| try { | ||
| await putConfigByIpc(STORAGE_KEY, notes.value) | ||
| emit(NOTES_CHANGED_EVENT).catch(() => {}) | ||
| } catch (error) { | ||
| console.error('Failed to persist player notes:', error) | ||
| } | ||
| } |
There was a problem hiding this comment.
已修复(6e6e669):persist 落盘失败时改为重新抛出(记日志后 throw),setNote/removeNote 不再静默 resolve,上层 try/catch 能正确弹"保存/删除失败"。加了回归测试断言 putConfig 失败时 setNote rejects。
| async function onConsentDecide(enabled: boolean): Promise<void> { | ||
| showConsent.value = false | ||
| if (enabled) { | ||
| try { | ||
| await putConfigByIpc('errorReportingEnabled', true) | ||
| message.success('已开启,重启后生效') | ||
| } catch { | ||
| message.error('保存失败') | ||
| } | ||
| } | ||
| putConfigByIpc('errorReportingConsentShown', true).catch(() => {}) | ||
| } |
There was a problem hiding this comment.
已修复(6e6e669):onConsentDecide 改为无论启用/保持关闭都持久化 errorReportingEnabled=enabled。这样此前已在设置开启的情况下点"保持关闭"也会真正关掉,与按钮文案一致。
- C2: playerNotes persist 落盘失败时重新抛出,让 setNote/removeNote 的上层 try/catch 能反馈失败,不再假成功(写盘失败仍弹已保存)。 - C3: 同意弹窗无论启用/保持关闭都持久化 errorReportingEnabled=enabled, 避免此前已在设置开启时点保持关闭不生效、与按钮文案不符。 - C1: loadFromConfig 后把单调时钟 lastTs 顶到已有最大 updatedAt,避免 reload 后归 0 导致下次保存时间戳回退、破坏最近优先排序(含回归测试)。
- 新增 services/configKeys.ts,收口 errorReportingEnabled/ConsentShown 两个键, General.vue 与 Framework.vue 共用,避免裸字符串散落、改名漏改。 - PlayerNoteBadge 触发按钮 title 改用 triggerTitle computed,去掉模板里的 note! 非空断言。
Summary
PlayerCard)、玩家详情页(UserRecord)、战绩详情页每个玩家行(MatchDetailModal)。views/settings/PlayerNotes.vue),可查看 / 行内编辑 / 删除。OneGamePlayer记入PlayerNote.encounters(gameId / 英雄 / KDA / 胜负 / 敌我 / 日期 / 队列名),按 gameId 去重、最近在前、上限 20 条。徽标气泡与设置页(可展开行)均复用MettingPlayersCard展示,点卡片可开那局详情。player-notes-changedTauri 事件广播,战绩详情独立窗口与主窗口即时一致,无需重启。ErrorReportingConsentDialog),等客户端连接、首屏就绪后弹一次,预选"启用"但保留真实拒绝、不强制;选择后写errorReportingConsentShown,之后不再弹。Test plan
npm run check通过(prettier + eslint 0 error + vue-tsc + cargo fmt + clippy -Dwarnings)npm run test通过(425 passed,含 store + 遇见记录合并测试)Closes #67