2025-02-20 14:14:51 +08:00
package com.syzb.course.service ;
2025-01-27 21:47:33 +08:00
import cn.hutool.core.collection.CollUtil ;
import cn.hutool.core.util.StrUtil ;
2025-02-20 14:14:51 +08:00
import com.syzb.advisor.entity.AdvisorBasic ;
import com.syzb.advisor.service.AdvisorInfoService ;
2025-01-27 21:47:33 +08:00
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper ;
import com.baomidou.mybatisplus.core.toolkit.Wrappers ;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page ;
2025-02-20 14:14:51 +08:00
import com.syzb.common.config.cache.CacheKey ;
import com.syzb.common.constant.IsDisplay ;
import com.syzb.common.constant.IsRecommend ;
import com.syzb.common.handler.BizException ;
import com.syzb.common.query.OnlyIdQuery ;
import com.syzb.common.result.AppPager ;
import com.syzb.common.result.Pager ;
import com.syzb.common.result.ResponseStatus ;
import com.syzb.common.service.AppUserService ;
import com.syzb.common.service.CacheService ;
import com.syzb.common.service.SensitiveWordService ;
import com.syzb.common.state.StateMachine ;
import com.syzb.common.vo.BackendUserVO ;
import com.syzb.common.vo.FrontUserVO ;
import com.syzb.common.vo.InsertIdVO ;
import com.syzb.course.constant.* ;
import com.syzb.course.entity.CoursePackage ;
import com.syzb.course.entity.CoursePackageContent ;
import com.syzb.course.entity.CourseSortEntity ;
import com.syzb.course.mapper.CoursePackageContentMapper ;
import com.syzb.course.mapper.CoursePackageMapper ;
import com.syzb.course.query.* ;
import com.syzb.course.vo.CoursePackageContentVO ;
import com.syzb.course.vo.CoursePackageVO ;
import com.syzb.course.vo.CourseVO ;
import com.syzb.course.vo.SerialVO ;
2025-01-27 21:47:33 +08:00
import com.hazelcast.map.IMap ;
2025-02-20 14:14:51 +08:00
import com.syzb.rbac.entity.UserDept ;
import com.syzb.rbac.service.AuthService ;
import com.syzb.rbac.service.UserService ;
import com.syzb.video.constant.VideoUserType ;
2025-01-27 21:47:33 +08:00
import org.springframework.stereotype.Service ;
import org.springframework.transaction.annotation.Transactional ;
import javax.annotation.Resource ;
import java.time.LocalDateTime ;
import java.util.* ;
import java.util.stream.Collectors ;
import java.util.stream.Stream ;
// 课程Service
@Service
public class CoursePackageService {
@Resource
private CoursePackageMapper coursePackageMapper ;
@Resource
private SensitiveWordService sensitiveWordService ;
@Resource
private StateMachine < CoursePackageStatus > coursePackageSM ;
@Resource
private AdvisorInfoService advisorInfoService ;
@Resource
private UserService userService ;
@Resource
private CoursePackageContentMapper coursePackageContentMapper ;
@Resource
private SerialService serialService ;
@Resource
private CourseService courseService ;
@Resource
private CacheService cacheService ;
@Resource
private AuthService authService ;
@Resource
private PageService pageService ;
@Resource
private CourseCommonService courseCommonService ;
@Resource
private AppUserService appUserService ;
@Resource
private IMap < String , Object > courseCache ;
/ * *
* 保存课程
*
* @param query 保存课程参数
* @param backendUserVO 后台用户
* @return 课程ID
* /
@Transactional ( rollbackFor = Exception . class )
public InsertIdVO save ( SaveCoursePackageQuery query , BackendUserVO backendUserVO ) {
sensitiveWordService . check ( query . getName ( ) , query . getRemark ( ) ) ;
Integer advisorId = courseCommonService . getAdvisorId ( query . getAdvisorId ( ) , backendUserVO ) ;
CoursePackage coursePackage = query . toPO ( backendUserVO , advisorId ) ;
coursePackageMapper . insert ( coursePackage ) ;
return new InsertIdVO ( coursePackage . getId ( ) ) ;
}
/ * *
* 更新课程
*
* @param query 更新课程参数
* @param backendUserVO 后台用户
* /
@Transactional ( rollbackFor = Exception . class )
public void update ( UpdateCoursePackageQuery query , BackendUserVO backendUserVO ) {
sensitiveWordService . check ( query . getName ( ) , query . getRemark ( ) ) ;
CoursePackage coursePackageInDB = coursePackageMapper . selectById ( query . getId ( ) ) ;
if ( coursePackageInDB = = null ) {
throw new BizException ( ResponseStatus . ID_NOT_EXIST_ERROR ) ;
}
// 状态机扭转,判断是否能够编辑
CoursePackageStatus dbStatus = CoursePackageStatus . fromValue ( coursePackageInDB . getStatus ( ) ) ;
coursePackageSM . send ( dbStatus , CoursePackageStatus . EVENT_UPDATE ) ;
CoursePackage coursePackage = query . toPO ( backendUserVO ) ;
coursePackageMapper . updateById ( coursePackage ) ;
clearCache ( query . getId ( ) ) ;
}
/ * *
* 更新课程状态
*
* @param query 更新课程状态参数
* @param backendUserVO 后台用户
* /
@Transactional ( rollbackFor = Exception . class )
public void updateStatus ( UpdateCoursePackageStatusQuery query , BackendUserVO backendUserVO ) {
CoursePackage coursePackageInDB = coursePackageMapper . selectById ( query . getId ( ) ) ;
if ( coursePackageInDB = = null ) {
throw new BizException ( ResponseStatus . ID_NOT_EXIST_ERROR ) ;
}
// 状态机扭转
CoursePackageStatus dbStatus = CoursePackageStatus . fromValue ( coursePackageInDB . getStatus ( ) ) ;
CoursePackageStatus targetStatus = coursePackageSM . send ( dbStatus , CoursePackageStatus . fromValue ( query . getEvent ( ) ) ) ;
CoursePackage coursePackage = query . toPO ( targetStatus , backendUserVO ) ;
coursePackageMapper . updateById ( coursePackage ) ;
clearCache ( query . getId ( ) ) ;
}
/ * *
* 查询课程列表
*
* @param query 查询参数
* @param backendUserVO 后台用户
* @return 课程列表
* /
public Pager < CoursePackageVO > list ( ListCoursePackageQuery query , BackendUserVO backendUserVO ) {
String name = query . getName ( ) ;
Integer status = query . getStatus ( ) ;
Integer userType = query . getUserType ( ) ;
Integer contentType = query . getContentType ( ) ;
Integer contentId = query . getContentId ( ) ;
Integer advisorId = query . getAdvisorId ( ) ;
Set < Integer > authSet = authService . getAuthByUserType ( VideoUserType . format ( userType ) , backendUserVO , true ) ;
if ( authSet ! = null & & authSet . isEmpty ( ) ) {
return null ;
}
LambdaQueryWrapper < CoursePackage > wrapper = Wrappers . < CoursePackage > lambdaQuery ( )
. in ( CollUtil . isNotEmpty ( authSet ) , CoursePackage : : getAdvisorId , authSet )
. eq ( advisorId ! = null & & advisorId ! = 0 , CoursePackage : : getAdvisorId , advisorId )
. like ( StrUtil . isNotEmpty ( name ) , CoursePackage : : getName , name )
. eq ( status ! = null & & status ! = 0 , CoursePackage : : getStatus , status )
. exists ( contentType ! = null & & contentId ! = null ,
" select 0 from course_package_content where course_package_content.course_package_id = course_package.id and course_package_content.type = {0} and course_package_content.content_id = {1} " ,
contentType , contentId )
. ne ( ! VideoUserType . MANAGER_USER . value . equals ( userType ) , CoursePackage : : getStatus , CoursePackageStatus . DELETED . value )
. orderByDesc ( CoursePackage : : getId ) ;
Page < CoursePackage > page = coursePackageMapper . selectPage ( query . toPage ( ) , wrapper ) ;
Map < Integer , String > advisorNameMap = advisorInfoService . getAdvisorMap ( ) . values ( ) . stream ( )
. collect ( Collectors . toMap ( AdvisorBasic : : getId , AdvisorBasic : : getName ) ) ;
Map < Integer , String > userNameMap = userService . getUserMap ( ) . values ( ) . stream ( )
. collect ( Collectors . toMap ( UserDept : : getUserId , UserDept : : getName ) ) ;
List < CoursePackageVO > list = page . getRecords ( ) . stream ( ) . map ( coursePackage - > new CoursePackageVO (
coursePackage ,
advisorNameMap . get ( coursePackage . getAdvisorId ( ) ) ,
userNameMap . get ( coursePackage . getCreateUserId ( ) ) ,
userNameMap . get ( coursePackage . getAuditUserId ( ) ) ,
pageService . getForApp ( coursePackage . getPageId ( ) ) ,
getContentCount ( coursePackage . getId ( ) )
) ) . collect ( Collectors . toList ( ) ) ;
return new Pager < > ( list , page . getTotal ( ) ) ;
}
/ * *
* 查询课程详情
*
* @param query 查询参数
* @param backendUserVO 后台用户
* @return 课程详情
* /
public CoursePackageVO get ( OnlyIdQuery query , BackendUserVO backendUserVO ) {
Integer id = query . getId ( ) ;
CoursePackage coursePackage = getEntity ( id , backendUserVO ) ;
if ( coursePackage = = null ) {
return null ;
}
Map < Integer , String > advisorNameMap = advisorInfoService . getAdvisorMap ( ) . values ( ) . stream ( )
. collect ( Collectors . toMap ( AdvisorBasic : : getId , AdvisorBasic : : getName ) ) ;
Map < Integer , String > userNameMap = userService . getUserMap ( ) . values ( ) . stream ( )
. collect ( Collectors . toMap ( UserDept : : getUserId , UserDept : : getName ) ) ;
return new CoursePackageVO (
coursePackage ,
advisorNameMap . get ( coursePackage . getAdvisorId ( ) ) ,
userNameMap . get ( coursePackage . getCreateUserId ( ) ) ,
userNameMap . get ( coursePackage . getAuditUserId ( ) ) ,
coursePackage . getPageId ( ) = = null ? null : pageService . get ( new OnlyIdQuery ( coursePackage . getPageId ( ) ) , null ) ,
getContentCount ( id ) ) ;
}
/ * *
* 查询课程内容列表
*
* @param query 查询参数
* @param backendUserVO 后台用户
* /
public Pager < CoursePackageContentVO > listContent ( ListCoursePackageContentQuery query , BackendUserVO backendUserVO ) {
// 不使用返回值,仅校验课程是否存在以及数据权限
if ( getEntity ( query . getCoursePackageId ( ) , backendUserVO ) = = null ) {
throw new BizException ( ResponseStatus . ID_NOT_EXIST_ERROR ) ;
}
Integer type = query . getType ( ) ;
LambdaQueryWrapper < CoursePackageContent > wrapper = Wrappers . < CoursePackageContent > lambdaQuery ( )
. eq ( CoursePackageContent : : getCoursePackageId , query . getCoursePackageId ( ) )
. eq ( type ! = null & & type ! = 0 , CoursePackageContent : : getType , type )
. orderByDesc ( CoursePackageContent : : getIsRecommend , CoursePackageContent : : getCreateTime ) ;
Page < CoursePackageContent > page = coursePackageContentMapper . selectPage ( query . toPage ( ) , wrapper ) ;
List < CoursePackageContentVO > list = page . getRecords ( ) . stream ( ) . map ( content - > {
if ( CoursePackageContentType . SERIAL . value . equals ( content . getType ( ) ) ) {
SerialVO serial = serialService . get ( new OnlyIdQuery ( content . getContentId ( ) ) , null ) ;
return new CoursePackageContentVO ( content , serial ) ;
} else if ( CoursePackageContentType . COURSE . value . equals ( content . getType ( ) ) ) {
CourseVO course = courseService . get ( new OnlyIdQuery ( content . getContentId ( ) ) , null ) ;
return new CoursePackageContentVO ( content , course ) ;
}
return null ;
} ) . filter ( Objects : : nonNull ) . collect ( Collectors . toList ( ) ) ;
return new Pager < > ( list , page . getTotal ( ) ) ;
}
/ * *
* 更新课程内容
*
* @param query 更新课程内容参数
* @param backendUserVO 后台用户
* /
@Transactional ( rollbackFor = Exception . class )
public void updateContent ( UpdateCoursePackageContentQuery query , BackendUserVO backendUserVO ) {
// 不使用返回值,仅校验课程是否存在以及数据权限
if ( getEntity ( query . getCoursePackageId ( ) , backendUserVO ) = = null ) {
throw new BizException ( ResponseStatus . ID_NOT_EXIST_ERROR ) ;
}
// 构造查询条件
LambdaQueryWrapper < CoursePackageContent > wrapper = Wrappers . < CoursePackageContent > lambdaQuery ( )
. eq ( CoursePackageContent : : getCoursePackageId , query . getCoursePackageId ( ) )
. eq ( CoursePackageContent : : getType , query . getType ( ) )
. eq ( CoursePackageContent : : getContentId , query . getContentId ( ) ) ;
UpdateContentEvent event = UpdateContentEvent . fromValue ( query . getEvent ( ) ) ;
switch ( event ) {
case SAVE :
saveContentList ( query . getCoursePackageId ( ) , query . getType ( ) , query . toContentListPO ( ) , event ) ;
break ;
case RECOMMEND :
if ( query . getIsRecommend ( ) = = null | | IsRecommend . NO . value . equals ( query . getIsRecommend ( ) ) ) {
throw new BizException ( ResponseStatus . PARM_ERROR , " 权重值错误 " ) ;
}
CoursePackageContent recommendContent = new CoursePackageContent ( ) ;
recommendContent . setIsRecommend ( query . getIsRecommend ( ) ) ;
coursePackageContentMapper . update ( recommendContent , wrapper ) ;
break ;
case UN_RECOMMEND :
CoursePackageContent unRecommendContent = new CoursePackageContent ( ) ;
unRecommendContent . setIsRecommend ( IsRecommend . NO . value ) ;
coursePackageContentMapper . update ( unRecommendContent , wrapper ) ;
break ;
case ADD :
saveContentList ( query . getCoursePackageId ( ) , query . getType ( ) , query . toContentListPO ( ) , event ) ;
break ;
case DELETE :
saveContentList ( query . getCoursePackageId ( ) , query . getType ( ) , Collections . singletonList ( query . toContentPO ( ) ) , event ) ;
break ;
}
clearCache ( query . getCoursePackageId ( ) ) ;
}
/ * *
* APP端查询课程详情
*
* @param query 查询参数
* @param frontUserVO 前台用户
* @return 课程详情
* /
public CoursePackageVO getForApp ( OnlyIdQuery query , FrontUserVO frontUserVO ) {
CoursePackageVO vo = cacheService . get ( courseCache , CacheKey . CourseKey . COURSE_PACKAGE + query . getId ( ) , ( ) - > get ( query , null ) ) ;
if ( vo = = null ) {
return null ;
}
// 防止落地页修改后,未更新缓存
if ( vo . getPage ( ) ! = null ) {
vo . setPage ( pageService . getForApp ( vo . getPage ( ) . getId ( ) ) ) ;
}
if ( frontUserVO ! = null ) {
vo . setAuthResult ( appUserService . checkAuth ( vo . getAuthorityId ( ) , frontUserVO ) ) ;
}
return vo ;
}
/ * *
* APP端查询课程内容列表
*
* @param query 查询参数
* @param frontUserVO 前台用户
* @return 课程内容列表
* /
public List < CoursePackageContentVO > listContentForApp ( OnlyIdQuery query , FrontUserVO frontUserVO ) {
if ( frontUserVO ! = null ) {
CoursePackageVO vo = getForApp ( query , frontUserVO ) ;
if ( vo = = null ) {
throw new BizException ( ResponseStatus . ID_NOT_EXIST_ERROR ) ;
}
if ( vo . getAuthResult ( ) ! = null & & ! vo . getAuthResult ( ) . getAuth ( ) ) {
throw new BizException ( ResponseStatus . NOT_PRODUCT_AUTH ) ;
}
}
return cacheService . get ( CacheKey . COURSE , CacheKey . CourseKey . COURSE_PACKAGE_CONTENT + query . getId ( ) , ( ) - > {
ListCoursePackageContentQuery contentQuery = new ListCoursePackageContentQuery ( ) ;
contentQuery . setCoursePackageId ( query . getId ( ) ) ;
contentQuery . setCurrent ( 1 ) ;
contentQuery . setSize ( 10000 ) ;
List < CoursePackageContentVO > list = listContent ( contentQuery , null ) . getList ( ) ;
// 过滤合集状态
return list . stream ( )
. filter ( content - >
( content . getSerial ( ) ! = null & & SerialStatus . AUDITED . value . equals ( content . getSerial ( ) . getStatus ( ) ) ) | |
( content . getCourse ( ) ! = null & & CourseStatus . AUDITED . value . equals ( content . getCourse ( ) . getStatus ( ) ) ) )
. collect ( Collectors . toList ( ) ) ;
} ) ;
}
/ * *
* APP端查询课程列表
*
* @param query 查询参数
* @return 课程列表
* /
public AppPager < CoursePackageVO > listForApp ( ListCourseAppQuery query ) {
Integer id = query . getId ( ) ;
Integer lastId = query . getLastId ( ) ;
LocalDateTime lastPublishTime = query . getLastPublishTime ( ) ;
Integer lastWeight = query . getLastWeight ( ) ;
Integer size = query . getSize ( ) ;
NavigableSet < CourseSortEntity > sortedSet = cacheService . get ( courseCache , CacheKey . CourseKey . MAIN_COURSE_LIST + id , ( ) - > {
LambdaQueryWrapper < CoursePackage > wrapper = Wrappers . < CoursePackage > lambdaQuery ( )
. eq ( CoursePackage : : getAdvisorId , id )
. eq ( CoursePackage : : getStatus , CoursePackageStatus . AUDITED . value )
. eq ( CoursePackage : : getIsDisplay , IsDisplay . YES . value )
. orderByDesc ( CoursePackage : : getIsRecommend , CoursePackage : : getAuditTime ) ;
List < CoursePackage > list = coursePackageMapper . selectList ( wrapper ) ;
NavigableSet < CourseSortEntity > set = new TreeSet < > ( ) ;
list . stream ( ) . map ( CourseSortEntity : : new ) . forEach ( set : : add ) ;
return set ;
} ) ;
CourseSortEntity lastEntity = lastId = = null | | lastWeight = = null | | lastPublishTime = = null ? null : new CourseSortEntity ( lastId , lastWeight , lastPublishTime ) ;
if ( lastEntity ! = null ) {
sortedSet = sortedSet . tailSet ( lastEntity , false ) ;
}
List < CoursePackageVO > voList = new ArrayList < > ( size ) ;
Iterator < CourseSortEntity > iterator = sortedSet . iterator ( ) ;
while ( iterator . hasNext ( ) & & voList . size ( ) < size ) {
CourseSortEntity entity = iterator . next ( ) ;
CoursePackageVO vo = getForApp ( new OnlyIdQuery ( entity . getId ( ) ) , null ) ;
if ( vo ! = null ) {
voList . add ( vo ) ;
}
}
return new AppPager < > ( voList , iterator . hasNext ( ) ) ;
}
/ * *
* 设置首页权重
*
* @param query 查询参数
* @param backendUserVO 后台用户
* /
public void setMainPageParam ( SetMainPageQuery query , BackendUserVO backendUserVO ) {
// 不使用返回值,仅校验课程是否存在以及数据权限
if ( getEntity ( query . getId ( ) , backendUserVO ) = = null ) {
throw new BizException ( ResponseStatus . ID_NOT_EXIST_ERROR ) ;
}
CoursePackage coursePackage = query . toCoursePackagePO ( ) ;
coursePackageMapper . updateById ( coursePackage ) ;
}
/ * *
* 清除缓存
*
* @param id 课程ID
* /
private void clearCache ( Integer id ) {
courseCache . delete ( CacheKey . CourseKey . COURSE_PACKAGE + id ) ;
courseCache . delete ( CacheKey . CourseKey . COURSE_PACKAGE_CONTENT + id ) ;
}
private CoursePackage getEntity ( Integer id , BackendUserVO backendUserVO ) {
CoursePackage coursePackage = coursePackageMapper . selectById ( id ) ;
if ( coursePackage = = null ) {
return null ;
}
courseCommonService . checkAdvisorId ( coursePackage . getAdvisorId ( ) , backendUserVO ) ;
return coursePackage ;
}
private Integer getContentCount ( Integer coursePackageId ) {
LambdaQueryWrapper < CoursePackageContent > wrapper = Wrappers . < CoursePackageContent > lambdaQuery ( )
. eq ( CoursePackageContent : : getCoursePackageId , coursePackageId ) ;
List < CoursePackageContent > list = coursePackageContentMapper . selectList ( wrapper ) ;
return list . stream ( ) . mapToInt ( content - > {
if ( CoursePackageContentType . SERIAL . value . equals ( content . getType ( ) ) ) {
return serialService . getContentCount ( content . getContentId ( ) ) ;
} else if ( CoursePackageContentType . COURSE . value . equals ( content . getType ( ) ) ) {
return courseService . getContentCount ( content . getContentId ( ) ) ;
} else {
return 0 ;
}
} ) . sum ( ) ;
}
private void saveContentList ( Integer coursePackageId , Integer contentType , List < CoursePackageContent > contentListPO , UpdateContentEvent event ) {
LambdaQueryWrapper < CoursePackageContent > wrapper = Wrappers . < CoursePackageContent > lambdaQuery ( )
. select ( CoursePackageContent : : getContentId )
. eq ( CoursePackageContent : : getCoursePackageId , coursePackageId )
. eq ( CoursePackageContent : : getType , contentType ) ;
List < CoursePackageContent > existContentList = coursePackageContentMapper . selectList ( wrapper ) ;
Set < Integer > existContentIdSet = existContentList . stream ( ) . map ( CoursePackageContent : : getContentId ) . collect ( Collectors . toSet ( ) ) ;
if ( UpdateContentEvent . SAVE . equals ( event ) | | UpdateContentEvent . ADD . equals ( event ) ) {
// 添加新增的
List < CoursePackageContent > contentList = contentListPO . stream ( ) . filter ( content - > ! existContentIdSet . contains ( content . getContentId ( ) ) ) . collect ( Collectors . toList ( ) ) ;
if ( CollUtil . isNotEmpty ( contentList ) ) {
coursePackageContentMapper . insertBatchSomeColumn ( contentList ) ;
}
}
if ( UpdateContentEvent . SAVE . equals ( event ) | | UpdateContentEvent . DELETE . equals ( event ) ) {
Stream < CoursePackageContent > contentStream = Stream . empty ( ) ;
if ( UpdateContentEvent . SAVE . equals ( event ) ) {
// 删除多余的
Set < Integer > contentIdSet = contentListPO . stream ( ) . map ( CoursePackageContent : : getContentId ) . collect ( Collectors . toSet ( ) ) ;
contentStream = existContentList . stream ( ) . filter ( content - > ! contentIdSet . contains ( content . getContentId ( ) ) ) ;
} else if ( UpdateContentEvent . DELETE . equals ( event ) ) {
// 删除传入的
contentStream = contentListPO . stream ( ) ;
}
contentStream . forEach ( content - > {
LambdaQueryWrapper < CoursePackageContent > deleteWrapper = Wrappers . < CoursePackageContent > lambdaQuery ( )
. eq ( CoursePackageContent : : getCoursePackageId , coursePackageId )
. eq ( CoursePackageContent : : getContentId , content . getContentId ( ) )
. eq ( CoursePackageContent : : getType , contentType ) ;
coursePackageContentMapper . delete ( deleteWrapper ) ;
} ) ;
}
refreshUpdateTime ( coursePackageId ) ;
}
public void refreshUpdateTime ( Integer coursePackageId ) {
CoursePackage coursePackage = new CoursePackage ( ) ;
coursePackage . setId ( coursePackageId ) ;
coursePackage . setUpdateTime ( LocalDateTime . now ( ) ) ;
coursePackageMapper . updateById ( coursePackage ) ;
}
}