项目导览
大约 3 分钟
项目导览
本页带你快速认识后端与前端的目录结构、关键入口与常见开发路径(新增模块/路由/权限/前端菜单)。
后端结构
qiluo/
├── 📁 config/ # 配置文件
├── 📁 data/ # 数据存储目录
│ ├── 📁 img/ # 图片资源
│ ├── 📁 log/ # 日志文件
│ ├── 📁 static/ # 静态资源
│ ├── 📁 upload/ # 上传文件
│ └── 📁 web/ # 前端文件
├── 📁 migration/ # 数据库迁移
├── 📁 src/ # 源代码
│ ├── 📁 api/ # API 控制器
│ │ ├── 📁 sys_controll/ # 系统管理接口
│ │ └── 📁 wechat/ # 微信接口
│ ├── 📁 cache/ # 缓存管理
│ ├── 📁 common/ # 公共模块
│ ├── 📁 config/ # 配置模块
│ ├── 📁 midle_ware/ # 中间件
│ ├── 📁 model/ # 数据模型
│ ├── 📁 service/ # 业务服务
│ └── 📁 worker/ # 后台任务
└── 📄 Cargo.toml # 项目配置
- 入口 main.rs:App::run().await 初始化配置、日志、数据库连接、AppState,启动 Axum 服务
- app.rs:注册路由、挂载中间件、版本化
- middleware:请求 ID、Trace 日志、CORS、JWT 鉴权、RBAC 权限、限流等
- system:统一日志、定时任务、雪花 ID
lib.rs 模块组织(片段)
pub mod api;
pub mod service;
mod db;
pub mod model;
pub mod cache;
pub mod config;
pub mod common;
pub mod app;
pub mod midle_ware;
pub mod worker;
pub use db::db as DB;
pub use db::generator_id as GID;
pub mod banner;
统一响应与错误(片段)
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
Message(String),
WithStatus(StatusCode, String)
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ApiResponse<T> {
pub message: String,
pub data: T
}
路由与中间件(片段)
fn configure_middlewares(&self, mut app: Router) -> Router {
let serverconfig = APPCOFIG.server.clone();
// CORS配置
app = app.layer(self.configure_cors(&serverconfig));
// Payload限制
if let Some(limit) = serverconfig.middlewares.limit_payload.clone() {
if limit.enable {
if let Ok(size) = byte_unit::Byte::parse_str(&limit.body_limit, true) {
app = app.layer(axum::extract::DefaultBodyLimit::max(size.as_u64() as usize));
tracing::info!(
data = &limit.body_limit,
"[Middleware] Adding limit payload"
);
}
}
}
// Panic处理
if let Some(catch_panic) = serverconfig.middlewares.catch_panic {
if catch_panic.enable {
app = app.layer(CatchPanicLayer::custom(Self::handle_panic));
}
}
// 压缩
if let Some(compression) = serverconfig.middlewares.compression.clone() {
if compression.enable {
let predicate =
DefaultPredicate::new().and(NotForContentType::new("text/event-stream"));
app = app.layer(CompressionLayer::new().compress_when(predicate));
tracing::info!("[Middleware] Adding compression layer");
}
}
// 超时
if let Some(timeout_request) = serverconfig.middlewares.timeout_request {
if timeout_request.enable {
app = app.layer(TimeoutLayer::new(Duration::from_millis(
timeout_request.timeout,
)));
tracing::info!("[Middleware] Adding timeout layer");
}
}
app
}
impl WebApi {
pub fn routers() -> Router {
let mut webpath = WebPath::new();
webpath = webpath.merge(sys_controll::router_sys());
webpath = webpath.final_to_path();
let expand_path = webpath.get_last_level_paths();
let invfun = InvokeFunctionMsg {
job_id: None,
callfun: "updateapi".to_owned(),
parmets: serde_json::to_string(&expand_path).unwrap(),
};
tokio::spawn(async move {
let _ = InvokeFunctionWorker::execute_async(invfun).await;
});
let mut router = Router::new();
for p in expand_path {
if let Some(method_router) = p.method_router.clone() {
router = router.route(&p.final_path, method_router);
}
}
Router::new().merge(router)
}
pub fn white_routers() -> Router {
Router::new().merge(sys_controll::white_sys())
}
}
前端结构(示例)
qiluo_vue/
├── 📁 public/ # Static resources directory
├── 📁 src/ # Source code directory
│ ├── 📁 api/ # API interface definitions
│ ├── 📁 assets/ # Project resource files
│ ├── 📁 axios/ # Axios request configuration
│ ├── 📁 components/ # Common components
│ ├── 📁 constants/ # Constant definitions
│ ├── 📁 directives/ # Custom directives
│ ├── 📁 hooks/ # Custom Hooks
│ ├── 📁 layout/ # Layout components
│ ├── 📁 locales/ # Internationalization resources
│ ├── 📁 plugins/ # Plugin configurations
│ ├── 📁 router/ # Routing configuration
│ ├── 📁 store/ # State management
│ ├── 📁 styles/ # Style files
│ ├── 📁 utils/ # Utility functions
│ ├── 📁 views/ # Page views
│ ├── 📄 App.vue # Root component
│ ├── 📄 main.ts # Application entry file
│ └── 📄 permission.ts # Permission control
├── 📁 types/ # TypeScript type definitions
├── 📄 index.html # HTML template
├── 📄 package.json # Project dependencies
└── 📄 vite.config.ts # Vite configuration
- 动态菜单:登录后从后端获取菜单树,生成路由
- 按钮权限:permission_code + v-permission 控制显示
- API 拦截:自动注入 Authorization Bearer Token,统一错误提示
新增一个业务模块的标准流程(示例:文章 Article)
- 数据库与实体
sea-orm-cli migrate generate create_article
# 在迁移中定义字段(id/title/content/status/created_at...)
sea-orm-cli migrate up
sea-orm-cli generate entity -o src/db/entities
- Service
pub struct ArticleService { pub db: sea_orm::DatabaseConnection }
impl ArticleService {
pub async fn list(&self) -> anyhow::Result<Vec<ArticleVO>> { /* ... */ Ok(vec![]) }
pub async fn create(&self, req: CreateArticleReq) -> anyhow::Result<ArticleVO> { /* ... */ Ok(/*...*/) }
}
// handlers/article_handler.rs(示意)
pub async fn list(State(state): State<AppState>) -> Json<ApiResponse<Vec<ArticleVO>>> {
let items = state.services.article.list().await?;
Json(ApiResponse::ok(items))
}
- 路由与权限编码
// app.rs(片段)
.nest("/content",
axum::Router::new()
.route("/articles", get(article_handler::list).post(article_handler::create))
.route_layer(axum::middleware::from_fn(mw::auth::require_auth))
)
// 在权限系统中注册:content:article:list、content:article:create
配置与环境
- 基于 config/development.yaml
下一步
- 进入“基础 → 路由 / 中间件 / 控制器 / 请求与响应”,快速上手增删改查
- 进入“Sea-ORM → 简介 / 模型查询 / 关联关系”,深入数据库访问
- 进入“深入探究 → 任务/队列/缓存/文件存储”,完善系统能力