# zssport1
**Repository Path**: llisten1421/zssport1
## Basic Information
- **Project Name**: zssport1
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-07-03
- **Last Updated**: 2026-07-03
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# ZSSport
ZSSport 是一个基于 ASP.NET Core 的 Web API 项目,使用 SqlSugar 访问 MySQL,使用 Scalar 展示接口文档,项目启动时会根据 `Models` 类库中带 `[SugarTable]` 的实体自动创建数据库表。
本文档面向新加入项目的开发同学,重点说明项目结构、开发约定,以及如何编写一个新接口。
## 项目结构
```text
ZSSport
├─ ZSSport.slnx # 解决方案文件
├─ ZSSport # Web API 主项目
│ ├─ Controllers # 接口控制器
│ │ ├─ ApiControllerBase.cs # API 控制器基类,统一路由、鉴权和返回格式
│ │ └─ ExampleController.cs # 示例增删改查接口
│ ├─ Models # 接口请求参数 DTO,不放数据库实体
│ │ └─ ExampleInputs.cs # 示例接口请求参数
│ ├─ Extentions # 项目启动、服务注册、JWT、数据库初始化扩展
│ │ ├─ Extension.ServiceCollection.cs
│ │ ├─ Extension.Database.cs
│ │ └─ Extension.Jwt.cs
│ ├─ appsettings.json # 配置文件,包含数据库连接、JWT、跨域等配置
│ └─ Program.cs # 应用启动入口
├─ Models # 数据库实体类库
│ └─ ExampleInfo.cs # 示例数据库实体
└─ Shared # 公共类库
├─ Primitives # 统一响应模型
├─ Filters # JWT 过滤器等
├─ Exceptions # 全局异常处理
├─ Extensions # Serilog、跨域、静态文件等扩展
├─ Helper # 工具 Helper
└─ Util # 通用工具类
```
## 运行环境
- .NET 10
- MySQL
- SqlSugarCore
- Scalar.AspNetCore
- Serilog
数据库连接在 `ZSSport/appsettings.json`:
```json
{
"ConnectionStrings": {
"DefaultConnection": "Server=192.168.1.86;Port=3306;Database=zs_sport;Uid=root;Pwd=你的密码;"
}
}
```
启动项目后,开发环境会打开 OpenAPI/Scalar 文档:
```text
/scalar
```
## 重要约定
### 1. Controller 必须继承 ApiControllerBase
所有业务接口 Controller 都放在 `ZSSport/Controllers` 下,并继承:
```csharp
public class XxxController : ApiControllerBase
```
`ApiControllerBase` 已经统一配置:
```csharp
[Route("api/[controller]/[Action]")]
[ApiController]
[Authorize]
[JwtAuthorizeFilter]
```
因此接口地址规则是:
```text
api/控制器名/方法名
```
例如:
```text
api/Example/GetList
api/Example/Create
```
### 2. 只使用 GET 和 POST
本项目接口只允许使用:
```csharp
[HttpGet]
[HttpPost]
```
查询类接口使用 `GET`,新增、修改、删除使用 `POST`。
### 3. POST 参数使用 [FromBody]
POST 接口统一使用 JSON body:
```csharp
public IActionResult Create([FromBody] ExampleCreateInput input)
```
请求时必须设置:
```http
Content-Type: application/json
```
请求示例:
```json
{
"name": "测试",
"remark": "备注"
}
```
### 4. 请求参数类放到 ZSSport/Models
接口请求参数 DTO 放在 `ZSSport/Models` 下,不要写在 Controller 文件底部。
命名建议:
```text
XxxCreateInput
XxxUpdateInput
XxxDeleteInput
XxxQueryInput
```
### 5. 数据库实体放到 Models 类库
数据库表实体放在根目录的 `Models` 类库中。
只有带 `[SugarTable]` 的类才会被认为是数据库表实体,项目启动时才会参与自动建表。
```csharp
[SugarTable("example_info", "示例信息表")]
public class ExampleInfo
{
[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键编号")]
public int Id { get; set; }
}
```
### 6. 表和字段必须写中文备注
实体类必须写:
- XML 中文注释
- `[SugarTable]` 表备注
- `[SugarColumn]` 字段备注
这样接口文档和数据库都能看到清楚说明。
### 7. 接口必须写中文 XML 注释
Controller、Action、参数类、参数属性都要写中文 XML 注释。
项目已开启 XML 文档生成,注释会进入接口文档。
## 如何新增一个接口
下面以“商品”接口为例,演示完整开发流程。
### 第一步:新增数据库实体
在 `Models` 类库中新建:
```text
Models/ProductInfo.cs
```
示例:
```csharp
using SqlSugar;
namespace Models;
///
/// 商品信息
///
[SugarTable("product_info", "商品信息表")]
public class ProductInfo
{
///
/// 主键编号
///
[SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键编号")]
public int Id { get; set; }
///
/// 商品名称
///
[SugarColumn(Length = 100, IsNullable = false, ColumnDescription = "商品名称")]
public string Name { get; set; } = string.Empty;
///
/// 商品价格
///
[SugarColumn(ColumnDescription = "商品价格")]
public decimal Price { get; set; }
///
/// 创建时间
///
[SugarColumn(ColumnDescription = "创建时间")]
public DateTime CreateTime { get; set; } = DateTime.Now;
}
```
注意:
- 必须有 `[SugarTable]`
- 必须有表中文备注
- 每个字段建议都有 `[SugarColumn(ColumnDescription = "...")]`
- 主键自增使用 `IsPrimaryKey = true, IsIdentity = true`
### 第二步:新增请求参数 DTO
在 `ZSSport/Models` 下新建:
```text
ZSSport/Models/ProductInputs.cs
```
示例:
```csharp
namespace ZSSport.Models;
///
/// 新增商品请求参数
///
public class ProductCreateInput
{
///
/// 商品名称
///
public string Name { get; set; } = string.Empty;
///
/// 商品价格
///
public decimal Price { get; set; }
}
///
/// 修改商品请求参数
///
public class ProductUpdateInput : ProductCreateInput
{
///
/// 商品编号
///
public int Id { get; set; }
}
///
/// 删除商品请求参数
///
public class ProductDeleteInput
{
///
/// 商品编号
///
public int Id { get; set; }
}
```
注意:
- DTO 只描述接口请求参数
- DTO 不要加 `[SugarTable]`
- DTO 不要放进 `Models` 类库,否则容易和数据库实体混淆
### 第三步:新增 Controller
在 `ZSSport/Controllers` 下新建:
```text
ZSSport/Controllers/ProductController.cs
```
示例:
```csharp
using Models;
using SqlSugar;
using ZSSport.Models;
namespace WebApi.Controllers;
///
/// 商品管理
///
public class ProductController : ApiControllerBase
{
private readonly ISqlSugarClient _db;
///
/// 初始化商品管理控制器
///
/// 日志组件
/// 数据库客户端
public ProductController(ILogger logger, ISqlSugarClient db) : base(logger)
{
_db = db;
}
///
/// 获取商品列表
///
/// 商品列表
[HttpGet]
public IActionResult GetList()
{
var list = _db.Queryable()
.OrderByDescending(item => item.Id)
.ToList();
return Success(list);
}
///
/// 获取商品详情
///
/// 商品编号
/// 商品详情
[HttpGet]
public IActionResult Get(int id)
{
var entity = _db.Queryable()
.First(item => item.Id == id);
if (entity is null)
{
return Error("数据不存在。");
}
return Success(entity);
}
///
/// 新增商品
///
/// 新增商品请求参数
/// 操作结果
[HttpPost]
public IActionResult Create([FromBody] ProductCreateInput input)
{
if (string.IsNullOrWhiteSpace(input.Name))
{
return Error("商品名称不能为空。");
}
var entity = new ProductInfo
{
Name = input.Name.Trim(),
Price = input.Price,
CreateTime = DateTime.Now
};
_db.Insertable(entity).ExecuteCommand();
return Success("新增成功!");
}
///
/// 修改商品
///
/// 修改商品请求参数
/// 操作结果
[HttpPost]
public IActionResult Update([FromBody] ProductUpdateInput input)
{
if (input.Id <= 0)
{
return Error("商品编号无效。");
}
if (string.IsNullOrWhiteSpace(input.Name))
{
return Error("商品名称不能为空。");
}
var rows = _db.Updateable()
.SetColumns(item => item.Name == input.Name.Trim())
.SetColumns(item => item.Price == input.Price)
.Where(item => item.Id == input.Id)
.ExecuteCommand();
return rows > 0 ? Success("修改成功!") : Error("数据不存在。");
}
///
/// 删除商品
///
/// 删除商品请求参数
/// 操作结果
[HttpPost]
public IActionResult Delete([FromBody] ProductDeleteInput input)
{
if (input.Id <= 0)
{
return Error("商品编号无效。");
}
var rows = _db.Deleteable()
.Where(item => item.Id == input.Id)
.ExecuteCommand();
return rows > 0 ? Success("删除成功!") : Error("数据不存在。");
}
}
```
### 第四步:确认接口地址
根据项目统一路由:
```csharp
[Route("api/[controller]/[Action]")]
```
商品接口地址为:
```text
GET api/Product/GetList
GET api/Product/Get?id=1
POST api/Product/Create
POST api/Product/Update
POST api/Product/Delete
```
### 第五步:启动项目并检查接口文档
运行:
```bash
dotnet build
dotnet run --project ZSSport
```
开发环境访问 Scalar 文档:
```text
/scalar
```
如果新增接口、参数说明没有显示:
1. 确认 Controller、Action、DTO、DTO 属性都有 `/// `
2. 确认项目已重新编译
3. 重启项目
4. 刷新 Scalar 页面
## 自动建库建表说明
项目启动时会执行:
```csharp
app.UseModelsCodeFirst();
```
逻辑在:
```text
ZSSport/Extentions/Extension.Database.cs
```
规则:
- 从 `DefaultConnection` 读取数据库连接字符串
- 如果数据库不存在,则自动创建
- 扫描 `Models` 类库
- 只有带 `[SugarTable]` 的实体才会自动建表
- 调用 SqlSugar CodeFirst 创建表
注意:
- 普通 DTO 不要放到 `Models` 类库
- 不带 `[SugarTable]` 的类不会建表
- 已存在的表不一定会自动同步字段备注,必要时需要手动迁移或重建表
## 统一返回格式
Controller 继承 `ApiControllerBase` 后,可以直接使用:
```csharp
return Success();
return Success(data);
return Success("操作成功!");
return Error("错误提示");
```
成功响应基础结构:
```json
{
"success": true,
"responseTime": "2026-06-29 15:30:00",
"code": 1,
"msg": "请求成功!",
"data": {}
}
```
失败响应基础结构:
```json
{
"success": false,
"responseTime": "2026-06-29 15:30:00",
"code": 0,
"msg": "错误提示"
}
```
## 鉴权说明
`ApiControllerBase` 默认带:
```csharp
[Authorize]
[JwtAuthorizeFilter]
```
所以业务接口默认需要 JWT。
如果某个接口临时允许匿名访问,可以在 Action 上加:
```csharp
[AllowAnonymous]
```
正式业务接口不要随意加匿名访问。
## 日志说明
项目使用 Serilog:
```text
Shared/Extensions/Extension.Serilog.cs
```
日志输出到:
- 控制台
- 本地日志文件
- MySQL 表 `log_serilogs`
首次启动时会自动创建日志表。
## 新人开发检查清单
新增接口提交前,请逐项确认:
- Controller 放在 `ZSSport/Controllers`
- Controller 继承 `ApiControllerBase`
- 只使用 `[HttpGet]` 或 `[HttpPost]`
- POST 参数使用 `[FromBody]`
- 请求 DTO 放在 `ZSSport/Models`
- 数据库实体放在 `Models` 类库
- 数据库实体必须有 `[SugarTable]`
- 表和字段都有中文备注
- Controller、Action、DTO、DTO 属性都有中文 XML 注释
- 返回值使用 `Success(...)` 或 `Error(...)`
- 执行过 `dotnet build`
- 在 Scalar 文档中确认接口说明和参数说明正常显示