package com.org.flashsalesystem.service; import com.org.flashsalesystem.dto.UserDTO; import com.org.flashsalesystem.entity.Order; import com.org.flashsalesystem.entity.Product; import com.org.flashsalesystem.entity.ProductReview; import com.org.flashsalesystem.entity.User; import com.org.flashsalesystem.entity.UserFavorite; import com.org.flashsalesystem.repository.FlashSaleRepository; import com.org.flashsalesystem.repository.OrderItemRepository; import com.org.flashsalesystem.repository.OrderRepository; import com.org.flashsalesystem.repository.ProductRepository; import com.org.flashsalesystem.repository.ProductReviewRepository; import com.org.flashsalesystem.repository.UserFavoriteRepository; import com.org.flashsalesystem.repository.UserRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import javax.sql.DataSource; import java.io.File; import java.lang.management.ManagementFactory; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; import java.util.stream.Collectors; /** * 管理后台服务类 */ @Service @Slf4j public class AdminService { @Autowired private UserRepository userRepository; @Autowired private ProductRepository productRepository; @Autowired private OrderRepository orderRepository; @Autowired private OrderItemRepository orderItemRepository; @Autowired private ProductReviewRepository productReviewRepository; @Autowired private UserFavoriteRepository userFavoriteRepository; @Autowired private FlashSaleRepository flashSaleRepository; @Autowired private RedisService redisService; @Autowired private DataSource dataSource; @Autowired private RequestMetricsService requestMetricsService; /** * 获取仪表盘统计数据 */ public Map getDashboardStats() { Map stats = new HashMap<>(); try { // 总用户数 long totalUsers = userRepository.count(); stats.put("totalUsers", totalUsers); // 总商品数 long totalProducts = productRepository.count(); stats.put("totalProducts", totalProducts); // 活跃秒杀数 LocalDateTime now = LocalDateTime.now(); long activeFlashSales = flashSaleRepository.countByStartTimeLessThanEqualAndEndTimeGreaterThanEqual(now, now); stats.put("activeFlashSales", activeFlashSales); // 今日订单数 LocalDateTime startOfDay = LocalDate.now().atStartOfDay(); LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX); long todayOrders = orderRepository.countByCreatedAtBetween(startOfDay, endOfDay); stats.put("todayOrders", todayOrders); // 总订单数 long totalOrders = orderRepository.count(); stats.put("totalOrders", totalOrders); // 已支付订单数 Long paidOrdersCount = orderRepository.countByStatus(2); // 2-已支付 long paidOrders = paidOrdersCount != null ? paidOrdersCount : 0L; stats.put("paidOrders", paidOrders); // 待处理订单数 Long pendingOrdersCount = orderRepository.countByStatus(1); // 1-待支付 long pendingOrders = pendingOrdersCount != null ? pendingOrdersCount : 0L; stats.put("pendingOrders", pendingOrders); // 总交易额 BigDecimal totalAmount = orderRepository.sumTotalPriceByStatus(2); // 2-已支付 if (totalAmount == null) { totalAmount = BigDecimal.ZERO; } stats.put("totalAmount", totalAmount); log.info("获取仪表盘统计数据成功: {}", stats); } catch (Exception e) { log.error("获取仪表盘统计数据失败", e); // 返回默认值 stats.put("totalUsers", 0L); stats.put("totalProducts", 0L); stats.put("activeFlashSales", 0L); stats.put("todayOrders", 0L); stats.put("totalOrders", 0L); stats.put("paidOrders", 0L); stats.put("pendingOrders", 0L); stats.put("totalAmount", BigDecimal.ZERO); } return stats; } /** * 获取用户统计数据 */ public Map getUserStats() { Map stats = new HashMap<>(); try { // 总用户数 long totalUsers = userRepository.count(); stats.put("totalUsers", totalUsers); // 活跃用户数(最近7天登录) LocalDateTime sevenDaysAgo = LocalDateTime.now().minusDays(7); long activeUsers = userRepository.countByLastLoginAfter(sevenDaysAgo); stats.put("activeUsers", activeUsers); // 新用户数(今天注册) LocalDateTime startOfDay = LocalDate.now().atStartOfDay(); LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX); long newUsers = userRepository.countByCreatedAtBetween(startOfDay, endOfDay); stats.put("newUsers", newUsers); // 在线用户数(从Redis获取) String onlineUsersKey = "online_users"; long onlineUsers = redisService.sCard(onlineUsersKey); stats.put("onlineUsers", onlineUsers); } catch (Exception e) { log.error("获取用户统计数据失败", e); stats.put("totalUsers", 0L); stats.put("activeUsers", 0L); stats.put("newUsers", 0L); stats.put("onlineUsers", 0L); } return stats; } /** * 获取订单统计数据 */ public Map getOrderStats() { Map stats = new HashMap<>(); try { // 总订单数 long totalOrders = orderRepository.count(); stats.put("totalOrders", totalOrders); // 已支付订单数 Long paidOrdersCount = orderRepository.countByStatus(2); // 2-已支付 long paidOrders = paidOrdersCount != null ? paidOrdersCount : 0L; stats.put("paidOrders", paidOrders); // 待处理订单数 Long pendingOrdersCount = orderRepository.countByStatus(1); // 1-待支付 long pendingOrders = pendingOrdersCount != null ? pendingOrdersCount : 0L; stats.put("pendingOrders", pendingOrders); // 已取消订单数 Long cancelledOrdersCount = orderRepository.countByStatus(5); // 5-已取消 long cancelledOrders = cancelledOrdersCount != null ? cancelledOrdersCount : 0L; stats.put("cancelledOrders", cancelledOrders); // 总交易额 BigDecimal totalAmount = orderRepository.sumTotalPriceByStatus(2); // 2-已支付 if (totalAmount == null) { totalAmount = BigDecimal.ZERO; } stats.put("totalAmount", totalAmount); // 今日订单数 LocalDateTime startOfDay = LocalDate.now().atStartOfDay(); LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX); long todayOrders = orderRepository.countByCreatedAtBetween(startOfDay, endOfDay); stats.put("todayOrders", todayOrders); } catch (Exception e) { log.error("获取订单统计数据失败", e); stats.put("totalOrders", 0L); stats.put("paidOrders", 0L); stats.put("pendingOrders", 0L); stats.put("cancelledOrders", 0L); stats.put("totalAmount", BigDecimal.ZERO); stats.put("todayOrders", 0L); } return stats; } /** * 获取商品统计数据 */ public Map getProductStats() { Map stats = new HashMap<>(); try { // 总商品数 long totalProducts = productRepository.count(); stats.put("totalProducts", totalProducts); // 上架商品数 long activeProducts = productRepository.countByStatus(1); stats.put("activeProducts", activeProducts); // 下架商品数 long inactiveProducts = productRepository.countByStatus(0); stats.put("inactiveProducts", inactiveProducts); // 库存不足商品数(库存小于10) long lowStockProducts = productRepository.countByStockLessThan(10); stats.put("lowStockProducts", lowStockProducts); } catch (Exception e) { log.error("获取商品统计数据失败", e); stats.put("totalProducts", 0L); stats.put("activeProducts", 0L); stats.put("inactiveProducts", 0L); stats.put("lowStockProducts", 0L); } return stats; } /** * 获取秒杀统计数据 */ public Map getFlashSaleStats() { Map stats = new HashMap<>(); try { LocalDateTime now = LocalDateTime.now(); // 总秒杀活动数 long totalFlashSales = flashSaleRepository.count(); stats.put("totalFlashSales", totalFlashSales); // 活跃秒杀数 long activeFlashSales = flashSaleRepository.countByStartTimeLessThanEqualAndEndTimeGreaterThanEqual(now, now); stats.put("activeFlashSales", activeFlashSales); // 即将开始的秒杀数 LocalDateTime oneHourLater = now.plusHours(1); long upcomingFlashSales = flashSaleRepository.countByStartTimeBetween(now, oneHourLater); stats.put("upcomingFlashSales", upcomingFlashSales); // 已结束的秒杀数 long endedFlashSales = flashSaleRepository.countByEndTimeLessThan(now); stats.put("endedFlashSales", endedFlashSales); } catch (Exception e) { log.error("获取秒杀统计数据失败", e); stats.put("totalFlashSales", 0L); stats.put("activeFlashSales", 0L); stats.put("upcomingFlashSales", 0L); stats.put("endedFlashSales", 0L); } return stats; } /** * 获取最近订单列表 */ public List> getRecentOrders(int limit) { try { Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt")); Page orders = orderRepository.findAll(pageable); return orders.getContent().stream().map(order -> { Map orderMap = new HashMap<>(); orderMap.put("id", order.getId()); orderMap.put("username", order.getUser().getUsername()); orderMap.put("productName", order.getProduct().getName()); orderMap.put("quantity", order.getQuantity()); orderMap.put("totalAmount", order.getTotalPrice()); orderMap.put("status", order.getStatus()); orderMap.put("createdAt", order.getCreatedAt()); orderMap.put("isFlashSale", order.getOrderType() == 2); // 2表示秒杀订单 return orderMap; }).collect(Collectors.toList()); } catch (Exception e) { log.error("获取最近订单失败", e); return new ArrayList<>(); } } /** * 获取热门商品列表 */ public List> getHotProducts(int limit) { try { // 这里可以根据销量排序,暂时按创建时间排序 Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt")); Page products = productRepository.findAll(pageable); return products.getContent().stream().map(product -> { Map productMap = new HashMap<>(); productMap.put("id", product.getId()); productMap.put("name", product.getName()); productMap.put("price", product.getPrice()); productMap.put("category", product.getCategory()); productMap.put("stock", product.getStock()); productMap.put("sales", 0); // 暂时设为0,后续可以添加销量统计 return productMap; }).collect(Collectors.toList()); } catch (Exception e) { log.error("获取热门商品失败", e); return new ArrayList<>(); } } /** * 获取用户列表 */ public Map getUsers(int page, int size, String keyword, Integer status) { try { Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page userPage; if (keyword != null && !keyword.trim().isEmpty()) { userPage = userRepository.findByUsernameContainingOrEmailContaining(keyword, keyword, pageable); } else if (status != null) { userPage = userRepository.findByStatus(status, pageable); } else { userPage = userRepository.findAll(pageable); } List userDTOs = userPage.getContent().stream().map(user -> { UserDTO dto = new UserDTO(); BeanUtils.copyProperties(user, dto); dto.setPassword(null); // 不返回密码 dto.setIsOnline(redisService.sIsMember("online_users", user.getId().toString())); dto.setRole(user.getRole() == null ? ("admin".equalsIgnoreCase(user.getUsername()) ? "ADMIN" : "USER") : user.getRole()); dto.setAvatar(""); return dto; }).collect(Collectors.toList()); Map result = new HashMap<>(); result.put("users", userDTOs); result.put("total", userPage.getTotalElements()); result.put("totalPages", userPage.getTotalPages()); result.put("currentPage", page); result.put("size", size); return result; } catch (Exception e) { log.error("获取用户列表失败", e); Map result = new HashMap<>(); result.put("users", new ArrayList<>()); result.put("total", 0L); result.put("totalPages", 0); result.put("currentPage", page); result.put("size", size); return result; } } /** * 获取订单列表 */ public Map getOrders(int page, int size, String keyword, String status) { try { Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page orderPage; if (keyword != null && !keyword.trim().isEmpty()) { orderPage = orderRepository.findByIdContainingOrUserUsernameContaining(keyword, keyword, pageable); } else if (status != null && !status.trim().isEmpty()) { Integer statusInt = Integer.parseInt(status); orderPage = orderRepository.findByStatus(statusInt, pageable); } else { orderPage = orderRepository.findAll(pageable); } List> orders = orderPage.getContent().stream().map(order -> { Map orderMap = new HashMap<>(); orderMap.put("id", order.getId()); orderMap.put("username", order.getUser().getUsername()); orderMap.put("productName", order.getProduct().getName()); orderMap.put("quantity", order.getQuantity()); orderMap.put("totalAmount", order.getTotalPrice()); orderMap.put("status", order.getStatus()); orderMap.put("createdAt", order.getCreatedAt()); orderMap.put("isFlashSale", order.getOrderType() == 2); // 2表示秒杀订单 return orderMap; }).collect(Collectors.toList()); Map result = new HashMap<>(); result.put("orders", orders); result.put("total", orderPage.getTotalElements()); result.put("totalPages", orderPage.getTotalPages()); result.put("currentPage", page); result.put("size", size); return result; } catch (Exception e) { log.error("获取订单列表失败", e); Map result = new HashMap<>(); result.put("orders", new ArrayList<>()); result.put("total", 0L); result.put("totalPages", 0); result.put("currentPage", page); result.put("size", size); return result; } } /** * 获取商品列表 */ public Object getProducts(int page, int size, String keyword, String category, Integer status) { try { Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page productPage; productPage = productRepository.searchProducts( status, keyword != null && !keyword.trim().isEmpty() ? keyword.trim() : null, category != null && !category.trim().isEmpty() ? category.trim() : null, null, null, pageable ); // 转换为DTO List> productList = productPage.getContent().stream().map(product -> { Map productMap = new HashMap<>(); productMap.put("id", product.getId()); productMap.put("name", product.getName()); productMap.put("price", product.getPrice()); productMap.put("category", product.getCategory()); productMap.put("stock", product.getStock()); productMap.put("status", product.getStatus()); productMap.put("description", product.getDescription()); productMap.put("imageUrl", product.getImageUrl()); productMap.put("createdAt", product.getCreatedAt()); return productMap; }).collect(Collectors.toList()); Map result = new HashMap<>(); result.put("products", productList); result.put("total", productPage.getTotalElements()); result.put("totalPages", productPage.getTotalPages()); result.put("currentPage", page); result.put("size", size); return result; } catch (Exception e) { log.error("获取商品列表失败", e); Map result = new HashMap<>(); result.put("products", new ArrayList<>()); result.put("total", 0L); result.put("totalPages", 0); result.put("currentPage", page); result.put("size", size); return result; } } /** * 获取系统状态 */ public Object getSystemStatus() { try { Map systemStatus = new HashMap<>(); Runtime runtime = Runtime.getRuntime(); long totalMemory = runtime.totalMemory(); long freeMemory = runtime.freeMemory(); long usedMemory = totalMemory - freeMemory; double memoryUsage = totalMemory == 0 ? 0 : (double) usedMemory / totalMemory * 100; double cpuUsage = 0; java.lang.management.OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean(); if (osBean instanceof com.sun.management.OperatingSystemMXBean) { cpuUsage = ((com.sun.management.OperatingSystemMXBean) osBean).getSystemCpuLoad() * 100; if (cpuUsage < 0) { cpuUsage = 0; } } File root = new File("/"); long totalSpace = root.getTotalSpace(); long usableSpace = root.getUsableSpace(); long usedSpace = totalSpace - usableSpace; double diskUsage = totalSpace == 0 ? 0 : (double) usedSpace / totalSpace * 100; boolean dbHealthy = false; try (java.sql.Connection connection = dataSource.getConnection()) { dbHealthy = connection.isValid(2); } String redisPing = redisService.ping(); boolean redisHealthy = "PONG".equalsIgnoreCase(redisPing); String requestCountKey = "request_count:" + LocalDate.now().format(java.time.format.DateTimeFormatter.BASIC_ISO_DATE); Object requestCountValue = redisService.get(requestCountKey); long requestCountToday = requestCountValue == null ? requestMetricsService.getTotalRequests() : Long.parseLong(requestCountValue.toString()); systemStatus.put("status", dbHealthy && redisHealthy ? "正常" : "异常"); systemStatus.put("cpuUsage", Math.round(cpuUsage)); systemStatus.put("memoryUsage", Math.round(memoryUsage)); systemStatus.put("diskUsage", Math.round(diskUsage)); systemStatus.put("availableProcessors", runtime.availableProcessors()); systemStatus.put("totalMemory", totalMemory / 1024 / 1024 + "MB"); systemStatus.put("usedMemory", usedMemory / 1024 / 1024 + "MB"); systemStatus.put("dbStatus", dbHealthy ? "正常" : "异常"); systemStatus.put("redisStatus", redisHealthy ? "正常" : "异常"); systemStatus.put("requestCountToday", requestCountToday); return systemStatus; } catch (Exception e) { log.error("获取系统状态失败", e); Map errorStatus = new HashMap<>(); errorStatus.put("status", "异常"); errorStatus.put("cpuUsage", 0); errorStatus.put("memoryUsage", 0); errorStatus.put("diskUsage", 0); errorStatus.put("dbStatus", "异常"); errorStatus.put("redisStatus", "异常"); errorStatus.put("requestCountToday", requestMetricsService.getTotalRequests()); return errorStatus; } } /** * 获取Redis状态 */ public Object getRedisStatus() { try { List> redisNodes = new ArrayList<>(); Properties memoryInfo = redisService.info("memory"); Properties clientInfo = redisService.info("clients"); String ping = redisService.ping(); Map nodeStatus = new HashMap<>(); nodeStatus.put("node", "default"); nodeStatus.put("status", "PONG".equalsIgnoreCase(ping) ? "正常" : "异常"); nodeStatus.put("memory", memoryInfo.getProperty("used_memory_human", "unknown")); nodeStatus.put("connections", Integer.parseInt(clientInfo.getProperty("connected_clients", "0"))); redisNodes.add(nodeStatus); return redisNodes; } catch (Exception e) { log.error("获取Redis状态失败", e); return new ArrayList<>(); } } /** * 获取单个商品详情 */ public Object getProduct(Long id) { try { Optional productOpt = productRepository.findById(id); if (productOpt.isPresent()) { Product product = productOpt.get(); Map productMap = new HashMap<>(); productMap.put("id", product.getId()); productMap.put("name", product.getName()); productMap.put("price", product.getPrice()); productMap.put("stock", product.getStock()); productMap.put("status", product.getStatus()); productMap.put("description", product.getDescription()); productMap.put("imageUrl", product.getImageUrl()); productMap.put("createdAt", product.getCreatedAt()); productMap.put("updatedAt", product.getUpdatedAt()); long totalSales = orderItemRepository.countByProductId(product.getId()); java.math.BigDecimal totalRevenue = orderItemRepository.sumSubtotalByProductId(product.getId()); Double averageRating = productReviewRepository.findAverageRatingByProductId(product.getId()); long reviewCount = productReviewRepository.countByProductId(product.getId()); productMap.put("totalSales", totalSales); productMap.put("totalRevenue", totalRevenue == null ? 0.0 : totalRevenue); productMap.put("viewCount", 0); productMap.put("rating", averageRating == null ? 0.0 : averageRating); productMap.put("reviewCount", reviewCount); return productMap; } else { throw new RuntimeException("商品不存在"); } } catch (Exception e) { log.error("获取商品详情失败", e); throw new RuntimeException("获取商品详情失败"); } } /** * 更新商品 */ public void updateProduct(Long id, Map productData) { try { Optional productOpt = productRepository.findById(id); if (productOpt.isPresent()) { Product product = productOpt.get(); if (productData.containsKey("name")) { product.setName((String) productData.get("name")); } if (productData.containsKey("price")) { product.setPrice(new BigDecimal(productData.get("price").toString())); } if (productData.containsKey("stock")) { product.setStock(Integer.parseInt(productData.get("stock").toString())); } if (productData.containsKey("category")) { product.setCategory((String) productData.get("category")); } if (productData.containsKey("status")) { product.setStatus(Integer.parseInt(productData.get("status").toString())); } if (productData.containsKey("description")) { product.setDescription((String) productData.get("description")); } if (productData.containsKey("imageUrl")) { product.setImageUrl((String) productData.get("imageUrl")); } product.setUpdatedAt(LocalDateTime.now()); productRepository.save(product); } else { throw new RuntimeException("商品不存在"); } } catch (Exception e) { log.error("更新商品失败", e); throw new RuntimeException("更新商品失败: " + e.getMessage()); } } /** * 删除商品 */ public void deleteProduct(Long id) { try { if (productRepository.existsById(id)) { productRepository.deleteById(id); } else { throw new RuntimeException("商品不存在"); } } catch (Exception e) { log.error("删除商品失败", e); throw new RuntimeException("删除商品失败: " + e.getMessage()); } } /** * 添加商品 */ public Object addProduct(Map productData) { try { Product product = new Product(); product.setName((String) productData.get("name")); product.setPrice(new BigDecimal(productData.get("price").toString())); product.setCategory((String) productData.getOrDefault("category", "默认分类")); product.setStock(Integer.parseInt(productData.get("stock").toString())); product.setStatus(Integer.parseInt(productData.get("status").toString())); product.setDescription((String) productData.get("description")); product.setImageUrl((String) productData.get("imageUrl")); product.setCreatedAt(LocalDateTime.now()); product.setUpdatedAt(LocalDateTime.now()); Product savedProduct = productRepository.save(product); Map result = new HashMap<>(); result.put("id", savedProduct.getId()); result.put("name", savedProduct.getName()); result.put("price", savedProduct.getPrice()); result.put("category", savedProduct.getCategory()); result.put("stock", savedProduct.getStock()); result.put("status", savedProduct.getStatus()); result.put("description", savedProduct.getDescription()); result.put("imageUrl", savedProduct.getImageUrl()); result.put("createdAt", savedProduct.getCreatedAt()); return result; } catch (Exception e) { log.error("添加商品失败", e); throw new RuntimeException("添加商品失败: " + e.getMessage()); } } public Map getReviewStats() { Map stats = new HashMap<>(); List reviews = productReviewRepository.findAll(); LocalDateTime startOfDay = LocalDate.now().atStartOfDay(); long todayReviews = reviews.stream().filter(item -> item.getCreatedAt() != null && item.getCreatedAt().isAfter(startOfDay)).count(); double averageRating = reviews.isEmpty() ? 0.0 : reviews.stream().mapToInt(ProductReview::getRating).average().orElse(0.0); stats.put("totalReviews", reviews.size()); stats.put("todayReviews", todayReviews); stats.put("averageRating", averageRating); stats.put("fiveStarReviews", reviews.stream().filter(item -> item.getRating() == 5).count()); return stats; } public Map getFavoriteStats() { Map stats = new HashMap<>(); List favorites = userFavoriteRepository.findAll(); stats.put("totalFavorites", favorites.size()); stats.put("favoriteUsers", favorites.stream().map(UserFavorite::getUserId).distinct().count()); stats.put("favoriteProducts", favorites.stream().map(UserFavorite::getProductId).distinct().count()); stats.put("todayFavorites", favorites.stream().filter(item -> item.getCreatedAt() != null && item.getCreatedAt().isAfter(LocalDate.now().atStartOfDay())).count()); return stats; } public Map getReviews(int page, int size, String keyword) { List> rows = productReviewRepository.findAll(Sort.by(Sort.Direction.DESC, "createdAt")) .stream() .map(review -> { Map item = new HashMap<>(); item.put("id", review.getId()); item.put("productId", review.getProductId()); item.put("userId", review.getUserId()); item.put("orderId", review.getOrderId()); item.put("rating", review.getRating()); item.put("content", review.getContent()); item.put("status", review.getStatus()); item.put("statusText", review.getStatus() != null && review.getStatus() == 1 ? "显示" : "隐藏"); item.put("adminReply", review.getAdminReply()); item.put("repliedAt", review.getRepliedAt()); item.put("createdAt", review.getCreatedAt()); Product product = productRepository.findById(review.getProductId()).orElse(null); User user = userRepository.findById(review.getUserId()).orElse(null); item.put("productName", product != null ? product.getName() : "未知商品"); item.put("username", user != null ? user.getUsername() : "未知用户"); return item; }) .filter(item -> { if (keyword == null || keyword.trim().isEmpty()) return true; String value = keyword.trim().toLowerCase(); return String.valueOf(item.get("productName")).toLowerCase().contains(value) || String.valueOf(item.get("username")).toLowerCase().contains(value) || String.valueOf(item.get("content")).toLowerCase().contains(value); }) .collect(Collectors.toList()); return paginate(rows, page, size, "reviews"); } public Object updateReview(Long id, com.org.flashsalesystem.dto.ProductReviewDTO.UpdateDTO updateDTO) { ProductReview review = productReviewRepository.findById(id) .orElseThrow(() -> new RuntimeException("评价不存在")); if (updateDTO.getStatus() != null) { review.setStatus(updateDTO.getStatus()); } if (updateDTO.getAdminReply() != null) { review.setAdminReply(updateDTO.getAdminReply()); review.setRepliedAt(java.time.LocalDateTime.now()); } review = productReviewRepository.save(review); Map result = new HashMap<>(); result.put("id", review.getId()); result.put("status", review.getStatus()); result.put("statusText", review.getStatus() != null && review.getStatus() == 1 ? "显示" : "隐藏"); result.put("adminReply", review.getAdminReply()); result.put("repliedAt", review.getRepliedAt()); return result; } public void deleteReview(Long id) { productReviewRepository.deleteById(id); } public Map getFavorites(int page, int size, String keyword) { List> rows = userFavoriteRepository.findAll(Sort.by(Sort.Direction.DESC, "createdAt")) .stream() .map(favorite -> { Map item = new HashMap<>(); item.put("id", favorite.getId()); item.put("userId", favorite.getUserId()); item.put("productId", favorite.getProductId()); item.put("createdAt", favorite.getCreatedAt()); Product product = productRepository.findById(favorite.getProductId()).orElse(null); User user = userRepository.findById(favorite.getUserId()).orElse(null); item.put("productName", product != null ? product.getName() : "未知商品"); item.put("productCategory", product != null ? product.getCategory() : "默认分类"); item.put("username", user != null ? user.getUsername() : "未知用户"); return item; }) .filter(item -> { if (keyword == null || keyword.trim().isEmpty()) return true; String value = keyword.trim().toLowerCase(); return String.valueOf(item.get("productName")).toLowerCase().contains(value) || String.valueOf(item.get("username")).toLowerCase().contains(value); }) .collect(Collectors.toList()); return paginate(rows, page, size, "favorites"); } public void deleteFavorite(Long id) { userFavoriteRepository.deleteById(id); } private Map paginate(List> rows, int page, int size, String key) { int currentPage = Math.max(page, 1); int pageSize = Math.max(size, 1); int fromIndex = Math.min((currentPage - 1) * pageSize, rows.size()); int toIndex = Math.min(fromIndex + pageSize, rows.size()); Map result = new HashMap<>(); result.put(key, rows.subList(fromIndex, toIndex)); result.put("total", rows.size()); result.put("totalPages", (int) Math.ceil(rows.size() * 1.0 / pageSize)); result.put("currentPage", currentPage); result.put("size", pageSize); return result; } }