mirror of
https://github.com/imsyy/SPlayer.git
synced 2025-11-25 03:14:57 +08:00
fix: 修复快捷键异常占用 & 去除部分动画效果
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { join } from "path";
|
||||
import { app, protocol, shell, BrowserWindow, globalShortcut } from "electron";
|
||||
import { optimizer, is } from "@electron-toolkit/utils";
|
||||
import { platform, optimizer, is } from "@electron-toolkit/utils";
|
||||
import { startNcmServer } from "@main/startNcmServer";
|
||||
import { startMainServer } from "@main/startMainServer";
|
||||
import { configureAutoUpdater } from "@main/utils/checkUpdates";
|
||||
@@ -49,7 +49,7 @@ class MainProcess {
|
||||
});
|
||||
}
|
||||
|
||||
// 检查上次程序
|
||||
// 单例锁
|
||||
async checkApp() {
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
log.error("已有一个程序正在运行,本次启动阻止");
|
||||
@@ -164,7 +164,7 @@ class MainProcess {
|
||||
// 创建主窗口
|
||||
this.createWindow();
|
||||
// 检测更新
|
||||
configureAutoUpdater(process.platform);
|
||||
configureAutoUpdater();
|
||||
// 创建系统信息
|
||||
createSystemInfo(this.mainWindow);
|
||||
// 引入主 Ipc
|
||||
@@ -173,7 +173,7 @@ class MainProcess {
|
||||
createGlobalShortcut(this.mainWindow);
|
||||
});
|
||||
|
||||
// 在开发模式下默认通过 F12 打开或关闭 DevTools
|
||||
// 开发环境下 F12 打开控制台
|
||||
app.on("browser-window-created", (_, window) => {
|
||||
optimizer.watchWindowShortcuts(window);
|
||||
});
|
||||
@@ -196,7 +196,7 @@ class MainProcess {
|
||||
|
||||
// 当所有窗口都关闭时退出应用,macOS 除外
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
if (!platform.isMacOS) {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,9 +6,19 @@ import { globalShortcut } from "electron";
|
||||
*/
|
||||
const createGlobalShortcut = (win) => {
|
||||
// 刷新程序
|
||||
globalShortcut.register("CommandOrControl+R", () => {
|
||||
globalShortcut.register("CmdOrCtrl+Shift+R", () => {
|
||||
if (win && win.isFocused()) win?.reload();
|
||||
});
|
||||
|
||||
// 打开开发者工具
|
||||
globalShortcut.register("CmdOrCtrl+Shift+I", () => {
|
||||
if (win && win.isFocused()) {
|
||||
win?.webContents.openDevTools({
|
||||
mode: "right",
|
||||
activate: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default createGlobalShortcut;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { join } from "path";
|
||||
import { platform } from "@electron-toolkit/utils";
|
||||
import { Tray, Menu, app, ipcMain, nativeImage, nativeTheme } from "electron";
|
||||
|
||||
// 当前播放歌曲数据
|
||||
@@ -39,7 +40,7 @@ const createSystemInfo = (win) => {
|
||||
mainTray.popUpContextMenu(Menu.buildFromTemplate(createTrayMenu(win)));
|
||||
});
|
||||
// linux 右键菜单
|
||||
if (process.platform === "linux") {
|
||||
if (platform.isLinux) {
|
||||
mainTray.setContextMenu(Menu.buildFromTemplate(createTrayMenu(win)));
|
||||
}
|
||||
};
|
||||
@@ -75,7 +76,7 @@ const createTrayMenu = (win) => {
|
||||
{
|
||||
label: "上一曲",
|
||||
icon: createIcon("prev"),
|
||||
accelerator: "CommandOrControl+Left",
|
||||
accelerator: "CmdOrCtrl+Left",
|
||||
click: () => {
|
||||
win.webContents.send("playNextOrPrev", "prev");
|
||||
},
|
||||
@@ -83,7 +84,7 @@ const createTrayMenu = (win) => {
|
||||
{
|
||||
label: playSongState ? "暂停" : "播放",
|
||||
icon: createIcon(playSongState ? "pause" : "play"),
|
||||
accelerator: "Space",
|
||||
accelerator: "CmdOrCtrl+Space",
|
||||
click: () => {
|
||||
win.webContents.send("playOrPause");
|
||||
},
|
||||
@@ -91,7 +92,7 @@ const createTrayMenu = (win) => {
|
||||
{
|
||||
label: "下一曲",
|
||||
icon: createIcon("next"),
|
||||
accelerator: "CommandOrControl+Right",
|
||||
accelerator: "CmdOrCtrl+Right",
|
||||
click: () => {
|
||||
win.webContents.send("playNextOrPrev", "next");
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<Provider>
|
||||
<!-- 主框架 -->
|
||||
<n-layout :class="['all-layout', status.showFullPlayer ? 'full-player' : null]">
|
||||
<n-layout class="all-layout">
|
||||
<!-- 导航栏 -->
|
||||
<n-layout-header bordered>
|
||||
<MainNav />
|
||||
@@ -183,8 +183,5 @@ onUnmounted(() => {
|
||||
padding: 24px;
|
||||
}
|
||||
}
|
||||
&.full-player {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -35,12 +35,13 @@ import {
|
||||
useNotification,
|
||||
} from "naive-ui";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { siteSettings, siteData } from "@/stores";
|
||||
import { siteSettings, siteStatus } from "@/stores";
|
||||
import themeColorData from "@/assets/themeColor.json";
|
||||
|
||||
const data = siteData();
|
||||
const osThemeRef = useOsTheme();
|
||||
const status = siteStatus();
|
||||
const settings = siteSettings();
|
||||
const osThemeRef = useOsTheme();
|
||||
const { coverTheme } = storeToRefs(status);
|
||||
const { themeType, themeAuto, themeTypeName, themeTypeData, themeAutoCover } =
|
||||
storeToRefs(settings);
|
||||
|
||||
@@ -63,62 +64,63 @@ const changeTheme = () => {
|
||||
|
||||
// 配置主题色
|
||||
const changeThemeColor = (val, isCover = false) => {
|
||||
const color =
|
||||
isCover && Object.keys(val)?.length
|
||||
try {
|
||||
// 获取主色数据
|
||||
const mainColorData =
|
||||
isCover && Object.keys(val)?.length
|
||||
? val[themeType.value]
|
||||
: val !== "custom"
|
||||
? themeColorData[val]
|
||||
: themeTypeData.value;
|
||||
// 微调主题色
|
||||
const primaryColor = isCover ? `rgb(${mainColorData.bg})` : mainColorData.primaryColor;
|
||||
const primaryColorHover = isCover ? `rgba(${mainColorData.bg}, 0.29)` : primaryColor + "29";
|
||||
const primaryColorPressed = isCover ? `rgba(${mainColorData.bg}, 0.26)` : primaryColor + "26";
|
||||
const primaryColorSuppl = isCover ? `rgba(${mainColorData.bg}, 0.05)` : primaryColor + "05";
|
||||
// 自适应主题背景色
|
||||
const coverAutobgCover = isCover
|
||||
? themeType.value === "dark"
|
||||
? val.light.bg
|
||||
: val.dark.bg
|
||||
: val !== "custom"
|
||||
? themeColorData[val]
|
||||
: themeTypeData.value;
|
||||
// 微调主题色
|
||||
const primaryColor = isCover ? `rgb(${color})` : color.primaryColor;
|
||||
const primaryColorHover = isCover ? `rgba(${color}, 0.29)` : primaryColor + "29";
|
||||
const primaryColorPressed = isCover ? `rgba(${color}, 0.26)` : primaryColor + "26";
|
||||
const primaryColorSuppl = isCover ? `rgba(${color}, 0.05)` : primaryColor + "05";
|
||||
// 自适应主题背景色
|
||||
const coverAutobgCover = isCover
|
||||
? themeType.value === "dark"
|
||||
? val.dark.bg
|
||||
: "239, 239, 239"
|
||||
: null;
|
||||
// 更新主题覆盖
|
||||
themeOverrides.value = {
|
||||
common:
|
||||
isCover && Object.keys(val)?.length
|
||||
? {
|
||||
primaryColor,
|
||||
primaryColorHover,
|
||||
primaryColorPressed,
|
||||
primaryColorSuppl,
|
||||
textColor1: `rgba(${color}, 0.9)`,
|
||||
textColor2: `rgba(${color}, 0.82)`,
|
||||
textColor3: `rgba(${color}, 0.52)`,
|
||||
bodyColor: `rgba(${val.dark.mainBg}, 0.52)`,
|
||||
cardColor: `rgb(${coverAutobgCover})`,
|
||||
tagColor: `rgb(${coverAutobgCover})`,
|
||||
modalColor: `rgb(${coverAutobgCover})`,
|
||||
popoverColor: `rgb(${coverAutobgCover})`,
|
||||
}
|
||||
: color,
|
||||
Icon: { color: isCover ? primaryColor : null },
|
||||
};
|
||||
if (!isCover) themeTypeData.value = color;
|
||||
// 更新全局颜色变量
|
||||
setCssVariable("--main-color", primaryColor);
|
||||
setCssVariable(
|
||||
"--main-color-bg",
|
||||
isCover ? `rgb(${val[themeType.value]?.bg})` : "rgb(16, 16, 20)",
|
||||
);
|
||||
setCssVariable("--main-second-color", primaryColorHover);
|
||||
setCssVariable("--main-boxshadow-color", primaryColorPressed);
|
||||
setCssVariable("--main-boxshadow-hover-color", primaryColorSuppl);
|
||||
: "239, 239, 239"
|
||||
: null;
|
||||
// 更新主题覆盖
|
||||
themeOverrides.value = {
|
||||
common:
|
||||
isCover && Object.keys(val)?.length
|
||||
? {
|
||||
primaryColor,
|
||||
primaryColorHover,
|
||||
primaryColorPressed,
|
||||
primaryColorSuppl,
|
||||
textColor1: `rgba(${mainColorData.bg}, 0.9)`,
|
||||
textColor2: `rgba(${mainColorData.bg}, 0.82)`,
|
||||
textColor3: `rgba(${mainColorData.bg}, 0.52)`,
|
||||
bodyColor: `rgba(${val.dark.mainBg}, 0.52)`,
|
||||
cardColor: `rgb(${coverAutobgCover})`,
|
||||
tagColor: `rgb(${coverAutobgCover})`,
|
||||
modalColor: `rgb(${coverAutobgCover})`,
|
||||
popoverColor: `rgb(${coverAutobgCover})`,
|
||||
}
|
||||
: mainColorData,
|
||||
Icon: { color: isCover ? primaryColor : null },
|
||||
};
|
||||
if (!isCover) themeTypeData.value = mainColorData;
|
||||
// 更新全局颜色变量
|
||||
setCssVariable("--main-color", primaryColor);
|
||||
setCssVariable("--main-second-color", primaryColorHover);
|
||||
setCssVariable("--main-boxshadow-color", primaryColorPressed);
|
||||
setCssVariable("--main-boxshadow-hover-color", primaryColorSuppl);
|
||||
} catch (error) {
|
||||
themeOverrides.value = {};
|
||||
console.error("切换主题色出现错误:", error);
|
||||
$message.error("切换主题色出现错误,已使用默认配置");
|
||||
}
|
||||
};
|
||||
|
||||
// 修改全局颜色
|
||||
const setCssVariable = (name, value) => {
|
||||
document.documentElement.style.setProperty(name, value);
|
||||
// document.body.style.setProperty(name, value);
|
||||
// document.documentElement.style.setProperty(name, value);
|
||||
document.body.style.setProperty(name, value);
|
||||
};
|
||||
|
||||
// 挂载 naive 组件
|
||||
@@ -148,8 +150,10 @@ watch(
|
||||
() => {
|
||||
changeTheme();
|
||||
changeThemeColor(
|
||||
themeAutoCover.value ? data.coverTheme : themeTypeName.value,
|
||||
themeAutoCover.value,
|
||||
themeAutoCover.value && Object.keys(coverTheme.value)?.length
|
||||
? coverTheme.value
|
||||
: themeTypeName.value,
|
||||
themeAutoCover.value && Object.keys(coverTheme.value)?.length,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -170,9 +174,8 @@ watch(
|
||||
(val) => changeThemeColor(val.label),
|
||||
);
|
||||
watch(
|
||||
() => data.coverTheme,
|
||||
() => coverTheme.value,
|
||||
(val) => {
|
||||
console.log(val);
|
||||
if (themeAutoCover.value) changeThemeColor(val, themeAutoCover.value);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -29,25 +29,28 @@
|
||||
<!-- 搜索框 -->
|
||||
<SearchInp />
|
||||
<!-- GitHub -->
|
||||
<n-button class="github" circle quaternary @click="openGithub">
|
||||
<template #icon>
|
||||
<n-icon size="20">
|
||||
<SvgIcon icon="github" />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<n-button v-if="setting.showGithub" class="github" circle quaternary @click="openGithub">
|
||||
<template #icon>
|
||||
<n-icon size="20">
|
||||
<SvgIcon icon="github" />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</Transition>
|
||||
<!-- 用户信息 -->
|
||||
<userData />
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { siteStatus } from "@/stores";
|
||||
import { siteStatus, siteSettings } from "@/stores";
|
||||
import { useRouter } from "vue-router";
|
||||
import packageJson from "@/../package.json";
|
||||
|
||||
const router = useRouter();
|
||||
const status = siteStatus();
|
||||
const setting = siteSettings();
|
||||
|
||||
// 站点信息
|
||||
const siteName = import.meta.env.RENDERER_VITE_SITE_TITLE;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<div
|
||||
v-if="showFullPlayer"
|
||||
:style="{
|
||||
'--cover-main-color': `rgb(${coverTheme?.dark?.shadeTwo})` || '#efefef',
|
||||
'--cover-second-color': `rgba(${coverTheme?.dark?.shadeTwo}, 0.14)` || '#efefef14',
|
||||
'--cover-main-color': `rgb(${coverTheme?.light?.shadeTwo})` || '#efefef',
|
||||
'--cover-second-color': `rgba(${coverTheme?.light?.shadeTwo}, 0.14)` || '#efefef14',
|
||||
'--cover-bg': coverBackground,
|
||||
cursor: playerControlShow ? 'auto' : 'none',
|
||||
}"
|
||||
@@ -183,20 +183,24 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useRouter } from "vue-router";
|
||||
import { musicData, siteStatus, siteSettings, siteData } from "@/stores";
|
||||
import { musicData, siteStatus, siteSettings } from "@/stores";
|
||||
import screenfull from "screenfull";
|
||||
import throttle from "@/utils/throttle";
|
||||
|
||||
const router = useRouter();
|
||||
const data = siteData();
|
||||
const music = musicData();
|
||||
const status = siteStatus();
|
||||
const settings = siteSettings();
|
||||
const { playList, playSongLyric } = storeToRefs(music);
|
||||
const { playerBackgroundType, showYrc } = storeToRefs(settings);
|
||||
const { coverTheme, coverBackground } = storeToRefs(data);
|
||||
const { playerControlShow, controlTimeOut, showFullPlayer, playUseOtherSource } =
|
||||
storeToRefs(status);
|
||||
const {
|
||||
playerControlShow,
|
||||
controlTimeOut,
|
||||
showFullPlayer,
|
||||
playUseOtherSource,
|
||||
coverTheme,
|
||||
coverBackground,
|
||||
} = storeToRefs(status);
|
||||
|
||||
// 全屏状态
|
||||
const screenfullStatus = ref(false);
|
||||
|
||||
@@ -171,7 +171,7 @@
|
||||
<!-- 播放暂停 -->
|
||||
<n-button
|
||||
:loading="playLoading"
|
||||
:keyboard="false"
|
||||
tag="div"
|
||||
type="primary"
|
||||
class="play-control"
|
||||
strong
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
<div
|
||||
class="private-fm"
|
||||
:style="{
|
||||
color: playMode === 'fm' && settings.themeAutoCover ? 'var(--main-color)' : '#efefef',
|
||||
'--color':
|
||||
playMode === 'fm' && settings.themeAutoCover && Object.keys(coverTheme)?.length
|
||||
? `rgb(${coverTheme.dark.bg})`
|
||||
: '#efefef',
|
||||
}"
|
||||
>
|
||||
<!-- 背景 -->
|
||||
@@ -68,7 +71,7 @@
|
||||
<!-- 播放暂停 -->
|
||||
<n-button
|
||||
:loading="playLoading"
|
||||
:class="{ 'play-control': true, isFm: playMode === 'fm' && settings.themeAutoCover }"
|
||||
class="play-control"
|
||||
color="#efefef"
|
||||
type="primary"
|
||||
strong
|
||||
@@ -134,7 +137,7 @@ const status = siteStatus();
|
||||
const settings = siteSettings();
|
||||
const router = useRouter();
|
||||
const { privateFmSong, playMode } = storeToRefs(music);
|
||||
const { playLoading, playState } = storeToRefs(status);
|
||||
const { playLoading, playState, coverTheme } = storeToRefs(status);
|
||||
|
||||
// 播放暂停
|
||||
const fmPlayOrPause = () => {
|
||||
@@ -240,6 +243,7 @@ onBeforeMount(async () => {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
color: var(--color);
|
||||
.info {
|
||||
.name {
|
||||
display: -webkit-box;
|
||||
@@ -256,6 +260,7 @@ onBeforeMount(async () => {
|
||||
align-items: center;
|
||||
.n-icon {
|
||||
margin-right: 4px;
|
||||
color: var(--color);
|
||||
}
|
||||
.all-ar {
|
||||
display: -webkit-box;
|
||||
@@ -292,6 +297,7 @@ onBeforeMount(async () => {
|
||||
align-items: center;
|
||||
.n-icon {
|
||||
margin-right: 4px;
|
||||
color: var(--color);
|
||||
}
|
||||
.al {
|
||||
display: -webkit-box;
|
||||
@@ -315,9 +321,11 @@ onBeforeMount(async () => {
|
||||
align-items: center;
|
||||
height: 46px;
|
||||
margin-top: auto;
|
||||
color: var(--color);
|
||||
.play-control {
|
||||
--n-width: 46px;
|
||||
--n-height: 46px;
|
||||
color: var(--color);
|
||||
margin-right: 12px;
|
||||
transition:
|
||||
background-color 0.3s,
|
||||
@@ -331,9 +339,6 @@ onBeforeMount(async () => {
|
||||
&:active {
|
||||
transform: scale(1);
|
||||
}
|
||||
&.isFm {
|
||||
color: var(--main-color);
|
||||
}
|
||||
}
|
||||
.play-other {
|
||||
margin-right: 12px;
|
||||
@@ -355,6 +360,7 @@ onBeforeMount(async () => {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
color: var(--color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
<template>
|
||||
<div class="title-bar">
|
||||
<n-divider vertical />
|
||||
<n-button class="bar-icon" quaternary circle @click="windowMin">
|
||||
<n-button class="bar-icon" tag="div" quaternary circle @click="windowMin">
|
||||
<template #icon>
|
||||
<n-icon :depth="2">
|
||||
<SvgIcon icon="window-minimize" />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button class="bar-icon" quaternary circle @click="maxOrRestore">
|
||||
<n-button class="bar-icon" tag="div" quaternary circle @click="maxOrRestore">
|
||||
<template #icon>
|
||||
<n-icon :depth="2">
|
||||
<SvgIcon :icon="defaultWindowState ? 'window-restore' : 'window-maximize'" />
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
<n-button class="bar-icon" quaternary circle @click="openCloseTip">
|
||||
<n-button class="bar-icon" tag="div" quaternary circle @click="openCloseTip">
|
||||
<template #icon>
|
||||
<n-icon :depth="2">
|
||||
<SvgIcon icon="window-close" />
|
||||
|
||||
@@ -46,9 +46,6 @@ const useSiteDataStore = defineStore("siteData", {
|
||||
catList: [], // 普通分类
|
||||
hqCatList: [], // 精品分类
|
||||
},
|
||||
// 封面主题
|
||||
coverTheme: {},
|
||||
coverBackground: null,
|
||||
};
|
||||
},
|
||||
getters: {
|
||||
|
||||
@@ -10,6 +10,7 @@ const useSiteSettingsStore = defineStore("siteSettings", {
|
||||
showTaskbarProgress: false, // 显示歌曲任务栏进度
|
||||
searchHistory: true, // 搜索历史
|
||||
autoSignIn: true, // 自动签到
|
||||
showGithub: true,
|
||||
// 主题部分
|
||||
themeType: "dark",
|
||||
themeAuto: false,
|
||||
|
||||
@@ -25,6 +25,9 @@ const useSiteStatusStore = defineStore("siteStatus", {
|
||||
playSeek: 0,
|
||||
// 是否下一首
|
||||
hasNextSong: false,
|
||||
// 封面主题
|
||||
coverTheme: {},
|
||||
coverBackground: null,
|
||||
};
|
||||
},
|
||||
getters: {},
|
||||
|
||||
@@ -12,7 +12,6 @@ body,
|
||||
height: 100vh;
|
||||
font-family: "HarmonyOS_Regular", sans-serif !important;
|
||||
overflow: hidden;
|
||||
background-color: var(--main-color-bg) !important;
|
||||
}
|
||||
|
||||
// n-text
|
||||
@@ -169,12 +168,3 @@ body,
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
}
|
||||
|
||||
// n-switch
|
||||
.n-switch {
|
||||
&.n-switch--active {
|
||||
.n-switch__rail {
|
||||
background-color: var(--main-second-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Howl, Howler } from "howler";
|
||||
import { musicData, siteStatus, siteSettings, siteData } from "@/stores";
|
||||
import { musicData, siteStatus, siteSettings } from "@/stores";
|
||||
import { getSongUrl, getSongLyric, songScrobble } from "@/api/song";
|
||||
import { checkPlatform, getLocalCoverData } from "@/utils/helper";
|
||||
import { decode as base642Buffer } from "@/utils/base64";
|
||||
@@ -673,17 +673,17 @@ const initMediaSession = async (data, islocal, cover) => {
|
||||
* @returns {string} - 主要颜色的RGB十六进制表示
|
||||
*/
|
||||
const getColorMainColor = async (islocal, cover) => {
|
||||
const data = siteData();
|
||||
const status = siteStatus();
|
||||
try {
|
||||
// 获取封面图像的URL
|
||||
if (!cover) return (data.coverColor = {});
|
||||
if (!cover) return (status.coverColor = {});
|
||||
const colorUrl = islocal ? cover : cover.s;
|
||||
// 获取渐变色背景
|
||||
const gradientColor = await getCoverGradient(colorUrl);
|
||||
data.coverBackground = gradientColor;
|
||||
status.coverBackground = gradientColor;
|
||||
} catch (error) {
|
||||
console.error("封面颜色获取失败:", error);
|
||||
data.coverColor = {};
|
||||
status.coverColor = {};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
Hct,
|
||||
Score,
|
||||
} from "@material/material-color-utilities";
|
||||
import { siteData, siteSettings } from "@/stores";
|
||||
import { siteSettings, siteStatus } from "@/stores";
|
||||
import { getGradientFromPalette, argb2Rgb, rgb2Argb } from "@/utils/color-utils";
|
||||
import { chunk } from "@/utils/helper";
|
||||
import ColorThief from "colorthief";
|
||||
@@ -45,7 +45,7 @@ export const getCoverGradient = (coverSrc) => {
|
||||
*/
|
||||
const calcAccentColor = (dom) => {
|
||||
// pinia
|
||||
const data = siteData();
|
||||
const status = siteStatus();
|
||||
const settings = siteSettings();
|
||||
// 创建一个用于提取颜色的 canvas
|
||||
const canvas = document.createElement("canvas");
|
||||
@@ -77,11 +77,11 @@ const calcAccentColor = (dom) => {
|
||||
const top = ranked[0];
|
||||
const theme = themeFromSourceColor(top);
|
||||
// 错误 error, 中性 neutral, 中性的变体 neutralVariant, 主要的 primary, 二次 secondary, 三级 tertiary
|
||||
const variant = window.accentColorVariant ?? "secondary";
|
||||
const variant = "secondary";
|
||||
// 更新主题色
|
||||
data.coverTheme = {
|
||||
light: {
|
||||
light: getAccentColor(theme.schemes.dark[variant]),
|
||||
status.coverTheme = {
|
||||
dark: {
|
||||
dark: getAccentColor(theme.schemes.dark[variant]),
|
||||
primary: getAccentColor(
|
||||
Hct.from(theme.palettes[variant].hue, theme.palettes[variant].chroma, 100).toInt(),
|
||||
),
|
||||
@@ -94,9 +94,12 @@ const calcAccentColor = (dom) => {
|
||||
bg: getAccentColor(
|
||||
Hct.from(theme.palettes.secondary.hue, theme.palettes.secondary.chroma, 90).toInt(),
|
||||
),
|
||||
mainBg: getAccentColor(
|
||||
Hct.from(theme.palettes.secondary.hue, theme.palettes.secondary.chroma, 10).toInt(),
|
||||
),
|
||||
},
|
||||
dark: {
|
||||
dark: getAccentColor(theme.schemes.dark[variant]),
|
||||
light: {
|
||||
light: getAccentColor(theme.schemes.light[variant]),
|
||||
primary: getAccentColor(
|
||||
Hct.from(theme.palettes[variant].hue, theme.palettes[variant].chroma, 20).toInt(),
|
||||
),
|
||||
@@ -110,13 +113,13 @@ const calcAccentColor = (dom) => {
|
||||
Hct.from(theme.palettes.secondary.hue, theme.palettes.secondary.chroma, 20).toInt(),
|
||||
),
|
||||
mainBg: getAccentColor(
|
||||
Hct.from(theme.palettes.secondary.hue, theme.palettes.secondary.chroma, 10).toInt(),
|
||||
Hct.from(theme.palettes.secondary.hue, theme.palettes.secondary.chroma, 100).toInt(),
|
||||
),
|
||||
},
|
||||
};
|
||||
// 尝试更新主题色
|
||||
if (typeof $changeThemeColor !== "undefined" && settings.themeAutoCover) {
|
||||
$changeThemeColor(data.coverTheme, settings.themeAutoCover);
|
||||
$changeThemeColor(status.coverTheme, settings.themeAutoCover);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -125,17 +128,18 @@ const calcAccentColor = (dom) => {
|
||||
*/
|
||||
const useGreyAccentColor = () => {
|
||||
// pinia
|
||||
const data = siteData();
|
||||
data.coverTheme = {
|
||||
light: {
|
||||
light: getAccentColor(rgb2Argb(120, 120, 120)),
|
||||
const status = siteStatus();
|
||||
status.coverTheme = {
|
||||
dark: {
|
||||
dark: getAccentColor(rgb2Argb(120, 120, 120)),
|
||||
primary: getAccentColor(rgb2Argb(250, 250, 250)),
|
||||
shade: getAccentColor(rgb2Argb(40, 40, 40)),
|
||||
shadeTwo: getAccentColor(rgb2Argb(20, 20, 20)),
|
||||
bg: getAccentColor(rgb2Argb(190, 190, 190)),
|
||||
mainBg: getAccentColor(rgb2Argb(11, 11, 11)),
|
||||
},
|
||||
dark: {
|
||||
dark: getAccentColor(rgb2Argb(150, 150, 150)),
|
||||
light: {
|
||||
light: getAccentColor(rgb2Argb(150, 150, 150)),
|
||||
primary: getAccentColor(rgb2Argb(10, 10, 10)),
|
||||
shade: getAccentColor(rgb2Argb(210, 210, 210)),
|
||||
shadeTwo: getAccentColor(rgb2Argb(255, 255, 255)),
|
||||
|
||||
@@ -51,21 +51,8 @@ watch(
|
||||
font-weight: bold;
|
||||
}
|
||||
.tabs {
|
||||
position: sticky;
|
||||
top: 20px;
|
||||
margin-bottom: 20px;
|
||||
z-index: 2;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: -25px;
|
||||
width: calc(100% + 50px);
|
||||
height: calc(100% + 40px);
|
||||
background-color: var(--n-color);
|
||||
backdrop-filter: blur(40px);
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -275,6 +275,7 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
.tag {
|
||||
background-color: var(--n-action-color);
|
||||
transition:
|
||||
transform 0.3s,
|
||||
background-color 0.3s,
|
||||
|
||||
@@ -2,21 +2,18 @@
|
||||
<template>
|
||||
<div class="search">
|
||||
<template v-if="searchKeywords">
|
||||
<!-- 固定 -->
|
||||
<div class="fixed">
|
||||
<div class="title">
|
||||
<n-text class="key">{{ searchKeywords }}</n-text>
|
||||
<n-text depth="3">的相关搜索</n-text>
|
||||
</div>
|
||||
<!-- 标签页 -->
|
||||
<n-tabs v-model:value="tabValue" class="tabs" type="line" @update:value="tabChange">
|
||||
<n-tab name="sea-songs"> 单曲 </n-tab>
|
||||
<n-tab name="sea-artists"> 歌手 </n-tab>
|
||||
<n-tab name="sea-albums"> 专辑 </n-tab>
|
||||
<n-tab name="sea-playlists"> 歌单 </n-tab>
|
||||
<n-tab name="sea-videos"> 视频 </n-tab>
|
||||
</n-tabs>
|
||||
<div class="title">
|
||||
<n-text class="key">{{ searchKeywords }}</n-text>
|
||||
<n-text depth="3">的相关搜索</n-text>
|
||||
</div>
|
||||
<!-- 标签页 -->
|
||||
<n-tabs v-model:value="tabValue" class="tabs" type="line" @update:value="tabChange">
|
||||
<n-tab name="sea-songs"> 单曲 </n-tab>
|
||||
<n-tab name="sea-artists"> 歌手 </n-tab>
|
||||
<n-tab name="sea-albums"> 专辑 </n-tab>
|
||||
<n-tab name="sea-playlists"> 歌单 </n-tab>
|
||||
<n-tab name="sea-videos"> 视频 </n-tab>
|
||||
</n-tabs>
|
||||
<!-- 路由页面 -->
|
||||
<router-view v-slot="{ Component }">
|
||||
<keep-alive>
|
||||
@@ -69,38 +66,20 @@ watch(
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search {
|
||||
.fixed {
|
||||
position: sticky;
|
||||
top: 34px;
|
||||
background-color: var(--n-color);
|
||||
z-index: 2;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
left: -25px;
|
||||
width: calc(100% + 50px);
|
||||
height: calc(100% + 54px);
|
||||
background-color: var(--n-color);
|
||||
backdrop-filter: blur(40px);
|
||||
z-index: -1;
|
||||
.title {
|
||||
margin: 10px 0;
|
||||
font-size: 22px;
|
||||
.key {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 10px 0;
|
||||
font-size: 22px;
|
||||
.key {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.n-text {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
.tabs {
|
||||
margin-bottom: 20px;
|
||||
.n-text {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
.tabs {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<!-- 全局设置 -->
|
||||
<template>
|
||||
<div class="setting">
|
||||
<div :class="{ setting: true, 'use-cover': themeAutoCover }">
|
||||
<n-h1 class="title">
|
||||
<n-text>全局设置</n-text>
|
||||
<n-text class="version" depth="3">v {{ packageJson.version }}</n-text>
|
||||
@@ -24,7 +24,7 @@
|
||||
ref="setScrollRef"
|
||||
:style="{
|
||||
height: `calc(100vh - ${
|
||||
Object.keys(music.getPlaySongData)?.length && status.showPlayBar ? 328 : 248
|
||||
Object.keys(music.getPlaySongData)?.length && showPlayBar ? 328 : 248
|
||||
}px)`,
|
||||
}"
|
||||
class="all-set"
|
||||
@@ -92,6 +92,7 @@
|
||||
<n-switch
|
||||
v-model:value="themeAutoCover"
|
||||
:round="false"
|
||||
:disabled="Object.keys(coverTheme)?.length === 0"
|
||||
@update:value="themeAutoCoverChange"
|
||||
/>
|
||||
</n-card>
|
||||
@@ -386,6 +387,10 @@
|
||||
<!-- 其他 -->
|
||||
<div class="set-type">
|
||||
<n-h3 prefix="bar"> 其他 </n-h3>
|
||||
<n-card class="set-item">
|
||||
<div class="name">是否显示 GitHub 仓库按钮</div>
|
||||
<n-switch v-model:value="showGithub" :round="false" />
|
||||
</n-card>
|
||||
<n-card class="set-item">
|
||||
<div class="name">
|
||||
默认加载数量
|
||||
@@ -426,15 +431,15 @@
|
||||
<script setup>
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useOsTheme } from "naive-ui";
|
||||
import { siteSettings, siteStatus, musicData, siteData } from "@/stores";
|
||||
import { siteSettings, siteStatus, musicData } from "@/stores";
|
||||
import { checkPlatform } from "@/utils/helper";
|
||||
import debounce from "@/utils/debounce";
|
||||
import packageJson from "@/../package.json";
|
||||
|
||||
const music = musicData();
|
||||
const status = siteStatus();
|
||||
const data = siteData();
|
||||
const settings = siteSettings();
|
||||
const { showPlayBar, coverTheme } = storeToRefs(status);
|
||||
const {
|
||||
themeType,
|
||||
themeTypeName,
|
||||
@@ -464,6 +469,7 @@ const {
|
||||
bottomLyricShow,
|
||||
downloadPath,
|
||||
memorySeek,
|
||||
showGithub,
|
||||
} = storeToRefs(settings);
|
||||
|
||||
// 标签页数据
|
||||
@@ -515,9 +521,9 @@ const songLevelData = {
|
||||
|
||||
// 封面自动跟随变化
|
||||
const themeAutoCoverChange = (val) => {
|
||||
typeof $changeThemeColor !== "undefined" && val
|
||||
? $changeThemeColor(data.coverTheme, val)
|
||||
: $changeThemeColor(themeTypeName.value, val);
|
||||
if ($changeThemeColor !== "undefined" && Object.keys(coverTheme.value)?.length) {
|
||||
$changeThemeColor(val ? coverTheme.value : themeTypeName.value, val);
|
||||
}
|
||||
};
|
||||
|
||||
// 标签页切换
|
||||
@@ -635,5 +641,14 @@ const resetApp = () => {
|
||||
}
|
||||
}
|
||||
}
|
||||
&.use-cover {
|
||||
.n-switch {
|
||||
&.n-switch--active {
|
||||
:deep(.n-switch__rail) {
|
||||
background-color: var(--main-second-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user