Merge PR #121: show requester names in play history

Merges feature/play-history-requester (@Fa1nttt) into main.

The PR records the WebUI/TeamSpeak requester on queued songs and persists it
to play history (schema migration for requestedBy), rendering it as a badge in
SongCard (gray for 游客/guest).

Conflicts (frontend platform union) resolved to keep both 'spotify' (from #118)
and the new requestedBy/playedAt fields.

Integration fix: the Spotify playback branch in resolveAndPlay (added by #118,
which did not exist on the PR's base) also records play history — added
`requestedBy: song.requestedBy` there so Spotify tracks carry attribution too,
matching the non-Spotify path.

Verified on the merged tree: tsc --noEmit clean, full suite 1309/1309, web build clean.

Co-Authored-By: Fa1nttt <noreply@github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
committed 2026-07-04 23:17:16 +08:00
commit b9767a7471
7 files changed
+102 -39

No files matched your search

+25
View File
@@ -9,6 +9,11 @@
class="platform-badge"
:class="song.platform === 'bilibili' ? 'badge-bilibili' : song.platform === 'qq' ? 'badge-qq' : song.platform === 'youtube' ? 'badge-youtube' : song.platform === 'local' ? 'badge-local' : song.platform === 'kugou' ? 'badge-kugou' : song.platform === 'spotify' ? 'badge-spotify' : 'badge-netease'"
>{{ song.platform === 'bilibili' ? 'B站' : song.platform === 'qq' ? 'QQ' : song.platform === 'youtube' ? 'YouTube' : song.platform === 'local' ? '本地' : song.platform === 'kugou' ? '酷狗' : song.platform === 'spotify' ? 'Spotify' : '网易云' }}</span>
<span
v-if="song.requestedBy"
class="requester-badge"
:class="{ 'requester-badge-guest': song.requestedBy === '游客' }"
>{{ song.requestedBy }}</span>
</div>
<div class="song-artist">{{ song.artist }}</div>
</div>
@@ -115,6 +120,26 @@ function formatDuration(seconds: number): string {
line-height: 1.4;
}
.requester-badge {
flex-shrink: 0;
max-width: 96px;
font-size: var(--fs-micro);
font-weight: var(--fw-semi);
padding: 1px 5px;
border-radius: var(--radius-xs);
line-height: 1.4;
background: var(--color-online-15);
color: var(--color-online);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.requester-badge-guest {
background: rgba(156, 163, 175, 0.18);
color: rgba(156, 163, 175, 0.95);
}
.badge-netease {
background: var(--brand-netease-15);
color: var(--brand-netease);
+2
View File
@@ -11,6 +11,8 @@ export interface Song {
duration: number;
coverUrl: string;
platform: 'netease' | 'qq' | 'bilibili' | 'youtube' | 'local' | 'kugou' | 'spotify';
requestedBy?: string;
playedAt?: string;
}
export type Source = 'netease' | 'qq' | 'kugou' | 'spotify';