package com.tcm.training.admin.live.service; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.tcm.training.admin.common.Jsons; import com.tcm.training.admin.common.PageResponse; import com.tcm.training.admin.live.dto.LiveCourseStatusRequest; import com.tcm.training.admin.live.dto.LiveCourseUpsertRequest; import com.tcm.training.admin.live.dto.LiveCoursePasswordRequest; import com.tcm.training.admin.live.dto.LiveCoursePasswordVerifyRequest; import com.tcm.training.admin.live.entity.Expert; import com.tcm.training.admin.live.entity.LiveCourse; import com.tcm.training.admin.live.entity.LiveSession; import com.tcm.training.admin.live.entity.LiveSessionQuestion; import com.tcm.training.admin.live.mapper.ExpertMapper; import com.tcm.training.admin.live.mapper.LiveCourseMapper; import com.tcm.training.admin.live.mapper.LiveSessionMapper; import com.tcm.training.admin.live.mapper.LiveSessionQuestionMapper; import com.tcm.training.admin.live.vo.ExpertVO; import com.tcm.training.admin.live.vo.LiveCourseDetailVO; import com.tcm.training.admin.live.vo.LiveCourseListItemVO; import com.tcm.training.admin.live.vo.LiveCourseListRow; import com.tcm.training.admin.live.vo.LiveCourseDetailRow; import com.tcm.training.admin.live.vo.LiveCourseStatusVO; import org.springframework.stereotype.Service; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Service public class LiveCourseAppService { private static final int LIVE_ROOM_PASSWORD_TYPE = 1; private final LiveCourseMapper liveCourseMapper; private final ExpertMapper expertMapper; private final LiveSessionMapper liveSessionMapper; private final LiveSessionQuestionMapper liveSessionQuestionMapper; private final BCryptPasswordEncoder passwordEncoder; public LiveCourseAppService(LiveCourseMapper liveCourseMapper, ExpertMapper expertMapper, LiveSessionMapper liveSessionMapper, LiveSessionQuestionMapper liveSessionQuestionMapper, BCryptPasswordEncoder passwordEncoder) { this.liveCourseMapper = liveCourseMapper; this.expertMapper = expertMapper; this.liveSessionMapper = liveSessionMapper; this.liveSessionQuestionMapper = liveSessionQuestionMapper; this.passwordEncoder = passwordEncoder; } public PageResponse page(int page, int pageSize, String keyword, Long expertId, Integer status, Integer liveStatus) { IPage p = liveCourseMapper.selectCoursePage(new Page(page, pageSize), keyword, expertId, status, liveStatus); List list = new ArrayList(); for (LiveCourseListRow row : p.getRecords()) { LiveCourseListItemVO vo = new LiveCourseListItemVO(); vo.setId(row.getId()); vo.setTitle(row.getTitle()); vo.setLevel(row.getLevel()); vo.setExpert(new ExpertVO(row.getExpertId(), row.getExpertName(), row.getExpertAvatar())); vo.setCoverImg(row.getCoverImg()); vo.setReserveCount(row.getReserveCount() == null ? 0L : row.getReserveCount()); vo.setWatchCount(row.getWatchCount() == null ? 0L : row.getWatchCount()); vo.setQuizPoints(row.getQuizPoints()); vo.setStartTime(row.getStartTime()); vo.setLiveStatus(row.getLiveStatus()); vo.setStatus(row.getStatus()); vo.setCreatedAt(row.getCreatedAt()); list.add(vo); } return PageResponse.of(list, p.getTotal(), p.getCurrent(), p.getSize()); } @Transactional public LiveCourseDetailVO create(LiveCourseUpsertRequest req) { throw new IllegalArgumentException("直播课程为初始化数据,禁止新增"); /* validateExpert(req.getExpertId()); LiveCourse course = new LiveCourse(); course.setTitle(req.getTitle()); course.setLevel(req.getLevel()); course.setExpertId(req.getExpertId()); course.setCoverImg(req.getCoverImg()); course.setBannerImgs(req.getBannerImgs()); course.setIntro(req.getIntro()); course.setTargetUsers(req.getTargetUsers()); course.setQuizDelayMinutes(req.getQuizDelayMinutes()); course.setQuizPoints(req.getQuizPoints()); course.setStatus(req.getStatus()); liveCourseMapper.insert(course); return detail(course.getId()); */ } public LiveCourseDetailVO detail(Long id) { LiveCourseDetailRow row = liveCourseMapper.selectCourseDetail(id); if (row == null) { throw new IllegalArgumentException("课程不存在"); } LiveCourseDetailVO vo = new LiveCourseDetailVO(); vo.setId(row.getId()); vo.setTitle(row.getTitle()); vo.setLevel(row.getLevel()); vo.setExpert(new ExpertVO(row.getExpertId(), row.getExpertName(), row.getExpertAvatar())); vo.setCoverImg(row.getCoverImg()); vo.setBannerImgs(Jsons.parseStringList(row.getBannerImgs())); vo.setIntro(row.getIntro()); vo.setTargetUsers(row.getTargetUsers()); vo.setQuizDelayMinutes(row.getQuizDelayMinutes()); vo.setQuizPoints(row.getQuizPoints()); vo.setStartTime(row.getStartTime()); vo.setVideoUrl(row.getVideoUrl()); vo.setLiveStatus(row.getLiveStatus()); vo.setStatus(row.getStatus()); vo.setReserveCount(row.getReserveCount() == null ? 0L : row.getReserveCount()); vo.setWatchCount(row.getWatchCount() == null ? 0L : row.getWatchCount()); vo.setCreatedAt(row.getCreatedAt()); vo.setUpdatedAt(row.getUpdatedAt()); return vo; } @Transactional public LiveCourseDetailVO update(Long id, LiveCourseUpsertRequest req) { validateExpert(req.getExpertId()); LiveCourse course = liveCourseMapper.selectById(id); if (course == null) { throw new IllegalArgumentException("课程不存在"); } course.setTitle(req.getTitle()); course.setLevel(req.getLevel()); course.setExpertId(req.getExpertId()); course.setCoverImg(req.getCoverImg()); course.setBannerImgs(req.getBannerImgs()); course.setIntro(req.getIntro()); course.setTargetUsers(req.getTargetUsers()); course.setQuizDelayMinutes(req.getQuizDelayMinutes()); course.setQuizPoints(req.getQuizPoints()); course.setStatus(req.getStatus()); liveCourseMapper.updateById(course); return detail(id); } @Transactional public LiveCourseStatusVO patchStatus(Long id, LiveCourseStatusRequest req) { LiveCourse course = liveCourseMapper.selectById(id); if (course == null) { throw new IllegalArgumentException("课程不存在"); } course.setStatus(req.getStatus()); liveCourseMapper.updateById(course); return new LiveCourseStatusVO(id, req.getStatus()); } @Transactional public void updatePassword(Long id, LiveCoursePasswordRequest req) { String password = req.getPassword(); if (StrUtil.isNotBlank(password)) { if (password.length() != 6) { throw new IllegalArgumentException("直播间密码必须是6个字符"); } } LiveCourse course = liveCourseMapper.selectById(id); if (course == null) { throw new IllegalArgumentException("课程不存在"); } if (StrUtil.isNotBlank(password)) { course.setPassword(passwordEncoder.encode(req.getPassword())); } else { course.setPassword(null); } liveCourseMapper.updateById(course); } public boolean verifyPassword(LiveCoursePasswordVerifyRequest req) { if (req.getType() != LIVE_ROOM_PASSWORD_TYPE) { throw new IllegalArgumentException("不支持的密码类型"); } LiveCourse course = liveCourseMapper.selectOne(new LambdaQueryWrapper() .isNotNull(LiveCourse::getPassword) .orderByAsc(LiveCourse::getId) .last("limit 1")); return course != null && course.getPassword() != null && !course.getPassword().isEmpty() && passwordEncoder.matches(req.getPassword(), course.getPassword()); } @Transactional public void delete(Long id) { throw new IllegalArgumentException("直播课程为初始化数据,禁止删除"); } private void validateExpert(Long expertId) { Expert expert = expertMapper.selectById(expertId); if (expert == null) { throw new IllegalArgumentException("授课专家不存在"); } if (expert.getStatus() != null && expert.getStatus() != 1) { throw new IllegalArgumentException("授课专家已禁用"); } } }