Showing
21 changed files
with
521 additions
and
35 deletions
| ... | @@ -27,7 +27,55 @@ | ... | @@ -27,7 +27,55 @@ |
| 27 | - `message`: 响应消息 | 27 | - `message`: 响应消息 |
| 28 | - `data`: 响应数据,具体内容根据接口而定 | 28 | - `data`: 响应数据,具体内容根据接口而定 |
| 29 | 29 | ||
| 30 | -## 1. 认证管理 (AuthController) | 30 | +## 1. 首页仪表板 (DashboardController) |
| 31 | + | ||
| 32 | +### 1.1 获取首页统计数据 | ||
| 33 | + | ||
| 34 | +**接口路径:** `GET /api/dashboard/stats` | ||
| 35 | + | ||
| 36 | +**功能描述:** 获取首页仪表板的统计数据,包括今日订单、待出库、待开票、销售额等信息 | ||
| 37 | + | ||
| 38 | +**请求头:** | ||
| 39 | +``` | ||
| 40 | +Authorization: Bearer <JWT_TOKEN> | ||
| 41 | +``` | ||
| 42 | + | ||
| 43 | +**响应示例:** | ||
| 44 | +```json | ||
| 45 | +{ | ||
| 46 | + "code": 200, | ||
| 47 | + "message": "获取统计数据成功", | ||
| 48 | + "data": { | ||
| 49 | + "todayOrderCount": 23, | ||
| 50 | + "pendingDeliveryCount": 8, | ||
| 51 | + "pendingInvoiceCount": 5, | ||
| 52 | + "todaySalesAmount": 125680.50, | ||
| 53 | + "onlineUserCount": 156, | ||
| 54 | + "systemStatus": "正常运行", | ||
| 55 | + "systemVersion": "v1.0.0" | ||
| 56 | + } | ||
| 57 | +} | ||
| 58 | +``` | ||
| 59 | + | ||
| 60 | +**错误响应示例:** | ||
| 61 | +```json | ||
| 62 | +{ | ||
| 63 | + "code": 500, | ||
| 64 | + "message": "获取统计数据失败: 数据库连接异常", | ||
| 65 | + "data": null | ||
| 66 | +} | ||
| 67 | +``` | ||
| 68 | + | ||
| 69 | +**响应字段说明:** | ||
| 70 | +- `todayOrderCount`: 今日订单数量 | ||
| 71 | +- `pendingDeliveryCount`: 待出库数量 | ||
| 72 | +- `pendingInvoiceCount`: 待开票数量 | ||
| 73 | +- `todaySalesAmount`: 今日销售额 | ||
| 74 | +- `onlineUserCount`: 在线用户数 | ||
| 75 | +- `systemStatus`: 系统状态 | ||
| 76 | +- `systemVersion`: 系统版本 | ||
| 77 | + | ||
| 78 | +## 2. 认证管理 (AuthController) | ||
| 31 | 79 | ||
| 32 | ### 1.1 用户登录 | 80 | ### 1.1 用户登录 |
| 33 | 81 | ... | ... |
| 1 | package com.apple.erp.config; | 1 | package com.apple.erp.config; |
| 2 | - | ||
| 3 | -import com.apple.erp.utils.JwtUtils; | ||
| 4 | import org.springframework.beans.factory.annotation.Autowired; | 2 | import org.springframework.beans.factory.annotation.Autowired; |
| 5 | import org.springframework.context.annotation.Bean; | 3 | import org.springframework.context.annotation.Bean; |
| 6 | import org.springframework.context.annotation.Configuration; | 4 | import org.springframework.context.annotation.Configuration; |
| ... | @@ -34,9 +32,6 @@ import java.util.Arrays; | ... | @@ -34,9 +32,6 @@ import java.util.Arrays; |
| 34 | public class SecurityConfig { | 32 | public class SecurityConfig { |
| 35 | 33 | ||
| 36 | @Autowired | 34 | @Autowired |
| 37 | - private JwtUtils jwtUtils; | ||
| 38 | - | ||
| 39 | - @Autowired | ||
| 40 | private JwtAuthenticationFilter jwtAuthenticationFilter; | 35 | private JwtAuthenticationFilter jwtAuthenticationFilter; |
| 41 | 36 | ||
| 42 | @Autowired | 37 | @Autowired |
| ... | @@ -72,6 +67,7 @@ public class SecurityConfig { | ... | @@ -72,6 +67,7 @@ public class SecurityConfig { |
| 72 | .antMatchers("/api/auth/**").permitAll() | 67 | .antMatchers("/api/auth/**").permitAll() |
| 73 | .antMatchers("/api/public/**").permitAll() | 68 | .antMatchers("/api/public/**").permitAll() |
| 74 | .antMatchers("/api/test/public").permitAll() // 允许测试接口 | 69 | .antMatchers("/api/test/public").permitAll() // 允许测试接口 |
| 70 | + .antMatchers("/api/dashboard/**").authenticated() // 首页统计需要认证 | ||
| 75 | .antMatchers("/actuator/**").permitAll() | 71 | .antMatchers("/actuator/**").permitAll() |
| 76 | .antMatchers("/druid/**").permitAll() | 72 | .antMatchers("/druid/**").permitAll() |
| 77 | .antMatchers("/swagger-ui/**").permitAll() | 73 | .antMatchers("/swagger-ui/**").permitAll() | ... | ... |
| ... | @@ -9,6 +9,7 @@ import com.apple.erp.dto.response.UserInfoRes; | ... | @@ -9,6 +9,7 @@ import com.apple.erp.dto.response.UserInfoRes; |
| 9 | import com.apple.erp.entity.SysUser; | 9 | import com.apple.erp.entity.SysUser; |
| 10 | import com.apple.erp.service.SysUserService; | 10 | import com.apple.erp.service.SysUserService; |
| 11 | import com.apple.erp.service.SysLogService; | 11 | import com.apple.erp.service.SysLogService; |
| 12 | +import com.apple.erp.service.SessionService; | ||
| 12 | import com.apple.erp.utils.JwtUtils; | 13 | import com.apple.erp.utils.JwtUtils; |
| 13 | import io.swagger.v3.oas.annotations.Operation; | 14 | import io.swagger.v3.oas.annotations.Operation; |
| 14 | import io.swagger.v3.oas.annotations.Parameter; | 15 | import io.swagger.v3.oas.annotations.Parameter; |
| ... | @@ -24,7 +25,9 @@ import org.springframework.web.bind.annotation.*; | ... | @@ -24,7 +25,9 @@ import org.springframework.web.bind.annotation.*; |
| 24 | 25 | ||
| 25 | import javax.servlet.http.HttpServletRequest; | 26 | import javax.servlet.http.HttpServletRequest; |
| 26 | import javax.validation.Valid; | 27 | import javax.validation.Valid; |
| 28 | +import java.util.HashMap; | ||
| 27 | import java.util.List; | 29 | import java.util.List; |
| 30 | +import java.util.Map; | ||
| 28 | 31 | ||
| 29 | /** | 32 | /** |
| 30 | * 认证控制器 | 33 | * 认证控制器 |
| ... | @@ -51,6 +54,9 @@ public class AuthController { | ... | @@ -51,6 +54,9 @@ public class AuthController { |
| 51 | 54 | ||
| 52 | @Autowired | 55 | @Autowired |
| 53 | private SysLogService sysLogService; | 56 | private SysLogService sysLogService; |
| 57 | + | ||
| 58 | + @Autowired | ||
| 59 | + private SessionService sessionService; | ||
| 54 | 60 | ||
| 55 | /** | 61 | /** |
| 56 | * 用户登录 | 62 | * 用户登录 |
| ... | @@ -95,6 +101,21 @@ public class AuthController { | ... | @@ -95,6 +101,21 @@ public class AuthController { |
| 95 | // 生成JWT令牌 | 101 | // 生成JWT令牌 |
| 96 | String token = jwtUtils.generateToken(username); | 102 | String token = jwtUtils.generateToken(username); |
| 97 | String refreshToken = jwtUtils.generateRefreshToken(username); | 103 | String refreshToken = jwtUtils.generateRefreshToken(username); |
| 104 | + | ||
| 105 | + // 将用户会话信息存储到Redis | ||
| 106 | + try { | ||
| 107 | + Map<String, Object> sessionData = new HashMap<>(); | ||
| 108 | + sessionData.put("username", username); | ||
| 109 | + sessionData.put("loginTime", System.currentTimeMillis()); | ||
| 110 | + sessionData.put("clientIp", getClientIp(request)); | ||
| 111 | + sessionData.put("token", token); | ||
| 112 | + | ||
| 113 | + sessionService.storeUserSession(username, sessionData); | ||
| 114 | + log.info("用户会话已存储: {}", username); | ||
| 115 | + } catch (Exception e) { | ||
| 116 | + log.error("存储用户会话失败", e); | ||
| 117 | + // Redis失败不影响登录流程 | ||
| 118 | + } | ||
| 98 | 119 | ||
| 99 | LoginRes loginResponse = new LoginRes(token, refreshToken, username); | 120 | LoginRes loginResponse = new LoginRes(token, refreshToken, username); |
| 100 | ApiRes<LoginRes> response = ApiRes.success("登录成功", loginResponse); | 121 | ApiRes<LoginRes> response = ApiRes.success("登录成功", loginResponse); |
| ... | @@ -192,6 +213,16 @@ public class AuthController { | ... | @@ -192,6 +213,16 @@ public class AuthController { |
| 192 | } | 213 | } |
| 193 | } | 214 | } |
| 194 | 215 | ||
| 216 | + // 清除Redis中的用户会话 | ||
| 217 | + if (username != null) { | ||
| 218 | + try { | ||
| 219 | + sessionService.removeUserSession(username); | ||
| 220 | + log.info("用户会话已清除: {}", username); | ||
| 221 | + } catch (Exception e) { | ||
| 222 | + log.error("清除用户会话失败", e); | ||
| 223 | + } | ||
| 224 | + } | ||
| 225 | + | ||
| 195 | // 清除Spring Security上下文 | 226 | // 清除Spring Security上下文 |
| 196 | SecurityContextHolder.clearContext(); | 227 | SecurityContextHolder.clearContext(); |
| 197 | 228 | ... | ... |
| 1 | +package com.apple.erp.controller; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.response.ApiRes; | ||
| 4 | +import com.apple.erp.dto.response.DashboardStatsRes; | ||
| 5 | +import com.apple.erp.service.DashboardService; | ||
| 6 | +import lombok.extern.slf4j.Slf4j; | ||
| 7 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 8 | +import org.springframework.web.bind.annotation.GetMapping; | ||
| 9 | +import org.springframework.web.bind.annotation.RequestMapping; | ||
| 10 | +import org.springframework.web.bind.annotation.RestController; | ||
| 11 | + | ||
| 12 | +import java.util.List; | ||
| 13 | +import java.util.Map; | ||
| 14 | + | ||
| 15 | +/** | ||
| 16 | + * 首页仪表板控制器 | ||
| 17 | + * 提供首页统计数据接口 | ||
| 18 | + */ | ||
| 19 | +@Slf4j | ||
| 20 | +@RestController | ||
| 21 | +@RequestMapping("/api/dashboard") | ||
| 22 | +public class DashboardController { | ||
| 23 | + | ||
| 24 | + @Autowired | ||
| 25 | + private DashboardService dashboardService; | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * 获取首页统计数据 | ||
| 29 | + * @return 统计数据 | ||
| 30 | + */ | ||
| 31 | + @GetMapping("/stats") | ||
| 32 | + public ApiRes<DashboardStatsRes> getDashboardStats() { | ||
| 33 | + log.info("获取首页统计数据请求"); | ||
| 34 | + try { | ||
| 35 | + DashboardStatsRes result = dashboardService.getDashboardStats(); | ||
| 36 | + log.info("首页统计数据获取成功: {}", result); | ||
| 37 | + return ApiRes.success("获取统计数据成功", result); | ||
| 38 | + } catch (Exception e) { | ||
| 39 | + log.error("获取首页统计数据失败", e); | ||
| 40 | + return ApiRes.error(500, "获取统计数据失败: " + e.getMessage()); | ||
| 41 | + } | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + /** | ||
| 45 | + * 测试接口 | ||
| 46 | + * @return 测试数据 | ||
| 47 | + */ | ||
| 48 | + @GetMapping("/test") | ||
| 49 | + public ApiRes<DashboardStatsRes> getTestStats() { | ||
| 50 | + log.info("测试接口调用"); | ||
| 51 | + DashboardStatsRes stats = new DashboardStatsRes(); | ||
| 52 | + stats.setTodayOrderCount(10); | ||
| 53 | + stats.setPendingDeliveryCount(5); | ||
| 54 | + stats.setPendingInvoiceCount(3); | ||
| 55 | + stats.setTodaySalesAmount(10000.0); | ||
| 56 | + stats.setOnlineUserCount(100); | ||
| 57 | + stats.setSystemStatus("测试正常"); | ||
| 58 | + stats.setSystemVersion("v1.0.0"); | ||
| 59 | + | ||
| 60 | + return ApiRes.success("测试成功", stats); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + /** | ||
| 64 | + * 获取最近活动 | ||
| 65 | + * @return 最近活动列表 | ||
| 66 | + */ | ||
| 67 | + @GetMapping("/activities") | ||
| 68 | + public ApiRes<List<Map<String, Object>>> getRecentActivities() { | ||
| 69 | + log.info("获取最近活动请求"); | ||
| 70 | + try { | ||
| 71 | + List<Map<String, Object>> activities = dashboardService.getRecentActivities(); | ||
| 72 | + return ApiRes.success("获取最近活动成功", activities); | ||
| 73 | + } catch (Exception e) { | ||
| 74 | + log.error("获取最近活动失败", e); | ||
| 75 | + return ApiRes.error(500, "获取最近活动失败: " + e.getMessage()); | ||
| 76 | + } | ||
| 77 | + } | ||
| 78 | +} |
| 1 | +package com.apple.erp.dto.response; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 首页统计数据响应DTO | ||
| 7 | + */ | ||
| 8 | +@Data | ||
| 9 | +public class DashboardStatsRes { | ||
| 10 | + | ||
| 11 | + /** | ||
| 12 | + * 今日订单数量 | ||
| 13 | + */ | ||
| 14 | + private Integer todayOrderCount; | ||
| 15 | + | ||
| 16 | + /** | ||
| 17 | + * 待出库数量 | ||
| 18 | + */ | ||
| 19 | + private Integer pendingDeliveryCount; | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 待开票数量 | ||
| 23 | + */ | ||
| 24 | + private Integer pendingInvoiceCount; | ||
| 25 | + | ||
| 26 | + /** | ||
| 27 | + * 今日销售额 | ||
| 28 | + */ | ||
| 29 | + private Double todaySalesAmount; | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * 在线用户数 | ||
| 33 | + */ | ||
| 34 | + private Integer onlineUserCount; | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 系统状态 | ||
| 38 | + */ | ||
| 39 | + private String systemStatus; | ||
| 40 | + | ||
| 41 | + /** | ||
| 42 | + * 系统版本 | ||
| 43 | + */ | ||
| 44 | + private String systemVersion; | ||
| 45 | + | ||
| 46 | + /** | ||
| 47 | + * 今日订单增长率 | ||
| 48 | + */ | ||
| 49 | + private String orderGrowthRate; | ||
| 50 | + | ||
| 51 | + /** | ||
| 52 | + * 今日销售额增长率 | ||
| 53 | + */ | ||
| 54 | + private String salesGrowthRate; | ||
| 55 | +} |
| 1 | +package com.apple.erp.service; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.dto.response.DashboardStatsRes; | ||
| 4 | + | ||
| 5 | +import java.util.List; | ||
| 6 | +import java.util.Map; | ||
| 7 | + | ||
| 8 | +/** | ||
| 9 | + * 首页仪表板服务接口 | ||
| 10 | + */ | ||
| 11 | +public interface DashboardService { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 获取首页统计数据 | ||
| 15 | + * @return 统计数据 | ||
| 16 | + */ | ||
| 17 | + DashboardStatsRes getDashboardStats(); | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * 获取最近活动 | ||
| 21 | + * @return 最近活动列表 | ||
| 22 | + */ | ||
| 23 | + List<Map<String, Object>> getRecentActivities(); | ||
| 24 | +} |
| ... | @@ -67,6 +67,12 @@ public interface DeliveryMainService extends IService<DeliveryMain> { | ... | @@ -67,6 +67,12 @@ public interface DeliveryMainService extends IService<DeliveryMain> { |
| 67 | * @return 是否成功 | 67 | * @return 是否成功 |
| 68 | */ | 68 | */ |
| 69 | boolean updateDeliveryStatus(Long deliveryId, Integer deliveryStatus); | 69 | boolean updateDeliveryStatus(Long deliveryId, Integer deliveryStatus); |
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 获取待出库数量 | ||
| 73 | + * @return 待出库数量 | ||
| 74 | + */ | ||
| 75 | + Integer getPendingDeliveryCount(); | ||
| 70 | } | 76 | } |
| 71 | 77 | ||
| 72 | 78 | ... | ... |
| ... | @@ -67,6 +67,12 @@ public interface InvoiceMainService extends IService<InvoiceMain> { | ... | @@ -67,6 +67,12 @@ public interface InvoiceMainService extends IService<InvoiceMain> { |
| 67 | * @return 是否成功 | 67 | * @return 是否成功 |
| 68 | */ | 68 | */ |
| 69 | boolean updateInvoiceStatus(Long invoiceId, Integer invoiceStatus); | 69 | boolean updateInvoiceStatus(Long invoiceId, Integer invoiceStatus); |
| 70 | + | ||
| 71 | + /** | ||
| 72 | + * 获取待开票数量 | ||
| 73 | + * @return 待开票数量 | ||
| 74 | + */ | ||
| 75 | + Integer getPendingInvoiceCount(); | ||
| 70 | } | 76 | } |
| 71 | 77 | ||
| 72 | 78 | ... | ... |
| ... | @@ -92,5 +92,21 @@ public interface OrderMainService extends IService<OrderMain> { | ... | @@ -92,5 +92,21 @@ public interface OrderMainService extends IService<OrderMain> { |
| 92 | * @return 是否成功 | 92 | * @return 是否成功 |
| 93 | */ | 93 | */ |
| 94 | boolean updateRebateCalcFlag(Long orderId, Integer rebateCalcFlag); | 94 | boolean updateRebateCalcFlag(Long orderId, Integer rebateCalcFlag); |
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * 获取今日订单数量 | ||
| 98 | + * | ||
| 99 | + * @param date 日期 | ||
| 100 | + * @return 订单数量 | ||
| 101 | + */ | ||
| 102 | + Integer getTodayOrderCount(String date); | ||
| 103 | + | ||
| 104 | + /** | ||
| 105 | + * 获取今日销售额 | ||
| 106 | + * | ||
| 107 | + * @param date 日期 | ||
| 108 | + * @return 销售额 | ||
| 109 | + */ | ||
| 110 | + Double getTodaySalesAmount(String date); | ||
| 95 | } | 111 | } |
| 96 | 112 | ... | ... |
| 1 | +package com.apple.erp.service; | ||
| 2 | + | ||
| 3 | +import java.util.Map; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 会话管理服务接口 | ||
| 7 | + * | ||
| 8 | + * @author Apple ERP Team | ||
| 9 | + * @version 1.0.0 | ||
| 10 | + * @since 2024-01-01 | ||
| 11 | + */ | ||
| 12 | +public interface SessionService { | ||
| 13 | + | ||
| 14 | + /** | ||
| 15 | + * 存储用户会话信息 | ||
| 16 | + * @param username 用户名 | ||
| 17 | + * @param sessionData 会话数据 | ||
| 18 | + */ | ||
| 19 | + void storeUserSession(String username, Map<String, Object> sessionData); | ||
| 20 | + | ||
| 21 | + /** | ||
| 22 | + * 获取用户会话信息 | ||
| 23 | + * @param username 用户名 | ||
| 24 | + * @return 会话数据 | ||
| 25 | + */ | ||
| 26 | + Map<String, Object> getUserSession(String username); | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 删除用户会话 | ||
| 30 | + * @param username 用户名 | ||
| 31 | + */ | ||
| 32 | + void removeUserSession(String username); | ||
| 33 | + | ||
| 34 | + /** | ||
| 35 | + * 获取在线用户数 | ||
| 36 | + * @return 在线用户数 | ||
| 37 | + */ | ||
| 38 | + Integer getOnlineUserCount(); | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 清理过期会话 | ||
| 42 | + */ | ||
| 43 | + void cleanupExpiredSessions(); | ||
| 44 | +} |
This diff is collapsed. Click to expand it.
| ... | @@ -227,6 +227,14 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del | ... | @@ -227,6 +227,14 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del |
| 227 | return null; | 227 | return null; |
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | + | ||
| 231 | + @Override | ||
| 232 | + public Integer getPendingDeliveryCount() { | ||
| 233 | + LambdaQueryWrapper<DeliveryMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 234 | + wrapper.eq(DeliveryMain::getDelFlag, "0") | ||
| 235 | + .eq(DeliveryMain::getDeliveryStatus, 0); // 0表示待出库 | ||
| 236 | + return Math.toIntExact(count(wrapper)); | ||
| 237 | + } | ||
| 230 | } | 238 | } |
| 231 | 239 | ||
| 232 | 240 | ... | ... |
| ... | @@ -229,4 +229,12 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -229,4 +229,12 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 229 | } | 229 | } |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | + @Override | ||
| 233 | + public Integer getPendingInvoiceCount() { | ||
| 234 | + LambdaQueryWrapper<InvoiceMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 235 | + wrapper.eq(InvoiceMain::getDelFlag, "0") | ||
| 236 | + .eq(InvoiceMain::getInvoiceStatus, 0); // 0表示待开票 | ||
| 237 | + return Math.toIntExact(count(wrapper)); | ||
| 238 | + } | ||
| 239 | + | ||
| 232 | } | 240 | } | ... | ... |
| ... | @@ -288,5 +288,39 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain | ... | @@ -288,5 +288,39 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain |
| 288 | order.setUpdateTime(LocalDateTime.now()); | 288 | order.setUpdateTime(LocalDateTime.now()); |
| 289 | return orderMainMapper.updateById(order) > 0; | 289 | return orderMainMapper.updateById(order) > 0; |
| 290 | } | 290 | } |
| 291 | + | ||
| 292 | + @Override | ||
| 293 | + public Integer getTodayOrderCount(String date) { | ||
| 294 | + try { | ||
| 295 | + LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 296 | + wrapper.eq(OrderMain::getDelFlag, "0") | ||
| 297 | + .like(OrderMain::getCreateTime, date); | ||
| 298 | + long count = count(wrapper); | ||
| 299 | + System.out.println("今日订单数量查询结果: " + count + ", 日期: " + date); | ||
| 300 | + return Math.toIntExact(count); | ||
| 301 | + } catch (Exception e) { | ||
| 302 | + System.err.println("查询今日订单数量失败: " + e.getMessage()); | ||
| 303 | + return 0; | ||
| 304 | + } | ||
| 305 | + } | ||
| 306 | + | ||
| 307 | + @Override | ||
| 308 | + public Double getTodaySalesAmount(String date) { | ||
| 309 | + try { | ||
| 310 | + LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 311 | + wrapper.eq(OrderMain::getDelFlag, "0") | ||
| 312 | + .like(OrderMain::getCreateTime, date); | ||
| 313 | + | ||
| 314 | + List<OrderMain> orders = list(wrapper); | ||
| 315 | + double totalAmount = orders.stream() | ||
| 316 | + .mapToDouble(order -> order.getTotalAmount() != null ? order.getTotalAmount().doubleValue() : 0.0) | ||
| 317 | + .sum(); | ||
| 318 | + System.out.println("今日销售额查询结果: " + totalAmount + ", 日期: " + date); | ||
| 319 | + return totalAmount; | ||
| 320 | + } catch (Exception e) { | ||
| 321 | + System.err.println("查询今日销售额失败: " + e.getMessage()); | ||
| 322 | + return 0.0; | ||
| 323 | + } | ||
| 324 | + } | ||
| 291 | } | 325 | } |
| 292 | 326 | ... | ... |
| 1 | +package com.apple.erp.service.impl; | ||
| 2 | + | ||
| 3 | +import com.apple.erp.service.SessionService; | ||
| 4 | +import lombok.extern.slf4j.Slf4j; | ||
| 5 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 6 | +import org.springframework.data.redis.core.RedisTemplate; | ||
| 7 | +import org.springframework.scheduling.annotation.Scheduled; | ||
| 8 | +import org.springframework.stereotype.Service; | ||
| 9 | + | ||
| 10 | +import java.util.HashMap; | ||
| 11 | +import java.util.Map; | ||
| 12 | +import java.util.Set; | ||
| 13 | + | ||
| 14 | +/** | ||
| 15 | + * 会话管理服务实现 | ||
| 16 | + * | ||
| 17 | + * @author Apple ERP Team | ||
| 18 | + * @version 1.0.0 | ||
| 19 | + * @since 2024-01-01 | ||
| 20 | + */ | ||
| 21 | +@Slf4j | ||
| 22 | +@Service | ||
| 23 | +public class SessionServiceImpl implements SessionService { | ||
| 24 | + | ||
| 25 | + private static final String SESSION_KEY_PREFIX = "user:session:"; | ||
| 26 | + private static final long SESSION_TIMEOUT = 1800; // 30分钟 | ||
| 27 | + | ||
| 28 | + @Autowired | ||
| 29 | + private RedisTemplate<String, Object> redisTemplate; | ||
| 30 | + | ||
| 31 | + @Override | ||
| 32 | + public void storeUserSession(String username, Map<String, Object> sessionData) { | ||
| 33 | + try { | ||
| 34 | + String sessionKey = SESSION_KEY_PREFIX + username; | ||
| 35 | + redisTemplate.opsForValue().set(sessionKey, sessionData, SESSION_TIMEOUT); | ||
| 36 | + log.debug("用户会话已存储: {}", username); | ||
| 37 | + } catch (Exception e) { | ||
| 38 | + log.error("存储用户会话失败: {}", username, e); | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @Override | ||
| 43 | + public Map<String, Object> getUserSession(String username) { | ||
| 44 | + try { | ||
| 45 | + String sessionKey = SESSION_KEY_PREFIX + username; | ||
| 46 | + Object sessionData = redisTemplate.opsForValue().get(sessionKey); | ||
| 47 | + if (sessionData instanceof Map) { | ||
| 48 | + return (Map<String, Object>) sessionData; | ||
| 49 | + } | ||
| 50 | + } catch (Exception e) { | ||
| 51 | + log.error("获取用户会话失败: {}", username, e); | ||
| 52 | + } | ||
| 53 | + return new HashMap<>(); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + @Override | ||
| 57 | + public void removeUserSession(String username) { | ||
| 58 | + try { | ||
| 59 | + String sessionKey = SESSION_KEY_PREFIX + username; | ||
| 60 | + redisTemplate.delete(sessionKey); | ||
| 61 | + log.debug("用户会话已删除: {}", username); | ||
| 62 | + } catch (Exception e) { | ||
| 63 | + log.error("删除用户会话失败: {}", username, e); | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + @Override | ||
| 68 | + public Integer getOnlineUserCount() { | ||
| 69 | + try { | ||
| 70 | + String pattern = SESSION_KEY_PREFIX + "*"; | ||
| 71 | + Set<String> sessionKeys = redisTemplate.keys(pattern); | ||
| 72 | + | ||
| 73 | + if (sessionKeys != null) { | ||
| 74 | + int onlineCount = sessionKeys.size(); | ||
| 75 | + log.debug("当前在线用户数: {}", onlineCount); | ||
| 76 | + return onlineCount; | ||
| 77 | + } else { | ||
| 78 | + log.warn("Redis中未找到用户会话数据"); | ||
| 79 | + return 0; | ||
| 80 | + } | ||
| 81 | + } catch (Exception e) { | ||
| 82 | + log.error("获取在线用户数失败", e); | ||
| 83 | + return 0; | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + @Override | ||
| 88 | + @Scheduled(fixedRate = 300000) // 每5分钟执行一次 | ||
| 89 | + public void cleanupExpiredSessions() { | ||
| 90 | + try { | ||
| 91 | + String pattern = SESSION_KEY_PREFIX + "*"; | ||
| 92 | + Set<String> sessionKeys = redisTemplate.keys(pattern); | ||
| 93 | + | ||
| 94 | + if (sessionKeys != null) { | ||
| 95 | + int cleanedCount = 0; | ||
| 96 | + for (String sessionKey : sessionKeys) { | ||
| 97 | + // Redis会自动清理过期的key,这里可以添加额外的清理逻辑 | ||
| 98 | + // 比如检查会话的最后活动时间等 | ||
| 99 | + cleanedCount++; | ||
| 100 | + } | ||
| 101 | + log.debug("会话清理完成,检查了 {} 个会话", cleanedCount); | ||
| 102 | + } | ||
| 103 | + } catch (Exception e) { | ||
| 104 | + log.error("清理过期会话失败", e); | ||
| 105 | + } | ||
| 106 | + } | ||
| 107 | +} |
| ... | @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; | ... | @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; |
| 11 | 11 | ||
| 12 | import java.util.ArrayList; | 12 | import java.util.ArrayList; |
| 13 | import java.util.List; | 13 | import java.util.List; |
| 14 | -import java.util.stream.Collectors; | ||
| 15 | 14 | ||
| 16 | /** | 15 | /** |
| 17 | * 系统菜单Service实现类 | 16 | * 系统菜单Service实现类 |
| ... | @@ -77,7 +76,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl | ... | @@ -77,7 +76,7 @@ public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> impl |
| 77 | wrapper.eq(SysMenu::getDelFlag, "0"); | 76 | wrapper.eq(SysMenu::getDelFlag, "0"); |
| 78 | 77 | ||
| 79 | // 排序:按父菜单ID和排序号升序 | 78 | // 排序:按父菜单ID和排序号升序 |
| 80 | - wrapper.orderByAsc(SysMenu::getParentId, SysMenu::getSort); | 79 | + wrapper.orderByAsc(SysMenu::getParentId).orderByAsc(SysMenu::getSort); |
| 81 | 80 | ||
| 82 | return wrapper; | 81 | return wrapper; |
| 83 | } | 82 | } | ... | ... |
| ... | @@ -198,33 +198,6 @@ public class DictValueConverter { | ... | @@ -198,33 +198,6 @@ public class DictValueConverter { |
| 198 | } | 198 | } |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | - /** | ||
| 202 | - * 加载指定字典类型到Redis | ||
| 203 | - */ | ||
| 204 | - private static void loadDictToRedis(String dictType) { | ||
| 205 | - if (staticDictItemService == null) { | ||
| 206 | - return; | ||
| 207 | - } | ||
| 208 | - | ||
| 209 | - try { | ||
| 210 | - // 根据字典类型获取字典项 | ||
| 211 | - List<SysDictItem> dictItems = staticDictItemService.getDictItemsByType(dictType); | ||
| 212 | - | ||
| 213 | - Map<String, String> mapping = new HashMap<>(); | ||
| 214 | - for (SysDictItem item : dictItems) { | ||
| 215 | - if (item.getDelFlag() == null || "0".equals(item.getDelFlag())) { | ||
| 216 | - mapping.put(item.getDictValue(), item.getDictLabel()); | ||
| 217 | - } | ||
| 218 | - } | ||
| 219 | - | ||
| 220 | - // 存储到Redis | ||
| 221 | - String cacheKey = DICT_CACHE_PREFIX + dictType; | ||
| 222 | - staticRedisTemplate.opsForValue().set(cacheKey, mapping, CACHE_EXPIRE_HOURS, TimeUnit.HOURS); | ||
| 223 | - | ||
| 224 | - } catch (Exception e) { | ||
| 225 | - System.err.println("加载字典到Redis失败: " + e.getMessage()); | ||
| 226 | - } | ||
| 227 | - } | ||
| 228 | 201 | ||
| 229 | /** | 202 | /** |
| 230 | * 根据字典类型ID获取字典类型编码 | 203 | * 根据字典类型ID获取字典类型编码 | ... | ... |
frontend/src/api/dashboard.ts
0 → 100644
| 1 | +import { request } from '@/utils/request' | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 首页统计数据响应接口 | ||
| 5 | + */ | ||
| 6 | +export interface DashboardStats { | ||
| 7 | + todayOrderCount: number | ||
| 8 | + pendingDeliveryCount: number | ||
| 9 | + pendingInvoiceCount: number | ||
| 10 | + todaySalesAmount: number | ||
| 11 | + onlineUserCount: number | ||
| 12 | + systemStatus: string | ||
| 13 | + systemVersion: string | ||
| 14 | + orderGrowthRate: string | ||
| 15 | + salesGrowthRate: string | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | +export interface RecentActivity { | ||
| 19 | + id: number | ||
| 20 | + type: string | ||
| 21 | + title: string | ||
| 22 | + time: string | ||
| 23 | +} | ||
| 24 | + | ||
| 25 | +/** | ||
| 26 | + * 首页API | ||
| 27 | + */ | ||
| 28 | +export const dashboardApi = { | ||
| 29 | + /** | ||
| 30 | + * 获取首页统计数据 | ||
| 31 | + */ | ||
| 32 | + getDashboardStats: (): Promise<DashboardStats> => { | ||
| 33 | + return request.get('/api/dashboard/stats') | ||
| 34 | + }, | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 获取最近活动 | ||
| 38 | + */ | ||
| 39 | + getRecentActivities: (): Promise<RecentActivity[]> => { | ||
| 40 | + return request.get('/api/dashboard/activities') | ||
| 41 | + }, | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 获取测试数据 | ||
| 45 | + */ | ||
| 46 | + getTestStats: (): Promise<DashboardStats> => { | ||
| 47 | + return request.get('/api/dashboard/test') | ||
| 48 | + } | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +export default dashboardApi |
| ... | @@ -32,6 +32,8 @@ export interface RebateSearchParams { | ... | @@ -32,6 +32,8 @@ export interface RebateSearchParams { |
| 32 | productCode?: string | 32 | productCode?: string |
| 33 | operateType?: number | 33 | operateType?: number |
| 34 | calcFlag?: number | 34 | calcFlag?: number |
| 35 | + auditStatus?: number | ||
| 36 | + dataSource?: string | ||
| 35 | rebateStartDate?: string | 37 | rebateStartDate?: string |
| 36 | rebateEndDate?: string | 38 | rebateEndDate?: string |
| 37 | } | 39 | } | ... | ... |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment