This commit is contained in:
Jerry 2025-09-10 21:57:09 +08:00
parent b523fafdeb
commit c5ce5acfec
13 changed files with 48 additions and 737 deletions

View File

@ -21,9 +21,6 @@ export default class Base {
/** /**
* 截图默认数据 * 截图默认数据
* @param saveId html保存id
* @param tplFile 模板html路径
* @param pluResPath 插件资源路径
*/ */
get screenData() { get screenData() {
return { return {

View File

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

View File

@ -2,76 +2,58 @@ import fs from 'node:fs';
import _ from 'lodash'; import _ from 'lodash';
import YAML from 'yaml'; import YAML from 'yaml';
import chokidar from 'chokidar'; import chokidar from 'chokidar';
import Base from "./base.js"; import Base from './base.js';
class RConfig extends Base{ class RConfig extends Base {
constructor(e) { constructor(e) {
super(e); super(e);
this.configPath = `./plugins/${RConfig.pluginName}/config/`; this.configPath = `./plugins/${RConfig.pluginName}/config/`;
this.previousContent = new Map(); // 存储每个文件之前的内容 this.previousContent = new Map(); // 存储每个文件之前的内容
}
getConfig(name) {
return this.getYaml(name);
}
getYaml(name, isWatch = true) {
let file = this.getFilePath(name);
const yaml = YAML.parse(fs.readFileSync(file, 'utf8'));
if (isWatch) {
this.previousContent.set(name, yaml); // 保存初始内容
this.watch(file, name);
} }
return yaml;
}
getConfig(name) { getFilePath(name) {
return this.getYaml(name); return `${this.configPath}${name}.yaml`;
} }
getField(name, field) { watch(file, name) {
const config = this.getConfig(name); const watcher = chokidar.watch(file);
return config[field];
} watcher.on('change', (path) => {
const currentContent = YAML.parse(fs.readFileSync(path, 'utf8'));
updateField(name, field, value) { const previousContent = this.previousContent.get(name);
let config = this.getConfig(name);
config[field] = value; if (!_.isEqual(previousContent, currentContent)) {
logger.mark(`[R插件][修改配置项][${name}][${field}]修改为:${value}`); logger.mark(`[R插件][配置文件]${name}已经被重置`);
this.saveAllConfig(name, config); this.previousContent.set(name, currentContent); // 更新之前的内容
} }
});
deleteField(name, field) { }
let config = this.getConfig(name);
delete config[field]; saveAllConfig(name, data) {
this.saveAllConfig(name, config); let file = this.getFilePath(name);
} if (_.isEmpty(data)) {
fs.existsSync(file) && fs.unlinkSync(file);
getYaml(name, isWatch = true) { } else {
let file = this.getFilePath(name); let yaml = YAML.stringify(data);
const yaml = YAML.parse(fs.readFileSync(file, 'utf8')); fs.writeFileSync(file, yaml, 'utf8');
if (isWatch) {
this.previousContent.set(name, yaml); // 保存初始内容
this.watch(file, name);
}
return yaml;
}
getFilePath(name) {
return `${this.configPath}${name}.yaml`;
}
watch(file, name) {
const watcher = chokidar.watch(file);
watcher.on('change', path => {
const currentContent = YAML.parse(fs.readFileSync(path, 'utf8'));
const previousContent = this.previousContent.get(name);
if (!_.isEqual(previousContent, currentContent)) {
logger.mark(`[R插件][配置文件]${name}已经被重置`);
this.previousContent.set(name, currentContent); // 更新之前的内容
}
});
}
saveAllConfig(name, data) {
let file = this.getFilePath(name);
if (_.isEmpty(data)) {
fs.existsSync(file) && fs.unlinkSync(file);
} else {
let yaml = YAML.stringify(data);
fs.writeFileSync(file, yaml, 'utf8');
}
this.watch(file, name);
} }
this.watch(file, name);
}
} }
export default new RConfig(); export default new RConfig();

View File

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

View File

@ -1,17 +0,0 @@
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

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

View File

@ -1,21 +0,0 @@
import Base from './base.js'
export default class Version extends Base {
constructor (e) {
super(e)
this.model = 'version'
}
/** 生成版本信息图片 */
async getData (versionData) {
const version =
(versionData && versionData.length && versionData[0].version) || '1.0.0'
return {
...this.screenData,
userId: version,
quality: 100,
saveId: version,
versionData
}
}
}

View File

@ -1,196 +0,0 @@
<!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('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap');
:root {
--primary-color: #C20C0C;
--secondary-color: #E74C3C;
--text-color: #FFFFFF;
--background-color: #2C3E50;
}
body, html {
margin: 0;
padding: 0;
height: 100%;
font-family: 'Noto Sans SC', 'PingFang SC', 'Microsoft YaHei', sans-serif;
background-color: var(--background-color);
color: var(--text-color);
}
.user-card {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
position: relative;
overflow: hidden;
}
.user-content {
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-radius: 20px;
padding: 40px;
max-width: 450px;
width: 90%;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
position: relative;
z-index: 1;
}
.user-header {
display: flex;
align-items: center;
margin-bottom: 30px;
}
.user-avatar {
width: 100px;
height: 100px;
border-radius: 50%;
border: 4px solid white;
margin-right: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
transition: transform 0.3s ease;
}
.user-avatar:hover {
transform: scale(1.05);
}
.user-name {
font-size: 2em;
font-weight: bold;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.user-name::after {
content: '♪';
margin-left: 10px;
font-size: 0.8em;
vertical-align: super;
opacity: 0.7;
}
.user-info {
background-color: rgba(255, 255, 255, 0.05);
border-radius: 15px;
padding: 25px;
backdrop-filter: blur(5px);
}
.info-item {
margin-bottom: 20px;
transition: transform 0.3s ease;
}
.info-item:hover {
transform: translateX(5px);
}
.info-label {
font-size: 1.1em;
opacity: 0.8;
margin-bottom: 5px;
font-weight: 400;
}
.info-value {
font-size: 1.3em;
font-weight: 700;
letter-spacing: 0.5px;
}
.music-note {
position: absolute;
font-size: 50px;
opacity: 0.2;
animation: float 8s infinite ease-in-out;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}
.note-1 { top: 10%; left: 10%; animation-delay: 0s; }
.note-2 { top: 20%; right: 10%; animation-delay: 2s; }
.note-3 { bottom: 15%; left: 20%; animation-delay: 4s; }
.note-4 { bottom: 25%; right: 15%; animation-delay: 6s; }
@keyframes float {
0%, 100% { transform: translateY(0) rotate(0deg); }
50% { transform: translateY(-30px) rotate(10deg); }
}
.background-wave {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 320'%3E%3Cpath fill='%23ffffff' fill-opacity='0.1' d='M0,96L48,112C96,128,192,160,288,186.7C384,213,480,235,576,213.3C672,192,768,128,864,128C960,128,1056,192,1152,208C1248,224,1344,192,1392,176L1440,160L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z'%3E%3C/path%3E%3C/svg%3E");
background-size: cover;
animation: wave 10s linear infinite;
}
@keyframes wave {
0% { background-position-x: 0; }
100% { background-position-x: 1440px; }
}
@media (max-width: 480px) {
.user-content {
padding: 30px;
}
.user-avatar {
width: 80px;
height: 80px;
}
.user-name {
font-size: 1.5em;
}
.info-label {
font-size: 1em;
}
.info-value {
font-size: 1.2em;
}
.music-note {
font-size: 40px;
}
}
</style>
</head>
<body>
<div class="user-card">
<div class="music-note note-1"></div>
<div class="music-note note-2"></div>
<div class="music-note note-3"></div>
<div class="music-note note-4"></div>
<div class="user-content">
<div class="user-header">
<img src="{{ neteaseData.avatarUrl }}" alt="用户头像" class="user-avatar">
<div class="user-name">{{ neteaseData.nickname }}</div>
</div>
<div class="user-info">
<div class="info-item">
<div class="info-label">会员等级:</div>
<div class="info-value">{{ neteaseData.vipLevel }}</div>
</div>
<div class="info-item">
<div class="info-label">最高解析音质:</div>
<div class="info-value">{{ neteaseData.musicQuality }}</div>
</div>
<div class="info-item">
<div class="info-label">会员到期时间:</div>
<div class="info-value">{{ neteaseData.expireDate }}</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,143 +0,0 @@
@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;
object-fit: cover;
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);
}
.typeNav:first-child {
margin-left: 0px;
}
.logo{
width: 100%;
text-align: center;
font-size: 15px;
margin-top: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'singerName';
}

View File

@ -1,58 +0,0 @@
<!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">
{{ if songInfo.cover != 'def' }}
<img src="{{ songInfo.cover }}" alt="" class="img" width="100%">
{{ else }}
<img src="{{pluResPath}}img/default.png" alt="" class="img" width="100%">
{{ /if }}
<div class="inner"></div>
</div>
<div class="infoBox">
<div class="info">
<div class="songinfobox">
<div class="cover">
{{ if songInfo.cover != 'def' }}
<img src="{{ songInfo.cover }}" alt="">
{{ else }}
<img src="{{pluResPath}}img/default.png" alt="">
{{ /if }}
</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>

View File

@ -1,137 +0,0 @@
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;700&display=swap');
@font-face {
font-family: 'number';
src: url("../../font/江城月湖体\ 400W.ttf");
}
body,
html {
margin: 0;
padding: 0;
font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
}
.songList {
min-height: 50vh;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
background: #121212ef;
position: relative;
padding: 0px 40px 20px 40px;
box-sizing: border-box;
}
.songListNav {
box-sizing: border-box;
width: 100%;
height: 100px;
margin-top: 30px;
display: flex;
justify-content: space-between;
position: relative;
z-index: 2;
}
.navText {
font-size: 30px;
color: #fff;
margin-left: 20px;
width: 85%;
}
.songName{
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.singerText{
font-size: 25px;
color: #aaa;
margin-top: 5px;
}
.navInfo {
display: flex;
width: 80%;
}
.navDuration {
color: #aaa;
width: 70px;
font-size: 25px;
height: 100%;
align-content: center;
text-align: center;
}
.cloudBox{
height: 100%;
width: 70px;
justify-content: center;
display: flex;
align-items: center;
}
.cloud{
color: #dd001b;
box-sizing: border-box;
padding: 0px 8px;
font-size: 22px;
height: 40px;
width: 70px;
border-radius: 10px;
display: flex;
justify-content: center;
border: 1px solid;
align-items: center;
}
.navInfo img {
width: 90px;
height: 90px;
border-radius: 8px;
flex-shrink: 0;
object-fit: cover;
}
.bgicon {
position: absolute;
top: calc(50% - 100px);
left: calc(50% - 85px);
width: 200px;
height: 200px;
z-index: 1;
}
.bgicon img {
width: 100%;
height: 100%;
opacity: 0.4
}
.number {
width: 40px;
height: 100%;
display: flex;
flex-shrink: 0;
justify-content: center;
align-items: center;
font-size: 40px;
color: #fff;
margin-right: 25px;
margin-left: -20px;
font-family: 'number'
}
.footer{
width: 100%;
text-align: center;
font-size: 20px;
margin-top: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'number';
}

View File

@ -1,45 +0,0 @@
<!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/pick-song/pick-song.css');
</style>
</head>
<body>
<div class="songList">
{{each songData info key}}
<div class="songListNav">
<div class="navInfo">
<div class="number">{{ key+1 }}</div>
{{ if info.cover != 'def' }}
<img src="{{ info.cover }}" alt="">
{{ else }}
<img src="{{pluResPath}}img/default.png" alt="">
{{ /if }}
<div class="navText">
<div class="songName">{{ info.songName }}</div>
<div class="singerText">{{ info.singerName }}</div>
</div>
</div>
{{ if info.duration == '云盘' }}
<div class="cloudBox">
<div class="cloud">{{ info.duration }}</div>
</div>
{{ else }}
<div class="navDuration">{{ info.duration }}</div>
{{ /if }}
</div>
{{ /each }}
<div class="bgicon">
<img src="{{pluResPath}}img/icon/neteaseRank.png" alt="">
</div>
<div class="footer">Created By Yunzai-Bot & R-Plugin</div>
</div>
</body>
</html>