Merge branch 'electron'

# Conflicts:
#	src/store/actions.js
#	src/store/mutations.js
This commit is contained in:
qier222 2020-11-23 16:48:18 +08:00
commit 7d32e8f3bf
291 changed files with 23897 additions and 161 deletions

View file

@ -1,6 +1,6 @@
<template>
<div id="app">
<Navbar />
<Navbar ref="navbar" />
<main>
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
@ -25,6 +25,7 @@
import Navbar from "./components/Navbar.vue";
import Player from "./components/Player.vue";
import GlobalEvents from "vue-global-events";
import { ipcRenderer } from "./electron/ipcRenderer";
export default {
name: "App",
@ -33,6 +34,16 @@ export default {
Player,
GlobalEvents,
},
data() {
return {
isElectron: process.env.IS_ELECTRON, // true || undefined
};
},
created() {
if (this.isElectron) {
ipcRenderer(this);
}
},
methods: {
play(e) {
e.preventDefault();
@ -121,6 +132,11 @@ a {
}
}
// for electron
body.is-electron::-webkit-scrollbar {
width: 0;
}
/* Let's get this party started */
::-webkit-scrollbar {
width: 8px;

153
src/background.js Normal file
View file

@ -0,0 +1,153 @@
"use strict";
import { app, protocol, BrowserWindow, globalShortcut } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
import { startNeteaseMusicApi } from "./electron/services";
import { initIpcMain } from "./electron/ipcMain.js";
import { createMenu } from "./electron/menu";
import { createTouchBar } from "./electron/touchBar";
import { createDockMenu } from "./electron/dockMenu";
import { createTray } from "./electron/tray.js";
// import { autoUpdater } from "electron-updater"
const isDevelopment = process.env.NODE_ENV !== "production";
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
// ipcMain
initIpcMain(win);
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: "app", privileges: { secure: true, standard: true } },
]);
function createWindow() {
win = new BrowserWindow({
width: 1440,
height: 840,
titleBarStyle: "hiddenInset",
webPreferences: {
webSecurity: false,
nodeIntegration: true,
},
});
win.setMenuBarVisibility(false);
if (process.platform !== "darwin") {
createTray(win);
}
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
if (!process.env.IS_TEST) win.webContents.openDevTools();
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadURL("app://./index.html");
}
win.on("closed", () => {
win = null;
});
return win;
}
// Quit when all windows are closed.
app.on("window-all-closed", () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow();
}
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
// start netease music api
startNeteaseMusicApi();
// Install Vue Devtools xtension
if (isDevelopment && !process.env.IS_TEST) {
try {
await installExtension(VUEJS_DEVTOOLS);
} catch (e) {
console.error("Vue Devtools failed to install:", e.toString());
}
}
// Register shortcut for debug
globalShortcut.register("CommandOrControl+K", function () {
win.webContents.openDevTools();
});
// create window
createWindow();
win.once("ready-to-show", () => {
win.show();
});
// create menu
createMenu(win);
// create dock menu for macOS
app.dock.setMenu(createDockMenu(win));
// create touchbar
win.setTouchBar(createTouchBar(win));
// autoUpdater.checkForUpdatesAndNotify()
});
// autoUpdater.on("checking-for-update", () => {});
// autoUpdater.on("update-available", info => {
// console.log(info);
// dialog.showMessageBox({
// title: "新版本发布",
// message: "有新内容更新,稍后将重新为您安装",
// buttons: ["确定"],
// type: "info",
// noLink: true
// });
// });
// autoUpdater.on("update-downloaded", info => {
// console.log(info);
// autoUpdater.quitAndInstall();
// });
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === "win32") {
process.on("message", (data) => {
if (data === "graceful-exit") {
app.quit();
}
});
} else {
process.on("SIGTERM", () => {
app.quit();
});
}
}
// Make sure the app is singleton.
function initialize() {
const shouldQuit = !app.requestSingleInstanceLock();
if (shouldQuit) return app.quit();
}
initialize();

View file

@ -35,6 +35,7 @@
<svg-icon icon-class="search" />
<div class="input">
<input
ref="searchInput"
:placeholder="inputFocus ? '' : $t('nav.search')"
v-model="keywords"
@keydown.enter="goToSearchPage"

View file

@ -18,7 +18,7 @@
<div class="controls">
<div class="playing">
<img
:src="currentTrack.al.picUrl | resizeImage(224)"
:src="currentTrack.al && currentTrack.al.picUrl | resizeImage(224)"
@click="goToAlbum"
/>
<div class="track-info">
@ -141,9 +141,12 @@ export default {
oldVolume: 0.5,
};
},
created() {
mounted() {
setInterval(() => {
this.progress = ~~this.howler.seek();
// fix _id
if (this.howler && this.howler._sounds[0]._id) {
this.progress = ~~this.howler.seek();
}
}, 1000);
if (isAccountLoggedIn()) {
userLikedSongsIDs(this.data.user.userId).then((data) => {
@ -167,9 +170,12 @@ export default {
},
playing() {
if (this.howler.state() === "loading") {
this.updatePlayerState({ key: "playing", value: true });
return true;
}
return this.howler.playing();
const status = this.howler.playing();
this.updatePlayerState({ key: "playing", value: status });
return status;
},
progressMax() {
let max = ~~(this.currentTrack.dt / 1000);

25
src/electron/dockMenu.js Normal file
View file

@ -0,0 +1,25 @@
const { Menu } = require("electron");
export function createDockMenu(win) {
return Menu.buildFromTemplate([
{
label: "Play",
click() {
win.webContents.send("play");
},
},
{ type: "separator" },
{
label: "Next",
click() {
win.webContents.send("next");
},
},
{
label: "Previous",
click() {
win.webContents.send("previous");
},
},
]);
}

19
src/electron/ipcMain.js Normal file
View file

@ -0,0 +1,19 @@
import { app, ipcMain } from "electron";
export function initIpcMain(win) {
// Make vuex copy for electron.
global.vuexCopy = null;
// 同步 vuex 状态,由于 player 有循环引用问题,拷贝部分属性
ipcMain.on("vuex-state", (e, state) => {
global.vuexCopy = state;
});
ipcMain.on("close", () => {
win.close();
app.quit();
});
ipcMain.on("minimize", () => {
win.minimize();
});
}

View file

@ -0,0 +1,49 @@
export function ipcRenderer(vueInstance) {
const self = vueInstance;
// 添加专有的类名
document.body.classList.add("is-electron");
// ipc message channel
const electron = window.require("electron");
const ipcRenderer = electron.ipcRenderer;
// listens to the main process 'changeRouteTo' event and changes the route from
// inside this Vue instance, according to what path the main process requires.
// responds to Menu click() events at the main process and changes the route accordingly.
ipcRenderer.on("changeRouteTo", (event, path) => {
self.$router.push(path);
});
ipcRenderer.on("search", () => {
// 触发数据响应
self.$refs.navbar.$refs.searchInput.focus();
self.$refs.navbar.inputFocus = true;
});
ipcRenderer.on("play", () => {
self.$refs.player.play();
});
ipcRenderer.on("next", () => {
self.$refs.player.next();
});
ipcRenderer.on("previous", () => {
self.$refs.player.previous();
});
ipcRenderer.on("increaseVolume", () => {
if (self.$refs.player.volume + 0.1 >= 1) {
return (self.$refs.player.volume = 1);
}
self.$refs.player.volume += 0.1;
});
ipcRenderer.on("decreaseVolume", () => {
if (self.$refs.player.volume - 0.1 <= 0) {
return (self.$refs.player.volume = 0);
}
self.$refs.player.volume -= 0.1;
});
ipcRenderer.on("like", () => {
self.$refs.player.likeCurrentSong();
});
ipcRenderer.on("repeat", () => {
self.$refs.player.repeat();
});
ipcRenderer.on("shuffle", () => {
self.$refs.player.shuffle();
});
}

205
src/electron/menu.js Normal file
View file

@ -0,0 +1,205 @@
const { app, Menu } = require("electron");
// import { autoUpdater } from "electron-updater"
// const version = app.getVersion();
const isMac = process.platform === "darwin";
export function createMenu(win) {
let menu = null;
const template = [
...(isMac
? [
{
label: app.name,
submenu: [
{ role: "about" },
{ type: "separator" },
{ role: "services" },
{ type: "separator" },
{ type: "separator" },
{
label: "Preferences...",
accelerator: (() => (isMac ? "CmdOrCtrl+," : "Ctrl+,"))(),
click: () => {
win.webContents.send("changeRouteTo", "/settings");
},
role: "preferences",
},
{ type: "separator" },
{ role: "hide" },
{ role: "hideothers" },
{ role: "unhide" },
{ type: "separator" },
{ role: "quit" },
],
},
]
: []),
{
label: "Edit",
submenu: [
{ role: "undo" },
{ role: "redo" },
{ type: "separator" },
{ role: "cut" },
{ role: "copy" },
{ role: "paste" },
...(isMac
? [
{ role: "delete" },
{ role: "selectAll" },
{ type: "separator" },
{
label: "Speech",
submenu: [{ role: "startspeaking" }, { role: "stopspeaking" }],
},
]
: [{ role: "delete" }, { type: "separator" }, { role: "selectAll" }]),
{
label: "Search",
accelerator: "CmdOrCtrl+F",
click: () => {
win.webContents.send("search");
},
},
],
},
{
label: "Controls",
submenu: [
{
label: "Play",
accelerator: "Space",
click: () => {
win.webContents.send("play");
},
},
{
label: "Next",
accelerator: "CmdOrCtrl+Right",
click: () => {
win.webContents.send("next");
},
},
{
label: "Previous",
accelerator: "CmdOrCtrl+Left",
click: () => {
win.webContents.send("previous");
},
},
{
label: "Increase Volume",
accelerator: "CmdOrCtrl+Up",
click: () => {
win.webContents.send("increaseVolume");
},
},
{
label: "Decrease Volume",
accelerator: "CmdOrCtrl+Down",
click: () => {
win.webContents.send("decreaseVolume");
},
},
{
label: "Like",
accelerator: "CmdOrCtrl+L",
click: () => {
win.webContents.send("like");
},
},
{
label: "Repeat",
accelerator: "Alt+R",
click: () => {
win.webContents.send("repeat");
},
},
{
label: "Shuffle",
accelerator: "Alt+S",
click: () => {
win.webContents.send("shuffle");
},
},
],
},
{
label: "Window",
submenu: [
{ role: "minimize" },
{ role: "zoom" },
{ role: "reload" },
{ role: "forcereload" },
{ role: "toggledevtools" },
{ type: "separator" },
{ role: "togglefullscreen" },
...(isMac
? [
{ type: "separator" },
{ role: "front" },
{ type: "separator" },
{
role: "window",
id: "window",
label: "YesPlayMusic",
type: "checkbox",
checked: true,
click: () => {
const current = menu.getMenuItemById("window");
if (current.checked === false) {
win.hide();
} else {
win.show();
}
},
},
]
: [{ role: "close" }]),
],
},
{
label: "Help",
submenu: [
{
label: "Github",
click: async () => {
const { shell } = require("electron");
await shell.openExternal("https://github.com/qier222/YesPlayMusic");
},
},
{
label: "Electron",
click: async () => {
const { shell } = require("electron");
await shell.openExternal("https://electronjs.org");
},
},
],
},
];
// for window
// if (process.platform === "win32") {
// template.push({
// label: "Help",
// submenu: [
// {
// label: `Current version v${version}`,
// enabled: false,
// },
// {
// label: "Check for update",
// accelerator: "Ctrl+U",
// click: (item, focusedWindow) => {
// win = focusedWindow;
// updateSource = "menu";
// autoUpdater.checkForUpdates();
// },
// },
// ],
// });
// }
menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}

58
src/electron/services.js Normal file
View file

@ -0,0 +1,58 @@
const express = require("express");
const bodyParser = require("body-parser");
const cache = require("../../netease_api/util/apicache").middleware;
const fileUpload = require("express-fileupload");
import routes from "../../netease_api/routes";
export function startNeteaseMusicApi() {
// Integrate API
const app = express();
// CORS & Preflight request
app.use((req, res, next) => {
if (req.path !== "/" && !req.path.includes(".")) {
res.set({
"Access-Control-Allow-Credentials": true,
"Access-Control-Allow-Origin": req.headers.origin || "*",
"Access-Control-Allow-Headers": "X-Requested-With,Content-Type",
"Access-Control-Allow-Methods": "PUT,POST,GET,DELETE,OPTIONS",
"Content-Type": "application/json; charset=utf-8",
});
}
req.method === "OPTIONS" ? res.status(204).end() : next();
});
// cookie parser
app.use((req, res, next) => {
req.cookies = {};
(req.headers.cookie || "").split(/\s*;\s*/).forEach((pair) => {
let crack = pair.indexOf("=");
if (crack < 1 || crack == pair.length - 1) return;
req.cookies[
decodeURIComponent(pair.slice(0, crack)).trim()
] = decodeURIComponent(pair.slice(crack + 1)).trim();
});
next();
});
// body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(fileUpload());
// cache
app.use(cache("2 minutes", (req, res) => res.statusCode === 200));
// router
Object.keys(routes).forEach((route) => {
app.use(route, routes[route]);
});
const port = process.env.PORT || 10754;
const host = process.env.HOST || "127.0.0.1";
app.server = app.listen(port, host, () => {
console.log(`server running @ http://${host ? host : "localhost"}:${port}`);
});
}

131
src/electron/touchbar.js Normal file
View file

@ -0,0 +1,131 @@
const { TouchBar, nativeImage, ipcMain } = require("electron");
const path = require("path");
const {
TouchBarButton,
TouchBarGroup,
TouchBarSpacer,
TouchBarSegmentedControl,
} = TouchBar;
function getNativeIcon(name, width = 24, height = 24) {
return nativeImage
.createFromPath(path.join(__static, "img/icons/touchbar/", name))
.resize({
width,
height,
});
}
export function createSegmentedControl(renderer) {
const segments = [
{
icon: getNativeIcon("previous.png"),
},
{
icon: getNativeIcon("play.png", 20, 20),
},
{
icon: getNativeIcon("next.png"),
},
];
const segmentedControl = new TouchBarSegmentedControl({
segments,
change: (selectedIndex) => {
const temp = Object.assign([], segmentedControl.segments);
if (selectedIndex === 0) {
renderer.send("previous");
}
if (selectedIndex === 1) {
ipcMain.on("vuex-state", (e, { player }) => {
const playing = player.playing;
if (playing === true) {
// To be paused
temp[1].icon = getNativeIcon("play.png", 20, 20);
segmentedControl.segments = temp;
} else {
temp[1].icon = getNativeIcon("play.png", 20, 20);
segmentedControl.segments = temp;
}
});
renderer.send("play");
}
if (selectedIndex === 2) {
renderer.send("next");
}
},
mode: "buttons",
});
return segmentedControl;
}
export function createPreferGroup(renderer) {
const search = new TouchBarButton({
icon: getNativeIcon("search.png", 22, 22),
click: () => {
renderer.send("search");
},
});
const like = new TouchBarButton({
icon: getNativeIcon("like.png"),
click: () => {
ipcMain.on("vuex-state", (e, { liked, player }) => {
const currentTrack = player.currentTrack;
if (liked.songs.includes(currentTrack.id)) {
like.icon = getNativeIcon("liked.png");
} else {
like.icon = getNativeIcon("like.png");
}
});
renderer.send("like");
},
});
const repeat = new TouchBarButton({
icon: getNativeIcon("repeat.png"),
click: () => {
ipcMain.on("vuex-state", (e, { player }) => {
const repeat = player.repeat;
if (repeat === "on") {
repeat.icon = getNativeIcon("repeat.png");
} else if (repeat === "one") {
repeat.icon = getNativeIcon("repeat.png");
} else {
repeat.icon = getNativeIcon("repeat.png");
}
});
renderer.send("repeat");
},
});
const shuffle = new TouchBarButton({
icon: getNativeIcon("shuffle.png"),
click: () => {
ipcMain.on("vuex-state", (e, { player }) => {
const shuffle = player.shuffle;
if (shuffle === true) {
shuffle.icon = getNativeIcon("shuffle.png");
} else {
shuffle.icon = getNativeIcon("shuffle.png");
}
});
renderer.send("shuffle");
},
});
return new TouchBar({
items: [search, like, repeat, shuffle],
});
}
export function createTouchBar(window) {
const renderer = window.webContents;
const segmentedControl = createSegmentedControl(renderer);
const preferGroup = createPreferGroup(renderer);
const touchBar = new TouchBar({
items: [
new TouchBarGroup({ items: preferGroup }),
new TouchBarSpacer({ size: "large" }),
segmentedControl,
new TouchBarSpacer({ size: "large" }),
],
});
return touchBar;
}

104
src/electron/touchbar1.js Normal file
View file

@ -0,0 +1,104 @@
// 运用 ipdMain 请求用户喜欢的歌手的数据,随机抽几个歌手进行随机
const { TouchBar } = require("electron");
const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar;
let spinning = false;
// Reel labels
const reel1 = new TouchBarLabel();
const reel2 = new TouchBarLabel();
const reel3 = new TouchBarLabel();
// Spin result label
const result = new TouchBarLabel();
// Spin button
const spin = new TouchBarButton({
label: "🎰 Spin",
backgroundColor: "#7851A9",
click: () => {
// Ignore clicks if already spinning
if (spinning) {
return;
}
spinning = true;
result.label = "";
let timeout = 10;
const spinLength = 4 * 1000; // 4 seconds
const startTime = Date.now();
const spinReels = () => {
updateReels();
if (Date.now() - startTime >= spinLength) {
finishSpin();
} else {
// Slow down a bit on each spin
timeout *= 1.1;
setTimeout(spinReels, timeout);
}
};
spinReels();
},
});
const getRandomValue = () => {
const values = ["🍒", "💎", "7⃣", "🍊", "🔔", "⭐", "🍇", "🍀"];
return values[Math.floor(Math.random() * values.length)];
};
const updateReels = () => {
reel1.label = getRandomValue();
reel2.label = getRandomValue();
reel3.label = getRandomValue();
};
const finishSpin = () => {
const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size;
if (uniqueValues === 1) {
// All 3 values are the same
result.label = "💰 Jackpot!";
result.textColor = "#FDFF00";
} else if (uniqueValues === 2) {
// 2 values are the same
result.label = "😍 Winner!";
result.textColor = "#FDFF00";
} else {
// No values are the same
result.label = "🙁 Spin Again";
result.textColor = null;
}
spinning = false;
};
const touchBar = new TouchBar({
items: [
spin,
new TouchBarSpacer({ size: "large" }),
reel1,
new TouchBarSpacer({ size: "small" }),
reel2,
new TouchBarSpacer({ size: "small" }),
reel3,
new TouchBarSpacer({ size: "large" }),
result,
],
});
// let window
// app.whenReady().then(() => {
// window = new BrowserWindow({
// frame: false,
// titleBarStyle: 'hiddenInset',
// backgroundColor: '#000'
// })
// window.loadURL('about:blank')
// window.setTouchBar(touchBar)
// })
module.exports = touchBar;

21
src/electron/tray.js Normal file
View file

@ -0,0 +1,21 @@
import path from "path";
import { nativeImage, Tray } from "electron";
export function createTray(win) {
let icon = nativeImage
.createFromPath(path.join(__static, "img/icons/menu@88.png"))
.resize({
height: 20,
width: 20,
});
let tray = new Tray(icon);
tray.on("click", () => {
if (win && win.isVisible()) {
win.hide();
} else {
win.show();
}
});
return tray;
}

View file

@ -2,7 +2,10 @@
import { register } from "register-service-worker";
if (process.env.NODE_ENV === "production") {
if (
process.env.NODE_ENV === "production" &&
process.env.IS_ELECTRON === "undefined"
) {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log(

View file

@ -7,42 +7,46 @@ import initLocalStorage from "./initLocalStorage";
import { Howl, Howler } from "howler";
import { changeAppearance } from "@/utils/common";
import updateApp from "@/utils/updateApp";
import pack from "../../package.json";
import pkg from "../../package.json";
// vuex 自定义插件
import { getBroadcastPlugin } from "./plugins/broadcast";
import saveToLocalStorage from "./plugins/localStorage";
if (localStorage.getItem("appVersion") === null) {
localStorage.setItem("player", JSON.stringify(initLocalStorage.player));
localStorage.setItem("settings", JSON.stringify(initLocalStorage.settings));
localStorage.setItem("data", JSON.stringify(initLocalStorage.data));
localStorage.setItem("appVersion", pack.version);
localStorage.setItem("appVersion", pkg.version);
window.location.reload();
}
updateApp();
const saveToLocalStorage = (store) => {
store.subscribe((mutation, state) => {
// console.log(mutation);
localStorage.setItem("player", JSON.stringify(state.player));
localStorage.setItem("settings", JSON.stringify(state.settings));
localStorage.setItem("data", JSON.stringify(state.data));
});
};
Vue.use(Vuex);
const store = new Vuex.Store({
state: state,
let plugins = [saveToLocalStorage];
if (process.env.IS_ELECTRON === true) {
let vuexBroadCast = getBroadcastPlugin();
plugins.push(vuexBroadCast);
}
const options = {
state,
mutations,
actions,
plugins: [saveToLocalStorage],
});
plugins,
};
const store = new Vuex.Store(options);
store.state.howler = new Howl({
src: [
`https://music.163.com/song/media/outer/url?id=${store.state.player.currentTrack.id}`,
],
html5: true,
format: ["mp3"],
format: ["webm", "mp3"],
});
Howler.volume(store.state.player.volume);
if ([undefined, null].includes(store.state.settings.lang)) {
@ -53,6 +57,7 @@ if ([undefined, null].includes(store.state.settings.lang)) {
}
changeAppearance(store.state.settings.appearance);
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", () => {

View file

@ -0,0 +1,23 @@
export function getBroadcastPlugin() {
const electron = window.require("electron");
const ipcRenderer = electron.ipcRenderer;
return (store) => {
// 第一行初始化第一次的状态
ipcRenderer.send("vuex-state", store.state);
store.subscribe(
(
mutation,
{ data = "", settings = "", player = {}, contextMenu = {}, liked = {} }
) => {
const copyState = { data, settings, player, contextMenu, liked };
ipcRenderer.send("vuex-state", copyState);
}
);
store.subscribe((mutation, state) => {
if (mutation.type === "updateData") {
ipcRenderer.send("updateData", state.data);
}
});
};
}

View file

@ -0,0 +1,8 @@
export default (store) => {
store.subscribe((mutation, state) => {
// console.log(mutation);
localStorage.setItem("player", JSON.stringify(state.player));
localStorage.setItem("settings", JSON.stringify(state.settings));
localStorage.setItem("data", JSON.stringify(state.data));
});
};

View file

@ -34,3 +34,19 @@ export function isUsernameLoggedIn() {
export function isLooseLoggedIn() {
return isAccountLoggedIn() || isUsernameLoggedIn();
}
export function getMusicU(string) {
const temp = string.split(";");
if (!temp.length) {
return undefined;
}
const MUSIC_U = temp.find((item) => item.includes("MUSIC_U"));
if (MUSIC_U) {
return MUSIC_U.split("=")[1];
}
return "";
}
export function setMusicU(key, value) {
return Cookies.set(key, value);
}

View file

@ -1,11 +1,11 @@
import axios from "axios";
// import axios from "axios";
import localforage from "localforage";
import { getMP3 } from "@/api/track";
export function cacheTrack(id) {
let tracks = localforage.createInstance({
name: "tracks",
});
// let tracks = localforage.createInstance({
// name: "tracks",
// });
// TODO: limit cache songs number
// tracks.length().then(function (length) {
@ -18,14 +18,15 @@ export function cacheTrack(id) {
// TODO: cache track details
return getMP3(id).then((data) => {
return axios
.get(data.data[0].url.replace(/^http:/, "https:"), {
responseType: "blob",
})
.then((data) => {
tracks.setItem(`${id}`, { mp3: data.data });
return { mp3: data.data };
});
// return axios
// .get(data.data[0].url.replace(/^http:/, "https:"), {
// responseType: "blob",
// })
// .then((data) => {
// tracks.setItem(`${id}`, { mp3: data.data });
// return { mp3: data.data };
// });
return { mp3: data.data[0].url.replace(/^http:/, "https:") };
});
}

View file

@ -1,7 +1,15 @@
import axios from "axios";
let baseURL = "";
// Web 和 Electron 跑在不同端口避免同时启动时冲突
if (process.env.IS_ELECTRON) {
baseURL = process.env.VUE_APP_ELECTRON_API_URL;
} else {
baseURL = process.env.VUE_APP_NETEASE_API_URL;
}
const service = axios.create({
baseURL: process.env.VUE_APP_NETEASE_API_URL,
baseURL,
withCredentials: true,
timeout: 15000,
});

View file

@ -89,6 +89,7 @@ import { loginWithPhone, loginWithEmail } from "@/api/auth";
import md5 from "crypto-js/md5";
import { mapMutations } from "vuex";
import { userPlaylist } from "@/api/user";
import { getMusicU, setMusicU } from "@/utils/auth";
export default {
name: "Login",
@ -177,6 +178,10 @@ export default {
md5_password: md5(this.password).toString(),
})
.then((data) => {
// MUSIC_U cookie
// 301
const MUSIC_U = getMusicU(data.cookie);
setMusicU("MUSIC_U", MUSIC_U);
if (data.code !== 502) {
this.updateData({ key: "user", value: data.profile });
this.afterLogin();