package com.tcm.training.admin.system.service; 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.PageResponse; import com.tcm.training.admin.live.entity.HealthCourse; import com.tcm.training.admin.live.entity.LiveCourse; import com.tcm.training.admin.live.mapper.HealthCourseMapper; import com.tcm.training.admin.live.mapper.LiveCourseMapper; import com.tcm.training.admin.system.dto.SystemBannerBatchDeleteRequest; import com.tcm.training.admin.system.dto.SystemBannerPublishStatusRequest; import com.tcm.training.admin.system.dto.SystemBannerSaveRequest; import com.tcm.training.admin.system.entity.SystemBannerConfig; import com.tcm.training.admin.system.mapper.SystemBannerConfigMapper; import com.tcm.training.admin.system.vo.SystemBannerCourseOptionVO; import com.tcm.training.admin.system.vo.SystemBannerDetailVO; import com.tcm.training.admin.system.vo.SystemBannerListItemVO; import com.tcm.training.admin.system.vo.SystemBannerPublishStatusVO; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @Service public class SystemBannerAppService { private final SystemBannerConfigMapper systemBannerConfigMapper; private final HealthCourseMapper healthCourseMapper; private final LiveCourseMapper liveCourseMapper; public SystemBannerAppService(SystemBannerConfigMapper systemBannerConfigMapper, HealthCourseMapper healthCourseMapper, LiveCourseMapper liveCourseMapper) { this.systemBannerConfigMapper = systemBannerConfigMapper; this.healthCourseMapper = healthCourseMapper; this.liveCourseMapper = liveCourseMapper; } public PageResponse page(int page, int pageSize, String title, Integer status) { LambdaQueryWrapper qw = new LambdaQueryWrapper() .eq(SystemBannerConfig::getDeleted, 0) .orderByDesc(SystemBannerConfig::getId); String trimmedTitle = trimToNull(title); if (trimmedTitle != null) { qw.like(SystemBannerConfig::getTitle, trimmedTitle); } LocalDateTime now = LocalDateTime.now(); if (status != null) { if (status == SystemBannerConfig.DISPLAY_STATUS_NOT_STARTED) { qw.gt(SystemBannerConfig::getStartAt, now); } else if (status == SystemBannerConfig.DISPLAY_STATUS_ONGOING) { qw.le(SystemBannerConfig::getStartAt, now).ge(SystemBannerConfig::getEndAt, now); } else if (status == SystemBannerConfig.DISPLAY_STATUS_ENDED) { qw.lt(SystemBannerConfig::getEndAt, now); } else { throw new IllegalArgumentException("状态筛选不合法"); } } IPage result = systemBannerConfigMapper.selectPage(new Page(page, pageSize), qw); List list = new ArrayList(); for (SystemBannerConfig item : result.getRecords()) { list.add(toListItem(item)); } return PageResponse.of(list, result.getTotal(), result.getCurrent(), result.getSize()); } public SystemBannerDetailVO detail(Long id) { return toDetailVO(requireItem(id)); } @Transactional public SystemBannerDetailVO create(SystemBannerSaveRequest request) { SystemBannerConfig item = new SystemBannerConfig(); fillEntity(item, request); item.setDeleted(0); systemBannerConfigMapper.insert(item); return detail(item.getId()); } @Transactional public SystemBannerDetailVO update(Long id, SystemBannerSaveRequest request) { SystemBannerConfig item = requireItem(id); fillEntity(item, request); systemBannerConfigMapper.updateById(item); return detail(id); } @Transactional public SystemBannerPublishStatusVO patchPublishStatus(Long id, SystemBannerPublishStatusRequest request) { SystemBannerConfig item = requireItem(id); item.setPublishEnabled(booleanToInteger(request.getPublishEnabled())); systemBannerConfigMapper.updateById(item); return new SystemBannerPublishStatusVO(id, request.getPublishEnabled()); } @Transactional public void delete(Long id) { requireItem(id); systemBannerConfigMapper.deleteById(id); } @Transactional public void batchDelete(SystemBannerBatchDeleteRequest request) { Set ids = new LinkedHashSet(request.getIds()); if (ids.isEmpty()) { throw new IllegalArgumentException("请选择要删除的banner"); } for (Long id : ids) { requireItem(id); } systemBannerConfigMapper.deleteBatchIds(new ArrayList(ids)); } public List healthCourseOptions(String keyword) { List list = healthCourseMapper.selectList(new LambdaQueryWrapper() .eq(HealthCourse::getDeleted, 0) .like(keyword != null && !keyword.trim().isEmpty(), HealthCourse::getTitle, keyword == null ? null : keyword.trim()) .orderByAsc(HealthCourse::getSort) .orderByDesc(HealthCourse::getId)); List options = new ArrayList(); for (HealthCourse item : list) { options.add(new SystemBannerCourseOptionVO(item.getId(), item.getTitle())); } return options; } public List liveCourseOptions(String keyword) { List list = liveCourseMapper.selectList(new LambdaQueryWrapper() .eq(LiveCourse::getDeleted, 0) .like(keyword != null && !keyword.trim().isEmpty(), LiveCourse::getTitle, keyword == null ? null : keyword.trim()) .orderByDesc(LiveCourse::getId)); List options = new ArrayList(); for (LiveCourse item : list) { options.add(new SystemBannerCourseOptionVO(item.getId(), item.getTitle())); } return options; } private void fillEntity(SystemBannerConfig item, SystemBannerSaveRequest request) { LocalDateTime startAt = request.getStartAt(); LocalDateTime endAt = request.getEndAt(); if (!endAt.isAfter(startAt)) { throw new IllegalArgumentException("banner结束时间必须晚于开始时间"); } String jumpType = normalizeJumpType(request.getJumpType()); item.setBannerImg(request.getBannerImg().trim()); item.setTitle(request.getTitle().trim()); item.setStartAt(startAt); item.setEndAt(endAt); item.setJumpType(jumpType); item.setPublishEnabled(booleanToInteger(request.getPublishEnabled())); if (SystemBannerConfig.JUMP_TYPE_HEALTH_COURSE.equals(jumpType)) { HealthCourse course = requireHealthCourse(request.getTargetId()); item.setTargetId(course.getId()); item.setTargetName(course.getTitle()); item.setTargetUrl(null); return; } if (SystemBannerConfig.JUMP_TYPE_LIVE_COURSE.equals(jumpType)) { LiveCourse course = requireLiveCourse(request.getTargetId()); item.setTargetId(course.getId()); item.setTargetName(course.getTitle()); item.setTargetUrl(null); return; } if (SystemBannerConfig.JUMP_TYPE_MEMBER.equals(jumpType)) { item.setTargetId(null); item.setTargetName("会员"); item.setTargetUrl(null); return; } String targetUrl = trimToNull(request.getTargetUrl()); if (targetUrl == null) { throw new IllegalArgumentException("请输入地址信息"); } item.setTargetId(null); item.setTargetName(null); item.setTargetUrl(targetUrl); } private String normalizeJumpType(String jumpType) { if (jumpType == null) { throw new IllegalArgumentException("请选择跳转类型"); } String normalized = jumpType.trim().toUpperCase(); if (SystemBannerConfig.JUMP_TYPE_HEALTH_COURSE.equals(normalized) || SystemBannerConfig.JUMP_TYPE_LIVE_COURSE.equals(normalized) || SystemBannerConfig.JUMP_TYPE_MEMBER.equals(normalized) || SystemBannerConfig.JUMP_TYPE_THIRD_PARTY_URL.equals(normalized)) { return normalized; } throw new IllegalArgumentException("跳转类型不合法"); } private HealthCourse requireHealthCourse(Long targetId) { if (targetId == null) { throw new IllegalArgumentException("请选择养生课程"); } HealthCourse course = healthCourseMapper.selectById(targetId); if (course == null || defaultNumber(course.getDeleted()) == 1) { throw new IllegalArgumentException("养生课程不存在"); } return course; } private LiveCourse requireLiveCourse(Long targetId) { if (targetId == null) { throw new IllegalArgumentException("请选择直播课程"); } LiveCourse course = liveCourseMapper.selectById(targetId); if (course == null || defaultNumber(course.getDeleted()) == 1) { throw new IllegalArgumentException("直播课程不存在"); } return course; } private SystemBannerConfig requireItem(Long id) { SystemBannerConfig item = systemBannerConfigMapper.selectOne(new LambdaQueryWrapper() .eq(SystemBannerConfig::getId, id) .eq(SystemBannerConfig::getDeleted, 0) .last("limit 1")); if (item == null) { throw new IllegalArgumentException("banner不存在"); } return item; } private SystemBannerListItemVO toListItem(SystemBannerConfig item) { SystemBannerListItemVO vo = new SystemBannerListItemVO(); vo.setId(item.getId()); vo.setBannerImg(item.getBannerImg()); vo.setTitle(item.getTitle()); vo.setStartAt(item.getStartAt()); vo.setEndAt(item.getEndAt()); vo.setStatus(resolveDisplayStatus(item.getStartAt(), item.getEndAt())); vo.setPublishEnabled(integerToBoolean(item.getPublishEnabled())); vo.setJumpType(item.getJumpType()); vo.setJumpTargetDisplay(resolveJumpTargetDisplay(item)); vo.setCreatedAt(item.getCreatedAt()); return vo; } private SystemBannerDetailVO toDetailVO(SystemBannerConfig item) { SystemBannerDetailVO vo = new SystemBannerDetailVO(); vo.setId(item.getId()); vo.setBannerImg(item.getBannerImg()); vo.setTitle(item.getTitle()); vo.setStartAt(item.getStartAt()); vo.setEndAt(item.getEndAt()); vo.setJumpType(item.getJumpType()); vo.setTargetId(item.getTargetId()); vo.setTargetName(item.getTargetName()); vo.setTargetUrl(item.getTargetUrl()); vo.setPublishEnabled(integerToBoolean(item.getPublishEnabled())); vo.setStatus(resolveDisplayStatus(item.getStartAt(), item.getEndAt())); vo.setCreatedAt(item.getCreatedAt()); vo.setUpdatedAt(item.getUpdatedAt()); return vo; } private Integer resolveDisplayStatus(LocalDateTime startAt, LocalDateTime endAt) { LocalDateTime now = LocalDateTime.now(); if (startAt != null && now.isBefore(startAt)) { return SystemBannerConfig.DISPLAY_STATUS_NOT_STARTED; } if (endAt != null && now.isAfter(endAt)) { return SystemBannerConfig.DISPLAY_STATUS_ENDED; } return SystemBannerConfig.DISPLAY_STATUS_ONGOING; } private String resolveJumpTargetDisplay(SystemBannerConfig item) { if (SystemBannerConfig.JUMP_TYPE_MEMBER.equals(item.getJumpType())) { return "会员"; } if (SystemBannerConfig.JUMP_TYPE_THIRD_PARTY_URL.equals(item.getJumpType())) { return item.getTargetUrl(); } return item.getTargetName(); } private Integer booleanToInteger(Boolean value) { return Boolean.TRUE.equals(value) ? 1 : 0; } private Boolean integerToBoolean(Integer value) { return value != null && value == 1; } private Integer defaultNumber(Integer value) { return value == null ? 0 : value; } private String trimToNull(String value) { if (value == null) { return null; } String trimmed = value.trim(); return trimmed.isEmpty() ? null : trimmed; } }