package com.emotion.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.emotion.common.PageResult; import com.emotion.dto.request.achievement.AchievementCreateRequest; import com.emotion.dto.request.achievement.AchievementPageRequest; import com.emotion.dto.request.achievement.AchievementUpdateRequest; import com.emotion.dto.response.achievement.AchievementResponse; import com.emotion.entity.Achievement; import com.emotion.mapper.AchievementMapper; import com.emotion.service.AchievementService; import com.emotion.util.SnowflakeIdGenerator; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; import java.util.stream.Collectors; /** * 成就服务实现类 * * @author huazhongmin * @date 2025-09-08 */ @Service public class AchievementServiceImpl extends ServiceImpl implements AchievementService { @Autowired private SnowflakeIdGenerator snowflakeIdGenerator; private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); @Override public IPage getPage(AchievementPageRequest request) { Page page = new Page<>(request.getCurrent(), request.getSize()); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // 关键词搜索 if (StringUtils.hasText(request.getKeyword())) { wrapper.and(w -> w.like(Achievement::getTitle, request.getKeyword()) .or().like(Achievement::getDescription, request.getKeyword())); } // 分类筛选 if (StringUtils.hasText(request.getCategory())) { wrapper.eq(Achievement::getCategory, request.getCategory()); } // 稀有度筛选 if (StringUtils.hasText(request.getRarity())) { wrapper.eq(Achievement::getRarity, request.getRarity()); } // 解锁状态筛选 if (request.getUnlocked() != null) { if (request.getUnlocked()) { wrapper.isNotNull(Achievement::getUnlockedTime); } else { wrapper.isNull(Achievement::getUnlockedTime); } } // 隐藏状态筛选 if (request.getHidden() != null) { wrapper.eq(Achievement::getIsHidden, request.getHidden() ? 1 : 0); } wrapper.eq(Achievement::getIsDeleted, 0); // 排序 if (StringUtils.hasText(request.getOrderBy())) { if ("asc".equalsIgnoreCase(request.getOrderDirection())) { wrapper.orderByAsc(Achievement::getCreateTime); } else { wrapper.orderByDesc(Achievement::getCreateTime); } } else { wrapper.orderByDesc(Achievement::getCreateTime); } return this.page(page, wrapper); } @Override public List getByCategory(String category) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getCategory, category) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public List getByRarity(String rarity) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getRarity, rarity) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public List getByConditionType(String conditionType) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getConditionType, conditionType) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public List getUnlockedAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.isNotNull(Achievement::getUnlockedTime) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getUnlockedTime); return this.list(wrapper); } @Override public List getLockedAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.isNull(Achievement::getUnlockedTime) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public List getHiddenAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getIsHidden, 1) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public List getVisibleAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getIsHidden, 0) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public List getByProgressRange(Double minProgress, Double maxProgress) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.between(Achievement::getProgress, minProgress, maxProgress) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getProgress); return this.list(wrapper); } @Override public List getByUnlockTimeRange(LocalDateTime startTime, LocalDateTime endTime) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.between(Achievement::getUnlockedTime, startTime, endTime) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getUnlockedTime); return this.list(wrapper); } @Override public Long countUnlockedAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.isNotNull(Achievement::getUnlockedTime) .eq(Achievement::getIsDeleted, 0); return this.count(wrapper); } @Override public Long countLockedAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.isNull(Achievement::getUnlockedTime) .eq(Achievement::getIsDeleted, 0); return this.count(wrapper); } @Override public Long countByCategory(String category) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getCategory, category) .eq(Achievement::getIsDeleted, 0); return this.count(wrapper); } @Override public Long countByRarity(String rarity) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getRarity, rarity) .eq(Achievement::getIsDeleted, 0); return this.count(wrapper); } @Override public Double getAvgProgress() { List achievements = this.list(new LambdaQueryWrapper() .eq(Achievement::getIsDeleted, 0) .isNotNull(Achievement::getProgress)); return achievements.stream() .mapToDouble(a -> a.getProgress() != null ? a.getProgress().doubleValue() : 0.0) .average() .orElse(0.0); } @Override public Double getAvgProgressByCategory(String category) { List achievements = this.list(new LambdaQueryWrapper() .eq(Achievement::getCategory, category) .eq(Achievement::getIsDeleted, 0) .isNotNull(Achievement::getProgress)); return achievements.stream() .mapToDouble(a -> a.getProgress() != null ? a.getProgress().doubleValue() : 0.0) .average() .orElse(0.0); } @Override public List getRecentlyUnlocked(Integer limit) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.isNotNull(Achievement::getUnlockedTime) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getUnlockedTime) .last("LIMIT " + limit); return this.list(wrapper); } @Override public List getNearCompletion() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.gt(Achievement::getProgress, 80) .isNull(Achievement::getUnlockedTime) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getProgress); return this.list(wrapper); } @Override public List getRareAchievements() { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.in(Achievement::getRarity, "legendary", "epic") .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime); return this.list(wrapper); } @Override public boolean unlockAchievement(String id, LocalDateTime unlockedTime) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(Achievement::getId, id) .set(Achievement::getUnlockedTime, unlockedTime) .set(Achievement::getProgress, 100) .set(Achievement::getUpdateTime, LocalDateTime.now()); return this.update(wrapper); } @Override public boolean updateProgress(String id, Double progress) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(Achievement::getId, id) .set(Achievement::getProgress, progress) .set(Achievement::getUpdateTime, LocalDateTime.now()); return this.update(wrapper); } @Override public boolean updateHiddenStatus(String id, Integer isHidden) { LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(Achievement::getId, id) .set(Achievement::getIsHidden, isHidden) .set(Achievement::getUpdateTime, LocalDateTime.now()); return this.update(wrapper); } @Override public List getRecommendedAchievements(String category, String rarity, Integer limit) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(Achievement::getCategory, category) .eq(Achievement::getRarity, rarity) .isNull(Achievement::getUnlockedTime) .eq(Achievement::getIsHidden, 0) .eq(Achievement::getIsDeleted, 0) .orderByDesc(Achievement::getCreateTime) .last("LIMIT " + limit); return this.list(wrapper); } // 新增的Response相关方法实现 @Override public PageResult getPageWithResponse(AchievementPageRequest request) { IPage page = getPage(request); List responses = page.getRecords().stream() .map(this::convertToResponse) .collect(Collectors.toList()); PageResult pageResult = new PageResult<>(); pageResult.setCurrent(page.getCurrent()); pageResult.setSize(page.getSize()); pageResult.setTotal(page.getTotal()); pageResult.setPages(page.getPages()); pageResult.setRecords(responses); return pageResult; } @Override public AchievementResponse getAchievementResponseById(String id) { Achievement achievement = this.getById(id); if (achievement == null) { return null; } return convertToResponse(achievement); } @Override public AchievementResponse createAchievementWithResponse(AchievementCreateRequest request) { Achievement achievement = new Achievement(); org.springframework.beans.BeanUtils.copyProperties(request, achievement); achievement.setId(snowflakeIdGenerator.nextIdAsString()); boolean saved = this.save(achievement); if (!saved) { return null; } return convertToResponse(achievement); } @Override public AchievementResponse updateAchievementWithResponse(AchievementUpdateRequest request) { Achievement achievement = this.getById(request.getId()); if (achievement == null) { return null; } // 更新非空字段 if (request.getTitle() != null) { achievement.setTitle(request.getTitle()); } if (request.getDescription() != null) { achievement.setDescription(request.getDescription()); } if (request.getCategory() != null) { achievement.setCategory(request.getCategory()); } if (request.getIcon() != null) { achievement.setIcon(request.getIcon()); } if (request.getRarity() != null) { achievement.setRarity(request.getRarity()); } if (request.getConditionType() != null) { achievement.setConditionType(request.getConditionType()); } if (request.getConditionValue() != null) { achievement.setConditionValue(request.getConditionValue()); } if (request.getRewards() != null) { achievement.setRewards(request.getRewards()); } if (request.getIsHidden() != null) { achievement.setIsHidden(request.getIsHidden()); } achievement.setUpdateTime(LocalDateTime.now()); boolean updated = this.updateById(achievement); if (!updated) { return null; } return convertToResponse(achievement); } @Override public List getByCategoryWithResponse(String category) { List achievements = getByCategory(category); return achievements.stream() .map(this::convertToResponse) .collect(Collectors.toList()); } @Override public List getByRarityWithResponse(String rarity) { List achievements = getByRarity(rarity); return achievements.stream() .map(this::convertToResponse) .collect(Collectors.toList()); } @Override public List getUnlockedAchievementsWithResponse() { List achievements = getUnlockedAchievements(); return achievements.stream() .map(this::convertToResponse) .collect(Collectors.toList()); } @Override public List getLockedAchievementsWithResponse() { List achievements = getLockedAchievements(); return achievements.stream() .map(this::convertToResponse) .collect(Collectors.toList()); } @Override public List getRecentlyUnlockedWithResponse(Integer limit) { List achievements = getRecentlyUnlocked(limit); return achievements.stream() .map(this::convertToResponse) .collect(Collectors.toList()); } /** * 转换为响应对象 */ private AchievementResponse convertToResponse(Achievement achievement) { AchievementResponse response = new AchievementResponse(); org.springframework.beans.BeanUtils.copyProperties(achievement, response); response.setId(achievement.getId()); if (achievement.getCreateTime() != null) { response.setCreateTime(achievement.getCreateTime().format(DATE_TIME_FORMATTER)); } if (achievement.getUpdateTime() != null) { response.setUpdateTime(achievement.getUpdateTime().format(DATE_TIME_FORMATTER)); } if (achievement.getUnlockedTime() != null) { response.setUnlockedTime(achievement.getUnlockedTime().format(DATE_TIME_FORMATTER)); } return response; } }