mirror of
https://github.com/Jerryplusy/rc-plugin.git
synced 2025-10-14 08:09:19 +00:00
✨feat: 添加配置页面:bili、tiktok、YouTube、ncm、以及通用杂项
This commit is contained in:
parent
fddc036832
commit
af436915b9
@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
"form-data": "^4.0.1",
|
"form-data": "^4.0.1",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
"next": "^14.2.16",
|
"next": "^14.2.16",
|
||||||
"node-id3": "^0.2.6",
|
"node-id3": "^0.2.6",
|
||||||
"p-queue": "^8.0.1",
|
"p-queue": "^8.0.1",
|
||||||
|
52
server/app/r/api/config/route.js
Normal file
52
server/app/r/api/config/route.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import yaml from 'js-yaml';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export async function GET(req, res) {
|
||||||
|
const configPath = path.join(process.cwd(), "../", 'config', 'tools.yaml');
|
||||||
|
try {
|
||||||
|
const yamlContent = await fs.promises.readFile(configPath, 'utf8');
|
||||||
|
const config = yaml.load(yamlContent);
|
||||||
|
return new Response(JSON.stringify(config), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('读取配置文件失败:', error);
|
||||||
|
return new Response(JSON.stringify({ error: '读取配置文件失败' }), {
|
||||||
|
status: 500,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function POST(req, res) {
|
||||||
|
const configPath = path.join(process.cwd(), "../", 'config', 'tools.yaml');
|
||||||
|
try {
|
||||||
|
const updates = await req.json();
|
||||||
|
|
||||||
|
const yamlContent = await fs.promises.readFile(configPath, 'utf8');
|
||||||
|
const currentConfig = yaml.load(yamlContent);
|
||||||
|
|
||||||
|
// 只更新指定的字段
|
||||||
|
const newConfig = { ...currentConfig, ...updates };
|
||||||
|
|
||||||
|
// 转换回YAML并保存
|
||||||
|
const newYamlContent = yaml.dump(newConfig, {
|
||||||
|
indent: 2,
|
||||||
|
lineWidth: -1,
|
||||||
|
quotingType: '"'
|
||||||
|
});
|
||||||
|
await fs.promises.writeFile(configPath, newYamlContent, 'utf8');
|
||||||
|
return new Response(JSON.stringify({ success: true }), {
|
||||||
|
status: 200,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新配置文件失败:', error);
|
||||||
|
return new Response(JSON.stringify({ error: '更新配置文件失败' }), {
|
||||||
|
status: 500,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,21 @@
|
|||||||
import Bili from "./contents/bili.jsx";
|
import Bili from "./contents/bili.jsx";
|
||||||
|
import Generic from "./contents/generic.jsx";
|
||||||
import Home from "./contents/home.jsx";
|
import Home from "./contents/home.jsx";
|
||||||
|
import Ncm from "./contents/ncm.jsx";
|
||||||
import Tiktok from "./contents/tiktok.jsx";
|
import Tiktok from "./contents/tiktok.jsx";
|
||||||
import Weekly from "./contents/weekly.jsx";
|
import Weekly from "./contents/weekly.jsx";
|
||||||
|
import Youtube from "./contents/youtube.jsx";
|
||||||
|
|
||||||
export function Content({ activeItem }) {
|
export function Content({ activeItem }) {
|
||||||
|
|
||||||
// 使用对象映射内容,以便于后期扩展和维护
|
// 使用对象映射内容,以便于后期扩展和维护
|
||||||
const contentMap = {
|
const contentMap = {
|
||||||
"总控制台": <Home />,
|
"总控制台": <Home />,
|
||||||
|
"通用及杂项": <Generic />,
|
||||||
"哔哩哔哩控制台": <Bili />,
|
"哔哩哔哩控制台": <Bili />,
|
||||||
"抖音控制台": <Tiktok />,
|
"抖音控制台": <Tiktok />,
|
||||||
|
"网易云控制台": <Ncm />,
|
||||||
|
"油管控制台": <Youtube />,
|
||||||
"周刊预览": <Weekly />
|
"周刊预览": <Weekly />
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,7 +1,297 @@
|
|||||||
export default function Bili() {
|
import { useState, useEffect } from 'react';
|
||||||
|
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
||||||
|
|
||||||
|
export default function Bili() {
|
||||||
|
const [config, setConfig] = useState({
|
||||||
|
biliSessData: '',
|
||||||
|
biliDuration: 480,
|
||||||
|
biliIntroLenLimit: 50,
|
||||||
|
biliDisplayCover: true,
|
||||||
|
biliDisplayInfo: true,
|
||||||
|
biliDisplayIntro: true,
|
||||||
|
biliDisplayOnline: true,
|
||||||
|
biliDisplaySummary: false,
|
||||||
|
biliUseBBDown: false,
|
||||||
|
biliCDN: 0,
|
||||||
|
biliDownloadMethod: 0,
|
||||||
|
biliResolution: 5
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// 读取配置
|
||||||
|
useEffect(() => {
|
||||||
|
const loadConfig = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
biliSessData: yamlConfig.biliSessData || '',
|
||||||
|
biliDuration: yamlConfig.biliDuration || 480,
|
||||||
|
biliIntroLenLimit: yamlConfig.biliIntroLenLimit || 50,
|
||||||
|
biliDisplayCover: yamlConfig.biliDisplayCover ?? true,
|
||||||
|
biliDisplayInfo: yamlConfig.biliDisplayInfo ?? true,
|
||||||
|
biliDisplayIntro: yamlConfig.biliDisplayIntro ?? true,
|
||||||
|
biliDisplayOnline: yamlConfig.biliDisplayOnline ?? true,
|
||||||
|
biliDisplaySummary: yamlConfig.biliDisplaySummary ?? false,
|
||||||
|
biliUseBBDown: yamlConfig.biliUseBBDown ?? false,
|
||||||
|
biliCDN: yamlConfig.biliCDN || 0,
|
||||||
|
biliDownloadMethod: yamlConfig.biliDownloadMethod || 0,
|
||||||
|
biliResolution: yamlConfig.biliResolution || 5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
const handleSave = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const success = await updateYamlConfig({
|
||||||
|
biliSessData: config.biliSessData,
|
||||||
|
biliDuration: config.biliDuration,
|
||||||
|
biliIntroLenLimit: config.biliIntroLenLimit,
|
||||||
|
biliDisplayCover: config.biliDisplayCover,
|
||||||
|
biliDisplayInfo: config.biliDisplayInfo,
|
||||||
|
biliDisplayIntro: config.biliDisplayIntro,
|
||||||
|
biliDisplayOnline: config.biliDisplayOnline,
|
||||||
|
biliDisplaySummary: config.biliDisplaySummary,
|
||||||
|
biliUseBBDown: config.biliUseBBDown,
|
||||||
|
biliCDN: config.biliCDN,
|
||||||
|
biliDownloadMethod: config.biliDownloadMethod,
|
||||||
|
biliResolution: config.biliResolution
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
// 使用 daisyUI 的 toast 提示
|
||||||
|
document.getElementById('toast-success').classList.remove('hidden');
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('toast-success').classList.add('hidden');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存配置失败:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置配置
|
||||||
|
const handleReset = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
biliSessData: yamlConfig.biliSessData || '',
|
||||||
|
biliDuration: yamlConfig.biliDuration || 480,
|
||||||
|
biliIntroLenLimit: yamlConfig.biliIntroLenLimit || 50,
|
||||||
|
biliDisplayCover: yamlConfig.biliDisplayCover ?? true,
|
||||||
|
biliDisplayInfo: yamlConfig.biliDisplayInfo ?? true,
|
||||||
|
biliDisplayIntro: yamlConfig.biliDisplayIntro ?? true,
|
||||||
|
biliDisplayOnline: yamlConfig.biliDisplayOnline ?? true,
|
||||||
|
biliDisplaySummary: yamlConfig.biliDisplaySummary ?? false,
|
||||||
|
biliUseBBDown: yamlConfig.biliUseBBDown ?? false,
|
||||||
|
biliCDN: yamlConfig.biliCDN || 0,
|
||||||
|
biliDownloadMethod: yamlConfig.biliDownloadMethod || 0,
|
||||||
|
biliResolution: yamlConfig.biliResolution || 5
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>Bili</div>
|
<div className="p-6 mx-auto container">
|
||||||
|
{/* 成功提示 */}
|
||||||
|
<div id="toast-success" className="toast toast-top toast-end hidden">
|
||||||
|
<div className="alert alert-success">
|
||||||
|
<span>配置保存成功!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-5xl mx-auto">
|
||||||
|
<h2 className="text-2xl font-bold mb-6">Bilibili 配置</h2>
|
||||||
|
|
||||||
|
{/* 基础配置部分 */}
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-6">
|
||||||
|
<div className="card-body">
|
||||||
|
<h3 className="card-title mb-4">基础配置</h3>
|
||||||
|
|
||||||
|
{/* SESSDATA配置 */}
|
||||||
|
<div className="form-control w-full mb-4">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">SESSDATA</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.biliSessData}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliSessData: e.target.value })}
|
||||||
|
placeholder="请输入Bilibili SESSDATA"
|
||||||
|
className="input input-bordered w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 数值配置部分 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-4">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频时长限制(秒)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.biliDuration}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDuration: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">简介长度限制</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.biliIntroLenLimit}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliIntroLenLimit: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 开关配置部分 */}
|
||||||
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4 mb-4">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">显示封面</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.biliDisplayCover}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDisplayCover: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">显示视频信息</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.biliDisplayInfo}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDisplayInfo: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">显示简介</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.biliDisplayIntro}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDisplayIntro: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">显示在线人数</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.biliDisplayOnline}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDisplayOnline: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">显示总结</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.biliDisplaySummary}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDisplaySummary: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">使用BBDown</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.biliUseBBDown}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliUseBBDown: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 下拉选择配置部分 */}
|
||||||
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">CDN选择</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="select select-bordered"
|
||||||
|
value={config.biliCDN}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliCDN: parseInt(e.target.value) })}>
|
||||||
|
<option value={0}>不使用CDN</option>
|
||||||
|
<option value={1}>CDN 1</option>
|
||||||
|
<option value={2}>CDN 2</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">下载方式</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="select select-bordered"
|
||||||
|
value={config.biliDownloadMethod}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliDownloadMethod: parseInt(e.target.value) })}>
|
||||||
|
<option value={0}>原生下载</option>
|
||||||
|
<option value={1}>wget</option>
|
||||||
|
<option value={2}>axel</option>
|
||||||
|
<option value={3}>Aria2</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频画质</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="select select-bordered"
|
||||||
|
value={config.biliResolution}
|
||||||
|
onChange={(e) => setConfig({ ...config, biliResolution: parseInt(e.target.value) })}>
|
||||||
|
<option value={5}>480P</option>
|
||||||
|
<option value={16}>360P</option>
|
||||||
|
<option value={32}>720P</option>
|
||||||
|
<option value={64}>1080P</option>
|
||||||
|
<option value={74}>720P60</option>
|
||||||
|
<option value={80}>1080P+</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 保存按钮 */}
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost"
|
||||||
|
onClick={handleReset}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? <span className="loading loading-spinner"></span> : '保存配置'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
289
server/components/contents/generic.jsx
Normal file
289
server/components/contents/generic.jsx
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
||||||
|
|
||||||
|
export default function Generic() {
|
||||||
|
const [config, setConfig] = useState({
|
||||||
|
defaultPath: './data/rcmp4/',
|
||||||
|
videoSizeLimit: 70,
|
||||||
|
proxyAddr: '127.0.0.1',
|
||||||
|
proxyPort: '7890',
|
||||||
|
identifyPrefix: '',
|
||||||
|
streamDuration: 10,
|
||||||
|
streamCompatibility: false,
|
||||||
|
queueConcurrency: 1,
|
||||||
|
videoDownloadConcurrency: 1,
|
||||||
|
autoclearTrashtime: '0 0 8 * * ?',
|
||||||
|
deeplApiUrls: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// 读取配置
|
||||||
|
useEffect(() => {
|
||||||
|
const loadConfig = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
defaultPath: yamlConfig.defaultPath || './data/rcmp4/',
|
||||||
|
videoSizeLimit: yamlConfig.videoSizeLimit || 70,
|
||||||
|
proxyAddr: yamlConfig.proxyAddr || '127.0.0.1',
|
||||||
|
proxyPort: yamlConfig.proxyPort || '7890',
|
||||||
|
identifyPrefix: yamlConfig.identifyPrefix || '',
|
||||||
|
streamDuration: yamlConfig.streamDuration || 10,
|
||||||
|
streamCompatibility: yamlConfig.streamCompatibility ?? false,
|
||||||
|
queueConcurrency: yamlConfig.queueConcurrency || 1,
|
||||||
|
videoDownloadConcurrency: yamlConfig.videoDownloadConcurrency || 1,
|
||||||
|
autoclearTrashtime: yamlConfig.autoclearTrashtime || '0 0 8 * * ?',
|
||||||
|
deeplApiUrls: yamlConfig.deeplApiUrls || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
const handleSave = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const success = await updateYamlConfig({
|
||||||
|
defaultPath: config.defaultPath,
|
||||||
|
videoSizeLimit: config.videoSizeLimit,
|
||||||
|
proxyAddr: config.proxyAddr,
|
||||||
|
proxyPort: config.proxyPort,
|
||||||
|
identifyPrefix: config.identifyPrefix,
|
||||||
|
streamDuration: config.streamDuration,
|
||||||
|
streamCompatibility: config.streamCompatibility,
|
||||||
|
queueConcurrency: config.queueConcurrency,
|
||||||
|
videoDownloadConcurrency: config.videoDownloadConcurrency,
|
||||||
|
autoclearTrashtime: config.autoclearTrashtime,
|
||||||
|
deeplApiUrls: config.deeplApiUrls
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
document.getElementById('generic-toast-success').classList.remove('hidden');
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('generic-toast-success').classList.add('hidden');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存配置失败:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置配置
|
||||||
|
const handleReset = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
defaultPath: yamlConfig.defaultPath || './data/rcmp4/',
|
||||||
|
videoSizeLimit: yamlConfig.videoSizeLimit || 70,
|
||||||
|
proxyAddr: yamlConfig.proxyAddr || '127.0.0.1',
|
||||||
|
proxyPort: yamlConfig.proxyPort || '7890',
|
||||||
|
identifyPrefix: yamlConfig.identifyPrefix || '',
|
||||||
|
streamDuration: yamlConfig.streamDuration || 10,
|
||||||
|
streamCompatibility: yamlConfig.streamCompatibility ?? false,
|
||||||
|
queueConcurrency: yamlConfig.queueConcurrency || 1,
|
||||||
|
videoDownloadConcurrency: yamlConfig.videoDownloadConcurrency || 1,
|
||||||
|
autoclearTrashtime: yamlConfig.autoclearTrashtime || '0 0 8 * * ?',
|
||||||
|
deeplApiUrls: yamlConfig.deeplApiUrls || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6 mx-auto container">
|
||||||
|
{/* 成功提示 */}
|
||||||
|
<div id="generic-toast-success" className="toast toast-top toast-end hidden">
|
||||||
|
<div className="alert alert-success">
|
||||||
|
<span>配置保存成功!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-5xl mx-auto">
|
||||||
|
<h2 className="text-2xl font-bold mb-6">通用配置</h2>
|
||||||
|
|
||||||
|
{/* 基础配置部分 */}
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-6">
|
||||||
|
<div className="card-body">
|
||||||
|
<h3 className="card-title mb-4">基础配置</h3>
|
||||||
|
|
||||||
|
{/* 路径和大小限制配置 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频保存路径</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.defaultPath}
|
||||||
|
onChange={(e) => setConfig({ ...config, defaultPath: e.target.value })}
|
||||||
|
placeholder="请输入视频保存路径..."
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频大小限制(MB)</span>
|
||||||
|
<span className="label-text-alt text-xs">超过限制转为群文件</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.videoSizeLimit}
|
||||||
|
onChange={(e) => setConfig({ ...config, videoSizeLimit: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 代理配置 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">代理地址</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.proxyAddr}
|
||||||
|
onChange={(e) => setConfig({ ...config, proxyAddr: e.target.value })}
|
||||||
|
placeholder="请输入代理地址..."
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">代理端口</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.proxyPort}
|
||||||
|
onChange={(e) => setConfig({ ...config, proxyPort: e.target.value })}
|
||||||
|
placeholder="请输入代理端口..."
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 其他基础配置 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">识别前缀</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.identifyPrefix}
|
||||||
|
onChange={(e) => setConfig({ ...config, identifyPrefix: e.target.value })}
|
||||||
|
placeholder="请输入识别前缀..."
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频最大时长(秒)</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.streamDuration}
|
||||||
|
onChange={(e) => setConfig({ ...config, streamDuration: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 并发和定时配置 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">队列并发数</span>
|
||||||
|
<span className="label-text-alt text-xs">仅影响B站下载</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.queueConcurrency}
|
||||||
|
onChange={(e) => setConfig({ ...config, queueConcurrency: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频下载并发数</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.videoDownloadConcurrency}
|
||||||
|
onChange={(e) => setConfig({ ...config, videoDownloadConcurrency: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* DeepL API配置 */}
|
||||||
|
<div className="form-control w-full mb-6">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">DeepL API地址</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={config.deeplApiUrls}
|
||||||
|
onChange={(e) => setConfig({ ...config, deeplApiUrls: e.target.value })}
|
||||||
|
placeholder="请输入DeepL API地址,多个地址用逗号分隔..."
|
||||||
|
className="textarea textarea-bordered h-24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 开关配置 */}
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">兼容模式</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.streamCompatibility}
|
||||||
|
onChange={(e) => setConfig({ ...config, streamCompatibility: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<span className="text-xs text-base-content/70 ml-2">
|
||||||
|
NCQQ不用开启,其他ICQQ、LLO需要开启
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 定时清理配置 */}
|
||||||
|
<div className="form-control w-full mt-6">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">自动清理时间</span>
|
||||||
|
<span className="label-text-alt text-xs">Cron表达式</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.autoclearTrashtime}
|
||||||
|
onChange={(e) => setConfig({ ...config, autoclearTrashtime: e.target.value })}
|
||||||
|
placeholder="请输入Cron表达式..."
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 保存按钮 */}
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost"
|
||||||
|
onClick={handleReset}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? <span className="loading loading-spinner"></span> : '保存配置'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
242
server/components/contents/ncm.jsx
Normal file
242
server/components/contents/ncm.jsx
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
||||||
|
|
||||||
|
export default function Ncm() {
|
||||||
|
const [config, setConfig] = useState({
|
||||||
|
useLocalNeteaseAPI: false,
|
||||||
|
useNeteaseSongRequest: false,
|
||||||
|
isSendVocal: true,
|
||||||
|
songRequestMaxList: 10,
|
||||||
|
neteaseCookie: '',
|
||||||
|
neteaseCloudAPIServer: '',
|
||||||
|
neteaseCloudAudioQuality: 'exhigh',
|
||||||
|
neteaseUserId: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// 读取配置
|
||||||
|
useEffect(() => {
|
||||||
|
const loadConfig = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
useLocalNeteaseAPI: yamlConfig.useLocalNeteaseAPI ?? false,
|
||||||
|
useNeteaseSongRequest: yamlConfig.useNeteaseSongRequest ?? false,
|
||||||
|
isSendVocal: yamlConfig.isSendVocal ?? true,
|
||||||
|
songRequestMaxList: yamlConfig.songRequestMaxList || 10,
|
||||||
|
neteaseCookie: yamlConfig.neteaseCookie || '',
|
||||||
|
neteaseCloudAPIServer: yamlConfig.neteaseCloudAPIServer || '',
|
||||||
|
neteaseCloudAudioQuality: yamlConfig.neteaseCloudAudioQuality || 'exhigh',
|
||||||
|
neteaseUserId: yamlConfig.neteaseUserId || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
const handleSave = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const success = await updateYamlConfig({
|
||||||
|
useLocalNeteaseAPI: config.useLocalNeteaseAPI,
|
||||||
|
useNeteaseSongRequest: config.useNeteaseSongRequest,
|
||||||
|
isSendVocal: config.isSendVocal,
|
||||||
|
songRequestMaxList: config.songRequestMaxList,
|
||||||
|
neteaseCookie: config.neteaseCookie,
|
||||||
|
neteaseCloudAPIServer: config.neteaseCloudAPIServer,
|
||||||
|
neteaseCloudAudioQuality: config.neteaseCloudAudioQuality,
|
||||||
|
neteaseUserId: config.neteaseUserId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
document.getElementById('ncm-toast-success').classList.remove('hidden');
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('ncm-toast-success').classList.add('hidden');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存配置失败:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置配置
|
||||||
|
const handleReset = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
useLocalNeteaseAPI: yamlConfig.useLocalNeteaseAPI ?? false,
|
||||||
|
useNeteaseSongRequest: yamlConfig.useNeteaseSongRequest ?? false,
|
||||||
|
isSendVocal: yamlConfig.isSendVocal ?? true,
|
||||||
|
songRequestMaxList: yamlConfig.songRequestMaxList || 10,
|
||||||
|
neteaseCookie: yamlConfig.neteaseCookie || '',
|
||||||
|
neteaseCloudAPIServer: yamlConfig.neteaseCloudAPIServer || '',
|
||||||
|
neteaseCloudAudioQuality: yamlConfig.neteaseCloudAudioQuality || 'exhigh',
|
||||||
|
neteaseUserId: yamlConfig.neteaseUserId || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const audioQualityOptions = [
|
||||||
|
{ value: 'standard', label: '标准' },
|
||||||
|
{ value: 'higher', label: '较高' },
|
||||||
|
{ value: 'exhigh', label: '极高' },
|
||||||
|
{ value: 'lossless', label: '无损' },
|
||||||
|
{ value: 'hires', label: 'Hi-Res' },
|
||||||
|
{ value: 'jyeffect', label: '高清环绕声' },
|
||||||
|
{ value: 'sky', label: '沉浸环绕声' },
|
||||||
|
{ value: 'dolby', label: '杜比全景声' },
|
||||||
|
{ value: 'jymaster', label: '超清母带' }
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6 mx-auto container">
|
||||||
|
{/* 成功提示 */}
|
||||||
|
<div id="ncm-toast-success" className="toast toast-top toast-end hidden">
|
||||||
|
<div className="alert alert-success">
|
||||||
|
<span>配置保存成功!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-5xl mx-auto">
|
||||||
|
<h2 className="text-2xl font-bold mb-6">网易云音乐配置</h2>
|
||||||
|
|
||||||
|
{/* 基础配置部分 */}
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-6">
|
||||||
|
<div className="card-body">
|
||||||
|
<h3 className="card-title mb-4">基础配置</h3>
|
||||||
|
|
||||||
|
{/* 文本输入配置 */}
|
||||||
|
<div className="space-y-4 mb-6">
|
||||||
|
<div className="form-control w-full">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">Cookie</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={config.neteaseCookie}
|
||||||
|
onChange={(e) => setConfig({ ...config, neteaseCookie: e.target.value })}
|
||||||
|
placeholder="请输入网易云Cookie..."
|
||||||
|
className="textarea textarea-bordered h-24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control w-full">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">自建API服务器地址</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.neteaseCloudAPIServer}
|
||||||
|
onChange={(e) => setConfig({ ...config, neteaseCloudAPIServer: e.target.value })}
|
||||||
|
placeholder="请输入API服务器地址..."
|
||||||
|
className="input input-bordered w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control w-full">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">用户ID</span>
|
||||||
|
<span className="label-text-alt text-xs text-warning">不要手动更改!</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.neteaseUserId}
|
||||||
|
onChange={(e) => setConfig({ ...config, neteaseUserId: e.target.value })}
|
||||||
|
placeholder="网易云用户ID"
|
||||||
|
className="input input-bordered w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 开关配置部分 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">使用自建API</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.useLocalNeteaseAPI}
|
||||||
|
onChange={(e) => setConfig({ ...config, useLocalNeteaseAPI: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">开启点歌功能</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.useNeteaseSongRequest}
|
||||||
|
onChange={(e) => setConfig({ ...config, useNeteaseSongRequest: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">发送群语音</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.isSendVocal}
|
||||||
|
onChange={(e) => setConfig({ ...config, isSendVocal: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 其他配置 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">点歌最大列表数</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.songRequestMaxList}
|
||||||
|
onChange={(e) => setConfig({ ...config, songRequestMaxList: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">音频质量</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="select select-bordered"
|
||||||
|
value={config.neteaseCloudAudioQuality}
|
||||||
|
onChange={(e) => setConfig({ ...config, neteaseCloudAudioQuality: e.target.value })}>
|
||||||
|
{audioQualityOptions.map(option => (
|
||||||
|
<option key={option.value} value={option.value}>
|
||||||
|
{option.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 保存按钮 */}
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost"
|
||||||
|
onClick={handleReset}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? <span className="loading loading-spinner"></span> : '保存配置'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -1,5 +1,151 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
||||||
|
|
||||||
export default function Tiktok() {
|
export default function Tiktok() {
|
||||||
|
const [config, setConfig] = useState({
|
||||||
|
douyinCookie: '',
|
||||||
|
douyinCompression: true,
|
||||||
|
douyinComments: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// 读取配置
|
||||||
|
useEffect(() => {
|
||||||
|
const loadConfig = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
douyinCookie: yamlConfig.douyinCookie || '',
|
||||||
|
douyinCompression: yamlConfig.douyinCompression ?? true,
|
||||||
|
douyinComments: yamlConfig.douyinComments ?? false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
const handleSave = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const success = await updateYamlConfig({
|
||||||
|
douyinCookie: config.douyinCookie,
|
||||||
|
douyinCompression: config.douyinCompression,
|
||||||
|
douyinComments: config.douyinComments
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
document.getElementById('tiktok-toast-success').classList.remove('hidden');
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('tiktok-toast-success').classList.add('hidden');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存配置失败:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置配置
|
||||||
|
const handleReset = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
douyinCookie: yamlConfig.douyinCookie || '',
|
||||||
|
douyinCompression: yamlConfig.douyinCompression ?? true,
|
||||||
|
douyinComments: yamlConfig.douyinComments ?? false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>Tiktok</div>
|
<div className="p-6 mx-auto container">
|
||||||
)
|
{/* 成功提示 */}
|
||||||
|
<div id="tiktok-toast-success" className="toast toast-top toast-end hidden">
|
||||||
|
<div className="alert alert-success">
|
||||||
|
<span>配置保存成功!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-5xl mx-auto">
|
||||||
|
<h2 className="text-2xl font-bold mb-6">抖音配置</h2>
|
||||||
|
|
||||||
|
{/* 基础配置部分 */}
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-6">
|
||||||
|
<div className="card-body">
|
||||||
|
<h3 className="card-title mb-4">基础配置</h3>
|
||||||
|
|
||||||
|
{/* Cookie配置 */}
|
||||||
|
<div className="form-control w-full mb-6">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">Cookie</span>
|
||||||
|
<span className="label-text-alt text-xs text-base-content/70">
|
||||||
|
格式:odin_tt=xxx;passport_fe_beating_status=xxx;...
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
value={config.douyinCookie}
|
||||||
|
onChange={(e) => setConfig({ ...config, douyinCookie: e.target.value })}
|
||||||
|
placeholder="请输入抖音Cookie..."
|
||||||
|
className="textarea textarea-bordered h-24"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 开关配置部分 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">视频压缩</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.douyinCompression}
|
||||||
|
onChange={(e) => setConfig({ ...config, douyinCompression: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<span className="text-xs text-base-content/70 ml-2">
|
||||||
|
开启后使用压缩格式,加速视频发送
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label cursor-pointer">
|
||||||
|
<span className="label-text">显示评论</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={config.douyinComments}
|
||||||
|
onChange={(e) => setConfig({ ...config, douyinComments: e.target.checked })}
|
||||||
|
className="toggle toggle-primary"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<span className="text-xs text-base-content/70 ml-2">
|
||||||
|
是否显示视频评论
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 保存按钮 */}
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost"
|
||||||
|
onClick={handleReset}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? <span className="loading loading-spinner"></span> : '保存配置'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
164
server/components/contents/youtube.jsx
Normal file
164
server/components/contents/youtube.jsx
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
|
||||||
|
|
||||||
|
export default function Youtube() {
|
||||||
|
const [config, setConfig] = useState({
|
||||||
|
youtubeGraphicsOptions: 720,
|
||||||
|
youtubeClipTime: 0,
|
||||||
|
youtubeDuration: 480,
|
||||||
|
youtubeCookiePath: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// 读取配置
|
||||||
|
useEffect(() => {
|
||||||
|
const loadConfig = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
youtubeGraphicsOptions: yamlConfig.youtubeGraphicsOptions || 720,
|
||||||
|
youtubeClipTime: yamlConfig.youtubeClipTime || 0,
|
||||||
|
youtubeDuration: yamlConfig.youtubeDuration || 480,
|
||||||
|
youtubeCookiePath: yamlConfig.youtubeCookiePath || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
loadConfig();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 保存配置
|
||||||
|
const handleSave = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const success = await updateYamlConfig({
|
||||||
|
youtubeGraphicsOptions: config.youtubeGraphicsOptions,
|
||||||
|
youtubeClipTime: config.youtubeClipTime,
|
||||||
|
youtubeDuration: config.youtubeDuration,
|
||||||
|
youtubeCookiePath: config.youtubeCookiePath
|
||||||
|
});
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
document.getElementById('youtube-toast-success').classList.remove('hidden');
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('youtube-toast-success').classList.add('hidden');
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存配置失败:', error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 重置配置
|
||||||
|
const handleReset = async () => {
|
||||||
|
const yamlConfig = await readYamlConfig();
|
||||||
|
if (yamlConfig) {
|
||||||
|
setConfig({
|
||||||
|
youtubeGraphicsOptions: yamlConfig.youtubeGraphicsOptions || 720,
|
||||||
|
youtubeClipTime: yamlConfig.youtubeClipTime || 0,
|
||||||
|
youtubeDuration: yamlConfig.youtubeDuration || 480,
|
||||||
|
youtubeCookiePath: yamlConfig.youtubeCookiePath || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="p-6 mx-auto container">
|
||||||
|
{/* 成功提示 */}
|
||||||
|
<div id="youtube-toast-success" className="toast toast-top toast-end hidden">
|
||||||
|
<div className="alert alert-success">
|
||||||
|
<span>配置保存成功!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="max-w-5xl mx-auto">
|
||||||
|
<h2 className="text-2xl font-bold mb-6">YouTube 配置</h2>
|
||||||
|
|
||||||
|
{/* 基础配置部分 */}
|
||||||
|
<div className="card bg-base-200 shadow-xl mb-6">
|
||||||
|
<div className="card-body">
|
||||||
|
<h3 className="card-title mb-4">基础配置</h3>
|
||||||
|
|
||||||
|
{/* Cookie路径配置 */}
|
||||||
|
<div className="form-control w-full mb-6">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">Cookie文件路径</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.youtubeCookiePath}
|
||||||
|
onChange={(e) => setConfig({ ...config, youtubeCookiePath: e.target.value })}
|
||||||
|
placeholder="请输入Cookie.txt文件路径..."
|
||||||
|
className="input input-bordered w-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 数值配置部分 */}
|
||||||
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">下载画质</span>
|
||||||
|
<span className="label-text-alt text-xs">0为原画</span>
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
className="select select-bordered"
|
||||||
|
value={config.youtubeGraphicsOptions}
|
||||||
|
onChange={(e) => setConfig({ ...config, youtubeGraphicsOptions: parseInt(e.target.value) })}>
|
||||||
|
<option value={0}>原画</option>
|
||||||
|
<option value={1080}>1080P</option>
|
||||||
|
<option value={720}>720P</option>
|
||||||
|
<option value={480}>480P</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">最大截取时长(秒)</span>
|
||||||
|
<span className="label-text-alt text-xs">建议不超过5分钟</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.youtubeClipTime}
|
||||||
|
onChange={(e) => setConfig({ ...config, youtubeClipTime: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-control">
|
||||||
|
<label className="label">
|
||||||
|
<span className="label-text">视频时长限制(秒)</span>
|
||||||
|
<span className="label-text-alt text-xs">建议不超过30分钟</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={config.youtubeDuration}
|
||||||
|
onChange={(e) => setConfig({ ...config, youtubeDuration: parseInt(e.target.value) })}
|
||||||
|
className="input input-bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 保存按钮 */}
|
||||||
|
<div className="flex justify-end gap-4">
|
||||||
|
<button
|
||||||
|
className="btn btn-ghost"
|
||||||
|
onClick={handleReset}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={handleSave}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? <span className="loading loading-spinner"></span> : '保存配置'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -2,55 +2,26 @@ export function BotConfig() {
|
|||||||
return (
|
return (
|
||||||
<div className="card bg-base-100 shadow-xl">
|
<div className="card bg-base-100 shadow-xl">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<h2 className="card-title text-lg font-bold">🔥热门快捷配置</h2>
|
<h2 className="card-title text-lg font-bold">🔥快捷更新</h2>
|
||||||
<div className="grid grid-cols-1 gap-2">
|
<div className="grid grid-cols-1 gap-2">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-bold">通用</h3>
|
<h3 className="font-bold">检查更新</h3>
|
||||||
<p>R 插件一些通用配置:魔法配置、线程配置等</p>
|
<p>当前最新版本为:v0.0.0</p>
|
||||||
</div>
|
|
||||||
<button onClick={()=>document.getElementById('my_modal_5').showModal()} className="btn">配置</button>
|
|
||||||
<dialog id="my_modal_5" className="modal ">
|
|
||||||
<div className="modal-box w-11/12 max-w-2xl">
|
|
||||||
<div className="mockup-browser bg-base-300 border">
|
|
||||||
<div className="mockup-browser-toolbar">
|
|
||||||
<div className="input">https://daisyui.com</div>
|
|
||||||
</div>
|
|
||||||
<div className="bg-base-200 flex justify-center px-4 pt-8">
|
|
||||||
<label className="input input-bordered flex items-center gap-2">
|
|
||||||
魔法地址
|
|
||||||
<input type="text" className="grow"
|
|
||||||
placeholder="例如:http://localhost"/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div className="bg-base-200 flex justify-center px-4 py-8">
|
|
||||||
<label className="input input-bordered flex items-center gap-2">
|
|
||||||
魔法端口
|
|
||||||
<input type="text" className="grow"
|
|
||||||
placeholder="例如:7890"/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="modal-action">
|
|
||||||
<form method="dialog">
|
|
||||||
{/* if there is a button in form, it will close the modal */ }
|
|
||||||
<button className="btn">Close</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</dialog>
|
|
||||||
</div>
|
|
||||||
<div className="flex justify-between items-center">
|
|
||||||
<div>
|
|
||||||
<h3 className="font-bold">哔哩哔哩</h3>
|
|
||||||
<p>哔哩哔哩相关配置</p>
|
|
||||||
</div>
|
</div>
|
||||||
<button className="btn btn-warning">🚧施工</button>
|
<button className="btn btn-warning">🚧施工</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-bold">抖音</h3>
|
<h3 className="font-bold">非强制更新</h3>
|
||||||
<p>抖音相关配置</p>
|
<p>R 插件的非强制更新,力度小</p>
|
||||||
|
</div>
|
||||||
|
<button className="btn btn-warning">🚧施工</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-bold">强制更新</h3>
|
||||||
|
<p>R 插件的强制更新,力度大</p>
|
||||||
</div>
|
</div>
|
||||||
<button className="btn btn-warning">🚧施工</button>
|
<button className="btn btn-warning">🚧施工</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,26 +2,39 @@ export const SIDEBAR_ITEMS = [
|
|||||||
{
|
{
|
||||||
name: "总控制台",
|
name: "总控制台",
|
||||||
icon: <svg t="1730947011086" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
icon: <svg t="1730947011086" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="8312" width="32" height="32">
|
xmlns="http://www.w3.org/2000/svg" p-id="8312" width="32" height="32">
|
||||||
<path
|
<path
|
||||||
d="M806.31 1004.13H217.69c-109.1 0-197.83-88.74-197.83-197.81V217.69c0-109.07 88.74-197.82 197.83-197.82h588.62c109.1 0 197.83 88.75 197.83 197.82v588.64c0 109.07-88.73 197.8-197.83 197.8zM217.69 97.57c-66.25 0-120.13 53.88-120.13 120.11v588.64c0 66.22 53.88 120.1 120.13 120.1h588.62c66.25 0 120.13-53.88 120.13-120.1V217.69c0-66.24-53.88-120.11-120.13-120.11H217.69v-0.01z"
|
d="M806.31 1004.13H217.69c-109.1 0-197.83-88.74-197.83-197.81V217.69c0-109.07 88.74-197.82 197.83-197.82h588.62c109.1 0 197.83 88.75 197.83 197.82v588.64c0 109.07-88.73 197.8-197.83 197.8zM217.69 97.57c-66.25 0-120.13 53.88-120.13 120.11v588.64c0 66.22 53.88 120.1 120.13 120.1h588.62c66.25 0 120.13-53.88 120.13-120.1V217.69c0-66.24-53.88-120.11-120.13-120.11H217.69v-0.01z"
|
||||||
fill="#333333" p-id="8313"></path>
|
fill="#333333" p-id="8313"></path>
|
||||||
<path d="M494.93 300.08h77.71v420.77h-77.71z" fill="#333333" p-id="8314"></path>
|
<path d="M494.93 300.08h77.71v420.77h-77.71z" fill="#333333" p-id="8314"></path>
|
||||||
<path d="M533.78 324.93m-81.76 0a81.76 81.76 0 1 0 163.52 0 81.76 81.76 0 1 0-163.52 0Z"
|
<path d="M533.78 324.93m-81.76 0a81.76 81.76 0 1 0 163.52 0 81.76 81.76 0 1 0-163.52 0Z"
|
||||||
fill="#C6C6C6" p-id="8315"></path>
|
fill="#C6C6C6" p-id="8315"></path>
|
||||||
<path d="M730.78 300.08h77.71v420.77h-77.71z" fill="#333333" p-id="8316"></path>
|
<path d="M730.78 300.08h77.71v420.77h-77.71z" fill="#333333" p-id="8316"></path>
|
||||||
<path d="M769.62 673.98m-81.76 0a81.76 81.76 0 1 0 163.52 0 81.76 81.76 0 1 0-163.52 0Z"
|
<path d="M769.62 673.98m-81.76 0a81.76 81.76 0 1 0 163.52 0 81.76 81.76 0 1 0-163.52 0Z"
|
||||||
fill="#C6C6C6" p-id="8317"></path>
|
fill="#C6C6C6" p-id="8317"></path>
|
||||||
<path d="M270.58 300.08h77.71v420.77h-77.71z" fill="#333333" p-id="8318"></path>
|
<path d="M270.58 300.08h77.71v420.77h-77.71z" fill="#333333" p-id="8318"></path>
|
||||||
<path d="M309.44 510.47m-81.76 0a81.76 81.76 0 1 0 163.52 0 81.76 81.76 0 1 0-163.52 0Z"
|
<path d="M309.44 510.47m-81.76 0a81.76 81.76 0 1 0 163.52 0 81.76 81.76 0 1 0-163.52 0Z"
|
||||||
fill="#C6C6C6" p-id="8319"></path>
|
fill="#C6C6C6" p-id="8319"></path>
|
||||||
</svg>,
|
</svg>,
|
||||||
theme: "light"
|
theme: "light"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "通用及杂项",
|
||||||
|
icon: <svg t="1732247159359" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" p-id="7981" width="32" height="32">
|
||||||
|
<path
|
||||||
|
d="M512.1 896.4c-102.6 0-199-39.9-271.5-112.5-72.5-72.5-112.5-169-112.5-271.5 0-102.6 39.9-199 112.5-271.5 72.5-72.5 169-112.5 271.5-112.5 102.6 0 199 39.9 271.5 112.5 72.5 72.5 112.5 169 112.5 271.5 0 102.6-39.9 199-112.5 271.5-72.5 72.5-168.9 112.5-271.5 112.5z"
|
||||||
|
fill="#FFFFFF" p-id="7982"></path>
|
||||||
|
<path
|
||||||
|
d="M512.1 192.4c43.3 0 85.2 8.4 124.5 25.1 38.1 16.1 72.3 39.2 101.8 68.6 29.4 29.4 52.5 63.7 68.6 101.8 16.7 39.4 25.1 81.3 25.1 124.5s-8.4 85.2-25.1 124.5c-16.1 38.1-39.2 72.3-68.6 101.8s-63.7 52.5-101.8 68.6c-39.4 16.7-81.3 25.1-124.5 25.1-43.3 0-85.2-8.4-124.5-25.1-38.1-16.1-72.3-39.2-101.8-68.6-29.4-29.4-52.5-63.7-68.6-101.8-16.7-39.4-25.1-81.3-25.1-124.5s8.4-85.2 25.1-124.5c16.1-38.1 39.2-72.3 68.6-101.8 29.4-29.4 63.7-52.5 101.8-68.6 39.4-16.7 81.3-25.1 124.5-25.1m0-128c-247.4 0-448 200.6-448 448s200.6 448 448 448 448-200.6 448-448c0-247.5-200.6-448-448-448z"
|
||||||
|
fill="#333333" p-id="7983"></path>
|
||||||
|
</svg>,
|
||||||
|
theme: "cupcake"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "哔哩哔哩控制台",
|
name: "哔哩哔哩控制台",
|
||||||
icon: <svg t="1730946721024" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
icon: <svg t="1730946721024" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="4282" width="32" height="32">
|
xmlns="http://www.w3.org/2000/svg" p-id="4282" width="32" height="32">
|
||||||
<path
|
<path
|
||||||
d="M729.32864 373.94944c-9.79456-5.94432-19.06176-6.784-19.14368-6.784l-1.06496-0.0512c-57.20064-3.8656-121.1648-5.83168-190.12608-5.83168l-13.98784 0.00512c-68.95616 0-132.92544 1.96096-190.12096 5.83168l-1.06496 0.0512c-0.08192 0-9.34912 0.83968-19.14368 6.784-15.04768 9.12896-24.27392 25.94816-27.4176 49.9712-10.07104 76.91264-4.38272 173.64992 0.18944 251.392 2.93888 49.96608 33.408 62.45888 85.04832 67.1488 10.78272 0.98816 69.08928 5.86752 159.50848 5.89312v-0.00512c90.4192-0.02048 148.72576-4.90496 159.5136-5.888 51.64032-4.68992 82.10944-17.18272 85.0432-67.1488 4.57728-77.74208 10.26048-174.47936 0.18944-251.392-3.1488-24.02816-12.37504-40.84736-27.42272-49.97632z m-390.9888 172.71808a23.64928 23.64928 0 0 1-31.68768-10.84416 23.68 23.68 0 0 1 10.84416-31.68768c2.03776-1.00352 50.69312-24.72448 110.5408-43.06432a23.68 23.68 0 1 1 13.88032 45.29152c-56.2944 17.24928-103.11168 40.07424-103.5776 40.30464z m268.89728 35.88608c-0.44032 2.23232-11.26912 54.64064-50.93888 54.64064-21.44256 0-36.10112-14.04928-44.98432-26.77248-8.69376 12.70784-22.80448 26.77248-42.65472 26.77248-35.5328 0-50.13504-48.26624-51.68128-53.77024a11.3664 11.3664 0 0 1 21.87776-6.1696c2.74944 9.6512 14.1312 37.20192 29.7984 37.20192 16.37376 0 28.89216-23.64416 31.98464-31.92832a11.37152 11.37152 0 0 1 10.6496-7.38816h0.06144c4.76672 0.03072 9.0112 3.02592 10.62912 7.50592 0.10752 0.28672 11.96544 31.81568 34.31424 31.81568 20.864 0 28.56448-35.95264 28.64128-36.32128a11.34592 11.34592 0 0 1 13.35808-8.93952 11.36128 11.36128 0 0 1 8.94464 13.35296z m110.11584-46.73536a23.68 23.68 0 0 1-31.68256 10.84416c-0.47104-0.2304-47.47264-23.1168-103.57248-40.30976a23.69024 23.69024 0 0 1-15.70816-29.58336 23.66976 23.66976 0 0 1 29.57824-15.70304c59.84768 18.33984 108.49792 42.0608 110.55104 43.06432a23.68 23.68 0 0 1 10.83392 31.68768z"
|
d="M729.32864 373.94944c-9.79456-5.94432-19.06176-6.784-19.14368-6.784l-1.06496-0.0512c-57.20064-3.8656-121.1648-5.83168-190.12608-5.83168l-13.98784 0.00512c-68.95616 0-132.92544 1.96096-190.12096 5.83168l-1.06496 0.0512c-0.08192 0-9.34912 0.83968-19.14368 6.784-15.04768 9.12896-24.27392 25.94816-27.4176 49.9712-10.07104 76.91264-4.38272 173.64992 0.18944 251.392 2.93888 49.96608 33.408 62.45888 85.04832 67.1488 10.78272 0.98816 69.08928 5.86752 159.50848 5.89312v-0.00512c90.4192-0.02048 148.72576-4.90496 159.5136-5.888 51.64032-4.68992 82.10944-17.18272 85.0432-67.1488 4.57728-77.74208 10.26048-174.47936 0.18944-251.392-3.1488-24.02816-12.37504-40.84736-27.42272-49.97632z m-390.9888 172.71808a23.64928 23.64928 0 0 1-31.68768-10.84416 23.68 23.68 0 0 1 10.84416-31.68768c2.03776-1.00352 50.69312-24.72448 110.5408-43.06432a23.68 23.68 0 1 1 13.88032 45.29152c-56.2944 17.24928-103.11168 40.07424-103.5776 40.30464z m268.89728 35.88608c-0.44032 2.23232-11.26912 54.64064-50.93888 54.64064-21.44256 0-36.10112-14.04928-44.98432-26.77248-8.69376 12.70784-22.80448 26.77248-42.65472 26.77248-35.5328 0-50.13504-48.26624-51.68128-53.77024a11.3664 11.3664 0 0 1 21.87776-6.1696c2.74944 9.6512 14.1312 37.20192 29.7984 37.20192 16.37376 0 28.89216-23.64416 31.98464-31.92832a11.37152 11.37152 0 0 1 10.6496-7.38816h0.06144c4.76672 0.03072 9.0112 3.02592 10.62912 7.50592 0.10752 0.28672 11.96544 31.81568 34.31424 31.81568 20.864 0 28.56448-35.95264 28.64128-36.32128a11.34592 11.34592 0 0 1 13.35808-8.93952 11.36128 11.36128 0 0 1 8.94464 13.35296z m110.11584-46.73536a23.68 23.68 0 0 1-31.68256 10.84416c-0.47104-0.2304-47.47264-23.1168-103.57248-40.30976a23.69024 23.69024 0 0 1-15.70816-29.58336 23.66976 23.66976 0 0 1 29.57824-15.70304c59.84768 18.33984 108.49792 42.0608 110.55104 43.06432a23.68 23.68 0 0 1 10.83392 31.68768z"
|
||||||
fill="#F16C8D" p-id="4283"></path>
|
fill="#F16C8D" p-id="4283"></path>
|
||||||
@ -32,32 +45,71 @@ export const SIDEBAR_ITEMS = [
|
|||||||
theme: "valentine"
|
theme: "valentine"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "抖音控制台", icon: <svg t="1730946961123" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
name: "抖音控制台",
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="5496" width="32" height="32">
|
icon: <svg t="1732246520808" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" p-id="6894" width="32" height="32">
|
||||||
<path
|
<path
|
||||||
d="M0 0m184.32 0l655.36 0q184.32 0 184.32 184.32l0 655.36q0 184.32-184.32 184.32l-655.36 0q-184.32 0-184.32-184.32l0-655.36q0-184.32 184.32-184.32Z"
|
d="M208.323765 0h607.35247C922.262588 0 1008.941176 89.088 1008.941176 198.595765V822.814118c0 109.507765-86.678588 198.595765-193.264941 198.595764H208.323765C101.737412 1021.379765 15.058824 932.291765 15.058824 822.784V198.595765C15.058824 89.088 101.737412 0 208.323765 0z"
|
||||||
fill="#111111" p-id="5497"></path>
|
fill="#170B1A" p-id="6895"></path>
|
||||||
<path
|
<path
|
||||||
d="M204.27776 670.59712a246.25152 246.25152 0 0 1 245.97504-245.97504v147.57888a98.49856 98.49856 0 0 0-98.38592 98.38592c0 48.34304 26.14272 100.352 83.54816 100.352 3.81952 0 93.55264-0.88064 93.55264-77.19936V134.35904h157.26592a133.31456 133.31456 0 0 0 133.12 132.99712l-0.13312 147.31264a273.152 273.152 0 0 1-142.62272-38.912l-0.06144 317.98272c0 146.00192-124.24192 224.77824-241.14176 224.77824-131.74784 0.03072-231.1168-106.56768-231.1168-247.92064z"
|
d="M503.356235 309.458824c0.572235-63.427765 0-126.855529 0.572236-190.283295h128.150588c-0.572235 11.203765 1.114353 22.437647 2.770823 33.129412h-94.32847v515.312941a124.295529 124.295529 0 0 1-15.510588 62.85553c-16.655059 29.214118-47.736471 49.392941-81.016471 52.224a107.580235 107.580235 0 0 1-61.590588-12.950588A106.134588 106.134588 0 0 1 346.352941 737.249882c32.737882 18.522353 75.444706 16.835765 107.068235-3.915294 30.509176-19.094588 50.507294-55.024941 50.507295-92.069647-0.572235-110.592-0.572235-221.184-0.572236-331.776z m211.395765-36.472471c17.769412 11.203765 37.707294 20.178824 58.247529 24.696471 12.197647 2.800941 24.395294 3.915294 37.165177 3.915294v29.214117a182.302118 182.302118 0 0 1-95.412706-57.825882z"
|
||||||
fill="#FF4040" p-id="5498"></path>
|
fill="#25F4EE" p-id="6896"></path>
|
||||||
<path
|
<path
|
||||||
d="M164.92544 631.23456a246.25152 246.25152 0 0 1 245.97504-245.97504v147.57888a98.49856 98.49856 0 0 0-98.38592 98.38592c0 48.34304 26.14272 100.352 83.54816 100.352 3.81952 0 93.55264-0.88064 93.55264-77.19936V94.99648h157.26592a133.31456 133.31456 0 0 0 133.12 132.99712l-0.13312 147.31264a273.152 273.152 0 0 1-142.62272-38.912l-0.06144 317.98272c0 146.00192-124.24192 224.77824-241.14176 224.77824-131.74784 0.03072-231.1168-106.56768-231.1168-247.92064z"
|
d="M275.576471 427.459765a223.111529 223.111529 0 0 1 153.6-33.520941v31.232a267.956706 267.956706 0 0 0-42.255059 5.12 236.664471 236.664471 0 0 0-94.328471 43.730823c-30.177882 23.280941-53.217882 55.115294-69.12 90.322824a250.277647 250.277647 0 0 0-22.497882 107.911529c0 40.899765 10.962824 80.655059 29.605647 116.434824 8.794353 16.474353 18.672941 32.376471 31.834353 45.447529-26.895059-19.335529-49.392941-45.477647-65.837177-74.992941-22.497882-39.183059-33.430588-85.202824-32.37647-131.192471A256.210824 256.210824 0 0 1 198.776471 508.084706a236.212706 236.212706 0 0 1 76.8-80.624941z"
|
||||||
fill="#00F5FF" p-id="5499"></path>
|
fill="#25F4EE" p-id="6897"></path>
|
||||||
<path
|
<path
|
||||||
d="M410.91072 427.58144c-158.8224 20.15232-284.44672 222.72-154.112 405.00224 120.40192 98.47808 373.68832 41.20576 380.70272-171.85792l-0.17408-324.1472a280.7296 280.7296 0 0 0 142.88896 38.62528V261.2224a144.98816 144.98816 0 0 1-72.8064-54.82496 135.23968 135.23968 0 0 1-54.70208-72.45824h-123.66848l-0.08192 561.41824c-0.11264 78.46912-130.9696 106.41408-164.18816 30.2592-83.18976-39.77216-64.37888-190.9248 46.31552-192.57344z"
|
d="M540.491294 153.208471h94.780235c3.312941 18.582588 9.999059 36.050824 18.31153 52.946823 13.312 25.901176 32.135529 49.031529 56.530823 64.240941a13.071059 13.071059 0 0 1 3.915294 3.915294 181.428706 181.428706 0 0 0 95.894589 58.066824c0.542118 33.792 0 68.156235 0 101.978353a297.020235 297.020235 0 0 1-176.308706-56.922353c0 81.136941 0 162.273882 0.542117 243.380706 0 10.721882 0.572235 21.413647 0 32.677647a269.312 269.312 0 0 1-34.334117 112.700235 243.802353 243.802353 0 0 1-66.56 76.619294 211.516235 211.516235 0 0 1-121.404235 42.255059c-22.166588 0.572235-44.363294-0.572235-65.957648-5.632a235.459765 235.459765 0 0 1-84.841411-37.737412l-1.656471-1.716706c-12.769882-12.950588-23.311059-28.732235-32.165647-45.056-18.853647-34.936471-29.936941-74.932706-29.936941-115.501176a246.061176 246.061176 0 0 1 22.738823-107.038118c16.052706-34.936471 39.905882-66.499765 69.872942-89.6a241.242353 241.242353 0 0 1 95.322353-43.369411c13.854118-2.831059 28.310588-4.517647 42.706823-5.059765 0.542118 12.950588 0 25.901176 0.542118 38.309647v65.897412c-16.082824-5.632-33.822118-5.632-50.447059-1.686589a124.084706 124.084706 0 0 0-54.332235 27.045648c-9.426824 8.432941-17.769412 18.582588-23.280942 29.876705-9.999059 19.154824-13.312 41.682824-11.083294 63.096471 2.198588 20.841412 11.083294 41.110588 24.395294 56.922353 8.854588 11.233882 20.48 19.696941 32.13553 27.587765 9.426824 13.522824 21.624471 24.786824 36.050823 32.677647a111.796706 111.796706 0 0 0 61.530353 12.950588c33.28-2.258824 64.301176-23.100235 80.956236-52.404706 10.541176-19.154824 16.082824-41.110588 15.510588-63.096471 1.114353-173.537882 0.572235-345.931294 0.572235-518.324705z"
|
||||||
fill="#FFFFFF" p-id="5500"></path>
|
fill="#FFFFFF" p-id="6898"></path>
|
||||||
|
<path
|
||||||
|
d="M650.119529 136.192c10.992941 0.542118 21.985882 0 33.490824 0a189.138824 189.138824 0 0 0 32.948706 106.616471c2.740706 3.975529 5.481412 7.348706 8.252235 10.752-24.154353-15.239529-43.369412-38.369882-56.018823-64.331295a216.335059 216.335059 0 0 1-18.672942-53.037176z m172.965647 179.440941c12.047059 2.800941 24.154353 3.915294 36.773648 3.915294v131.493647c-62.584471 0.602353-125.168941-20.871529-176.248471-58.669176v260.698353a233.833412 233.833412 0 0 1-5.481412 58.669176c-12.047059 58.699294-46.110118 111.736471-93.334588 146.160941a225.520941 225.520941 0 0 1-83.425882 38.369883 225.942588 225.942588 0 0 1-109.808942-1.686588A230.309647 230.309647 0 0 1 280.094118 825.735529a222.780235 222.780235 0 0 0 84.028235 37.797647c21.383529 5.089882 43.369412 6.204235 65.295059 5.662118a207.932235 207.932235 0 0 0 120.259764-42.345412c26.895059-20.299294 48.850824-46.832941 65.867295-76.739764a271.962353 271.962353 0 0 0 34.032941-112.850824c0.542118-10.721882 0.542118-21.443765 0-32.737882-0.542118-81.227294-0.542118-162.484706-0.542118-243.742118a291.900235 291.900235 0 0 0 174.592 56.982588c-0.542118-33.852235 0-68.276706-0.542118-102.128941z"
|
||||||
|
fill="#FE2C55" p-id="6899"></path>
|
||||||
|
<path
|
||||||
|
d="M440.380235 425.562353c12.649412 0 25.840941 0.602353 38.490353 2.258823v134.866824a106.706824 106.706824 0 0 0-58.006588-2.258824 110.983529 110.983529 0 0 0-79.299765 69.421177c-12.649412 33.852235-7.469176 73.366588 14.366118 102.128941a120.229647 120.229647 0 0 1-33.310118-27.648 105.502118 105.502118 0 0 1-25.298823-56.982588c-2.288941-21.443765 1.174588-44.032 11.504941-63.216941 5.722353-11.264 14.366118-21.443765 24.124235-29.906824 16.082824-13.552941 36.201412-21.985882 56.32-27.075765 17.227294-3.945412 35.599059-3.945412 52.254118 1.686589v-66.017883c-1.144471-11.294118-0.572235-24.274824-1.144471-37.255529z"
|
||||||
|
fill="#FE2C55" p-id="6900"></path>
|
||||||
</svg>,
|
</svg>,
|
||||||
theme: "dark"
|
theme: "dark"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "油管控制台",
|
||||||
|
icon: <svg t="1732245926879" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" p-id="4280" width="32" height="32">
|
||||||
|
<path
|
||||||
|
d="M985.742 749.896c0 130.902-106.178 237.004-237.17 237.004H274.298c-130.954 0-237.092-106.102-237.092-237.004V276.018c0-130.902 106.138-236.966 237.092-236.966h474.274c130.992 0 237.17 106.064 237.17 236.966v473.878z"
|
||||||
|
fill="#FF312E" p-id="4281"></path>
|
||||||
|
<path
|
||||||
|
d="M801.952 389.486s-5.792-42.618-23.544-61.324c-22.54-24.568-47.82-24.76-59.358-26.148-83.02-6.248-207.416-6.248-207.416-6.248h-0.27s-124.47 0-207.422 6.248c-11.58 1.388-36.822 1.582-59.4 26.148-17.752 18.706-23.544 61.324-23.544 61.324s-5.944 49.984-5.944 99.97v46.812c0 50.06 5.944 100.044 5.944 100.044s5.792 42.542 23.544 61.286c22.578 24.608 52.22 23.796 65.382 26.382 47.434 4.744 201.556 6.208 201.556 6.208s124.55-0.23 207.57-6.44c11.538-1.428 36.818-1.542 59.358-26.15 17.754-18.744 23.544-61.286 23.544-61.286s5.944-49.984 5.944-100.044v-46.812c-0.002-49.986-5.944-99.97-5.944-99.97zM450.304 593.118l-0.04-173.546 160.172 87.088-160.132 86.458z"
|
||||||
|
fill="#FFFFFF" p-id="4282"></path>
|
||||||
|
<path
|
||||||
|
d="M511.632 295.766s124.396 0 207.416 6.248c11.538 1.388 36.818 1.582 59.358 26.148 17.754 18.706 23.544 61.324 23.544 61.324s5.944 49.984 5.944 99.97v46.812c0 50.06-5.944 100.044-5.944 100.044s-5.792 42.542-23.544 61.286c-22.54 24.608-47.82 24.722-59.358 26.15-83.02 6.208-207.57 6.44-207.57 6.44s-154.124-1.462-201.556-6.208c-13.162-2.586-42.804-1.776-65.382-26.382-17.752-18.744-23.544-61.286-23.544-61.286s-5.944-49.984-5.944-100.044v-46.812c0-49.986 5.944-99.97 5.944-99.97s5.792-42.618 23.544-61.324c22.578-24.568 47.82-24.76 59.4-26.148 82.952-6.248 207.422-6.248 207.422-6.248h0.27m-61.328 297.352l160.132-86.458-160.172-87.088 0.04 173.546m61.328-317.106h-0.27c-1.252 0-126.17 0.072-208.906 6.304-0.29 0.022-0.58 0.05-0.868 0.084-0.964 0.116-2.038 0.22-3.204 0.336-13.884 1.376-42.758 4.244-68.292 31.954-21.424 22.712-27.992 67.136-28.67 72.136l-0.042 0.328c-0.248 2.088-6.082 51.728-6.082 102.302v46.812c0 50.648 5.834 100.29 6.082 102.376l0.042 0.332c0.68 4.992 7.248 49.342 28.662 72.084 23.586 25.626 53.29 29.344 69.256 31.342 2.666 0.334 5.184 0.65 6.774 0.96 0.61 0.122 1.224 0.21 1.842 0.274 47.772 4.778 197.006 6.244 203.334 6.304h0.224c1.252-0.002 126.226-0.302 209.006-6.494 0.318-0.024 0.636-0.054 0.954-0.096 1-0.124 2.118-0.232 3.336-0.356 13.858-1.396 42.668-4.298 68.058-31.942 21.41-22.746 27.976-67.088 28.656-72.078 0.014-0.11 0.03-0.22 0.042-0.332 0.248-2.088 6.082-51.728 6.082-102.376v-46.812c0-50.574-5.834-100.214-6.082-102.302a9.188 9.188 0 0 0-0.042-0.328c-0.68-5-7.246-49.42-28.67-72.134-25.49-27.704-54.36-30.574-68.244-31.954-1.168-0.116-2.24-0.222-3.204-0.336a18.54 18.54 0 0 0-0.876-0.086c-82.802-6.23-207.646-6.302-208.898-6.302z m-41.582 283.994l-0.024-107.206 98.944 53.798-98.92 53.408z"
|
||||||
|
fill="#801917" p-id="4283"></path>
|
||||||
|
<path
|
||||||
|
d="M728.078 956.122H294.83c-124.896 0-226.506-101.636-226.506-226.566V296.358c0-124.908 101.61-226.526 226.506-226.526h433.248c124.918 0 226.544 101.62 226.544 226.526v433.198c0.002 124.928-101.626 226.566-226.544 226.566zM294.83 89.636c-113.976 0-206.702 92.734-206.702 206.72v433.198c0 114.008 92.726 206.762 206.702 206.762h433.248c113.996 0 206.74-92.754 206.74-206.762V296.358c0-113.986-92.744-206.72-206.74-206.72H294.83z"
|
||||||
|
fill="#801917" p-id="4284"></path>
|
||||||
|
</svg>,
|
||||||
|
theme: "dracula"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "网易云控制台",
|
||||||
|
icon: <svg t="1732246497646" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" p-id="5759" width="32" height="32">
|
||||||
|
<path
|
||||||
|
d="M0 0m184.32 0l655.36 0q184.32 0 184.32 184.32l0 655.36q0 184.32-184.32 184.32l-655.36 0q-184.32 0-184.32-184.32l0-655.36q0-184.32 184.32-184.32Z"
|
||||||
|
fill="#EA3E3C" p-id="5760"></path>
|
||||||
|
<path
|
||||||
|
d="M527.616 849.43872a373.6064 373.6064 0 0 1-162.54976-39.00416c-112.36352-55.16288-180.00896-176.29184-172.55424-308.67456 7.41376-130.34496 85.10464-237.4656 202.752-279.552a35.85024 35.85024 0 0 1 24.15616 67.51232c-107.66336 38.49216-150.81472 136.86784-155.29984 216.13568-5.86752 103.51616 46.08 197.79584 132.34176 240.13824 124.69248 60.30336 216.91392 22.35392 260.82304-5.64224 59.8016-38.16448 97.86368-100.01408 96.95232-157.55264-1.024-63.72352-24.064-120.99584-63.27296-157.14304a145.408 145.408 0 0 0-65.5872-35.28704q2.82624 9.76896 5.64224 19.32288c13.38368 45.63968 24.94464 85.05344 25.6 114.40128a134.26688 134.26688 0 0 1-37.69344 97.76128 139.1104 139.1104 0 0 1-100.6592 40.45824 140.10368 140.10368 0 0 1-100.47488-42.24 169.12384 169.12384 0 0 1-46.2848-122.76736c1.19808-85.12512 80.11776-153.28256 162.816-175.104a324.80256 324.80256 0 0 1-6.71744-67.05152 92.0576 92.0576 0 0 1 69.18144-91.81184c46.21312-12.53376 104.448 5.19168 124.66176 37.888a35.84 35.84 0 0 1-11.70432 49.31584 35.84 35.84 0 0 1-49.26464-11.65312 62.34112 62.34112 0 0 0-48.45568-5.21216c-4.32128 1.71008-12.35968 4.90496-12.76928 23.10144a270.87872 270.87872 0 0 0 6.73792 58.51136 217.4976 217.4976 0 0 1 133.56032 57.6512c53.57568 49.38752 85.0432 125.46048 86.35392 208.71168 1.29024 81.85856-49.7664 167.86432-130.048 219.136a310.14912 310.14912 0 0 1-168.2432 48.65024z m23.6544-457.55392c-56.77056 15.6672-107.4688 63.03744-108.07296 106.42432a98.304 98.304 0 0 0 25.6512 71.43424 68.0448 68.0448 0 0 0 49.36704 20.87936 67.24608 67.24608 0 0 0 49.44896-18.944 63.19104 63.19104 0 0 0 17.23392-46.08c-0.4096-19.79392-11.7248-58.368-22.67136-95.6928-3.61472-12.42112-7.35232-25.14944-10.9568-38.02112z"
|
||||||
|
fill="#FFFFFF" p-id="5761"></path>
|
||||||
|
</svg>,
|
||||||
|
theme: "lofi"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "周刊预览",
|
name: "周刊预览",
|
||||||
icon: <svg t="1730970789425" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
icon: <svg t="1730970789425" className="icon" viewBox="0 0 1024 1024" version="1.1"
|
||||||
xmlns="http://www.w3.org/2000/svg" p-id="4284" width="32" height="32">
|
xmlns="http://www.w3.org/2000/svg" p-id="4284" width="32" height="32">
|
||||||
<path
|
<path
|
||||||
d="M1024 157.866667v712.533333a80.64 80.64 0 0 0-7.68 14.08c-21.333333 68.693333-66.986667 113.066667-135.68 133.12a116.48 116.48 0 0 0-14.506667 6.4H153.6a58.88 58.88 0 0 0-11.946667-6.826667q-103.68-31.146667-134.4-134.4a58.88 58.88 0 0 0-6.826666-11.946666v-716.8a58.88 58.88 0 0 0 6.826666-11.946667Q38.4 38.4 141.653333 7.68A58.88 58.88 0 0 0 153.6 0.853333h712.533333a62.293333 62.293333 0 0 0 10.24 5.12q111.36 31.146667 142.506667 142.506667A62.293333 62.293333 0 0 0 1024 157.866667zM573.013333 720.213333c13.653333 1.706667 26.026667 4.266667 38.826667 5.12a320 320 0 0 0 44.8 0.426667c32-2.56 47.786667-19.2 47.786667-51.2 0.426667-113.92 0-227.413333 0.426666-341.333333 0-16.64-5.546667-22.613333-22.613333-22.186667q-165.12 0.853333-330.666667 0c-17.92 0-23.466667 6.826667-23.466666 23.893333 0.426667 66.986667 2.133333 133.546667-0.426667 200.533334-1.28 40.96-8.533333 81.493333-14.933333 122.453333-2.986667 18.773333-9.813333 36.693333-15.36 57.173333l40.106666 11.093334c19.2-51.2 30.293333-101.973333 29.866667-155.306667q-0.426667-100.266667 0-200.533333c0-8.533333-2.986667-20.053333 11.946667-20.053334h111.786666v33.28h-102.4v36.266667H490.666667v37.546667H389.12v34.133333h256V456.533333h-112.213333v-37.12h112.213333v-36.693333H533.333333v-32.426667c38.4 0 75.52 0.853333 112.213334-0.426666 16.213333-0.426667 20.48 4.693333 20.48 20.48-0.853333 95.146667-0.426667 190.72-0.426667 285.866666 0 25.173333-6.4 32-32 29.866667s-40.106667-6.4-60.16-9.813333z m-175.36-65.706666h237.653334v-133.12H397.226667z"
|
d="M1024 157.866667v712.533333a80.64 80.64 0 0 0-7.68 14.08c-21.333333 68.693333-66.986667 113.066667-135.68 133.12a116.48 116.48 0 0 0-14.506667 6.4H153.6a58.88 58.88 0 0 0-11.946667-6.826667q-103.68-31.146667-134.4-134.4a58.88 58.88 0 0 0-6.826666-11.946666v-716.8a58.88 58.88 0 0 0 6.826666-11.946667Q38.4 38.4 141.653333 7.68A58.88 58.88 0 0 0 153.6 0.853333h712.533333a62.293333 62.293333 0 0 0 10.24 5.12q111.36 31.146667 142.506667 142.506667A62.293333 62.293333 0 0 0 1024 157.866667zM573.013333 720.213333c13.653333 1.706667 26.026667 4.266667 38.826667 5.12a320 320 0 0 0 44.8 0.426667c32-2.56 47.786667-19.2 47.786667-51.2 0.426667-113.92 0-227.413333 0.426666-341.333333 0-16.64-5.546667-22.613333-22.613333-22.186667q-165.12 0.853333-330.666667 0c-17.92 0-23.466667 6.826667-23.466666 23.893333 0.426667 66.986667 2.133333 133.546667-0.426667 200.533334-1.28 40.96-8.533333 81.493333-14.933333 122.453333-2.986667 18.773333-9.813333 36.693333-15.36 57.173333l40.106666 11.093334c19.2-51.2 30.293333-101.973333 29.866667-155.306667q-0.426667-100.266667 0-200.533333c0-8.533333-2.986667-20.053333 11.946667-20.053334h111.786666v33.28h-102.4v36.266667H490.666667v37.546667H389.12v34.133333h256V456.533333h-112.213333v-37.12h112.213333v-36.693333H533.333333v-32.426667c38.4 0 75.52 0.853333 112.213334-0.426666 16.213333-0.426667 20.48 4.693333 20.48 20.48-0.853333 95.146667-0.426667 190.72-0.426667 285.866666 0 25.173333-6.4 32-32 29.866667s-40.106667-6.4-60.16-9.813333z m-175.36-65.706666h237.653334v-133.12H397.226667z"
|
||||||
fill="#19B883" p-id="4285"></path>
|
fill="#19B883" p-id="4285"></path>
|
||||||
<path d="M598.186667 557.653333v60.16h-162.56v-60.16z" fill="#22BB88" p-id="4286"></path>
|
<path d="M598.186667 557.653333v60.16h-162.56v-60.16z" fill="#22BB88" p-id="4286"></path>
|
||||||
</svg>,
|
</svg>,
|
||||||
theme: "dim"
|
theme: "retro"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
@ -16,7 +16,7 @@ const config = {
|
|||||||
daisyui,
|
daisyui,
|
||||||
],
|
],
|
||||||
daisyui: {
|
daisyui: {
|
||||||
themes: ["light", "dark", "valentine"],
|
themes: ["light", "dark", "valentine", "retro", "lofi", "dracula", "aqua", "cupcake"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
29
server/utils/yamlHelper.js
Normal file
29
server/utils/yamlHelper.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export const readYamlConfig = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/r/api/config');
|
||||||
|
if (!response.ok) throw new Error('获取配置失败');
|
||||||
|
return await response.json();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('读取配置文件失败:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateYamlConfig = async (updates) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/r/api/config', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(updates)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('更新配置失败');
|
||||||
|
const result = await response.json();
|
||||||
|
return result.success;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('更新配置文件失败:', error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user