feat: add global image proxy config

This commit is contained in:
shinya
2025-07-15 22:20:42 +08:00
parent cca4092519
commit 90129c0d69
9 changed files with 165 additions and 16 deletions

View File

@@ -50,6 +50,7 @@ interface SiteConfig {
Announcement: string;
SearchDownstreamMaxPage: number;
SiteInterfaceCacheTime: number;
ImageProxy: string;
}
// 视频源数据类型
@@ -947,6 +948,7 @@ const SiteConfigComponent = ({ config }: { config: AdminConfig | null }) => {
Announcement: '',
SearchDownstreamMaxPage: 1,
SiteInterfaceCacheTime: 7200,
ImageProxy: '',
});
// 保存状态
const [saving, setSaving] = useState(false);
@@ -958,7 +960,10 @@ const SiteConfigComponent = ({ config }: { config: AdminConfig | null }) => {
useEffect(() => {
if (config?.SiteConfig) {
setSiteSettings(config.SiteConfig);
setSiteSettings({
...config.SiteConfig,
ImageProxy: config.SiteConfig.ImageProxy || '',
});
}
}, [config]);
@@ -1092,6 +1097,41 @@ const SiteConfigComponent = ({ config }: { config: AdminConfig | null }) => {
/>
</div>
{/* 图片代理 */}
<div>
<label
className={`block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 ${
isD1Storage ? 'opacity-50' : ''
}`}
>
{isD1Storage && (
<span className='ml-2 text-xs text-gray-500 dark:text-gray-400'>
(D1 )
</span>
)}
</label>
<input
type='text'
placeholder='例如: https://imageproxy.example.com/?url='
value={siteSettings.ImageProxy}
onChange={(e) =>
!isD1Storage &&
setSiteSettings((prev) => ({
...prev,
ImageProxy: e.target.value,
}))
}
disabled={isD1Storage}
className={`w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-green-500 focus:border-transparent ${
isD1Storage ? 'opacity-50 cursor-not-allowed' : ''
}`}
/>
<p className='mt-1 text-xs text-gray-500 dark:text-gray-400'>
访访使
</p>
</div>
{/* 操作按钮 */}
<div className='flex justify-end'>
<button

View File

@@ -33,11 +33,13 @@ export async function POST(request: NextRequest) {
Announcement,
SearchDownstreamMaxPage,
SiteInterfaceCacheTime,
ImageProxy,
} = body as {
SiteName: string;
Announcement: string;
SearchDownstreamMaxPage: number;
SiteInterfaceCacheTime: number;
ImageProxy: string;
};
// 参数校验
@@ -45,7 +47,8 @@ export async function POST(request: NextRequest) {
typeof SiteName !== 'string' ||
typeof Announcement !== 'string' ||
typeof SearchDownstreamMaxPage !== 'number' ||
typeof SiteInterfaceCacheTime !== 'number'
typeof SiteInterfaceCacheTime !== 'number' ||
typeof ImageProxy !== 'string'
) {
return NextResponse.json({ error: '参数格式错误' }, { status: 400 });
}
@@ -70,6 +73,7 @@ export async function POST(request: NextRequest) {
Announcement,
SearchDownstreamMaxPage,
SiteInterfaceCacheTime,
ImageProxy,
};
// 写入数据库

View File

@@ -40,17 +40,20 @@ export default async function RootLayout({
process.env.ANNOUNCEMENT ||
'本网站仅提供影视信息搜索服务,所有内容均来自第三方网站。本站不存储任何视频资源,不对任何内容的准确性、合法性、完整性负责。';
let enableRegister = process.env.NEXT_PUBLIC_ENABLE_REGISTER === 'true';
let imageProxy = process.env.NEXT_PUBLIC_IMAGE_PROXY || '';
if (process.env.NEXT_PUBLIC_STORAGE_TYPE !== 'd1') {
const config = await getConfig();
siteName = config.SiteConfig.SiteName;
announcement = config.SiteConfig.Announcement;
enableRegister = config.UserConfig.AllowRegister;
imageProxy = config.SiteConfig.ImageProxy;
}
// 将运行时配置注入到全局 window 对象,供客户端在运行时读取
const runtimeConfig = {
STORAGE_TYPE: process.env.NEXT_PUBLIC_STORAGE_TYPE || 'localstorage',
ENABLE_REGISTER: enableRegister,
IMAGE_PROXY: imageProxy,
};
return (