后端:新增cors,前端:新增设备判断钩子
This commit is contained in:
parent
b75433cdbd
commit
5a6c020920
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@ -35,7 +35,7 @@
|
||||
"type": "shell",
|
||||
"command": "serve .",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/client/target/dx/client/release/web/public"
|
||||
"cwd": "${workspaceFolder}/target/dx/client/release/web/public"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
|
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -3632,6 +3632,23 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket_cors"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfac3a1df83f8d4fc96aa41dba3b86c786417b7fc0f52ec76295df2ba781aa69"
|
||||
dependencies = [
|
||||
"http 0.2.12",
|
||||
"log",
|
||||
"regex",
|
||||
"rocket",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"unicase",
|
||||
"unicase_serde",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket_http"
|
||||
version = "0.5.1"
|
||||
@ -3988,6 +4005,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"common",
|
||||
"rocket",
|
||||
"rocket_cors",
|
||||
"serde",
|
||||
"surrealdb",
|
||||
"tokio",
|
||||
@ -4984,6 +5002,16 @@ version = "2.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||
|
||||
[[package]]
|
||||
name = "unicase_serde"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ef53697679d874d69f3160af80bc28de12730a985d57bdf2b47456ccb8b11f1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
|
@ -19,6 +19,7 @@ rocket = "0.5.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.0", features = ["full"] }
|
||||
surrealdb = "2.1.4"
|
||||
rocket_cors = "0.6.0"
|
||||
|
||||
[profile]
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
@ -10,14 +10,9 @@ html[data-theme="dark"]{
|
||||
background-color:black;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'AlimamaTi';
|
||||
src: url('/assets/fonts/AlimamaFangYuanTiVF.ttf') format('truetype');
|
||||
font-display: swap;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
html {
|
||||
overflow-x:hidden;
|
||||
font-family: 'AlimamaTi', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
font-weight: 500;
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
}
|
||||
|
@ -586,10 +586,6 @@ video {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.top-5 {
|
||||
top: 1.25rem;
|
||||
}
|
||||
|
||||
.top-\[0\.06rem\] {
|
||||
top: 0.06rem;
|
||||
}
|
||||
@ -631,10 +627,6 @@ video {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.h-1 {
|
||||
height: 0.25rem;
|
||||
}
|
||||
@ -667,14 +659,14 @@ video {
|
||||
min-width: 0px;
|
||||
}
|
||||
|
||||
.min-w-7 {
|
||||
min-width: 1.75rem;
|
||||
}
|
||||
|
||||
.flex-shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.transform {
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
@keyframes slide-in {
|
||||
0% {
|
||||
transform: translateX(100%);
|
||||
@ -727,8 +719,8 @@ video {
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.gap-10 {
|
||||
gap: 2.5rem;
|
||||
.gap-5 {
|
||||
gap: 1.25rem;
|
||||
}
|
||||
|
||||
.justify-self-start {
|
||||
@ -739,12 +731,20 @@ video {
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.whitespace-nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
@ -832,8 +832,9 @@ video {
|
||||
background-color: rgb(148 163 184 / var(--tw-bg-opacity, 1));
|
||||
}
|
||||
|
||||
.p-2 {
|
||||
padding: 0.5rem;
|
||||
.px-2 {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
@ -906,6 +907,10 @@ video {
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
|
||||
.duration-150 {
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
|
||||
.duration-200 {
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
use super::Toggle;
|
||||
use crate::DeviceProvider;
|
||||
use crate::Route;
|
||||
use dioxus::{logger::tracing, prelude::*};
|
||||
use global_attributes::dangerous_inner_html;
|
||||
use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
use web_sys::Event;
|
||||
|
||||
#[component]
|
||||
pub fn Navbar() -> Element {
|
||||
let mut progress_signal = use_signal(|| 0);
|
||||
let mut progress_hover = use_signal(|| false);
|
||||
|
||||
// 监听滚动事件
|
||||
let mut is_more_single = use_signal(|| false);
|
||||
let mut device_context = use_context::<Signal<DeviceProvider>>();
|
||||
|
||||
use_effect(move || {
|
||||
let window = web_sys::window().unwrap();
|
||||
let document = window.document().unwrap();
|
||||
let document_element = document.document_element().unwrap();
|
||||
|
||||
let closure: Closure<dyn FnMut(_)> = {
|
||||
Closure::wrap(Box::new(move |_: web_sys::Event| {
|
||||
let closure = Closure::wrap(Box::new(move |_: Event| {
|
||||
let screen_height = document_element.scroll_height() as f64;
|
||||
let inner_height = window.inner_height().unwrap().as_f64().unwrap();
|
||||
let scrool_height = window.scroll_y().unwrap();
|
||||
let scroll_height = window.scroll_y().unwrap();
|
||||
let max_scroll_height = screen_height - inner_height;
|
||||
|
||||
let percent = if max_scroll_height > 0.0 {
|
||||
scrool_height / max_scroll_height
|
||||
scroll_height / max_scroll_height
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let percent = (percent.clamp(0.0, 1.0) * 100.0) as i32;
|
||||
progress_signal.set(percent);
|
||||
}) as Box<dyn FnMut(_)>)
|
||||
};
|
||||
}) as Box<dyn FnMut(Event)>);
|
||||
|
||||
document
|
||||
.add_event_listener_with_callback("scroll", closure.as_ref().unchecked_ref())
|
||||
@ -38,6 +39,8 @@ pub fn Navbar() -> Element {
|
||||
closure.forget();
|
||||
});
|
||||
|
||||
let tp = r#"<div>hello,world</div>"#;
|
||||
|
||||
rsx! {
|
||||
nav {
|
||||
class: "border-red-500 bg-slate-400 text-xl fixed top-0 left-0 right-0",
|
||||
@ -51,7 +54,7 @@ pub fn Navbar() -> Element {
|
||||
}
|
||||
}
|
||||
div {
|
||||
class:"flex gap-10 justify-center",
|
||||
class:"flex gap-5 justify-center",
|
||||
Link {
|
||||
to: Route::Home {},
|
||||
"首页"
|
||||
@ -60,10 +63,10 @@ pub fn Navbar() -> Element {
|
||||
to: Route::Home {},
|
||||
"首页"
|
||||
}
|
||||
Link {
|
||||
to: Route::Home {},
|
||||
"首页"
|
||||
|
||||
}
|
||||
div{
|
||||
dangerous_inner_html:"{tp}"
|
||||
}
|
||||
|
||||
div {
|
||||
|
@ -222,7 +222,7 @@ pub fn Notification() -> Element {
|
||||
|
||||
return rsx! {
|
||||
div {
|
||||
class: "w-[20rem] absolute right-8 top-5 max-sm:w-[12rem] ",
|
||||
class: "w-[20rem] absolute right-8 max-sm:w-[12rem]",
|
||||
{notifications.notifications.iter().map(move |item| {
|
||||
rsx! {
|
||||
NotificationCard {
|
||||
|
@ -3,12 +3,12 @@ use wasm_bindgen::{prelude::Closure, JsCast};
|
||||
mod components;
|
||||
mod utils;
|
||||
mod views;
|
||||
use crate::utils::error::CustomResult;
|
||||
use components::notification::{Notification, NotificationProvider};
|
||||
use components::theme_toggle::{get_theme, ThemeProvider};
|
||||
use components::Navbar;
|
||||
use utils::dom::{get_media_theme, set_element_dataset};
|
||||
use views::Home;
|
||||
use web_sys::Event;
|
||||
|
||||
#[derive(Debug, Clone, Routable, PartialEq)]
|
||||
enum Route {
|
||||
@ -22,6 +22,42 @@ const FAVICON: Asset = asset!("/assets/favicon.ico");
|
||||
const GLOBAL_CSS: Asset = asset!("/assets/styling/global.css");
|
||||
const TAILWIND_CSS: Asset = asset!("/assets/styling/tailwind.css");
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
enum DeviceType {
|
||||
DESKTOP,
|
||||
MOBILE,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for DeviceType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let s = match self {
|
||||
DeviceType::DESKTOP => "desktop",
|
||||
DeviceType::MOBILE => "mobile",
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
struct DeviceProvider(pub DeviceType);
|
||||
|
||||
impl Default for DeviceProvider {
|
||||
fn default() -> Self {
|
||||
DeviceProvider(DeviceType::DESKTOP)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for DeviceProvider {
|
||||
fn from(value: f64) -> Self {
|
||||
let derive_type = if value > 1024.0 {
|
||||
DeviceType::DESKTOP
|
||||
} else {
|
||||
DeviceType::MOBILE
|
||||
};
|
||||
DeviceProvider(derive_type)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
dioxus::launch(App);
|
||||
}
|
||||
@ -31,7 +67,24 @@ fn App() -> Element {
|
||||
let theme = get_theme();
|
||||
use_context_provider(|| Signal::new(ThemeProvider(theme.clone())));
|
||||
use_context_provider(|| Signal::new(NotificationProvider::default()));
|
||||
use_context_provider(|| Signal::new(DeviceProvider::default()));
|
||||
let mut is_dark_context = use_context::<Signal<ThemeProvider>>();
|
||||
let mut dervice_context = use_context::<Signal<DeviceProvider>>();
|
||||
|
||||
use_effect(move || {
|
||||
let window = web_sys::window().unwrap();
|
||||
let width = window.inner_width().unwrap().as_f64().unwrap();
|
||||
dervice_context.set(width.into());
|
||||
let closure = Closure::wrap(Box::new(move |_: Event| {
|
||||
let width = window.inner_width().unwrap().as_f64().unwrap();
|
||||
dervice_context.set(width.into());
|
||||
}) as Box<dyn FnMut(Event)>);
|
||||
let window = web_sys::window().unwrap();
|
||||
window
|
||||
.add_event_listener_with_callback("resize", closure.as_ref().unchecked_ref())
|
||||
.unwrap();
|
||||
closure.forget();
|
||||
});
|
||||
|
||||
use_effect(move || {
|
||||
let _ = set_element_dataset("html", "theme", &theme);
|
||||
|
@ -10,3 +10,4 @@ rocket = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
surrealdb = { workspace = true }
|
||||
rocket_cors = { workspace = true }
|
||||
|
@ -2,9 +2,8 @@ mod db;
|
||||
mod utils;
|
||||
|
||||
use db::Database;
|
||||
use rocket::{get, routes, State};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use rocket::{get, http::Method, routes};
|
||||
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors, CorsOptions};
|
||||
|
||||
use utils::error::CustomResult;
|
||||
|
||||
@ -13,15 +12,29 @@ fn index() -> &'static str {
|
||||
"Hello, world!"
|
||||
}
|
||||
|
||||
#[get("/api/theme")]
|
||||
fn get_theme() -> &'static str {
|
||||
"light"
|
||||
}
|
||||
|
||||
pub struct AppState {
|
||||
db: Database,
|
||||
}
|
||||
|
||||
fn cors() -> Cors {
|
||||
CorsOptions {
|
||||
allowed_origins: AllowedOrigins::all(),
|
||||
allowed_methods: vec![Method::Get, Method::Post, Method::Options]
|
||||
.into_iter()
|
||||
.map(From::from)
|
||||
.collect(),
|
||||
allowed_headers: AllowedHeaders::all(),
|
||||
allow_credentials: true,
|
||||
expose_headers: Default::default(),
|
||||
max_age: None,
|
||||
send_wildcard: false,
|
||||
fairing_route_base: "/".to_string(),
|
||||
fairing_route_rank: 0,
|
||||
}
|
||||
.to_cors()
|
||||
.expect("CORS配置错误")
|
||||
}
|
||||
|
||||
#[rocket::main]
|
||||
async fn main() -> CustomResult<()> {
|
||||
let rocket_build = rocket::build();
|
||||
@ -29,8 +42,9 @@ async fn main() -> CustomResult<()> {
|
||||
let db = Database::link().await?;
|
||||
|
||||
let rocket = rocket_build
|
||||
.mount("/", routes![index, get_theme])
|
||||
.mount("/", routes![index])
|
||||
.manage(AppState { db })
|
||||
.attach(cors())
|
||||
.ignite()
|
||||
.await?;
|
||||
rocket.launch().await?;
|
||||
|
Loading…
Reference in New Issue
Block a user