envelope.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. /**
  2. * envelope.ts —— mock 信封辅助(academic-mock-plan §4 三条硬要求之一)。
  3. *
  4. * 契约来源:unified/03-migration/academic-frontend-contract-v1.md §1.1 / §1.3(冻结)。
  5. * 纪律:
  6. * - 信封恒四字段 {success, code, message, data};success 为兼容字段,新代码判 code;
  7. * - data 无值时**键不出现**(对齐后端 omitempty),不得为 null/undefined 占位;
  8. * - 分页恒 PageData 五字段 {list, total, page, pageSize, pages},空列表 [](非 null);
  9. * - pageSize 超 200 由 mock 侧钳制(对齐后端 ParsePage:默认 10 / 上限 200)。
  10. *
  11. * 本文件仅在 dev + VITE_API_MOCK 下被加载(http.ts 动态 import 门控),不进 dist。
  12. */
  13. import type { PageData, R } from '@/types/api';
  14. /** 成功信封(data 为 undefined 时键不出现,对齐后端 omitempty)。 */
  15. export function ok<T>(data: T): R<T>;
  16. /** 成功信封(无返回数据:data 键不出现)。 */
  17. export function ok(): R<undefined>;
  18. export function ok<T>(data?: T): R<T | undefined> {
  19. const body: Record<string, unknown> = { success: true, code: 200, message: 'ok' };
  20. if (data !== undefined) body.data = data;
  21. return body as unknown as R<T | undefined>;
  22. }
  23. /** 失败信封(无 data 键;message 为可直接展示的中文文案)。 */
  24. export function fail(code: number, message: string): R<undefined> {
  25. return { success: false, code, message };
  26. }
  27. /**
  28. * 分页封装(PageData 五字段全量下发)。
  29. *
  30. * 入参:
  31. * - list 完整数据集(mock 侧已按筛选条件过滤完毕);
  32. * - page 请求页码(缺省 1;<1 按 1 计);
  33. * - size 请求每页条数(缺省 10;**>200 钳制为 200**,对齐后端钳制语义)。
  34. *
  35. * 出参:
  36. * - R<PageData<T>>:list 切片(越界页 = [],不报错)/ total = 完整集长度 / pages = ceil(total/size),
  37. * size=0 时 pages=0(与后端一致)。
  38. */
  39. export function page<T>(list: T[], pageArg: number, sizeArg: number): R<PageData<T>> {
  40. const pageSize = Math.min(Math.max(Math.trunc(sizeArg) || 10, 1), 200);
  41. const pageNow = Math.max(Math.trunc(pageArg) || 1, 1);
  42. const total = list.length;
  43. const start = (pageNow - 1) * pageSize;
  44. return ok({
  45. list: list.slice(start, start + pageSize),
  46. total,
  47. page: pageNow,
  48. pageSize,
  49. pages: pageSize > 0 ? Math.ceil(total / pageSize) : 0,
  50. });
  51. }