fix(songitem): 添加到歌单权限判断改为响应式并提示不可用原因

- 权限判断从 localStorage 快照改为 userStore 响应式状态,登录/登出后菜单状态即时刷新
- 菜单项不再灰色禁用,未登录或 UID 登录时点击给出明确提示(新增 5 语言文案)

Closes #706
This commit is contained in:
alger
2026-07-05 14:09:57 +08:00
parent edc7e70158
commit baf3c7832e
6 changed files with 90 additions and 71 deletions
@@ -15,13 +15,15 @@
<script lang="ts" setup>
import type { MenuOption } from 'naive-ui';
import { NDropdown, NEllipsis, NImage } from 'naive-ui';
import { createDiscreteApi, NDropdown, NEllipsis, NImage } from 'naive-ui';
import { computed, h, inject } from 'vue';
import { useI18n } from 'vue-i18n';
import { useUserStore } from '@/store';
import type { SongResult } from '@/types/music';
import { getImgUrl, isElectron } from '@/utils';
import { hasPermission } from '@/utils/auth';
const { message } = createDiscreteApi(['message']);
const { t } = useI18n();
@@ -50,6 +52,13 @@ const emits = defineEmits([
const openPlaylistDrawer = inject<(songId: number | string) => void>('openPlaylistDrawer');
const userStore = useUserStore();
// 是否具有真实登录权限(Cookie/扫码登录)。
// 用 userStore 的响应式状态而非直接读 localStorage
// 后者不具备响应性,登录/登出后菜单禁用状态不会刷新(#706)
const hasRealAuth = computed(() => !!userStore.user && userStore.loginType !== 'uid');
// 渲染歌曲预览
const renderSongPreview = () => {
return h(
@@ -123,8 +132,6 @@ const renderSongPreview = () => {
// 下拉菜单选项
const dropdownOptions = computed<MenuOption[]>(() => {
const hasRealAuth = hasPermission(true);
const options: MenuOption[] = [
{
key: 'header',
@@ -160,10 +167,10 @@ const dropdownOptions = computed<MenuOption[]>(() => {
icon: () => h('i', { class: 'iconfont ri-file-text-line' })
},
{
// 不做灰色禁用:点击时提示不可用原因,避免用户不知道"为什么用不了"#706
label: t('songItem.menu.addToPlaylist'),
key: 'addToPlaylist',
icon: () => h('i', { class: 'iconfont ri-folder-add-line' }),
disabled: !hasRealAuth
icon: () => h('i', { class: 'iconfont ri-folder-add-line' })
},
{
label: props.isFavorite ? t('songItem.menu.unfavorite') : t('songItem.menu.favorite'),
@@ -216,6 +223,10 @@ const handleSelect = (key: string | number) => {
emits('play-next');
break;
case 'addToPlaylist':
if (!hasRealAuth.value) {
message.warning(t('songItem.message.addToPlaylistNeedLogin'));
break;
}
openPlaylistDrawer?.(props.item.id);
break;
case 'favorite':