From a43a9bac36b3e3504080cd284acb728b9cc6ca67 Mon Sep 17 00:00:00 2001 From: lsy Date: Sat, 30 Nov 2024 14:03:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=EF=BC=9A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=BC=82=E5=B8=B8=E8=BF=9E=E6=8E=A5?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=90=8E=E7=BB=AD=E6=97=A0=E6=B3=95=E6=AD=A3?= =?UTF-8?q?=E5=B8=B8=E9=87=8D=E5=90=AF=EF=BC=9B=20=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=EF=BC=9A=E6=B6=88=E6=81=AF=E6=8F=90=E7=A4=BA=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=A0=87=E9=A2=98=EF=BC=8C=E6=B7=BB=E5=8A=A0Radix=20UI?= =?UTF-8?q?=EF=BC=8C=E9=87=8D=E6=9E=84HTTP=E9=94=99=E8=AF=AF=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/api/setup.rs | 4 +- backend/src/api/users.rs | 7 ++ backend/src/main.rs | 56 ++++------------ backend/src/storage/sql/builder.rs | 2 +- frontend/app/index.css | 43 +++++++++++- frontend/app/init.tsx | 10 +-- frontend/app/root.tsx | 67 +++++++++---------- frontend/app/routes.tsx | 10 ++- .../{common => commons}/serializableType.ts | 0 frontend/config/constants.ts | 32 --------- frontend/config/env.ts | 29 -------- frontend/core/http.ts | 48 +++++++++++-- frontend/core/theme.ts | 17 +++-- frontend/hooks/message.tsx | 54 +++++++++------ frontend/hooks/servicesProvider.tsx | 5 +- frontend/hooks/stylesProvider.tsx | 10 +++ frontend/package.json | 3 + frontend/server/express.ts | 1 - frontend/start.ts | 4 +- frontend/tailwind.config.ts | 16 +++-- frontend/tsconfig.json | 2 +- frontend/vite.config.ts | 1 - package.json | 5 ++ 23 files changed, 227 insertions(+), 199 deletions(-) rename frontend/{common => commons}/serializableType.ts (100%) delete mode 100644 frontend/config/constants.ts delete mode 100644 frontend/config/env.ts create mode 100644 frontend/hooks/stylesProvider.tsx create mode 100644 package.json diff --git a/backend/src/api/setup.rs b/backend/src/api/setup.rs index 21a78d2..29912f5 100644 --- a/backend/src/api/setup.rs +++ b/backend/src/api/setup.rs @@ -33,7 +33,7 @@ pub async fn setup_sql( .into_app_result()?; config::Config::write(config).into_app_result()?; - state.restart_server().await.into_app_result()?; + state.trigger_restart().await.into_app_result()?; Ok("Database installation successful".to_string()) } @@ -123,7 +123,7 @@ pub async fn setup_account( .into_app_result()?; config.init.administrator = true; config::Config::write(config).into_app_result()?; - state.restart_server().await.into_app_result()?; + state.trigger_restart().await.into_app_result()?; Ok(status::Custom( Status::Ok, diff --git a/backend/src/api/users.rs b/backend/src/api/users.rs index 8bf71cf..4727f1c 100644 --- a/backend/src/api/users.rs +++ b/backend/src/api/users.rs @@ -1,6 +1,7 @@ use crate::common::error::{CustomErrorInto, CustomResult}; use crate::security::bcrypt; use crate::storage::{sql, sql::builder}; +use regex::Regex; use rocket::{get, http::Status, post, response::status, serde::json::Json, State}; use serde::{Deserialize, Serialize}; @@ -30,6 +31,12 @@ pub async fn insert_user(sql: &sql::Database, data: RegisterData) -> CustomResul let password_hash = bcrypt::generate_hash(&data.password)?; + let re = Regex::new(r"([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z0-9_-]+)")?; + + if false == re.is_match(&data.email) { + return Err("邮箱格式不正确".into_custom_error()); + } + let mut builder = builder::QueryBuilder::new( builder::SqlOperation::Insert, sql.table_name("users"), diff --git a/backend/src/main.rs b/backend/src/main.rs index 76bb1f6..b00063b 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -13,7 +13,6 @@ pub struct AppState { db: Arc>>, shutdown: Arc>>, restart_progress: Arc>, - restart_attempts: Arc>, } impl AppState { @@ -22,7 +21,6 @@ impl AppState { db: Arc::new(Mutex::new(None)), shutdown: Arc::new(Mutex::new(None)), restart_progress: Arc::new(Mutex::new(false)), - restart_attempts: Arc::new(Mutex::new(0)), } } @@ -35,8 +33,15 @@ impl AppState { } pub async fn sql_link(&self, config: &config::SqlConfig) -> CustomResult<()> { - *self.db.lock().await = Some(sql::Database::link(config).await?); - Ok(()) + match sql::Database::link(config).await { + Ok(db) => { + *self.db.lock().await = Some(db); + Ok(()) + } + Err(e) => { + Err(e) + } + } } pub async fn set_shutdown(&self, shutdown: Shutdown) { @@ -54,27 +59,6 @@ impl AppState { Ok(()) } - pub async fn restart_server(&self) -> CustomResult<()> { - const MAX_RESTART_ATTEMPTS: u32 = 3; - const RESTART_DELAY_MS: u64 = 1000; - - let mut attempts = self.restart_attempts.lock().await; - if *attempts >= MAX_RESTART_ATTEMPTS { - return Err("达到最大重启尝试次数".into_custom_error()); - } - *attempts += 1; - - *self.restart_progress.lock().await = true; - - self.shutdown - .lock() - .await - .take() - .ok_or_else(|| "未能获取rocket的shutdown".into_custom_error())? - .notify(); - - Ok(()) - } } #[rocket::main] @@ -115,31 +99,15 @@ async fn main() -> CustomResult<()> { rocket.launch().await?; if *state.restart_progress.lock().await { - tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await; - if let Ok(current_exe) = std::env::current_exe() { - println!("正在尝试重启服务器..."); - - let mut command = std::process::Command::new(current_exe); - command.env("RUST_BACKTRACE", "1"); - - match command.spawn() { - Ok(child) => { - println!("成功启动新进程 (PID: {})", child.id()); - tokio::time::sleep(tokio::time::Duration::from_millis(500)).await; - } - Err(e) => { - eprintln!("启动新进程失败: {}", e); - *state.restart_progress.lock().await = false; - return Err(format!("重启失败: {}", e).into_custom_error()); - } + match std::process::Command::new(current_exe).spawn() { + Ok(_) => println!("成功启动新进程"), + Err(e) => eprintln!("启动新进程失败: {}", e), }; } else { eprintln!("获取当前可执行文件路径失败"); - return Err("重启失败: 无法获取可执行文件路径".into_custom_error()); } } - println!("服务器正常退出"); std::process::exit(0); } diff --git a/backend/src/storage/sql/builder.rs b/backend/src/storage/sql/builder.rs index 0c72c49..54ee929 100644 --- a/backend/src/storage/sql/builder.rs +++ b/backend/src/storage/sql/builder.rs @@ -77,7 +77,7 @@ impl Default for TextValidator { impl TextValidator { pub fn validate(&self, text: &str, level: ValidationLevel) -> CustomResult<()> { if level == ValidationLevel::Raw { - return self.validate_sql_patterns(text); + return Ok(()); } let max_length = self .level_max_lengths diff --git a/frontend/app/index.css b/frontend/app/index.css index bd6213e..e825148 100644 --- a/frontend/app/index.css +++ b/frontend/app/index.css @@ -1,3 +1,44 @@ @tailwind base; @tailwind components; -@tailwind utilities; \ No newline at end of file +@tailwind utilities; + +@layer utilities { + .animate-slideIn { + animation: slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1); + } + + .animate-hide { + animation: hide 100ms ease-in; + } + + .animate-swipeOut { + animation: swipeOut 100ms ease-out; + } +} + +@keyframes hide { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes slideIn { + from { + transform: translateX(calc(100% + 1rem)); + } + to { + transform: translateX(0); + } +} + +@keyframes swipeOut { + from { + transform: translateX(var(--radix-toast-swipe-end-x)); + } + to { + transform: translateX(calc(100% + 1rem)); + } +} \ No newline at end of file diff --git a/frontend/app/init.tsx b/frontend/app/init.tsx index b950465..37c9743 100644 --- a/frontend/app/init.tsx +++ b/frontend/app/init.tsx @@ -131,7 +131,7 @@ const DatabaseConfig: React.FC = ({ onNext }) => { default: return field; } }); - message.error(`请填写以下必填项:${fieldNames.join('、')}`); + message.error(`请填写以下必填项:${fieldNames.join('、')}`, '验证失败'); return false; } return true; @@ -180,11 +180,11 @@ const DatabaseConfig: React.FC = ({ onNext }) => { Object.assign( newEnv) - message.success('数据库配置成功!'); + message.success('数据库配置已保存', '配置成功'); setTimeout(() => onNext(), 1000); } catch (error: any) { console.error( error); - message.error(error.message ); + message.error(error.message , error.title || '配置失败'); } finally { setLoading(false); } @@ -369,11 +369,11 @@ const AdminConfig: React.FC = ({ onNext }) => { body: JSON.stringify(newEnv), }); - message.success('管理员账号创建成功!'); + message.success('管理员账号已创建,即将进入下一步', '创建成功'); onNext(); } catch (error: any) { console.error(error); - message.error(error.message); + message.error(error.message, error.title || '创建失败'); } finally { setLoading(false); } diff --git a/frontend/app/root.tsx b/frontend/app/root.tsx index ae76c45..c6e4ce9 100644 --- a/frontend/app/root.tsx +++ b/frontend/app/root.tsx @@ -7,8 +7,7 @@ import { } from "@remix-run/react"; import { BaseProvider } from "hooks/servicesProvider"; -import { MessageProvider } from "hooks/message"; -import { MessageContainer } from "hooks/message"; + import "~/index.css"; @@ -24,42 +23,40 @@ export function Layout({ children }: { children: React.ReactNode }) { - - - - -