random.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
  2. import { z } from '@hono/zod-openapi';
  3. import { GoodsSchema } from '@/server/modules/goods/goods.schema';
  4. import { ErrorSchema } from '@/server/utils/errorHandler';
  5. import { AppDataSource } from '@/server/data-source';
  6. import { Goods } from '@/server/modules/goods/goods.entity';
  7. import { AuthContext } from '@/server/types/context';
  8. import { authMiddleware } from '@/server/middleware/auth.middleware';
  9. import { RandomGoodsQuerySchema, RandomGoodsResponseSchema } from '@/server/modules/goods/schemas/random.schema';
  10. import { parseWithAwait } from '@/server/utils/parseWithAwait';
  11. // 定义随机商品列表路由
  12. const routeDef = createRoute({
  13. method: 'get',
  14. path: '/',
  15. middleware: [authMiddleware],
  16. request: {
  17. query: RandomGoodsQuerySchema
  18. },
  19. responses: {
  20. 200: {
  21. description: '成功获取随机商品列表',
  22. content: {
  23. 'application/json': {
  24. schema: RandomGoodsResponseSchema
  25. }
  26. }
  27. },
  28. 400: {
  29. description: '请求参数错误',
  30. content: {
  31. 'application/json': {
  32. schema: ErrorSchema
  33. }
  34. }
  35. },
  36. 500: {
  37. description: '服务器错误',
  38. content: {
  39. 'application/json': {
  40. schema: ErrorSchema
  41. }
  42. }
  43. }
  44. }
  45. });
  46. // 路由实现
  47. const app = new OpenAPIHono<AuthContext>().openapi(routeDef, async (c) => {
  48. try {
  49. const query = c.req.valid('query');
  50. const { limit, categoryId, includeImages } = query;
  51. // 创建查询构建器
  52. const queryBuilder = AppDataSource.getRepository(Goods)
  53. .createQueryBuilder('goods')
  54. .where('goods.state = :state', { state: 1 }) // 只获取可用的商品
  55. .orderBy('RAND()') // 使用随机排序
  56. .limit(limit);
  57. // 如果指定了分类ID,添加分类过滤
  58. if (categoryId) {
  59. queryBuilder.andWhere(
  60. 'goods.category_id1 = :categoryId OR goods.category_id2 = :categoryId OR goods.category_id3 = :categoryId',
  61. { categoryId }
  62. );
  63. }
  64. // 如果需要包含关联数据
  65. if (includeImages) {
  66. queryBuilder
  67. .leftJoinAndSelect('goods.imageFile', 'imageFile')
  68. .leftJoinAndSelect('imageFile.uploadUser', 'imageUploadUser')
  69. .leftJoinAndSelect('goods.category1', 'category1')
  70. .leftJoinAndSelect('goods.category2', 'category2')
  71. .leftJoinAndSelect('goods.category3', 'category3')
  72. .leftJoinAndSelect('goods.supplier', 'supplier');
  73. }
  74. // 获取随机商品
  75. const goods = await queryBuilder.getMany();
  76. // 获取总数(用于分页参考)
  77. const totalQuery = AppDataSource.getRepository(Goods)
  78. .createQueryBuilder('goods')
  79. .where('goods.state = :state', { state: 1 });
  80. if (categoryId) {
  81. totalQuery.andWhere(
  82. 'goods.category_id1 = :categoryId OR goods.category_id2 = :categoryId OR goods.category_id3 = :categoryId',
  83. { categoryId }
  84. );
  85. }
  86. const total = await totalQuery.getCount();
  87. // 使用 parseWithAwait 确保数据格式正确
  88. const validatedGoods = await parseWithAwait(z.array(GoodsSchema), goods);
  89. return c.json({
  90. data: validatedGoods,
  91. total
  92. }, 200);
  93. } catch (error) {
  94. console.error('获取随机商品列表失败:', error);
  95. return c.json({
  96. code: 500,
  97. message: error instanceof Error ? error.message : '获取随机商品列表失败'
  98. }, 500);
  99. }
  100. });
  101. export default app;