骑行模块代码

This commit is contained in:
周鹏 committed 2026-09-13 08:55:09 +08:00
1 parent 377f9f56c7
commit 329c96f733
5 files changed
+89

No files matched your search

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordCreateReqVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordPageReqVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordRespVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordStatsRespVO;
import cn.iocoder.yudao.module.member.service.rideplan.MemberRideRecordService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -78,6 +79,14 @@ public class AppRideRecordController {
return success(rideRecordService.getCornerRank(roadName, cornerName));
}
@GetMapping("/stats")
@Operation(summary = "批量骑手战报统计(免登录)", description = "返回每个骑手的战报数/最佳压弯/总里程;最多 100 人")
@PermitAll
public CommonResult<List<AppRideRecordStatsRespVO>> stats(
@RequestParam("userIds") @Size(max = 100, message = "一次最多查询 100 个骑手") List<Long> userIds) {
return success(rideRecordService.getRideRecordStats(userIds));
}
@PostMapping("/like")
@Operation(summary = "点赞/取消点赞(需登录)", description = "幂等切换,返回操作后是否处于点赞状态")
@Parameter(name = "recordId", description = "战报编号", required = true, example = "1")
@@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.member.controller.app.rideplan.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 用户 APP - 骑手战报统计 Response VO
*
* 供首页骑友列表 / 骑友主页展示「战报数 / 最佳压弯 / 总里程」骑行数据行,
* 批量接口避免列表逐人查询。
*/
@Schema(description = "用户 APP - 骑手战报统计 Response VO")
@Data
public class AppRideRecordStatsRespVO {
@Schema(description = "骑手用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long userId;
@Schema(description = "战报数量(正常状态)", requiredMode = Schema.RequiredMode.REQUIRED, example = "3")
private Long reportCount;
@Schema(description = "最佳压弯角度(度)", requiredMode = Schema.RequiredMode.REQUIRED, example = "38.5")
private Double bestLean;
@Schema(description = "总里程(公里)", requiredMode = Schema.RequiredMode.REQUIRED, example = "260.8")
private Double totalKm;
}
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordPa
import cn.iocoder.yudao.module.member.dal.dataobject.rideplan.MemberRideRecordDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.Collection;
import java.util.List;
@Mapper
@@ -56,4 +57,13 @@ public interface MemberRideRecordMapper extends BaseMapperX<MemberRideRecordDO>
.eq(MemberRideRecordDO::getStatus, status));
}
/**
* 批量查一批骑手的正常状态战报(用于列表/主页骑行数据统计)
*/
default List<MemberRideRecordDO> selectNormalByUserIds(Collection<Long> userIds) {
return selectList(new LambdaQueryWrapperX<MemberRideRecordDO>()
.in(MemberRideRecordDO::getUserId, userIds)
.eq(MemberRideRecordDO::getStatus, 0));
}
}
@@ -4,7 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordCreateReqVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordPageReqVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordRespVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordStatsRespVO;
import java.util.Collection;
import java.util.List;
/**
@@ -42,6 +44,11 @@ public interface MemberRideRecordService {
*/
boolean toggleLike(Long userId, Long recordId);
/**
* 批量骑手战报统计(免登录):战报数 / 最佳压弯 / 总里程,供列表与主页骑行数据行
*/
List<AppRideRecordStatsRespVO> getRideRecordStats(Collection<Long> userIds);
/**
* 举报战报(需登录),达到阈值自动下架
*/
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordCreateReqVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordPageReqVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordRespVO;
import cn.iocoder.yudao.module.member.controller.app.rideplan.vo.AppRideRecordStatsRespVO;
import cn.iocoder.yudao.module.member.dal.dataobject.rideplan.MemberRideRecordDO;
import cn.iocoder.yudao.module.member.dal.dataobject.rideplan.MemberRideRecordLikeDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
@@ -18,6 +19,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -143,6 +145,39 @@ public class MemberRideRecordServiceImpl implements MemberRideRecordService {
return boards;
}
@Override
public List<AppRideRecordStatsRespVO> getRideRecordStats(Collection<Long> userIds) {
if (userIds == null || userIds.isEmpty()) {
return Collections.emptyList();
}
List<MemberRideRecordDO> records = rideRecordMapper.selectNormalByUserIds(userIds);
if (records.isEmpty()) {
return Collections.emptyList();
}
Map<Long, List<MemberRideRecordDO>> grouped = records.stream()
.collect(Collectors.groupingBy(MemberRideRecordDO::getUserId));
List<AppRideRecordStatsRespVO> statsList = new ArrayList<>(grouped.size());
for (Map.Entry<Long, List<MemberRideRecordDO>> entry : grouped.entrySet()) {
java.math.BigDecimal best = java.math.BigDecimal.ZERO;
java.math.BigDecimal totalKm = java.math.BigDecimal.ZERO;
for (MemberRideRecordDO r : entry.getValue()) {
if (r.getMaxLean() != null && r.getMaxLean().compareTo(best) > 0) {
best = r.getMaxLean();
}
if (r.getDistanceKm() != null) {
totalKm = totalKm.add(r.getDistanceKm());
}
}
AppRideRecordStatsRespVO vo = new AppRideRecordStatsRespVO();
vo.setUserId(entry.getKey());
vo.setReportCount((long) entry.getValue().size());
vo.setBestLean(best.doubleValue());
vo.setTotalKm(totalKm.doubleValue());
statsList.add(vo);
}
return statsList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean toggleLike(Long userId, Long recordId) {