public-goods-random.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
  2. import { z } from '@hono/zod-openapi';
  3. import { GoodsSchema } from '../schemas/goods.schema.js';
  4. import { ErrorSchema } from '@d8d/shared-utils';
  5. import { AppDataSource } from '@d8d/shared-utils';
  6. import { Goods } from '../entities/goods.entity.js';
  7. import { AuthContext } from '@d8d/shared-types';
  8. import { authMiddleware } from '@d8d/auth-module';
  9. import { RandomGoodsQuerySchema, RandomGoodsResponseSchema } from '../schemas/random.schema.js';
  10. import { parseWithAwait } from '@d8d/shared-utils';
  11. // 定义随机商品列表路由
  12. const routeDef = createRoute({
  13. method: 'get',
  14. path: '/',
  15. middleware: [],
  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. export const publicGoodsRandomRoutes = 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('RANDOM()') // 使用随机排序
  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. queryBuilder
  66. .leftJoinAndSelect('goods.category1', 'category1')
  67. .leftJoinAndSelect('goods.supplier', 'supplier')
  68. .leftJoinAndSelect('goods.merchant', 'merchant');
  69. // 如果需要包含图片关联数据
  70. if (includeImages) {
  71. queryBuilder
  72. .leftJoinAndSelect('goods.imageFile', 'imageFile')
  73. .leftJoinAndSelect('imageFile.uploadUser', 'imageUploadUser')
  74. .leftJoinAndSelect('goods.category2', 'category2')
  75. .leftJoinAndSelect('goods.category3', 'category3');
  76. }
  77. // 获取随机商品
  78. const goods = await queryBuilder.getMany();
  79. // 获取总数(用于分页参考)
  80. const totalQuery = AppDataSource.getRepository(Goods)
  81. .createQueryBuilder('goods')
  82. .where('goods.state = :state', { state: 1 });
  83. if (categoryId) {
  84. totalQuery.andWhere(
  85. 'goods.category_id1 = :categoryId OR goods.category_id2 = :categoryId OR goods.category_id3 = :categoryId',
  86. { categoryId }
  87. );
  88. }
  89. const total = await totalQuery.getCount();
  90. // 使用 parseWithAwait 确保数据格式正确
  91. const validatedGoods = await parseWithAwait(z.array(GoodsSchema), goods);
  92. return c.json({
  93. data: validatedGoods,
  94. total
  95. }, 200);
  96. } catch (error) {
  97. console.error('获取随机商品列表失败:', error);
  98. return c.json({
  99. code: 500,
  100. message: error instanceof Error ? error.message : '获取随机商品列表失败'
  101. }, 500);
  102. }
  103. });