440 lines
17 KiB
Java
440 lines
17 KiB
Java
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<AchievementMapper, Achievement> implements AchievementService {
|
|
|
|
@Autowired
|
|
private SnowflakeIdGenerator snowflakeIdGenerator;
|
|
|
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
@Override
|
|
public IPage<Achievement> getPage(AchievementPageRequest request) {
|
|
Page<Achievement> page = new Page<>(request.getCurrent(), request.getSize());
|
|
LambdaQueryWrapper<Achievement> 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<Achievement> getByCategory(String category) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getCategory, category)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getCreateTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getByRarity(String rarity) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getRarity, rarity)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getCreateTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getByConditionType(String conditionType) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getConditionType, conditionType)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getCreateTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getUnlockedAchievements() {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.isNotNull(Achievement::getUnlockedTime)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getUnlockedTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getLockedAchievements() {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.isNull(Achievement::getUnlockedTime)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getCreateTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getHiddenAchievements() {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getIsHidden, 1)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getCreateTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getVisibleAchievements() {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getIsHidden, 0)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getCreateTime);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getByProgressRange(Double minProgress, Double maxProgress) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.between(Achievement::getProgress, minProgress, maxProgress)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getProgress);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getByUnlockTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
|
|
LambdaQueryWrapper<Achievement> 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<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.isNotNull(Achievement::getUnlockedTime)
|
|
.eq(Achievement::getIsDeleted, 0);
|
|
return this.count(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public Long countLockedAchievements() {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.isNull(Achievement::getUnlockedTime)
|
|
.eq(Achievement::getIsDeleted, 0);
|
|
return this.count(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public Long countByCategory(String category) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getCategory, category)
|
|
.eq(Achievement::getIsDeleted, 0);
|
|
return this.count(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public Long countByRarity(String rarity) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.eq(Achievement::getRarity, rarity)
|
|
.eq(Achievement::getIsDeleted, 0);
|
|
return this.count(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public Double getAvgProgress() {
|
|
List<Achievement> achievements = this.list(new LambdaQueryWrapper<Achievement>()
|
|
.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<Achievement> achievements = this.list(new LambdaQueryWrapper<Achievement>()
|
|
.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<Achievement> getRecentlyUnlocked(Integer limit) {
|
|
LambdaQueryWrapper<Achievement> wrapper = new LambdaQueryWrapper<>();
|
|
wrapper.isNotNull(Achievement::getUnlockedTime)
|
|
.eq(Achievement::getIsDeleted, 0)
|
|
.orderByDesc(Achievement::getUnlockedTime)
|
|
.last("LIMIT " + limit);
|
|
return this.list(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getNearCompletion() {
|
|
LambdaQueryWrapper<Achievement> 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<Achievement> getRareAchievements() {
|
|
LambdaQueryWrapper<Achievement> 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<Achievement> 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<Achievement> 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<Achievement> wrapper = new LambdaUpdateWrapper<>();
|
|
wrapper.eq(Achievement::getId, id)
|
|
.set(Achievement::getIsHidden, isHidden)
|
|
.set(Achievement::getUpdateTime, LocalDateTime.now());
|
|
return this.update(wrapper);
|
|
}
|
|
|
|
@Override
|
|
public List<Achievement> getRecommendedAchievements(String category, String rarity, Integer limit) {
|
|
LambdaQueryWrapper<Achievement> 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<AchievementResponse> getPageWithResponse(AchievementPageRequest request) {
|
|
IPage<Achievement> page = getPage(request);
|
|
List<AchievementResponse> responses = page.getRecords().stream()
|
|
.map(this::convertToResponse)
|
|
.collect(Collectors.toList());
|
|
PageResult<AchievementResponse> 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<AchievementResponse> getByCategoryWithResponse(String category) {
|
|
List<Achievement> achievements = getByCategory(category);
|
|
return achievements.stream()
|
|
.map(this::convertToResponse)
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
@Override
|
|
public List<AchievementResponse> getByRarityWithResponse(String rarity) {
|
|
List<Achievement> achievements = getByRarity(rarity);
|
|
return achievements.stream()
|
|
.map(this::convertToResponse)
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
@Override
|
|
public List<AchievementResponse> getUnlockedAchievementsWithResponse() {
|
|
List<Achievement> achievements = getUnlockedAchievements();
|
|
return achievements.stream()
|
|
.map(this::convertToResponse)
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
@Override
|
|
public List<AchievementResponse> getLockedAchievementsWithResponse() {
|
|
List<Achievement> achievements = getLockedAchievements();
|
|
return achievements.stream()
|
|
.map(this::convertToResponse)
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
@Override
|
|
public List<AchievementResponse> getRecentlyUnlockedWithResponse(Integer limit) {
|
|
List<Achievement> 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;
|
|
}
|
|
} |