mirror of
https://github.com/imsyy/home.git
synced 2025-05-19 12:40:13 +09:00
[Add] 添加功能
# 添加独立的壁纸配置,增加壁纸时无需重新编译项目 # 允许为移动端设置不同分辨率的壁纸 # 允许在移动端点击 网站列表 以打开设置 # 依赖更新
This commit is contained in:
parent
a3480ad75b
commit
3cfb290fc5
@ -44,7 +44,7 @@ VITE_SITE_MPS = ""
|
|||||||
## 如果要使用逐字歌词功能,请使用 https://github.com/NanoRocky/meting-api 进行部署
|
## 如果要使用逐字歌词功能,请使用 https://github.com/NanoRocky/meting-api 进行部署
|
||||||
## 此处提供的服务可能会超量从而无法访问,请自行部署或前往搜索引擎使用其他站长搭建的
|
## 此处提供的服务可能会超量从而无法访问,请自行部署或前往搜索引擎使用其他站长搭建的
|
||||||
## 若使用 QQ 音乐歌单,歌曲数量最好不要超出 50 首
|
## 若使用 QQ 音乐歌单,歌曲数量最好不要超出 50 首
|
||||||
VITE_SONG_API = "https://api.wuenci.com/meting/api/"
|
VITE_SONG_API = "https://metingapi.nanorocky.top/"
|
||||||
# 歌曲服务器 ( netease-网易云, tencent-qq音乐 )
|
# 歌曲服务器 ( netease-网易云, tencent-qq音乐 )
|
||||||
VITE_SONG_SERVER = "netease"
|
VITE_SONG_SERVER = "netease"
|
||||||
# 播放类型 ( song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家 )
|
# 播放类型 ( song-歌曲, playlist-播放列表, album-专辑, search-搜索, artist-艺术家 )
|
||||||
@ -53,7 +53,7 @@ VITE_SONG_TYPE = "playlist"
|
|||||||
VITE_SONG_ID = "9379831714"
|
VITE_SONG_ID = "9379831714"
|
||||||
|
|
||||||
# 文字转语音 API 地址(请自行搭建)
|
# 文字转语音 API 地址(请自行搭建)
|
||||||
## 如果也使用 Azure ,您可直接使用 https://github.com/NanoRocky/AzureSpeechAPI-by-PHP 完成 API 部署
|
## 如果也使用 Azure ,您可直接使用 https://github.com/NanoRocky/AzureSpeechAPI-by-PHP 完成 API 部署
|
||||||
## (更多参数设置可以修改 \src\utils\speech.js 或自行补充)
|
## (更多参数设置可以修改 \src\utils\speech.js 或自行补充)
|
||||||
VITE_TTS_API = ""
|
VITE_TTS_API = ""
|
||||||
VITE_TTS_Voice = "zh-CN-YunxiaNeural"
|
VITE_TTS_Voice = "zh-CN-YunxiaNeural"
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- 主体内容 -->
|
<!-- 主体内容 -->
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- noscript -->
|
<!-- noscript -->
|
||||||
<noscript>
|
<noscript>
|
||||||
|
31
package.json
31
package.json
@ -1,10 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "home",
|
"name": "home",
|
||||||
"author": "imsyy",
|
"author": "imsyy",
|
||||||
|
"efua": "NanoRocky",
|
||||||
"github": "https://github.com/imsyy/home",
|
"github": "https://github.com/imsyy/home",
|
||||||
|
"efug": "https://github.com/NanoRocky/home",
|
||||||
"home": "https://imsyy.top",
|
"home": "https://imsyy.top",
|
||||||
|
"efuh": "https://nanorocky.top",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "4.1.4",
|
"version": "4.2.1 [EFU]",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host",
|
"dev": "vite --host",
|
||||||
@ -16,16 +19,16 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@worstone/vue-aplayer": "^1.0.7",
|
"@worstone/vue-aplayer": "^1.0.7",
|
||||||
"aplayer": "^1.10.1",
|
"aplayer": "^1.10.1",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.8.2",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"element-plus": "^2.9.3",
|
"element-plus": "^2.9.6",
|
||||||
"fetch-jsonp": "^1.3.0",
|
"fetch-jsonp": "^1.3.0",
|
||||||
"jparticles": "^3.5.0",
|
"jparticles": "^3.5.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"pinia": "^2.3.0",
|
"pinia": "^3.0.1",
|
||||||
"pinia-plugin-persistedstate-2": "^2.0.28",
|
"pinia-plugin-persistedstate-2": "^2.0.28",
|
||||||
"swiper": "^11.2.1",
|
"swiper": "^11.2.5",
|
||||||
"three": "^0.172.0",
|
"three": "^0.174.0",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vuex": "^4.1.0"
|
"vuex": "^4.1.0"
|
||||||
},
|
},
|
||||||
@ -38,14 +41,14 @@
|
|||||||
"@vicons/tabler": "^0.13.0",
|
"@vicons/tabler": "^0.13.0",
|
||||||
"@vicons/utils": "^0.1.4",
|
"@vicons/utils": "^0.1.4",
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
"@vitejs/plugin-vue": "^5.2.1",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.21.0",
|
||||||
"eslint-plugin-vue": "^9.32.0",
|
"eslint-plugin-vue": "^9.33.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.5.3",
|
||||||
"sass": "^1.83.4",
|
"sass": "^1.85.1",
|
||||||
"terser": "^5.37.0",
|
"terser": "^5.39.0",
|
||||||
"unplugin-auto-import": "^19.0.0",
|
"unplugin-auto-import": "^19.1.1",
|
||||||
"unplugin-vue-components": "^28.0.0",
|
"unplugin-vue-components": "^28.4.1",
|
||||||
"vite": "^6.0.9",
|
"vite": "^6.2.1",
|
||||||
"vite-plugin-compression2": "^1.3.3",
|
"vite-plugin-compression2": "^1.3.3",
|
||||||
"vite-plugin-pwa": "^0.21.1"
|
"vite-plugin-pwa": "^0.21.1"
|
||||||
},
|
},
|
||||||
|
2214
pnpm-lock.yaml
generated
2214
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
4
public/images/config.json
Normal file
4
public/images/config.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"bgImageCount": 10,
|
||||||
|
"bgImageCountP": 2
|
||||||
|
}
|
BIN
public/images/phone/backgroundphone1.jpg
Normal file
BIN
public/images/phone/backgroundphone1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
BIN
public/images/phone/backgroundphone2.jpg
Normal file
BIN
public/images/phone/backgroundphone2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 609 KiB |
@ -73,3 +73,28 @@ export const getOtherWeather = async () => {
|
|||||||
const res = await fetch("https://api.oioweb.cn/api/weather/GetWeather");
|
const res = await fetch("https://api.oioweb.cn/api/weather/GetWeather");
|
||||||
return await res.json();
|
return await res.json();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 这是一个待完善的新免 token 天气模块
|
||||||
|
|
||||||
|
// // 获取位置信息
|
||||||
|
// export const getLocation = async () => {
|
||||||
|
// const res = await fetch("http://inip.in/ip.json");
|
||||||
|
// return await res.json();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 转换城市 ID
|
||||||
|
// export const getCityId = async (city) => {
|
||||||
|
// const res = await fetch(
|
||||||
|
// `https://api.songzixian.com/api/china-city?dataSource=LOCAL_CHINA_CITY&district=${city}`,
|
||||||
|
// );
|
||||||
|
// return await res.json();
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // 获取小米天气 API
|
||||||
|
// export const getOtherWeather = async () => {
|
||||||
|
// const res = await fetch(
|
||||||
|
// `https://weatherapi.market.xiaomi.com/wtr-v3/weather/all?latitude=0&longitude=0&isLocated=true&locationKey=weathercn%3A${city}&days=2&appKey=weather20151024&sign=zUFJoAR2ZVrDy1vF3D07&locale=zh_cn&alpha=false&isGlobal=false`,
|
||||||
|
// );
|
||||||
|
// return await res.json();
|
||||||
|
// };
|
@ -23,21 +23,68 @@ const bgUrl = ref(null);
|
|||||||
const imgTimeout = ref(null);
|
const imgTimeout = ref(null);
|
||||||
const emit = defineEmits(["loadComplete"]);
|
const emit = defineEmits(["loadComplete"]);
|
||||||
|
|
||||||
// 壁纸随机数
|
// 自定义壁纸
|
||||||
// 请依据文件夹内的图片个数修改 Math.random() 后面的第一个数字
|
// 酪灰的小批注:这里增加了从配置文件读取壁纸数的功能,使得在增加壁纸时不需要重新编译项目,只需修改这个 json 文件内的值
|
||||||
const bgRandom = Math.floor(Math.random() * 10 + 1);
|
// 设置一个默认值,防止在无法加载 JSON 文件时壁纸失效。应该尽量保证壁纸数始终不小于这个默认值
|
||||||
|
let bgImageCount = 10; // PC 版壁纸
|
||||||
|
let bgImageCountP = 2; // 移动版壁纸
|
||||||
|
let bgRandom = 0;
|
||||||
|
let bgRandomp = 0;
|
||||||
|
|
||||||
|
// 加载 config.json
|
||||||
|
async function loadConfig() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/images/config.json');
|
||||||
|
const data = await response.json();
|
||||||
|
bgImageCount = Math.max(data.bgImageCount, 1);
|
||||||
|
bgImageCountP = Math.max(data.bgImageCountP, 1);
|
||||||
|
bgRandom = Math.floor(Math.random() * bgImageCount + 1);
|
||||||
|
bgRandomp = Math.floor(Math.random() * bgImageCountP + 1);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('无法加载壁纸配置文件:', error);
|
||||||
|
bgRandom = Math.floor(Math.random() * bgImageCount + 1);
|
||||||
|
bgRandomp = Math.floor(Math.random() * bgImageCountP + 1);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// 检测设备类型
|
||||||
|
const detectDevice = () => {
|
||||||
|
const userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
if (/mobile|android|iphone|ipad|ipod|windows phone/.test(userAgent)) {
|
||||||
|
if (/ipad|tablet|playbook|silk|kindle/.test(userAgent)) {
|
||||||
|
return 'tablet'; // 平板
|
||||||
|
} else {
|
||||||
|
return 'mobile'; // 手机
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return 'pc'; // PC
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// 更换壁纸链接
|
// 更换壁纸链接
|
||||||
const changeBg = (type) => {
|
const changeBg = (type) => {
|
||||||
if (type == 0) {
|
(async () => {
|
||||||
bgUrl.value = `/images/background${bgRandom}.jpg`;
|
await loadConfig(); // 加载配置文件
|
||||||
} else if (type == 1) {
|
const deviceType = detectDevice(); // 加载设备类型
|
||||||
bgUrl.value = "https://api.dujin.org/bing/1920.php";
|
if (type == 0) {
|
||||||
} else if (type == 2) {
|
// 这里指定了所有自定义背景的文件格式,必须统一。可以自定义修改,比如 webp 或 png
|
||||||
bgUrl.value = "https://api.vvhan.com/api/wallpaper/views";
|
// 酪灰的小批注:这里添加了设备类型识别以加载不同分辨率的壁纸
|
||||||
} else if (type == 3) {
|
// 如果不需要区分设备类型,则只需要保留这一行 bgUrl.value = `/images/background${bgRandom}.jpg`;
|
||||||
bgUrl.value = "https://api.vvhan.com/api/wallpaper/acg";
|
if (deviceType === 'mobile') {
|
||||||
};
|
bgUrl.value = `/images/phone/backgroundphone${bgRandomp}.jpg`;
|
||||||
|
} else if (deviceType === 'tablet' || deviceType === 'pc') {
|
||||||
|
bgUrl.value = `/images/background${bgRandom}.jpg`;
|
||||||
|
} else {
|
||||||
|
bgUrl.value = `/images/background${bgRandom}.jpg`;
|
||||||
|
};
|
||||||
|
} else if (type == 1) {
|
||||||
|
bgUrl.value = "https://api.dujin.org/bing/1920.php";
|
||||||
|
} else if (type == 2) {
|
||||||
|
bgUrl.value = "https://api.vvhan.com/api/wallpaper/views";
|
||||||
|
} else if (type == 3) {
|
||||||
|
bgUrl.value = "https://api.vvhan.com/api/wallpaper/acg";
|
||||||
|
};
|
||||||
|
})();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 图片加载完成
|
// 图片加载完成
|
||||||
|
@ -47,9 +47,9 @@
|
|||||||
:key="store.playerLrc.length != 0 ? `lrc-line-${store.playerLrc[0][2]}` : `lrc-line-null`">
|
:key="store.playerLrc.length != 0 ? `lrc-line-${store.playerLrc[0][2]}` : `lrc-line-null`">
|
||||||
<music-one theme="filled" size="18" fill="#efefef" />
|
<music-one theme="filled" size="18" fill="#efefef" />
|
||||||
|
|
||||||
<!-- <Icon size="20" style="transform: rotate(-18deg);" class="paws-1">
|
<Icon size="20" style="transform: rotate(-18deg);" class="paws-1">
|
||||||
<paw />
|
<paw />
|
||||||
</Icon> -->
|
</Icon>
|
||||||
<span class="yrc-box">
|
<span class="yrc-box">
|
||||||
<span class="yrc-2 lrc-text text-hidden" id="yrc-2-wrap">
|
<span class="yrc-2 lrc-text text-hidden" id="yrc-2-wrap">
|
||||||
<span v-for="i in store.playerLrc" :key="`lrc-over-char-${i[2]}-${i[3]}`" v-html="i[4]">
|
<span v-for="i in store.playerLrc" :key="`lrc-over-char-${i[2]}-${i[3]}`" v-html="i[4]">
|
||||||
@ -66,9 +66,9 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<!-- <Icon size="20" style="transform: rotate(18deg);" class="paws-2">
|
<Icon size="20" style="transform: rotate(18deg);" class="paws-2">
|
||||||
<paw />
|
<paw />
|
||||||
</Icon> -->
|
</Icon>
|
||||||
|
|
||||||
<music-one theme="filled" size="18" fill="#efefef" />
|
<music-one theme="filled" size="18" fill="#efefef" />
|
||||||
</div>
|
</div>
|
||||||
@ -78,13 +78,13 @@
|
|||||||
<div class="lrc-all" :key="store.getPlayerLrc">
|
<div class="lrc-all" :key="store.getPlayerLrc">
|
||||||
<music-one theme="filled" size="18" fill="#efefef" />
|
<music-one theme="filled" size="18" fill="#efefef" />
|
||||||
|
|
||||||
<!-- <Icon size="20" style="transform: rotate(-18deg);" class="paws-3">
|
<Icon size="20" style="transform: rotate(-18deg);" class="paws-3">
|
||||||
<paw />
|
<paw />
|
||||||
</Icon> -->
|
</Icon>
|
||||||
<span class="lrc-text text-hidden" v-html="store.getPlayerLrc[0][4]" :class="`lrc-char`" />
|
<span class="lrc-text text-hidden" v-html="store.getPlayerLrc[0][4]" :class="`lrc-char`" />
|
||||||
<!-- <Icon size="20" style="transform: rotate(18deg);" class="paws-4">
|
<Icon size="20" style="transform: rotate(18deg);" class="paws-4">
|
||||||
<paw />
|
<paw />
|
||||||
</Icon> -->
|
</Icon>
|
||||||
|
|
||||||
<music-one theme="filled" size="18" fill="#efefef" />
|
<music-one theme="filled" size="18" fill="#efefef" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,29 +4,20 @@
|
|||||||
<Icon size="20">
|
<Icon size="20">
|
||||||
<Link />
|
<Link />
|
||||||
</Icon>
|
</Icon>
|
||||||
<span class="title">网站列表</span>
|
<span class="title text-hidden" v-if="store.mobileOpenState" @click="store.setOpenState = !store.setOpenState">网站列表</span>
|
||||||
|
<span class="title" v-else>网站列表</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- 网站列表 -->
|
<!-- 网站列表 -->
|
||||||
<Swiper
|
<Swiper v-if="siteLinks[0]" :modules="[Pagination, Mousewheel]" :slides-per-view="1" :space-between="40"
|
||||||
v-if="siteLinks[0]"
|
|
||||||
:modules="[Pagination, Mousewheel]"
|
|
||||||
:slides-per-view="1"
|
|
||||||
:space-between="40"
|
|
||||||
:pagination="{
|
:pagination="{
|
||||||
el: '.swiper-pagination',
|
el: '.swiper-pagination',
|
||||||
clickable: true,
|
clickable: true,
|
||||||
bulletElement: 'div',
|
bulletElement: 'div',
|
||||||
}"
|
}" :mousewheel="true">
|
||||||
:mousewheel="true"
|
|
||||||
>
|
|
||||||
<SwiperSlide v-for="site in siteLinksList" :key="site">
|
<SwiperSlide v-for="site in siteLinksList" :key="site">
|
||||||
<el-row class="link-all" :gutter="20">
|
<el-row class="link-all" :gutter="20">
|
||||||
<el-col v-for="(item, index) in site" :span="8" :key="item">
|
<el-col v-for="(item, index) in site" :span="8" :key="item">
|
||||||
<div
|
<div class="item cards" :style="index < 3 ? 'margin-bottom: 20px' : null" @click="jumpLink(item)">
|
||||||
class="item cards"
|
|
||||||
:style="index < 3 ? 'margin-bottom: 20px' : null"
|
|
||||||
@click="jumpLink(item)"
|
|
||||||
>
|
|
||||||
<Icon size="26">
|
<Icon size="26">
|
||||||
<component :is="siteIcon[item.icon]" />
|
<component :is="siteIcon[item.icon]" />
|
||||||
</Icon>
|
</Icon>
|
||||||
@ -90,26 +81,31 @@ const jumpLink = (data) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
animation: fade 0.5s;
|
animation: fade 0.5s;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
font-size: 1.15rem;
|
font-size: 1.15rem;
|
||||||
text-shadow: 0 0 5px #00000050;
|
text-shadow: 0 0 5px #00000050;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper {
|
.swiper {
|
||||||
left: -10px;
|
left: -10px;
|
||||||
width: calc(100% + 20px);
|
width: calc(100% + 20px);
|
||||||
padding: 5px 10px 0;
|
padding: 5px 10px 0;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
|
||||||
.swiper-slide {
|
.swiper-slide {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-pagination {
|
.swiper-pagination {
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
:deep(.swiper-pagination-bullet) {
|
:deep(.swiper-pagination-bullet) {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
@ -118,17 +114,21 @@ const jumpLink = (data) => {
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
opacity: 0.2;
|
opacity: 0.2;
|
||||||
transition: opacity 0.3s;
|
transition: opacity 0.3s;
|
||||||
|
|
||||||
&.swiper-pagination-bullet-active {
|
&.swiper-pagination-bullet-active {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-all {
|
.link-all {
|
||||||
height: 220px;
|
height: 220px;
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -153,16 +153,20 @@ const jumpLink = (data) => {
|
|||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 720px) and (max-width: 820px) {
|
@media (min-width: 720px) and (max-width: 820px) {
|
||||||
.name {
|
.name {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
height: 80px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 460px) {
|
@media (max-width: 460px) {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
@ -170,6 +174,7 @@ const jumpLink = (data) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
height: 180px;
|
height: 180px;
|
||||||
}
|
}
|
||||||
|
@ -258,8 +258,8 @@ const fetchYrc = async (yrcUrl) => {
|
|||||||
};
|
};
|
||||||
const songUrlInfUrl = store.playerYrcATDBF
|
const songUrlInfUrl = store.playerYrcATDBF
|
||||||
? {
|
? {
|
||||||
netease: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
|
netease: `https://ghfast.top/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
|
||||||
tencent: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.qrc`,
|
tencent: `https://ghfast.top/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songId}.qrc`,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
|
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songId}.yrc`,
|
||||||
@ -351,8 +351,8 @@ function syncYrcLrc() {
|
|||||||
} else {
|
} else {
|
||||||
const songUrlInfwurl = store.playerYrcATDBF
|
const songUrlInfwurl = store.playerYrcATDBF
|
||||||
? {
|
? {
|
||||||
netease: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songIdlrc}.lrc`,
|
netease: `https://ghfast.top/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songIdlrc}.lrc`,
|
||||||
tencent: `https://ghp.ci/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songIdlrc}.lrc`,
|
tencent: `https://ghfast.top/https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/qq-lyrics/${songIdlrc}.lrc`,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songIdlrc}.lrc`,
|
netease: `https://raw.githubusercontent.com/Steve-xmh/amll-ttml-db/main/ncm-lyrics/${songIdlrc}.lrc`,
|
||||||
@ -390,40 +390,46 @@ function syncYrcLrc() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
})
|
||||||
};
|
.catch(() => {
|
||||||
const output = [[true, 1, playerLyricIndex, 0, lrc]];
|
lrc = "歌词加载失败";
|
||||||
if (store.playerLrc.toString() != output.toString()) {
|
});
|
||||||
store.setPlayerLrc(output);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// 逐字模块
|
const output = [[true, 1, playerLyricIndex, 0, lrc]];
|
||||||
const now = player.value.audioStatus.playedTime * 1000;
|
if (store.playerLrc.toString() != output.toString()) {
|
||||||
const yrcFiltered = store.yrcTemp.filter((i) => i[0] < now);
|
store.setPlayerLrc(output);
|
||||||
const yrcLyric =
|
|
||||||
yrcFiltered.length > 0
|
|
||||||
? yrcFiltered.slice(-1)[0][2].map((it) => {
|
|
||||||
const [[start, duration], word, line, row] = it;
|
|
||||||
const isCurrent = now >= start && now <= start + duration;
|
|
||||||
const isSungLyrics = start + duration < now;
|
|
||||||
const lessdur = start + duration - now;
|
|
||||||
return [isCurrent, isSungLyrics, line, row, word, duration, lessdur, "auto"];
|
|
||||||
})
|
|
||||||
: [[true, 1, 0, 0, `${store.playerTitle} - ${store.playerArtist}`]];
|
|
||||||
if (store.playerLrc.toString() != yrcLyric.toString()) {
|
|
||||||
store.setPlayerLrc(yrcLyric);
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} else {
|
||||||
console.error(error);
|
// 逐字模块
|
||||||
|
const now = player.value.audioStatus.playedTime * 1000;
|
||||||
|
const yrcFiltered = store.yrcTemp.filter((i) => i[0] < now);
|
||||||
|
const yrcLyric =
|
||||||
|
yrcFiltered.length > 0
|
||||||
|
? yrcFiltered.slice(-1)[0][2].map((it) => {
|
||||||
|
const [[start, duration], word, line, row] = it;
|
||||||
|
const isCurrent = now >= start && now <= start + duration;
|
||||||
|
const isSungLyrics = start + duration < now;
|
||||||
|
const lessdur = start + duration - now;
|
||||||
|
return [isCurrent, isSungLyrics, line, row, word, duration, lessdur, "auto"];
|
||||||
|
})
|
||||||
|
: [[true, 1, 0, 0, `${store.playerTitle} - ${store.playerArtist}`]];
|
||||||
|
if (store.playerLrc.toString() != yrcLyric.toString()) {
|
||||||
|
store.setPlayerLrc(yrcLyric);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
return requestAnimationFrame(syncYrcLrc);
|
|
||||||
};
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
};
|
||||||
|
return requestAnimationFrame(syncYrcLrc);
|
||||||
|
};
|
||||||
|
|
||||||
// 暴露子组件方法
|
// 暴露子组件方法
|
||||||
defineExpose({ playToggle, changeVolume, changeSong, toggleList });
|
defineExpose({ playToggle, changeVolume, changeSong, toggleList });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
@ -1,14 +1,40 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="set" @mouseenter="closeShow = true" @mouseleave="closeShow = false" @click.stop>
|
<div class="mobileset" v-if="store.mobileOpenState" @mouseenter="closeShow = true" @mouseleave="closeShow = false"
|
||||||
|
@click.stop>
|
||||||
<transition name="el-fade-in-linear">
|
<transition name="el-fade-in-linear">
|
||||||
<close-one
|
<close-one class="close" theme="filled" size="28" fill="#ffffff60" v-show="closeShow"
|
||||||
class="close"
|
@click="store.setOpenState = false" />
|
||||||
theme="filled"
|
</transition>
|
||||||
size="28"
|
<el-row>
|
||||||
fill="#ffffff60"
|
<el-col class="left">
|
||||||
v-show="closeShow"
|
<div class="logo text-hidden">
|
||||||
@click="store.setOpenState = false"
|
<span class="bg">{{ siteUrl[0] }}</span>
|
||||||
/>
|
<span class="sm">.{{ siteUrl[1] }}</span>
|
||||||
|
</div>
|
||||||
|
<!-- 移动端设置菜单 -->
|
||||||
|
<div class="title">
|
||||||
|
<setting-two theme="filled" size="28" fill="#ffffff60" />
|
||||||
|
<span class="name">全局设置</span>
|
||||||
|
</div>
|
||||||
|
<div class="mobileset-scrollable">
|
||||||
|
<Set />
|
||||||
|
</div>
|
||||||
|
<div class="version">
|
||||||
|
<div class="num">v {{ config.version }}</div>
|
||||||
|
<el-tooltip content="Powered by imsyy" placement="right" :show-arrow="false">
|
||||||
|
<github-one class="github" theme="outline" size="24" @click="jumpTo(config.github)" />
|
||||||
|
</el-tooltip>
|
||||||
|
<el-tooltip content="Extension Function Updates by NanoRocky" placement="right" :show-arrow="false">
|
||||||
|
<file-editing-one class="github" theme="outline" size="24" @click="jumpTo(config.efug)" />
|
||||||
|
</el-tooltip>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
<div class="set" v-else @mouseenter="closeShow = true" @mouseleave="closeShow = false" @click.stop>
|
||||||
|
<transition name="el-fade-in-linear">
|
||||||
|
<close-one class="close" theme="filled" size="28" fill="#ffffff60" v-show="closeShow"
|
||||||
|
@click="store.setOpenState = false" />
|
||||||
</transition>
|
</transition>
|
||||||
<el-row :gutter="40">
|
<el-row :gutter="40">
|
||||||
<el-col :span="12" class="left">
|
<el-col :span="12" class="left">
|
||||||
@ -21,6 +47,9 @@
|
|||||||
<el-tooltip content="Github 源代码仓库" placement="right" :show-arrow="false">
|
<el-tooltip content="Github 源代码仓库" placement="right" :show-arrow="false">
|
||||||
<github-one class="github" theme="outline" size="24" @click="jumpTo(config.github)" />
|
<github-one class="github" theme="outline" size="24" @click="jumpTo(config.github)" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
<el-tooltip content="扩展功能更新仓库" placement="right" :show-arrow="false">
|
||||||
|
<file-editing-one class="github" theme="outline" size="24" @click="jumpTo(config.efug)" />
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<el-card class="update">
|
<el-card class="update">
|
||||||
<template #header>
|
<template #header>
|
||||||
@ -40,6 +69,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<!-- 桌面端设置菜单 -->
|
||||||
<el-col :span="12" class="right">
|
<el-col :span="12" class="right">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<setting-two theme="filled" size="28" fill="#ffffff60" />
|
<setting-two theme="filled" size="28" fill="#ffffff60" />
|
||||||
@ -52,7 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { CloseOne, SettingTwo, GithubOne, AddOne, Bug } from "@icon-park/vue-next";
|
import { CloseOne, SettingTwo, GithubOne, AddOne, Bug, FileEditingOne } from "@icon-park/vue-next";
|
||||||
import { mainStore } from "@/store";
|
import { mainStore } from "@/store";
|
||||||
import Set from "@/components/Set.vue";
|
import Set from "@/components/Set.vue";
|
||||||
import config from "@/../package.json";
|
import config from "@/../package.json";
|
||||||
@ -75,12 +105,15 @@ const siteUrl = computed(() => {
|
|||||||
// 更新日志
|
// 更新日志
|
||||||
const upData = reactive({
|
const upData = reactive({
|
||||||
new: [
|
new: [
|
||||||
"采用 Vue 进行重构",
|
"增加逐字歌词功能",
|
||||||
"音乐歌单支持快速自定义",
|
"依赖组件更新",
|
||||||
"壁纸支持个性化设置",
|
"支持在移动端打开设置",
|
||||||
"音乐播放器支持音量控制",
|
"添加音乐进度条",
|
||||||
|
"动效优化",
|
||||||
|
"交互优化",
|
||||||
|
"支持在移动端显示不同的壁纸",
|
||||||
],
|
],
|
||||||
fix: ["修复天气 API", "时光胶囊显示错误", "移动端动画及细节", "图标更换为 IconPark"],
|
fix: ["消除依赖及功能弃用提示", "增强网页兼容性", "修复 Player 模块的故障"],
|
||||||
});
|
});
|
||||||
|
|
||||||
// 跳转源代码仓库
|
// 跳转源代码仓库
|
||||||
@ -137,6 +170,7 @@ const jumpTo = (url) => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 260px;
|
height: 260px;
|
||||||
min-height: 140px;
|
min-height: 140px;
|
||||||
|
|
||||||
.bg {
|
.bg {
|
||||||
font-size: 5rem;
|
font-size: 5rem;
|
||||||
}
|
}
|
||||||
@ -150,14 +184,17 @@ const jumpTo = (url) => {
|
|||||||
.bg {
|
.bg {
|
||||||
font-size: 4.5rem;
|
font-size: 4.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sm {
|
.sm {
|
||||||
font-size: 1.7rem;
|
font-size: 1.7rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 825px) {
|
@media (max-width: 825px) {
|
||||||
.bg {
|
.bg {
|
||||||
font-size: 3.8rem;
|
font-size: 3.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sm {
|
.sm {
|
||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
}
|
}
|
||||||
@ -242,4 +279,139 @@ const jumpTo = (url) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
|
||||||
|
.mobileset {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
-webkit-transform: translate(-50%, -50%);
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 82%;
|
||||||
|
height: 86%;
|
||||||
|
background: rgb(255 255 255 / 40%);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 36px;
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
top: 14px;
|
||||||
|
right: 14px;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-row {
|
||||||
|
height: 100%;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
height: 100%;
|
||||||
|
padding-left: 24px !important;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
// justify-content: space-between;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
transform: translateY(-8%);
|
||||||
|
font-family: "Pacifico-Regular";
|
||||||
|
padding-left: 6px;
|
||||||
|
width: 72%;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
.bg {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm {
|
||||||
|
margin-left: 6px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding-top: 18px;
|
||||||
|
|
||||||
|
.i-icon {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
margin-right: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobileset-scrollable {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: auto;
|
||||||
|
|
||||||
|
.num {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: "Pacifico-Regular";
|
||||||
|
}
|
||||||
|
|
||||||
|
.github {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin-left: 12px;
|
||||||
|
margin-top: 6px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.update {
|
||||||
|
margin-top: 30px;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.upnote {
|
||||||
|
padding: 20px;
|
||||||
|
height: calc(100% - 56px);
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.uptext {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
|
||||||
|
&:nth-last-of-type(1) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.i-icon {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -22,6 +22,9 @@ export default ({ mode }) =>
|
|||||||
}),
|
}),
|
||||||
VitePWA({
|
VitePWA({
|
||||||
registerType: "autoUpdate",
|
registerType: "autoUpdate",
|
||||||
|
// 酪灰的小批注:如果遇到了子页面自动跳转主页等问题,或不需要客户端浏览器缓存,可尝试取消注释这两行代码,而不需要完全移除 PWA ~
|
||||||
|
// selfDestroying: true,
|
||||||
|
// injectRegister: false,
|
||||||
workbox: {
|
workbox: {
|
||||||
skipWaiting: true,
|
skipWaiting: true,
|
||||||
clientsClaim: true,
|
clientsClaim: true,
|
||||||
@ -106,8 +109,10 @@ export default ({ mode }) =>
|
|||||||
css: {
|
css: {
|
||||||
preprocessorOptions: {
|
preprocessorOptions: {
|
||||||
scss: {
|
scss: {
|
||||||
|
api: 'modern',
|
||||||
charset: false,
|
charset: false,
|
||||||
additionalData: `@use "@/style/global.scss" as global;`,
|
additionalData: `@use "@/style/global.scss" as global;`,
|
||||||
|
silenceDeprecations: ["legacy-js-api"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user