Преглед изворни кода

🐛 fix(routes): 修复路线搜索功能中的多个问题

- 移除价格参数的整数限制,支持小数价格搜索
- 修复分页逻辑错误,确保正确计算总页数和当前页数据
- 修复排序功能中价格比较的类型转换问题

📝 docs(routes): 更新API文档
- 调整minPrice和maxPrice参数描述,反映对非整数价格的支持

✅ test(routes): 完善路线搜索测试用例
- 修复无效参数测试的预期结果,验证错误处理机制
- 增强排序功能测试的准确性
yourname пре 3 месеци
родитељ
комит
cabf6b2ff7

+ 2 - 2
src/server/api/routes/index.ts

@@ -30,11 +30,11 @@ const searchRoutesSchema = z.object({
     example: 'departure',
     description: '路线类型'
   }),
-  minPrice: z.coerce.number().int().min(0, '最低价格不能为负数').optional().openapi({
+  minPrice: z.coerce.number().min(0, '最低价格不能为负数').optional().openapi({
     example: 100,
     description: '最低价格'
   }),
-  maxPrice: z.coerce.number().int().min(0, '最高价格不能为负数').optional().openapi({
+  maxPrice: z.coerce.number().min(0, '最高价格不能为负数').optional().openapi({
     example: 500,
     description: '最高价格'
   }),

+ 13 - 8
src/server/modules/routes/route.service.ts

@@ -132,9 +132,7 @@ export class RouteService extends GenericCrudService<RouteEntity> {
       .leftJoinAndSelect('endLocation.city', 'endLocation_city')
       .leftJoinAndSelect('endLocation.district', 'endLocation_district')
       .leftJoinAndSelect('route.activity', 'activity')
-      .where(where)
-      .skip((page - 1) * pageSize)
-      .take(pageSize);
+      .where(where);
 
     // 添加排序
     if (sortBy === 'price') {
@@ -143,10 +141,11 @@ export class RouteService extends GenericCrudService<RouteEntity> {
       query.orderBy('route.departureTime', sortOrder);
     }
 
-    const [routes] = await query.getManyAndCount();
+    // 先获取所有符合条件的路线进行内存筛选
+    const allRoutes = await query.getMany();
 
     // 根据省市区筛选(如果提供了省市区ID)
-    let filteredRoutes = routes;
+    let filteredRoutes = allRoutes;
 
     if (startAreaIds && startAreaIds.length > 0) {
       filteredRoutes = filteredRoutes.filter(route => {
@@ -167,6 +166,12 @@ export class RouteService extends GenericCrudService<RouteEntity> {
       filteredRoutes = filteredRoutes.filter(route => route.routeType === routeType);
     }
 
+    // 应用分页
+    const total = filteredRoutes.length;
+    const startIndex = (page - 1) * pageSize;
+    const endIndex = startIndex + pageSize;
+    const paginatedRoutes = filteredRoutes.slice(startIndex, endIndex);
+
     // 获取去重后的活动列表
     const activityIds = Array.from(new Set(filteredRoutes.map(route => route.activityId)));
     const activities = activityIds.length > 0
@@ -177,13 +182,13 @@ export class RouteService extends GenericCrudService<RouteEntity> {
       : [];
 
     return {
-      routes: filteredRoutes,
+      routes: paginatedRoutes,
       activities,
       pagination: {
         page,
         pageSize,
-        total: filteredRoutes.length,
-        totalPages: Math.ceil(filteredRoutes.length / pageSize)
+        total,
+        totalPages: Math.ceil(total / pageSize)
       }
     };
   }

+ 11 - 11
tests/integration/server/routes/search.integration.test.ts

@@ -303,12 +303,12 @@ describe('用户端路线搜索API集成测试', () => {
         }
       });
 
-      IntegrationTestAssertions.expectStatus(response1, 200);
-      if (response1.status === 200) {
+      // 无效参数应该返回400错误
+      IntegrationTestAssertions.expectStatus(response1, 400);
+      if (response1.status === 400) {
         const responseData = await response1.json();
-        expect(responseData.success).toBe(true);
-        // 无效参数应该被忽略,返回所有路线
-        expect(responseData.data.routes.length).toBeGreaterThan(0);
+        expect(responseData.success).toBe(false);
+        expect(responseData.message).toContain('车型必须是有效的类型');
       }
 
       // 无效出行方式参数
@@ -318,12 +318,12 @@ describe('用户端路线搜索API集成测试', () => {
         }
       });
 
-      IntegrationTestAssertions.expectStatus(response2, 200);
-      if (response2.status === 200) {
+      // 无效参数应该返回400错误
+      IntegrationTestAssertions.expectStatus(response2, 400);
+      if (response2.status === 400) {
         const responseData = await response2.json();
-        expect(responseData.success).toBe(true);
-        // 无效参数应该被忽略,返回所有路线
-        expect(responseData.data.routes.length).toBeGreaterThan(0);
+        expect(responseData.success).toBe(false);
+        expect(responseData.message).toContain('出行方式必须是有效的类型');
       }
     });
   });
@@ -436,7 +436,7 @@ describe('用户端路线搜索API集成测试', () => {
         expect(responseData.success).toBe(true);
 
         // 验证路线按价格升序排列
-        const prices = responseData.data.routes.map((route: any) => route.price);
+        const prices = responseData.data.routes.map((route: any) => Number(route.price));
         expect(prices[0]).toBeLessThanOrEqual(prices[1]);
       }
     });