fix: 修复20个列表接口返回格式与Mock不一致问题,新增5.2.1 Mock数据结构对齐规范

main
haoliang 1 week ago
parent a094e59ffc
commit 32a7bf49d0

@ -242,6 +242,48 @@ public class ApiResponse<T>
}
```
### 5.2.1 Mock数据结构对齐强制
> **核心原则:后端 API 返回的 `data` 内部结构必须严格匹配 Mock 文件中的定义。前端代码按 Mock 结构取值,后端返回格式不一致将导致前端取不到数据。**
#### 规则说明
1. **列表接口**Mock 返回 `{ code: 0, data: { items: [...], total: N, page: N, pageSize: N } }`,后端必须返回 `ApiResponse<PagedResult<T>>``PagedResult` 包含 `items/total/page/pageSize` 四个字段
2. **非分页列表接口**如车间下拉、品牌下拉等Mock 返回 `{ code: 0, data: { items: [...] } }`,后端必须返回 `ApiResponse<object>` 并将列表包装为 `new { items = list }`**禁止**直接返回 `ApiResponse<List<T>>`
3. **单对象接口**如详情、统计Mock 返回 `{ code: 0, data: { ... } }`,后端返回 `ApiResponse<T>` 即可
4. **写操作接口**(新增/编辑/删除Mock 返回 `{ code: 0, message: "success", data: null }``{ code: 0, data: { id: N } }`,后端保持一致
5. **字段名必须与 Mock 一致**:经 CamelCase 序列化后的 JSON 字段名必须与 Mock 中的 key 完全匹配
#### 错误示例与正确示例
```csharp
// ❌ 错误:直接返回 Listdata 变成数组,前端 r.data.items 为 undefined
return Ok(ApiResponse<List<WorkshopListItem>>.Success(result));
// JSON: { "code": 0, "data": [{...}, {...}] }
// ✅ 正确:包装为 items 对象,与 Mock 的 { data: { items: [...] } } 一致
return Ok(ApiResponse<object>.Success(new { items = result }));
// JSON: { "code": 0, "data": { "items": [{...}, {...}] } }
```
```csharp
// ❌ 错误PagedResult 的 Items 字段不匹配(虽然是 PagedResult
// 如果前端期望 { items, total, page, pageSize }PagedResult 字段名必须完全匹配
// 当前 PagedResult<T> 已定义为 Items/Total/Page/PageSize经 CamelCase 序列化为 items/total/page/pageSize ✅
// ✅ 分页列表直接返回 PagedResult 即可
return Ok(ApiResponse<PagedResult<MachineListItem>>.Success(result));
// JSON: { "code": 0, "data": { "items": [...], "total": 160, "page": 1, "pageSize": 20 } }
```
#### 检查方法
每个接口开发完成后,必须:
1. 打开对应的 Mock 文件(`frontend/mock/*.ts`),找到该 URL 的 `response` 定义
2. 确认 Mock 中 `data` 的结构(是 `{ items: [...] }` 还是 `{ ... }` 或是 `null`
3. 确认后端 `ApiResponse<T>` 中的 `T` 能序列化出相同结构
4. 如有差异,调整后端返回格式以匹配 Mock
### 5.3 异常处理
```csharp

@ -33,7 +33,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetList()
{
var result = _brandService.GetList();
return Ok(ApiResponse<List<BrandListItem>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -117,7 +118,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetStandardFields()
{
var result = _brandService.GetStandardFields();
return Ok(ApiResponse<List<StandardFieldResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
}
}

@ -46,7 +46,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetWorkshopProduction(DateTime? startDate = null, DateTime? endDate = null)
{
var result = _dashboardService.GetWorkshopProduction(startDate, endDate);
return Ok(ApiResponse<List<WorkshopProductionResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -58,7 +59,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetMachineRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10)
{
var result = _dashboardService.GetMachineRank(startDate, endDate, top);
return Ok(ApiResponse<List<MachineRankResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -70,7 +72,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetWorkerRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10)
{
var result = _dashboardService.GetWorkerRank(startDate, endDate, top);
return Ok(ApiResponse<List<WorkerRankResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -106,7 +109,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetRecentAlerts(int count = 5)
{
var result = _dashboardService.GetRecentAlerts(count);
return Ok(ApiResponse<List<AlertListItem>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>

@ -48,7 +48,8 @@ namespace CncWebApi.Controllers
{
var list = _workshopService.GetList(null);
var items = list.Select(w => new SimpleOption { Value = w.Id.ToString(), Label = w.Name }).ToList();
return Ok(ApiResponse<List<SimpleOption>>.Success(items));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items }));
}
/// <summary>
@ -61,7 +62,8 @@ namespace CncWebApi.Controllers
{
var list = _brandService.GetList();
var items = list.Select(b => new SimpleOption { Value = b.Id.ToString(), Label = b.BrandName }).ToList();
return Ok(ApiResponse<List<SimpleOption>>.Success(items));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items }));
}
/// <summary>
@ -75,7 +77,8 @@ namespace CncWebApi.Controllers
var query = new CncModels.Dto.Machine.MachineQuery { Page = 1, PageSize = 1000 };
var paged = _machineService.GetList(query);
var items = paged.Items.Select(m => new SimpleOption { Value = m.Id.ToString(), Label = m.Name ?? m.DeviceCode }).ToList();
return Ok(ApiResponse<List<SimpleOption>>.Success(items));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items }));
}
/// <summary>
@ -89,7 +92,8 @@ namespace CncWebApi.Controllers
var query = new CncModels.Dto.Worker.WorkerQuery { Page = 1, PageSize = 1000 };
var paged = _workerService.GetList(query);
var items = paged.Items.Select(w => new SimpleOption { Value = w.Id.ToString(), Label = w.Name + "(" + w.Code + ")" }).ToList();
return Ok(ApiResponse<List<SimpleOption>>.Success(items));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items }));
}
/// <summary>
@ -103,7 +107,8 @@ namespace CncWebApi.Controllers
var query = new CncModels.Dto.CollectAddress.CollectAddressQuery { Page = 1, PageSize = 1000 };
var paged = _collectAddressService.GetList(query);
var items = paged.Items.Select(a => new SimpleOption { Value = a.Id.ToString(), Label = a.Name }).ToList();
return Ok(ApiResponse<List<SimpleOption>>.Success(items));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items }));
}
}
}

@ -36,7 +36,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetConfigs()
{
var result = _screenService.GetConfigs();
return Ok(ApiResponse<List<ScreenConfig>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -94,7 +95,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetFilters(string screenKey = null)
{
var result = _screenService.GetFilters(screenKey ?? "main_screen");
return Ok(ApiResponse<List<ScreenFilter>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>

@ -64,7 +64,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetWorkshopProduction()
{
var result = _dashboardService.GetWorkshopProduction(null, null);
return Ok(ApiResponse<List<WorkshopProductionResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -88,7 +89,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetMachineRank(int top = 10)
{
var result = _dashboardService.GetMachineRank(null, null, top);
return Ok(ApiResponse<List<MachineRankResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -100,7 +102,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetWorkerRank(int top = 10)
{
var result = _dashboardService.GetWorkerRank(null, null, top);
return Ok(ApiResponse<List<WorkerRankResponse>>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -112,7 +115,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetMachineStatus()
{
var result = _dashboardService.GetMachineStatusDistribution();
return Ok(ApiResponse<object>.Success(result));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>
@ -129,7 +133,8 @@ namespace CncWebApi.Controllers
Value = f.FilterValue,
Label = f.FilterType
}).ToList();
return Ok(ApiResponse<List<CncModels.Dto.Common.SimpleOption>>.Success(items));
// Mock约定data: { items: [...] }
return Ok(ApiResponse<object>.Success(new { items }));
}
/// <summary>

@ -49,7 +49,8 @@ namespace CncWebApi.Controllers
ValueType = c.ValueType,
Description = c.Description
}).ToList();
return Ok(ApiResponse<List<SysConfigListItem>>.Success(items));
// Mock约定data: { items: [...] },不能直接返回数组
return Ok(ApiResponse<object>.Success(new { items }));
}
/// <summary>
@ -95,7 +96,8 @@ namespace CncWebApi.Controllers
public IHttpActionResult GetWorkshopList(string keyword = null)
{
var result = _workshopService.GetList(keyword);
return Ok(ApiResponse<List<WorkshopListItem>>.Success(result));
// Mock约定data: { items: [...] },不能直接返回数组
return Ok(ApiResponse<object>.Success(new { items = result }));
}
/// <summary>

Loading…
Cancel
Save