diff --git a/src/i18n/lang/en-US/login.ts b/src/i18n/lang/en-US/login.ts index 7af66da..71de02f 100644 --- a/src/i18n/lang/en-US/login.ts +++ b/src/i18n/lang/en-US/login.ts @@ -1,22 +1,36 @@ export default { title: { qr: 'QR Code Login', - phone: 'Phone Login' + phone: 'Phone Login', + token: 'Cookie Login' }, qrTip: 'Scan with NetEase Cloud Music APP', phoneTip: 'Login with NetEase Cloud account', + tokenTip: 'Enter a valid NetEase Cloud Music Cookie to login', placeholder: { phone: 'Phone Number', - password: 'Password' + password: 'Password', + token: 'Please enter NetEase Cloud Music Cookie (token)' }, button: { login: 'Login', switchToQr: 'QR Code Login', - switchToPhone: 'Phone Login' + switchToPhone: 'Phone Login', + switchToToken: 'Use Cookie Login', + backToQr: 'Back to QR Code Login', + tokenLogin: 'Cookie Login', + autoGetCookie: 'Auto Get Cookie' }, message: { loginSuccess: 'Login successful', + tokenLoginSuccess: 'Cookie login successful', loadError: 'Error loading login information', - qrCheckError: 'Error checking QR code status' - } + qrCheckError: 'Error checking QR code status', + tokenRequired: 'Please enter Cookie', + tokenInvalid: 'Invalid Cookie, please check and try again', + autoGetCookieSuccess: 'Auto get Cookie successful', + autoGetCookieFailed: 'Auto get Cookie failed', + autoGetCookieTip: 'Will open NetEase Cloud Music login page, please complete login and close the window' + }, + qrTitle: 'NetEase Cloud Music QR Code Login' }; diff --git a/src/i18n/lang/en-US/settings.ts b/src/i18n/lang/en-US/settings.ts index 97601b8..b5d3ebf 100644 --- a/src/i18n/lang/en-US/settings.ts +++ b/src/i18n/lang/en-US/settings.ts @@ -19,6 +19,14 @@ export default { manualTheme: 'Manual Switch', language: 'Language Settings', languageDesc: 'Change display language', + tokenManagement: 'Cookie Management', + tokenManagementDesc: 'Manage NetEase Cloud Music login Cookie', + tokenStatus: 'Current Cookie Status', + tokenSet: 'Set', + tokenNotSet: 'Not Set', + setToken: 'Set Cookie', + modifyToken: 'Modify Cookie', + clearToken: 'Clear Cookie', font: 'Font Settings', fontDesc: 'Select fonts, prioritize fonts in order', fontScope: { @@ -185,6 +193,7 @@ export default { hideLyrics: 'Hide Lyrics', hidePlayBar: 'Hide Play Bar', hideMiniPlayBar: 'Hide Mini Play Bar', + showMiniPlayBar: 'Show Mini Play Bar', backgroundTheme: 'Background Theme', themeOptions: { default: 'Default', @@ -283,5 +292,33 @@ export default { emptyListHint: 'Empty list means allow all IPs', saveSuccess: 'Remote control settings saved', accessInfo: 'Remote control access address:' + }, + cookie: { + title: 'Cookie Settings', + description: 'Please enter NetEase Cloud Music Cookie:', + placeholder: 'Please paste the complete Cookie...', + help: { + format: 'Cookie usually starts with "MUSIC_U="', + source: 'Can be obtained from browser developer tools network requests', + storage: 'Cookie will be automatically saved to local storage after setting' + }, + action: { + save: 'Save Cookie', + paste: 'Paste', + clear: 'Clear' + }, + validation: { + required: 'Please enter Cookie', + format: 'Cookie format may be incorrect, please check if it contains MUSIC_U' + }, + message: { + saveSuccess: 'Cookie saved successfully', + saveError: 'Failed to save Cookie', + pasteSuccess: 'Pasted successfully', + pasteError: 'Paste failed, please copy manually' + }, + info: { + length: 'Current length: {length} characters' + } } }; diff --git a/src/i18n/lang/ja-JP/login.ts b/src/i18n/lang/ja-JP/login.ts index 8883acf..e08c044 100644 --- a/src/i18n/lang/ja-JP/login.ts +++ b/src/i18n/lang/ja-JP/login.ts @@ -1,22 +1,36 @@ export default { title: { qr: 'QRコードログイン', - phone: '電話番号ログイン' + phone: '電話番号ログイン', + token: 'Cookieログイン' }, qrTip: 'NetEase Cloudアプリでログイン', phoneTip: 'NetEase Cloudアカウントでログイン', + tokenTip: '有効なNetEase Cloud MusicのCookieを入力してログイン', placeholder: { phone: '電話番号', - password: 'パスワード' + password: 'パスワード', + token: 'NetEase Cloud MusicのCookie(token)を入力してください' }, button: { login: 'ログイン', switchToQr: 'QRコードログイン', - switchToPhone: '電話番号ログイン' + switchToPhone: '電話番号ログイン', + switchToToken: 'Cookieログインを使用', + backToQr: 'QRコードログインに戻る', + tokenLogin: 'Cookieログイン', + autoGetCookie: 'Cookie自動取得' }, message: { loginSuccess: 'ログイン成功', + tokenLoginSuccess: 'Cookieログイン成功', loadError: 'ログイン情報の読み込み中にエラーが発生しました', - qrCheckError: 'QRコードの状態確認中にエラーが発生しました' - } + qrCheckError: 'QRコードの状態確認中にエラーが発生しました', + tokenRequired: 'Cookieを入力してください', + tokenInvalid: 'Cookieが無効です。確認して再試行してください', + autoGetCookieSuccess: 'Cookie自動取得成功', + autoGetCookieFailed: 'Cookie自動取得失敗', + autoGetCookieTip: 'NetEase Cloud Musicのログインページを開きます。ログイン完了後、ウィンドウを閉じてください' + }, + qrTitle: 'NetEase Cloud Music QRコードログイン' }; \ No newline at end of file diff --git a/src/i18n/lang/ja-JP/settings.ts b/src/i18n/lang/ja-JP/settings.ts index 0b31457..182bf4d 100644 --- a/src/i18n/lang/ja-JP/settings.ts +++ b/src/i18n/lang/ja-JP/settings.ts @@ -19,6 +19,14 @@ export default { manualTheme: '手動切り替え', language: '言語設定', languageDesc: '表示言語を切り替え', + tokenManagement: 'Cookie管理', + tokenManagementDesc: 'NetEase Cloud MusicログインCookieを管理', + tokenStatus: '現在のCookieステータス', + tokenSet: '設定済み', + tokenNotSet: '未設定', + setToken: 'Cookieを設定', + modifyToken: 'Cookieを変更', + clearToken: 'Cookieをクリア', font: 'フォント設定', fontDesc: 'フォントを選択します。前に配置されたフォントが優先されます', fontScope: { @@ -183,6 +191,7 @@ export default { hideLyrics: '歌詞を非表示', hidePlayBar: '再生バーを非表示', hideMiniPlayBar: 'ミニ再生バーを非表示', + showMiniPlayBar: 'ミニ再生バーを表示', backgroundTheme: '背景テーマ', themeOptions: { default: 'デフォルト', @@ -281,5 +290,33 @@ export default { emptyListHint: '空のリストはすべてのIPアクセスを許可することを意味します', saveSuccess: 'リモートコントロール設定を保存しました', accessInfo: 'リモートコントロールアクセスアドレス:' + }, + cookie: { + title: 'Cookie設定', + description: 'NetEase Cloud MusicのCookieを入力してください:', + placeholder: '完全なCookieを貼り付けてください...', + help: { + format: 'Cookieは通常「MUSIC_U=」で始まります', + source: 'ブラウザの開発者ツールのネットワークリクエストから取得できます', + storage: 'Cookie設定後、自動的にローカルストレージに保存されます' + }, + action: { + save: 'Cookieを保存', + paste: '貼り付け', + clear: 'クリア' + }, + validation: { + required: 'Cookieを入力してください', + format: 'Cookie形式が正しくない可能性があります。MUSIC_Uが含まれているか確認してください' + }, + message: { + saveSuccess: 'Cookieの保存に成功しました', + saveError: 'Cookieの保存に失敗しました', + pasteSuccess: '貼り付けに成功しました', + pasteError: '貼り付けに失敗しました。手動でコピーしてください' + }, + info: { + length: '現在の長さ:{length} 文字' + } } }; \ No newline at end of file diff --git a/src/i18n/lang/ko-KR/login.ts b/src/i18n/lang/ko-KR/login.ts index 06a4618..1d44c72 100644 --- a/src/i18n/lang/ko-KR/login.ts +++ b/src/i18n/lang/ko-KR/login.ts @@ -1,22 +1,36 @@ export default { title: { qr: 'QR코드 로그인', - phone: '휴대폰 번호 로그인' + phone: '휴대폰 번호 로그인', + token: 'Cookie 로그인' }, qrTip: '넷이즈 클라우드 뮤직 앱으로 QR코드를 스캔하여 로그인', phoneTip: '넷이즈 클라우드 계정으로 로그인', + tokenTip: '유효한 넷이즈 클라우드 뮤직 Cookie을 입력하여 로그인', placeholder: { phone: '휴대폰 번호', - password: '비밀번호' + password: '비밀번호', + token: '넷이즈 클라우드 뮤직 Cookie(token)을 입력하세요' }, button: { login: '로그인', switchToQr: 'QR코드 로그인', - switchToPhone: '휴대폰 번호 로그인' + switchToPhone: '휴대폰 번호 로그인', + switchToToken: 'Cookie 로그인 사용', + backToQr: 'QR코드 로그인으로 돌아가기', + tokenLogin: 'Cookie 로그인', + autoGetCookie: 'Cookie 자동 가져오기' }, message: { loginSuccess: '로그인 성공', + tokenLoginSuccess: 'Cookie 로그인 성공', loadError: '로그인 정보 로드 중 오류 발생', - qrCheckError: 'QR코드 상태 확인 중 오류 발생' - } + qrCheckError: 'QR코드 상태 확인 중 오류 발생', + tokenRequired: 'Cookie을 입력하세요', + tokenInvalid: 'Cookie이 유효하지 않습니다. 확인 후 다시 시도하세요', + autoGetCookieSuccess: 'Cookie 자동 가져오기 성공', + autoGetCookieFailed: 'Cookie 자동 가져오기 실패', + autoGetCookieTip: '넷이즈 클라우드 뮤직 로그인 페이지를 열겠습니다. 로그인 완료 후 창을 닫아주세요' + }, + qrTitle: '넷이즈 클라우드 뮤직 QR코드 로그인' }; \ No newline at end of file diff --git a/src/i18n/lang/ko-KR/settings.ts b/src/i18n/lang/ko-KR/settings.ts index 0b30a5e..f5621c2 100644 --- a/src/i18n/lang/ko-KR/settings.ts +++ b/src/i18n/lang/ko-KR/settings.ts @@ -19,6 +19,14 @@ export default { manualTheme: '수동 전환', language: '언어 설정', languageDesc: '표시 언어 전환', + tokenManagement: 'Cookie 관리', + tokenManagementDesc: '넷이즈 클라우드 뮤직 로그인 Cookie 관리', + tokenStatus: '현재 Cookie 상태', + tokenSet: '설정됨', + tokenNotSet: '설정되지 않음', + setToken: 'Cookie 설정', + modifyToken: 'Cookie 수정', + clearToken: 'Cookie 지우기', font: '폰트 설정', fontDesc: '폰트 선택, 앞에 있는 폰트를 우선 사용', fontScope: { @@ -183,6 +191,7 @@ export default { hideLyrics: '가사 숨기기', hidePlayBar: '재생바 숨기기', hideMiniPlayBar: '미니 재생바 숨기기', + showMiniPlayBar: '미니 재생바 표시', backgroundTheme: '배경 테마', themeOptions: { default: '기본', @@ -281,5 +290,33 @@ export default { emptyListHint: '빈 목록은 모든 IP 액세스를 허용함을 의미합니다', saveSuccess: '원격 제어 설정이 저장되었습니다', accessInfo: '원격 제어 액세스 주소:' + }, + cookie: { + title: 'Cookie 설정', + description: '넷이즈 클라우드 뮤직의 Cookie를 입력하세요:', + placeholder: '완전한 Cookie를 붙여넣으세요...', + help: { + format: 'Cookie는 일반적으로 "MUSIC_U="로 시작합니다', + source: '브라우저 개발자 도구의 네트워크 요청에서 얻을 수 있습니다', + storage: 'Cookie 설정 후 자동으로 로컬 저장소에 저장됩니다' + }, + action: { + save: 'Cookie 저장', + paste: '붙여넣기', + clear: '지우기' + }, + validation: { + required: 'Cookie를 입력하세요', + format: 'Cookie 형식이 올바르지 않을 수 있습니다. MUSIC_U가 포함되어 있는지 확인하세요' + }, + message: { + saveSuccess: 'Cookie 저장 성공', + saveError: 'Cookie 저장 실패', + pasteSuccess: '붙여넣기 성공', + pasteError: '붙여넣기 실패, 수동으로 복사하세요' + }, + info: { + length: '현재 길이: {length} 문자' + } } }; \ No newline at end of file diff --git a/src/i18n/lang/zh-CN/login.ts b/src/i18n/lang/zh-CN/login.ts index 2b86294..8741f38 100644 --- a/src/i18n/lang/zh-CN/login.ts +++ b/src/i18n/lang/zh-CN/login.ts @@ -1,22 +1,36 @@ export default { title: { qr: '扫码登录', - phone: '手机号登录' + phone: '手机号登录', + token: 'Cookie登录' }, qrTip: '使用网易云APP扫码登录', phoneTip: '使用网易云账号登录', + tokenTip: '输入有效的网易云音乐Cookie即可登录', placeholder: { phone: '手机号', - password: '密码' + password: '密码', + token: '请输入网易云音乐Cookie(token)' }, button: { login: '登录', switchToQr: '扫码登录', - switchToPhone: '手机号登录' + switchToPhone: '手机号登录', + switchToToken: '使用Cookie登录', + backToQr: '返回二维码登录', + tokenLogin: 'Cookie登录', + autoGetCookie: '自动获取Cookie' }, message: { loginSuccess: '登录成功', + tokenLoginSuccess: 'Cookie登录成功', loadError: '加载登录信息时出错', - qrCheckError: '检查二维码状态时出错' - } + qrCheckError: '检查二维码状态时出错', + tokenRequired: '请输入Cookie', + tokenInvalid: 'Cookie无效,请检查后重试', + autoGetCookieSuccess: '自动获取Cookie成功', + autoGetCookieFailed: '自动获取Cookie失败', + autoGetCookieTip: '将打开网易云音乐登录页面,请完成登录后关闭窗口' + }, + qrTitle: '扫码登录网易云音乐' }; diff --git a/src/i18n/lang/zh-CN/settings.ts b/src/i18n/lang/zh-CN/settings.ts index a5684c4..df40155 100644 --- a/src/i18n/lang/zh-CN/settings.ts +++ b/src/i18n/lang/zh-CN/settings.ts @@ -19,6 +19,14 @@ export default { manualTheme: '手动切换', language: '语言设置', languageDesc: '切换显示语言', + tokenManagement: 'Cookie管理', + tokenManagementDesc: '管理网易云音乐登录Cookie', + tokenStatus: '当前Cookie状态', + tokenSet: '已设置', + tokenNotSet: '未设置', + setToken: '设置Cookie', + modifyToken: '修改Cookie', + clearToken: '清除Cookie', font: '字体设置', fontDesc: '选择字体,优先使用排在前面的字体', fontScope: { @@ -183,6 +191,7 @@ export default { hideLyrics: '隐藏歌词', hidePlayBar: '隐藏播放栏', hideMiniPlayBar: '隐藏迷你播放栏', + showMiniPlayBar: '显示迷你播放栏', backgroundTheme: '背景主题', themeOptions: { default: '默认', @@ -281,5 +290,33 @@ export default { emptyListHint: '空列表表示允许所有IP访问', saveSuccess: '远程控制设置已保存', accessInfo: '远程控制访问地址:' + }, + cookie: { + title: 'Cookie设置', + description: '请输入网易云音乐的Cookie:', + placeholder: '请粘贴完整的Cookie...', + help: { + format: 'Cookie通常以 "MUSIC_U=" 开头', + source: '可以从浏览器开发者工具的网络请求中获取', + storage: 'Cookie设置后将自动保存到本地存储' + }, + action: { + save: '保存Cookie', + paste: '粘贴', + clear: '清空' + }, + validation: { + required: '请输入Cookie', + format: 'Cookie格式可能不正确,请检查是否包含MUSIC_U' + }, + message: { + saveSuccess: 'Cookie保存成功', + saveError: 'Cookie保存失败', + pasteSuccess: '粘贴成功', + pasteError: '粘贴失败,请手动复制' + }, + info: { + length: '当前长度:{length} 字符' + } } }; diff --git a/src/i18n/lang/zh-Hant/login.ts b/src/i18n/lang/zh-Hant/login.ts index 7c8867e..64756e8 100644 --- a/src/i18n/lang/zh-Hant/login.ts +++ b/src/i18n/lang/zh-Hant/login.ts @@ -1,22 +1,36 @@ export default { title: { qr: '掃碼登入', - phone: '手機號登入' + phone: '手機號登入', + token: 'Cookie登入' }, qrTip: '使用網易雲APP掃碼登入', phoneTip: '使用網易雲帳號登入', + tokenTip: '輸入有效的網易雲音樂Cookie即可登入', placeholder: { phone: '手機號', - password: '密碼' + password: '密碼', + token: '請輸入網易雲音樂Cookie(token)' }, button: { login: '登入', switchToQr: '掃碼登入', - switchToPhone: '手機號登入' + switchToPhone: '手機號登入', + switchToToken: '使用Cookie登入', + backToQr: '返回二維碼登入', + tokenLogin: 'Cookie登入', + autoGetCookie: '自動取得Cookie' }, message: { loginSuccess: '登入成功', + tokenLoginSuccess: 'Cookie登入成功', loadError: '載入登入資訊時出錯', - qrCheckError: '檢查二維碼狀態時出錯' - } + qrCheckError: '檢查二維碼狀態時出錯', + tokenRequired: '請輸入Cookie', + tokenInvalid: 'Cookie無效,請檢查後重試', + autoGetCookieSuccess: '自動取得Cookie成功', + autoGetCookieFailed: '自動取得Cookie失敗', + autoGetCookieTip: '將開啟網易雲音樂登入頁面,請完成登入後關閉視窗' + }, + qrTitle: '掃碼登入網易雲音樂' }; diff --git a/src/i18n/lang/zh-Hant/settings.ts b/src/i18n/lang/zh-Hant/settings.ts index 6d7d877..4468c19 100644 --- a/src/i18n/lang/zh-Hant/settings.ts +++ b/src/i18n/lang/zh-Hant/settings.ts @@ -19,6 +19,14 @@ export default { manualTheme: '手動切換', language: '語言設定', languageDesc: '切換顯示語言', + tokenManagement: 'Cookie管理', + tokenManagementDesc: '管理網易雲音樂登入Cookie', + tokenStatus: '目前Cookie狀態', + tokenSet: '已設定', + tokenNotSet: '未設定', + setCookie: '設定Cookie', + modifyToken: '修改Cookie', + clearToken: '清除Cookie', font: '字體設定', fontDesc: '選擇字體,優先使用排在前面的字體', fontScope: { @@ -183,6 +191,7 @@ export default { hideLyrics: '隱藏歌詞', hidePlayBar: '隱藏播放列', hideMiniPlayBar: '隱藏迷你播放列', + showMiniPlayBar: '顯示迷你播放列', backgroundTheme: '背景主題', themeOptions: { default: '預設', @@ -221,5 +230,33 @@ export default { closeColorPicker: '關閉色板' }, placeholder: '#1db954' + }, + cookie: { + title: 'Cookie設定', + description: '請輸入網易雲音樂的Cookie:', + placeholder: '請貼上完整的Cookie...', + help: { + format: 'Cookie通常以 "MUSIC_U=" 開頭', + source: '可以從瀏覽器開發者工具的網路請求中取得', + storage: 'Cookie設定後將自動儲存到本機儲存' + }, + action: { + save: '儲存Cookie', + paste: '貼上', + clear: '清空' + }, + validation: { + required: '請輸入Cookie', + format: 'Cookie格式可能不正確,請檢查是否包含MUSIC_U' + }, + message: { + saveSuccess: 'Cookie儲存成功', + saveError: 'Cookie儲存失敗', + pasteSuccess: '貼上成功', + pasteError: '貼上失敗,請手動複製' + }, + info: { + length: '目前長度:{length} 字元' + } } }; diff --git a/src/main/index.ts b/src/main/index.ts index 0a523a6..efdfa6a 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -8,6 +8,7 @@ import { loadLyricWindow } from './lyric'; import { initializeConfig } from './modules/config'; import { initializeFileManager } from './modules/fileManager'; import { initializeFonts } from './modules/fonts'; +import { initializeLoginWindow } from './modules/loginWindow'; import { initializeRemoteControl } from './modules/remoteControl'; import { initializeShortcuts, registerShortcuts } from './modules/shortcuts'; import { initializeTray, updateCurrentSong, updatePlayState, updateTrayMenu } from './modules/tray'; @@ -41,6 +42,8 @@ function initialize() { initializeWindowManager(); // 初始化字体管理 initializeFonts(); + // 初始化登录窗口 + initializeLoginWindow(); // 创建主窗口 mainWindow = createMainWindow(icon); diff --git a/src/main/modules/loginWindow.ts b/src/main/modules/loginWindow.ts new file mode 100644 index 0000000..b417e03 --- /dev/null +++ b/src/main/modules/loginWindow.ts @@ -0,0 +1,104 @@ +import { BrowserWindow, ipcMain, session } from 'electron'; +import { join } from 'path'; + +import i18n from '../../i18n/main'; + +let loginWindow: BrowserWindow | null = null; + +const loginUrl = 'https://music.163.com/#/login/'; +const loginTitle = i18n.global.t('login.qrTitle'); + +/** + * 打开登录窗口获取Cookie + */ +const openLoginWindow = async (mainWin: BrowserWindow) => { + let loginTimer: NodeJS.Timeout; + + // 如果登录窗口已存在,则聚焦并返回 + if (loginWindow && !loginWindow.isDestroyed()) { + loginWindow.focus(); + return; + } + + const loginSession = session.fromPartition('persist:login'); + + // 清除 Cookie + await loginSession.clearStorageData({ + storages: ['cookies', 'localstorage'], + }); + + loginWindow = new BrowserWindow({ + parent: mainWin, + title: loginTitle, + width: 1280, + height: 800, + center: true, + autoHideMenuBar: true, + webPreferences: { + session: loginSession, + sandbox: false, + webSecurity: false, + preload: join(__dirname, '../../preload/index.js'), + }, + }); + + // 打开网易云登录页面 + loginWindow.loadURL(loginUrl); + + // 阻止新窗口创建 + loginWindow.webContents.setWindowOpenHandler(() => { + return { action: 'deny' }; + }); + + // 检查是否登录 + const checkLogin = async () => { + try { + if (!loginWindow || loginWindow.isDestroyed()) { + if (loginTimer) clearInterval(loginTimer); + return; + } + + const MUSIC_U = await loginSession.cookies.get({ + name: 'MUSIC_U', + }); + + if (MUSIC_U && MUSIC_U?.length > 0) { + if (loginTimer) clearInterval(loginTimer); + const value = `MUSIC_U=${MUSIC_U[0].value};`; + + mainWin?.webContents.send('send-cookies', value); + + // 关闭登录窗口 + loginWindow.destroy(); + loginWindow = null; + } + } catch (error) { + console.error('检查登录状态失败:', error); + } + }; + + // 循环检查登录状态 + loginWindow.webContents.once('did-finish-load', () => { + loginWindow?.show(); + loginTimer = setInterval(checkLogin, 500); + + loginWindow?.on('closed', () => { + if (loginTimer) clearInterval(loginTimer); + loginWindow = null; + }); + }); +}; + +/** + * 初始化登录窗口相关的IPC监听 + */ +export function initializeLoginWindow() { + ipcMain.on('open-login', (event) => { + const mainWin = BrowserWindow.fromWebContents(event.sender); + if (mainWin) { + openLoginWindow(mainWin); + } + }); +} + +export default openLoginWindow; diff --git a/src/renderer/components/login/CookieLogin.vue b/src/renderer/components/login/CookieLogin.vue new file mode 100644 index 0000000..58b29f3 --- /dev/null +++ b/src/renderer/components/login/CookieLogin.vue @@ -0,0 +1,202 @@ + + +