ソースを参照

feat(app): 添加课程详情功能- 在 AppCoursesMapper 中新增 getCourseInfo 方法获取课程信息
- 在 AppHomeController 中添加 getCourseInfo 接口
- 创建 CourseInfoVO 类用于课程详情展示
- 在 DetailServiceImpl 中实现 getCourseInfo 方法,包括计算课程年销售数和课程明细
- 更新 IDetailService 接口,添加 getCourseInfo 方法

SheepHy 2 週間 前
コミット
db27f246da

+ 13 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/AppHomeController.java

@@ -110,4 +110,17 @@ public class AppHomeController {
     public Result<PlaceInfoVO> getPlaceInfo(@RequestParam @Schema(description="门店ID") String id){
         return Result.ok(detailService.getPlaceInfo(id));
     }
+
+    /**
+     * @Author SheepHy
+     * @Description 课程详情
+     * @Date 13:36 2025/7/8
+     * @Param id 课程id
+     * @return CourseInfoVO {@link CourseInfoVO}
+     **/
+    @GetMapping("/getCourseInfo")
+    @Operation(summary = "课程详情")
+    public Result<CourseInfoVO> getCourseInfo(@Schema(description="课程ID")String id, double latitude, double longitude){
+        return Result.ok(detailService.getCourseInfo(id, latitude, longitude));
+    }
 }

+ 4 - 3
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IDetailService.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.app.service;
 
+import org.jeecg.modules.app.vo.CourseInfoVO;
 import org.jeecg.modules.app.vo.PlaceInfoVO;
 
 public interface IDetailService {
@@ -16,8 +17,8 @@ public interface IDetailService {
      * @Author SheepHy
      * @Description 课程详情
      * @Date 13:36 2025/7/8
-     * @Param 
-     * @return 
+     * @Param id 课程id
+     * @return CourseInfoVO {@link CourseInfoVO}
      **/
-
+    CourseInfoVO getCourseInfo(String id, double latitude, double longitude);
 }

+ 5 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java

@@ -0,0 +1,5 @@
+package org.jeecg.modules.app.service;
+
+public interface IOrderService {
+
+}

+ 48 - 4
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/DetailServiceImpl.java

@@ -3,17 +3,20 @@ package org.jeecg.modules.app.service.impl;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.extern.log4j.Log4j2;
 import org.jeecg.modules.app.service.IDetailService;
+import org.jeecg.modules.app.vo.CourseInfoVO;
 import org.jeecg.modules.app.vo.PlaceInfoVO;
-import org.jeecg.modules.system.app.entity.AppInstructor;
-import org.jeecg.modules.system.app.entity.AppOrderProduct;
-import org.jeecg.modules.system.app.entity.AppSite;
-import org.jeecg.modules.system.app.entity.AppSitePriceRules;
+import org.jeecg.modules.system.app.entity.*;
 import org.jeecg.modules.system.app.mapper.*;
+import org.jeecg.modules.system.util.PositionUtil;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 @Service
 @Log4j2
@@ -23,6 +26,8 @@ public class DetailServiceImpl implements IDetailService {
     @Resource
     private AppCoursesPriceRulesMapper appCoursesPriceRulesMapper;
     @Resource
+    private AppCoursesMapper appCoursesMapper;
+    @Resource
     private AppOrderProductMapper appOrderProductMapper;
     @Resource
     private AppSitePriceRulesMapper appSitePriceRulesMapper;
@@ -58,6 +63,24 @@ public class DetailServiceImpl implements IDetailService {
         return placeInfo;
     }
 
+    @Override
+    public CourseInfoVO getCourseInfo(String id, double latitude, double longitude) {
+        CourseInfoVO courseInfoVO = appCoursesMapper.getCourseInfo(id);
+        AppSite appSite = appSiteMapper.selectById(courseInfoVO.getSiteId());
+        courseInfoVO.setKm(PositionUtil.calculateDistance(latitude, longitude, appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()));
+        courseInfoVO.setSales(getCourseSales(id));
+        List<CourseInfoVO.CourseDetailVO> courseDetailVOList = new ArrayList<>();
+        appCoursesPriceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery()
+                .eq(AppCoursesPriceRules::getCoursesId, courseInfoVO.getId())).forEach(appCourses -> {
+            CourseInfoVO.CourseDetailVO courseDetailVO = new CourseInfoVO.CourseDetailVO();
+            BeanUtils.copyProperties(courseDetailVO, appCourses);
+            courseDetailVOList.add(courseDetailVO);
+        });
+        courseInfoVO.setCourseDetail(courseDetailVOList);
+        //todo 评价查询待添加
+        return courseInfoVO;
+    }
+
     /**
      * @return
      * @Author SheepHy
@@ -76,4 +99,25 @@ public class DetailServiceImpl implements IDetailService {
         }
         return totalOrders;
     }
+
+    /**
+     * @Author SheepHy
+     * @Description 计算当前课程年销售数
+     * @Date 15:47 2025/7/8
+     * @Param id 课程id
+     * @return int 课程年销售数
+     **/
+    private int getCourseSales(String id) {
+        // 获取当前年份的时间范围(如:2025-01-01 00:00:00 到 2026-01-01 00:00:00)
+        LocalDate now = LocalDate.now();
+        LocalDateTime startOfYear = now.withDayOfYear(1).atStartOfDay(); // 当前年份第一天
+        LocalDateTime endOfYear = startOfYear.plusYears(1); // 下一年第一天
+
+        return Math.toIntExact(appOrderProductMapper.selectCount(
+                Wrappers.<AppOrderProduct>lambdaQuery()
+                        .eq(AppOrderProduct::getProductId, id)
+                        .ge(AppOrderProduct::getCreateTime, Date.from(startOfYear.atZone(ZoneId.systemDefault()).toInstant())) // >= 2025-01-01
+                        .lt(AppOrderProduct::getCreateTime, Date.from(endOfYear.atZone(ZoneId.systemDefault()).toInstant())) // < 2026-01-01
+        ));
+    }
 }

+ 31 - 2
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/CourseInfoVO.java

@@ -7,6 +7,7 @@ import lombok.experimental.Accessors;
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 @Data
 @Accessors(chain = true)
@@ -15,6 +16,8 @@ import java.util.Date;
 public class CourseInfoVO {
     @Schema(description = "id")
     private String id;
+    @Schema(hidden = true)
+    private String siteId;
     @Schema(description = "产品名称")
     private String name;
     @Schema(description = "费用类型;0 精品 1免费 仅课程")
@@ -28,9 +31,9 @@ public class CourseInfoVO {
     @Schema(description = "视频")
     private String video;
     @Schema(description = "上课场地")
-    private String siteId;
+    private String address;
     @Schema(description = "KM")
-    private String km;
+    private double km;
     @Schema(description = "年销售")
     private Integer sales;
     @Schema(description = "开始时间")
@@ -39,5 +42,31 @@ public class CourseInfoVO {
     private Date endTime;
     @Schema(description = "课时")
     private Integer classHour;
+    @Schema(description = "限购次数")
+    private Integer limitNum;
+    @Schema(description = "服务详情")
+    private Integer details;
+    @Schema(description = "适用人群")
+    private Integer fitPeople;
+    @Schema(description = "提示/须知")
+    private String reminder;
+    @Schema(description = "课程明细")
+    private List<CourseDetailVO> courseDetail;
+
+    @Data
+    @Accessors(chain = true)
+    @EqualsAndHashCode(callSuper = false)
+    @Schema(description="课程明细返回参数")
+    public static class CourseDetailVO {
+        @Schema(description = "课程id")
+        private String courseId;
+        @Schema(description = "课程名称")
+        private String courseName;
+        @Schema(description = "开始时间")
+        private Date startTime;
+        @Schema(description = "结束时间")
+        private Date endTime;
+    }
+
 
 }

+ 10 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppCoursesMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Param;
 import org.jeecg.modules.app.dto.SearchDTO;
+import org.jeecg.modules.app.vo.CourseInfoVO;
 import org.jeecg.modules.app.vo.SearchVO;
 import org.jeecg.modules.system.app.entity.AppCourses;
 
@@ -22,4 +23,13 @@ public interface AppCoursesMapper extends BaseMapper<AppCourses> {
      * @return
      **/
     Page<SearchVO.SearchTrainVO> convertSearchTrainVOPage(@Param("page")Page<SearchVO.SearchTrainVO> page,@Param("searchDTO")SearchDTO searchDTO);
+
+    /**
+     * @Author SheepHy
+     * @Description 课程详情
+     * @Date 13:36 2025/7/8
+     * @Param id 课程id
+     * @return CourseInfoVO {@link CourseInfoVO}
+     **/
+    CourseInfoVO getCourseInfo(@Param("id")String id);
 }

+ 36 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppCoursesMapper.xml

@@ -36,4 +36,40 @@
             ORDER BY sales DESC
         </if>
     </select>
+    <select id="getCourseInfo" resultType="org.jeecg.modules.app.vo.CourseInfoVO">
+        SELECT
+            a.id,
+            a.name,
+            a.original_price,
+            a.selling_price,
+            a.cover,
+            a.video,
+            b.address,
+            a.site_id,
+            a.start_time,
+            a.end_time,
+            COUNT( c.id ) AS classHour,
+            a.limit_num,
+            a.reminder
+        FROM
+            nm_courses a
+                LEFT JOIN nm_site b ON a.site_id = b.id
+                LEFT JOIN nm_courses_price_rules c ON a.id = c.courses_id
+        WHERE
+            a.STATUS = 0
+          AND a.del_flag = 0
+          AND a.id = #{id}
+        GROUP BY
+            a.id,
+            a.name,
+            a.original_price,
+            a.selling_price,
+            a.cover,
+            a.video,
+            b.address,
+            a.start_time,
+            a.end_time,
+            a.limit_num,
+            a.reminder;
+    </select>
 </mapper>