yggdrasil/pages/admin/logs/
cleanup.rs1use crate::api::logs::{get_log_settings, update_log_settings};
3use crate::components::forms::NumberInput;
4use crate::components::ui::{
5 button_class, use_toast, ButtonSize, ButtonVariant, IconButton, IconName,
6};
7use crate::models::log::LogSettings;
8use crate::utils::error::failure_message;
9use leptos::prelude::*;
10use leptos::task::spawn_local;
11
12#[component]
17pub(super) fn CleanupPolicy(#[prop(into)] on_close: Callback<()>) -> impl IntoView {
18 let toast = use_toast();
19 let saved = RwSignal::new(None::<LogSettings>);
20 let days = RwSignal::new(7_i64);
21 let rows = RwSignal::new(100_000_i64);
22 let saving = RwSignal::new(false);
23 Effect::new(move |_| {
25 spawn_local(async move {
26 if let Ok(s) = get_log_settings().await {
27 days.try_set(i64::from(s.retention_days));
28 rows.try_set(i64::from(s.max_rows));
29 saved.try_set(Some(s));
30 }
31 });
32 });
33 let dirty = move || {
34 saved.with(|s| {
35 s.as_ref().is_some_and(|s| {
36 i64::from(s.retention_days) != days.get() || i64::from(s.max_rows) != rows.get()
37 })
38 })
39 };
40 let save = move |_| {
41 saving.set(true);
42 let (retention_days, max_rows) = (days.get_untracked() as i32, rows.get_untracked() as i32);
43 spawn_local(async move {
44 match update_log_settings(retention_days, max_rows).await {
45 Ok(s) => {
46 days.try_set(i64::from(s.retention_days));
47 rows.try_set(i64::from(s.max_rows));
48 saved.try_set(Some(s));
49 toast.success("清理策略已保存");
50 }
51 Err(e) => toast.error(failure_message("保存失败", &e)),
52 }
53 saving.try_set(false);
54 });
55 };
56 view! {
57 <section class="admin-panel logs-cleanup" aria-labelledby="logs-cleanup-h">
58 <div class="logs-cleanup-head">
59 <div>
60 <h2 id="logs-cleanup-h">"清理策略"</h2>
61 <p>"后台任务定期清理,保留期与行数上限先到者生效。"</p>
62 </div>
63 <IconButton
64 icon=IconName::X
65 label="收起"
66 size=ButtonSize::Sm
67 onclick=move |_| on_close.run(())
68 />
69 </div>
70 <div class="logs-cleanup-fields">
71 <label for="logs-days">"保留天数"</label>
72 <NumberInput
73 id="logs-days"
74 value=days
75 min=1
76 max=90
77 unit="天"
78 onchange=move |v: i64| days.set(v)
79 />
80 <label for="logs-rows">"最大行数"</label>
81 <NumberInput
82 id="logs-rows"
83 value=rows
84 min=1000
85 max=1_000_000
86 step=10_000
87 unit="行"
88 onchange=move |v: i64| rows.set(v)
89 />
90 <button
91 class=button_class(ButtonVariant::Primary, ButtonSize::Sm)
92 type="button"
93 disabled=move || !dirty() || saving.get()
94 on:click=save
95 >
96 {move || if saving.get() { "保存中…" } else { "保存" }}
97 </button>
98 </div>
99 </section>
100 }
101}