feat: 添加音质选择 优化灰色歌曲解析

This commit is contained in:
alger
2025-01-06 20:54:42 +08:00
parent fcc47dc0ff
commit 020aca7384
12 changed files with 78 additions and 54 deletions

View File

@@ -12,8 +12,8 @@ if (!fs.existsSync(path.resolve(os.tmpdir(), 'anonymous_token'))) {
} }
// 处理解锁音乐请求 // 处理解锁音乐请求
ipcMain.handle('unblock-music', async (_, id) => { ipcMain.handle('unblock-music', async (_, id, data) => {
return unblockMusic(id); return unblockMusic(id, data);
}); });
import server from 'netease-cloud-music-api-alger/server'; import server from 'netease-cloud-music-api-alger/server';

View File

@@ -6,12 +6,13 @@
"host": "127.0.0.1", "host": "127.0.0.1",
"port": 7890 "port": 7890
}, },
"enableRealIP":false, "enableRealIP": false,
"realIP":"", "realIP": "",
"noAnimate": false, "noAnimate": false,
"animationSpeed": 1, "animationSpeed": 1,
"author": "Alger", "author": "Alger",
"authorUrl": "https://github.com/algerkong", "authorUrl": "https://github.com/algerkong",
"musicApiPort": 30488, "musicApiPort": 30488,
"closeAction": "ask" "closeAction": "ask",
"musicQuality": "higher"
} }

View File

@@ -1,8 +1,8 @@
import match from '@unblockneteasemusic/server'; import match from '@unblockneteasemusic/server';
const unblockMusic = async (id: any): Promise<any> => { const unblockMusic = async (id: any, songData: any): Promise<any> => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
match(parseInt(id, 10), ['qq', 'migu', 'kugou', 'joox']) match(parseInt(id, 10), ['qq', 'migu', 'kugou', 'joox'], songData)
.then((data) => { .then((data) => {
resolve({ resolve({
data: { data: {

View File

@@ -12,7 +12,7 @@ declare global {
dragStart: (data: string) => void; dragStart: (data: string) => void;
miniTray: () => void; miniTray: () => void;
restart: () => void; restart: () => void;
unblockMusic: (id: number) => Promise<any>; unblockMusic: (id: number, data: any) => Promise<any>;
}; };
} }
} }

View File

@@ -3,9 +3,32 @@ import { IPlayMusicUrl } from '@/type/music';
import { isElectron } from '@/utils'; import { isElectron } from '@/utils';
import request from '@/utils/request'; import request from '@/utils/request';
import requestMusic from '@/utils/request_music'; import requestMusic from '@/utils/request_music';
import store from '@/store';
// 获取音乐音质详情
export const getMusicQualityDetail = (id: number) => {
return request.get('/song/music/detail', { params: { id } });
};
// 根据音乐Id获取音乐播放URl // 根据音乐Id获取音乐播放URl
export const getMusicUrl = (id: number) => { export const getMusicUrl = async (id: number) => {
return request.get<IPlayMusicUrl>('/song/url', { params: { id } }); const res = await request.get('/song/download/url/v1', {
params: {
id,
level: store.state.setData.musicQuality || 'higher'
}
});
if (res.data.data.url) {
return {data:{ data:[{url:res.data.data.url}]}};
}
return await request.get('/song/url/v1', {
params: {
id,
level: store.state.setData.musicQuality || 'higher'
}
});
}; };
// 获取歌曲详情 // 获取歌曲详情
@@ -18,9 +41,9 @@ export const getMusicLrc = (id: number) => {
return request.get<ILyric>('/lyric', { params: { id } }); return request.get<ILyric>('/lyric', { params: { id } });
}; };
export const getParsingMusicUrl = (id: number) => { export const getParsingMusicUrl = (id: number, data: any) => {
if (isElectron) { if (isElectron) {
return window.api.unblockMusic(id); return window.api.unblockMusic(id, data);
} }
return requestMusic.get<any>('/music', { params: { id } }); return requestMusic.get<any>('/music', { params: { id } });
}; };

View File

@@ -26,9 +26,12 @@ declare module 'vue' {
NMessageProvider: typeof import('naive-ui')['NMessageProvider'] NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NModal: typeof import('naive-ui')['NModal'] NModal: typeof import('naive-ui')['NModal']
NPopover: typeof import('naive-ui')['NPopover'] NPopover: typeof import('naive-ui')['NPopover']
NRadio: typeof import('naive-ui')['NRadio']
NRadioGroup: typeof import('naive-ui')['NRadioGroup']
NScrollbar: typeof import('naive-ui')['NScrollbar'] NScrollbar: typeof import('naive-ui')['NScrollbar']
NSelect: typeof import('naive-ui')['NSelect'] NSelect: typeof import('naive-ui')['NSelect']
NSlider: typeof import('naive-ui')['NSlider'] NSlider: typeof import('naive-ui')['NSlider']
NSpace: typeof import('naive-ui')['NSpace']
NSpin: typeof import('naive-ui')['NSpin'] NSpin: typeof import('naive-ui')['NSpin']
NSwitch: typeof import('naive-ui')['NSwitch'] NSwitch: typeof import('naive-ui')['NSwitch']
NTag: typeof import('naive-ui')['NTag'] NTag: typeof import('naive-ui')['NTag']

View File

@@ -81,6 +81,7 @@ import type { SongResult } from '@/type/music';
import { getImgUrl, isElectron } from '@/utils'; import { getImgUrl, isElectron } from '@/utils';
import { getImageBackground } from '@/utils/linearColor'; import { getImageBackground } from '@/utils/linearColor';
import { getSongUrl } from '@/hooks/MusicListHook'; import { getSongUrl } from '@/hooks/MusicListHook';
import { cloneDeep } from 'lodash';
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@@ -148,7 +149,7 @@ const downloadMusic = async () => {
isDownloading.value = true; isDownloading.value = true;
const loadingMessage = message.loading('正在下载中...', { duration: 0 }); const loadingMessage = message.loading('正在下载中...', { duration: 0 });
const url = await getSongUrl(props.item.id); const url = await getSongUrl(props.item.id, cloneDeep(props.item));
if (!url) { if (!url) {
loadingMessage.destroy(); loadingMessage.destroy();
message.error('获取音乐下载地址失败'); message.error('获取音乐下载地址失败');

View File

@@ -4,31 +4,31 @@ import { getMusicLrc, getMusicUrl, getParsingMusicUrl } from '@/api/music';
import { useMusicHistory } from '@/hooks/MusicHistoryHook'; import { useMusicHistory } from '@/hooks/MusicHistoryHook';
import { audioService } from '@/services/audioService'; import { audioService } from '@/services/audioService';
import type { ILyric, ILyricText, SongResult } from '@/type/music'; import type { ILyric, ILyricText, SongResult } from '@/type/music';
import { getImgUrl, getMusicProxyUrl } from '@/utils'; import { getImgUrl } from '@/utils';
import { getImageLinearBackground } from '@/utils/linearColor'; import { getImageLinearBackground } from '@/utils/linearColor';
import { cloneDeep } from 'lodash';
const musicHistory = useMusicHistory(); const musicHistory = useMusicHistory();
// 获取歌曲url // 获取歌曲url
export const getSongUrl = async (id: number) => { export const getSongUrl = async (id: number, songData: any) => {
const { data } = await getMusicUrl(id); const { data } = await getMusicUrl(id);
let url = ''; let url = '';
try { try {
if (data.data[0].freeTrialInfo || !data.data[0].url) { if (data.data[0].freeTrialInfo || !data.data[0].url) {
const res = await getParsingMusicUrl(id); const res = await getParsingMusicUrl(id, songData);
console.log('res', res);
url = res.data.data.url; url = res.data.data.url;
} }
} catch (error) { } catch (error) {
console.error('error', error); console.error('error', error);
} }
url = url || data.data[0].url; url = url || data.data[0].url;
return getMusicProxyUrl(url); return url;
}; };
const getSongDetail = async (playMusic: SongResult) => { const getSongDetail = async (playMusic: SongResult) => {
playMusic.playLoading = true; playMusic.playLoading = true;
const playMusicUrl = await getSongUrl(playMusic.id); const playMusicUrl = await getSongUrl(playMusic.id, cloneDeep(playMusic));
const { backgroundColor, primaryColor } = const { backgroundColor, primaryColor } =
playMusic.backgroundColor && playMusic.primaryColor playMusic.backgroundColor && playMusic.primaryColor
? playMusic ? playMusic

View File

@@ -6,15 +6,10 @@ import type { SongResult } from '@/type/music';
import { applyTheme, getCurrentTheme, ThemeType } from '@/utils/theme'; import { applyTheme, getCurrentTheme, ThemeType } from '@/utils/theme';
import { isElectron } from '@/utils'; import { isElectron } from '@/utils';
import { likeSong, getLikedList } from '@/api/music'; import { likeSong, getLikedList } from '@/api/music';
import setData from '@/../main/set.json'
// 默认设置 // 默认设置
const defaultSettings = { const defaultSettings = setData;
isProxy: false,
noAnimate: false,
animationSpeed: 1,
author: 'Alger',
authorUrl: 'https://github.com/algerkong'
};
function getLocalStorageItem<T>(key: string, defaultValue: T): T { function getLocalStorageItem<T>(key: string, defaultValue: T): T {
const item = localStorage.getItem(key); const item = localStorage.getItem(key);
@@ -139,7 +134,6 @@ const mutations = {
const actions = { const actions = {
initializeSettings({ commit }: { commit: any }) { initializeSettings({ commit }: { commit: any }) {
if (isElectron) { if (isElectron) {
// const setData = (window as any).electron.ipcRenderer.getStoreValue('set');
const setData = window.electron.ipcRenderer.sendSync('get-store-value', 'set'); const setData = window.electron.ipcRenderer.sendSync('get-store-value', 'set');
commit('setSetData', setData || defaultSettings); commit('setSetData', setData || defaultSettings);
} else { } else {

View File

@@ -54,34 +54,9 @@ export const formatNumber = (num: string | number) => {
return num.toString(); return num.toString();
}; };
const windowData = window as any;
export const getIsMc = () => {
if (!windowData.electron) {
return false;
}
const setData = window.electron.ipcRenderer.sendSync('get-store-value', 'set');
if (setData.isProxy) {
return true;
}
return false;
};
const ProxyUrl = import.meta.env.VITE_API_PROXY;
export const getMusicProxyUrl = (url: string) => {
if (!getIsMc()) {
return url;
}
const PUrl = url.split('').join('+');
return `${ProxyUrl}/mc?url=${PUrl}`;
};
export const getImgUrl = (url: string | undefined, size: string = '') => { export const getImgUrl = (url: string | undefined, size: string = '') => {
const bdUrl = 'https://image.baidu.com/search/down?url=';
const imgUrl = `${url}?param=${size}`; const imgUrl = `${url}?param=${size}`;
if (!getIsMc()) { return imgUrl;
return imgUrl;
}
return `${bdUrl}${encodeURIComponent(imgUrl)}`;
}; };
export const isMobile = computed(() => { export const isMobile = computed(() => {

View File

@@ -44,7 +44,9 @@ request.interceptors.request.use(
}; };
const token = localStorage.getItem('token'); const token = localStorage.getItem('token');
if (token) { if (token) {
config.params.cookie = token; config.params.cookie = token + ' os=pc;';
}else{
config.params.cookie = 'os=pc;';
} }
} }

View File

@@ -168,6 +168,27 @@
/> />
</div> </div>
</div> </div>
<div class="set-item">
<div>
<div class="set-item-title">音质设置</div>
<div class="set-item-content">选择音乐播放音质VIP</div>
</div>
<n-select
v-model:value="setData.musicQuality"
:options="[
{ label: '标准', value: 'standard' },
{ label: '较高', value: 'higher' },
{ label: '极高', value: 'exhigh' },
{ label: '无损', value: 'lossless' },
{ label: 'Hi-Res', value: 'hires' },
{ label: '高清环绕声', value: 'jyeffect' },
{ label: '沉浸环绕声', value: 'sky' },
{ label: '杜比全景声', value: 'dolby' },
{ label: '超清母带', value: 'jymaster' }
]"
style="width: 160px"
/>
</div>
</div> </div>
<PlayBottom/> <PlayBottom/>
<n-modal <n-modal
@@ -247,6 +268,10 @@ const setData = computed(() => {
port: 7890 port: 7890
}; };
} }
// 确保音质设置存在
if (!data.musicQuality) {
data.musicQuality = 'higher';
}
return data; return data;
}); });