diff --git a/frontend/Cargo.lock b/frontend/Cargo.lock index 892f35c..169f034 100644 --- a/frontend/Cargo.lock +++ b/frontend/Cargo.lock @@ -1477,6 +1477,7 @@ dependencies = [ "getrandom 0.2.15", "js-sys", "rand 0.8.5", + "tokio", "wasm-bindgen", "web-sys", ] diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index bfdfb4d..cc9b333 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -14,6 +14,7 @@ web-sys = { version = "0.3.76", features = ["Window","Storage","MediaQueryList", js-sys = "0.3.76" rand = "0.8.5" getrandom = { version = "0.2", features = ["js"] } +tokio = "1.42.0" [features] default = ["dioxus/web"] diff --git a/frontend/assets/styling/tailwind.css b/frontend/assets/styling/tailwind.css index 85a5e10..3b18f50 100644 --- a/frontend/assets/styling/tailwind.css +++ b/frontend/assets/styling/tailwind.css @@ -598,10 +598,18 @@ video { height: 0.25rem; } +.h-full { + height: 100%; +} + .w-\[20rem\] { width: 20rem; } +.w-full { + width: 100%; +} + .min-w-0 { min-width: 0px; } @@ -610,20 +618,6 @@ video { flex-shrink: 0; } -@keyframes progress { - 0% { - width: 0%; - } - - 100% { - width: 100%; - } -} - -.animate-progress { - animation: 5s progress linear infinite; -} - .items-center { align-items: center; } @@ -655,9 +649,14 @@ video { border-color: rgb(239 68 68 / var(--tw-border-opacity, 1)); } -.bg-white { +.bg-blue-500 { --tw-bg-opacity: 1; - background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1)); + background-color: rgb(59 130 246 / var(--tw-bg-opacity, 1)); +} + +.bg-slate-400 { + --tw-bg-opacity: 1; + background-color: rgb(148 163 184 / var(--tw-bg-opacity, 1)); } .px-3 { @@ -670,18 +669,26 @@ video { padding-bottom: 0.75rem; } -.text-gray-300 { +.text-gray-800 { --tw-text-opacity: 1; - color: rgb(209 213 219 / var(--tw-text-opacity, 1)); + color: rgb(31 41 55 / var(--tw-text-opacity, 1)); +} + +.opacity-75 { + opacity: 0.75; +} + +.filter { + filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); } .hover\:text-accent:hover { color: var(--accent-color); } -.dark\:text-gray-800:is(.dark *) { +.dark\:text-gray-200:is(.dark *) { --tw-text-opacity: 1; - color: rgb(31 41 55 / var(--tw-text-opacity, 1)); + color: rgb(229 231 235 / var(--tw-text-opacity, 1)); } @media not all and (min-width: 640px) { diff --git a/frontend/src/common/dom.rs b/frontend/src/common/dom.rs index b8494fa..0890567 100644 --- a/frontend/src/common/dom.rs +++ b/frontend/src/common/dom.rs @@ -54,3 +54,9 @@ pub fn add_element_class(ele_name: &str, class_name: &str) -> CustomResult<()> { pub fn remove_element_class(ele_name: &str, class_name: &str) -> CustomResult<()> { Ok(get_element(ele_name)?.class_list().remove_1(class_name)?) } + +pub fn remove_element(ele_name: &str)-> CustomResult<()> { + let e=get_element(ele_name)?; + let _=e.parent_node().ok_or("无法获取父节点")?.remove_child(&e)?; + Ok(()) +} \ No newline at end of file diff --git a/frontend/src/common/hooks.rs b/frontend/src/common/hooks.rs new file mode 100644 index 0000000..d2b2cf9 --- /dev/null +++ b/frontend/src/common/hooks.rs @@ -0,0 +1,5 @@ +use tokio; + +pub fn set_interval(time:u32,callback:fn()){ + +} \ No newline at end of file diff --git a/frontend/src/common/mod.rs b/frontend/src/common/mod.rs index fba8473..6eda43c 100644 --- a/frontend/src/common/mod.rs +++ b/frontend/src/common/mod.rs @@ -1,3 +1,4 @@ pub mod dom; pub mod error; pub mod helps; +pub mod hooks; \ No newline at end of file diff --git a/frontend/src/components/notification.rs b/frontend/src/components/notification.rs index 4f9e963..93dca57 100644 --- a/frontend/src/components/notification.rs +++ b/frontend/src/components/notification.rs @@ -1,7 +1,7 @@ use crate::common::error::{CustomErrorInto, CustomResult}; use crate::common::helps::generate_random_string; use crate::Route; -use dioxus::prelude::*; +use dioxus::{logger::tracing, prelude::*}; use dioxus_free_icons::icons::bs_icons::{BsCheckCircle, BsInfoCircle, BsXCircle, BsXLg}; use dioxus_free_icons::Icon; @@ -19,16 +19,25 @@ pub enum NotificationType { #[derive(PartialEq, Props, Clone)] pub struct NotificationProps { - #[props(default="".to_string())] + id: String, title: String, - #[props(default="".to_string())] content: String, - #[props(default = 5)] time: u64, - #[props(default=NotificationType::Info)] r#type: NotificationType, } +impl Default for NotificationProps { + fn default() -> Self { + Self { + id: "".to_string(), + title: "".to_string(), + content: "".to_string(), + time: 5, + r#type: NotificationType::Info, + } + } +} + #[derive(PartialEq, Clone)] struct NoticationColorMatching { color: String, @@ -38,7 +47,7 @@ struct NoticationColorMatching { fn get_color_matching(notification_type: &NotificationType) -> NoticationColorMatching { match notification_type { NotificationType::Info => NoticationColorMatching { - color: String::from("rgba(0,168,91,0.85)"), + color: String::from("rgb(38,131,255)"), icon: rsx! { Icon { icon: BsInfoCircle, @@ -48,7 +57,7 @@ fn get_color_matching(notification_type: &NotificationType) -> NoticationColorMa }, }, NotificationType::Error => NoticationColorMatching { - color: String::from("rgba(225,45,57,0.85)"), + color: String::from("rgb(225,45,57)"), icon: rsx! { Icon { icon: BsXCircle, @@ -58,7 +67,7 @@ fn get_color_matching(notification_type: &NotificationType) -> NoticationColorMa }, }, NotificationType::Success => NoticationColorMatching { - color: String::from("rgba(38,131,255,0.85)"), + color: String::from("rgb(0,168,91)"), icon: rsx! { Icon { icon: BsCheckCircle, @@ -70,26 +79,39 @@ fn get_color_matching(notification_type: &NotificationType) -> NoticationColorMa } } +pub fn remove_notification(id: String) { + let mut notifications_context = use_context::>(); + let new_notifications:Vec = notifications_context.clone()() + .notifications + .into_iter() + .filter(|i| i.id != id ) + .collect(); + + notifications_context.set(NotificationProvider { + notifications: new_notifications, + }); +} + #[component] pub fn Notification() -> Element { - let notifications = use_context::>()().notifications; + let notifications_context = use_context::>(); + let notifications = notifications_context().clone(); + return rsx! { div { class: "w-[20rem] absolute right-8 top-10 max-sm:w-[12rem]", - {notifications.iter().map(|item| { + {notifications.notifications.iter().map(move |item| { let color_matching=get_color_matching(&item.r#type); + let id = item.id.clone(); rsx!{ div { - id:format!("notification-{}",generate_random_string(10)), - class:"rounded px-3 py-3 m-2 !border-none text-gray-300 dark:text-gray-800 ", + id: id.clone(), + class:"rounded px-3 py-3 m-2 !border-none text-gray-800 dark:text-gray-200 opacity-75 ", style:format!("background-color:{}",color_matching.color), div { div { class:"flex items-center justify-between", div { - onclick:|e|{ - - }, class:"mr-2 relative top-[0.06rem] hover:text-accent", {color_matching.icon}, } @@ -98,6 +120,10 @@ pub fn Notification() -> Element { {item.title.clone()} } div { + onclick:move |e|{ + e.prevent_default(); + remove_notification(id.clone()); + }, class:"ml-1 flex-shrink-0", Icon{ icon:BsXLg, @@ -106,9 +132,15 @@ pub fn Notification() -> Element { } } } - div { - class:"mt-2 h-1 bg-white animate-progress", - style: format!("animation-duration: {}s", item.time), + div { + class:"mt-2 h-1 relative", + div { + class:"absolute bg-slate-400 w-full h-full", + } + div { + class:"absolute w-full h-full ", + style:"width:80%" + } } } } @@ -125,30 +157,35 @@ impl Toast { pub fn show(props: NotificationProps) { let mut notification_context = use_context::>(); let mut new_provider = notification_context().clone(); - new_provider.notifications.push(props); + let mut new_props = props; + new_props.id = format!("notification-{}",generate_random_string(10)); + new_provider.notifications.push(new_props); notification_context.set(new_provider); } pub fn info(title: String, content: String) { Self::show(NotificationProps { + id: Default::default(), title, content, - time: 5, + time: Default::default(), r#type: NotificationType::Info, }); } pub fn error(title: String, content: String) { Self::show(NotificationProps { + id: Default::default(), title, content, - time: 5, + time: Default::default(), r#type: NotificationType::Error, }); } pub fn success(title: String, content: String) { Self::show(NotificationProps { + id: Default::default(), title, content, - time: 5, + time: Default::default(), r#type: NotificationType::Success, }); } diff --git a/frontend/src/main.rs b/frontend/src/main.rs index d4cdf59..b06962a 100644 --- a/frontend/src/main.rs +++ b/frontend/src/main.rs @@ -4,7 +4,6 @@ mod common; use common::dom::{add_element_class, get_media_theme, remove_element_class}; use components::notification::{Notification, NotificationProvider}; use components::theme_toggle::{get_theme, ThemeProvider}; - use components::Navbar; use views::Home; diff --git a/frontend/src/views/home.rs b/frontend/src/views/home.rs index a90e965..2e14a63 100644 --- a/frontend/src/views/home.rs +++ b/frontend/src/views/home.rs @@ -14,8 +14,22 @@ pub fn Home() -> Element { onclick: move |_| { Toast::info("我是标sasadc我想二次TV要不以后牛魔题".to_string(), "我是内容".to_string()) }, - "Show Notification" + "info " } + button { + onclick: move |_| { + Toast::error("我是标sasadc我想二次TV要不以后牛魔题".to_string(), "我是内容".to_string()) + }, + "error " + } + button { + onclick: move |_| { + Toast::success("我是标sasadc我想二次TV要不以后牛魔题".to_string(), "我是内容".to_string()) + }, + "success" + } + + } } } diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 8cbc391..2faacb5 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -7,17 +7,6 @@ module.exports = { colors: { accent: 'var(--accent-color)', }, - animation:{ - progress:"5s progress linear infinite" - - }, - keyframes:{ - progress:{ - '0%':{width:'0%'}, - '100%':{width:'100%'} - } - - } }, }, plugins: [],