list.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { faker } from '@faker-js/faker';
  2. import { eventHandler, getQuery } from 'h3';
  3. import { verifyAccessToken } from '~/utils/jwt-utils';
  4. import {
  5. sleep,
  6. unAuthorizedResponse,
  7. usePageResponseSuccess,
  8. } from '~/utils/response';
  9. function generateMockDataList(count: number) {
  10. const dataList = [];
  11. for (let i = 0; i < count; i++) {
  12. const dataItem = {
  13. id: faker.string.uuid(),
  14. imageUrl: faker.image.avatar(),
  15. imageUrl2: faker.image.avatar(),
  16. open: faker.datatype.boolean(),
  17. status: faker.helpers.arrayElement(['success', 'error', 'warning']),
  18. productName: faker.commerce.productName(),
  19. price: faker.commerce.price(),
  20. currency: faker.finance.currencyCode(),
  21. quantity: faker.number.int({ min: 1, max: 100 }),
  22. available: faker.datatype.boolean(),
  23. category: faker.commerce.department(),
  24. releaseDate: faker.date.past(),
  25. rating: faker.number.float({ min: 1, max: 5 }),
  26. description: faker.commerce.productDescription(),
  27. weight: faker.number.float({ min: 0.1, max: 10 }),
  28. color: faker.color.human(),
  29. inProduction: faker.datatype.boolean(),
  30. tags: Array.from({ length: 3 }, () => faker.commerce.productAdjective()),
  31. };
  32. dataList.push(dataItem);
  33. }
  34. return dataList;
  35. }
  36. const mockData = generateMockDataList(100);
  37. export default eventHandler(async (event) => {
  38. const userinfo = verifyAccessToken(event);
  39. if (!userinfo) {
  40. return unAuthorizedResponse(event);
  41. }
  42. await sleep(600);
  43. const { page, pageSize, sortBy, sortOrder } = getQuery(event);
  44. // 规范化分页参数,处理 string[]
  45. const pageRaw = Array.isArray(page) ? page[0] : page;
  46. const pageSizeRaw = Array.isArray(pageSize) ? pageSize[0] : pageSize;
  47. const pageNumber = Math.max(
  48. 1,
  49. Number.parseInt(String(pageRaw ?? '1'), 10) || 1,
  50. );
  51. const pageSizeNumber = Math.min(
  52. 100,
  53. Math.max(1, Number.parseInt(String(pageSizeRaw ?? '10'), 10) || 10),
  54. );
  55. const listData = structuredClone(mockData);
  56. // 规范化 query 入参,兼容 string[]
  57. const sortKeyRaw = Array.isArray(sortBy) ? sortBy[0] : sortBy;
  58. const sortOrderRaw = Array.isArray(sortOrder) ? sortOrder[0] : sortOrder;
  59. // 检查 sortBy 是否是 listData 元素的合法属性键
  60. if (
  61. typeof sortKeyRaw === 'string' &&
  62. listData[0] &&
  63. Object.prototype.hasOwnProperty.call(listData[0], sortKeyRaw)
  64. ) {
  65. // 定义数组元素的类型
  66. type ItemType = (typeof listData)[0];
  67. const sortKey = sortKeyRaw as keyof ItemType; // 将 sortBy 断言为合法键
  68. const isDesc = sortOrderRaw === 'desc';
  69. listData.sort((a, b) => {
  70. const aValue = a[sortKey] as unknown;
  71. const bValue = b[sortKey] as unknown;
  72. let result = 0;
  73. if (typeof aValue === 'number' && typeof bValue === 'number') {
  74. result = aValue - bValue;
  75. } else if (aValue instanceof Date && bValue instanceof Date) {
  76. result = aValue.getTime() - bValue.getTime();
  77. } else if (typeof aValue === 'boolean' && typeof bValue === 'boolean') {
  78. if (aValue === bValue) {
  79. result = 0;
  80. } else {
  81. result = aValue ? 1 : -1;
  82. }
  83. } else {
  84. const aStr = String(aValue);
  85. const bStr = String(bValue);
  86. const aNum = Number(aStr);
  87. const bNum = Number(bStr);
  88. result =
  89. Number.isFinite(aNum) && Number.isFinite(bNum)
  90. ? aNum - bNum
  91. : aStr.localeCompare(bStr, undefined, {
  92. numeric: true,
  93. sensitivity: 'base',
  94. });
  95. }
  96. return isDesc ? -result : result;
  97. });
  98. }
  99. return usePageResponseSuccess(
  100. String(pageNumber),
  101. String(pageSizeNumber),
  102. listData,
  103. );
  104. });