video-shuoshan/web/src/pages/SettingsPage.tsx
zyc ffe92f7b15 Initial commit: 即梦视频生成平台
- web/: React + Vite + TypeScript 前端
- backend/: Django + DRF + SimpleJWT 后端
- prototype/: HTML 设计原型
- docs/: PRD 和设计评审文档
- test: 单元测试 + E2E 极限测试
2026-03-13 09:59:33 +08:00

126 lines
4.0 KiB
TypeScript

import { useEffect, useState, useCallback } from 'react';
import { adminApi } from '../lib/api';
import type { SystemSettings } from '../types';
import { showToast } from '../components/Toast';
import styles from './SettingsPage.module.css';
export function SettingsPage() {
const [settings, setSettings] = useState<SystemSettings>({
default_daily_seconds_limit: 600,
default_monthly_seconds_limit: 6000,
announcement: '',
announcement_enabled: false,
});
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const fetchSettings = useCallback(async () => {
try {
const { data } = await adminApi.getSettings();
setSettings(data);
} catch {
showToast('加载设置失败');
} finally {
setLoading(false);
}
}, []);
useEffect(() => { fetchSettings(); }, [fetchSettings]);
const handleSaveQuota = async () => {
setSaving(true);
try {
await adminApi.updateSettings(settings);
showToast('设置已保存');
} catch {
showToast('保存失败');
} finally {
setSaving(false);
}
};
const handleSaveAnnouncement = async () => {
setSaving(true);
try {
await adminApi.updateSettings(settings);
showToast('公告已保存');
} catch {
showToast('保存失败');
} finally {
setSaving(false);
}
};
if (loading) {
return (
<div className={styles.page}>
<h1 className={styles.title}></h1>
<div className={styles.skeletonCard} />
<div className={styles.skeletonCard} />
</div>
);
}
return (
<div className={styles.page}>
<h1 className={styles.title}></h1>
<div className={styles.card}>
<h2 className={styles.cardTitle}></h2>
<p className={styles.cardDesc}></p>
<div className={styles.formRow}>
<div className={styles.formGroup}>
<label> ()</label>
<input
type="number"
value={settings.default_daily_seconds_limit}
onChange={(e) => setSettings({ ...settings, default_daily_seconds_limit: Number(e.target.value) })}
/>
</div>
<div className={styles.formGroup}>
<label> ()</label>
<input
type="number"
value={settings.default_monthly_seconds_limit}
onChange={(e) => setSettings({ ...settings, default_monthly_seconds_limit: Number(e.target.value) })}
/>
</div>
</div>
<button className={styles.saveBtn} onClick={handleSaveQuota} disabled={saving}>
{saving ? '保存中...' : '保存配额设置'}
</button>
</div>
<div className={styles.card}>
<div className={styles.cardHeader}>
<div>
<h2 className={styles.cardTitle}></h2>
<p className={styles.cardDesc}></p>
</div>
<label className={styles.switch}>
<input
type="checkbox"
checked={settings.announcement_enabled}
onChange={(e) => setSettings({ ...settings, announcement_enabled: e.target.checked })}
/>
<span className={styles.slider}></span>
</label>
</div>
<div className={styles.formGroup}>
<label></label>
<textarea
className={styles.textarea}
value={settings.announcement}
onChange={(e) => setSettings({ ...settings, announcement: e.target.value })}
placeholder="输入公告内容..."
rows={4}
/>
</div>
<button className={styles.saveBtn} onClick={handleSaveAnnouncement} disabled={saving}>
{saving ? '保存中...' : '保存公告'}
</button>
</div>
</div>
);
}