1use dioxus::prelude::*;
7use dioxus::router::components::Link;
8
9use crate::api::auth::{login, AuthResponse};
10use crate::components::forms::{AlertBox, FormInput, FormLabel, BUTTON_PRIMARY_CLASS};
11use crate::context::UserContext;
12use crate::router::Route;
13
14#[component]
16pub fn Login() -> Element {
17 let mut username = use_signal(|| "".to_string());
19 let mut password = use_signal(|| "".to_string());
20 let mut error = use_signal(|| None::<String>);
22 let mut loading = use_signal(|| false);
23 let mut ctx: UserContext = use_context();
25
26 let on_submit = Callback::new(move |_| {
28 if loading() {
29 return;
30 }
31 error.set(None);
32 loading.set(true);
33
34 let username_val = username();
35 let password_val = password();
36
37 spawn(async move {
39 match login(username_val, password_val).await {
40 Ok(AuthResponse { success: true, .. }) => {
41 ctx.checked.set(false);
43 let _ = dioxus::router::navigator().push(Route::Admin {});
44 }
45 Ok(AuthResponse {
46 success: false,
47 message,
48 ..
49 }) => {
50 error.set(Some(message));
51 }
52 Err(e) => {
53 error.set(Some(format!("请求失败: {}", e)));
54 }
55 }
56 loading.set(false);
57 });
58 });
59
60 let is_loading = loading();
61
62 rsx! {
63 div { class: "min-h-screen flex items-center justify-center bg-paper-theme",
64 div { class: "w-full max-w-md p-8 bg-paper-entry rounded-2xl border border-paper-border shadow-sm",
65 h1 { class: "text-2xl font-bold text-center text-paper-primary mb-6",
66 "登录"
67 }
68
69 if let Some(err) = error() {
70 AlertBox { message: err, variant: "error" }
71 }
72
73 div { class: "space-y-4",
74 div {
75 FormLabel {
76 label: "用户名 / 邮箱",
77 html_for: Some("login-username".to_string()),
78 }
79 FormInput {
80 id: Some("login-username".to_string()),
81 r#type: "text",
82 placeholder: "用户名或邮箱",
83 value: username(),
84 disabled: is_loading,
85 oninput: move |v: String| username.set(v),
86 onkeydown: Some(
88 EventHandler::new(move |e: KeyboardEvent| {
89 if e.key() == Key::Enter {
90 on_submit(())
91 }
92 }),
93 ),
94 }
95 }
96 div {
97 FormLabel {
98 label: "密码",
99 html_for: Some("login-password".to_string()),
100 }
101 FormInput {
102 id: Some("login-password".to_string()),
103 r#type: "password",
104 placeholder: "密码",
105 value: password(),
106 disabled: is_loading,
107 oninput: move |v: String| password.set(v),
108 onkeydown: Some(
109 EventHandler::new(move |e: KeyboardEvent| {
110 if e.key() == Key::Enter {
111 on_submit(())
112 }
113 }),
114 ),
115 }
116 }
117 button {
118 class: "{BUTTON_PRIMARY_CLASS}",
119 class: if is_loading { "opacity-60 cursor-not-allowed" },
120 disabled: is_loading,
121 onclick: move |_| on_submit(()),
122 if is_loading {
123 "登录中..."
124 } else {
125 "登录"
126 }
127 }
128 Link {
129 class: "block w-full py-2 px-4 text-center text-paper-secondary hover:text-paper-accent font-medium rounded-lg transition-all duration-200 cursor-pointer",
130 to: Route::Register {},
131 "还没有账号?去注册"
132 }
133 }
134 }
135 }
136 }
137}