feat(photo-wall): 修复4个问题 + 特殊文件夹(共享公共相册) **照片墙修复:** - 右键菜单 z-index 40→9999,不再被元素遮挡 - 图片放大后强制重建 DOM(img key 绑定 w/h) - 右键菜单添加滑条调节旋转步长(1°-90°)和缩放步长(照片 px / 其他 scale) - Delete 键可删除右键菜单选中的元素(便签也能删) **特殊文件夹功能(按设计文档实现):** - 后端:FolderRegistry 解析 special_folders.txt 注册表 + FolderStore 按文件夹存图 - 后端:5 个接口(存在性检查/列表/上传/获取/删除),白名单 + 管理员鉴权 - 前端:App.tsx 按 hash 路由到特殊文件夹,复用 PhotoWallPage - 前端:文件夹模式无张数上限,localStorage 按文件夹隔离 - 前端:管理员配额警告条(超 1GiB 时显示) - 前端:403 无权访问时退回起始页 Co-Authored-By: Claude <noreply@anthropic.com> @
40 lines
1.2 KiB
Rust
40 lines
1.2 KiB
Rust
//! InternetProject 后端入口。
|
||
//!
|
||
//! 启动一个后台采样任务持续刷新系统指标,并对外提供 HTTP 接口:
|
||
//! - `GET /api/web/stats` 给 React 前端(挂 CORS)
|
||
//! - `GET /api/client/health` 给未来 .NET 客户端(不挂 CORS)
|
||
|
||
mod auth;
|
||
mod folders;
|
||
mod monitor;
|
||
mod photos;
|
||
mod routes;
|
||
mod state;
|
||
mod weather;
|
||
|
||
use std::net::SocketAddr;
|
||
|
||
use state::AppState;
|
||
|
||
#[tokio::main]
|
||
async fn main() {
|
||
let state = AppState::new();
|
||
|
||
// 后台每秒采样系统指标,写入共享快照。
|
||
tokio::spawn(monitor::run_sampler(state.clone()));
|
||
|
||
let app = routes::build_router(state);
|
||
|
||
let port = std::env::var("PORT").unwrap_or_else(|_| "8080".to_string());
|
||
let addr = format!("0.0.0.0:{port}");
|
||
let listener = tokio::net::TcpListener::bind(&addr)
|
||
.await
|
||
.unwrap_or_else(|_| panic!("无法绑定 {addr}"));
|
||
println!("backend listening on http://{addr}");
|
||
|
||
// 用 connect-info 让 handler 能拿到对端 socket 地址(天气接口要按访问者 IP 定位/限流)。
|
||
axum::serve(listener, app.into_make_service_with_connect_info::<SocketAddr>())
|
||
.await
|
||
.expect("server error");
|
||
}
|