package com.tourguide.modules.user.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.tourguide.common.api.PageResponse;
|
import com.tourguide.common.exception.BusinessException;
|
import com.tourguide.common.validation.ChineseIdCardValidator;
|
import com.tourguide.modules.order.dto.VisitorOrderStatRow;
|
import com.tourguide.modules.order.mapper.TourOrderMapper;
|
import com.tourguide.modules.review.dto.VisitorReviewStatRow;
|
import com.tourguide.modules.review.mapper.OrderReviewMapper;
|
import com.tourguide.modules.user.dto.MiniProfileUpdateRequest;
|
import com.tourguide.modules.user.dto.MiniRealNameUpdateRequest;
|
import com.tourguide.modules.user.dto.MiniUserDetailResponse;
|
import com.tourguide.modules.user.dto.MiniUserResponse;
|
import com.tourguide.modules.user.entity.MiniUser;
|
import com.tourguide.modules.user.mapper.MiniUserMapper;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
import java.math.BigDecimal;
|
import java.time.LocalDate;
|
import java.util.Collections;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.stream.Collectors;
|
|
/** 仅处理小程序用户,管理后台只能通过本服务执行查询或状态管理。 */
|
@Service
|
public class MiniUserService {
|
private final MiniUserMapper userMapper;
|
private final TourOrderMapper orderMapper;
|
private final OrderReviewMapper reviewMapper;
|
|
public MiniUserService(MiniUserMapper userMapper, TourOrderMapper orderMapper, OrderReviewMapper reviewMapper) {
|
this.userMapper = userMapper;
|
this.orderMapper = orderMapper;
|
this.reviewMapper = reviewMapper;
|
}
|
|
public MiniUser findEnabledById(Long id) {
|
MiniUser user = userMapper.selectById(id);
|
if (user == null || user.getStatus() == null || user.getStatus() != 1) {
|
throw new BusinessException(401, "小程序用户不存在或已停用");
|
}
|
return user;
|
}
|
|
public MiniUser findByUsername(String username) {
|
return userMapper.selectOne(new LambdaQueryWrapper<MiniUser>().eq(MiniUser::getUsername, username).last("LIMIT 1"));
|
}
|
|
public PageResponse<MiniUserResponse> page(long page, long size, String keyword, Integer status,
|
LocalDate startDate, LocalDate endDate) {
|
LambdaQueryWrapper<MiniUser> query = new LambdaQueryWrapper<MiniUser>();
|
if (StringUtils.hasText(keyword)) {
|
String searchKeyword = keyword.trim();
|
query.and(wrapper -> {
|
wrapper.like(MiniUser::getUsername, searchKeyword)
|
.or().like(MiniUser::getNickname, searchKeyword)
|
.or().like(MiniUser::getMobile, searchKeyword);
|
if (searchKeyword.matches("\\d+")) {
|
wrapper.or().eq(MiniUser::getId, Long.valueOf(searchKeyword));
|
}
|
});
|
}
|
query.eq(status != null, MiniUser::getStatus, status)
|
.ge(startDate != null, MiniUser::getCreatedAt, startDate == null ? null : startDate.atStartOfDay())
|
.lt(endDate != null, MiniUser::getCreatedAt, endDate == null ? null : endDate.plusDays(1).atStartOfDay())
|
.orderByDesc(MiniUser::getId);
|
Page<MiniUser> result = userMapper.selectPage(new Page<MiniUser>(page, size), query);
|
List<MiniUser> users = result.getRecords();
|
Map<Long, UserStats> statsByUserId = loadUserStats(
|
users.stream().map(MiniUser::getId).collect(Collectors.toList()));
|
return new PageResponse<MiniUserResponse>(users.stream()
|
.map(user -> MiniUserResponse.from(user, statsOf(statsByUserId, user.getId()).orderCount))
|
.collect(Collectors.toList()),
|
result.getTotal(), result.getCurrent(), result.getSize());
|
}
|
|
public MiniUserDetailResponse detail(Long id) {
|
MiniUser user = userMapper.selectById(id);
|
if (user == null) { throw new BusinessException(404, "游客不存在"); }
|
UserStats stats = statsOf(loadUserStats(Collections.singletonList(id)), id);
|
return MiniUserDetailResponse.from(user, stats.orderCount, stats.totalConsumption, stats.reviewCount);
|
}
|
|
private Map<Long, UserStats> loadUserStats(List<Long> visitorIds) {
|
if (visitorIds.isEmpty()) { return Collections.emptyMap(); }
|
Map<Long, UserStats> statsByUserId = new HashMap<Long, UserStats>();
|
for (Long visitorId : visitorIds) {
|
statsByUserId.put(visitorId, new UserStats());
|
}
|
List<VisitorOrderStatRow> orderRows = orderMapper.selectVisitorOrderStats(visitorIds);
|
if (orderRows != null) {
|
for (VisitorOrderStatRow row : orderRows) {
|
if (row.getVisitorId() == null) { continue; }
|
UserStats stats = statsByUserId.computeIfAbsent(row.getVisitorId(), ignored -> new UserStats());
|
stats.orderCount = defaultLong(row.getOrderCount());
|
stats.totalConsumption = row.getTotalConsumption() == null ? BigDecimal.ZERO : row.getTotalConsumption();
|
}
|
}
|
List<VisitorReviewStatRow> reviewRows = reviewMapper.selectVisitorReviewStats(visitorIds);
|
if (reviewRows != null) {
|
for (VisitorReviewStatRow row : reviewRows) {
|
if (row.getVisitorId() == null) { continue; }
|
statsByUserId.computeIfAbsent(row.getVisitorId(), ignored -> new UserStats())
|
.reviewCount = defaultLong(row.getReviewCount());
|
}
|
}
|
return statsByUserId;
|
}
|
|
private static UserStats statsOf(Map<Long, UserStats> statsByUserId, Long userId) {
|
UserStats stats = statsByUserId.get(userId);
|
return stats == null ? new UserStats() : stats;
|
}
|
|
private static long defaultLong(Long value) {
|
return value == null ? 0L : value;
|
}
|
|
@Transactional
|
public MiniUserResponse updateProfile(Long id, MiniProfileUpdateRequest request) {
|
MiniUser user = findEnabledById(id);
|
user.setNickname(request.getNickname().trim());
|
userMapper.updateById(user);
|
return MiniUserResponse.from(user);
|
}
|
|
@Transactional
|
public MiniUserResponse updateAvatar(Long id, String avatar) {
|
MiniUser user = findEnabledById(id);
|
user.setAvatar(avatar);
|
userMapper.updateById(user);
|
return MiniUserResponse.from(user);
|
}
|
|
@Transactional
|
public MiniUserResponse updateRealName(Long id, MiniRealNameUpdateRequest request) {
|
MiniUser user = findEnabledById(id);
|
String idCardNo = request.getIdCardNo().trim().toUpperCase();
|
if (!ChineseIdCardValidator.isValid(idCardNo)) {
|
throw new BusinessException(400, "身份证号格式不正确");
|
}
|
if (userMapper.selectCount(new LambdaQueryWrapper<MiniUser>()
|
.eq(MiniUser::getIdCardNo, idCardNo)
|
.ne(MiniUser::getId, id)) > 0) {
|
throw new BusinessException(409, "该身份证号已被其他账号使用");
|
}
|
user.setRealName(request.getRealName().trim());
|
user.setIdCardNo(idCardNo);
|
userMapper.updateById(user);
|
return MiniUserResponse.from(user);
|
}
|
|
@Transactional
|
public void updateStatus(Long id, Integer status) {
|
MiniUser user = userMapper.selectById(id);
|
if (user == null) { throw new BusinessException(404, "小程序用户不存在"); }
|
user.setStatus(status);
|
userMapper.updateById(user);
|
}
|
|
private static final class UserStats {
|
private long orderCount;
|
private BigDecimal totalConsumption = BigDecimal.ZERO;
|
private long reviewCount;
|
}
|
}
|