1、修改前台登陆样式背景可使用视频

2、增加后台配置前台背景样式
This commit is contained in:
2026-07-16 09:28:43 +08:00
parent 5036efe9aa
commit 41feb480ee
7 changed files with 342 additions and 363 deletions
+16
View File
@@ -276,6 +276,22 @@ export async function uploadLogo(file: File): Promise<{ url: string }> {
return { url: res.url };
}
export async function uploadLoginVideo(file: File): Promise<{ url: string }> {
const form = new FormData();
form.append('file', file);
const token = localStorage.getItem('auth_token');
const res = await fetch(`${import.meta.env.VITE_API_BASE || 'http://localhost:8000'}/api/admin/upload-login-video`, {
method: 'POST',
headers: token ? { Authorization: `Bearer ${token}` } : {},
body: form,
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err?.detail || '上传失败');
}
return res.json();
}
function setMaybe(params: URLSearchParams, key: string, value: unknown): void {
if (value !== undefined && value !== null && String(value) !== '') params.set(key, String(value));
}
+77 -1
View File
@@ -3,7 +3,7 @@ import {
Button, Card, Form, Input, InputNumber, message, Select, Space, Switch, Typography, Upload,
} from 'antd';
import {
SettingOutlined, SaveOutlined, UploadOutlined, FilePdfOutlined, EyeOutlined, DatabaseOutlined,
SettingOutlined, SaveOutlined, UploadOutlined, FilePdfOutlined, EyeOutlined, DatabaseOutlined, VideoCameraOutlined,
} from '@ant-design/icons';
import {
getGlobalResourceCapacity,
@@ -12,6 +12,7 @@ import {
updateSystemConfig,
uploadLogo,
uploadPdf,
uploadLoginVideo,
} from '../api';
import type { ResourceCapacityUnit, SystemConfig } from '../types';
@@ -118,6 +119,35 @@ const AdminSettings: React.FC = () => {
return false;
};
const handleLoginVideoUpload = async (file: File) => {
setUploading('login_bg_video');
try {
const res = await uploadLoginVideo(file);
setConfigs(prev => prev.map(c => c.key === 'login_bg_video' ? { ...c, value: res.url } : c));
form.setFieldsValue({ login_bg_video: res.url });
const config = configs.find(c => c.key === 'login_bg_video');
if (config) {
await updateSystemConfig(config.id, res.url);
}
message.success('登录背景视频上传成功并已保存');
} catch (e: any) {
message.error(e?.message || '上传失败');
} finally {
setUploading('');
}
return false;
};
const handleRemoveLoginVideo = async () => {
setConfigs(prev => prev.map(c => c.key === 'login_bg_video' ? { ...c, value: '' } : c));
form.setFieldsValue({ login_bg_video: '' });
const config = configs.find(c => c.key === 'login_bg_video');
if (config) {
await updateSystemConfig(config.id, '');
}
message.success('已移除登录背景视频');
};
const groupedConfigs: Record<string, SystemConfig[]> = {
'站点信息': configs.filter(c => c.key.startsWith('site_')),
'协议配置': configs.filter(c => c.key === 'user_agreement_privacy_url'),
@@ -297,6 +327,52 @@ const AdminSettings: React.FC = () => {
</div>
<Form form={form} layout="vertical">
{/* 登录背景视频 */}
<div style={{ marginBottom: 24 }}>
<Typography.Text strong style={{ fontSize: 14, display: 'block', marginBottom: 12, paddingBottom: 8, borderBottom: '1px solid #f0f0f5' }}>
</Typography.Text>
<div style={{ padding: 16, borderRadius: 10, border: '1px solid #f0f0f5', background: '#fafbfc' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
<Space>
<VideoCameraOutlined style={{ color: '#6366f1', fontSize: 18 }} />
<Typography.Text strong></Typography.Text>
</Space>
<Space>
{form.getFieldValue('login_bg_video') && (
<Button size="small" danger onClick={handleRemoveLoginVideo}>
</Button>
)}
<Upload
accept="video/mp4,video/webm,video/mov"
showUploadList={false}
beforeUpload={handleLoginVideoUpload}
>
<Button size="small" type="primary" icon={<UploadOutlined />} loading={uploading === 'login_bg_video'}>
</Button>
</Upload>
</Space>
</div>
{form.getFieldValue('login_bg_video') ? (
<video
src={form.getFieldValue('login_bg_video')}
controls
muted
style={{ width: '100%', maxHeight: 200, borderRadius: 8, background: '#000' }}
/>
) : (
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
使 backimage.png
</Typography.Text>
)}
<Typography.Text type="secondary" style={{ fontSize: 12, display: 'block', marginTop: 6 }}>
MP4WebMMOV 50MB
</Typography.Text>
</div>
</div>
{Object.entries(groupedConfigs).map(([group, items]) => (
<div key={group} style={{ marginBottom: 24 }}>
<Typography.Text strong style={{ fontSize: 14, display: 'block', marginBottom: 12, paddingBottom: 8, borderBottom: '1px solid #f0f0f5' }}>