Pārlūkot izejas kodu

feat(app): 重构首页接口并添加教练信息

- 重构了 AppHomeServiceImpl 中的 homeInfo 方法,优化了课程信息获取逻辑- 新增教练信息获取功能,展示好评率最高的两个教练
- 在 AppCourese 实体中添加了 userId 字段,用于关联教练
- 更新了 CoureseVO 和 InstructorVO,以适应新的数据结构
- 在 SysUserMapper 中添加了 getUserIdListByRoleId 方法,用于获取指定角色的用户 ID 列表
SheepHy 3 nedēļas atpakaļ
vecāks
revīzija
9b838f7f62

+ 5 - 0
national-motion-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java

@@ -630,4 +630,9 @@ public interface CommonConstant {
     * 修改手机号验证码请求次数超出
     */
    Integer PHONE_SMS_FAIL_CODE = 40002;
+
+   /**
+    * 教练
+    * */
+   String INSTRUCTOR = "instructor";
 }

+ 90 - 20
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/AppHomeServiceImpl.java

@@ -1,15 +1,22 @@
 package org.jeecg.modules.app.service.impl;
 
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import org.jeecg.modules.system.app.entity.AppBanner;
-import org.jeecg.modules.system.app.mapper.AppBannerMapper;
 import org.jeecg.modules.app.service.IAppHomeService;
 import org.jeecg.modules.app.vo.AppBannerVO;
 import org.jeecg.modules.app.vo.CoureseVO;
 import org.jeecg.modules.app.vo.HomeVO;
+import org.jeecg.modules.app.vo.InstructorVO;
+import org.jeecg.modules.system.app.entity.AppBanner;
 import org.jeecg.modules.system.app.entity.AppCourese;
+import org.jeecg.modules.system.app.entity.AppInstructor;
+import org.jeecg.modules.system.app.mapper.AppBannerMapper;
 import org.jeecg.modules.system.app.mapper.AppCoureseMapper;
-import org.jeecg.modules.system.app.mapper.AppCoursesPriceRulesMapper;
+import org.jeecg.modules.system.app.mapper.AppInstructorMapper;
+import org.jeecg.modules.system.entity.SysDepart;
+import org.jeecg.modules.system.entity.SysUser;
+import org.jeecg.modules.system.mapper.SysDepartMapper;
+import org.jeecg.modules.system.mapper.SysUserMapper;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -17,6 +24,8 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
+import static org.jeecg.common.constant.CommonConstant.INSTRUCTOR;
+
 @Service
 public class AppHomeServiceImpl implements IAppHomeService {
     @Resource
@@ -24,29 +33,90 @@ public class AppHomeServiceImpl implements IAppHomeService {
     @Resource
     private AppCoureseMapper appCoureseMapper;
     @Resource
-    private AppCoursesPriceRulesMapper appCoursesPriceRulesMapper;
+    private AppInstructorMapper appInstructorMapper;
+    @Resource
+    private SysUserMapper sysUserMapper;
+    @Resource
+    private SysDepartMapper sysDepartMapper;
+
     @Override
-    public HomeVO homeInfo(){
+    public HomeVO homeInfo() {
+        // 获取 banners
         List<AppBanner> appBanners = appBannerMapper.selectList(Wrappers.<AppBanner>lambdaQuery()
-                .eq(AppBanner::getDelFlag, 0));
-        //精品课程
+                .eq(AppBanner::getDelFlag, 0).eq(AppBanner::getIsEnabled,1));
+
+        // 精品课程(最多3个)
         List<AppCourese> appCoureseFine = appCoureseMapper.selectList(Wrappers.<AppCourese>lambdaQuery()
-                .eq(AppCourese::getPriceType, 0).last("limit 3"));
-        //免费课程
+                .eq(AppCourese::getPriceType, 0).last("LIMIT 3"));
+
+        // 免费课程(最多3个)
         List<AppCourese> appCoureseFree = appCoureseMapper.selectList(Wrappers.<AppCourese>lambdaQuery()
-                .eq(AppCourese::getPriceType, 1).last("limit 3"));
+                .eq(AppCourese::getPriceType, 1).last("LIMIT 3"));
+
+        // 合并课程信息
         List<CoureseVO> courseVO = new ArrayList<>();
         courseVO.addAll(convertToCoureseVOList(appCoureseFine));
         courseVO.addAll(convertToCoureseVOList(appCoureseFree));
-        return new HomeVO().setBannerList(appBanners.stream()
-                .map(banner -> new AppBannerVO()
-                        .setId(banner.getId())
-                        .setEventType(banner.getEventType())
-                        .setEventValue(banner.getEventValue())
-                        .setSortOrder(banner.getSortOrder())
-                        .setImageUrl(banner.getImageUrl()))
-                .collect(Collectors.toList()))
-                .setCourseList(courseVO);
+
+        // 获取好评率最高的两个教练 ID
+        List<String> topInstructorUserIds = sysUserMapper.getUserIdListByRoleId(INSTRUCTOR).stream()
+                .map(userId -> {
+                    AppInstructor instructor = appInstructorMapper.selectOne(
+                            Wrappers.<AppInstructor>lambdaQuery().eq(AppInstructor::getUserId, userId));
+                    return new Object() {
+                        final String id = userId;
+                        final Double goodRate = instructor != null ? Double.parseDouble(String.valueOf(instructor.getGoodRate())) : 0.0;
+                    };
+                })
+                .sorted((a, b) -> Double.compare(b.goodRate, a.goodRate))
+                .limit(2)
+                .map(obj -> obj.id)
+                .collect(Collectors.toList());
+
+        // 构建教练列表
+        List<InstructorVO> instructorList = new ArrayList<>();
+        for (String userId : topInstructorUserIds) {
+            SysUser sysUser = sysUserMapper.selectById(userId);
+            AppInstructor appInstructor = appInstructorMapper.selectOne(
+                    Wrappers.<AppInstructor>lambdaQuery().eq(AppInstructor::getUserId, userId));
+
+            InstructorVO instructorVO = new InstructorVO();
+            BeanUtils.copyProperties(instructorVO, appInstructor);
+
+            instructorVO.setId(sysUser.getId())
+                    .setAvatar(sysUser.getAvatar())
+                    .setName(sysUser.getRealname())
+                    .setOrgName(sysDepartMapper.selectOne(Wrappers.<SysDepart>lambdaQuery()
+                            .eq(SysDepart::getOrgCode, sysUser.getOrgCode())).getDepartName());
+
+            // 获取该教练的课程(最多取2个)
+            List<AppCourese> courses = appCoureseMapper.selectList(
+                    Wrappers.<AppCourese>lambdaQuery().eq(AppCourese::getUserId, userId).last("LIMIT 2"));
+
+            List<InstructorVO.CourseInfoVO> courseInfoVOS = courses.stream()
+                    .map(course -> {
+                        InstructorVO.CourseInfoVO vo = instructorVO.new CourseInfoVO();
+                        BeanUtils.copyProperties(vo, course);
+                        return vo;
+                    })
+                    .collect(Collectors.toList());
+
+            instructorVO.setCourseList(courseInfoVOS);
+            instructorList.add(instructorVO);
+        }
+
+        // 返回首页数据
+        return new HomeVO()
+                .setBannerList(appBanners.stream()
+                        .map(banner -> new AppBannerVO()
+                                .setId(banner.getId())
+                                .setEventType(banner.getEventType())
+                                .setEventValue(banner.getEventValue())
+                                .setSortOrder(banner.getSortOrder())
+                                .setImageUrl(banner.getImageUrl()))
+                        .collect(Collectors.toList()))
+                .setCourseList(courseVO)
+                .setInstructorList(instructorList);
     }
 
     /**
@@ -61,7 +131,7 @@ public class AppHomeServiceImpl implements IAppHomeService {
                 .map(courese -> new CoureseVO()
                         .setId(courese.getId()).setCover(courese.getCover())
                         .setPriceType(courese.getPriceType())
-                        .setSellingPrice(appCoursesPriceRulesMapper.selectById(courese.getId()).get))
+                        .setSellingPrice(courese.getSellingPrice()))
                 .collect(Collectors.toList());
     }
 }

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

@@ -5,10 +5,12 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
+import java.math.BigDecimal;
+
 @Data
 @Accessors(chain = true)
 @EqualsAndHashCode(callSuper = false)
-@Schema(description="首页轮播图管理")
+@Schema(description="产品信息返回VO")
 public class CoureseVO {
     @Schema(description = "主键id")
     private String id;
@@ -17,6 +19,6 @@ public class CoureseVO {
     @Schema(description = "产品类型 1、公益 2、试听")
     private int priceType;
     @Schema(description = "价格")
-    private String sellingPrice;
+    private BigDecimal sellingPrice;
 
 }

+ 3 - 3
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/InstructorVO.java

@@ -31,13 +31,13 @@ public class InstructorVO {
     @Schema(description = "擅长说明")
     private String excelMsg;
     @Schema(description = "课程列表")
-    private List<CourseVO> courseList;
+    private List<CourseInfoVO> courseList;
 
     @Data
     @Accessors(chain = true)
     @EqualsAndHashCode(callSuper = false)
-    @Schema(description="教练信息返回参数")
-    private class CourseVO {
+    @Schema(description="教练课程信息返回参数")
+    public class CourseInfoVO {
         @Schema(description = "主键id")
         private String id;
         @Schema(description = "课程名称")

+ 11 - 11
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/entity/AppCourese.java

@@ -1,23 +1,20 @@
 package org.jeecg.modules.system.app.entity;
 
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.util.Date;
-import java.math.BigDecimal;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.annotation.TableLogic;
-import org.jeecg.common.constant.ProvinceCityArea;
-import org.jeecg.common.util.SpringContextUtils;
-import lombok.Data;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
-import org.springframework.format.annotation.DateTimeFormat;
-import org.jeecgframework.poi.excel.annotation.Excel;
-import org.jeecg.common.aspect.annotation.Dict;
 import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.jeecgframework.poi.excel.annotation.Excel;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
 
 /**
  * @Description: 课程/培训表
@@ -41,6 +38,9 @@ public class AppCourese implements Serializable {
 	@Excel(name = "部门id", width = 15)
     @Schema(description = "部门id")
     private String orgCode;
+    @Excel(name = "教练ID", width = 15)
+    @Schema(description = "教练ID")
+    private String userId;
 	/**商户/场地id;场馆/学校等场地*/
 	@Excel(name = "商户/场地id;场馆/学校等场地", width = 15)
     @Schema(description = "商户/场地id;场馆/学校等场地")

+ 5 - 5
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/controller/SysUserController.java

@@ -13,10 +13,8 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shiro.SecurityUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
-import org.apache.shiro.authz.annotation.RequiresRoles;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.common.aspect.annotation.PermissionData;
-import org.jeecg.common.base.BaseMap;
 import org.jeecg.common.config.TenantContext;
 import org.jeecg.common.constant.CommonConstant;
 import org.jeecg.common.constant.SymbolConstant;
@@ -156,7 +154,8 @@ public class SysUserController {
 		Result<SysUser> result = new Result<SysUser>();
 		String selectedRoles = jsonObject.getString("selectedroles");
 		String selectedDeparts = jsonObject.getString("selecteddeparts");
-		try {
+        SysDepart departById = sysDepartService.getDepartById(selectedDeparts);
+        try {
 			SysUser user = JSON.parseObject(jsonObject.toJSONString(), SysUser.class);
 			user.setCreateTime(new Date());//设置创建时间
 			String salt = oConvertUtils.randomGen(8);
@@ -166,7 +165,7 @@ public class SysUserController {
 			user.setStatus(1);
 			user.setDelFlag(CommonConstant.DEL_FLAG_0);
 			//用户表字段org_code不能在这里设置他的值
-            user.setOrgCode(null);
+            user.setOrgCode(departById.getOrgCode());
 			// 保存用户走一个service 保证事务
             //获取租户ids
             String relTenantIds = jsonObject.getString("relTenantIds");
@@ -196,12 +195,13 @@ public class SysUserController {
 				user.setPassword(sysUser.getPassword());
 				String roles = jsonObject.getString("selectedroles");
                 String departs = jsonObject.getString("selecteddeparts");
+                SysDepart departById = sysDepartService.getDepartById(departs);
                 if(oConvertUtils.isEmpty(departs)){
                     //vue3.0前端只传递了departIds
                     departs=user.getDepartIds();
                 }
                 //用户表字段org_code不能在这里设置他的值
-                user.setOrgCode(null);
+                user.setOrgCode(departById.getOrgCode());
                 // 修改用户走一个service 保证事务
                 //获取租户ids
                 String relTenantIds = jsonObject.getString("relTenantIds");

+ 9 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/mapper/SysUserMapper.java

@@ -222,4 +222,13 @@ public interface SysUserMapper extends BaseMapper<SysUser> {
 	 */
 	@Select("select id,phone from sys_user where phone = #{phone} and username = #{username}")
     SysUser getUserByNameAndPhone(@Param("phone") String phone, @Param("username") String username);
+
+	/**
+	 * @Author SheepHy
+	 * @Description 根据角色编号获取到用户ID列表,可根据ORG_CODE进行过滤
+	 * @Date 9:33 2025/7/4
+	 * @Param
+	 * @return
+	 **/
+	List<String> getUserIdListByRoleId(@Param("roleCode") String roleCode);
 }

+ 5 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml

@@ -298,4 +298,9 @@
 		and sut.tenant_id=#{tenantId}
         and sut.status = '1'
 	</select>
+
+	<select id="getUserIdListByRoleId" resultType="string" parameterType="string">
+		SELECT b.id FROM `sys_role` a LEFT JOIN sys_user_role b ON a.id = b.role_id
+		WHERE a.role_code = #{roleCode}
+	</select>
 </mapper>