- 完善 User/Product/Order 实体字段和关联关系 - 更新 DTO 适配新增字段 - 增强 Service 层业务逻辑和 Repository 查询方法 - 优化控制器接口,完善管理后台 API - 新增请求监控过滤器和指标服务
856 lines
36 KiB
Java
856 lines
36 KiB
Java
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<String, Object> getDashboardStats() {
|
||
Map<String, Object> 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<String, Object> getUserStats() {
|
||
Map<String, Object> 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<String, Object> getOrderStats() {
|
||
Map<String, Object> 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<String, Object> getProductStats() {
|
||
Map<String, Object> 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<String, Object> getFlashSaleStats() {
|
||
Map<String, Object> 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<Map<String, Object>> getRecentOrders(int limit) {
|
||
try {
|
||
Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt"));
|
||
Page<Order> orders = orderRepository.findAll(pageable);
|
||
|
||
return orders.getContent().stream().map(order -> {
|
||
Map<String, Object> 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<Map<String, Object>> getHotProducts(int limit) {
|
||
try {
|
||
// 这里可以根据销量排序,暂时按创建时间排序
|
||
Pageable pageable = PageRequest.of(0, limit, Sort.by(Sort.Direction.DESC, "createdAt"));
|
||
Page<Product> products = productRepository.findAll(pageable);
|
||
|
||
return products.getContent().stream().map(product -> {
|
||
Map<String, Object> 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<String, Object> getUsers(int page, int size, String keyword, Integer status) {
|
||
try {
|
||
Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
|
||
Page<User> 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<UserDTO> 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<String, Object> 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<String, Object> 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<String, Object> getOrders(int page, int size, String keyword, String status) {
|
||
try {
|
||
Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt"));
|
||
Page<Order> 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<Map<String, Object>> orders = orderPage.getContent().stream().map(order -> {
|
||
Map<String, Object> 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<String, Object> 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<String, Object> 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<Product> 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<Map<String, Object>> productList = productPage.getContent().stream().map(product -> {
|
||
Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<Map<String, Object>> redisNodes = new ArrayList<>();
|
||
Properties memoryInfo = redisService.info("memory");
|
||
Properties clientInfo = redisService.info("clients");
|
||
String ping = redisService.ping();
|
||
|
||
Map<String, Object> 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<Product> productOpt = productRepository.findById(id);
|
||
if (productOpt.isPresent()) {
|
||
Product product = productOpt.get();
|
||
Map<String, Object> 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<String, Object> productData) {
|
||
try {
|
||
Optional<Product> 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<String, Object> 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<String, Object> 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<String, Object> getReviewStats() {
|
||
Map<String, Object> stats = new HashMap<>();
|
||
List<ProductReview> 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<String, Object> getFavoriteStats() {
|
||
Map<String, Object> stats = new HashMap<>();
|
||
List<UserFavorite> 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<String, Object> getReviews(int page, int size, String keyword) {
|
||
List<Map<String, Object>> rows = productReviewRepository.findAll(Sort.by(Sort.Direction.DESC, "createdAt"))
|
||
.stream()
|
||
.map(review -> {
|
||
Map<String, Object> 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<String, Object> 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<String, Object> getFavorites(int page, int size, String keyword) {
|
||
List<Map<String, Object>> rows = userFavoriteRepository.findAll(Sort.by(Sort.Direction.DESC, "createdAt"))
|
||
.stream()
|
||
.map(favorite -> {
|
||
Map<String, Object> 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<String, Object> paginate(List<Map<String, Object>> 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<String, Object> 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;
|
||
}
|
||
|
||
}
|