mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-05-17 10:27:30 +08:00
🦄 refactor: 重构代码将 Vuex替换为 Pinia
集成 Pinia 状态管理
This commit is contained in:
@@ -88,18 +88,18 @@ import { useMessage } from 'naive-ui';
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import { getMusicDetail } from '@/api/music';
|
||||
import SongItem from '@/components/common/SongItem.vue';
|
||||
import { getSongUrl } from '@/hooks/MusicListHook';
|
||||
import { usePlayerStore } from '@/store';
|
||||
import type { SongResult } from '@/type/music';
|
||||
import { isElectron, setAnimationClass, setAnimationDelay } from '@/utils';
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
const playerStore = usePlayerStore();
|
||||
const message = useMessage();
|
||||
const favoriteList = computed(() => store.state.favoriteList);
|
||||
const favoriteList = computed(() => playerStore.favoriteList);
|
||||
const favoriteSongs = ref<SongResult[]>([]);
|
||||
const loading = ref(false);
|
||||
const noMore = ref(false);
|
||||
@@ -277,7 +277,7 @@ const handleScroll = (e: any) => {
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
await store.dispatch('initializeFavoriteList');
|
||||
await playerStore.initializeFavoriteList();
|
||||
await getFavoriteSongs();
|
||||
});
|
||||
|
||||
@@ -293,7 +293,7 @@ watch(
|
||||
);
|
||||
|
||||
const handlePlay = () => {
|
||||
store.commit('setPlayList', favoriteSongs.value);
|
||||
playerStore.setPlayList(favoriteSongs.value);
|
||||
};
|
||||
|
||||
const getItemAnimationDelay = (index: number) => {
|
||||
|
||||
@@ -34,11 +34,11 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import { getMusicDetail } from '@/api/music';
|
||||
import SongItem from '@/components/common/SongItem.vue';
|
||||
import { useMusicHistory } from '@/hooks/MusicHistoryHook';
|
||||
import { usePlayerStore } from '@/store/modules/player';
|
||||
import type { SongResult } from '@/type/music';
|
||||
import { setAnimationClass, setAnimationDelay } from '@/utils';
|
||||
|
||||
@@ -47,12 +47,12 @@ defineOptions({
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
const { delMusic, musicList } = useMusicHistory();
|
||||
const scrollbarRef = ref();
|
||||
const loading = ref(false);
|
||||
const noMore = ref(false);
|
||||
const displayList = ref<SongResult[]>([]);
|
||||
const playerStore = usePlayerStore();
|
||||
|
||||
// 无限滚动相关配置
|
||||
const pageSize = 20;
|
||||
@@ -112,7 +112,7 @@ const handleScroll = (e: any) => {
|
||||
|
||||
// 播放全部
|
||||
const handlePlay = () => {
|
||||
store.commit('setPlayList', displayList.value);
|
||||
playerStore.setPlayList(displayList.value);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -3,9 +3,9 @@ import { useMessage } from 'naive-ui';
|
||||
import { onMounted } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import { checkQr, createQr, getQrKey, getUserDetail, loginByCellphone } from '@/api/login';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { setAnimationClass } from '@/utils';
|
||||
|
||||
defineOptions({
|
||||
@@ -14,11 +14,12 @@ defineOptions({
|
||||
|
||||
const { t } = useI18n();
|
||||
const message = useMessage();
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const isQr = ref(true);
|
||||
|
||||
const qrUrl = ref<string>();
|
||||
const userStore = useUserStore();
|
||||
|
||||
onMounted(() => {
|
||||
loadLogin();
|
||||
});
|
||||
@@ -56,7 +57,7 @@ const timerIsQr = (key: string) => {
|
||||
if (data.code === 803) {
|
||||
localStorage.setItem('token', data.cookie);
|
||||
const user = await getUserDetail();
|
||||
store.state.user = user.data.profile;
|
||||
userStore.user = user.data.profile;
|
||||
localStorage.setItem('user', JSON.stringify(user.data.profile));
|
||||
message.success(t('login.message.loginSuccess'));
|
||||
|
||||
@@ -95,7 +96,7 @@ const loginPhone = async () => {
|
||||
const { data } = await loginByCellphone(phone.value, password.value);
|
||||
if (data.code === 200) {
|
||||
message.success(t('login.message.loginSuccess'));
|
||||
store.state.user = data.profile;
|
||||
userStore.user = data.profile;
|
||||
localStorage.setItem('token', data.cookie);
|
||||
setTimeout(() => {
|
||||
router.push('/user');
|
||||
|
||||
@@ -64,11 +64,11 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import { getAllMv, getTopMv } from '@/api/mv';
|
||||
import MvPlayer from '@/components/MvPlayer.vue';
|
||||
import { audioService } from '@/services/audioService';
|
||||
import { usePlayerStore } from '@/store/modules/player';
|
||||
import { IMvItem } from '@/type/mv';
|
||||
import { formatNumber, getImgUrl, setAnimationClass, setAnimationDelay } from '@/utils';
|
||||
|
||||
@@ -79,7 +79,6 @@ defineOptions({
|
||||
const showMv = ref(false);
|
||||
const mvList = ref<Array<IMvItem>>([]);
|
||||
const playMvItem = ref<IMvItem>();
|
||||
const store = useStore();
|
||||
const initLoading = ref(false);
|
||||
const loadingMore = ref(false);
|
||||
const currentIndex = ref(0);
|
||||
@@ -97,6 +96,8 @@ const categories = [
|
||||
];
|
||||
const selectedCategory = ref('全部');
|
||||
|
||||
const playerStore = usePlayerStore();
|
||||
|
||||
watch(selectedCategory, async () => {
|
||||
offset.value = 0;
|
||||
mvList.value = [];
|
||||
@@ -114,8 +115,8 @@ onMounted(async () => {
|
||||
});
|
||||
|
||||
const handleShowMv = async (item: IMvItem, index: number) => {
|
||||
store.commit('setIsPlay', false);
|
||||
store.commit('setPlayMusic', false);
|
||||
playerStore.setIsPlay(false);
|
||||
playerStore.setPlayMusic(false);
|
||||
audioService.getCurrentSound()?.pause();
|
||||
showMv.value = true;
|
||||
currentIndex.value = index;
|
||||
|
||||
@@ -107,12 +107,13 @@ import { useDateFormat } from '@vueuse/core';
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import { getHotSearch } from '@/api/home';
|
||||
import { getSearch } from '@/api/search';
|
||||
import SearchItem from '@/components/common/SearchItem.vue';
|
||||
import SongItem from '@/components/common/SongItem.vue';
|
||||
import { usePlayerStore } from '@/store/modules/player';
|
||||
import { useSearchStore } from '@/store/modules/search';
|
||||
import type { IHotSearch } from '@/type/search';
|
||||
import { isMobile, setAnimationClass, setAnimationDelay } from '@/utils';
|
||||
|
||||
@@ -122,10 +123,11 @@ defineOptions({
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
const playerStore = usePlayerStore();
|
||||
const searchStore = useSearchStore();
|
||||
|
||||
const searchDetail = ref<any>();
|
||||
const searchType = computed(() => store.state.searchType as number);
|
||||
const searchType = computed(() => searchStore.searchType as number);
|
||||
const searchDetailLoading = ref(false);
|
||||
const searchHistory = ref<string[]>([]);
|
||||
|
||||
@@ -188,23 +190,6 @@ onMounted(() => {
|
||||
|
||||
const hotKeyword = ref(route.query.keyword || t('search.title.searchList'));
|
||||
|
||||
watch(
|
||||
() => store.state.searchValue,
|
||||
(value) => {
|
||||
loadSearch(value);
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => searchType.value,
|
||||
() => {
|
||||
if (store.state.searchValue) {
|
||||
loadSearch(store.state.searchValue);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const dateFormat = (time: any) => useDateFormat(time, 'YYYY.MM.DD').value;
|
||||
const loadSearch = async (keywords: any, type: any = null, isLoadMore = false) => {
|
||||
if (!keywords) return;
|
||||
|
||||
@@ -295,6 +280,31 @@ const loadSearch = async (keywords: any, type: any = null, isLoadMore = false) =
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => searchStore.searchValue,
|
||||
(value) => {
|
||||
loadSearch(value);
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => searchType.value,
|
||||
() => {
|
||||
if (searchStore.searchValue) {
|
||||
loadSearch(searchStore.searchValue);
|
||||
}
|
||||
}
|
||||
);
|
||||
// 修改 store.state 的访问
|
||||
if (searchStore.searchValue) {
|
||||
loadSearch(searchStore.searchValue);
|
||||
}
|
||||
|
||||
// 修改 store.state 的设置
|
||||
searchStore.searchValue = route.query.keyword as string;
|
||||
|
||||
const dateFormat = (time: any) => useDateFormat(time, 'YYYY.MM.DD').value;
|
||||
|
||||
// 添加滚动处理函数
|
||||
const handleScroll = (e: any) => {
|
||||
const { scrollTop, scrollHeight, clientHeight } = e.target;
|
||||
@@ -308,14 +318,14 @@ watch(
|
||||
() => route.path,
|
||||
async (path) => {
|
||||
if (path === '/search') {
|
||||
store.state.searchValue = route.query.keyword;
|
||||
searchStore.searchValue = route.query.keyword as string;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const handlePlay = () => {
|
||||
const tracks = searchDetail.value?.songs || [];
|
||||
store.commit('setPlayList', tracks);
|
||||
playerStore.setPlayList(tracks);
|
||||
};
|
||||
|
||||
// 点击搜索历史
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<n-button size="small" @click="store.commit('setShowDownloadDrawer', true)">
|
||||
<n-button size="small" @click="settingsStore.showDownloadDrawer = true">
|
||||
{{ t('settings.application.download') }}
|
||||
</n-button>
|
||||
</div>
|
||||
@@ -461,11 +461,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { cloneDeep } from 'lodash';
|
||||
import type { FormRules } from 'naive-ui';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { computed, h, nextTick, onMounted, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import localData from '@/../main/set.json';
|
||||
import Coffee from '@/components/Coffee.vue';
|
||||
@@ -473,13 +473,17 @@ import DonationList from '@/components/common/DonationList.vue';
|
||||
import PlayBottom from '@/components/common/PlayBottom.vue';
|
||||
import LanguageSwitcher from '@/components/LanguageSwitcher.vue';
|
||||
import ShortcutSettings from '@/components/settings/ShortcutSettings.vue';
|
||||
import { useSettingsStore } from '@/store/modules/settings';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { isElectron } from '@/utils';
|
||||
import { openDirectory, selectDirectory } from '@/utils/fileOperation';
|
||||
import { checkUpdate, UpdateResult } from '@/utils/update';
|
||||
|
||||
import config from '../../../../package.json';
|
||||
|
||||
const store = useStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const userStore = useUserStore();
|
||||
|
||||
const checking = ref(false);
|
||||
const updateInfo = ref<UpdateResult>({
|
||||
hasUpdate: false,
|
||||
@@ -490,37 +494,23 @@ const updateInfo = ref<UpdateResult>({
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const setData = computed(() => {
|
||||
const data = store.state.setData;
|
||||
// 确保代理配置存在
|
||||
if (!data.proxyConfig) {
|
||||
data.proxyConfig = {
|
||||
enable: false,
|
||||
protocol: 'http',
|
||||
host: '127.0.0.1',
|
||||
port: 7890
|
||||
};
|
||||
}
|
||||
// 确保音质设置存在
|
||||
if (!data.musicQuality) {
|
||||
data.musicQuality = 'higher';
|
||||
}
|
||||
return data;
|
||||
});
|
||||
|
||||
watch(
|
||||
() => setData.value,
|
||||
(newVal) => {
|
||||
store.commit('setSetData', newVal);
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const setData = ref(settingsStore.setData);
|
||||
const isDarkTheme = computed({
|
||||
get: () => store.state.theme === 'dark',
|
||||
set: () => store.commit('toggleTheme')
|
||||
get: () => settingsStore.theme === 'dark',
|
||||
set: () => settingsStore.toggleTheme()
|
||||
});
|
||||
|
||||
// watch(
|
||||
// () => setData.value,
|
||||
// (newData) => {
|
||||
// console.log('newData', newData);
|
||||
// settingsStore.setSetData(newData);
|
||||
// },
|
||||
// {
|
||||
// deep: true
|
||||
// }
|
||||
// );
|
||||
|
||||
const openAuthor = () => {
|
||||
window.open(setData.value.authorUrl);
|
||||
};
|
||||
@@ -552,16 +542,16 @@ const checkForUpdates = async (isClick = false) => {
|
||||
};
|
||||
|
||||
const openReleasePage = () => {
|
||||
store.commit('setShowUpdateModal', true);
|
||||
settingsStore.showUpdateModal = true;
|
||||
};
|
||||
|
||||
const selectDownloadPath = async () => {
|
||||
const path = await selectDirectory(message);
|
||||
if (path) {
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
downloadPath: path
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -606,7 +596,7 @@ const proxyRules: FormRules = {
|
||||
};
|
||||
|
||||
// 使用 store 中的字体列表
|
||||
const systemFonts = computed(() => store.state.systemFonts);
|
||||
const systemFonts = computed(() => settingsStore.systemFonts);
|
||||
|
||||
// 已选择的字体列表
|
||||
const selectedFonts = ref<string[]>([]);
|
||||
@@ -622,17 +612,17 @@ watch(
|
||||
(newFonts) => {
|
||||
// 如果没有选择任何字体,使用系统默认字体
|
||||
if (newFonts.length === 0) {
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
fontFamily: 'system-ui'
|
||||
});
|
||||
};
|
||||
return;
|
||||
}
|
||||
// 将选择的字体组合成字体列表
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
fontFamily: newFonts.join(',')
|
||||
});
|
||||
};
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
@@ -660,10 +650,10 @@ onMounted(async () => {
|
||||
}
|
||||
// 确保enableRealIP有默认值
|
||||
if (setData.value.enableRealIP === undefined) {
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
enableRealIP: false
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -686,7 +676,7 @@ const handleProxyConfirm = async () => {
|
||||
try {
|
||||
await formRef.value?.validate();
|
||||
// 保存代理配置时保留enable状态
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
proxyConfig: {
|
||||
enable: setData.value.proxyConfig?.enable || false,
|
||||
@@ -694,7 +684,7 @@ const handleProxyConfirm = async () => {
|
||||
host: proxyForm.value.host,
|
||||
port: proxyForm.value.port
|
||||
}
|
||||
});
|
||||
};
|
||||
showProxyModal.value = false;
|
||||
message.success(t('settings.network.messages.proxySuccess'));
|
||||
} catch (err) {
|
||||
@@ -705,20 +695,20 @@ const handleProxyConfirm = async () => {
|
||||
const validateAndSaveRealIP = () => {
|
||||
const ipRegex = /^(\d{1,3}\.){3}\d{1,3}$/;
|
||||
if (!setData.value.realIP || ipRegex.test(setData.value.realIP)) {
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
realIP: setData.value.realIP,
|
||||
enableRealIP: true
|
||||
});
|
||||
};
|
||||
if (setData.value.realIP) {
|
||||
message.success(t('settings.network.messages.realIPSuccess'));
|
||||
}
|
||||
} else {
|
||||
message.error(t('settings.network.messages.realIPError'));
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
realIP: ''
|
||||
});
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -727,11 +717,11 @@ watch(
|
||||
() => setData.value.enableRealIP,
|
||||
(newVal) => {
|
||||
if (!newVal) {
|
||||
store.commit('setSetData', {
|
||||
setData.value = {
|
||||
...setData.value,
|
||||
realIP: '',
|
||||
enableRealIP: false
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -795,7 +785,7 @@ const clearCache = async () => {
|
||||
localStorage.removeItem('favoriteList');
|
||||
break;
|
||||
case 'user':
|
||||
store.commit('logout');
|
||||
userStore.handleLogout();
|
||||
break;
|
||||
case 'settings':
|
||||
if (window.electron) {
|
||||
|
||||
@@ -99,7 +99,6 @@ import { useMessage } from 'naive-ui';
|
||||
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
import { getListDetail } from '@/api/list';
|
||||
import { updatePlaylistTracks } from '@/api/music';
|
||||
@@ -107,6 +106,8 @@ import { getUserDetail, getUserPlaylist, getUserRecord } from '@/api/user';
|
||||
import PlayBottom from '@/components/common/PlayBottom.vue';
|
||||
import SongItem from '@/components/common/SongItem.vue';
|
||||
import MusicList from '@/components/MusicList.vue';
|
||||
import { usePlayerStore } from '@/store/modules/player';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import type { Playlist } from '@/type/listDetail';
|
||||
import type { IUserDetail } from '@/type/user';
|
||||
import { getImgUrl, isMobile, setAnimationClass, setAnimationDelay } from '@/utils';
|
||||
@@ -116,7 +117,8 @@ defineOptions({
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const store = useStore();
|
||||
const userStore = useUserStore();
|
||||
const playerStore = usePlayerStore();
|
||||
const router = useRouter();
|
||||
const userDetail = ref<IUserDetail>();
|
||||
const playList = ref<any[]>([]);
|
||||
@@ -128,7 +130,7 @@ const list = ref<Playlist>();
|
||||
const listLoading = ref(false);
|
||||
const message = useMessage();
|
||||
|
||||
const user = computed(() => store.state.user);
|
||||
const user = computed(() => userStore.user);
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
mounted.value = false;
|
||||
@@ -145,8 +147,8 @@ const checkLoginStatus = () => {
|
||||
}
|
||||
|
||||
// 如果store中没有用户数据,但localStorage中有,则恢复用户数据
|
||||
if (!store.state.user && userData) {
|
||||
store.state.user = JSON.parse(userData);
|
||||
if (!userStore.user && userData) {
|
||||
userStore.setUser(JSON.parse(userData));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -184,7 +186,7 @@ const loadData = async () => {
|
||||
console.error('加载用户页面失败:', error);
|
||||
// 如果获取用户数据失败,可能是token过期
|
||||
if (error.response?.status === 401) {
|
||||
store.commit('logout');
|
||||
userStore.logout();
|
||||
router.push('/login');
|
||||
}
|
||||
} finally {
|
||||
@@ -208,17 +210,13 @@ watch(
|
||||
|
||||
// 监听用户状态变化
|
||||
watch(
|
||||
() => store.state.user,
|
||||
() => userStore.user,
|
||||
(newUser) => {
|
||||
if (!mounted.value) return;
|
||||
|
||||
if (!newUser) {
|
||||
router.push('/login');
|
||||
} else {
|
||||
loadPage();
|
||||
if (newUser) {
|
||||
loadUserData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
}
|
||||
);
|
||||
|
||||
// 页面挂载时检查登录状态
|
||||
@@ -271,7 +269,7 @@ const handleRemoveFromPlaylist = async (songId: number) => {
|
||||
|
||||
const handlePlay = () => {
|
||||
const tracks = recordList.value || [];
|
||||
store.commit('setPlayList', tracks);
|
||||
playerStore.setPlayList(tracks);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user