# anycms-core
支持多种 Rust Web 框架的统一 API 响应库。
## 特性
- **框架无关的核心**:`ApiResult<T>` 结构独立于任何 Web 框架工作
- **多框架支持**:内置 actix-web 和 axum 集成
- **Feature flags**:按需使用 - 零未使用的依赖
- **灵活的响应格式**:支持单值、列表、分页、错误码和额外元数据
- **字段级验证错误**:`FieldError` 支持表单验证场景
- **请求追踪**:内置 `traceId` 字段,方便生产环境排查
## 安装
在 `Cargo.toml` 中添加:
```toml
[dependencies]
anycms-core = "0.4"
```
### Feature Flags
- `actix` (默认):启用 actix-web 集成
- `axum`:启用 axum 集成
- `full`:启用所有框架集成
#### 示例
```toml
# 默认(仅 actix-web)
anycms-core = "0.4"
# 仅 axum
anycms-core = { version = "0.4", features = ["axum"] }
# 两个框架都启用
anycms-core = { version = "0.4", features = ["full"] }
```
## 项目结构
```
src/
├── lib.rs # 库入口,带 feature 条件导出
├── result.rs # 核心 ApiResult<T>、错误类型、FieldError
├── pagination.rs # 分页元数据结构
└── frameworks/
├── mod.rs # 框架模块声明
├── actix.rs # actix-web 集成 (Responder trait)
└── axum.rs # axum 集成 (IntoResponse trait)
```
## 架构设计
该库采用清晰的关注点分离设计:
1. **核心层** ([result.rs](src/result.rs), [pagination.rs](src/pagination.rs))
- 包含数据结构和构建器方法
- 零框架依赖
- 无论启用哪个 feature 都会编译
2. **框架层** ([frameworks/](src/frameworks/))
- 实现框架特定的 trait
- 基于 feature flags 条件编译
- 相互隔离,避免冲突
## 使用方法
### 成功响应
```rust
use anycms_core::{ApiResult, ResultPagination};
// 单值
let result = ApiResult::value(user);
// 列表 + 分页
let result = ApiResult::list(users)
.with_pagination(ResultPagination::new(100, 1, 10))
.with_extra("has_more", serde_json::json!(true));
// 空响应
let result = ApiResult::<()>::ok();
```
### 错误响应
```rust
use anycms_core::{ApiResult, ApiError};
// 使用 ApiError
let result: ApiResult<User> = ApiError::not_found("用户不存在").into();
// 使用快捷方法
let result = ApiResult::<User>::fail("操作失败").with_code(500);
```
### 验证错误
```rust
use anycms_core::{ApiResult, FieldError};
// 一次性传入所有字段错误
let result: ApiResult<User> = ApiResult::validation_errors(vec![
FieldError::new("email", "格式不正确"),
FieldError::new("name", "不能为空"),
]);
// 或链式添加
let result = ApiResult::<User>::fail("验证失败")
.with_code(422)
.with_error("email", "格式不正确")
.with_error("name", "不能为空");
```
### 请求追踪
```rust
use anycms_core::ApiResult;
let result = ApiResult::<User>::fail("用户不存在")
.with_code(404)
.with_trace_id("req-abc123");
```
### 分页辅助方法
```rust
use anycms_core::ResultPagination;
let pagination = ResultPagination::new(95, 3, 10);
pagination.total_pages(); // 10
pagination.has_next(); // true
pagination.has_prev(); // true
```
### 框架集成
#### Actix-web
```rust
use actix_web::get;
use anycms_core::ApiResult;
#[get("/users/{id}")]
async fn get_user(path: web::Path<u32>) -> ApiResult<User> {
match find_user(path.into_inner()).await {
Some(user) => ApiResult::value(user),
None => ApiResult::<User>::fail("用户不存在").with_code(404),
}
}
```
#### Axum
```rust
use axum::extract::Path;
use anycms_core::ApiResult;
async fn get_user(Path(id): Path<u32>) -> ApiResult<User> {
match find_user(id).await {
Some(user) => ApiResult::value(user),
None => ApiResult::<User>::fail("用户不存在").with_code(404),
}
}
```
## API 响应格式
### 成功响应(单值)
```json
{
"success": true,
"data": { "id": 1, "name": "张三" }
}
```
### 成功响应(列表)
```json
{
"success": true,
"data": [
{ "id": 1, "name": "张三" },
{ "id": 2, "name": "李四" }
],
"pagination": {
"total": 100,
"page": 1,
"pageSize": 10,
"currentPage": 1
}
}
```
### 空成功响应
```json
{
"success": true
}
```
### 错误响应
```json
{
"success": false,
"message": "用户不存在",
"code": 404
}
```
### 验证错误响应
```json
{
"success": false,
"message": "Validation failed",
"code": 422,
"errors": [
{ "field": "email", "message": "格式不正确" },
{ "field": "name", "message": "不能为空" }
]
}
```
### 带追踪的错误响应
```json
{
"success": false,
"message": "用户不存在",
"code": 404,
"traceId": "req-abc123"
}
```
## 示例
运行演示示例:
```bash
# Actix-web 演示
cargo run --example actix_demo --features actix
# Axum 演示
cargo run --example axum_demo --features axum
# 检查示例
cargo check --examples --all-features
```
## 许可证
MIT