设计好消息通知关闭

This commit is contained in:
lsy 2025-01-01 23:56:37 +08:00
parent 1f885b54f3
commit 995a3262ed
10 changed files with 115 additions and 55 deletions

1
frontend/Cargo.lock generated
View File

@ -1477,6 +1477,7 @@ dependencies = [
"getrandom 0.2.15",
"js-sys",
"rand 0.8.5",
"tokio",
"wasm-bindgen",
"web-sys",
]

View File

@ -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"]

View File

@ -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) {

View File

@ -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(())
}

View File

@ -0,0 +1,5 @@
use tokio;
pub fn set_interval(time:u32,callback:fn()){
}

View File

@ -1,3 +1,4 @@
pub mod dom;
pub mod error;
pub mod helps;
pub mod hooks;

View File

@ -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::<Signal<NotificationProvider>>();
let new_notifications:Vec<NotificationProps> = 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::<Signal<NotificationProvider>>()().notifications;
let notifications_context = use_context::<Signal<NotificationProvider>>();
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,
@ -107,8 +133,14 @@ pub fn Notification() -> Element {
}
}
div {
class:"mt-2 h-1 bg-white animate-progress",
style: format!("animation-duration: {}s", item.time),
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::<Signal<NotificationProvider>>();
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,
});
}

View File

@ -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;

View File

@ -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"
}
}
}
}

View File

@ -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: [],