后端:新增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",
|
"type": "shell",
|
||||||
"command": "serve .",
|
"command": "serve .",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/client/target/dx/client/release/web/public"
|
"cwd": "${workspaceFolder}/target/dx/client/release/web/public"
|
||||||
},
|
},
|
||||||
"problemMatcher": []
|
"problemMatcher": []
|
||||||
},
|
},
|
||||||
|
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -3632,6 +3632,23 @@ dependencies = [
|
|||||||
"version_check",
|
"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]]
|
[[package]]
|
||||||
name = "rocket_http"
|
name = "rocket_http"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@ -3988,6 +4005,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"common",
|
"common",
|
||||||
"rocket",
|
"rocket",
|
||||||
|
"rocket_cors",
|
||||||
"serde",
|
"serde",
|
||||||
"surrealdb",
|
"surrealdb",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -4984,6 +5002,16 @@ version = "2.8.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
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]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
@ -19,6 +19,7 @@ rocket = "0.5.0"
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tokio = { version = "1.0", features = ["full"] }
|
tokio = { version = "1.0", features = ["full"] }
|
||||||
surrealdb = "2.1.4"
|
surrealdb = "2.1.4"
|
||||||
|
rocket_cors = "0.6.0"
|
||||||
|
|
||||||
[profile]
|
[profile]
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -10,14 +10,9 @@ html[data-theme="dark"]{
|
|||||||
background-color:black;
|
background-color:black;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'AlimamaTi';
|
|
||||||
src: url('/assets/fonts/AlimamaFangYuanTiVF.ttf') format('truetype');
|
|
||||||
font-display: swap;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
html {
|
||||||
overflow-x:hidden;
|
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: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-5 {
|
|
||||||
top: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.top-\[0\.06rem\] {
|
.top-\[0\.06rem\] {
|
||||||
top: 0.06rem;
|
top: 0.06rem;
|
||||||
}
|
}
|
||||||
@ -631,10 +627,6 @@ video {
|
|||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-1 {
|
.h-1 {
|
||||||
height: 0.25rem;
|
height: 0.25rem;
|
||||||
}
|
}
|
||||||
@ -667,14 +659,14 @@ video {
|
|||||||
min-width: 0px;
|
min-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.min-w-7 {
|
|
||||||
min-width: 1.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-shrink-0 {
|
.flex-shrink-0 {
|
||||||
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 {
|
@keyframes slide-in {
|
||||||
0% {
|
0% {
|
||||||
transform: translateX(100%);
|
transform: translateX(100%);
|
||||||
@ -727,8 +719,8 @@ video {
|
|||||||
gap: 0.25rem;
|
gap: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gap-10 {
|
.gap-5 {
|
||||||
gap: 2.5rem;
|
gap: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.justify-self-start {
|
.justify-self-start {
|
||||||
@ -739,12 +731,20 @@ video {
|
|||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.truncate {
|
.truncate {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.whitespace-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
.rounded {
|
.rounded {
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
@ -832,8 +832,9 @@ video {
|
|||||||
background-color: rgb(148 163 184 / var(--tw-bg-opacity, 1));
|
background-color: rgb(148 163 184 / var(--tw-bg-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-2 {
|
.px-2 {
|
||||||
padding: 0.5rem;
|
padding-left: 0.5rem;
|
||||||
|
padding-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.px-3 {
|
.px-3 {
|
||||||
@ -906,6 +907,10 @@ video {
|
|||||||
transition-duration: 150ms;
|
transition-duration: 150ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.duration-150 {
|
||||||
|
transition-duration: 150ms;
|
||||||
|
}
|
||||||
|
|
||||||
.duration-200 {
|
.duration-200 {
|
||||||
transition-duration: 200ms;
|
transition-duration: 200ms;
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,37 @@
|
|||||||
use super::Toggle;
|
use super::Toggle;
|
||||||
|
use crate::DeviceProvider;
|
||||||
use crate::Route;
|
use crate::Route;
|
||||||
use dioxus::{logger::tracing, prelude::*};
|
use dioxus::{logger::tracing, prelude::*};
|
||||||
|
use global_attributes::dangerous_inner_html;
|
||||||
use wasm_bindgen::{prelude::Closure, JsCast};
|
use wasm_bindgen::{prelude::Closure, JsCast};
|
||||||
|
use web_sys::Event;
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub fn Navbar() -> Element {
|
pub fn Navbar() -> Element {
|
||||||
let mut progress_signal = use_signal(|| 0);
|
let mut progress_signal = use_signal(|| 0);
|
||||||
let mut progress_hover = use_signal(|| false);
|
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 || {
|
use_effect(move || {
|
||||||
let window = web_sys::window().unwrap();
|
let window = web_sys::window().unwrap();
|
||||||
let document = window.document().unwrap();
|
let document = window.document().unwrap();
|
||||||
let document_element = document.document_element().unwrap();
|
let document_element = document.document_element().unwrap();
|
||||||
|
|
||||||
let closure: Closure<dyn FnMut(_)> = {
|
let closure = Closure::wrap(Box::new(move |_: Event| {
|
||||||
Closure::wrap(Box::new(move |_: web_sys::Event| {
|
let screen_height = document_element.scroll_height() as f64;
|
||||||
let screen_height = document_element.scroll_height() as f64;
|
let inner_height = window.inner_height().unwrap().as_f64().unwrap();
|
||||||
let inner_height = window.inner_height().unwrap().as_f64().unwrap();
|
let scroll_height = window.scroll_y().unwrap();
|
||||||
let scrool_height = window.scroll_y().unwrap();
|
let max_scroll_height = screen_height - inner_height;
|
||||||
let max_scroll_height = screen_height - inner_height;
|
|
||||||
|
|
||||||
let percent = if max_scroll_height > 0.0 {
|
let percent = if max_scroll_height > 0.0 {
|
||||||
scrool_height / max_scroll_height
|
scroll_height / max_scroll_height
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
let percent = (percent.clamp(0.0, 1.0) * 100.0) as i32;
|
let percent = (percent.clamp(0.0, 1.0) * 100.0) as i32;
|
||||||
progress_signal.set(percent);
|
progress_signal.set(percent);
|
||||||
}) as Box<dyn FnMut(_)>)
|
}) as Box<dyn FnMut(Event)>);
|
||||||
};
|
|
||||||
|
|
||||||
document
|
document
|
||||||
.add_event_listener_with_callback("scroll", closure.as_ref().unchecked_ref())
|
.add_event_listener_with_callback("scroll", closure.as_ref().unchecked_ref())
|
||||||
@ -38,6 +39,8 @@ pub fn Navbar() -> Element {
|
|||||||
closure.forget();
|
closure.forget();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let tp = r#"<div>hello,world</div>"#;
|
||||||
|
|
||||||
rsx! {
|
rsx! {
|
||||||
nav {
|
nav {
|
||||||
class: "border-red-500 bg-slate-400 text-xl fixed top-0 left-0 right-0",
|
class: "border-red-500 bg-slate-400 text-xl fixed top-0 left-0 right-0",
|
||||||
@ -51,11 +54,7 @@ pub fn Navbar() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
class:"flex gap-10 justify-center",
|
class:"flex gap-5 justify-center",
|
||||||
Link {
|
|
||||||
to: Route::Home {},
|
|
||||||
"首页"
|
|
||||||
}
|
|
||||||
Link {
|
Link {
|
||||||
to: Route::Home {},
|
to: Route::Home {},
|
||||||
"首页"
|
"首页"
|
||||||
@ -64,6 +63,10 @@ pub fn Navbar() -> Element {
|
|||||||
to: Route::Home {},
|
to: Route::Home {},
|
||||||
"首页"
|
"首页"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
div{
|
||||||
|
dangerous_inner_html:"{tp}"
|
||||||
}
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
|
@ -222,7 +222,7 @@ pub fn Notification() -> Element {
|
|||||||
|
|
||||||
return rsx! {
|
return rsx! {
|
||||||
div {
|
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| {
|
{notifications.notifications.iter().map(move |item| {
|
||||||
rsx! {
|
rsx! {
|
||||||
NotificationCard {
|
NotificationCard {
|
||||||
|
@ -3,12 +3,12 @@ use wasm_bindgen::{prelude::Closure, JsCast};
|
|||||||
mod components;
|
mod components;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod views;
|
mod views;
|
||||||
use crate::utils::error::CustomResult;
|
|
||||||
use components::notification::{Notification, NotificationProvider};
|
use components::notification::{Notification, NotificationProvider};
|
||||||
use components::theme_toggle::{get_theme, ThemeProvider};
|
use components::theme_toggle::{get_theme, ThemeProvider};
|
||||||
use components::Navbar;
|
use components::Navbar;
|
||||||
use utils::dom::{get_media_theme, set_element_dataset};
|
use utils::dom::{get_media_theme, set_element_dataset};
|
||||||
use views::Home;
|
use views::Home;
|
||||||
|
use web_sys::Event;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Routable, PartialEq)]
|
#[derive(Debug, Clone, Routable, PartialEq)]
|
||||||
enum Route {
|
enum Route {
|
||||||
@ -22,6 +22,42 @@ const FAVICON: Asset = asset!("/assets/favicon.ico");
|
|||||||
const GLOBAL_CSS: Asset = asset!("/assets/styling/global.css");
|
const GLOBAL_CSS: Asset = asset!("/assets/styling/global.css");
|
||||||
const TAILWIND_CSS: Asset = asset!("/assets/styling/tailwind.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() {
|
fn main() {
|
||||||
dioxus::launch(App);
|
dioxus::launch(App);
|
||||||
}
|
}
|
||||||
@ -31,7 +67,24 @@ fn App() -> Element {
|
|||||||
let theme = get_theme();
|
let theme = get_theme();
|
||||||
use_context_provider(|| Signal::new(ThemeProvider(theme.clone())));
|
use_context_provider(|| Signal::new(ThemeProvider(theme.clone())));
|
||||||
use_context_provider(|| Signal::new(NotificationProvider::default()));
|
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 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 || {
|
use_effect(move || {
|
||||||
let _ = set_element_dataset("html", "theme", &theme);
|
let _ = set_element_dataset("html", "theme", &theme);
|
||||||
|
@ -10,3 +10,4 @@ rocket = { workspace = true }
|
|||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
surrealdb = { workspace = true }
|
surrealdb = { workspace = true }
|
||||||
|
rocket_cors = { workspace = true }
|
||||||
|
@ -2,9 +2,8 @@ mod db;
|
|||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use db::Database;
|
use db::Database;
|
||||||
use rocket::{get, routes, State};
|
use rocket::{get, http::Method, routes};
|
||||||
use serde::{Deserialize, Serialize};
|
use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors, CorsOptions};
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use utils::error::CustomResult;
|
use utils::error::CustomResult;
|
||||||
|
|
||||||
@ -13,15 +12,29 @@ fn index() -> &'static str {
|
|||||||
"Hello, world!"
|
"Hello, world!"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/api/theme")]
|
|
||||||
fn get_theme() -> &'static str {
|
|
||||||
"light"
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
db: Database,
|
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]
|
#[rocket::main]
|
||||||
async fn main() -> CustomResult<()> {
|
async fn main() -> CustomResult<()> {
|
||||||
let rocket_build = rocket::build();
|
let rocket_build = rocket::build();
|
||||||
@ -29,8 +42,9 @@ async fn main() -> CustomResult<()> {
|
|||||||
let db = Database::link().await?;
|
let db = Database::link().await?;
|
||||||
|
|
||||||
let rocket = rocket_build
|
let rocket = rocket_build
|
||||||
.mount("/", routes![index, get_theme])
|
.mount("/", routes![index])
|
||||||
.manage(AppState { db })
|
.manage(AppState { db })
|
||||||
|
.attach(cors())
|
||||||
.ignite()
|
.ignite()
|
||||||
.await?;
|
.await?;
|
||||||
rocket.launch().await?;
|
rocket.launch().await?;
|
||||||
|
Loading…
Reference in New Issue
Block a user