Merge pull request #45 from nikoyoke1/master

🦄 reactor: 优化解析点歌显示(bate)
This commit is contained in:
Zhiyu 2024-11-08 09:28:46 +08:00 committed by GitHub
commit 89dd3c6067
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 344 additions and 29 deletions

View File

@ -2,6 +2,7 @@ import axios from "axios";
import { formatTime } from '../utils/other.js' import { formatTime } from '../utils/other.js'
import puppeteer from "../../../lib/puppeteer/puppeteer.js"; import puppeteer from "../../../lib/puppeteer/puppeteer.js";
import PickSongList from "../model/pick-song.js"; import PickSongList from "../model/pick-song.js";
import NeteaseMusicInfo from '../model/neteaseMusicInfo.js'
import { NETEASE_API_CN, NETEASE_SONG_DOWNLOAD, NETEASE_TEMP_API } from "../constants/tools.js"; import { NETEASE_API_CN, NETEASE_SONG_DOWNLOAD, NETEASE_TEMP_API } from "../constants/tools.js";
import { COMMON_USER_AGENT, REDIS_YUNZAI_ISOVERSEA, REDIS_YUNZAI_SONGINFO } from "../constants/constant.js"; import { COMMON_USER_AGENT, REDIS_YUNZAI_ISOVERSEA, REDIS_YUNZAI_SONGINFO } from "../constants/constant.js";
import { downloadAudio } from "../utils/common.js"; import { downloadAudio } from "../utils/common.js";
@ -105,7 +106,7 @@ export class songRequest extends plugin {
await redisSetKey(REDIS_YUNZAI_SONGINFO, songInfo) await redisSetKey(REDIS_YUNZAI_SONGINFO, songInfo)
const data = await new PickSongList(e).getData(musicDate.data) const data = await new PickSongList(e).getData(musicDate.data)
let img = await puppeteer.screenshot("pick-song", data); let img = await puppeteer.screenshot("pick-song", data);
e.reply(img, true); e.reply(img);
} else { } else {
e.reply('暂未找到你想听的歌哦~') e.reply('暂未找到你想听的歌哦~')
} }
@ -119,10 +120,11 @@ export class songRequest extends plugin {
const saveId = songInfo.findIndex(item => item.group_id === e.group.group_id) const saveId = songInfo.findIndex(item => item.group_id === e.group.group_id)
const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality; const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality;
const pickSongUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", songInfo[saveId].data[pickNumber].id) const pickSongUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", songInfo[saveId].data[pickNumber].id)
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + songInfo[saveId].data[pickNumber].id
const statusUrl = autoSelectNeteaseApi + '/login/status' //用户状态API const statusUrl = autoSelectNeteaseApi + '/login/status' //用户状态API
const isCkExpired = await this.checkCooike(statusUrl) const isCkExpired = await this.checkCooike(statusUrl)
// // 请求netease数据 // // 请求netease数据
this.neteasePlay(e, pickSongUrl, songInfo[saveId].data, pickNumber, isCkExpired) this.neteasePlay(e, pickSongUrl, songWikiUrl, songInfo[saveId].data, pickNumber, isCkExpired)
} }
} }
@ -173,8 +175,9 @@ export class songRequest extends plugin {
}) })
const pickSongUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", songInfo[0].id) const pickSongUrl = AUTO_NETEASE_SONG_DOWNLOAD.replace("{}", songInfo[0].id)
const statusUrl = autoSelectNeteaseApi + '/login/status' //用户状态API const statusUrl = autoSelectNeteaseApi + '/login/status' //用户状态API
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + songInfo[0].id
const isCkExpired = await this.checkCooike(statusUrl) const isCkExpired = await this.checkCooike(statusUrl)
this.neteasePlay(e, pickSongUrl, songInfo, 0, isCkExpired) this.neteasePlay(e, pickSongUrl, songWikiUrl, songInfo, 0, isCkExpired)
} else { } else {
e.reply('暂未找到你想听的歌哦~') e.reply('暂未找到你想听的歌哦~')
} }
@ -256,7 +259,7 @@ export class songRequest extends plugin {
} }
// 网易云音乐下载策略 // 网易云音乐下载策略
neteasePlay(e, pickSongUrl, songInfo, pickNumber = 0, isCkExpired) { neteasePlay(e, pickSongUrl, songWikiUrl, songInfo, pickNumber = 0, isCkExpired) {
axios.get(pickSongUrl, { axios.get(pickSongUrl, {
headers: { headers: {
"User-Agent": COMMON_USER_AGENT, "User-Agent": COMMON_USER_AGENT,
@ -291,18 +294,57 @@ export class songRequest extends plugin {
let url = await resp.data.data?.[0]?.url || null; let url = await resp.data.data?.[0]?.url || null;
const AudioLevel = translateToChinese(resp.data.data?.[0]?.level) const AudioLevel = translateToChinese(resp.data.data?.[0]?.level)
const AudioSize = bytesToMB(resp.data.data?.[0]?.size) const AudioSize = bytesToMB(resp.data.data?.[0]?.size)
// 获取歌曲信息
// 获取歌曲标题
let title = songInfo[pickNumber].songName + '-' + songInfo[pickNumber].singerName let title = songInfo[pickNumber].songName + '-' + songInfo[pickNumber].singerName
let typelist = []
// 歌曲百科API
await axios.get(songWikiUrl, {
headers: {
"User-Agent": COMMON_USER_AGENT,
// "Cookie": this.neteaseCookie
},
}).then(res => {
const wikiData = res.data.data.blocks[1].creatives
typelist.push(wikiData[0].resources[0].uiElement.mainTitle.title)
// 防止数据过深出错
const recTags = wikiData[1]
if (recTags.resources[0]) {
for (let i = 0; i < Math.min(3, recTags.resources.length); i++) {
if (recTags.resources[i] && recTags.resources[i].uiElement && recTags.resources[i].uiElement.mainTitle.title) {
typelist.push(recTags.resources[i].uiElement.mainTitle.title)
}
}
} else {
if (recTags.uiElement.textLinks[0].text) typelist.push(recTags.uiElement.textLinks[0].text)
}
if (wikiData[2].uiElement.mainTitle.title == 'BPM') {
typelist.push('BPM ' + wikiData[2].uiElement.textLinks[0].text)
} else {
typelist.push(wikiData[2].uiElement.textLinks[0].text)
}
typelist.push(AudioLevel)
})
let musicInfo = {
'cover': songInfo[pickNumber].cover,
'songName': songInfo[pickNumber].songName,
'singerName': songInfo[pickNumber].singerName,
'size': AudioSize + ' MB',
'musicType': typelist
}
// 一般这个情况是VIP歌曲 (如果没有url或者是国内,公用接口暂时不可用必须自建并且ck可用状态才能进行高质量解析) // 一般这个情况是VIP歌曲 (如果没有url或者是国内,公用接口暂时不可用必须自建并且ck可用状态才能进行高质量解析)
if (!isCkExpired || url == null) { if (!isCkExpired || url == null) {
url = await this.musicTempApi(e, title, "网易云音乐"); url = await this.musicTempApi(e, musicInfo, title);
} else { } else {
// 拥有ck并且有效直接进行解析 // 拥有ck并且有效直接进行解析
let audioInfo = AudioLevel; let audioInfo = AudioLevel;
if (AudioLevel == '杜比全景声') { if (AudioLevel == '杜比全景声') {
audioInfo += '\n(杜比下载文件为MP4编码格式为AC-4需要设备支持才可播放)'; audioInfo += '\n(杜比下载文件为MP4编码格式为AC-4需要设备支持才可播放)';
} }
e.reply([segment.image(songInfo[pickNumber].cover), `${this.identifyPrefix}识别:网易云音乐,${title}\n当前下载音质: ${audioInfo}\n预估大小: ${AudioSize}MB`]); const data = await new NeteaseMusicInfo(e).getData(musicInfo)
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
e.reply(img);
} }
// 动态判断后缀名 // 动态判断后缀名
let musicExt = resp.data.data?.[0]?.type let musicExt = resp.data.data?.[0]?.type
@ -333,7 +375,7 @@ export class songRequest extends plugin {
}); });
} }
async musicTempApi(e, title, musicType) { async musicTempApi(e, musicInfo, title) {
let musicReqApi = NETEASE_TEMP_API; let musicReqApi = NETEASE_TEMP_API;
// 临时接口title经过变换后搜索到的音乐质量提升 // 临时接口title经过变换后搜索到的音乐质量提升
const vipMusicData = await axios.get(musicReqApi.replace("{}", title.replace("-", " ")), { const vipMusicData = await axios.get(musicReqApi.replace("{}", title.replace("-", " ")), {
@ -341,11 +383,13 @@ export class songRequest extends plugin {
"User-Agent": COMMON_USER_AGENT, "User-Agent": COMMON_USER_AGENT,
}, },
}); });
const messageTitle = title + "\nR插件检测到当前为VIP音乐正在转换..."; const url = vipMusicData.data?.music_url
// ??后的内容是适配`QQ_MUSIC_TEMP_API`、最后是汽水 const id = vipMusicData.data?.id ?? vipMusicData.data?.data?.quality ?? vipMusicData.data?.pay;
const url = vipMusicData.data?.music_url ?? vipMusicData.data?.data?.music_url ?? vipMusicData.data?.music; musicInfo.size = id
const cover = vipMusicData.data?.cover ?? vipMusicData.data?.data?.cover ?? vipMusicData.data?.cover; musicInfo.musicType = musicInfo.musicType.slice(0, -1)
await e.reply([segment.image(cover), `${this.identifyPrefix}识别:${musicType}${messageTitle}`]); const data = await new NeteaseMusicInfo(e).getData(musicInfo)
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
e.reply(img);
return url; return url;
} }

View File

@ -57,6 +57,7 @@ import {
XHS_REQ_LINK XHS_REQ_LINK
} from "../constants/tools.js"; } from "../constants/tools.js";
import BiliInfoModel from "../model/bili-info.js"; import BiliInfoModel from "../model/bili-info.js";
import NeteaseMusicInfo from '../model/neteaseMusicInfo.js'
import config from "../model/config.js"; import config from "../model/config.js";
import NeteaseModel from "../model/netease.js"; import NeteaseModel from "../model/netease.js";
import * as aBogus from "../utils/a-bogus.cjs"; import * as aBogus from "../utils/a-bogus.cjs";
@ -104,7 +105,7 @@ import Translate from "../utils/trans-strategy.js";
import { mid2id } from "../utils/weibo.js"; import { mid2id } from "../utils/weibo.js";
import { convertToSeconds, removeParams, ytbFormatTime } from "../utils/youtube.js"; import { convertToSeconds, removeParams, ytbFormatTime } from "../utils/youtube.js";
import { ytDlpGetDuration, ytDlpGetThumbnail, ytDlpGetTilt, ytDlpHelper } from "../utils/yt-dlp-util.js"; import { ytDlpGetDuration, ytDlpGetThumbnail, ytDlpGetTilt, ytDlpHelper } from "../utils/yt-dlp-util.js";
import { textArrayToMakeForward } from "../utils/yunzai-util.js"; import { textArrayToMakeForward, sendMusicCard } from "../utils/yunzai-util.js";
export class tools extends plugin { export class tools extends plugin {
/** /**
@ -1701,6 +1702,7 @@ export class tools extends plugin {
if (/mv\?/.test(message)) { if (/mv\?/.test(message)) {
const AUTO_NETEASE_MV_DETAIL = autoSelectNeteaseApi + "/mv/detail?mvid={}"; const AUTO_NETEASE_MV_DETAIL = autoSelectNeteaseApi + "/mv/detail?mvid={}";
const AUTO_NETEASE_MV_URL = autoSelectNeteaseApi + "/mv/url?id={}"; const AUTO_NETEASE_MV_URL = autoSelectNeteaseApi + "/mv/url?id={}";
// logger.info(AUTO_NETEASE_MV_DETAIL.replace("{}", id)); // logger.info(AUTO_NETEASE_MV_DETAIL.replace("{}", id));
// logger.info(AUTO_NETEASE_MV_URL.replace("{}", id)); // logger.info(AUTO_NETEASE_MV_URL.replace("{}", id));
const [mvDetailData, mvUrlData] = await Promise.all([ const [mvDetailData, mvUrlData] = await Promise.all([
@ -1726,6 +1728,7 @@ export class tools extends plugin {
}); });
return; return;
} }
const songWikiUrl = autoSelectNeteaseApi + '/song/wiki/summary?id=' + id
// 国内解决方案替换为国内API (其中NETEASE_API_CN是国内基址) // 国内解决方案替换为国内API (其中NETEASE_API_CN是国内基址)
const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality; const AUTO_NETEASE_SONG_DOWNLOAD = autoSelectNeteaseApi + "/song/url/v1?id={}&level=" + this.neteaseCloudAudioQuality;
const AUTO_NETEASE_SONG_DETAIL = autoSelectNeteaseApi + "/song/detail?ids={}"; const AUTO_NETEASE_SONG_DETAIL = autoSelectNeteaseApi + "/song/detail?ids={}";
@ -1769,39 +1772,81 @@ export class tools extends plugin {
const AudioLevel = translateToChinese(resp.data.data?.[0]?.level) const AudioLevel = translateToChinese(resp.data.data?.[0]?.level)
const AudioSize = bytesToMB(resp.data.data?.[0]?.size) const AudioSize = bytesToMB(resp.data.data?.[0]?.size)
// 获取歌曲信息 // 获取歌曲信息
let title = await axios.get(detailUrl).then(res => { let { songName, artistName } = await axios.get(detailUrl).then(res => {
// logger.info('歌曲详情---', res.data.songs[0])
const song = res.data.songs[0]; const song = res.data.songs[0];
return cleanFilename(`${song?.name}-${song?.ar?.[0].name}`); return {
songName: cleanFilename(song?.name),
artistName: cleanFilename(song?.ar?.[0].name)
};
}); });
let title = songName + '-' + artistName
// 获取歌曲封面 // 获取歌曲封面
let coverUrl = await axios.get(detailUrl).then(res => { let coverUrl = await axios.get(detailUrl).then(res => {
const song = res.data.songs[0]; const song = res.data.songs[0];
return song?.al?.picUrl return song?.al?.picUrl
}); });
let typelist = []
// 歌曲百科API
await axios.get(songWikiUrl, {
headers: {
"User-Agent": COMMON_USER_AGENT,
// "Cookie": this.neteaseCookie
},
}).then(res => {
const wikiData = res.data.data.blocks[1].creatives
typelist.push(wikiData[0].resources[0].uiElement.mainTitle.title)
// 防止数据过深出错
const recTags = wikiData[1]
if (recTags.resources[0]) {
for (let i = 0; i < Math.min(3, recTags.resources.length); i++) {
if (recTags.resources[i] && recTags.resources[i].uiElement && recTags.resources[i].uiElement.mainTitle.title) {
typelist.push(recTags.resources[i].uiElement.mainTitle.title)
}
}
} else {
if (recTags.uiElement.textLinks[0].text) typelist.push(recTags.uiElement.textLinks[0].text)
}
if (wikiData[2].uiElement.mainTitle.title == 'BPM') {
typelist.push('BPM ' + wikiData[2].uiElement.textLinks[0].text)
} else {
typelist.push(wikiData[2].uiElement.textLinks[0].text)
}
typelist.push(AudioLevel)
})
let musicInfo = {
'cover': coverUrl,
'songName': songName,
'singerName': artistName,
'size': AudioSize + " MB",
'musicType': typelist
}
// 一般这个情况是VIP歌曲 (如果没有url或者是国内,公用接口暂时不可用必须自建并且ck可用状态才能进行高质量解析) // 一般这个情况是VIP歌曲 (如果没有url或者是国内,公用接口暂时不可用必须自建并且ck可用状态才能进行高质量解析)
if (!isCkExpired || url == null) { if (!isCkExpired || url == null) {
url = await this.musicTempApi(e, title, "网易云音乐"); url = await this.musicTempApi(e, title, "网易云音乐", musicInfo);
} else { } else {
// 拥有ck并且有效直接进行解析 // 拥有ck并且有效直接进行解析
let audioInfo = AudioLevel; let audioInfo = AudioLevel;
if (AudioLevel == '杜比全景声') { if (AudioLevel == '杜比全景声') {
audioInfo += '\n(杜比下载文件为MP4编码格式为AC-4需要设备支持才可播放)'; audioInfo += '\n(杜比下载文件为MP4编码格式为AC-4需要设备支持才可播放)';
} }
e.reply([segment.image(coverUrl), `${this.identifyPrefix}识别:网易云音乐,${title}\n当前下载音质: ${audioInfo}\n预估大小: ${AudioSize}MB`]); const data = await new NeteaseMusicInfo(e).getData(musicInfo)
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
await e.reply(img);
// e.reply([segment.image(coverUrl), `${this.identifyPrefix}识别:网易云音乐,${title}\n当前下载音质: ${audioInfo}\n预估大小: ${AudioSize}MB`]);
} }
// 动态判断后缀名 // 动态判断后缀名
let musicExt = resp.data.data?.[0]?.type let musicExt = resp.data.data?.[0]?.type
// 下载音乐 // 下载音乐
downloadAudio(url, this.getCurDownloadPath(e), title, 'follow', musicExt).then(async path => { downloadAudio(url, this.getCurDownloadPath(e), title, 'follow', musicExt).then(async path => {
// 发送群文件
await this.uploadGroupFile(e, path);
// 删除文件
await checkAndRemoveFile(path);
// 发送语音 // 发送语音
if (musicExt != 'mp4' && this.isSendVocal) { if (musicExt != 'mp4' && this.isSendVocal) {
await e.reply(segment.record(path)); await e.reply(segment.record(path));
} }
// 上传群文件
await this.uploadGroupFile(e, path);
// 删除文件
await checkAndRemoveFile(path);
}).catch(err => { }).catch(err => {
logger.error(`下载音乐失败,错误信息为: ${err}`); logger.error(`下载音乐失败,错误信息为: ${err}`);
}); });
@ -1810,7 +1855,7 @@ export class tools extends plugin {
} }
// 临时接口 // 临时接口
async musicTempApi(e, title, musicType) { async musicTempApi(e, title, musicType, musicInfo = {}) {
let musicReqApi = NETEASE_TEMP_API; let musicReqApi = NETEASE_TEMP_API;
if (musicType === "QQ音乐") { if (musicType === "QQ音乐") {
musicReqApi = QQ_MUSIC_TEMP_API; musicReqApi = QQ_MUSIC_TEMP_API;
@ -1823,11 +1868,32 @@ export class tools extends plugin {
"User-Agent": COMMON_USER_AGENT, "User-Agent": COMMON_USER_AGENT,
}, },
}); });
const messageTitle = title + "\nR插件检测到当前为VIP音乐正在转换..."; // const messageTitle = title + "\nR插件检测到当前为VIP音乐正在转换...";
// ??后的内容是适配`QQ_MUSIC_TEMP_API`、最后是汽水 // ??后的内容是适配`QQ_MUSIC_TEMP_API`、最后是汽水
const url = vipMusicData.data?.music_url ?? vipMusicData.data?.data?.music_url ?? vipMusicData.data?.music; const url = vipMusicData.data?.music_url ?? vipMusicData.data?.data?.music_url ?? vipMusicData.data?.music;
const cover = vipMusicData.data?.cover ?? vipMusicData.data?.data?.cover ?? vipMusicData.data?.cover; const cover = vipMusicData.data?.cover ?? vipMusicData.data?.data?.cover ?? vipMusicData.data?.cover;
await e.reply([segment.image(cover), `${ this.identifyPrefix }识别:${ musicType }${ messageTitle }`]); const name = vipMusicData.data?.title ?? vipMusicData.data?.data?.song_name ?? vipMusicData.data?.title;
const singer = vipMusicData.data?.singer ?? vipMusicData.data?.data?.song_singer ?? vipMusicData.data?.singer;
const id = vipMusicData.data?.id ?? vipMusicData.data?.data?.quality ?? vipMusicData.data?.pay;
if (musicType === "网易云音乐") {
musicInfo.size = id
musicInfo.musicType = musicInfo.musicType.slice(0, -1)
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
await e.reply(img);
} else {
musicInfo = {
'cover': cover,
'songName': name,
'singerName': singer,
'size': id,
'musicType': ""
}
const data = await new NeteaseMusicInfo(e).getData(musicInfo)
let img = await puppeteer.screenshot("neteaseMusicInfo", data);
await e.reply(img);
}
// await e.reply([segment.image(cover), `${this.identifyPrefix}识别:${musicType}${messageTitle}`]);
return url; return url;
} }

View File

@ -265,7 +265,7 @@ export function supportGuoba() {
}, },
{ {
field: "tools.isSendVocal", field: "tools.isSendVocal",
label: "网易云开启发送音频", label: "网易云开启发送音频",
bottomHelpMessage: bottomHelpMessage:
"默认开启,识别音乐之后是否转化群语音发送,关闭将获得一定的性能提升", "默认开启,识别音乐之后是否转化群语音发送,关闭将获得一定的性能提升",
component: "Switch", component: "Switch",

17
model/neteaseMusicInfo.js Normal file
View File

@ -0,0 +1,17 @@
import Base from './base.js'
export default class NeteaseMusicInfo extends Base {
constructor (e) {
super(e)
this.model = 'neteaseMusicInfo'
}
/** 生成版本信息图片 */
async getData (songInfo) {
return {
...this.screenData,
saveId: 'neteaseMusicInfo',
songInfo: songInfo,
}
}
}

View File

@ -0,0 +1,138 @@
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap');
@font-face {
font-family: 'singerName';
src: url("../../font/江城月湖体\ 400W.ttf");
}
body,
html {
margin: 0;
padding: 0;
width: 100%;
font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
.bg-image,
.img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 450px;
z-index: -1;
object-fit: cover;
}
.inner {
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(5px);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.infoBox {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
}
.songinfobox {
width: 100%;
height: 100%;
padding: 25px 0px 17px 0px;
}
.info {
width: 100%;
height: 100%;
border: 0px solid #ffffff2e;
backdrop-filter: blur(10px);
background: hsla(0, 0%, 100%, 0.281);
box-shadow: 0 6px 15px 0 #8e8e8e30;
}
.cover {
width: 100%;
height: 135px;
display: flex;
justify-content: center;
}
.cover img {
width: 135px;
height: 135px;
border-radius: 10px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
}
.songSize {
width: 100%;
text-align: center;
margin-top: 20px;
font-size: 18px;
font-family: 'singerName';
color: #fff;
text-shadow: 2px 2px 5px rgba(255, 255, 255, 0.4);
}
.songName {
width: 100%;
text-align: center;
margin-top: 10px;
font-size: 20px;
color: #fff;
text-shadow: 2px 2px 5px rgba(255, 255, 255, 0.4);
}
.singerName {
width: 100%;
text-align: center;
font-family: 'singerName';
margin-top: 17px;
font-size: 17px;
color: #fff;
text-shadow: 2px 2px 5px rgba(255, 255, 255, 0.4);
}
.typeBox {
width: 100%;
margin-top: 22px;
display: flex;
justify-content: center;
}
.typeList {
display: flex;
}
.typeNav {
font-size: 15px;
height: 25px;
padding: 0px 10px;
box-sizing: border-box;
background-color: rgba(255, 255, 255, 0.2);
line-height: 0px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 12.5px;
margin-left: 10px;
color: #fff;
box-shadow: 0px 0px 3px rgba(255, 255, 255, 0.4);
}
.logo{
width: 100%;
text-align: center;
font-size: 15px;
margin-top: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'singerName';
}

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>歌曲信息</title>
<style>
@import url('{{pluResPath}}html/neteaseMusicInfo/neteaseMusicInfo.css');
</style>
</head>
<body>
<div class="bg-image">
<img src="{{ songInfo.cover }}" alt="" class="img" width="100%">
<div class="inner"></div>
</div>
<div class="infoBox">
<div class="info">
<div class="songinfobox">
<div class="cover">
<img src="{{ songInfo.cover }}" alt="">
</div>
<div class="songSize">
{{ songInfo.size }}
</div>
<div class="songName">
{{ songInfo.songName }}
</div>
<div class="singerName">
{{ songInfo.singerName }}
</div>
{{if songInfo.musicType}}
<div class="typeBox">
<div class="typeList">
{{each songInfo.musicType typeName}}
<div class="typeNav">
{{ typeName || '喵喵~'}}
</div>
{{ /each }}
</div>
</div>
{{/if}}
<div class="logo">Created By Yunzai-Bot & R-Plugin</div>
</div>
</div>
</div>
</body>
</html>