yggdrasil/pages/admin/settings/
backup_section.rs1use leptos::prelude::*;
7
8use super::kit::{use_section, SettingRow, SettingsCard, SwitchRow};
9use super::SettingsSection;
10use crate::api::error::ApiError;
11use crate::api::settings::{get_backup_settings, update_backup_settings};
12use crate::components::forms::{NumberInput, TimePicker};
13use crate::models::settings::BackupSettings;
14use crate::utils::time::{local_hhmm_to_utc, utc_hhmm_to_local};
15
16fn to_local(mut s: BackupSettings) -> BackupSettings {
18 s.time_utc = utc_hhmm_to_local(&s.time_utc);
19 s
20}
21
22async fn load() -> Result<BackupSettings, ApiError> {
23 get_backup_settings().await.map(|v| to_local(v.settings))
24}
25
26async fn save(d: BackupSettings) -> Result<BackupSettings, ApiError> {
27 update_backup_settings(
28 d.auto_enabled,
29 local_hhmm_to_utc(&d.time_utc),
30 d.retention_count,
31 d.include_uploads,
32 )
33 .await
34 .map(|v| to_local(v.settings))
35}
36
37#[component]
39pub fn BackupSection() -> impl IntoView {
40 let st = use_section(SettingsSection::Backup, load, save);
41 view! {
42 <SettingsCard
43 section=SettingsSection::Backup
44 description="每天定时备份数据库。创建、恢复与删除备份在「系统」页。"
45 ready=st.ready()
46 load_failed=st.load_failed()
47 failed=st.failed()
48 >
49 <SwitchRow
50 label="启用定时备份"
51 hint="保存后调度任务立即按新时间重排。"
52 checked=st.field(|d| d.auto_enabled)
53 ontoggle=move |()| st.edit(|d| d.auto_enabled = !d.auto_enabled)
54 />
55 <SettingRow label="执行时间" html_for="backup-time" hint="按本地时间显示与编辑,服务端以 UTC 保存。">
56 <TimePicker
57 id="backup-time"
58 value=st.field(|d| d.time_utc.clone())
59 onchange=move |v: String| st.edit(|d| d.time_utc = v)
60 />
61 </SettingRow>
62 <SettingRow label="保留份数" html_for="backup-retention">
63 <NumberInput
64 id="backup-retention"
65 value=st.field(|d| i64::from(d.retention_count))
66 min=1
67 max=365
68 unit="份"
69 hint="超出后最旧的自动备份连同 uploads 包一起删除;手动备份不会自动删除。"
70 onchange=move |v: i64| st.edit(|d| d.retention_count = v as i32)
71 />
72 </SettingRow>
73 <SwitchRow
74 label="包含 uploads"
75 hint="同时打包上传的素材(tar.gz,跳过可重建的缓存)。"
76 checked=st.field(|d| d.include_uploads)
77 ontoggle=move |()| st.edit(|d| d.include_uploads = !d.include_uploads)
78 />
79 </SettingsCard>
80 }
81}