yggdrasil/pages/admin/system/backup/
import.rs1use super::task::BackupState;
2use crate::components::ui::{button_class, ButtonSize, ButtonVariant};
3use leptos::prelude::*;
4
5#[cfg(target_arch = "wasm32")]
7const IMPORT_MAX_BYTES_CLIENT: u64 = 512 * 1024 * 1024;
8
9#[component]
10pub(super) fn ImportBackup(state: BackupState) -> impl IntoView {
11 let import_busy = state.importing;
12 let is_busy = move || state.busy();
13 let on_import = move |evt| {
14 #[cfg(target_arch = "wasm32")]
15 {
16 if state.busy_untracked() {
17 return;
18 }
19 let input = event_target::<web_sys::HtmlInputElement>(&evt);
20 let Some(web_file) = input.files().and_then(|files| files.get(0)) else {
21 return;
22 };
23 input.set_value("");
25 if !web_file.name().ends_with(".sql") {
27 state.error.set(Some("仅接受 .sql 备份文件".to_string()));
28 return;
29 }
30 if web_file.size() as u64 > IMPORT_MAX_BYTES_CLIENT {
31 state.error.set(Some(format!(
32 "文件超过导入上限({}MB)",
33 IMPORT_MAX_BYTES_CLIENT / 1024 / 1024
34 )));
35 return;
36 }
37 import_busy.set(true);
38 state.error.set(None);
39 leptos::task::spawn_local(async move {
40 match crate::utils::web_upload::post_multipart_file(
41 "/api/database/backups/import",
42 "file",
43 &web_file,
44 )
45 .await
46 {
47 Ok(_) => state.refresh(),
48 Err(msg) => {
49 let _ = state.error.try_set(Some(msg));
50 }
51 }
52 let _ = import_busy.try_set(false);
53 });
54 }
55 #[cfg(not(target_arch = "wasm32"))]
56 let _ = evt;
57 };
58
59 view! {
60 <label
61 class=format!("{} sys-file-button", button_class(ButtonVariant::Secondary, ButtonSize::Sm))
62 aria-disabled=move || (import_busy.get() || is_busy()).then_some("true")
63 >
64 {move || if import_busy.get() { "导入中…" } else { "导入备份" }}
65 <input
66 type="file"
67 accept=".sql"
68 class="sr-only"
69 disabled=move || import_busy.get() || is_busy()
70 on:change=on_import
71 />
72 </label>
73 }
74}