Skip to content

Commit 76be3cc

Browse files
authored
Merge pull request #942 from WorldSansha/feat-new-work
feat: 在播放界面、评论区、专辑等页面添加具体评论数量
2 parents 31beaaa + 18633b7 commit 76be3cc

9 files changed

Lines changed: 159 additions & 15 deletions

File tree

src/components/List/ListComment.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
<div class="title">
2626
<SvgIcon name="Message" />
2727
<span>全部评论</span>
28+
<span v-if="commentTotalCount > 0" class="count">{{ commentTotalCount }}</span>
2829
</div>
2930
</div>
3031
<CommentList
@@ -62,6 +63,10 @@ const props = withDefaults(
6263
{},
6364
);
6465
66+
const emit = defineEmits<{
67+
"update:commentCount": [count: number];
68+
}>();
69+
6570
const commentListRef = ref<HTMLElement | null>(null);
6671
6772
// 列表高度
@@ -73,6 +78,7 @@ const commentData = ref<CommentType[]>([]);
7378
const commentHotData = ref<CommentType[] | null>(null);
7479
const commentPage = ref<number>(1);
7580
const commentHasMore = ref<boolean>(true);
81+
const commentTotalCount = ref<number>(0);
7682
7783
// 获取热门评论
7884
const getHotCommentData = async () => {
@@ -106,6 +112,11 @@ const getCommentData = async (clean: boolean = true) => {
106112
: undefined;
107113
// 获取评论
108114
const result = await getComment(props.id, props.type, commentPage.value, 20, 3, cursor);
115+
// 更新评论总数
116+
if (result.data?.totalCount != null) {
117+
commentTotalCount.value = result.data.totalCount;
118+
emit("update:commentCount", result.data.totalCount);
119+
}
109120
if (isEmpty(result.data?.comments)) {
110121
commentHasMore.value = false;
111122
commentLoading.value = false;
@@ -140,6 +151,7 @@ watch(
140151
commentHotData.value = null;
141152
commentPage.value = 1;
142153
commentHasMore.value = true;
154+
commentTotalCount.value = 0;
143155
getCommentData();
144156
}
145157
},
@@ -169,6 +181,12 @@ watch(
169181
margin-right: 8px;
170182
font-size: 20px;
171183
}
184+
.count {
185+
margin-left: 6px;
186+
font-size: 13px;
187+
font-weight: normal;
188+
opacity: 0.6;
189+
}
172190
}
173191
}
174192
</style>

src/components/List/ListDetail.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,12 @@
214214
{{ detailData?.count }}
215215
</n-text>
216216
</n-tab>
217-
<n-tab name="comments"> 评论 </n-tab>
217+
<n-tab name="comments">
218+
评论
219+
<n-text v-if="settingStore.showCommentCount !== 'off' && detailData?.commentCount" class="count" depth="3">
220+
{{ formatCommentCount(detailData.commentCount) }}
221+
</n-text>
222+
</n-tab>
218223
</n-tabs>
219224
</n-flex>
220225
</n-flex>
@@ -234,7 +239,7 @@
234239
import type { CoverType, SongType } from "@/types/main";
235240
import type { DropdownOption } from "naive-ui";
236241
import { coverLoaded, formatNumber } from "@/utils/helper";
237-
import { removeBrackets } from "@/utils/format";
242+
import { removeBrackets, formatCommentCount } from "@/utils/format";
238243
import { renderToolbar } from "@/utils/meta";
239244
import { formatTimestamp } from "@/utils/time";
240245
import { openDescModal, openJumpArtist } from "@/utils/modal";

src/components/Player/PlayerComponents/PlayerComment.vue

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@
6363
<div class="title">
6464
<SvgIcon name="Message" />
6565
<span>全部评论</span>
66+
<span v-if="statusStore.songCommentCount > 0" class="count">
67+
{{ statusStore.songCommentCount }}
68+
</span>
6669
</div>
6770
</div>
6871
<CommentList
@@ -170,6 +173,10 @@ const getAllComment = async () => {
170173
: undefined;
171174
// 获取评论
172175
const result = await getComment(songId.value, songType.value, commentPage.value, 20, 3, cursor);
176+
// 更新评论总数
177+
if (result.data?.totalCount != null) {
178+
statusStore.songCommentCount = result.data.totalCount;
179+
}
173180
if (isEmpty(result.data?.comments)) {
174181
commentHasMore.value = false;
175182
commentLoading.value = false;
@@ -197,6 +204,7 @@ watch(
197204
commentHotData.value = [];
198205
commentPage.value = 1;
199206
commentHasMore.value = true;
207+
statusStore.songCommentCount = 0;
200208
if (!isShowComment.value) return;
201209
getHotCommentData();
202210
getAllComment();
@@ -322,6 +330,12 @@ onMounted(() => {
322330
.n-icon {
323331
margin-right: 6px;
324332
}
333+
.count {
334+
margin-left: 6px;
335+
font-size: 14px;
336+
font-weight: normal;
337+
opacity: 0.6;
338+
}
325339
}
326340
}
327341
}

src/components/Player/PlayerControl.vue

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,22 @@
3939
>
4040
<SvgIcon name="Download" />
4141
</div>
42-
<!-- 显示评论 -->
43-
<div
44-
v-if="
45-
!musicStore.playSong.path &&
46-
!statusStore.pureLyricMode &&
47-
settingStore.fullscreenPlayerElements.comments
48-
"
49-
class="menu-icon"
50-
@click.stop="statusStore.showPlayerComment = !statusStore.showPlayerComment"
42+
<n-badge
43+
:value="formatCommentCount(statusStore.songCommentCount)"
44+
:show="settingStore.showCommentCount !== 'off' && statusStore.songCommentCount > 0"
5145
>
52-
<SvgIcon :depth="statusStore.showPlayerComment ? 1 : 3" name="Message" />
53-
</div>
46+
<div
47+
v-if="
48+
!musicStore.playSong.path &&
49+
!statusStore.pureLyricMode &&
50+
settingStore.fullscreenPlayerElements.comments
51+
"
52+
class="menu-icon"
53+
@click.stop="statusStore.showPlayerComment = !statusStore.showPlayerComment"
54+
>
55+
<SvgIcon :depth="statusStore.showPlayerComment ? 1 : 3" name="Message" />
56+
</div>
57+
</n-badge>
5458
</n-flex>
5559
<div class="center">
5660
<div class="btn">
@@ -151,6 +155,8 @@ import { useDataStore, useMusicStore, useStatusStore, useSettingStore } from "@/
151155
import { toLikeSong } from "@/utils/auth";
152156
import { useTimeFormat } from "@/composables/useTimeFormat";
153157
import { openDownloadSong, openPlaylistAdd } from "@/utils/modal";
158+
import { getComment } from "@/api/comment";
159+
import { formatCommentCount } from "@/utils/format";
154160
155161
const dataStore = useDataStore();
156162
const musicStore = useMusicStore();
@@ -162,6 +168,37 @@ const player = usePlayerController();
162168
163169
const { timeDisplay, toggleTimeFormat } = useTimeFormat();
164170
171+
// 获取评论数量
172+
const fetchCommentCount = async () => {
173+
if (settingStore.showCommentCount === "off") return;
174+
const id = musicStore.playSong.id;
175+
if (!id || typeof id !== "number" || musicStore.playSong.path) return;
176+
try {
177+
const type = musicStore.playSong.type === "radio" ? 4 : 0;
178+
const result = await getComment(id, type as 0 | 4, 1, 1);
179+
if (result.data?.totalCount != null) {
180+
statusStore.songCommentCount = result.data.totalCount;
181+
}
182+
} catch {
183+
// 忽略错误
184+
}
185+
};
186+
187+
// 歌曲变化时获取评论数量
188+
watch(
189+
() => musicStore.playSong.id,
190+
() => {
191+
statusStore.songCommentCount = 0;
192+
fetchCommentCount();
193+
},
194+
);
195+
196+
onMounted(() => {
197+
if (musicStore.playSong.id && !musicStore.playSong.path) {
198+
fetchCommentCount();
199+
}
200+
});
201+
165202
const showAutomixFx = ref(false);
166203
let automixFxTimer: number | null = null;
167204
const showAutomixLabel = ref(false);
@@ -274,6 +311,12 @@ onBeforeUnmount(() => {
274311
transform: scale(1);
275312
}
276313
}
314+
:deep(.n-badge-sup) {
315+
background-color: rgba(var(--main-cover-color), 0.14);
316+
.n-base-slot-machine {
317+
color: rgb(var(--main-cover-color));
318+
}
319+
}
277320
:deep(.right-menu) {
278321
.n-badge-sup {
279322
background-color: rgba(var(--main-cover-color), 0.14);

src/components/Setting/config/appearance.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,21 @@ export const useAppearanceSettings = (): SettingConfig => {
169169
set: (v) => (settingStore.showPlaylistCount = v),
170170
}),
171171
},
172+
{
173+
key: "showCommentCount",
174+
label: "显示评论数量",
175+
type: "select",
176+
description: "在评论按钮上显示评论数量",
177+
options: [
178+
{ label: "关闭", value: "off" },
179+
{ label: "缩减", value: "compact" },
180+
{ label: "完整", value: "full" },
181+
],
182+
value: computed({
183+
get: () => settingStore.showCommentCount,
184+
set: (v) => (settingStore.showCommentCount = v),
185+
}),
186+
},
172187
{
173188
key: "routeAnimation",
174189
label: "页面切换动画",

src/stores/setting.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ export interface SettingState {
221221
progressAdjustLyric: boolean;
222222
/** 显示播放列表数量 */
223223
showPlaylistCount: boolean;
224+
/** 显示评论数量 */
225+
showCommentCount: "off" | "compact" | "full";
224226
/** 是否显示音乐频谱 */
225227
showSpectrums: boolean;
226228
/** 是否开启系统音频集成 */
@@ -570,6 +572,7 @@ export const useSettingStore = defineStore("setting", {
570572
progressTooltipShow: true,
571573
progressAdjustLyric: false,
572574
showPlaylistCount: true,
575+
showCommentCount: "compact",
573576
showSpectrums: false,
574577
smtcOpen: true,
575578
playSongDemo: false,

src/stores/status.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ interface StatusState {
165165
playlistMode: "online" | "local";
166166
automixFxSeq: number;
167167
automixEndedSeq: number;
168+
/** 当前歌曲评论数量 */
169+
songCommentCount: number;
168170
}
169171

170172
export const useStatusStore = defineStore("status", {
@@ -248,6 +250,7 @@ export const useStatusStore = defineStore("status", {
248250
playlistMode: "online",
249251
automixFxSeq: 0,
250252
automixEndedSeq: 0,
253+
songCommentCount: 0,
251254
}),
252255
getters: {
253256
// 播放音量图标

src/utils/format.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,28 @@
1-
import { useDataStore, useMusicStore, useStatusStore } from "@/stores";
1+
import { useDataStore, useMusicStore, useSettingStore, useStatusStore } from "@/stores";
22
import type { ArtistType, CatType, CommentType, CoverType, MetaData, SongType } from "@/types/main";
33
import { flatMap, isArray, uniqBy } from "lodash-es";
44
import { handleSongQuality } from "./helper";
55
import { msToTime } from "./time";
66

7+
/**
8+
* 格式化评论数量
9+
* @param count 评论数量
10+
* @returns 格式化后的评论数量
11+
*/
12+
export const formatCommentCount = (count: number): string | number => {
13+
const settingStore = useSettingStore();
14+
if (settingStore.showCommentCount === "full") return count;
15+
if (count >= 10000) {
16+
const val = Math.floor(count / 1000) / 10;
17+
return `${val % 1 === 0 ? val.toFixed(0) : val}W+`;
18+
}
19+
if (count >= 1000) {
20+
const val = Math.floor(count / 100) / 10;
21+
return `${val % 1 === 0 ? val.toFixed(0) : val}K+`;
22+
}
23+
return count;
24+
};
25+
726
/**
827
* 移除文本中的括号内容(支持中英文括号)
928
* @param text 原始文本

src/views/List/album.vue

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
</template>
5555
<!-- 评论 -->
5656
<template v-else>
57-
<ListComment :id="albumId" :type="3" :height="songListHeight" />
57+
<ListComment :id="albumId" :type="3" :height="songListHeight" @update:comment-count="handleCommentCount" />
5858
</template>
5959
</Transition>
6060
</div>
@@ -64,6 +64,7 @@
6464
import type { DropdownOption } from "naive-ui";
6565
import { songDetail } from "@/api/song";
6666
import { albumDetail } from "@/api/album";
67+
import { getComment } from "@/api/comment";
6768
import { formatCoverList, formatSongsList } from "@/utils/format";
6869
import { renderIcon, copyData, getShareUrl } from "@/utils/helper";
6970
import { openBatchList } from "@/utils/modal";
@@ -194,6 +195,8 @@ const getAlbumDetail = async (id: number, refresh: boolean = false) => {
194195
setListData(cached.songs);
195196
setLoading(false);
196197
198+
// 获取专辑评论数量(专辑API不返回commentCount)
199+
fetchAlbumCommentCount(id);
197200
// 后台检查更新
198201
backgroundCheck(id, cached);
199202
return;
@@ -208,6 +211,8 @@ const getAlbumDetail = async (id: number, refresh: boolean = false) => {
208211
// 检查是否仍然是当前请求的专辑
209212
if (currentRequestId.value !== id) return;
210213
setDetailData(formatCoverList(detail.album)[0]);
214+
// 获取专辑评论数量(专辑API不返回commentCount)
215+
fetchAlbumCommentCount(id);
211216
// 获取专辑歌曲
212217
const ids: number[] = detail.songs.map((song: any) => song.id as number);
213218
const result = await songDetail(ids);
@@ -251,6 +256,25 @@ const handleTabChange = (value: "songs" | "comments") => {
251256
currentTab.value = value;
252257
};
253258
259+
// 更新评论数量(从 ListComment emit 回调)
260+
const handleCommentCount = (count: number) => {
261+
if (detailData.value) {
262+
detailData.value.commentCount = count;
263+
}
264+
};
265+
266+
// 主动获取专辑评论数量
267+
const fetchAlbumCommentCount = async (id: number) => {
268+
try {
269+
const result = await getComment(id, 3, 1, 1);
270+
if (result.data?.totalCount != null && detailData.value?.id === id) {
271+
detailData.value.commentCount = result.data.totalCount;
272+
}
273+
} catch {
274+
// 忽略错误
275+
}
276+
};
277+
254278
// 播放全部歌曲
255279
const playAllSongs = useDebounceFn(() => {
256280
if (!detailData.value || !displayData.value?.length) return;

0 commit comments

Comments
 (0)