Merge branch 'master' of http://gitlab.erry.com/zhouhui.jiang/test_cursor
Showing
30 changed files
with
742 additions
and
38 deletions
This diff is collapsed. Click to expand it.
| 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 | * 认证控制器 |
| ... | @@ -52,6 +55,9 @@ public class AuthController { | ... | @@ -52,6 +55,9 @@ public class AuthController { |
| 52 | @Autowired | 55 | @Autowired |
| 53 | private SysLogService sysLogService; | 56 | private SysLogService sysLogService; |
| 54 | 57 | ||
| 58 | + @Autowired | ||
| 59 | + private SessionService sessionService; | ||
| 60 | + | ||
| 55 | /** | 61 | /** |
| 56 | * 用户登录 | 62 | * 用户登录 |
| 57 | */ | 63 | */ |
| ... | @@ -96,6 +102,21 @@ public class AuthController { | ... | @@ -96,6 +102,21 @@ public class AuthController { |
| 96 | String token = jwtUtils.generateToken(username); | 102 | String token = jwtUtils.generateToken(username); |
| 97 | String refreshToken = jwtUtils.generateRefreshToken(username); | 103 | String refreshToken = jwtUtils.generateRefreshToken(username); |
| 98 | 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 | + } | ||
| 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); |
| 101 | return ResponseEntity.ok(response); | 122 | return ResponseEntity.ok(response); |
| ... | @@ -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 | +} |
| ... | @@ -6,12 +6,14 @@ import com.apple.erp.dto.ExceptionWorkorderRes; | ... | @@ -6,12 +6,14 @@ import com.apple.erp.dto.ExceptionWorkorderRes; |
| 6 | import com.apple.erp.dto.ExceptionWorkorderStatusUpdateReq; | 6 | import com.apple.erp.dto.ExceptionWorkorderStatusUpdateReq; |
| 7 | import com.apple.erp.dto.ExceptionWorkorderUpdateReq; | 7 | import com.apple.erp.dto.ExceptionWorkorderUpdateReq; |
| 8 | import com.apple.erp.service.ExceptionWorkorderService; | 8 | import com.apple.erp.service.ExceptionWorkorderService; |
| 9 | +import com.apple.erp.service.ExcelExportService; | ||
| 9 | import com.apple.erp.dto.response.ApiRes; | 10 | import com.apple.erp.dto.response.ApiRes; |
| 10 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | 11 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| 11 | import io.swagger.v3.oas.annotations.Operation; | 12 | import io.swagger.v3.oas.annotations.Operation; |
| 12 | import io.swagger.v3.oas.annotations.Parameter; | 13 | import io.swagger.v3.oas.annotations.Parameter; |
| 13 | import io.swagger.v3.oas.annotations.tags.Tag; | 14 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 14 | import org.springframework.beans.factory.annotation.Autowired; | 15 | import org.springframework.beans.factory.annotation.Autowired; |
| 16 | +import org.springframework.http.ResponseEntity; | ||
| 15 | import org.springframework.security.access.prepost.PreAuthorize; | 17 | import org.springframework.security.access.prepost.PreAuthorize; |
| 16 | import org.springframework.validation.annotation.Validated; | 18 | import org.springframework.validation.annotation.Validated; |
| 17 | import org.springframework.web.bind.annotation.*; | 19 | import org.springframework.web.bind.annotation.*; |
| ... | @@ -34,6 +36,9 @@ public class ExceptionWorkorderController { | ... | @@ -34,6 +36,9 @@ public class ExceptionWorkorderController { |
| 34 | @Autowired | 36 | @Autowired |
| 35 | private ExceptionWorkorderService exceptionWorkorderService; | 37 | private ExceptionWorkorderService exceptionWorkorderService; |
| 36 | 38 | ||
| 39 | + @Autowired | ||
| 40 | + private ExcelExportService excelExportService; | ||
| 41 | + | ||
| 37 | @Operation(summary = "分页查询异常工单列表", description = "根据条件分页查询异常工单列表") | 42 | @Operation(summary = "分页查询异常工单列表", description = "根据条件分页查询异常工单列表") |
| 38 | @GetMapping("/list") | 43 | @GetMapping("/list") |
| 39 | @PreAuthorize("hasAuthority('exception:workorder:list')") | 44 | @PreAuthorize("hasAuthority('exception:workorder:list')") |
| ... | @@ -168,4 +173,22 @@ public class ExceptionWorkorderController { | ... | @@ -168,4 +173,22 @@ public class ExceptionWorkorderController { |
| 168 | List<ExceptionWorkorderRes> stats = exceptionWorkorderService.getExceptionWorkorderStats(); | 173 | List<ExceptionWorkorderRes> stats = exceptionWorkorderService.getExceptionWorkorderStats(); |
| 169 | return ApiRes.success(stats); | 174 | return ApiRes.success(stats); |
| 170 | } | 175 | } |
| 176 | + | ||
| 177 | + @Operation(summary = "导出异常工单数据", description = "根据查询条件导出异常工单数据到Excel") | ||
| 178 | + @PostMapping("/export") | ||
| 179 | + @PreAuthorize("hasAuthority('exception:workorder:export')") | ||
| 180 | + public ResponseEntity<byte[]> exportExceptionWorkorders(@RequestBody(required = false) ExceptionWorkorderQueryReq queryReq) { | ||
| 181 | + try { | ||
| 182 | + // 如果请求体为空,创建默认查询条件 | ||
| 183 | + if (queryReq == null) { | ||
| 184 | + queryReq = new ExceptionWorkorderQueryReq(); | ||
| 185 | + } | ||
| 186 | + // 获取异常工单数据 | ||
| 187 | + List<ExceptionWorkorderRes> workorders = exceptionWorkorderService.getExceptionWorkorderListForExport(queryReq); | ||
| 188 | + // 导出Excel | ||
| 189 | + return excelExportService.exportExceptionWorkorders(workorders); | ||
| 190 | + } catch (Exception e) { | ||
| 191 | + throw new RuntimeException("导出异常工单数据失败: " + e.getMessage()); | ||
| 192 | + } | ||
| 193 | + } | ||
| 171 | } | 194 | } | ... | ... |
| 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 | +} |
| ... | @@ -54,4 +54,12 @@ public interface ExceptionWorkorderMapper extends BaseMapper<ExceptionWorkorder> | ... | @@ -54,4 +54,12 @@ public interface ExceptionWorkorderMapper extends BaseMapper<ExceptionWorkorder> |
| 54 | int batchUpdateWorkorderStatus(@Param("workorderIds") List<Long> workorderIds, | 54 | int batchUpdateWorkorderStatus(@Param("workorderIds") List<Long> workorderIds, |
| 55 | @Param("workorderStatus") Integer workorderStatus, | 55 | @Param("workorderStatus") Integer workorderStatus, |
| 56 | @Param("handlerUser") String handlerUser); | 56 | @Param("handlerUser") String handlerUser); |
| 57 | + | ||
| 58 | + /** | ||
| 59 | + * 获取异常工单列表用于导出 | ||
| 60 | + * | ||
| 61 | + * @param queryReq 查询条件 | ||
| 62 | + * @return 异常工单列表(不分页) | ||
| 63 | + */ | ||
| 64 | + List<ExceptionWorkorderRes> selectExceptionWorkorderListForExport(@Param("query") ExceptionWorkorderQueryReq queryReq); | ||
| 57 | } | 65 | } | ... | ... |
| 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,20 @@ public interface DeliveryMainService extends IService<DeliveryMain> { | ... | @@ -67,6 +67,20 @@ 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(); | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 获取最近的出库记录 | ||
| 79 | + * | ||
| 80 | + * @param limit 限制数量 | ||
| 81 | + * @return 最近出库列表 | ||
| 82 | + */ | ||
| 83 | + List<DeliveryRes> getRecentDeliveries(Integer limit); | ||
| 70 | } | 84 | } |
| 71 | 85 | ||
| 72 | 86 | ... | ... |
| ... | @@ -91,4 +91,12 @@ public interface ExceptionWorkorderService extends IService<ExceptionWorkorder> | ... | @@ -91,4 +91,12 @@ public interface ExceptionWorkorderService extends IService<ExceptionWorkorder> |
| 91 | * @return 统计信息 | 91 | * @return 统计信息 |
| 92 | */ | 92 | */ |
| 93 | List<ExceptionWorkorderRes> getExceptionWorkorderStats(); | 93 | List<ExceptionWorkorderRes> getExceptionWorkorderStats(); |
| 94 | + | ||
| 95 | + /** | ||
| 96 | + * 获取异常工单列表用于导出 | ||
| 97 | + * | ||
| 98 | + * @param queryReq 查询条件 | ||
| 99 | + * @return 异常工单列表(不分页) | ||
| 100 | + */ | ||
| 101 | + List<ExceptionWorkorderRes> getExceptionWorkorderListForExport(ExceptionWorkorderQueryReq queryReq); | ||
| 94 | } | 102 | } | ... | ... |
| ... | @@ -67,6 +67,20 @@ public interface InvoiceMainService extends IService<InvoiceMain> { | ... | @@ -67,6 +67,20 @@ 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(); | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * 获取最近的发票记录 | ||
| 79 | + * | ||
| 80 | + * @param limit 限制数量 | ||
| 81 | + * @return 最近发票列表 | ||
| 82 | + */ | ||
| 83 | + List<InvoiceRes> getRecentInvoices(Integer limit); | ||
| 70 | } | 84 | } |
| 71 | 85 | ||
| 72 | 86 | ... | ... |
| ... | @@ -92,5 +92,29 @@ public interface OrderMainService extends IService<OrderMain> { | ... | @@ -92,5 +92,29 @@ 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); | ||
| 111 | + | ||
| 112 | + /** | ||
| 113 | + * 获取最近的订单记录 | ||
| 114 | + * | ||
| 115 | + * @param limit 限制数量 | ||
| 116 | + * @return 最近订单列表 | ||
| 117 | + */ | ||
| 118 | + List<OrderRes> getRecentOrders(Integer limit); | ||
| 95 | } | 119 | } |
| 96 | 120 | ... | ... |
| ... | @@ -139,4 +139,12 @@ public interface RebateService extends IService<Rebate> { | ... | @@ -139,4 +139,12 @@ public interface RebateService extends IService<Rebate> { |
| 139 | * @return 趋势统计数据 | 139 | * @return 趋势统计数据 |
| 140 | */ | 140 | */ |
| 141 | List<Map<String, Object>> getRebateTrendStats(String startDate, String endDate); | 141 | List<Map<String, Object>> getRebateTrendStats(String startDate, String endDate); |
| 142 | + | ||
| 143 | + /** | ||
| 144 | + * 获取最近的返利记录 | ||
| 145 | + * | ||
| 146 | + * @param limit 限制数量 | ||
| 147 | + * @return 最近返利列表 | ||
| 148 | + */ | ||
| 149 | + List<RebateRes> getRecentRebates(Integer limit); | ||
| 142 | } | 150 | } | ... | ... |
| 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.
| ... | @@ -22,6 +22,7 @@ import org.springframework.util.StringUtils; | ... | @@ -22,6 +22,7 @@ import org.springframework.util.StringUtils; |
| 22 | 22 | ||
| 23 | import java.time.LocalDateTime; | 23 | import java.time.LocalDateTime; |
| 24 | import java.time.format.DateTimeFormatter; | 24 | import java.time.format.DateTimeFormatter; |
| 25 | +import java.util.ArrayList; | ||
| 25 | import java.util.List; | 26 | import java.util.List; |
| 26 | import java.util.stream.Collectors; | 27 | import java.util.stream.Collectors; |
| 27 | 28 | ||
| ... | @@ -254,6 +255,34 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del | ... | @@ -254,6 +255,34 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del |
| 254 | return null; | 255 | return null; |
| 255 | } | 256 | } |
| 256 | } | 257 | } |
| 258 | + | ||
| 259 | + @Override | ||
| 260 | + public Integer getPendingDeliveryCount() { | ||
| 261 | + LambdaQueryWrapper<DeliveryMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 262 | + wrapper.eq(DeliveryMain::getDelFlag, "0") | ||
| 263 | + .eq(DeliveryMain::getDeliveryStatus, 0); // 0表示待出库 | ||
| 264 | + return Math.toIntExact(count(wrapper)); | ||
| 265 | + } | ||
| 266 | + | ||
| 267 | + @Override | ||
| 268 | + public List<DeliveryRes> getRecentDeliveries(Integer limit) { | ||
| 269 | + try { | ||
| 270 | + LambdaQueryWrapper<DeliveryMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 271 | + wrapper.eq(DeliveryMain::getDelFlag, "0") | ||
| 272 | + .orderByDesc(DeliveryMain::getCreateTime) | ||
| 273 | + .last("LIMIT " + (limit != null ? limit : 5)); | ||
| 274 | + | ||
| 275 | + List<DeliveryMain> deliveries = list(wrapper); | ||
| 276 | + return deliveries.stream().map(delivery -> { | ||
| 277 | + DeliveryRes deliveryRes = new DeliveryRes(); | ||
| 278 | + BeanUtils.copyProperties(delivery, deliveryRes); | ||
| 279 | + return deliveryRes; | ||
| 280 | + }).collect(Collectors.toList()); | ||
| 281 | + } catch (Exception e) { | ||
| 282 | + log.error("获取最近出库记录失败", e); | ||
| 283 | + return new ArrayList<>(); | ||
| 284 | + } | ||
| 285 | + } | ||
| 257 | } | 286 | } |
| 258 | 287 | ||
| 259 | 288 | ... | ... |
| ... | @@ -18,11 +18,9 @@ import org.springframework.beans.BeanUtils; | ... | @@ -18,11 +18,9 @@ import org.springframework.beans.BeanUtils; |
| 18 | import org.springframework.beans.factory.annotation.Autowired; | 18 | import org.springframework.beans.factory.annotation.Autowired; |
| 19 | import org.springframework.stereotype.Service; | 19 | import org.springframework.stereotype.Service; |
| 20 | import org.springframework.transaction.annotation.Transactional; | 20 | import org.springframework.transaction.annotation.Transactional; |
| 21 | -import org.springframework.util.StringUtils; | ||
| 22 | 21 | ||
| 23 | import java.time.LocalDateTime; | 22 | import java.time.LocalDateTime; |
| 24 | import java.util.List; | 23 | import java.util.List; |
| 25 | -import java.util.stream.Collectors; | ||
| 26 | 24 | ||
| 27 | /** | 25 | /** |
| 28 | * 异常工单Service实现类 | 26 | * 异常工单Service实现类 |
| ... | @@ -200,4 +198,10 @@ public class ExceptionWorkorderServiceImpl extends ServiceImpl<ExceptionWorkorde | ... | @@ -200,4 +198,10 @@ public class ExceptionWorkorderServiceImpl extends ServiceImpl<ExceptionWorkorde |
| 200 | public List<ExceptionWorkorderRes> getExceptionWorkorderStats() { | 198 | public List<ExceptionWorkorderRes> getExceptionWorkorderStats() { |
| 201 | return exceptionWorkorderMapper.selectExceptionWorkorderStats(); | 199 | return exceptionWorkorderMapper.selectExceptionWorkorderStats(); |
| 202 | } | 200 | } |
| 201 | + | ||
| 202 | + @Override | ||
| 203 | + public List<ExceptionWorkorderRes> getExceptionWorkorderListForExport(ExceptionWorkorderQueryReq queryReq) { | ||
| 204 | + // 不分页查询所有数据用于导出 | ||
| 205 | + return exceptionWorkorderMapper.selectExceptionWorkorderListForExport(queryReq); | ||
| 206 | + } | ||
| 203 | } | 207 | } | ... | ... |
| ... | @@ -21,6 +21,7 @@ import org.springframework.util.StringUtils; | ... | @@ -21,6 +21,7 @@ import org.springframework.util.StringUtils; |
| 21 | import java.time.LocalDate; | 21 | import java.time.LocalDate; |
| 22 | import java.time.LocalDateTime; | 22 | import java.time.LocalDateTime; |
| 23 | import java.time.format.DateTimeFormatter; | 23 | import java.time.format.DateTimeFormatter; |
| 24 | +import java.util.ArrayList; | ||
| 24 | import java.util.List; | 25 | import java.util.List; |
| 25 | import java.util.stream.Collectors; | 26 | import java.util.stream.Collectors; |
| 26 | 27 | ||
| ... | @@ -229,4 +230,31 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -229,4 +230,31 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 229 | } | 230 | } |
| 230 | } | 231 | } |
| 231 | 232 | ||
| 233 | + @Override | ||
| 234 | + public Integer getPendingInvoiceCount() { | ||
| 235 | + LambdaQueryWrapper<InvoiceMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 236 | + wrapper.eq(InvoiceMain::getDelFlag, "0") | ||
| 237 | + .eq(InvoiceMain::getInvoiceStatus, 0); // 0表示待开票 | ||
| 238 | + return Math.toIntExact(count(wrapper)); | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + @Override | ||
| 242 | + public List<InvoiceRes> getRecentInvoices(Integer limit) { | ||
| 243 | + try { | ||
| 244 | + LambdaQueryWrapper<InvoiceMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 245 | + wrapper.eq(InvoiceMain::getDelFlag, "0") | ||
| 246 | + .orderByDesc(InvoiceMain::getCreateTime) | ||
| 247 | + .last("LIMIT " + (limit != null ? limit : 5)); | ||
| 248 | + | ||
| 249 | + List<InvoiceMain> invoices = list(wrapper); | ||
| 250 | + return invoices.stream().map(invoice -> { | ||
| 251 | + InvoiceRes invoiceRes = new InvoiceRes(); | ||
| 252 | + BeanUtils.copyProperties(invoice, invoiceRes); | ||
| 253 | + return invoiceRes; | ||
| 254 | + }).collect(Collectors.toList()); | ||
| 255 | + } catch (Exception e) { | ||
| 256 | + log.error("获取最近发票记录失败", e); | ||
| 257 | + return new ArrayList<>(); | ||
| 258 | + } | ||
| 259 | + } | ||
| 232 | } | 260 | } | ... | ... |
| ... | @@ -16,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional; | ... | @@ -16,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional; |
| 16 | import org.springframework.util.StringUtils; | 16 | import org.springframework.util.StringUtils; |
| 17 | 17 | ||
| 18 | import java.time.LocalDateTime; | 18 | import java.time.LocalDateTime; |
| 19 | +import java.util.ArrayList; | ||
| 19 | import java.util.List; | 20 | import java.util.List; |
| 20 | import java.util.stream.Collectors; | 21 | import java.util.stream.Collectors; |
| 21 | 22 | ||
| ... | @@ -288,5 +289,59 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain | ... | @@ -288,5 +289,59 @@ public class OrderMainServiceImpl extends ServiceImpl<OrderMainMapper, OrderMain |
| 288 | order.setUpdateTime(LocalDateTime.now()); | 289 | order.setUpdateTime(LocalDateTime.now()); |
| 289 | return orderMainMapper.updateById(order) > 0; | 290 | return orderMainMapper.updateById(order) > 0; |
| 290 | } | 291 | } |
| 292 | + | ||
| 293 | + @Override | ||
| 294 | + public Integer getTodayOrderCount(String date) { | ||
| 295 | + try { | ||
| 296 | + LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 297 | + wrapper.eq(OrderMain::getDelFlag, "0") | ||
| 298 | + .like(OrderMain::getCreateTime, date); | ||
| 299 | + long count = count(wrapper); | ||
| 300 | + System.out.println("今日订单数量查询结果: " + count + ", 日期: " + date); | ||
| 301 | + return Math.toIntExact(count); | ||
| 302 | + } catch (Exception e) { | ||
| 303 | + System.err.println("查询今日订单数量失败: " + e.getMessage()); | ||
| 304 | + return 0; | ||
| 305 | + } | ||
| 306 | + } | ||
| 307 | + | ||
| 308 | + @Override | ||
| 309 | + public Double getTodaySalesAmount(String date) { | ||
| 310 | + try { | ||
| 311 | + LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 312 | + wrapper.eq(OrderMain::getDelFlag, "0") | ||
| 313 | + .like(OrderMain::getCreateTime, date); | ||
| 314 | + | ||
| 315 | + List<OrderMain> orders = list(wrapper); | ||
| 316 | + double totalAmount = orders.stream() | ||
| 317 | + .mapToDouble(order -> order.getTotalAmount() != null ? order.getTotalAmount().doubleValue() : 0.0) | ||
| 318 | + .sum(); | ||
| 319 | + System.out.println("今日销售额查询结果: " + totalAmount + ", 日期: " + date); | ||
| 320 | + return totalAmount; | ||
| 321 | + } catch (Exception e) { | ||
| 322 | + System.err.println("查询今日销售额失败: " + e.getMessage()); | ||
| 323 | + return 0.0; | ||
| 324 | + } | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + @Override | ||
| 328 | + public List<OrderRes> getRecentOrders(Integer limit) { | ||
| 329 | + try { | ||
| 330 | + LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>(); | ||
| 331 | + wrapper.eq(OrderMain::getDelFlag, "0") | ||
| 332 | + .orderByDesc(OrderMain::getCreateTime) | ||
| 333 | + .last("LIMIT " + (limit != null ? limit : 5)); | ||
| 334 | + | ||
| 335 | + List<OrderMain> orders = list(wrapper); | ||
| 336 | + return orders.stream().map(order -> { | ||
| 337 | + OrderRes orderRes = new OrderRes(); | ||
| 338 | + BeanUtils.copyProperties(order, orderRes); | ||
| 339 | + return orderRes; | ||
| 340 | + }).collect(Collectors.toList()); | ||
| 341 | + } catch (Exception e) { | ||
| 342 | + log.error("获取最近订单失败", e); | ||
| 343 | + return new ArrayList<>(); | ||
| 344 | + } | ||
| 345 | + } | ||
| 291 | } | 346 | } |
| 292 | 347 | ... | ... |
| ... | @@ -275,4 +275,24 @@ public class RebateServiceImpl extends ServiceImpl<RebateMapper, Rebate> impleme | ... | @@ -275,4 +275,24 @@ public class RebateServiceImpl extends ServiceImpl<RebateMapper, Rebate> impleme |
| 275 | log.info("获取返利趋势统计数据,开始日期:{},结束日期:{}", startDate, endDate); | 275 | log.info("获取返利趋势统计数据,开始日期:{},结束日期:{}", startDate, endDate); |
| 276 | return rebateMapper.getRebateTrendStats(startDate, endDate); | 276 | return rebateMapper.getRebateTrendStats(startDate, endDate); |
| 277 | } | 277 | } |
| 278 | + | ||
| 279 | + @Override | ||
| 280 | + public List<RebateRes> getRecentRebates(Integer limit) { | ||
| 281 | + try { | ||
| 282 | + LambdaQueryWrapper<Rebate> wrapper = new LambdaQueryWrapper<>(); | ||
| 283 | + wrapper.eq(Rebate::getDelFlag, "0") | ||
| 284 | + .orderByDesc(Rebate::getCreateTime) | ||
| 285 | + .last("LIMIT " + (limit != null ? limit : 5)); | ||
| 286 | + | ||
| 287 | + List<Rebate> rebates = list(wrapper); | ||
| 288 | + return rebates.stream().map(rebate -> { | ||
| 289 | + RebateRes rebateRes = new RebateRes(); | ||
| 290 | + BeanUtils.copyProperties(rebate, rebateRes); | ||
| 291 | + return rebateRes; | ||
| 292 | + }).collect(Collectors.toList()); | ||
| 293 | + } catch (Exception e) { | ||
| 294 | + log.error("获取最近返利记录失败", e); | ||
| 295 | + return new ArrayList<>(); | ||
| 296 | + } | ||
| 297 | + } | ||
| 278 | } | 298 | } | ... | ... |
| 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获取字典类型编码 | ... | ... |
| ... | @@ -150,4 +150,76 @@ | ... | @@ -150,4 +150,76 @@ |
| 150 | AND del_flag = '0' | 150 | AND del_flag = '0' |
| 151 | </update> | 151 | </update> |
| 152 | 152 | ||
| 153 | + <!-- 获取异常工单列表用于导出 --> | ||
| 154 | + <select id="selectExceptionWorkorderListForExport" resultType="com.apple.erp.dto.ExceptionWorkorderRes"> | ||
| 155 | + SELECT | ||
| 156 | + ew.workorder_id, | ||
| 157 | + ew.workorder_no, | ||
| 158 | + ew.order_no, | ||
| 159 | + ew.dealer_code, | ||
| 160 | + ew.dealer_name, | ||
| 161 | + ew.exception_type, | ||
| 162 | + CASE ew.exception_type | ||
| 163 | + WHEN 1 THEN '逻辑验证异常' | ||
| 164 | + WHEN 2 THEN '源头验证异常' | ||
| 165 | + WHEN 3 THEN '交叉验证异常' | ||
| 166 | + ELSE '未知类型' | ||
| 167 | + END AS exception_type_name, | ||
| 168 | + ew.severity_level, | ||
| 169 | + CASE ew.severity_level | ||
| 170 | + WHEN 1 THEN '高' | ||
| 171 | + WHEN 2 THEN '中' | ||
| 172 | + WHEN 3 THEN '低' | ||
| 173 | + ELSE '未知' | ||
| 174 | + END AS severity_level_name, | ||
| 175 | + ew.workorder_status, | ||
| 176 | + CASE ew.workorder_status | ||
| 177 | + WHEN 1 THEN '待处理' | ||
| 178 | + WHEN 2 THEN '处理中' | ||
| 179 | + WHEN 3 THEN '已解决' | ||
| 180 | + WHEN 4 THEN '已关闭' | ||
| 181 | + ELSE '未知状态' | ||
| 182 | + END AS workorder_status_name, | ||
| 183 | + ew.exception_desc, | ||
| 184 | + ew.handler_user, | ||
| 185 | + ew.create_by, | ||
| 186 | + ew.create_time, | ||
| 187 | + ew.update_time | ||
| 188 | + FROM t_exception_workorder ew | ||
| 189 | + <where> | ||
| 190 | + ew.del_flag = '0' | ||
| 191 | + <if test="query.workorderNo != null and query.workorderNo != ''"> | ||
| 192 | + AND ew.workorder_no LIKE CONCAT('%', #{query.workorderNo}, '%') | ||
| 193 | + </if> | ||
| 194 | + <if test="query.orderNo != null and query.orderNo != ''"> | ||
| 195 | + AND ew.order_no LIKE CONCAT('%', #{query.orderNo}, '%') | ||
| 196 | + </if> | ||
| 197 | + <if test="query.dealerCode != null and query.dealerCode != ''"> | ||
| 198 | + AND ew.dealer_code = #{query.dealerCode} | ||
| 199 | + </if> | ||
| 200 | + <if test="query.dealerName != null and query.dealerName != ''"> | ||
| 201 | + AND ew.dealer_name LIKE CONCAT('%', #{query.dealerName}, '%') | ||
| 202 | + </if> | ||
| 203 | + <if test="query.workorderStatus != null"> | ||
| 204 | + AND ew.workorder_status = #{query.workorderStatus} | ||
| 205 | + </if> | ||
| 206 | + <if test="query.exceptionType != null"> | ||
| 207 | + AND ew.exception_type = #{query.exceptionType} | ||
| 208 | + </if> | ||
| 209 | + <if test="query.severityLevel != null"> | ||
| 210 | + AND ew.severity_level = #{query.severityLevel} | ||
| 211 | + </if> | ||
| 212 | + <if test="query.handlerUser != null and query.handlerUser != ''"> | ||
| 213 | + AND ew.handler_user LIKE CONCAT('%', #{query.handlerUser}, '%') | ||
| 214 | + </if> | ||
| 215 | + <if test="query.startTime != null"> | ||
| 216 | + AND ew.create_time >= #{query.startTime} | ||
| 217 | + </if> | ||
| 218 | + <if test="query.endTime != null"> | ||
| 219 | + AND ew.create_time <= #{query.endTime} | ||
| 220 | + </if> | ||
| 221 | + </where> | ||
| 222 | + ORDER BY ew.create_time DESC | ||
| 223 | + </select> | ||
| 224 | + | ||
| 153 | </mapper> | 225 | </mapper> | ... | ... |
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 |
| ... | @@ -146,6 +146,13 @@ export const exceptionWorkorderApi = { | ... | @@ -146,6 +146,13 @@ export const exceptionWorkorderApi = { |
| 146 | // 获取异常工单统计信息 | 146 | // 获取异常工单统计信息 |
| 147 | getExceptionWorkorderStats: () => { | 147 | getExceptionWorkorderStats: () => { |
| 148 | return request.get('/api/exception-workorder/stats') | 148 | return request.get('/api/exception-workorder/stats') |
| 149 | + }, | ||
| 150 | + | ||
| 151 | + // 导出异常工单数据 | ||
| 152 | + exportExceptionWorkorders: (params: ExceptionWorkorderQueryReq) => { | ||
| 153 | + return request.post('/api/exception-workorder/export', params, { | ||
| 154 | + responseType: 'blob' | ||
| 155 | + }) | ||
| 149 | } | 156 | } |
| 150 | } | 157 | } |
| 151 | 158 | ... | ... |
| ... | @@ -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.
| ... | @@ -734,8 +734,38 @@ const handleBatchProcess = () => { | ... | @@ -734,8 +734,38 @@ const handleBatchProcess = () => { |
| 734 | } | 734 | } |
| 735 | 735 | ||
| 736 | // 导出 | 736 | // 导出 |
| 737 | -const handleExport = () => { | 737 | +const handleExport = async () => { |
| 738 | - ElMessage.info('导出功能开发中...') | 738 | + try { |
| 739 | + await ElMessageBox.confirm('确定要导出异常工单数据吗?', '确认导出', { | ||
| 740 | + confirmButtonText: '确定', | ||
| 741 | + cancelButtonText: '取消', | ||
| 742 | + type: 'warning' | ||
| 743 | + }) | ||
| 744 | + | ||
| 745 | + ElMessage.info('正在导出数据,请稍候...') | ||
| 746 | + | ||
| 747 | + const response = await exceptionWorkorderApi.exportExceptionWorkorders(searchParams.value) | ||
| 748 | + | ||
| 749 | + // 创建下载链接 | ||
| 750 | + const blob = new Blob([response as unknown as BlobPart], { | ||
| 751 | + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' | ||
| 752 | + }) | ||
| 753 | + const url = window.URL.createObjectURL(blob) | ||
| 754 | + const link = document.createElement('a') | ||
| 755 | + link.href = url | ||
| 756 | + link.download = `异常工单数据_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.xlsx` | ||
| 757 | + document.body.appendChild(link) | ||
| 758 | + link.click() | ||
| 759 | + document.body.removeChild(link) | ||
| 760 | + window.URL.revokeObjectURL(url) | ||
| 761 | + | ||
| 762 | + ElMessage.success('导出成功') | ||
| 763 | + } catch (error: any) { | ||
| 764 | + if (error !== 'cancel') { | ||
| 765 | + console.error('导出失败:', error) | ||
| 766 | + ElMessage.error('导出失败: ' + (error?.message || '未知错误')) | ||
| 767 | + } | ||
| 768 | + } | ||
| 739 | } | 769 | } |
| 740 | 770 | ||
| 741 | // 提交新增 | 771 | // 提交新增 | ... | ... |
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment