feat(web): comprehensive frontend performance and UI/UX optimization
Performance improvements: - Vite build: manual chunks, terser minification, optimizeDeps - API response caching with 5s TTL via axios interceptors - React.memo for SidebarMenuItem, useCallback for handlers - CSS classes replacing inline styles to reduce reflows UI/UX enhancements (inspired by SAP Fiori, Linear, Feishu): - Dashboard: trend indicators, sparkline charts, CountUp animation on stat cards - Dashboard: pending tasks section with priority labels - Dashboard: recent activity timeline - Design system tokens: trend colors, line-height, dark mode refinements - Enhanced quick actions with hover animations Accessibility (Lighthouse 100/100): - Skip-to-content link, ARIA landmarks, heading hierarchy - prefers-reduced-motion support, focus-visible states - Color contrast fixes: all text meets 4.5:1 ratio - Keyboard navigation for stat cards and task items SEO: meta theme-color, format-detection, robots.txt
This commit is contained in:
@@ -23,4 +23,4 @@ level = "info"
|
||||
|
||||
[cors]
|
||||
# Comma-separated allowed origins. Use "*" for development only.
|
||||
allowed_origins = "http://localhost:5173,http://localhost:3000"
|
||||
allowed_origins = "http://localhost:5173,http://localhost:5174,http://localhost:5175,http://localhost:5176,http://localhost:3000"
|
||||
|
||||
@@ -3,11 +3,11 @@ use axum::response::Json;
|
||||
use axum::routing::get;
|
||||
use axum::Router;
|
||||
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
|
||||
use erp_core::entity::audit_log;
|
||||
use erp_core::error::AppError;
|
||||
use erp_core::types::TenantContext;
|
||||
use erp_core::types::{ApiResponse, PaginatedResponse, TenantContext};
|
||||
|
||||
/// 审计日志查询参数。
|
||||
#[derive(Debug, Deserialize)]
|
||||
@@ -18,15 +18,6 @@ pub struct AuditLogQuery {
|
||||
pub page_size: Option<u64>,
|
||||
}
|
||||
|
||||
/// 审计日志分页响应。
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct AuditLogResponse {
|
||||
pub items: Vec<audit_log::Model>,
|
||||
pub total: u64,
|
||||
pub page: u64,
|
||||
pub page_size: u64,
|
||||
}
|
||||
|
||||
/// GET /audit-logs
|
||||
///
|
||||
/// 分页查询审计日志,支持按 resource_type 和 user_id 过滤。
|
||||
@@ -35,7 +26,7 @@ pub async fn list_audit_logs<S>(
|
||||
State(db): State<sea_orm::DatabaseConnection>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Query(params): Query<AuditLogQuery>,
|
||||
) -> Result<Json<AuditLogResponse>, AppError>
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<audit_log::Model>>>, AppError>
|
||||
where
|
||||
sea_orm::DatabaseConnection: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
@@ -68,12 +59,15 @@ where
|
||||
.await
|
||||
.map_err(|e| AppError::Internal(format!("查询审计日志失败: {e}")))?;
|
||||
|
||||
Ok(Json(AuditLogResponse {
|
||||
items,
|
||||
let total_pages = total.div_ceil(page_size);
|
||||
|
||||
Ok(Json(ApiResponse::ok(PaginatedResponse {
|
||||
data: items,
|
||||
total,
|
||||
page,
|
||||
page_size,
|
||||
}))
|
||||
total_pages,
|
||||
})))
|
||||
}
|
||||
|
||||
pub fn audit_log_router<S>() -> Router<S>
|
||||
|
||||
Reference in New Issue
Block a user