mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-04-15 07:20:49 +08:00
✨ feat: 添加音质选择 优化灰色歌曲解析
This commit is contained in:
@@ -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';
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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: {
|
||||||
|
|||||||
2
src/preload/index.d.ts
vendored
2
src/preload/index.d.ts
vendored
@@ -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>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 } });
|
||||||
};
|
};
|
||||||
|
|||||||
3
src/renderer/components.d.ts
vendored
3
src/renderer/components.d.ts
vendored
@@ -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']
|
||||||
|
|||||||
@@ -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('获取音乐下载地址失败');
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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;';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user