yggdrasil/pages/admin/settings/
upload_section.rs1use dioxus::prelude::*;
4
5#[cfg(target_arch = "wasm32")]
6use crate::api::settings::{get_upload_settings, update_upload_settings};
7#[cfg(target_arch = "wasm32")]
8use crate::components::forms::{FormLabel, FormSelect};
9#[cfg(target_arch = "wasm32")]
10use crate::components::ui::{LoadingButton, ADMIN_CARD_CLASS};
11#[cfg(target_arch = "wasm32")]
12use crate::models::settings::UploadSettings;
13
14#[allow(non_snake_case)]
16#[component]
17pub fn UploadSection(toast: Callback<(String, bool)>) -> Element {
18 #[cfg(target_arch = "wasm32")]
19 {
20 let mut saved: Signal<UploadSettings> = use_signal(UploadSettings::default);
21 let mut draft: Signal<i32> =
22 use_signal(|| crate::models::settings::DEFAULT_UPLOAD_CONCURRENCY);
23 let loading = use_signal(|| true);
24 let mut saving = use_signal(|| false);
25 let mut just_saved = use_signal(|| false);
26
27 use_effect(move || {
28 #[cfg(target_arch = "wasm32")]
29 {
30 let mut saved = saved;
31 let mut draft = draft;
32 let mut loading = loading;
33 spawn(async move {
34 match get_upload_settings().await {
35 Ok(s) => {
36 saved.set(s.clone());
37 draft.set(s.concurrency);
38 }
39 Err(e) => toast.call((format!("加载失败:{e}"), true)),
40 }
41 loading.set(false);
42 });
43 }
44 });
45
46 let dirty = use_memo(move || draft() != saved().concurrency);
47
48 rsx! {
49 div { class: "space-y-6",
50 div { class: "{ADMIN_CARD_CLASS} p-6 md:p-8 flex flex-col gap-6",
51 div { class: "flex items-center gap-3",
52 span { class: "inline-flex items-center justify-center w-10 h-10 rounded-full bg-[var(--color-paper-theme)] text-[var(--color-paper-primary)] border border-[var(--color-paper-border)]",
53 svg {
54 class: "w-5 h-5",
55 view_box: "0 0 24 24",
56 fill: "none",
57 stroke: "currentColor",
58 stroke_width: "1.8",
59 stroke_linecap: "round",
60 stroke_linejoin: "round",
61 path { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }
62 polyline { points: "17 8 12 3 7 8" }
63 line {
64 x1: "12",
65 y1: "3",
66 x2: "12",
67 y2: "15",
68 }
69 }
70 }
71 div {
72 h2 { class: "text-xl font-bold text-[var(--color-paper-primary)]",
73 "素材上传并发数"
74 }
75 p { class: "text-sm text-[var(--color-paper-secondary)] mt-0.5",
76 "素材管理页上传弹窗同时发起的上传任务数,调高可加速批量上传。"
77 }
78 }
79 }
80
81 div { class: "flex flex-col gap-2 max-w-xl",
82 FormLabel {
83 label: "并发数",
84 html_for: Some("upload-concurrency".to_string()),
85 }
86 FormSelect {
87 id: Some("upload-concurrency".to_string()),
88 value: draft(),
89 options: vec![
90 (1, "1(顺序上传)"),
91 (2, "2"),
92 (3, "3(默认)"),
93 (4, "4"),
94 (5, "5"),
95 (6, "6"),
96 (7, "7"),
97 (8, "8"),
98 ],
99 onchange: move |v: i32| {
100 draft.set(v);
101 just_saved.set(false);
102 },
103 }
104 p { class: "text-xs text-[var(--color-paper-secondary)]",
105 "弹窗按并发数自动放大张间间隔,聚合速率始终与上传限流对齐,不会触发 429。"
106 }
107 }
108
109 div { class: "flex items-center justify-between gap-4 pt-1",
110 if just_saved() {
111 span { class: "inline-flex items-center gap-1.5 text-xs text-[var(--color-paper-accent)]",
112 svg {
113 class: "w-3.5 h-3.5",
114 view_box: "0 0 24 24",
115 fill: "none",
116 stroke: "currentColor",
117 stroke_width: "2.5",
118 path {
119 stroke_linecap: "round",
120 stroke_linejoin: "round",
121 d: "M5 13l4 4L19 7",
122 }
123 }
124 "已保存"
125 }
126 } else if dirty() {
127 span { class: "text-xs text-[var(--color-paper-secondary)]",
128 "有未保存的更改"
129 }
130 } else {
131 span { class: "text-xs text-transparent select-none", "·" }
132 }
133 LoadingButton {
134 label: "保存设置".to_string(),
135 loading: saving(),
136 disabled: loading() || just_saved() || !dirty(),
137 onclick: move |_| {
138 let n = draft();
139 saving.set(true);
140 spawn(async move {
141 match update_upload_settings(n).await {
142 Ok(s) => {
143 saved.set(s.clone());
144 draft.set(s.concurrency);
145 just_saved.set(true);
146 toast.call(("保存成功".to_string(), false));
147 }
148 Err(e) => toast.call((format!("保存失败:{e}"), true)),
149 }
150 saving.set(false);
151 });
152 },
153 }
154 }
155 }
156 }
157 }
158 }
159 #[cfg(not(target_arch = "wasm32"))]
160 {
161 rsx! {
162 div { class: "p-8 text-[var(--color-paper-secondary)]", "上传配置(前端渲染)" }
163 }
164 }
165}