🪛 chore: 封装 Toast

This commit is contained in:
zhiyu1998 2024-11-22 23:14:59 +08:00
parent 971e001c6a
commit 8a6b9339e7
6 changed files with 85 additions and 61 deletions

View File

@ -1,6 +1,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD, BILI_RESOLUTION_LIST } from "../../../constants/constant.js"; import { BILI_CDN_SELECT_LIST, BILI_DOWNLOAD_METHOD, BILI_RESOLUTION_LIST } from "../../../constants/constant.js";
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper'; import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
import Toast from "../toast.jsx";
export default function Bili() { export default function Bili() {
const [config, setConfig] = useState({ const [config, setConfig] = useState({
@ -102,11 +103,7 @@ export default function Bili() {
return ( return (
<div className="p-6 mx-auto container"> <div className="p-6 mx-auto container">
{/* 成功提示 */} {/* 成功提示 */}
<div id="toast-success" className="toast toast-top toast-end hidden z-[9999]"> <Toast id="toast-success" />
<div className="alert alert-success">
<span>配置保存成功</span>
</div>
</div>
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
<h2 className="text-2xl font-bold mb-6">Bilibili 配置</h2> <h2 className="text-2xl font-bold mb-6">Bilibili 配置</h2>

View File

@ -1,5 +1,6 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper'; import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
import Toast from "../toast.jsx";
export default function Generic() { export default function Generic() {
const [config, setConfig] = useState({ const [config, setConfig] = useState({
@ -13,6 +14,7 @@ export default function Generic() {
queueConcurrency: 1, queueConcurrency: 1,
videoDownloadConcurrency: 1, videoDownloadConcurrency: 1,
autoclearTrashtime: '0 0 8 * * ?', autoclearTrashtime: '0 0 8 * * ?',
xiaohongshuCookie: '',
deeplApiUrls: '' deeplApiUrls: ''
}); });
@ -34,6 +36,7 @@ export default function Generic() {
queueConcurrency: yamlConfig.queueConcurrency || 1, queueConcurrency: yamlConfig.queueConcurrency || 1,
videoDownloadConcurrency: yamlConfig.videoDownloadConcurrency || 1, videoDownloadConcurrency: yamlConfig.videoDownloadConcurrency || 1,
autoclearTrashtime: yamlConfig.autoclearTrashtime || '0 0 8 * * ?', autoclearTrashtime: yamlConfig.autoclearTrashtime || '0 0 8 * * ?',
xiaohongshuCookie: yamlConfig.xiaohongshuCookie || '',
deeplApiUrls: yamlConfig.deeplApiUrls || '' deeplApiUrls: yamlConfig.deeplApiUrls || ''
}); });
} }
@ -57,6 +60,7 @@ export default function Generic() {
queueConcurrency: config.queueConcurrency, queueConcurrency: config.queueConcurrency,
videoDownloadConcurrency: config.videoDownloadConcurrency, videoDownloadConcurrency: config.videoDownloadConcurrency,
autoclearTrashtime: config.autoclearTrashtime, autoclearTrashtime: config.autoclearTrashtime,
xiaohongshuCookie: config.xiaohongshuCookie,
deeplApiUrls: config.deeplApiUrls deeplApiUrls: config.deeplApiUrls
}); });
@ -88,7 +92,8 @@ export default function Generic() {
queueConcurrency: yamlConfig.queueConcurrency || 1, queueConcurrency: yamlConfig.queueConcurrency || 1,
videoDownloadConcurrency: yamlConfig.videoDownloadConcurrency || 1, videoDownloadConcurrency: yamlConfig.videoDownloadConcurrency || 1,
autoclearTrashtime: yamlConfig.autoclearTrashtime || '0 0 8 * * ?', autoclearTrashtime: yamlConfig.autoclearTrashtime || '0 0 8 * * ?',
deeplApiUrls: yamlConfig.deeplApiUrls || '' xiaohongshuCookie: yamlConfig.xiaohongshuCookie || '',
deeplApiUrls: yamlConfig.deeplApiUrls || '',
}); });
} }
}; };
@ -96,11 +101,7 @@ export default function Generic() {
return ( return (
<div className="p-6 mx-auto container"> <div className="p-6 mx-auto container">
{/* 成功提示 */} {/* 成功提示 */}
<div id="generic-toast-success" className="toast toast-top toast-end hidden z-[9999]"> <Toast id="generic-toast-success" />
<div className="alert alert-success">
<span>配置保存成功</span>
</div>
</div>
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
<h2 className="text-2xl font-bold mb-6">通用配置</h2> <h2 className="text-2xl font-bold mb-6">通用配置</h2>
@ -110,7 +111,7 @@ export default function Generic() {
<div className="card-body"> <div className="card-body">
<h3 className="card-title mb-4">基础配置</h3> <h3 className="card-title mb-4">基础配置</h3>
{/* 路径和大小限制配置 */} {/* 路径和大小限制配置 */ }
<div className="grid md:grid-cols-2 gap-4 mb-6"> <div className="grid md:grid-cols-2 gap-4 mb-6">
<div className="form-control"> <div className="form-control">
<label className="label"> <label className="label">
@ -118,8 +119,8 @@ export default function Generic() {
</label> </label>
<input <input
type="text" type="text"
value={config.defaultPath} value={ config.defaultPath }
onChange={(e) => setConfig({ ...config, defaultPath: e.target.value })} onChange={ (e) => setConfig({ ...config, defaultPath: e.target.value }) }
placeholder="请输入视频保存路径..." placeholder="请输入视频保存路径..."
className="input input-bordered" className="input input-bordered"
/> />
@ -131,14 +132,17 @@ export default function Generic() {
</label> </label>
<input <input
type="number" type="number"
value={config.videoSizeLimit} value={ config.videoSizeLimit }
onChange={(e) => setConfig({ ...config, videoSizeLimit: parseInt(e.target.value) })} onChange={ (e) => setConfig({
...config,
videoSizeLimit: parseInt(e.target.value)
}) }
className="input input-bordered" className="input input-bordered"
/> />
</div> </div>
</div> </div>
{/* 代理配置 */} {/* 代理配置 */ }
<div className="grid md:grid-cols-2 gap-4 mb-6"> <div className="grid md:grid-cols-2 gap-4 mb-6">
<div className="form-control"> <div className="form-control">
<label className="label"> <label className="label">
@ -146,8 +150,8 @@ export default function Generic() {
</label> </label>
<input <input
type="text" type="text"
value={config.proxyAddr} value={ config.proxyAddr }
onChange={(e) => setConfig({ ...config, proxyAddr: e.target.value })} onChange={ (e) => setConfig({ ...config, proxyAddr: e.target.value }) }
placeholder="请输入代理地址..." placeholder="请输入代理地址..."
className="input input-bordered" className="input input-bordered"
/> />
@ -158,15 +162,15 @@ export default function Generic() {
</label> </label>
<input <input
type="text" type="text"
value={config.proxyPort} value={ config.proxyPort }
onChange={(e) => setConfig({ ...config, proxyPort: e.target.value })} onChange={ (e) => setConfig({ ...config, proxyPort: e.target.value }) }
placeholder="请输入代理端口..." placeholder="请输入代理端口..."
className="input input-bordered" className="input input-bordered"
/> />
</div> </div>
</div> </div>
{/* 其他基础配置 */} {/* 其他基础配置 */ }
<div className="grid md:grid-cols-2 gap-4 mb-6"> <div className="grid md:grid-cols-2 gap-4 mb-6">
<div className="form-control"> <div className="form-control">
<label className="label"> <label className="label">
@ -174,8 +178,8 @@ export default function Generic() {
</label> </label>
<input <input
type="text" type="text"
value={config.identifyPrefix} value={ config.identifyPrefix }
onChange={(e) => setConfig({ ...config, identifyPrefix: e.target.value })} onChange={ (e) => setConfig({ ...config, identifyPrefix: e.target.value }) }
placeholder="请输入识别前缀..." placeholder="请输入识别前缀..."
className="input input-bordered" className="input input-bordered"
/> />
@ -186,14 +190,17 @@ export default function Generic() {
</label> </label>
<input <input
type="number" type="number"
value={config.streamDuration} value={ config.streamDuration }
onChange={(e) => setConfig({ ...config, streamDuration: parseInt(e.target.value) })} onChange={ (e) => setConfig({
...config,
streamDuration: parseInt(e.target.value)
}) }
className="input input-bordered" className="input input-bordered"
/> />
</div> </div>
</div> </div>
{/* 并发和定时配置 */} {/* 并发和定时配置 */ }
<div className="grid md:grid-cols-2 gap-4 mb-6"> <div className="grid md:grid-cols-2 gap-4 mb-6">
<div className="form-control"> <div className="form-control">
<label className="label"> <label className="label">
@ -202,8 +209,11 @@ export default function Generic() {
</label> </label>
<input <input
type="number" type="number"
value={config.queueConcurrency} value={ config.queueConcurrency }
onChange={(e) => setConfig({ ...config, queueConcurrency: parseInt(e.target.value) })} onChange={ (e) => setConfig({
...config,
queueConcurrency: parseInt(e.target.value)
}) }
className="input input-bordered" className="input input-bordered"
/> />
</div> </div>
@ -213,34 +223,37 @@ export default function Generic() {
</label> </label>
<input <input
type="number" type="number"
value={config.videoDownloadConcurrency} value={ config.videoDownloadConcurrency }
onChange={(e) => setConfig({ ...config, videoDownloadConcurrency: parseInt(e.target.value) })} onChange={ (e) => setConfig({
...config,
videoDownloadConcurrency: parseInt(e.target.value)
}) }
className="input input-bordered" className="input input-bordered"
/> />
</div> </div>
</div> </div>
{/* DeepL API配置 */} {/* DeepL API配置 */ }
<div className="form-control w-full mb-6"> <div className="form-control w-full mb-6">
<label className="label"> <label className="label">
<span className="label-text">DeepL API地址</span> <span className="label-text">DeepL API地址</span>
</label> </label>
<textarea <textarea
value={config.deeplApiUrls} value={ config.deeplApiUrls }
onChange={(e) => setConfig({ ...config, deeplApiUrls: e.target.value })} onChange={ (e) => setConfig({ ...config, deeplApiUrls: e.target.value }) }
placeholder="请输入DeepL API地址多个地址用逗号分隔..." placeholder="请输入DeepL API地址多个地址用逗号分隔..."
className="textarea textarea-bordered h-24" className="textarea textarea-bordered h-24"
/> />
</div> </div>
{/* 开关配置 */} {/* 开关配置 */ }
<div className="form-control"> <div className="form-control">
<label className="label cursor-pointer"> <label className="label cursor-pointer">
<span className="label-text">兼容模式</span> <span className="label-text">兼容模式</span>
<input <input
type="checkbox" type="checkbox"
checked={config.streamCompatibility} checked={ config.streamCompatibility }
onChange={(e) => setConfig({ ...config, streamCompatibility: e.target.checked })} onChange={ (e) => setConfig({ ...config, streamCompatibility: e.target.checked }) }
className="toggle toggle-primary" className="toggle toggle-primary"
/> />
</label> </label>
@ -249,7 +262,21 @@ export default function Generic() {
</span> </span>
</div> </div>
{/* 定时清理配置 */} {/* 小红书 Cookie */ }
<div className="form-control w-full mt-6">
<label className="label">
<span className="label-text">小红书Cookie</span>
</label>
<input
type="text"
value={ config.xiaohongshuCookie }
onChange={ (e) => setConfig({ ...config, xiaohongshuCookie: e.target.value }) }
placeholder="请输入小红书的Cookie..."
className="input input-bordered"
/>
</div>
{/* 定时清理配置 */ }
<div className="form-control w-full mt-6"> <div className="form-control w-full mt-6">
<label className="label"> <label className="label">
<span className="label-text">自动清理时间</span> <span className="label-text">自动清理时间</span>
@ -257,8 +284,8 @@ export default function Generic() {
</label> </label>
<input <input
type="text" type="text"
value={config.autoclearTrashtime} value={ config.autoclearTrashtime }
onChange={(e) => setConfig({ ...config, autoclearTrashtime: e.target.value })} onChange={ (e) => setConfig({ ...config, autoclearTrashtime: e.target.value }) }
placeholder="请输入Cron表达式..." placeholder="请输入Cron表达式..."
className="input input-bordered" className="input input-bordered"
/> />
@ -266,21 +293,21 @@ export default function Generic() {
</div> </div>
</div> </div>
{/* 保存按钮 */} {/* 保存按钮 */ }
<div className="flex justify-end gap-4"> <div className="flex justify-end gap-4">
<button <button
className="btn btn-ghost" className="btn btn-ghost"
onClick={handleReset} onClick={ handleReset }
disabled={loading} disabled={ loading }
> >
重置 重置
</button> </button>
<button <button
className="btn btn-primary" className="btn btn-primary"
onClick={handleSave} onClick={ handleSave }
disabled={loading} disabled={ loading }
> >
{loading ? <span className="loading loading-spinner"></span> : '保存配置'} { loading ? <span className="loading loading-spinner"></span> : '保存配置' }
</button> </button>
</div> </div>
</div> </div>

View File

@ -1,6 +1,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { NETEASECLOUD_QUALITY_LIST } from "../../../constants/constant.js"; import { NETEASECLOUD_QUALITY_LIST } from "../../../constants/constant.js";
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper'; import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
import Toast from "../toast.jsx";
export default function Ncm() { export default function Ncm() {
const [config, setConfig] = useState({ const [config, setConfig] = useState({
@ -85,11 +86,7 @@ export default function Ncm() {
return ( return (
<div className="p-6 mx-auto container"> <div className="p-6 mx-auto container">
{/* 成功提示 */} {/* 成功提示 */}
<div id="ncm-toast-success" className="toast toast-top toast-end hidden z-[9999]"> <Toast id="ncm-toast-success" />
<div className="alert alert-success">
<span>配置保存成功</span>
</div>
</div>
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
<h2 className="text-2xl font-bold mb-6">网易云音乐配置</h2> <h2 className="text-2xl font-bold mb-6">网易云音乐配置</h2>

View File

@ -1,5 +1,6 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper'; import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
import Toast from "../toast.jsx";
export default function Tiktok() { export default function Tiktok() {
const [config, setConfig] = useState({ const [config, setConfig] = useState({
@ -64,11 +65,7 @@ export default function Tiktok() {
return ( return (
<div className="p-6 mx-auto container"> <div className="p-6 mx-auto container">
{/* 成功提示 */} {/* 成功提示 */}
<div id="tiktok-toast-success" className="toast toast-top toast-end hidden z-[9999]"> <Toast id="tiktok-toast-success" />
<div className="alert alert-success">
<span>配置保存成功</span>
</div>
</div>
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
<h2 className="text-2xl font-bold mb-6">抖音配置</h2> <h2 className="text-2xl font-bold mb-6">抖音配置</h2>

View File

@ -1,6 +1,7 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { BILI_CDN_SELECT_LIST, YOUTUBE_GRAPHICS_LIST } from "../../../constants/constant.js"; import { BILI_CDN_SELECT_LIST, YOUTUBE_GRAPHICS_LIST } from "../../../constants/constant.js";
import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper'; import { readYamlConfig, updateYamlConfig } from '../../utils/yamlHelper';
import Toast from "../toast.jsx";
export default function Youtube() { export default function Youtube() {
const [config, setConfig] = useState({ const [config, setConfig] = useState({
@ -69,11 +70,7 @@ export default function Youtube() {
return ( return (
<div className="p-6 mx-auto container"> <div className="p-6 mx-auto container">
{/* 成功提示 */} {/* 成功提示 */}
<div id="youtube-toast-success" className="toast toast-top toast-end hidden z-[9999]"> <Toast id="youtube-toast-success" />
<div className="alert alert-success">
<span>配置保存成功</span>
</div>
</div>
<div className="max-w-5xl mx-auto"> <div className="max-w-5xl mx-auto">
<h2 className="text-2xl font-bold mb-6">YouTube 配置</h2> <h2 className="text-2xl font-bold mb-6">YouTube 配置</h2>

View File

@ -0,0 +1,9 @@
export default function Toast({ id }) {
return (
<div id={ id } className="toast toast-top toast-end hidden z-[9999]">
<div className="alert alert-success">
<span>配置保存成功</span>
</div>
</div>
);
};